diff --git a/.merlin b/.merlin new file mode 100644 index 0000000000000000000000000000000000000000..b303a900ed8bbfa4d03e8e614dcf099e7bea1ad4 --- /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 81f58f53282286779c545691e22ab1ba63b2ac3b..0000000000000000000000000000000000000000 --- 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 1420963034c4d1208433163db9769da38912ab5d..ea1b2fc1941241afd81d99e7eae90da7c7e23a05 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 e912e15a7a8156d712c4d3a40ccd87273c3172a9..56edba642af88b579bc44cb46a3681fae9bdf525 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 d00c42c4c88e5025d491883cd10f672ed14d0a8a..05c46e8f89de90069aeaa9939a17a671a6a5369f 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 51bf386e446eb2de4b9b499699356a4ae832fb8f..a85db2d94a2a496328c8b08124a797fa7c7875c4 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 e5933e37734879a422a8c014f66f6e10e4524194..0000000000000000000000000000000000000000 --- 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 e3849d49900b2b47c425e7ca3b5e9788fd001e4f..0000000000000000000000000000000000000000 --- 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 bcd6b95ec7e710629ccc9fe8582443e4b0bec4ac..0000000000000000000000000000000000000000 --- 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 7b51b2afcab6f65b7179652a824599e587f5ed8e..0000000000000000000000000000000000000000 --- 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 b98dd2b1fdd9ee97c3409a9171feef0f750cce20..0000000000000000000000000000000000000000 --- 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/debian/changelog b/debian/changelog index fd1fa7123bc2ff22f2ceb948456341a00b7cc412..eea73bd8b4f1f15a2415ae78380071b0daed0012 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,21 @@ -haxe (1:3.2.1+dfsg-1~ubuntu12.04.1~ppa1) precise; urgency=low +haxe (1:3.4.0-1~ubuntu12.04.1~ppa1) precise; urgency=low * Backport to precise. - + Removed -D embed_js support for swfobject. - -- Andy Li Wed, 14 Oct 2015 11:28:08 +0800 + -- Andy Li Fri, 03 Feb 2015 13:48:00 +0800 + +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 09:27:56 +0800 haxe (1:3.2.1+dfsg-1) unstable; urgency=low diff --git a/debian/control b/debian/control index e7030895e562191e80efdff8452e213bc635d555..5c7b5a8fac165598abfc6b90f4b6579bad48771e 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, @@ -19,8 +19,7 @@ Homepage: http://haxe.org Package: haxe Architecture: any -Depends: libjs-jquery, - neko (>= 2.0.0), +Depends: neko (>= 2.0.0), ${misc:Depends}, ${ocaml:Depends}, ${shlibs:Depends} diff --git a/debian/copyright b/debian/copyright index 1149ec7b9e4172c1f1779a2b7ca78c5d2afe73dc..98061fb1959b5b7492850581b513da13e210754c 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,24 +135,12 @@ 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: 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. +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. . - 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. + 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'. + diff --git a/debian/haxe.links b/debian/haxe.links deleted file mode 100644 index 21afe8eb393222daea197924e6b498e919fe15f1..0000000000000000000000000000000000000000 --- a/debian/haxe.links +++ /dev/null @@ -1 +0,0 @@ -usr/share/javascript/jquery/jquery.min.js usr/share/haxe/std/js/jquery-latest.min.js diff --git a/debian/rules b/debian/rules index d64b0ed88dfa2cff58e59b948b181c797ec9cb1c..f9d780f2ba7bc8dfaaa4de8c36313384b41eb74a 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.*)(?:\-\d+.*)};') override_dh_auto_configure: @@ -25,9 +23,8 @@ 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 && \ - 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 19989bdf68d163448fcf69bc6a747e9d51165705..19d902e3c93d06a5a01572d898cd9c172b7e3f5e 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 diff --git a/extra/CHANGES.txt b/extra/CHANGES.txt index eb924b2f32e531eec6a01493324f3b4fe99bbb35..03f089e964b8ba2fd42cf1c63ae259f03cd691ef 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 b4a19544e6cd48d747ad679614f99c2d8bf66901..b1af8034587addb1063e7680b464a8f58e1b9156 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 0711f5194f547369ec3ffd6fec17fefba07cc7b9..b4142af748da6420ab697e7485b105c8e6689486 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 e9756dcc3d3ebf43c7f1cca954cf88ed25e1c6d1..73f38e226aaf84fbc4c7e2fda69154c103753442 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 0000000000000000000000000000000000000000..b8b893c578275457221858b14e12f0e1ff170c9d --- /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 0000000000000000000000000000000000000000..f04bbf231c779bbfa2387acb8a14ea52697b4c53 --- /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 Binary files /dev/null and b/extra/deploy_key.enc differ diff --git a/extra/extract.hxml b/extra/extract.hxml index 4ae6de90f54bee21268cc3ae1fb7f9a0b9719660..e0b3f0770b5ee96ec31f4488fd9fe15970c4e039 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 93f847f36966291245339e5c4b8316219b73eb71..a5a52a8fa7092169acf21a99f925091cc7016b72 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 Binary files /dev/null and b/extra/haxeci_sec.gpg.enc differ diff --git a/extra/haxeci_ssh.enc b/extra/haxeci_ssh.enc new file mode 100644 index 0000000000000000000000000000000000000000..ccf5c25cf7e18018fe1cc71ae5a24fe8435a706c Binary files /dev/null and b/extra/haxeci_ssh.enc differ diff --git a/extra/haxelib_src/.dockerignore b/extra/haxelib_src/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..16696f845a39a003c3f937e7784a9288189893e5 --- /dev/null +++ b/extra/haxelib_src/.dockerignore @@ -0,0 +1,7 @@ +uf-content +deploy +bin +test +deploy_key +www/bower_components +.haxelib \ No newline at end of file diff --git a/extra/haxelib_src/.ebextensions/cloudwatch.config b/extra/haxelib_src/.ebextensions/cloudwatch.config new file mode 100644 index 0000000000000000000000000000000000000000..d67b7e6b1dae034d1897b71d04a0cbf38e0dc714 --- /dev/null +++ b/extra/haxelib_src/.ebextensions/cloudwatch.config @@ -0,0 +1,26 @@ +packages: + yum: + perl-DateTime: [] + perl-Sys-Syslog: [] + perl-LWP-Protocol-https: [] + perl-Switch: [] + perl-URI: [] + perl-Bundle-LWP: [] + +sources: + /opt/cloudwatch: http://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.1.zip + +container_commands: + 01-setupcron: + command: | + echo '*/5 * * * * root perl /opt/cloudwatch/aws-scripts-mon/mon-put-instance-data.pl `{"Fn::GetOptionSetting" : { "OptionName" : "CloudWatchMetrics", "DefaultValue" : "--mem-util --disk-space-util --disk-path=/" }}` >> /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 0000000000000000000000000000000000000000..5640e53bcbeb16b445b9493ce0babfe4c4da224d --- /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 0000000000000000000000000000000000000000..45a6a0d9fe69e18f4d078161bf07901a1a6149f2 --- /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 da1248d01cdf6fb7c351cb24eb71cb2194e58841..90f70d6a666543101630280d294a5da5460f2f1a 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 0000000000000000000000000000000000000000..fffce17ae9e616ab00ac2850b407e2540238b139 --- /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 0000000000000000000000000000000000000000..6a789b94dc2df3ba7bac5f9f523a3ac99f7e9a90 --- /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 0000000000000000000000000000000000000000..5fc523542b8a22d032a107542b4608127cda6501 --- /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 0000000000000000000000000000000000000000..1d55f33a723910bd8a66f98cb0b2f2168f73f69d --- /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 0000000000000000000000000000000000000000..874a77178f77598004cd49b9f8e385c32dab10d4 --- /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 e283915790ee1055bb36879b85d1cbda64dfd1a5..0000000000000000000000000000000000000000 --- 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 2446612ee71a8eb174b437629101373ed2ca0b0b..36acf8d839c6986834b2ae8b6216469c5452cada 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 0000000000000000000000000000000000000000..9d3c0e28e91eb20c31c6d5e5cbf0f79cd200e8a4 --- /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 b3c94e8f2323d24508f4a8c81461a74751379c3f..4485444ce7ae1ec155fae0ed4f1661d0232c7de6 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 0000000000000000000000000000000000000000..42c091d479262de40dcb91f3a84ad79d060f2d41 --- /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 0000000000000000000000000000000000000000..97b705ed37586770e79369160fa4170d14bcf1a8 --- /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 e4699a65b5047f3ba49a4a2d3e46f72e29c0404f..bfd5fd592d397158d9c88de73160e33edde8d638 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 902314beb914cf1584b9bb663032e649e946d43e..5f5d85c485f340216f948984fd18df2977156964 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 0000000000000000000000000000000000000000..d064590b71a9509fc291a21b46bc5a7049a85ebb --- /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 Binary files /dev/null and b/extra/haxelib_src/deploy_key.enc differ diff --git a/extra/haxelib_src/haxelib.hxml b/extra/haxelib_src/haxelib.hxml deleted file mode 100644 index 07f5bf280920eb4f940eed686400be72c2783b81..0000000000000000000000000000000000000000 --- 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 4e1f3beb1365f77457b969c762fa07cd2257058d..0000000000000000000000000000000000000000 --- 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 db877601b2c5db62cb15bf2a046919cd385c3102..e23f974b1a9b846b8d1b2c8cde66a2ebc36e44f7 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 b4d08f41163aabb62744ba50f0c1cc0358120194..0000000000000000000000000000000000000000 --- 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 16c52a56e2d1d5b73e9543e799b9103b09dea373..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..bddcaec6ac018090586ae700a1455ec3896b9f21 --- /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 c367c0159967b4cac70a44e06711cfcfd7abbaad..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..c5e4ebba5f71544b985691233ff12d55a2b85fce --- /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 49e2a240de524197177a30a28b8d1451d71cb5b4..0000000000000000000000000000000000000000 --- 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 3fcec8d3453f518f8cd380ac714d7db39fc0a1f2..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..8b55e5b662ffe3da19c0226e30af33517b3da146 --- /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 335fe77b074cd6215edcf009254bf89dd84f443c..0000000000000000000000000000000000000000 --- 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 Binary files /dev/null and b/extra/haxelib_src/run.n differ diff --git a/extra/haxelib_src/schema.json b/extra/haxelib_src/schema.json index 855f8d9dd7ae8ecc83ab3c6327cfcb1eb82532cd..6e20db78f3d9abf2e3968cf0c9071efa663d8345 100644 --- a/extra/haxelib_src/schema.json +++ b/extra/haxelib_src/schema.json @@ -1,45 +1,54 @@ { - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-04/schema#", "description": "A haxelib project", "type": "object", "properties": { "name": { "$ref": "#/definitions/projectName" }, - "license": { - "description": "The open source license under which the project is licensed", - "enum": ["GPL", "LGPL", "BSD", "Public", "MIT"] - }, - "tags": { - "type": "array", - "items": { "$ref": "#/definitions/haxelibTag" }, - "uniqueItems": true + "url": { + "description": "Project's website", + "type": "string", + "format": "uri" }, "description": { + "description": "Short description of the project", "type": "string" }, + "license": { + "description": "Open source license under which the project is licensed", + "enum": ["GPL", "LGPL", "BSD", "Public", "MIT", "Apache"] + }, + "version": { "$ref": "#/definitions/semver" }, "classPath": { - "description": "The folder in the package which contains the source files for this haxelib", + "description": "Folder in the package which contains the source files for this project", "type": "string" }, "contributors": { + "description": "List of project contributors that are allowed to upload to haxelib", "type": "array", "items": { "$ref": "#/definitions/userName" }, "minItems": 1, "uniqueItems": true }, - "releasenote": { - "type": "string" - }, - "version": { "$ref": "#/definitions/semver" }, - "url": { - "type": "string", - "format": "uri" + "tags": { + "description": "List of tags for easier finding the project on haxelib", + "type": "array", + "items": { "$ref": "#/definitions/haxelibTag" }, + "uniqueItems": true }, "dependencies": { "type": "object", - "additionalProperties": { "$ref": "#/definitions/dependancyVersion" } + "description": "Project's dependencies", + "patternProperties": { + "^[A-Za-z0-9_.-]{3,}$": { "$ref": "#/definitions/dependencyVersion" } + }, + "additionalProperties": false + }, + "releasenote": { + "description": "Short description of changes made in this version", + "type": "string" } }, - "additionalProperties": true, + "additionalProperties": false, "required": ["name", "license", "releasenote", "contributors", "version"], "definitions": { "userName": { @@ -52,7 +61,13 @@ "description": "The name of a haxelib project", "type": "string", "minLength": 3, - "pattern": "^[A-Za-z0-9_.-]{3,}$" + "pattern": "^[A-Za-z0-9_.-]{3,}$", + "not": { + "anyOf": [ + {"enum": ["haxe", "all"]}, + {"pattern": "\\.(zip|hxml)$"} + ] + } }, "haxelibTag": { "description": "A keyword or term associated with a haxelib project", @@ -62,9 +77,10 @@ }, "semver": { "type": "string", - "pattern": "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-(alpha|beta|rc)(\\.([0-9]+))?)?$" + "description": "Project's version", + "pattern": "^(\\d|[1-9]\\d*)\\.(\\d|[1-9]\\d*)\\.(\\d|[1-9]\\d*)(-(alpha|beta|rc)(\\.(\\d|[1-9]\\d*))?)?$" }, - "dependancyVersion": { + "dependencyVersion": { "oneOf": [ { "$ref": "#/definitions/semver" }, { @@ -74,5 +90,4 @@ ] } } - } diff --git a/extra/haxelib_src/server.hxml b/extra/haxelib_src/server.hxml new file mode 100644 index 0000000000000000000000000000000000000000..55a1e32b2eccbe4b5a5349ce1bce92d374f62da0 --- /dev/null +++ b/extra/haxelib_src/server.hxml @@ -0,0 +1,7 @@ +# The new haxelib website (on the same 3.0 repo) + +server_website.hxml +--next +server_tasks.hxml +--next +server_api.hxml \ No newline at end of file diff --git a/extra/haxelib_src/server_api.hxml b/extra/haxelib_src/server_api.hxml new file mode 100644 index 0000000000000000000000000000000000000000..27756f94c4ccbea28ee81980a26b7093a1eafc35 --- /dev/null +++ b/extra/haxelib_src/server_api.hxml @@ -0,0 +1,6 @@ +-cp src +-neko www/api/3.0/index.n +-main haxelib.server.Repo +-lib aws-sdk-neko:0.2.0 +-dce no +-D haxelib_api diff --git a/extra/haxelib_src/server_each.hxml b/extra/haxelib_src/server_each.hxml new file mode 100644 index 0000000000000000000000000000000000000000..94940c0bf58014a137cd935fd1b67df7116369d6 --- /dev/null +++ b/extra/haxelib_src/server_each.hxml @@ -0,0 +1,12 @@ +-cp src +-lib ufront +-lib ufront-mail:1.0.0-rc.4 +-lib ufront-ufadmin +-lib erazor:1.0.1 +-lib markdown:1.0.0 +-lib cleversort +-lib aws-sdk-neko:0.2.0 +-D server +-D getter_support +# https://github.com/HaxeFoundation/haxe/issues/4903 +--macro keep('StringBuf') \ No newline at end of file diff --git a/extra/haxelib_src/server_legacy.hxml b/extra/haxelib_src/server_legacy.hxml new file mode 100644 index 0000000000000000000000000000000000000000..3e559317b3e08574fcf660bd6f3980f7bdfb544b --- /dev/null +++ b/extra/haxelib_src/server_legacy.hxml @@ -0,0 +1,8 @@ +server_each.hxml +-cp src +-neko www/legacy/index.n +-main legacyhaxelib.Site +-lib hx2compat +-D haxelib_site +-D haxelib_legacy +-dce no diff --git a/extra/haxelib_src/server_tasks.hxml b/extra/haxelib_src/server_tasks.hxml new file mode 100644 index 0000000000000000000000000000000000000000..6e87d06a348655ea6ad5f7c82fd1eeef49e45910 --- /dev/null +++ b/extra/haxelib_src/server_tasks.hxml @@ -0,0 +1,4 @@ +server_each.hxml +-lib ufront-uftasks +-main website.Tasks +-neko www/tasks.n diff --git a/extra/haxelib_src/server_tests.hxml b/extra/haxelib_src/server_tests.hxml new file mode 100644 index 0000000000000000000000000000000000000000..729dfc037a1076322d73d17e4af03ba5753f9370 --- /dev/null +++ b/extra/haxelib_src/server_tests.hxml @@ -0,0 +1,10 @@ +server_each.hxml +-cp test +# Now the testing libs +-lib buddy:0.18.1 +-lib mockatoo +-lib utest +--no-inline +-main WebsiteTests +-neko bin/websitetest.n +-cmd neko bin/websitetest.n diff --git a/extra/haxelib_src/server_website.hxml b/extra/haxelib_src/server_website.hxml new file mode 100644 index 0000000000000000000000000000000000000000..eb28c416e4a6dd1ebfdd035018ed789bceef6e52 --- /dev/null +++ b/extra/haxelib_src/server_website.hxml @@ -0,0 +1,3 @@ +server_each.hxml +-main website.Server +-neko www/index.n diff --git a/extra/haxelib_src/site.bat b/extra/haxelib_src/site.bat deleted file mode 100644 index 04dc13323f9d53e9711dda53c6ba203b7ef4c2d4..0000000000000000000000000000000000000000 --- a/extra/haxelib_src/site.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -cd server -nekotools server -rewrite -pause diff --git a/extra/haxelib_src/site.hxml b/extra/haxelib_src/site.hxml deleted file mode 100644 index aab1e7da6080a6562521114783d86907ffdd7921..0000000000000000000000000000000000000000 --- a/extra/haxelib_src/site.hxml +++ /dev/null @@ -1,21 +0,0 @@ --cp src --neko server/index.n --main tools.haxelib.Site --dce no - ---next - --cp src --neko server/api/3.0/index.n --main tools.haxelib.Repo --dce no --D haxelib_api - ---next - --cp src --neko server/legacy/index.n --main tools.legacyhaxelib.Site --lib hx2compat --D haxelib_site --dce no \ No newline at end of file diff --git a/extra/haxelib_src/site.sh b/extra/haxelib_src/site.sh deleted file mode 100755 index 408020d861b240de97a43ea1a720aea978485e40..0000000000000000000000000000000000000000 --- a/extra/haxelib_src/site.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -# Build the site, copy components over - -mkdir -p server/legacy -mkdir -p server/api/3.0 - -haxe site.hxml - -cp src/tools/haxelib/.htaccess server/ -cp -ar src/tools/haxelib/tmpl server/ -cp src/tools/haxelib/haxelib.css server/ -cp src/tools/haxelib/dbconfig.json.example server/ - -cp src/tools/legacyhaxelib/.htaccess server/legacy/ -cp src/tools/legacyhaxelib/website.mtt server/legacy/ -cp src/tools/legacyhaxelib/haxelib.css server/legacy/ - -# If the databases don't exist, run "setup" - -if [ ! -f server/haxelib.db ]; -then - cd server - neko index.n setup - cd .. -fi - -if [ ! -f server/legacy/haxelib.db ]; -then - cd server/legacy - neko index.n setup - cd ../.. -fi - -# Make sure the server folders are writeable. - -chmod a+w server -chmod a+w server/tmp -chmod a+w server/files -chmod a+w server/files/3.0 -chmod a+w server/legacy -chmod a+w server/haxelib.db -chmod a+w server/legacy/haxelib.db - - -cd server -# starting server on port 2000, because binding port 80 requires root privileges, -# which might be a bad idea -nekotools server -rewrite diff --git a/extra/haxelib_src/src/Package.hx b/extra/haxelib_src/src/Package.hx new file mode 100644 index 0000000000000000000000000000000000000000..378cb964c379976faf441e7d451e88710c64337f --- /dev/null +++ b/extra/haxelib_src/src/Package.hx @@ -0,0 +1,69 @@ +import haxe.crypto.Crc32; +import haxe.zip.Entry; +import haxe.zip.Writer; +import haxe.zip.Tools; + +import sys.io.File; +import sys.FileSystem; +import haxelib.client.Main.VERSION; +import haxelib.Data.Infos; + +class Package { + static var outPath = "package.zip"; + + static function main() { + checkVersion(); + + var entries = new List(); + + 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 f9b66db4ee0b74606b11b3cf09bc4ee315e6189c..6becc1d8bb73da7de699f5418e525c19efdb69a4 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 80b76543a8de792f4c2d23c0ffaa377190a4f8d6..9a45cb158e501b0be8a62796b86fcf624d3d587a 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 4e988580e0b4d0788d1c0af13cf4cc6a564fa8b4..2bb1f858ba00d1cc6ed93cb399556d1470fec663 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 bec27b38400b8bfe8386709e1da518f52added37..34c984f64d41b8a99f38a092fcb0417fb07ee1c8 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 0000000000000000000000000000000000000000..b0c5fbea54867d7f9203d4e5dda4c1a3711df9df --- /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 a4f97c5f1f4ce6348d72e33a97c53ae88a04709e..b7196033639181c2909a15af3d7234d668c42d54 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 0000000000000000000000000000000000000000..7492583608a170249befb22bfaedadd3f3b0aa56 --- /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 dc1881558690279dbd35394472ed1ccacc58a926..9f9f34de046a03845aef1552f1e0a5c0de893b19 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 0000000000000000000000000000000000000000..a24c1e3dbe76d2b90608241f3e5a4a5f620c023d --- /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 0000000000000000000000000000000000000000..97922d68eb54eac9645a0882e20484bf3a22541d --- /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 0000000000000000000000000000000000000000..ed8205a127d52712409516f24a8e42050b57964e --- /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 0000000000000000000000000000000000000000..2bbf2faca2e91284d7316b4e2e1edaa3a24789c2 --- /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 8123eeeddb98c5db8fc47b2e01dc38a43f2e484c..482a0e71a40538f669335436fd1878c1041547ec 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 093ef0cccb3bf69ddd2a3aed85ecf5bcebbab974..e15a567bdc6dce4fbb1756bcedea640d7b1635cc 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 bdba8e1a4978a6cc2b35c52e742c705a31fda5db..caeefc83b38b76af85c979216983927c5a690b66 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 b3f113a9d7f5265f489a58d8fa183cfa9a573f67..b8deded5939bd677dac04dd0bfd0a2843bbe2ed9 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 a6db5d1cdaafdf4c6003f226c8a2dae06dc4f33e..9c181f2fa47ff81852e8ea7d430cf0b392b9464d 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 fa77216301659b4cf67403a74ec8178c3e786e78..a0283b2d45e8f931191a33ad856c74c8f0375d3a 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 e98559c95540d3cffa6c236431cfe8bb1e8093a9..abad7f593f84d129cfaba33d89adce144c9a988d 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 0000000000000000000000000000000000000000..cad281caef33da049711e1d84927640c64935457 --- /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 0000000000000000000000000000000000000000..ef1b1df6669df8691ff62933eb72589d07d60638 --- /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 1acf47df1ebfe6b9e9eb4e1dabb00037236eeff4..0000000000000000000000000000000000000000 --- 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 946fd5b4ea9819ce1b98cfa4fa2a25ede6e598c8..0000000000000000000000000000000000000000 --- 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 4a31e389a627d39d7776354babace159ef839ca3..0000000000000000000000000000000000000000 --- 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 937823d57fc4f4c86fa9f7fe3071c5ff9264ea13..0000000000000000000000000000000000000000 --- 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 fd0f55a5e7c6360a694b2ac33825e572d26307fd..0000000000000000000000000000000000000000 --- 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 a8709e9a640d625f9767eb61926d2b5678774ef2..0000000000000000000000000000000000000000 --- 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 9902c0934e28b0a1b14b76babab62e7563033e81..0000000000000000000000000000000000000000 --- 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 39f779842e67189fefb2919fae813a064c70425d..0000000000000000000000000000000000000000 --- 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 b5df2f36d064fa0394f6657ee05de8649e83a5c9..0000000000000000000000000000000000000000 --- a/extra/haxelib_src/src/tools/haxelib/tmpl/error.mtt +++ /dev/null @@ -1,5 +0,0 @@ -
-

::error::

- -

Perhaps what you are looking for is still on the legacy haxelib site

-
\ 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 c6232308114fad82f8bffdc0850a55ec3e4567f7..0000000000000000000000000000000000000000 --- 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 f530edda3e106fc442b21cfdbf6c48c4662d78d9..0000000000000000000000000000000000000000 --- 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 bdc7188ff43bbb18ca30f03d0db522556e122163..0000000000000000000000000000000000000000 --- 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 71a230c7c64c4f2631f55c19a47534970d054bd8..0000000000000000000000000000000000000000 --- 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 476c0bd270f8b6dd973b4cbd9b4ce13b616e534c..0000000000000000000000000000000000000000 --- 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 fe0cc64070b8411cac05d76e887e37ad983ebf30..0000000000000000000000000000000000000000 --- 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 4a0621d429d541c4a2d718f328682947e29f875f..0000000000000000000000000000000000000000 --- 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 e7b575f48035056624adbb9453b1a8957f11c436..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..b02c9a31b2d527ad033596a7c33d55225c2ad9eb --- /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 0000000000000000000000000000000000000000..2cb7fed76323135c488b36faa7d0656e3cf7cc34 --- /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 0000000000000000000000000000000000000000..862b359a63c0185c28b38d27a592182824b16448 --- /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 0000000000000000000000000000000000000000..095e78bc0d540f5b6b60fe9496cc41dafe0e089c --- /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 0000000000000000000000000000000000000000..a1d1ed6f0e9951b75dd9cf058b57875c6598a23f --- /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 0000000000000000000000000000000000000000..f156d5103ea0ffa20acfe3cb915ef021d136639e --- /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 0000000000000000000000000000000000000000..3017caf2f8a85c03ded18d9351d1a68c5bfb6d1f --- /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 0000000000000000000000000000000000000000..19abf2362020e7faa19aae196d9f4b3153cd1e28 --- /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 0000000000000000000000000000000000000000..8f7c7565b2804631f62aafea03de4d05e5d0bb32 --- /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 0000000000000000000000000000000000000000..1f6cd8e14acff51882f35a3e00964c341a7c3882 --- /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 0000000000000000000000000000000000000000..566b06d089e4a1afb5611ec8a0d6776648a5608e --- /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 0000000000000000000000000000000000000000..57f9d0108809be0f458a22021be9888a1dad258f --- /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 0000000000000000000000000000000000000000..0c6eea23ce859a1ac14052ffcb3e6ca07ef92d4c --- /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 0000000000000000000000000000000000000000..dc0ee364fed157dc88bbc2d361a60275a1e56071 --- /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 435329eb181b7b5f2da424962712ba21015b976d..0000000000000000000000000000000000000000 --- 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 a08efa7a573aa2a0edfbba7e8296c14a98f77e2e..51306f9535f4557a090521ab05e297ffbb0c0d26 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 0000000000000000000000000000000000000000..2fefdb2d9b9b86dd2e4119d6dc0740ee31d9f7e9 --- /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 0000000000000000000000000000000000000000..d17a4aadcdfb33e579beb736e7534470df781f97 --- /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 0000000000000000000000000000000000000000..5dfd1134854014e54fa11759cf9e5998ee1fdd1f --- /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 0000000000000000000000000000000000000000..56674e45bdb7fa4308ef398540edf240bf9d4f36 --- /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 0000000000000000000000000000000000000000..2e097daa4e588f56311cf1a2f9b26c4b8a624af9 --- /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 0000000000000000000000000000000000000000..8edeae2c1361aa460ba3bb20bc0d2b4913c0aa18 --- /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 0000000000000000000000000000000000000000..f8bc56678bf82fe948caf284d5cfe053cb5dd126 --- /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 0000000000000000000000000000000000000000..cf0cf2540e602824266b370c290669b676456e27 --- /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 0000000000000000000000000000000000000000..0bbc31ddec9bbd19d7194101a38ec2f231d48c57 --- /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 0000000000000000000000000000000000000000..38cf8a656521ec925768b54e9b0c5e2766ea62be --- /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 0000000000000000000000000000000000000000..078f011b0f928f5dd3da1630935ae73b0643e8f8 --- /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 0000000000000000000000000000000000000000..2936374c09fd9ec3ac752b23c93de783ce5e94fc --- /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 0000000000000000000000000000000000000000..2936374c09fd9ec3ac752b23c93de783ce5e94fc --- /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 0000000000000000000000000000000000000000..56b00b50dceb8c34498e88f22f33e71e076e7559 --- /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 0000000000000000000000000000000000000000..476a4920c7efc04f3b616b3a8d0759e73c4fcfc0 --- /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 0000000000000000000000000000000000000000..1ecc074b8a1c982050e959ac06ee3ee4203acdbb --- /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 38f9bb072ed7c7dca1160bc8368e0ab5747fe01d..359642ad7fc8611ceba34c4cb5faacea8fbb00b6 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 124c2de09e3f054bc49b42a914bb8e45ba7b6d9d..0000000000000000000000000000000000000000 --- 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 435e1af392d9d4eb04806a776c778c155836dd04..82f2dac9a3b222bea5209eb76ba008532aa87cd6 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 0000000000000000000000000000000000000000..6cceea46321910e9d7101d3150d0bcebd123fa41 --- /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 0000000000000000000000000000000000000000..c4c8c2d0981738a7254f5f9fe922503064c6f927 --- /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 0000000000000000000000000000000000000000..9cb6bdd7250e40283ff1e3456a05a006afd21bf5 --- /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 331c2c9cfa53c8e72749f5f193a8d40568113229..6abe7b4b0549ca65d92d5c4fc36cbf2e69d642fc 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 0000000000000000000000000000000000000000..7a351b77094a5bc06847c5d2f42e4479eca3a692 --- /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 8f83772023937e9c042f680d05d38dae0a100a19..c538bb6bce44085781b29726931baae9ecc14dcc 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 031370aa55b300a1a6a676905687b946de93a3a0..71200a0bfef97bed5fed6f4a2b6c9215d69c3bcd 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 0a259b414c442c8e6ac4c69f685173182d67bc8f..946b227691751656f42e6c06d70b8a452ccedb7a 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 0000000000000000000000000000000000000000..57f3811f3b20c389ae4dafef621355f6c3263365 --- /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 0000000000000000000000000000000000000000..8f75c2b96c0166235d24c2292e806d711a53fac8 --- /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 0000000000000000000000000000000000000000..c70dcbc0a15a403bd0861671fb06165a560b6cc7 --- /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 0000000000000000000000000000000000000000..4810042c52eb6073225cf29b8fb77bce75d2e1a4 --- /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 0000000000000000000000000000000000000000..b4336e8ffb6b67f96910a2e245066b0021eea527 --- /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 0000000000000000000000000000000000000000..cfa7918cf37f615be2ffb518cc7bcce0de5f2fae --- /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 0000000000000000000000000000000000000000..ad4463d5875be7cbb8e76d77cf634029dbacd6a6 --- /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 0000000000000000000000000000000000000000..6226e1115e8733bf59b7b0715a5eb75826455985 --- /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 0000000000000000000000000000000000000000..7b0ebda5733b3a07adc9c45e4a88d33578ab0e87 --- /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 0000000000000000000000000000000000000000..9ef2a4100fb4b1b0cf4f96803b80081e84b196a2 --- /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 0000000000000000000000000000000000000000..3c9cf8f6958c7a5e85de62e80197a08367cb9415 --- /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 0000000000000000000000000000000000000000..208199b3ad8d10db1eb3005ab2eee9d0257141b0 --- /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 0000000000000000000000000000000000000000..1a1a206a9c54dc0f6c9c03829aa747b11dae4b43 --- /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 0000000000000000000000000000000000000000..3f0240dfa1f67fc3be0729e08e2c2951c99f067d --- /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 9163b6a3a667779002cb061c00793aac05125d22..0000000000000000000000000000000000000000 --- 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 f3768e5da78bc42c3e8a0edd73c06f8a6a6e1f37..0000000000000000000000000000000000000000 --- 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 e3aab222abc2ee0af566f24737786acf159ecb29..b9b20dd820cefc98d01aac266c66d0faf80a97a7 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 0000000000000000000000000000000000000000..730bbc82c1035808b942601431f5490eb06300de --- /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 0000000000000000000000000000000000000000..3cf8004aec367fd98569490ef827158e3609320a --- /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 0000000000000000000000000000000000000000..13d44178866f14f0e0750330c3ddee3b790cce7c --- /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 baf97456d68fd50d9fbc62cf16445740a7fa9828..d008ca9688ef11a0e895adc3e982fcdea8aa5534 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 0000000000000000000000000000000000000000..2f77dfb02a2df112af9b0b49805b1d8449c5d8e1 --- /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 0000000000000000000000000000000000000000..5589f8afd0e3519eb2b7684c7b2f179fa796ed0a --- /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 0000000000000000000000000000000000000000..5be8f1bba8d29bb56ad46f671ec77b6ec98ab560 --- /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 0000000000000000000000000000000000000000..6445b5b20ad6b495e51c44f12a4d7930fe386197 --- /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 0000000000000000000000000000000000000000..88816f108941c7bdcfda4d30c682c22d1bcdad35 --- /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 0000000000000000000000000000000000000000..d8fcf99ba5d439c7bd5f8c0f4a8461b0f21ed12e --- /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 0000000000000000000000000000000000000000..351ef3f54cc083c0f133a509554f3a1103dc0156 --- /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 0000000000000000000000000000000000000000..4e7d02f447a819e8dac8641c1c0c2b8e204f11e5 --- /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 Binary files /dev/null and b/extra/haxelib_src/www/favicon.ico differ diff --git a/extra/haxelib_src/www/img/glyphicons-halflings-white.png b/extra/haxelib_src/www/img/glyphicons-halflings-white.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf6484a29d8da269f9bc874b25493a45fae3bae Binary files /dev/null and b/extra/haxelib_src/www/img/glyphicons-halflings-white.png differ 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 Binary files /dev/null and b/extra/haxelib_src/www/img/glyphicons-halflings.png differ 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 Binary files /dev/null and b/extra/haxelib_src/www/img/haxe-logo-horizontal-on-dark.png differ 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 0000000000000000000000000000000000000000..c18ccdae1708486dcda26c5d9a9dacf407b9a2fc --- /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 0000000000000000000000000000000000000000..3c2ee83d7e7d13c4300537e21f4f26babdaefcc6 --- /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 0000000000000000000000000000000000000000..e3351449252d8bda03211543769456959ccab965 --- /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 Binary files /dev/null and b/extra/haxelib_src/www/img/haxe-logo.png differ diff --git a/extra/haxelib_src/www/img/haxe-logo.svg b/extra/haxelib_src/www/img/haxe-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..71c1a7c93f3ea9e9059391c20a87eeb441a4c811 --- /dev/null +++ b/extra/haxelib_src/www/img/haxe-logo.svg @@ -0,0 +1,103 @@ + + + +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 Binary files /dev/null and b/extra/haxelib_src/www/img/homepage_banner.jpg differ 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 Binary files /dev/null and b/extra/haxelib_src/www/img/logo_small.png differ diff --git a/extra/haxelib_src/www/robots.txt b/extra/haxelib_src/www/robots.txt new file mode 100644 index 0000000000000000000000000000000000000000..27a4026cc864b002397e8402be430eaf3cc0a9d1 --- /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 0000000000000000000000000000000000000000..05f6bb1a6dfa2f5ca3ab72d2346db095647cc6bb --- /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 0000000000000000000000000000000000000000..0c00c4f306278f5fb035f19640419d20a5f41b6e --- /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 0000000000000000000000000000000000000000..9121cbcd566bb3bfe53ede0dd4511e909eb0421a --- /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 0000000000000000000000000000000000000000..c7a5a78fc2480f0e099fe30ea5921ddd185e743d --- /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 0000000000000000000000000000000000000000..94a06a4ad15a773bb218a6f64bed8374dcdcf48d --- /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 0000000000000000000000000000000000000000..ac147492a381580f5c05cca75b78f9f21bf7387a --- /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 0000000000000000000000000000000000000000..5ac96fa34d77f8a91788df1b9cf741a5dc0c32dc --- /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 0000000000000000000000000000000000000000..dff775a11dea4b67dc2f0fb81071fd2f6c6e42fe --- /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 0000000000000000000000000000000000000000..323b994e306dd9d93bc11570c47b3fd52d762408 --- /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 0000000000000000000000000000000000000000..acb272f7e6c513b915398530e8afe3dc5839d7ea --- /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 0000000000000000000000000000000000000000..2d0cdf1e94e88424efc0ef1cace730b75aa2ce1b --- /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 0000000000000000000000000000000000000000..72ac08bb0de344c48b2fb63f6ae6d367bbf46c22 --- /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 Binary files a/extra/images/Banner.bmp and b/extra/images/Banner.bmp differ diff --git a/extra/images/Wizard.bmp b/extra/images/Wizard.bmp index 8bbd1799c33f877dd50da82f3ec5269c00e05cf3..60fa52ac53a93dcb1f0e57473d755da4a28e5ba1 100644 Binary files a/extra/images/Wizard.bmp and b/extra/images/Wizard.bmp differ diff --git a/extra/installer.nsi b/extra/installer.nsi index 36f843b94cdd339770699db61c265d7b4a737c50..b118b502772967628aa210834e378db258740b55 100644 --- a/extra/installer.nsi +++ b/extra/installer.nsi @@ -25,7 +25,7 @@ ; Installer details VIAddVersionKey "CompanyName" "Haxe Foundation" VIAddVersionKey "ProductName" "Haxe Installer" -VIAddVersionKey "LegalCopyright" "Haxe Foundation 2005-2013" +VIAddVersionKey "LegalCopyright" "Haxe Foundation 2005-2016" VIAddVersionKey "FileDescription" "Haxe Installer" VIAddVersionKey "ProductVersion" "${VERSION}.0" VIAddVersionKey "FileVersion" "${VERSION}.0" diff --git a/extra/release-checklist.txt b/extra/release-checklist.txt index 32b00d641011d1f72a1f8580dffecfc1f2f69336..aa2e99c5b1c9b5009b0f45c9d7cfdb6371ebf9bf 100644 --- a/extra/release-checklist.txt +++ b/extra/release-checklist.txt @@ -7,7 +7,9 @@ # Building the binaries and installers - Make sure CHANGES.txt has a proper date set! -- Make sure `version` in main.ml has the correct value. +- Make sure `version` in globals.ml has the correct value. +- Update README.md: + - Version compatibility: add/update the Haxe/Neko version - Merge development branch into master. - Wait for Travis to greenlight master. - Tag master as MAJOR.MINOR.PATCH. @@ -17,15 +19,13 @@ # Making the release -- Push the generated binaries and installers to haxe.org. -- Copy relevant changelog part to CHANGES.md. +- Copy relevant changelog part to downloads/$version/CHANGES.md. - Write announcement post. -- Copy announcement post to RELEASE.md. -- Update versions.json +- Copy announcement post to downloads/$version/RELEASE.md. +- Update downloads/versions.json +- Push the generated binaries and installers to haxe.org, requires git-lfs # Announcing the release -- Update Github README page. -- Regenerate and upload API documentation. -- Update http://haxe.org/file/CHANGES.txt +- Regenerate and upload API documentation (check --title and -D version values). - Post announcement post to haxelang. diff --git a/extra/setup.cpp b/extra/setup.cpp index 0bdeeb9e2fcb23db78509bc7285e1e244ff6b910..bfebf31bb20b92b7fca8490de2023b6ae379828c 100644 --- a/extra/setup.cpp +++ b/extra/setup.cpp @@ -1,22 +1,21 @@ /* - * Haxe Setup - * Copyright (c)2006 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + Haxe Setup + Copyright (C) 2005-2016 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. +*/ // this is a small program that do basic Haxe setup on Windows #include diff --git a/gencpp.ml b/gencpp.ml deleted file mode 100644 index 6584a9c44cfc3cb0ee005c20658d76ef1dcf416b..0000000000000000000000000000000000000000 --- 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 27bf5b5330ed57fed4797e25a2edfd6e86748d47..b29fe73b826a32504fed2eaa20be4ea2b4f719e7 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 0000000000000000000000000000000000000000..703bf30aca700e7d382df3df247799b8c3de9e36 --- /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 0000000000000000000000000000000000000000..b71ffd8e3e33258f23286e90bd5defd8c9e3b283 --- /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 d0e8b2f05549d15b9911ba63eb34f42bb9a65c1a..913d020f2188d8f3b1126fb53a3bd692e64d1680 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 0000000000000000000000000000000000000000..2298a441728caf3ed9aabffb55fb707f0b7288a8 --- /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 5b6e7c66c276e7610d4a73c70ec1a1f7c1003259..ecbc0593737be657aef92e3adcf3bcbd6fdb812e 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 2fd95ed1fe28f32bcbab5eebf5124ba964aeda56..101efd300ffc5e3a08b795756cd6c92781913bc1 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 c7e29ea5b52270a237d04192a041fe5b58d67d13..be7a6057cf3cfb13cb20cfa2c087c141d4bd34de 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 012fe1b2494d25702e1b66b3323544545ecafc28..644288371561a469ef9bfe8153e0f02038090084 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 8e94f7d535cb0f967ecbdc7df0b02f7dd2faab97..fef8c0984d9238f669997e0ed07abd007fe6e39e 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 b083fb1a969863a575fb6574e10f52a077800e1c..97bb7fe9adf842d13f011e4e13c4192280923c0d 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 0dfccdf32430dc7deda124838ca8b4ad9ec75461..20eb2900063e361763c9460e85c861046c776b53 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 a6bafaec28d7f437b1c6bda3209c060a31f2c46a..0000000000000000000000000000000000000000 --- 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 557594c173e8baf46ea0b4a5be18b4603bc59091..0000000000000000000000000000000000000000 --- 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 022817927ce3d6b1abe5ac57bff70e7de5291ae0..0000000000000000000000000000000000000000 --- 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 Binary files a/libs/extc/zlib/zlib.lib and /dev/null differ diff --git a/libs/extlib/IO.ml b/libs/extlib/IO.ml index 010969708a8491d477051e5282e6f93e23f9235e..1dec21650070fa06019865180303cbbf40ea92bf 100644 --- a/libs/extlib/IO.ml +++ b/libs/extlib/IO.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 input = { diff --git a/libs/extlib/IO.mli b/libs/extlib/IO.mli index 0d8a08f5f61dc08d5bbbd782d99d6e8fb97d6dca..e3f217fd0028acc5075236609bc11023dfb2cd9c 100644 --- a/libs/extlib/IO.mli +++ b/libs/extlib/IO.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 *) (** High-order abstract I/O. diff --git a/libs/extlib/LICENSE b/libs/extlib/LICENSE index d158692805c70720c018010f95e81d1b837c2a74..62dca13d71f20956be5f85cdce9cf407819596a9 100644 --- a/libs/extlib/LICENSE +++ b/libs/extlib/LICENSE @@ -17,183 +17,505 @@ Public License. ------------ -GNU LESSER GENERAL PUBLIC LICENSE -Version 2.1, February 1999 + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 - -Copyright (C) 1991, 1999 Free Software Foundation, Inc. -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Everyone is permitted to copy and distribute verbatim copies -of this license document, but changing it is not allowed. + Copyright (C) 1991, 1999 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. [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. - - -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 -How to Apply These Terms to Your New Libraries -If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). - -To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - - -one line to give the library's name and an idea of what it does. -Copyright (C) year name of author - -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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. - -signature of Ty Coon, 1 April 1990 -Ty Coon, President of Vice - -That's all there is to it! + 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 + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + 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 488d5072ab51dbcda5222afbdd70dc77eeedcb7f..9ed56c469950894e6394278235bd4548dc76859d 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 fc31848fbd348afae8e6d58c6c7c7a5bf4aaae06..70e68e7d258090b584264029e609cd57129b098e 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 0ac96136a1dd886dc24d1a552c5f889cbef73637..87893a0aace09f3a90fb5c32c25d7e3a23fef50e 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 38dd9b4cb453950eec0ca6b3f2a890167e607a5f..c812efcdef15816fdbb6a8959324fe2c2d23cbdb 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 7f10f47c75664df651807e82204a41c78ef855eb..184408455e351b7637c1d3d1d5386857a12a6f62 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 aeff7f7e0e9b77321d7d4c03839014c5de893399..9412f446785cae071dc3fe622b0d3948dec1ce52 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 07182917dfa5c999b047e4b7311d435b96fc3b05..308cfabc42a68182223fdacfaaba64d13c9ee209 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 0e0990eb68fff2e5507fdece4c95edec6033f673..1c992ae867b75993803740606b9afff2bd61ac6d 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 a94dbb349278cd490401aa95bb8bd54ee038919c..0f6f14b0c6a37e497ee802a51c0840cb5d42bdce 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 29660e16f37652a6e28bb8db86081da34e7ccb30..2ce39e98ad2e6489a6d91e0e8cf0b2af01c98070 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 3b7708d027d98a2fcac03be4ea1beca742bd2140..4528ad3e8801631251b8262f4423fd08b86ee3d8 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 96e0b759c7c7a4019e07711e20073dbbab49fabc..79c102e8f1fc346dce2b34c04924d23bf59d4ffc 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 545151a7632d3bb43c677f11ed68aab2dfc56d16..07c83905c2a330fb5ea2de261a8ab0ad099bbbd9 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 738427927890758ce21a862fa4a24773872c190a..ae198618903242477651a00126bf60c51339c487 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 52ff0734c9aed5427a9b8bfd95aa99a0d66c2622..aaac6494cf5362db2b0c5dff9dfe967126ea7361 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 8df3f4f87fca1bd49543c5042d0a1bdc97068d94..d6254d1e73d8ca68acda31260f21d19925b5846e 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 17ddb56c0014b16e8cd99180fd2e0a6159fb5dda..bfaf31b633b9b83513d62f22f24e18fdfd6868f4 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 9380df5c7876136865f7e913a55065af50429888..f699feccb2ff2932b9f0f95db6cf248114dd0c62 --- 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 a8af16df3c0eb39a08b459338e8c1202165bc369..87db836e6486516ee7d23ceb1653940d65d3f7d6 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 4365d7c054fb967c167b7051dfd42d7c93f9d648..ffe96a2f3f412ae719ce07edff5288db3390706b 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 e3c94a93a36f5eb65ad8ff09d9061499a8e28c62..93213c0cae2317b3051dea4240352889d2df9ce4 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 16d2af7a870c8a17459d9ed02e3efdcd49890e6e..7cfe62325aa89d515ff316664bfbaf777cc3df37 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 904a7d417704428cbb18440a901a68b36862279c..76436bb333aafc12067f5c9d1b47427abb889a87 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 009ebab8a0e02c1a79544903f795e111652ebb1d..862adeffc0f349ad0c12e4cf437c2406c5133d63 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 e9d439d03c43369db130bdebe35d69614f54028d..29ea20520ffe02e3ddfb9287e2fe92682f2ccb73 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 72bbba76ed483c933c33790cfc700a422c49d392..0c046f25ae1ec59f6ed1f5dc8af87a92b68f97bf 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 4ff4488bf39e1160da28839bee2547c117010613..ef64e72d8987959bf27b35663293cff6d26ec9cb 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 760258049c104eb2feea334d879be2a028dea2c2..65fa71205e83f8800ff0103f6397b9657842bc60 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 ab6fffddb17e7e0be87be6be5b7b046512865119..46601008a8eb2afb6477619eaa7ec488d6a06998 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 0fba89e70f72029763d03e05c9202ddd2c5d3f59..21960d6833ffe709f5f521b028de184052512432 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 b63c64e7f32083cef2ffcb31def9bd99f4bd5b16..c6dcbc7544eedc1c036a651fcbe44bc91aaf4e93 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 01f2c8cde1f337dcbad7f67c6894f5ced2116934..0e703d84d80395f51f949f22649dca5dc7fc29d8 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 fe9f0bd752188e0f0b3e4b51233d9bf15b250b03..9c4d15c527459da3678a00200e5dabcc92d8155e 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 b16b6f21e35d1ab6cfe9ff3a1aa0e5106a709a92..c031cebb530dbcaa84cc4270e590000405d8768f 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 ea7bc06f4040409c0ad0b6a41ecd5384eb14958e..fac93435168c1b63c8e180ae8818ff6d768e5267 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 0000000000000000000000000000000000000000..025f3cc4ddcf38309cddea869436a5a3c8b39084 --- /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 0000000000000000000000000000000000000000..e35746767945dd02fe93ff84a28a8eb700a2c495 --- /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 4903b82961b43312c9150ae07a84833777c21ddd..157bb3724b082e2d6eb7213ef5f186d340445972 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 128d969d7691e19f4c07a465af7715ba121e9ec4..ce243161ecad30dc69e2949b49fa51d1e5687bdc 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 194a7532f029d56422c4bf28f6171b567c87913f..b8d52dc95451750f98e978882f9d42b0fc993fd3 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 23015053542ae52486af2e79d75d012d02a9f1a4..864b423bbd1e6e05392d54541e793f1bcb290b63 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 b7da7b9401a55d108e542310308753162b68bc00..3929228b46c3a669a6013024998d4e5859ae305b 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 72d9a13dbc382bb29c86f24db67a1f467895ca04..55720d1401fee86875c0c079972299df8e450e0a 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 a27e12cc189c456a1134f0a3cd31a9ac2ba67de4..bce81032baadbf8b377f6f4c8d5acec571e54324 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 5a21cfce58a3c896207b6eae2f7e0e4671c546be..7de371734cb6d55f6f11054f2df92e4f5b272655 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 d8776bdf9bb9cda3dbb2e06f12f510eb19a2a2d8..377fa234dfe53b33a266c9dae5e710c1e7dc7d9b 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 abe9bedae0deed0f9356c081ab318974f963c078..4c77746b4c5afcbd73aef890a8eae42d95b0ba69 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 50972581a410ae2b02b76da3c4d357c39b51ea66..023a14e5aae421f149bc19810ab072ad3bb7abf7 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 3d4a62b1e76ef95c6b640ebeff8384188f3f57d6..b123d19b3bb1719c4cf6b7881e4845488a3e1666 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 402099bbb97f01f0f3b2ba0b3cd781e22b500bc3..5630e99bb0e67e5cdd6564bf06d442252c9fdcff 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 48956d5fae4208c160643238441742681161589a..7e9b5465c65ef26c8758c21661606491d184f971 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 5cd4d5d5a47108777e1d53753e13351f6c70b63b..0a3881aa25fa6fbad8cb64dc8841a49fed9710e2 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 50a7605199c4b5e782e2c859277957960734dc9f..2c41a51d7ae609d751df4d38d163e098384d1e7e 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 6016ff192201382909ab12960501c23667a771ad..1bd1f7e8e73b834c4f40f304cda5289b3f79118d 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 cd8d40919edc9eafbe55c1a70f090a00ea4237cd..c6f976fbcdb24b7c252461c5c461e5da4c1e9dca 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 2032fc62ae7b921c016a8df71c1ff3c63cc51bd0..e5b1d78ff0f81a5c10b51aaec8020bdfb64c054a 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 82fe19c7615245c57b742b24679cbea7e80d7692..12f2561edc6f030c94d75dc2d156f4a15c5947f0 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 6752d40fd841e6760d66173504d42586de17d44e..95a7c5248ba817e772c2b33f375f7a4fc2b18269 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 76486a43da4b5b3018997f27ed971c93fca72dbe..2288854c34a1ce9d91e0104cab9b6bbf2728a768 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 26b5cf86da7ac3fcd0328602aa2bfdbf8001ef41..c73398734baa3b6a5034f58d836d5ecf73e3d2f0 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 90c84a7206d35621465ec6769c7cea494c40a52a..c265794b5e6bb6c9ddaa5bdbafcb668accca157f 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 8dbe61dc4f13fe0e13847a4b170f2dc4dfde872f..4e373e0b2766cc8eb555f00bed97d4f59d7305c9 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 93f3b8ebb89afa7351de6de7fb15e1f9a2d2c2ca..756c62a166d6dbd64358ef5b47c9caab55328886 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 ac0317c96dfb54e496aff34090e519ec6899544b..e0bda81b8f3d40d682c488ef6ce2e69f4eb37ded 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 0000000000000000000000000000000000000000..8561650ae114e3387520506b7c3254f27c32edf5 --- /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 0000000000000000000000000000000000000000..59eaad119b55c717fac19354ff40f4b6d0e58446 --- /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 0000000000000000000000000000000000000000..733831d8ece8ffbeb76ab59c7e0caeee89d0c62f --- /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 5b6e7c66c276e7610d4a73c70ec1a1f7c1003259..ecbc0593737be657aef92e3adcf3bcbd6fdb812e 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 f299a1e7f77854bd57a0b2e9b86a8c18c91d7e9d..ed80b6f57a2d58e0cf51bc80d52f83983bac94fc 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 f8d9f04066e535b70e6db065dfe4a0d7d6f6b9e3..69ad6f5e007b4987ce3ba2b7728785d516506768 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 ce8f2695093c9442c10ca463ef2064be56866159..283f3ab99b45234a58ac2c5304583033d0fd376a 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 17a7b4780882041fea78b10768acdf6f6ee87893..859da70a5e6fb93bf7860b9adda97817e680dcfe 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 d4a18538484633ab45b62967534431ea11572d64..8d6ee2d7c233ac2936fd0a13089a9932820e4842 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 ae7baba1c23bfd6b65b158d7cadb868959c04fda..9e81184f105e5c4da6bae2eff518b04e24328306 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 45ecf54f3c9ff4e740c348660e5f11556c14a546..95c4a71f771e27d25f8af4c8a030c37c52ba25d7 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 43e91dbabaacda2390eb535edf6b5feaff4ce621..38804a058c06913d24345a1163526901edd3eed8 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 c8b5a420a8d20aec856aaf2678466dbe205a9913..5d0a9f64a41e2632b810c4a26808bf1fb9d5df53 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 5bcc9a6fb7184a488262d01559edaa9dd656445a..a753df45997dec5d420be7562717756d614ba49c 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 91714b6be41cb25c9c61e18bd63b5214c417f907..4cd9698c9971744dfcf890080c6ccd23c8a78691 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 58edb1ae35df935deae9b061fc34267baaef8a10..6fb95f1bb8fc8260d8521ba015bd93529e2a2a63 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 a3b69dea5990fd5719555963798835d9cf0a2840..06ae73f7521990f3bff2c32d8e3959fd779082b7 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 4f4c32c54561780bc72f1d5573038576efcc4548..0000000000000000000000000000000000000000 --- 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 49397060eb86b4fc3c2196b93ffccd049499bb58..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..52b67c6b165e79a66df95a34ed09436f9de54d37 --- /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 0000000000000000000000000000000000000000..0cbba02db5a96eb69a2ebeb55b86de474bc654b3 --- /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 0000000000000000000000000000000000000000..466bd411fceb357364a5d88db6facf66fa887098 --- /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 0000000000000000000000000000000000000000..778b9b4e3f1a1e62114f5cfc397d7871f91e64a5 --- /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 0000000000000000000000000000000000000000..83c13cf4f8fea8a367ee71adbf4d40fab0106070 --- /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 0000000000000000000000000000000000000000..1e9b08436b55962a54862b5833c8b6a841f92493 --- /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 5f999bd540c5b72f12af175370b9fed795b853bb..7b717f23950abea860e2a2085a7f84ce4731f84f 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 a8b955e51b82f7c483a43bdf71bedbfe55394527..39fe80a83784894c6d2033425b70eea57c204c96 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 0000000000000000000000000000000000000000..355fcb41dbe7809654de6f6a1a4fc8a279b94665 --- /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 3c80a34a9393361efd32b10f133f704a16713ffb..3f695b2ecccae464af44d22ec3d889541bf554cd 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 0000000000000000000000000000000000000000..2e3fc1917b8cd916afc1ad495864e2e8f5c29383 --- /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 92fd954760de5480af57f13dc35135dd0914ef4a..65905d58bb5671b7eb24db94a0d10f83fc71ba4e 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 2a23015e0e0533b864f385ba420fb84943ab7607..d094edc2809677681ab95dcb2afacd2699c4635d 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 0000000000000000000000000000000000000000..4daebe0fc7bdf72c3bc3a2208ff6358c0b7adab2 --- /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 d64ec87956c4ab721a6125761fabe84f6b8fae77..326a328056c10289febd8c71cd0a3ad5c8b651be 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 7f7e3404dbb701e59897c2a983425770f341cb28..46f22293b9a9cb906ad383d5b7b4db7099babdaa 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 0000000000000000000000000000000000000000..675a0491eda1b3aed26a529126f48571553f9fe3 --- /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 f9d7c85bf16a9d9d958efc0e0701faf7118a6b5a..ca3b2960a363e22e93f6a7ec02a5f9ae389681ed 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 e53ec3f271af6f6fc0b18bfa877206bfcb1bb65f..cea1267bddf55ab7e2da4431c4327ec163e4ce0d 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 1d3bf9f3c102db40d0e094dc99216ff23aa02528..f66447d7014da5ce30bbb94eb843391c682b0857 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 34d86dbafaec6172487807bc9c6f43e5f7314363..5fa9b37f31023868fa2984fdeeb861acabb4bf3b 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 0000000000000000000000000000000000000000..00b541b4cb7745895e6a5d8925aacfe739696481 --- /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 0000000000000000000000000000000000000000..00a689c2b62aa19f0853e52d1dbae5dac4f93019 --- /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 0000000000000000000000000000000000000000..bbd65f1dd0e5b97216dd327f429fee0e8d23103b --- /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 0000000000000000000000000000000000000000..66ee3f78428ba458542ac8332c97d759de18cefb --- /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 0000000000000000000000000000000000000000..11d06d91e7d9977f9ec826b7bb260cdd2d75e916 --- /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 0000000000000000000000000000000000000000..550d9b08bb44c017255f3db3d9027eedbbc04866 --- /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 0000000000000000000000000000000000000000..ddd4b8a53ddef3f44c392e13a5ff3f036321b229 --- /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 492b909bce8ef4e602203b5871bf34ec585e0315..eb7b7e37d0791dbdec06678d1335ccf55034d224 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 0000000000000000000000000000000000000000..9a0c2c87910712e52c291896a97781941e23e84d --- /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 0000000000000000000000000000000000000000..b19a3a02876921a025118b78061fdd973bf42e6c --- /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 0000000000000000000000000000000000000000..5fc1140e6749dd1e98c5d554ecb5360548a88554 --- /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 0000000000000000000000000000000000000000..827abceae1b6533171e36563cb965d776864bab3 --- /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 0000000000000000000000000000000000000000..d93cad09f4e8533f038eff3a682aa2e56445a27b --- /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 0000000000000000000000000000000000000000..8a4f78144abe9c223a636f46c8c4db2cd67b9734 --- /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 0000000000000000000000000000000000000000..7a3edb4d77d3367461b66d94c6767e0e686139bf --- /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 0000000000000000000000000000000000000000..04d7099593cfbae3db7bb123528ab54b218247e8 --- /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 ca34d26b437e680e484d0cd5a9d6f387fd0c3281..40f757dcb92255512fbfddd1a6e1980bf7955d98 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 a8d557e4f7a406bcabcbe0793889024294d25aa5..9d1bbea96192c114ef8080f5de436d12cad90b46 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 5cdd33362e6f59874cea6c23fe17ca7b536597b0..51f1e1851c71457594b7a8876a492668ac655316 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 0000000000000000000000000000000000000000..ae703076f555b3c7ffb8bc8d5b4906f78c3b96b7 --- /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 0000000000000000000000000000000000000000..a3b75cfa335ff5c611f8a496dde7c36ca2dc9a5b --- /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 0000000000000000000000000000000000000000..c1ef7f05ba15feff4493eec1dde16cd3acb1073f --- /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 0000000000000000000000000000000000000000..08e11efc6e7f2b93481d4534c1cdaa4888dcf2cd --- /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 7ce94570e308142f18b27b2dcbc12a4e0abccb4b..c4077c0d822304a3f7ab2b071d4cfc9d559d5080 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 e45e9def74b174cdbe8678197f3bc85a78a82cc0..fd5097a1918d8a7b278dd150d1143e8e8a6c5d3f 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 0000000000000000000000000000000000000000..63eb912abd28e5d3f23eee4c55d0a230dd7796ae --- /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 0000000000000000000000000000000000000000..8e8447d21d26b5536cce3bcac306413968716a0b --- /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 0000000000000000000000000000000000000000..f3de28e82bbeaad1f7e1d1c33dff537b41a5f97a --- /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 0000000000000000000000000000000000000000..4cc8d5ca3d46318d9f01d1176d510780f58e5eed --- /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 541c976843c55bddf55cb59fb99cbe30fc1e5510..b1c176095b3d26a89f1bdf57113291e86eb9a354 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 0000000000000000000000000000000000000000..8bdff33f897b52ace1995410c590e4524fef271b --- /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 0000000000000000000000000000000000000000..838c68ff5ee263fbaea5ca8eb71d3f0fc2cc86ab --- /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 2ddf7ed6f0fe8a29ce4a9a0e837638aca02ad727..919758a16220612a859c65166100efa22e417459 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 0000000000000000000000000000000000000000..015fd7359611fb80a27077d0fe81f3b36ddc410f --- /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 2645f92214f68d50f5ec7dee8a89ed0ca413286c..76784692b32cc43b1ef1b2edb149fb72e95f66c1 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 6d28bb2f127bd585751f29f19129be878ebd98fa..5eb31102a8409ab2f82ccb8135e32bde8c7773b5 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 6fb58a1457c6b48f729d3ed3dbce7a6608d95abb..fa833baf70eef11f7f9b1fc94fcad91bee2c6c48 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 a4a0e1c93871db719ce928e27bdc2d2d33db7130..f7578bd97c35bd2ad66a806289e065933c2574f7 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 509c6c810eab4d033d90b00cf2f71414b2e29aee..62f2397b33f0ff6466682d595cc5d0880662dadc 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 ce1bc76bb26cb16b631e7ac9b1b463d36f7f5567..8748bf94ebeb20335d9106dc7c67e2ae29d9bca0 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 db0b5bfe155683cc4ac10a8f9c796076039bcfff..eca6d58d484a095c87aac8d66537bc37dba4fd83 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 a97c4297c166c5c2ec00715807d9e20d15a001ec..64705e2b5bd7e3ed7778c1cf0f57935b36587f5b 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 9313d9b246337c8ec09c0f41a1da8a2d55e41fdf..5d6efecba40512442dd1ef44d5500f8e80041895 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 dcb58bd5ecfe294ff9923b4a781149beda37f4f9..4cfed4012367f3d6111948c1c1156b0ace1f09cc 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 1d0227ac27d29a313d35b87b8f08581ca631de05..e9eece5542fe0fd5a81a673cc68f0adc751fd9fe 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 4d246f8aaaa9187825c4aca9d90fe5b67430c13e..8837f100049c0255f517f9b2e9ce9747fbbd23f8 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 e94ac3218337f3e82a4ae4a2f8012bf81909b258..03807936b75f71a419e951e29572ebb2df4e2d87 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 70e64b96f09fc51f56f28382c6d011eab850f49e..10cffb3a32a8188be1cefbedc9e4c6511cd80dd6 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 76222f7fc445e54b68228768b10b169f97beb285..8a2a62c6f5e2129ce6d96264390783509994ce02 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 e523500cf98aa96cec86cecde32591d2032d06e6..37b38e2066fc4c6539e2f360cc7f463a4da95fd6 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 2684e2a007c9d3d24e35d3bfacc1ce7f3f0afb17..6b80b1178186b0c89a84f721cc4d2cc985253614 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 23fb84d7db1e674d3a3aca9572e817822a75a04a..3d502516bdad05849721595c70b5c3995df7e493 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 687a12485a8e3909ed97d43175c33ec57f412f12..de52eaf817880bc7ffcd543f44c998856cab6d4d 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 fe1c831552c2c688e3ab1f8a53e30f1bab047024..ad81c2806fa033bee8dccd1b362ab8f81171ef93 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 458ce7f4602c76d8272676bd508d83c5ecea1376..bdef243d41192d598f9616490fc337ee6bb4234e 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 0cd40d403bb0ca04fa3afc03069828b329074484..0a0f922eb675077982ba3de21574856788bcaced 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 06e26eab204875211b4aa3994bf6a4a18872481e..518db9a426f5277a78e150b4adf3f0958f0f0f68 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 0000000000000000000000000000000000000000..cc88d8c07f10cc5da311cbbce0a41b11dada24b7 --- /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 0000000000000000000000000000000000000000..f7fe302abb5ecbea4ca53679302a2fceac9ba1b3 --- /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 6488a1dc072b869b7e9054aad89a1010d4e18fec..a3c55b2a6f46ba5cccc81258fc89c3f3cf77ad16 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 0d6d2957ee543e1029594b414d510fec2159550e..fb91fb981c2cf77a5ea70c8e962b18763c3c53fb 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 bff39e9ed99eb02b59a6607136200c9e9464b8ce..5524efa6f176d5c01bff18b1c9cbcc4ab3effeeb 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 10818f955253f85c666295de3abe605c0c89a7be..5c7cd82254333a65297820afd9b28abd35a65d0e 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 27dd222c0a5ab62de9bcc26d7b8e9897a0473474..3d1225c334b6f9f28283706ed95523326bfd4900 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 0000000000000000000000000000000000000000..9cb66493f2c58726efb203c7b185c9d2079edb52 --- /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 d7b11a49ac1aae564bc11f5b66c58055fc488171..f80371d979f0343e391d183cbfd9f30b086ab8a4 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 bf31025e53c4177d1642c9f35b7a8ff03d159170..b64f41793874faba02c75953b8866f7c073a99d4 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 0000000000000000000000000000000000000000..31a086ac1a2c5c72351566ed6232689bce17a7a2 --- /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 16fee0e14b5a48ee888d38d87cc0a76b484c43e6..7b852f032a3a0e3f4f5649578d6f37a48b60764d 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 122a738244b7564a44dde3c75c7e376334b65a67..1bf957fda49dfad9b1913c451392a58651cdd4b6 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 0f266a51b344849cdf39c3337476e59b5fbbaf1d..dc1ad36e96e2d68fffa2b9a2c8bc8501bdb513af 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 3a4e5d5a93af358de8438c8bf409d48051f0da8d..0b67d0d3470d09f06b905a509269974fcdf2dd8a 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 200d91df2929e8334a61416cd53ccef85a701716..625499018d67b4ce9c9cec81dfd41c243951706f 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 0ceed936ad02bcc1f8c0e2397d1ce2ed178e7dc8..b10e041f685ef1afc582af347627eaf99a91387a 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 bd195bc186de9fc3d615776912ee51da966378f9..844cdd3e2c45bfe2b1ed88edac60ab65166ef898 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 af6bcd0a479fa0e43ebb884a798857ca859d5af7..49978fa980e9c4c2c9a53d2aea095528f46d3bcf 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 0000000000000000000000000000000000000000..286b7147b9583dd64bbef5403940ab5ace1f1ef4 --- /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 901d9e36125527c03a8459b325cc2d039a163c12..05bec6222b0532581bc023a8dbbbc554572bf29f 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 0000000000000000000000000000000000000000..1caaf9b23dee1dfe7ec596c1936f6e3948b9bd88 --- /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 0000000000000000000000000000000000000000..efe65a94def6ccb300b49ebf31ccb4c077beac92 --- /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 0000000000000000000000000000000000000000..d6bfaa6ade1f3793dd2600a3391cbed0fd725b92 --- /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 0000000000000000000000000000000000000000..fcce680fd3aa355aa82c6787ac2c9f638e0c7d7a --- /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 0000000000000000000000000000000000000000..3b6a41be178992aa151de7becea607510b07dab8 --- /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 0000000000000000000000000000000000000000..0125556405ef5390ed6f8aa9f6f0e6e38976128a --- /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 0000000000000000000000000000000000000000..24766599619bf90978d18dff05a09c6f7ec91c73 --- /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 c0f9d5c991a81334b2d2bde28d059440ffc30362..b9e3ce5332db60f8af74ef71e3b068f37260fade 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 0000000000000000000000000000000000000000..17e0383d2f8c694d0b3ba75e1c4d75d2d87545c4 --- /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 9e2a6f220961703f92b96ef4eaf320fa109a032f..0670d686109592f928548ae997de86d2a9fcd7cf 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 0000000000000000000000000000000000000000..140f3988d70d5bf350a59745fe33e0b3b67508e6 --- /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 266970926beb17dbc661330efff52e833559fca1..0a0386964960895b920ee636c55c9d1ea98a4001 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 0000000000000000000000000000000000000000..b527fc2a872b6629463776bb902640e3fa0fce29 --- /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 de4aa7f48d3ee658048350ebd870788defc60bb3..98cc1323964c1f4e2c45541153f634bad6ff56d1 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 5f6019078836d5e949b49382f62cc9f4cf2ed8e1..b0ce509ff761a459697dffa515929309a21a9057 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 5821def7feef4199a12d898960873b93044e230b..3b47b8872e02a72044c102cfa025f47ebb9fe384 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 80a51ade90885579ac595ae2bd62dabec6676876..426b0307625ef3fc0f7dd6a5bc83c639a4b46a8e 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 17bdc048170ba8619cc452f32f8c963e2afb8111..2a9381bbd0acbda3250c731925f980ed09a8fbcb 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 7dbef5e22715a8fae05a9b6b98b029754df9c38a..884608cdcc3f9e3044eeb22e2123c1e54b971fd6 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 0000000000000000000000000000000000000000..c476e72c8b242382deb1408fa9bc9f11646681c9 --- /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 b87ce198711c4eb5ddfc2d2702d2cb955fef3d77..7adb84042951f2c1f9cd923eb7f1b504fd516f9f 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 0000000000000000000000000000000000000000..f640dc30e1b5650ac1dd7262cda344524d47532d --- /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 0000000000000000000000000000000000000000..63dd8f272e3b87ff0ab1a784afdcc779215a7687 --- /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 0000000000000000000000000000000000000000..6e09a66025a7efff60d5f4c1f735c43d8abceb75 --- /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 0000000000000000000000000000000000000000..12a461438822b8ddbad4b67265027514c3c365aa --- /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 5cc859b5d35f6c8c484d2529e5f6f5809439cfa6..9a82bbb4594187e2609c51bab71bb6d282280976 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 825497bcd3f7daf15547426d07b372cbc7cc24ec..0188d5b9633c73e35095ebc601304625ced8b4af 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 ee729164510f278df2724db6ccedb4e922bbe1fc..6662d6a603e7a842388f65cb40d19520c1bcb56a 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 5514225eac547160d89b665434ccecfd66d8b5f2..f32df37c2f69ee29f3662eb10fbbbb9f43ddf9a4 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 0000000000000000000000000000000000000000..655587fe8475748aea23144caefd7acac60cd373 --- /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 0000000000000000000000000000000000000000..263ab7528670a7818957240646de5303227e1116 --- /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 4f5bea4854baf15d59d1622610a9884ff660820b..af33561ef47432c1689a985368809a3cf6dedc2c 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 f448b1f82d53bd140dc2e3999b8b9da762987202..f960aa14b74ae900257a0a9f6dccb556f6b78cbc 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 c806668dc5482dfaff2b9f1f0f6cefc50d4ada8d..676837558aeb82890948b8d3828dd93d4c93a8d2 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 c6d53f6ca39e1ac089a3f1b7c12be790ff83bdf8..a80e4d214b21966790ec1ac7e96b4999065f88ac 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 1ea51dc3309a8769f54fc1eaa3a561b96b8305f6..fe7a71048a7347ac20d36ea89e3cbeb9f6de9ebc 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 5f4dd1a04557fc82d9e2cffac55300f32adb14c8..30d4e4b8e21463489d705813b5c396dfb1bf1e1f 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 e5bd3f98bd03917db9ae7ade98947a9b7294f7c3..88a0c90f23ec1065e97c9246246e7273ba5cc52e 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 9ec0bf5103f1e175f1abc28ed0c6ea02aade885e..0e75eea568942ebea765ae7a47e5a3c611ff8956 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 96a040e48ec181b47d12cf452e542ca569b96b94..e59d97a74680e1c0a9105c2f88549a3cfee076cc 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 a5a13dd9ff2cb26373c4e7b0ceec26991f46c799..ff6e0501804b4b4893356031a535f29e02b78dfa 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 b2b2a9893a711052fd862d249b4d82a3b2d4c7c2..24645e1221e7e381a56830a53a5e95b46273d9d5 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 6a454ce6136c1ff948251d1044e397bbc207922c..4dd8ba34284740f442ef31651bf3904840dadc7f 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 44c1ddcbd0668a04c2dfb0ce1862ba9820083e0e..5fdf58eea6c77540309efb18671be989dc1e7d04 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 ac0df37e8fb137387669168bf1ac0c607a08c332..0b7b34e0ce8812d6352d30091dfb9029ab9882e3 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 eba277957ad9e1087568a501a51d0c1f263f715b..afa69eb3c3fa643304b4979ca3d376777ade2d44 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 92e236441b5f169395631754d94189afe4c8c339..8a6244f3888d35dd962b004a0edc5fb2d2b933c0 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 3972505569328fff8036f47cb8edf86d6a2fb242..959b42e85361a89ce97a91ec44fba63c3ec4e6e1 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 c6783360ddc3aeb9029c4dae3063ae9ac233bdbe..449b97f6f86a72e7957af322e477dd01d4538fc5 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 4fe60d37f2c23ea5a28d9192ac4bd32e038c24ac..153207bbf89a7a6194ec0c00b1a177a53d05a25f 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 babadf959d3ad72f00ad4de3f94e3d214e6b8cac..d193f9eef25dff717433dfe053dbac4969d6bdc8 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 1f97f6b10fba69a8d270e85dc5b26eb0d6bd900a..086641580e9c1c9138d46e0044dbe156b7c1177a 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 1cc9d44c55a6097864340caf304fd93d1ecfa1f8..e7ba92bccb0bd45e4cc8e461322fe561403cdd3c 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 59d8e2493a3f35b39fe2f10c535b4bb9ef1d7840..a719e5011d737675feca2623c5f856fc946a1060 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 3035104b2cd2610bb9cd3d63db2f44bbf991f8b0..1d1177f64a2e1c76969072b255d5cd5ed6d07aab 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 e6612ef429a202184d6892933958fcdaf0c1419a..e8710b3189a771dfe8442354793e1c76fd962bc6 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 0000000000000000000000000000000000000000..f3deae9f857636d071713a971d2757ff7778a5a2 --- /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 0000000000000000000000000000000000000000..de676f4a53d9b24d7a42aa84aaf0fbfb018ea7f1 --- /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 0000000000000000000000000000000000000000..ca6300b4e1021dc23eee6390f0fdc2e5737308b2 --- /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 0000000000000000000000000000000000000000..b078855df83435792d3b1a1123f5ab07813ae0fe --- /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 0000000000000000000000000000000000000000..204ffc4130f0d8f3e41454b2965df7b6e0cafab5 --- /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 4e65c89e4995bf9f7f464b15c79aec071676d3bf..c313080925cec46ad072e5d9d3b380fc8407e1a2 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 dd754e4042d0009c78af70b9f8348374028fd39c..8b8cf6f5f397e00f2ea131a3b5734f440f8ea575 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 a8802b71cdeeb4fcb702d24d9d51f20024868e4a..921bfa2ff4bb4e64bb6f24703a19e4a75361476a 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 3e0fd8171fc184357d6a5bd3682dfa862c10c0a8..271f3d79ac72145c66d1c62ff0eb24e4d7edf7e5 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 1e98f0e7f76a93d8c1dc7d445b3a106065b0b0b4..077f8294dd1b571bbcc977fd3031197bcf0ac108 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 4a57e31d9ebcc57a9da7b7ac84f457e2a8116c8f..1ad8dd7be975f0916aa7023375899b53d6c54783 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 dac1e75850215c30cc4fdfc2c9a861e2cc422495..5efd1e9e99f31aa0c4975df5535274253833951f 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 d2b9c6644f7f55f4c55aefbf8b1b6dfbf2121e24..5f371114256013876bdcceddf2c161c705b86bf1 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 0000000000000000000000000000000000000000..8bcbee36d273a165976f51f1a926588f13332d59 --- /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 75d5e4480e9d9c1c0c1c9fecf8749d2c9da0b40b..bf6a487f4445f0fc745185392c8f10438fb44a2f 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 74a8cdfb986932166449de1394e5e7c5b871d137..9e470c188c9bc34bcb2b59221e26d6f91fe0d09b 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 1e382f139d2f340127be8e568c604f78ecae69f8..dcc34722e7338d0d726108e6a6d7e9cfe229cefe 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 a58166d89ca118d01fac3850938884bf35e6cebc..d65097c3d589954eefe16de25c44ae25a35e22f1 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 471000a05ae6ea125e9708597e59c85064054f3f..ef71a56818e15b91a4ff222e0522827821c930fb 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 08bd05b293eb487ed0a613661eec8f21e94494a1..58a502d4a84a3c3fba5a956760c492e03c194d95 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 ebc996ae51258cdf331131b9d83dc25c3c822a30..54d85faeb66e04da2a21a941a02226bca23b0333 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 0000000000000000000000000000000000000000..9980c8bda6ae967fd32bfab89589faf3ebfba5c4 --- /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 0000000000000000000000000000000000000000..a8dd97d6a15d126479a8d5690c0ae416fb463fd6 --- /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 ccd57269f86566a1c7a37b0bfe81e0b7d94a3c9f..2510d66d96dd51001128c538657dc17047601699 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 0000000000000000000000000000000000000000..9bba4c32737482e506c6ad0dad3533d406e42d62 --- /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 0000000000000000000000000000000000000000..9c8398d85006342b62e3f4e69038105450c1b1c3 --- /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 0000000000000000000000000000000000000000..c82e228bbf7ae2fc60c790577582f2bf768b9ee2 --- /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 0000000000000000000000000000000000000000..4075faaaa2026467ddba8126989a848e8d32e3ad --- /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 0000000000000000000000000000000000000000..1c5c4d92b538dc72d016f456c38d0459e953f472 --- /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 9b9ad7c39b9a7fad931ece6740448d607c91343f..86908b8c98e3a4beea4c7caad48c17713e2b5487 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 baf3d9d36e2f23e1441f2abb34813c548d6a84dc..bc04b1d30cb1d97d876f74a6b417a7d3c5d32911 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 1dc517bb75ae284638a2d5975ae4673ec94d1ef0..acfac5bff8d74121745e411450708b7e282e04dc 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 999afe521bff26f9e64d1203cbabe43aecc776b6..df6859f8581ba30ae09902483338c5339526bb01 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 773bcf168c68b010affd5726e90a8e2b78d282b1..a9a9e579b8d03dcda9c63228a466b9a251c2f9f3 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 be6b593ec71c11228b0a67cf6c0c793138a46a30..7aa0f8612d0ea6d11e7e42d9618ccad7cc2d65cf 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 5b65939c6ad262870e692441640578b437ffd93f..bcde565ec16cfe87296d7674995344e90135e81d 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 6c0759e2a0eb58974ab7041ec551ae0a4f5d004a..926e0992f9ab70eba3ff92ef6c079b749f570b8e 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 8d2f9eb7ea6a3cb5964a17870a5c5f062bc67d7b..256ff70d594b6f654ab59f21d24aa4a3c7c4988c 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 db7fec68e326aebe31a3594b873be3ddde595a44..1c23f1d1b5f13710e6a0e9dd6bb14af659186268 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 e5585aeda463c5840aa3a36b532101fb6a40b552..7b04453eb3ba65634e77c08b948b5e82a84de6ae 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 f7291145e85ba5324f76826e4dd7213f27ca9a7c..c6a969755b1eaf7d28baaa93a7979b978c265b20 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 5e52bf68ca456e04276aa1eb168926e6eb0c0ca6..5f94877abc82d2e7f72cd1bd9b14056c4380e572 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 aebaf300ffd1b68189ca87d0d3d26614ab6b3d60..adfc2827042c685f8cf9ec7469630d3e513311de 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 1af7536284cc675ac33fbc6fefb2700cdd766465..5f256fb15bb352433db9b41868276312e44c4cf5 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 6313aca6b7ea7ba78c9c2541e0a345f7c7945e35..8446b44408648c8cafc3035303dde8be47f4f823 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 9a3d6bf462ced8fe9c1807e9f6d3d2248630d607..be60e5cac1ebc9b47843ddb71f474e088a1f845f 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 f9204ba359ce996d39df29eb439bb0a13a16ee86..2dcbddac11713ddc1ce9e98106229046fdffefa8 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 b884dfe2b3a7ae7a4f1efdd078ad6dc7d7cb878e..b8cd8ceafc072126f70ab05aa6e9b017f4b11158 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 2435dd3cb2efcf5b6a5423d6d208ff4dc9f7880e..478cbe3b03e7fd9a0a44584858df7fc815bea005 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 df8c0d850365ca109705db4436da98c188f81761..587097667e2e8fb993605176eae2a7ddb05956cf 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 16dc0474c7b6410a77bcd74acf53570d3db58cb5..b71af6b484a4ed48b4055b2e0e0a524a8b329b16 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 aeec15adeca1553f1ba0aa923684674bc6641434..024d5da8a3f3142e965081aa94b5245cc3e1d979 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 bcf746dbce4ac68527b824ed318c7df4dcd7f231..05cef4bc506b87b1df103a87f4f16acc83ebb39b 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 d8e1f6f1290fa75dae5bc9bce4fb53375e97c12d..5ed8d0f0abe389cf21fd0f943e68895f9de001c9 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 afe45e877a68674c3664886c355c88f1fdb6e910..1f94ac2ae21780ed8d88b650f5123de823f32728 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 262407a42f06b17d236ca8b88c9daa847b6e994c..b430359a6d4c43c4a6533e3bd945fea19423f5ad 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 b06b4d11bc3fa41a9ba98fdbcdaf3ce6bc009b35..3b867070bcbd5d9f7d35e2cc043115596fe4ff44 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 b4b2164aafe421b591d0ed97105769998aa69a15..1462caab9045f32eefe57c116b54c93a32ae2a3a 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 d67b0f806f95b03439df742ed2f45533c574956e..9a1349d40ead0b3bd3c120152a37ae1d139c71af 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 7c7d984f3b79ecce261318c64713e3a1893f031d..f4af89a28e00f7084655830b0fc9ddd319ff100a 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 2dfe944c8fa9f16cb0d10bb5c6d4dd41fdae6b38..2fadac9bb2b4bd271c503e7ca357962d191bdcb7 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 3acc1c1dc6bafe1f283666aa8199df0ef6c3a542..edb583bd52c6db59f7cffac4157951e22d723bd5 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 06468d77ddfe167ca9def9892d7080e47e809b7e..a45c1735d22a608bd114410ba53335b5e9c115c0 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 79e51e7c01735a9ea375817577b2ccaf37314143..7f441fbb523842ff636037b6f06387a5ee326283 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 5c326e4c2d92e8c2959ec70e94328ee7160b14a5..958040cc7966cf818e5c258545ab82e2f6af9862 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 eea2791c978553d2b1b2b26239419464586d1149..864edfa87312127a70a931fa51a2105e055b36ba 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 4f1315feb827575580384ccdb23b5d1d54d52d00..d7137e6ceafae95331cc0a84e9ffbb7b5107b1ab 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 9a53bff679bffaa1a5611adf2234df5c7b5bb1e9..72faafccf93e45c75216f4691924939445fa3b18 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 f27938858044de1029f53924e5543e299022f0e0..52ef590eaf95e2740b81c3e144235a82bae134ee 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 efa64ab429b492119f3fb04d08eba4b654f058ae..ae41d4f7a3df7384a4f831f8f5d814f45456c53d 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 05f08ef6f7873b61ea2b67c171897a5ef9ca1d39..10e84f4a555a01cefe1fe5c68692e165b080dba7 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 305f615f8d8b7f32b1ca866f1c30eb338e5dc84f..51c1d1a5af24b902461b94c60266a2a9bedb2367 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 640fe8e0d9bb209467737b9c2b1b2d678284b76e..b58bdb21409ad7322a083f02043a12055cf0b54e 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 af578c52e898ac633acdd68863b2726ff5c9a3a7..71f49b481b7dccf46c51740296dd6aa4ddb26355 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 b9d0b4963d5bfc14eec85e2b89e27196d41eef38..6e02ef9f42127a0d22b96c5d2bba6e5d58e953cb 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 31c9f77792ccaadc2d1fea2355169db402e16b7a..735e11711642b59cdd50de2f1859814c3d2531a4 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 58cea1eabbb9733ea7079a37e2e730ac98ccc913..0d32b25b25711251d6076e351616ad621ffb17f7 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 e76d5677a092bfa1e667bc68633ca70acab02fbc..3c9d7c3ba2fcaca2ea830172a1678a4cb6e340b6 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 2a75ac8c845870fac344c4df4e74fad9dd0dea5e..5ac0df5b5d435740863898df5b59da5b22e63405 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 9ca1580dd9fba2a85df878a97183f7db8184cf6e..aa532dc31bef896f08c8beb274b9e17e6409f7d4 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 abfadac6a9b14ba80d794e6ab84c069ec4383480..d0c674ce94871f7e5e28d973a47fe603b7ff0ba5 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 2a91688a964a5ae65d038d15d8a4235540067040..12446a76c1b731c926f274b7c16f43f66b478a27 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 9b63d3275a6aeae552a132e2180ad7a2902ceaae..d43153ceef8f5b7a1295e296f89b343a6c0fd6d6 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 3fa19e2e24487b05707e91d2f7a5ac6fa4af98c3..92fd1eb18e81ae47563e51954b82a2b29707005f 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 b4be8bcb9070453b9d755788bfdbf9e6379bab9a..32d2b816b87316b604aa0eafebd7198a3b9ca1f8 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 3d0b5b57ba1888289476aa6ba3774211ffeddeea..ca60c98492e83202d2adb64ad48cae106690bb2f 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 08907e4a1568e9d5c7dc111c8173867cdba340fb..782e58d65df6c744811d930560979d59d32fa25d 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 3fa5f822f8473e0d6efc28cd036f3fa2bf85ffdb..a78dd707ad330df9faee4853bee3dd394178e4e7 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 084eb711ef7ae6b25fb58bf9d12d716d0d2d9e4d..0943e2247af9e0d6606eb40f193568cc9f5cdd24 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 682d19fdbd727470f59b9627e194890cb524ea9f..8513cda5527de9b2a3884e3a94cc38b4e6ffb079 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 a39604a38e2586388631fabe54ab6247077b383c..1bed678386d56629e0431fc35ce89c80ab00810f 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 ac4d92fd8005bfd858cb220729188aec05ef028c..2a112a2d7b4cb69b49e3047b5af2515644f9974d 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 28e8876e595ede6649fd532f032ff46b801c77d2..59d12456a96125fedd2ea260cb05a280d2424354 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 a556a53ffac5125cbb2b11aabe023de70106892a..22cfd0832f8a60443c4528cfe18979b24fdaf4e0 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 2635604c81aff2a766dba428a7980edd7396cf3c..9fbc97ce1110e7ee4b37b88ce6625152a8087859 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 a49d6afdc76853d9c928a1c4f0efdde5861e35ca..c19a7d0074ed2dbfcfb9efc780b8f665e08cfb80 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 19768d6dfff216cb5552f5c5dd07c5660e9706f2..5dd355a3eb72df7f63769385a8b818aa290d7d9a 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 c80e149771cf379cbb47f0f745ef05ff435dc7d1..4d20d19d5ea45e0b729111ffda6d5ab8d2a2d685 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 b9610a95a38d8c4f04800a93f15d9acbd2dc93fb..dfb090f3b8ce785a1a0e50700994f1970bf932ff 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 5273fc2877fbf180c0e2603fa92febc5e306d454..b841ae7e89b66dcf005c9e2504bbfd7e64b55478 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 7ba12b0ceb637e8a4906c4ffa2142ec156a840f6..7c49a78f021579741c3104c2c0c9e2912a9a5f53 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 a950f85ef47e0376365e7f7a55d9704bd56eb68f..e5b1dd82c4c4224959b4e1973df3a4578c269212 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 0f4a78a7148d0296af8d9bf9e88e585c19aaa532..361f24f841dab4075b2c15c77499222ebf3fcea4 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 4aaeefaef70d950615aee49a99f1a1e5ac81ea98..f5c836940d8f8598fb623721f0f0be6ad2ed3700 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 a7865eef094c753829160c93fdd5e5fe965997d5..39a32f42930c2bf618962bce700f03c3adb2f573 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 437a4de2229e63467bc0939f46e5c38c9ea5e439..dd4ebd420021ae0939ad57ead93762bd597f46b1 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 681de03b4d2281ae14a2e0e2767e40e69aa7c649..ba0d0467fe2e0508278b66ddae4bb40db7537d55 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 9c264761c88965e5bc50b5d1bd28fff8671e0626..e62b794c3e3a4a5b63822d60a478d24f8986bad7 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 edf394f3d60c7bb4ac528d3d327445fe73d5f215..d037d67318320c99f31bed6ecfb4790e834afda2 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 7c817f7f31c4ff3864ed77e4d55310b7b6a794b4..da4f5ace8e4a2f77c2335b545a984a62a8effaf7 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 4f2c5a2e9f6d6cf08c88edecb5f78eca00024714..9b125e5f086269d7fb0f5fbc89795df21a7edf64 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 e833c6d2794bec4bea91c4890e1c6be812ac1b0c..0efc61f610c2cbf9295ad77d97640475d5534950 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 8dbf8402b1330ec8a6f4a37f3bd1d9fe9f81254e..2332fe9fbbbe8ea2129e5bb31e4db30d0c2d9401 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 dcfd80f45e786e89c5c073c8ab325c13758f461c..6df721c36bcc481a9b275b353cea43cd22fe0ead 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 19544846f9fd11560b48ac33591d0c1e14f01b90..474dee6469c12963e61ea3ea9d9db6c8174df4bc 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 9f437821475ab716f89c1ebff712929e32588729..01b8c890d1cc188f6157c45194a0890eb5e47794 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 35eb783a3fd7b3b92fec577b8188f511ad28443e..3bd1b84b20581c4225881c19ce6f8dae072f5548 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 08aa180f2837ee474689cb034e520b28e6ec3f83..ed5ca7b999bea02bce05fb5e4d605d62c721048d 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 d9574f831f8db030cc7b07ca524fe9e78b83a97e..518b3520d70a014075080ca2db88c6d524008b30 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 43f5c3cc6a6d55194a1c44c4959ec2287824c859..dfd58f2ac99121e96917e42322f4322e15000a83 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 8b89542dbe82e6add56ec9653a58a15a9de35d3c..c02222660ac2e77dddba764d05c96dff2f3679bd 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 fb7b9b9c139b84a6676c4308f5a542d9d853fabd..66316fcbbcadca11155a2661e8780357f06727ad 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 a8cd7c063af81a4aef3ab672b51dccc6733831c8..45fed1f6a90a37c98933e802042405b366980b93 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 cc0df79840f872cea5d5084897397e247f406d81..1b5dad0d841c89e57cbb5af2e604b9d900f0871f 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 0000000000000000000000000000000000000000..4d4763777a3a1e31d3b15ee318cdc5069db34811 --- /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 54fd145c20fac3eda65732bfbb70a82b514786ef..2f100402640a6f94dc88ee88b620714b1ef93598 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 183f412df4be2c849224e34d22377c23c9d32727..639e08a65cba311185acd054c59816225b6630d2 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 417c7a2db1d3cd449cc1e032e6b43bfdaa63a538..deb49ed2832fd8f8304b3f39c1fdee18a660be4b 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 2295b71508af1f3ea0be3d03c9b47ed25cdc65f2..605633657d30218fc4f0f007ad99d2c959a5e257 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 a520bc02397f7d58a32df2870b8b13b65f295808..eaa237b370a4d44b4b883c75dd12e8dedf61a494 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 7133a3651ee41fe111e4f892de31e6ff8460516f..3264fd6ab23f92653a5bd4d95ede0731430602dc 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 ebfd9f77e044664531cb3f329e572cc09d7f8273..eeaacb898f49123aee825f03fdb343376373ea96 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 ca5727e62b6e2e3b24772052d891f17781f39d45..10ba642a406868cfdb9cab3af1e0a84710cfc2b8 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 297ae67b45b06871a55e52cde39eb6f24a49bc82..9912de01704b65f6b11336dff1c3130a8d49dce1 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 3141fe108bc70201b4db6dcd88aefefc2515b97f..4fa352135a480845e3de77fcb3c37a01034ae534 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 e97974c911976d462ac59d1e05bd97eb850d712e..59a70c4daad4654eeacd1c42595750609e395f0b 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 45aeb0a712602b1b31b50f721fd91d18d2e58aab..5ce1686dc2ab199efb8ed118bb9840ea91ff1f20 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 bd14b500540c2e53f96e41652ea6f4a8e87bfe55..f5108222806a9a0996a6091e6f8be27b61b60c14 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 a0687f6158346c5bee64ac497b3839baa1510eda..4b02ccb89817762a0e8e2c7231cae10324dbacda 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 dd4cbbe34befb663c0d05accf8425023beee9f67..fb13285c781b0aff12419005b077b643ab927769 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 d559f2a96cba1bc1c8213c77d4d47c7cf286645b..aad8eeb98d15b0da6c2b1bb42f279e7c055e8a3c 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 3bebca4088bb964f51db03f1001ca91b7edecdbf..6bdc2aaa60caf2dc5d9c634b745cb2714c21ec8e 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 e76f9b67c4aa0b9ae71cd8066c31d860d5519d38..09784dc11151a8f055b51c5c022d0e81518658cb 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 e9154f7e413e471ec81a54bca90540dd5eb2bbe6..7d355ad78ce00bd83a9214d41bb8f0b7e238d7b3 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 f2aaf21ade45cb30ce25c72476751546fdd2448c..c66f3122a1cc9bea6c96e86a81a8cca228b0fbc5 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 cd5184c7608d463b43e7df5afa244f8f8ad8420f..a90ea9c6eaea10e1b2f0f0989ef40dfdcd76eecb 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 0c04f1d2d8b7f63e6ea3714c3c032bc0832696e3..ae3175e90696739e10c8eb0bf717f435c24907a9 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 cb53e4a007980e3d7dbb7f6cfed7126b63ebf1a6..573d73c1a460f913d4f36ee98515031dccfcb24b 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 3f7f2b1364c78c23c2a4436aba3dcdb3b0a4d64e..b5bd7281040591a941b1386aba77c255d3b769dc 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 396ad8c2f7626972939dc089b361e91218bed0c4..98e41dbef99c07b51bf0af4de5cdc916c6032d77 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 bed4c2e260ccba4e9b16761b5812ac2ad4fa1ce6..a0f02831467de8ef8f96eafb24cc22cdf8e7b691 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 9923eb354a4ebf6f6b0db2c2e0785ecf4581b4a3..2415b32f5a5036c4c0fc961fafee502af361f84c 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 ac596852883f599505f7d99f2aeefbe29d544d7d..5a168b6e138f67ab1eaa14a4a597a8f2f9d30016 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 d211ebb9ab5b5c459b1f5ef9e53f2c8c2c1c34fc..2a577c888cef0f4f388881d2b3ee6c47ca53fce7 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 8a9dd6541b7d09829dca09d8579607d6548eb0b6..f5c6d2174bd4f19d44ab40b25fb51e850f5d8ce6 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 24f618b495d143971ea17e54e7f57f6586eba473..99a2a806fb15f1c68e0475534975a9ca41deb6f2 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 da837bb9105ae3d4218e2edbdbb0d92fc9d73733..e216a7af2160318a333f3b6c86fd4445bcc3f0ce 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 427a5af854bd43986e462c6d494d545849e43954..08997c6d0a9ac9e995522354d5dec3bdda9dbf22 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 6298c4753921f099b022b83a7e7326790a6ff627..c569a3da74068b3bd77aa53c8747db0a61c1f7ce 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 26a397fa2751994576a111bed750542e75545d21..00e8def810c1f78f11efd2facc2b5a288a894e62 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 4e23891e037a5e48fcf8628e25a64f5a1fb39e84..35cc0959ca7bdd422e5dea97106eaa10a8714feb 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 4146a1fe26cef74a1372b9ab3200cad36188d457..02181ee55b84d26fe87d273ea1c3128c4929c5e8 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 020953a1fafa70a3235554a2632c4ace69daed69..018b08a6793138f11cfaf189fc710b12af0ce406 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 1ebd39ae42db4f56a4b5ccef3f1b3c98e008bcb5..cfd134f6d07e73ca01fcc2b2bb98db2dca049522 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 3a3c0e383556299f0d72f2256d08b9088aa2577a..982bf386ff1aa68dd1f8903a6fde16bc4b148d37 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 9149c10229f9f65e5de003327e508dc54bae0d12..57af6bd0a1135ea7f096cacdd2b8e6d01f8b475f 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 75d4f28cb15b614057f5df36a3c158a3930b190d..9e035fab261432b36e0f36699302bc6810500228 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 db39bd6b9e9cff6ec7254917106684433c726362..873f4b8292a1b87e09a09d05bb93f268d051ecdd 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 b585b96454e38204454cc9891b0ea3c2fe8f481d..4a4aebd011eab4e4814d7ea65566119d0eff2233 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 076f21c49e7d9d7e871cb52f449ff1f336a5f7e8..dbec165c5d5fb43ae91775e1cdacec3ad89317ae 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 83b8911530df46d8a885923c0713d0b58be93451..568a31ad995cd70748c61234f2dc7b1865de801d 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 78224797290909b953dc9094ad3adcb977987f25..ac71f0b5037fe0d38d7229ddb25d7b04378c0aa6 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 1e478b6c2538bd9e7612b317c2b3afa994ac2cdf..359146c4a496de41615113ca5bff11bfc0ba1e07 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 97335b2e2a99d31b5311071e10bf8efe27e8f3a1..1541236f46d1fc0308e6f340f044f8de3ce5791e 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 af8180de96b5f00ad0f773103f2a6d894ca23a43..1406fbde427152973dbdb637b83b3fde3108137e 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 8d7691d9b9c19f32f14b871b8590fd515f49ed33..1142f5ab767e863e13d94d5b794fecdd0cfda9f3 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 c4a6646d00cadda03f2bba32845a0e7ecf0ae66b..bcb6e000c8228de062c84072493fa8705c3c723d 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 ea5b84bc7228bd98c2ed375477d6a2741a497c49..7bcbb9a96617aedb78ba82dd191117ebc7df43f8 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 dd4ba592148fb133fddad2a007585dbec262aec9..d6248acc436396373ded1fef09f26a11cde8e67c 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 845b3bd7b03cafc049d451688504198623036952..40e002857d4e991ba03c42efdd7ed4897df74694 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 25d2e4daab7efe11e17aa007da02e5596be27e3c..131b65cf1fc7dd740f3fc23f614d0f88fcc6d641 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 fe37fb8cf8fa0f6e0c1e0cbac87dd4995c3d1043..0553d5857163f9a20a76233d710979324bf45953 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 a4fac09b54cf526a42787042f18921110ec84ab7..4b351378c3024f1dc7952cb8c71ab2762b475e29 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 e14199be66a79881eaaf5ffc6bc1e539f243808e..5e913d4523a2ba66e43b58d07ad9c2d88e290978 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 96a0110d6f151aefa5c70414780dfdd28b5c1e5e..c5b1d4c13edd7892449c5d73a0e94dce94fda1a6 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 6a9201b5b6903d7dcf44c11ca81ee367baf92eff..8349d780bd2ec39c5a0a708cc7afd0e88562e38c 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 63876883430f3d4b87e513ffbc6c262d2a456032..6c3b743d4f5bab2c2067efad1a5e121ce244ecec 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 c0e43a04355eb89d888de49feda686ba4a248dd0..fe23b7bc233b3bc6e23b32374bf918a69639de83 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 790284387684bfd19f9f93de3d868e1cbe76b1ae..501a67bf8ba5fd100c9879a65fd1a152f4cbe0d7 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 339d862d42c330fac0d4504460aa304f1441abcf..6a65ab76188fc0c0463cd62346b3a6ba94f1dade 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 51f74df0b4a0aed99b713365c3fdc3ce2ab10124..d49dc3480115f7e8cba724af67a05497c720d803 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 dd7e7ffb14e4e01b09ac36838916889aaebfe949..219332fb1d1f5613742a88860efb33900ff05270 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 754af509de665b58d1a80fe1e89280b314088b4c..9d4e267faf2410325e31eeba641330fe21fcd76b 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 589c990b74d8a9360d295db9a7a59b21ab9c142b..b7055cb6a1d2e19f36758ec2d93dc2a58d64976b 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 7f393683b8b900eb1099c5fff90c265cc4166789..c1100893423561a5d9f86434db1fd242aedf2d24 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 ab656d147488ecd9aaf6faf3bd93d05a22d872da..1396ac37b27cc53115b6ed50fc0d13f54ce8537d 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 03a651219a490b164839878479fc94b7a54efabc..8a8c16800f01c4652e1ef9ead342dc1da42f5533 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 4e0e95f04d01abdf9b2c6f350afcd68171adee0e..8df13c91d2abe2752c3151d8eac4d29381be81ba 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 fd98a5b3db77d28f9062dd14753fe03a06fc7989..fa06b59566e6ff893367545572c651bddb44fd99 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 501bfc85cd1c17ea7a6b9b119013a305b0c138bc..c519ab9f7958a58769d23029484d165f380b99cd 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 d5ca5a28bdf748ed75319e4b1946bbad5a1b3057..fbaa1e36b0a5a7e50a63f65bf59988f378da95e2 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 a277cb87f9b49350fd2fe527b08077aa6a86184d..8cf89a37a51f2480b3fc5afd0cf124ab9b1744d2 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 83ea065e3e5003d8e83b0ffa5592fbb9f8fbff9d..3195b0faecbf64f1a730b1920eb7a3bdaedd967e 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 9f5622710e4cbec5bf832d6324582f94280ee100..3b164614a8bd892a21d23b595decb880158c21c1 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 ff783a6e6c68dec2c8ba0dac1dc7527643f89736..1aaf5542f1382d19345d68e65f136a86a8b28ab9 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 f169f9c8b8ae4bf268d73e7d015bbe582045be1e..835d09283e56f22165794b3fd9f930a714da2dae 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 45052bca42de64110607af699b64ede6fefd8c94..69b1d50a03b7e99fd302d42b662513d98eb40eb2 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 2a10f06d355e83d61cc2e4dd49ae6b7fa42bcee1..c17657f8301822aceb4ffe4cb0093ef581d4ce9a 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 cfc5cc7288904819d96711d71a7ed0125a11fb01..052a7372ac31c8a174c5fd1cd1ed6172af6deb9a 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 5b9749964a5a42d5b565af7eebe19cce56b7a966..3f7bab6e53baec80acd2440a21bf2ba320b897db 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 df42a68e7c24d89db0e60f72402cec9ae953f8c5..1396b7fe8f1612ffb0c2dd27569c2be7184aed1e 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 fd4d1660163a22024ad8532b50cb09ddcbfe229b..13f3c4400286fedb9cbd85850fa2bc78c1f5fe7b 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 89ec85c47804f6be585ee05fdf5956fad818142b..01a91ff5b7e5366eed1620e31bf6df07e1f061a3 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 9d9572005a042fc32614e6e603fbb2160c3d27b7..de60b570c874ab4d53bb79f5b8fe8b238261b676 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 c0cf91de651fec487b035efe197aa472bbd97b91..c19793ba3612e9923098326073f61f31008eda83 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 b376b22a7ad043552c3e445eaf0f1723d07057b3..b26e7c8d5ddb6e22993336b86ad20330fff36a89 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 0caf2d1445922c126ca870c2694a5c4edbdfcafc..03b019cbf4eb53e1c7ff363ad65907f986c9e87e 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 b1a131b78689ac43366c820bb805451d37068851..250840c5f327523e1b82620b0b5c88e70bd3d7cf 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 6c01e02dfa58812f969fb82ddb9dc5f1fccff6af..325edfc77f9cea3188e27230d0c31c9952352ee1 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 426590e0e43bf4dcd8643d8ea6693ac2a89c8833..ab3484f679d6f6d2a5cf71009509ca3be2985720 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 55c3f8f1d2441caacced3f493b92a0ef78784cfd..7dd7fce80f2a7c0fa358666514b72b7270c7c26a 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 5c694a334a33d15b840a534b303a77edbefa641a..fb6f2e72c59e1c9a4fa1ba35de6e9c6c18622c56 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 90372068dc4af6887e683acee79e21711e602e61..990cc96b5597e791640df71e1cf8073208d63a5e 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 dd1603b37997e4ebd412bf738d501ad899054403..21436f18c31e5e674d1685ca281b027d7d579f92 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 732ef255c0be3e5307dbb93bfc7b1066603178e8..b8d7c852f4c88f70d8f35ade8e9a82c0f5261b8d 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 c3790e6370b01ec19b605af5332f6359592660cf..b306a15bb6864723bc3084de1152b989e2078987 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 a5851039a16242d9c68497b95ed012f97cddaeb3..91cde1a74ce315756e259b13b17f0969b8b3fd79 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 6b49c80f4966d5d47f44edab59059a42b9ab03c9..2b61091805e99fb33ffa3b46f21ddf2cb15c0ba9 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 245e4d3b31982c5542d40416d7c7ba52c632c238..0fad410f2fa3a3fd3dc280f054c99b33b1ff7f29 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 ab202aed68432aa8158ce2574a5c97b1592bc8e2..537775aaa998568e1ef4db3d566275367871efd8 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 56b4a60d4f39ac43b0e19880779081dde84eb375..e98442cecc6894a8c28f5ccae138e1038ae53176 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 5b46941797e7ec15e6f94df439544f37f86d4e08..6f3d42b652e41a97eaeef70885b84cf78306b66c 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 9497bc8542f753242f9094361acb7293d61c579f..b5ebd161462c7732473a415bbf3d271a294e1aaf 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 b47eafdf40ecedcc06d918e1778d1446451d3bb0..8ca3777a4509f47a6d067995dfdf61b56ac71282 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 f0e2ab753cd0c64146c1a08ebaaf445dc5e8584f..05c4ca9715af600f87e592348c79c3fa419ea22e 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 c416d8c2561462f4cb671e247b64539ee47215d6..6e6ef8ff028e1e131c3fd2e644332a2c6bc2ac9b 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 bfea1a2bfdce2221003ed0dfefbd1c6a0fe3ded7..a4fe5e9551547163af58edf98000ba66cd12305c 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 e016c14294711d52ba4389100b213cf527073474..75f0ef79e235628a715501a60bdbaef66912e9f8 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 6581b5fde536216bdeeb25a01b5e0ed7469000e1..02f62e1a5ea06823683bca93bddbad6247aa0765 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 dc15ae4f240a99a0f8b26d5ab64fcb9b34ff4715..92ec292899a914bfa2c29cc2555401623a6ab7db 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 c49823d5bcafe7a8e8439c40d875ee0c00a227c3..cc2c6e4eb7b880fee514d161ac41e10825f60605 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 3364b92ce0ecaf21db1aa140ca49945dee5ec7ab..f2daac99b2066425df241b907af8f19130cc6540 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 6cfeaf88ff671533e1b43c8964ae50c7cc4a48b1..6fda1e36b383484179c1ea3225c400349d162433 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 82d2cf42841eb45d871ae21748715eaefdf77902..adee7c79ce6bf6703eb0046d39ec46581acc566b 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 3de0c786979744e8088e52a6c368b6e81375b928..39a716e566cdd8d20ff0a5efd3d7c28c205d0356 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 9b0038da9d32f739f682100d63e49e8397c2f4be..88583b489c2a98cde87cb211f2b6bf654d5507cc 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 20ef59e4697b370dc94d9cf3759b663a42f9e64f..a09dfac3999f49379079c5fb89ee735a473b8f1b 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 b2a08fe40109fa86f7213317ee1e382e0bc2f612..f8ac7596ba7eb284a07d30e65dee78c25fe271b6 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 09200e1eea75478567569113f01dd3211ae928de..e18325f63d8640b277e087cf387a105f0bf9d54b 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 86cce3e0a18e0dbf00edf6922b2bcf8e39388780..0304da72d1b2a936da32f3478cdf91f663d7fed8 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 6db4bb9c255b151dad3ed02c8e8785261e99cc8d..305d8cc7ec2a37c7716597a462f2554dc389575d 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 698a698da03ee6aaa40f600121f3c090e38c0352..d86d601fc90b78a0efd616b983c90ef908da1427 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 c96c3e9d33970e23a508cf48e50270c6991622f6..decb89ddafd05a29a0fc073655de8d3e7fd774df 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 ded161bb6fd5f06e3b77ef06b79b6566e2aee8d4..c04e28a635d6b8050f2a7aa869521847b32b92b0 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 90e65f2df286d1a67d6f951016d2dcdb106ee790..5ba14b21a2871cf62630050df36c128674e88e18 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 9a3765575d8ce76a19afb38968d85485dc1251df..a2acc221b7ba8a8425462bed8a53c5c27a66da96 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 a1a1bb3183b19c79dd20f78c5a1c33ed05ac23b7..542541aed5da7b196628d0c01643ae5f895d60d9 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 a0b0dc5377bef2a65fa47ecb42f15601a4da8ab6..3f5696463b07c693ea243cd149c3de1befd2452e 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 3a8b9bb0364ebd75c11ad1a0004c18b985a456b7..00bdd9e79f94ceeed8df4b10f64a8eae1020bcb0 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 012c27c1a75ddc30e15e18dc1d03ac3b3813e5b2..5c7e2bd7e3269de5f5b59ca2be47eea99da6ff2c 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 ef20a55631baf3ec2c02236e437937ca5d9d9a86..79de5b709d42e283ba8d32b00813155b1723059f 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 8f0903dea8112912e3aac1de3dd290816e1d7f01..aa0122dba68e655a1fe666418225f0241d80a8bc 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 1b4e6250f87d0a5821a48d119e14b3a5f0088007..8451653d2c735af758c04f7cd3795c5f1e4df91b 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 c0292526f8816afb53ad44d01aef25b006edf88d..b7c7f8c9cd67f338ad51e903c95e0b036e011909 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 0d34233ccfc53cb72f32643ca6b2a4a3f4fb77a0..b65ea7767b85681500570fef674623a664422030 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 ebc8cecd78d29cd509611277e395c24c2d8f15e6..c86a04df0c5e994761df343b326f1057af831f9c 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 e01c559c6b3deaf3e8947a6a5c522eea08254315..0b7b9f1472f3e73f7286521ba0628ca5dc8fc2e1 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 be064bcc0d33944ccd9eba2980b0f27ebf65ffa5..a895d58e09d688f1764eb86b8bf493b42df40134 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 e29bb655797187d4be07ae2ebf9de10c8d81f2d5..267eb4fb7ead28b1683996c6fb6bdb97309a4b0b 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 1c64d810e1460077d5bdd01d1243ee35a8998407..505c2da01aa17a88e3c3a25123d1c2ff2b8277bf 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 852f563a8fb6f259813a4c2be2092592216c29fc..d8dfd1470d81cec19b3c4788bacdeb3f2e5fb161 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 0032a84d485b5e2ef654145f78ea5f2bd76e7c5a..7e00873f2e74c229282177d317aa3abe0bfd09b5 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 5f0b02f3703479eea8cb7f1a101e6ebe32a13e74..2cb4cf41f2a15c91d6bcdaba72143735cb0baeb3 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 39779e1234a8d3914e1a5b5945f4e49c259aebf4..b8e787efe2d484826c3fa70326c2eee5f4bfbfe4 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 156edf1eca5b7b72d31ee4b658ec3ffbefb08c40..89739329db1a966fa9e95479768584a3452e25ba 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 fcc01a11e74fd9e9533b805b22f725df8a215e21..44b4afe5f0e80423af02fca08c7edd167bbb1865 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 3655f7ee713dd724cbeb565409226075dd2f3449..c220658960d26771d2968bd81641ac91ecb9efee 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 dbe2e7618958cee8a7e73b201a85b8896801f829..5b5487ca776b7a004b948ce6a56767d77b576fe3 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 fb2784f6b3688fc45a2dd9684ff8d9f0d08a1281..7ede90f975a4909053e64e63bf3afb6de0bdaeec 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 e21977b61cfa22cc0b43ddd84bd08e8154866121..6e857657b6e80434be17e0b6aea2896f9e2fb0bf 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 e8cb8b294edb1eb43c065ad063b60403d0e83be0..be1f42228da4d13c066b8e325bdb05c04d06589c 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 f4eb2c570867460cadc66c279dbf52aade15d2af..7014bd2edafefcaaa8a5426eaff0446d50eef71a 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 0000000000000000000000000000000000000000..5a182247c61b888871518ab0cb9a2f136592a9ec --- /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 809f83cb2bedc9092283bcf0cc5892c78006c852..710510448819f515c2874b2049bd7e5b3b802333 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 747570525a36d56f572cfbd8f359428410af4db2..44c6725f40665c38efd527663187770bc2e68670 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 f961f15d20598074e6ea2e8c3509ae55b4d42040..dc731f06764f5e8c0c2692128b4ad54c74848999 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 678dc7a542338f4795bca94d91e9c50e5c52f002..18993c8d022c6a2d8a74025b27e3cdca5b0ad859 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 41c41dd59b7bd5b710670f698e4f927c12d252e7..895bd536b1b4040bbc984f878a33be55bda876cd 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 e7fe3760e57c8a2dea96cf28733490b67bb154ba..1fc72279c01dbac6d2316143bfb76bbff567b2ca 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 0000000000000000000000000000000000000000..2e878d40c4cdaac99aed41d82acc2638a54b0260 --- /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 463a56ed4ebc20691c03edb8916aa3225576a843..2969ec5603bce61a6865c17d8b2854c776cbca4e 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 18b13c44c7bd929407b61431e1e1ec337eed8d43..333afdd2eccb502cd6de7fa13bc2e393623f5b69 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 4ecf240ad021d5ee0e398b17e46b92bba74689c6..3b78bcc0b76316e57bfb926f75d26088512f83c8 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 80f0ffeb91f72df643058e783809737e870cbcb4..173137b37de271631501c95c724ae840ca165480 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 a201103f4c2f0c87a25a5fa00f53f5872bce9919..330213dedded0b4ce41303e604a38022884f24ce 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 7c89bb3b3ee758b1555afc46881ff90cc8e46d24..05f873cd83c32ac66ce6fb87ee6517e8ab8dd619 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 6c0c396b79f18aae77b42f8b388fada93275db5f..37defca3ac4800e044f8c1b6c0fae3c723de86f2 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 f8be9304e8aa94f2104ef6e7b65918e2fbf6400a..dfdd82c5f173532283cd5654f6dc82fa7b3b6328 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 a1ca5d7bd1ad1127c63469ad91aff024444d5e7c..dbeab47fca43eb7fc26aed4ea222ebb35e6595fc 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 74227bded0d067541f90afcea8de1e6e5e0e1e28..7f917e248b744a73b7754d1870eb3ce017b4b661 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 d422d6b4d6154f2220d6a88b67c3b941a1f5145e..557689e7539ee722beccf39f1ca0fd64010d38f2 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 6543e85e7ae33f8c9ef51d75fb1438b5d134cf65..6c658b177409c6285f365a6c2568427f29756dc9 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 a08f574e3a304803b6cecb0773bf934a8404972f..1eb9a131e0dda809866af6d5f47034b064a5d85a 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 feabe6187e160a162491df8c316918776bcf71e7..6f5934564ebc3f48c3105f95b8ec7a66d97b3151 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 30052e427c8b76a77047966235c04e6f06c5d72b..0fe6f780d782aa281a354f7175bcc44f61edddc6 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 5d347518d9a837742e6ad4378aae3da7ff04ea4c..5e94a16dfa92f19bcfc9153bcbcfcfdc1f5a586d 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 cc4ebb227b5f7e0c9255a5793e9349a4109af08b..9fcd885f7a1a5c9a030ea1d3086766dfd56310b6 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 bf42eb2c92b555c0bd3935871c186d4f51b8c9a7..27d04e81b45e21ad906cf19eb50732fc4e240f81 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 0c0fcdd42c5d94d5b94a8d80cef0f9326701c3df..1c5e586f31ae8b6451f1fd58bce008c04c237d6e 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 b31f2a16406d4e7d3edc4c35bdbfc5553e11cbe4..0334d7a17bb95e2ab3fa91d61a8358d5392992ac 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 a610e0c843f27305bbc55ffb5940f9cfea95d2a0..68110693249992bfb7f973644eeef5d19069967e 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 246cc45f9aff08aa2252f4c67d28fe0bddf4ff9c..bf55de5f9daf72bb94b1dec5295b027322649a32 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 6f0ded11deae148705b89748c24633eef945319c..806db4a08a9f3037a0d2a3d516c37bc6820adc2d 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 502d45ca31d07595c1a4867c0d3bf0452e2f08fa..6a30c0892c60176990dc979c719c8dd9619ff352 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 85d31473c1c73ea9fcc28fb14e23ee93690522fc..01d7e7c0e50d5fd94ad6e208f0bffb6d938c942a 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 45ee43a0acab8b3aa4b663cc570cd422e2a436da..10cb9a44039a5c3b6d9b84fa0b30127a4d133476 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 c36a3d5925e0a0a01691ae5bc71ea0860239359f..bfdba6105820c3eac30792bda4cce5d97b56dc8d 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 cc88242eefd26be3419c5cc60b058bd38bc4bcbc..08d6d45598796d06d19c0a4f00a3452f136971de 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 da929d6bd048a66383b3bb4497c80cfb05bffe40..80598c0d2430326940b2d19c2bc327b08db60845 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 0c71b3141a17b332047bb6224b1af9925ec2f0d8..c6cb5fbfd33cc81c7332b1c1c1a06f5965544c63 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 c4277878d63c40cb4d8b765d98a531f682e6ed7d..b48b4294efc97f0f700cd93711e6ea3ff8a5b3f4 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 8b5ea940408222dc1b14a30debb38112fafd6a3b..f59db45e1037c40f0768a478f8cb3e8eaee1a817 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 aa061bcf30ca529310b8ee49b20d923cf459a858..7525682faf61b51afd9ba1a27f3e4ed2c8657f39 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 e5920cdd5adfd8259aa3538ef7d184a3dcea056f..b6e6aabce182a630b3da3c7d583f0e8b82323539 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 238862cead8ff42c26ce179d81bdee527a604dd8..74f96c89456fc92842554eb8a2f9a81073144890 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 2c122da08bf5d68816e7354e31063e96ab1a82c8..12470fdde0e26ccc725489b062192d733145d29e 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 463ad70b59b40ea507fd32a87c7792605c4a1e02..05902f961234c9077946260a84637bfdafa76c70 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 6cbeb6875530881172ca081816b663dd48e84639..89cfe2bc507160c4e4d58204a47284c77f90753b 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 af19827c9dc91707af2a4fd6fef0917fc037319f..3f9671ffa759ac5252e0d09d4a843249ccd4becd 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 e31fabcbd1fbaeaf3f5d21fc3734efe43165abfb..e6c4314daef8562076318709cfc5ebda1a9e5b07 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 dcca88199eabd977fe0409906bd472f3e0012b4f..ad4b5994f3df7d9cd6ecf24ce6c5f9632d616bef 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 7d70eb0d141aa45ce2939cbf8bf99fe2387299dc..4d78de55be505685e2c013b0aa6f3b64ee235ae3 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 030432ac470dbb5fa7c687ad2cb94df90b6483da..e9070a8e9653fae9b5c9f3f915731c5cf96a4f31 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 56ce0620155e019c332508e4b781568cc2061e25..b5e62e6c5eab693a9b12560cd47fb2224edfa8d2 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 fc528ce648ee38ebc2909485d3d04ecd52ec9dc9..c1ae7018d213f88b42d93d3cbdb553cd2141b446 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 cea65bd28c4109f5f1b37de8000fdc9076bc1197..f9008156ff99cb8872a529460251e5bcc32373ed 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 284dd0b8d75f3cadfd00e7d5a844491839c9e03a..0082839b0be1e2a8becb4420b29b5cf6f0d5bbe7 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 20ae3fd0cb5898c37fbf14f237e8213c7549251c..0f51a1c1bd04d0a3f00cfd5af8c9804228929ebd 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 61f8a28695c692b8529045ecd75c474bcb120403..8531ba908d30bc5da683c22952a8272c37e7a382 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 f8a88155df5db8d1c76bfa4fc1ddbc8f7fb5ef0e..871a009e540e1be6e48deb24467045d62a9bc56d 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 1953436c40cb903d29fbfe82457f7f40d53e11bc..bf5a4ef9b1d0878cc385dd00153f61b8c27d3402 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 de7e83c17971ba0fa7289125f98606b72b7d6908..26b01c3dc21113c9af044e6d1a9d253ff01fea3e 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 5610b6e37196829a1db6733b029cc9bce2d5c5d3..728f9c5c993ba9e33477d3296ebeb4e87b2aac2f 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 4262af22ecccbabe26826f39bc032a3b873f777f..4dc45a5797056d941ec39b131593b585bc590690 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 6ec69a678f7de71eec8cfa1a3816804bee683f3e..782eb56ee0d9658f70ee42e52a6bb9b61de48b9d 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 28dad93968664c700ebd865ecea162933bd67e26..8d18b56928830168f377bee7fcf5307184ed4ded 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 e45d7775e1f929b1278aa9796b6b1ce2bc8a7f20..64924d71e499005e4f2fdc37015bac65a0a0c297 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 0000000000000000000000000000000000000000..fafafa26534397ef006fbabd9cd96415e11684d9 --- /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 5e2feb342dcfd4dc369b62ab3501a71feb2abda0..0ed5289117ebc9cd7ad3d9738e177f1dcf98e32f 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 caa6c90845fef929875d609b3bc6d8e89ec6e55b..93129ee6a77a55aa62b7a4c258e8d4aeeb1e134a 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 ac3633004cd16a47e89aecd43bc99e69ed802765..f104502a00214b4f96b4f25ac1560f970ca93472 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 8cce274a6c8cad5177e3c83e02908cd35907a21e..b37d6371cee03f0a2d71c18e682983a2e4280592 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 a50454701701724f40f97976e57ebc681ddb07c5..e803c8daba362236ed54d2e1858cd64680cded1c 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 0000000000000000000000000000000000000000..ba0ab8c6092dd4990e35913fef190318a7bbbd48 --- /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 98e7385ba838390c8cdd2c59feee28630c3bbea2..1f057ecfe8584ccbea1508e939fe9e9c37b6e9f5 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 6a7a944eaa19580f550718b4f25dce6bc5fd7b98..8c9b7a944dc443b42e6ebd858423969d5d841441 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 0000000000000000000000000000000000000000..8a2f45510e1037bbd71d5d595fd56c1266daeccf --- /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 1c9682de7bf09607f9130c5a9fbd80331f6d0a9a..8a18c39ddf3c10b628c4b3dbebd9841210445133 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 228111a31c6b986331efbc74ac715510d615e601..683a70614a64904f1d341ba640b54bd5f11036c3 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 acc92136473606f05d8639341d84a15d4999e0b4..5fc4a52e9b95c4758e16425c8f64861be27c9873 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 1855f7fd6b782ba921d5212d8d5efc718c15485d..26a23e0c3399f8ae0f00b69973e138aa2eaf2a3f 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 ea1924918d494c0f199a62ffea1cf800c6b0a1f7..ecbca0cc14c98dc6fa77fd0fe091453bc4b010d3 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 f974710404c6dd442e1d7750fd7e873dacafd038..74db83d204c99529fef1d8396d4ca9632e476e22 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 9e189fe5e02f222ceb226861aa7723edb39fd51c..f66f277a8c3945a0bf403e8071026c89772b216d 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 222c024641ea64713b4a364708fa1cf3eea9daf6..c7d5eb1c75983753bfe39a175562966e48a54ee3 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 4ce234ab633eea8a05435c55be608f9d049d88fe..93e3f6552d0686a1096be8f642ad087e5eeab6d2 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 765be3d21e29692d5f26c7f607b2eeed9eda2343..b7b811943fe817cfd0b648b5a5a85155eeeb44d7 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 ebb8952da61c58d3e4df63354c2740547729db02..9028c0af37ab5d7979d2a3fb6097d2d6996b416f 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 bb4f11763780bed17ba7f890b023a1ebe0d4e93f..a74d362a3d0f6bc7a403ab9dd3e3fd9a4c120d58 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 da60d1917d3f357515b2630e216157a30509a2c7..e98b66283ea574b6f36fdd5bb96654a1144cd990 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 c49a4b88a4046e16ae794dd9cb1ab5ba9ed718e2..98a87853d3cc7bc9ad0c4d098698d7a5e9caa697 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 9eb038ee2f94e46e333242353910843570b769a8..bc3cfbf6e8dbdeeb3959fb54b1877ef6adf6b3b1 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 a3cd5aadfaba6d90551bca5baa5c3c56cdb5a890..a511cfe4debba7205e6407f7b445eda9021506e7 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 2a08b38646a1e5a548c0cf73f13d2a440f96da93..dabddc9ee715c40c247a5ba31fe3ae3d15963264 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 4f826e5af892a15bdbf007e86c3780f093cb716a..c3ab76c7a73a83a8c7b17303c28f20168b782ee8 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 199ec3641e4f8296c8e510689b82279b61716da8..05a5b8f22d43604269275ea33fd5322c2d7abdf9 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 ca18894aad0617cb15d621c1ac659779bbe12256..3f405a230bb2e0031706c7b8e520be0157bf9e76 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 53d4416e4602df9b5281917b6ff2b2c8c9d2ceb4..32f031551c86c4fd33c48213e20ac74b8a5c1f6a 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 a165a98855318ba756c0a8fef1c3928b9b417aaf..ab0225122ffb111809d940d2b34f37fef9c2b488 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 616e7a8f4e45aeef98807cf0036b2aa3c6e2c576..b9af364a1e9d38b21a14428ac87bba8bb2bcb77c 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 3f9e8bc72e7419087d8e35a0ff63908e9e45f523..6090889dd8f0d662c103df5effd4384dfaf49b5a 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 63feb9c380725471ac147282ab2e41c71b2e64ff..a1f76afa197d68d76d7b855be7af2390b397cc82 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 c464838966dbab0cbda73780dc5e17478c2947a9..ad55de84d8ab13f95322a9d843a206ee178fe1be 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 7a873c6b62a56f8fefc49558fd56e2c02a2eec6a..69037fcda1cd660dec9bf376a4f8afd0e91f7ba4 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 c6a86b8999acbef2e345f52243ae58f6f248d20c..ab321c3aca56ff97de49778d9d2af653c33bd5f7 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 175d686da59627cacd907bf604389f7bc5be0078..20ddd11dca2e1f54bcbbb5b8a4a1958f1b73b052 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 c3730913073ea350fd2f14e5ba70927b855edccf..eaf983faa4ad63b3de59f46e7e60a67a5b39b110 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 0000000000000000000000000000000000000000..3e95a1c5807ccf54006388c66f1042a6792ea2b7 --- /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 ad027297015440e58904afb5cdf2b4a25e9e66f8..264bb1b4b4e3027c55da3c79cb2f6c8280c5c03c 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 494ca7c7c2b39b5db18642fedabf5e7c1728d7a9..f15328a8608997d4674669552542c118600ad041 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 f7bd0fcf09924a46ca7cf4c3793dce919269568c..9ba569c55c46089161a7236bdc6e0ae79b9c9fdd 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 2ae53c445e8c8fa00d9cec559073cafc7865c8b4..38a4e9b471a49fbb38bc6c9e496b5c15441b1fa6 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 1f1739800ad433e02fc90922b787716546566727..475775be68ac65213bcd383e410ec26fb9c88448 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 cfbdbddf0b238f2d4d83165ac6aa501cede33433..4802f553b64c67d10b7bce5eccee61af7a2350b7 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 3be2b22ad061f7f500002f42daf1c8fd3e478aff..a70b1adcd28545bea3bfc0c182946d09bfe05cce 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 1619b335c9c2f7276553c1e6bce266301a762efd..88c69735a3b9afff844917bcf869441fa0ec36f7 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 e099af1af78523def65c368a298f5906b7fc8d09..271f42d64431fdead40f5873f57f50382bc1ee9c 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 2cc65f59eb947c64c6a9aff9cc371cadd2470cf9..3ca2a6c211c5b7c0abe15ef776002031379c6441 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 e8f8c0084bd9546372cfe9015ef70e68ec735a69..8f5ea7fa0d3bdcd36df316ebe1f328c10d5ea6b8 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 1fa64e7d166e55a8b00260fc8e7ab84eee51e4ed..1fe3ac7a990df243a3211e9b1010f6327b8e720a 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 bdb7316a32fa28c5899c2243843801620a2ae961..86c9dc5951eed39d919f476cc049803f1898623e 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 117c318cf80e64d2fee04a5e3be66ccff887488f..17a04c35e3441f76eb21d7205a5a3355f6fb6ec9 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 a45d84ce857c8fda6450168ecb5dca0b4bdb7e7b..2fb078b743359e59649392e00068fb14e20d9b44 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 6747ee1d520e06a4332a4c7e7b0d4c0d386fb2fd..8f5314fe6ebcc675317973ddb5e85d2e6bb87a4a 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 b1f9ff5b1a05d17b999a7e322b999909b657b5a6..158b79560b604d25d603f52d60b7f141ba5df030 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 29a04343c331e114e65fe6e690614b847bb06fd5..56131f81a07db5538ef7fb2284e8d6b9b39b68ec 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 6147ee0638c129942432c68824c57a05b8bb9287..3a830ecb350a2890116d907ffefef92180b4bd11 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 8a8e9ad9c018503acfabb280bbc101887fd57ebc..7bf4906fc412814c450eae4f99206ecc80a8bf68 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 2cf40b93b9dfe18a32caee461d445302722aacc3..95b0416b407a437755ba35f3728f45c597feb25c 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 6fad64a069bd9ea5a3b80b67f33ad6778548c395..978e406c5b3b87b6338557ed3640717e4c4118e6 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 fe2c5a85c83b0353fede0e136e0a3f24d7740e53..128a39bf8124d40b5071d0a2580209ecea45a4a6 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 e40a6727696f0478670e152b494d986244551d88..5f5f64c6a74b6f6080f22b809a118673e3baf829 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 0000000000000000000000000000000000000000..a30ced04a32c6d7040cea049bac3ec77513e4d5f --- /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 b6be64944e7d2aeb4b356e03fe05ff4c302f96bf..ae170e8dc0d3328ab80ccf5aa4c23f04e98103c8 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 e4682f004954dfb8f775c8a0f66549a0312c784a..cb546f15a192f91e1b01538fe14482fae6756fbe 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 0000000000000000000000000000000000000000..2437d9b7684edf3b41d6cc64af2a7b0ed9cddf17 --- /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 f38b45d54650cad04aae5b9cae24ab378c0d19db..fc23aaca37404cc0b72b0822d7ec8eb4617fd084 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 389a766fe34b6b6aa861f6d84c04bb0fa736e46d..f6c0a388c81981039d47b6e08151600099c051b5 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 fff72d4c48f71885e6f6cf50de4c99e05ad74a50..90af80f4d711237a9f205f755546a5812b34a91f 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 0352e3a439eefb9068104198ceab8ee0311409cc..b801b05b13febaaaa61b67a7ee215027e6f92fce 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 2cc7302884b23573d251c6f8d1d042122b04b90e..9ec9f8360fa9933b595858735f72e5ef676385b6 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 93e89c2a16302bf26c9711edbd2a9c4b6b7aa8f9..4fbb1f52a4d617819424bc8835835a45a0da0779 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 d22d5def7951c5acbbab8c7cbc584f825bd2626d..4af3b5efb82fecfe7a2523cd847a29167b3ce35e 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 e95c20739242c9b54a1371415d6b9140c1ff4fb9..a1befdd1d14485235917e3a2214b53d00d78ea05 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 2be5e608d8edf807a93ed1e13259319002e92f5a..1307cb023915badbbbe10f2d4fd3ab3036f0d2d3 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 491930512be45f12f8714fe081b6603a25bf5cf0..99481b742e813361ed516904448cef6d0a39aadc 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 2c429687969943f282502ad1fde361111cc2297b..56d1e4f5dcc775d9318c68720ac44091f24c147e 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 366fafd0268d8f014a96b08069cd98963bc83a66..9c8bf976bea865f2d0d518947519159afc4009a3 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 3bb179a3b7f8a134b1bff7dddebd13e9b7f81db2..16655921d575b792c2610af376a68ad6911fe5ed 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 0a0177c2f28ac1d1b2ad6864920acce83341aca6..b2a2c88dd5708e43cb48816acb64cbc4a84894ac 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 fe0a2920547b60c94843fea6e5b814fecfb4e4c1..984704c10b00ade8498be9c78a323e5dc32baf12 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 7812b50be50bfca909cbacdd139bfeb19621b34d..abbd2eada5a1cd356572b5cb00d77202a57028a7 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 fc290a66e5a1a33e8cd3acbbf335af413e2ac2df..90e515e03f0698241613f27b6c3476d90f0d9078 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 4d9425b37ef835db2521adf7ea58a106b140bb3c..f6ae1d50ca1a15215e5c10d7bbcd3d3ba1be73af 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 7b335d190903044a197234398019d31588ba1e94..dafa0a26e3fe2d9e5d9d7d55aaa9664e5d498bf5 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 3e798b02ac1675ae763bfc3717173900e22cad11..91177bb33b0279292b5d62f7822a5b5d5ed3f4fa 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 0b57bbeede0e752d695ae0abe741520f24f52c71..d42f8e9933d4c551b3d5a897b5bcb6ea6be8fe97 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 830d26dbe8b3bd2fadb7f14c1ce746a5dbd90a4d..f8b7c2aa1e51e3d07fec2003af0563a33f327774 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 aee7792693df434713510375fccdddeb30d37400..ccc84e28d136275c40dfe193c237a73c53b8962f 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 57c98d61720ab2abd8ff08f88526665c4699c412..9f8dcfed80c5b86545a9ff2d1d34a24f08163257 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 11ba2b09cb988f5cb834fbd2a32f9666c74870d5..316732cd610c1600ac2acaa6159813e8f729991f 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 9885617d4c8d1b4768fe819c8160de2fc3693ae0..99091f51fc766950ccdefa5cae030dbbe845f9ca 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 885bea597454b647cbd454a49cbe1c46d26306be..efcbecdc58687542ee8031eaf39b580b45cd724f 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 033e25f004f7fb09c67837e0b4f8c31d09e58a6a..7b534976d4add948876e10b2526d0468d097d88b 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 e60bf9e96a1a2afe4a23dd5e0f1aa4fca8c6751b..7a8e54911a4b76943301741f55c35bb75eb3cab2 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 9c8c27fbf2965672e3dd6dd20a86d43dafef5e43..2e64f879a87ef3a3a596940654474f4b3ac60b2b 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 8342f6bd8cc7ad40104d1f5d71670d707d8169ac..6274af5d1c06121462248985a23a83ce33b9666a 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 64022247b5840716d0b9b58628e88c898b06c66f..c2bc67e9cfb46fcd0808fdf81c31f5aa4401ca8a 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 f3555f4795f04dd668fad59714bdbfad563397f3..41cf2104997169f795913362812747680caa320e 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 2183e959b82402dbeddf2eabbe0406832aaf4aef..175785632192e188efc7da3b4c80965949e79e06 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 eebfff5f291b7d49649e07ce253f94346525897c..ec0cac982330bd0867e747f6c5aa2f23e21764d1 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 a6d7ea2ad25f0c71c8f38ae6acab801af7e9c469..c7c0e432b699de6b7d43d34852f02a5651c60370 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 d445664af7a17bfdd5b4e431166d27b355bf1a65..70af7628e694c224dd9c51ed6353d07b7ecf9a36 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 8c90e9b82b26b143357be8334185e1c4b2da5de6..b817043167ae550ebec194a9f2b31fac70e26c33 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 94a65888f6d70cd20dcc71588c8333a6fe7ca9ef..f906e42438510eee775d1d648b9da348cd7e6763 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 5937f41599d53b4e49861a7b331bfdf0d6af26fc..7473d780f05ea5dd9110b07e96a726edaae0c396 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 7f72aa7ed1f386a6bf56b86887f68304de147941..bd885597b1207f8bbc8c3e0a879f0be6d2f22fc6 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 0fe0dfc6843cd7324ca186509658fbf86ba96755..47526fb482821b9a8772d5cf81dd98aa0a7e04e2 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 c5de4d100fd98502c90ef53f23b4877c27db4c4e..90d86f31b7cef5ef7f572d0102958eac4e79b5f6 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 2c4675644d56c1c8aa94a5a804e6da95f097340f..d16b5184394cf59ca3e0c3bcd175c320e947dd38 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 531e31db8d24bc36c9a29e7e935d3cc4ba40c1d4..4fac79fedc50f8f7ace8752172a2257e06b08e6b 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 94607477a18672dd00becee449630b9715b5d8b0..76560e45171aad014e989336967fa0d25fe6e888 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 aa5bd6c971561dce393d38435611477e8656c58c..aa47d1e2ace652221f312ae89a2f32c7ea34a06f 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 daad00d7917ac97785a549178ae58c4b1dcf4027..b607e6128a2fa1936a5f4b288d4721bd5281c376 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 308159c309d1de005c14586a53bc5e4c3a1d4526..d87535b5302a4c9329e374ad5d4239a4ce007d87 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 e63b02714dd79bb241789d08ba793b45a96860e2..4ca3cf4e8a3625bdfbc09cdcce4501f173b70e22 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 071e9ebd838e6c6199700d95d0d0d84d2da18b4d..9a529f7b4cc4575b31c50f90ab98b269a05de970 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 d9696a0b20372781fbc1e1361d2e5c0815d9c6c1..b1e87443c2bf34e8bc28aa6735148ea70ef2c6f7 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 6f7a79301a056e2fb3a2dfc08efaec555bc6af70..f77ff0fb33771996ea18e4cd348bd90258165d43 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 e5ccffb1cde8c9e3d0f1a59936708875cb98b117..f25be4d1b98c5eb5f6665b5ec46b7ee05b3928dd 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 64299148c66de4fcabb74fc30d58fe2d88911207..c180332af8763bb55072a7f20c27bef06b1d9344 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 53a28d34b72bd26bcae1c63162f65c58142f80d4..3e792b06f56c7b696f24889feca019663cb17cb4 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 55a94b02dd641c2dd16a62359304943764ffc51b..6b33b8dad680a2ecbe2ed7ecc310caac25dd10ba 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 0000000000000000000000000000000000000000..b3b99d7ad6433e794b8e2c47dfc880f69d6221d7 --- /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 0000000000000000000000000000000000000000..f79f6d77a1cdf8f2009af94f4c2b4ac04f76652f --- /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 0000000000000000000000000000000000000000..76eee600bd99315210f4eca497a2b3340a6da2dc --- /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 0000000000000000000000000000000000000000..680e2239cdd9d6729de3076b5e0dbccc803cabb3 --- /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 0000000000000000000000000000000000000000..0e502ccfc6116ea9efd46aaedc1714212155abdc --- /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 0000000000000000000000000000000000000000..b0c8e32660724622ba932d147be603c9173ceaa7 --- /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 0000000000000000000000000000000000000000..8cca901c59d37bed234d2843e66e6de7ceb20803 --- /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 0000000000000000000000000000000000000000..02b74c385fadee867a0b04186b36da323a60b537 --- /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 0000000000000000000000000000000000000000..c57d2278256b53fee6dc05ad571c1d3a0c2401ea --- /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 0000000000000000000000000000000000000000..e5391590820c4b2994f133090481f4e8e7fb8096 --- /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 0000000000000000000000000000000000000000..d1756caa5c3cc63e16613bc69b7526ba5739135c --- /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 0000000000000000000000000000000000000000..b75e7f5664a1e5fb99d63716b9664e85c0361fbb --- /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 0000000000000000000000000000000000000000..c34a77960dc092d17b82fa02d3744f382d6cc0dc --- /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 0000000000000000000000000000000000000000..109aac5a0e3c2159239668d9ca6b098970567ea9 --- /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 0000000000000000000000000000000000000000..0b77920e13623cf36a066060ca3e94de30c62e6c --- /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 0000000000000000000000000000000000000000..e3acda17267487662b7bf8331012654b8eb29092 --- /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 0000000000000000000000000000000000000000..acb923457ea580f1620315ea3ab1da7ea0f6c49e --- /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 0000000000000000000000000000000000000000..f04a23e73da63916394003718314123e00557a7b --- /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 0000000000000000000000000000000000000000..031a8672aa62334b22d9cf56530d694e79ef24d9 --- /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 0000000000000000000000000000000000000000..14e199429b8b812c398f0e7eedb49e407a0d5640 --- /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 0000000000000000000000000000000000000000..e4d417d0a26d11876aecbe386bcc728dfac62e96 --- /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 0000000000000000000000000000000000000000..880722deb8b24fc9a3836b16fb90ec87c25d236d --- /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 0000000000000000000000000000000000000000..52a5cb715963926fb008da1e448c3112ff96a905 --- /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 0000000000000000000000000000000000000000..b98f1779567239a4f94102352304222b66e8a628 --- /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 0000000000000000000000000000000000000000..a7ffe06ff3df0637ea59d3f8667392bfd07cee45 --- /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 0000000000000000000000000000000000000000..c6a12a448a0bfac7261bdaaef3cf6edbd449f709 --- /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 0000000000000000000000000000000000000000..cc22a5173bd2ef1245e8fe7c93b9962e6d1d28cd --- /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 931b26fd1e7b39cc8020d0413edd8e18cfb2402c..7e7f66fb24cbcdf0f2d49d2e2f6888ce0d2a0bce 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 0000000000000000000000000000000000000000..810ca4a4c540f51444a7b38a8d4f393990e5e2fe --- /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 0000000000000000000000000000000000000000..9562db1d01f22f6d1035987c0dd0d02a02c2ef2c --- /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 0000000000000000000000000000000000000000..44815ff33b18c45cc40f3f29121607570fb7a0aa --- /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 0000000000000000000000000000000000000000..e93ab5f168c3b4cb406522cf3391940009b02e68 --- /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 0000000000000000000000000000000000000000..c0bd1744b208c899d1203c89f97d5c0bc3306ece --- /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 0000000000000000000000000000000000000000..f9494247afd1f2f698b74544e7d405b3b15d2691 --- /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 0000000000000000000000000000000000000000..e4dbebf5ca98a485a44d98ec5d108bb53c38fdb7 --- /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 0000000000000000000000000000000000000000..94f19dc8270304ec7496d6f0e35f925b7aa865bf --- /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 0000000000000000000000000000000000000000..20fdf585e4d65e2b587060992977f4f919d1672a --- /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 0000000000000000000000000000000000000000..d4bd0c706e8fd64c617e7325dcc0a00683a1fdbd --- /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 0000000000000000000000000000000000000000..74168e032531e267b82efe4e0e063227ffc482b8 --- /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 0000000000000000000000000000000000000000..070ccac6bfe366e17a6f95365b2eac020c50df73 --- /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 0000000000000000000000000000000000000000..132cf282213946e343458c965e014e9cdf34533d --- /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 0000000000000000000000000000000000000000..7b7c4460f796e89add10a846d3f16878b5ad2119 --- /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 0000000000000000000000000000000000000000..6f953f5cc9cca21687552bd5aa0b7505d9fb4d34 --- /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 0000000000000000000000000000000000000000..41579ed094a7fa97a01b9d0841d816ff97a0979e --- /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 0000000000000000000000000000000000000000..b2db5575967b8914364b8efc88390853d3648924 --- /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 0000000000000000000000000000000000000000..2b121e68b51530bef311dd8f1cf89a0fcb95a2b3 --- /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 0000000000000000000000000000000000000000..1d62628fbe7df1acbbcaabdf7b936e068e3b5ac5 --- /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 0000000000000000000000000000000000000000..c501b64736ff37022c710c47857183fbfd13b15c --- /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 0000000000000000000000000000000000000000..70f9f5a632b071dd6846566c21dd45621e674d15 --- /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 0000000000000000000000000000000000000000..1683850fe5fa25b6b727ed2d745e6c100e675c43 --- /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 0000000000000000000000000000000000000000..197434fd0c05b3d9b89f04a36a50e446b606333f --- /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 0000000000000000000000000000000000000000..f0b20306e4bba878581b58ac52083b09e946935c --- /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 0000000000000000000000000000000000000000..de36c3ebdc6fe9dba16f91aff06898e84c41c72f --- /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 0000000000000000000000000000000000000000..ea947d91d89159cb9003da27867a3045981666be --- /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 0000000000000000000000000000000000000000..f07674a428c398938e4407c5df26030b0eb99134 --- /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 0000000000000000000000000000000000000000..5a342fba14d0538939397fc6e186bc03c5ecf213 --- /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 24d4197ce5673400259a37117b3a248997b05c2f..3dc116a83e2b4910dce2508911104abbc3dc9666 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 b7aa3a894b633c2e56e1a458db50686329d35836..06a8e84c7e757f1e3663cc0e0075d45e20365a4e 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 14b153acaf49d310ea7e80cb732407a38129e779..c427450ba4344914660bfa5ea8883108caaa08bb 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 b03e7e95bdd8cedc0f23515c2c8e6bf2301c4398..8d39212e9c96687c7d1a39d4b05e0b555afa80b1 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 1dd1113cd2dc4351e3b4ca8c03fa5f3f1514a372..cac869ead1186375191658b88ee57974a283e0cc 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 a16b55506c6671c31053056f7c87feac497e9186..03609efc872430260875c153e2d6170d4bb1ea1f 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 e8a0964d2886811864022649e364a9bf9ec79a65..7f13c9a798d5c48c5a123b3c073840dffdde0b11 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 6f159c06ee388ae1d5c40071fbff800c503e5e3c..13f4487150a711bea48b3e0a07aea056adad829b 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 a0e77934fd8187e44a44c52c421954ed001264b8..a9395fd63fc649db234417595ca5800ba16aaa6d 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 b1fff42516245dc90839dc336515ef30bc697ec7..4556baf285a661d27a52aee0f6483b2d395e20fc 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 76a176d9511e112f3d9cb202e2b561101a3f39fb..c51ee32ac17fde6ff5cfc7deb1db12e6b9a48573 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 c12851047281b7ba08124fbac1c9c60274ce15d4..bb03d30ae13fbcc21fe0ff952174bdc4ff1e9096 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 3e0eba0632703f3a4430dce5746ea784c4b41508..dde0f25119e16ca8953b365689b9f706e65e5fd8 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 e077e2cff3ec211959943be1bcabfd3c21f31049..c92832c07a244b594c4e870553d7ad6ad60bc602 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 602c26eb2769c98f3c3e8585d94841964c61dcc7..5d2d2a54812c2a376c099abc5f78a485a9ee3264 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 973ba68d30f131ceb56c4042a2f1c1ef565de39e..38a243220f9167c8f9378e7d24c1f210f747aad5 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 4b5a0d0d7d2a24e2f6e784bfee0a4ee3d453ff09..9dc4a85eb3d1841b1dacb184a1e0e329f78fdb48 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 997e4f024afa8d69bf13eaafe7124ab17645dba2..7e7c6c1be121f8db7b250b368796cd46b8ce2a21 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 12caac8c56207d4355c9a8335d660cac85415df8..ddc8115631f533a3f08aa419287e281cfa81e5e9 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 8e43c0a053b87bb1cea5836f3255e243469b6235..17f747042000ce45af20a57dc36f823b220582d3 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 45e0749365afd70308c99fb5d4411659c7fb9e4b..41050626d74160e7ccc3f73f40048aa72d0b45bc 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 fe698257a93e607e10be884d38d9a9b64f54cd64..e6c1f1f59b7356b9578d64f9949409022e434ded 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 1bcc3ed7bfa2839daa13b483ee4df446c45f0646..366ac0a9bddf8b6f4ed6e6be9223432a5682d7dc 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 0b9beb4e18fbc11fc3a1e2c29c4c44633e963dfa..5984291f1422ffecdf9887cee2a66eace1de24b5 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 1583091258232e6d5d0531e8b14ed14296da78d2..21e6b903804de08a22b9851f15d3e2f605a01a8e 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 34d5b311c7e1cbf4b74c8bd7565c9b93dff23230..179f99cb694d94b18159db58c67167af8d4f02d5 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 4c98c6db84619b16135b6570ab522a4dfa44b4e7..9cb37473d9088b30f7eef93b4e5fdae46c40fa7c 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 6fad33c8f35940f7520299677b1cf33544239ef5..d42818646e72e14269cc41283ffbbe1e0da82bf8 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 75396d2a8f237d7c3375307cc45d227408001686..70a2a8b1379896727aa37473e87e62a0f1a5e08c 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 c0e6548661ad5980ba3ac7a997e69c6e9cad0fc8..665776bc268491ff7a3970fe36aa85c89302c78c 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 52202d120d212c463ffd7ad1c76ba5def1460342..a1462e56a369199a2c265d2883ef47ca83681615 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 c1e007044231afc3a8a42c7ce72aa135abdeca6f..0f3aae53e3dc2272a7b42abbfcb743888c0e43a6 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 88e98ba3281f8ed31aa5bece2aa86caa2ebbf939..34cd57d152cccd43c987e068302d70935d6fb5a8 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 c0c6f71e8507760c9a3abf51d42c2c60ec1a53f3..9018cce83f9f91a6a0035a8ac28ded21c53a479e 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 4bcae251451b17114d22b742c8de628a5684ae39..25d6bd174bab31734f36fd250d06455da957db62 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 875a265f358715f9708c76d711066ea8a03df202..c6bcf82a1625f14e617d53591bfa8ac96eb65224 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 d04115ac76eec6ef8d851724614d18fd04e0f919..699ddd4e21e0a77f695e1eee47f8c427fefbd122 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 98982e07d7100f64d654ab356d8bce7616990b2e..dca2df64fcad113d0e410c6c6a6a59aa64912a97 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 79d696dd51e64f407ff69940c69ae461a5cdce0c..a29542c5cee66a9c882a776c8db677f43a2a003d 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 f2923532ffb9b8230f36096f7d92bf611a3e9dd8..0b65ea2ca5baed6a4eca9828a66cbfc1e8359b12 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 a9dcd03d2fa1c2e32ab69888c808a2779764bc84..4343bb338c29625b141f828e3aec6a8765874671 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 20ebb756b3389802454f77618ce64274630f3172..daa9f72e4a43d1d4022c23485657dff5206d2d9f 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 0d76ef10776651bbc2fc9289545b713902c3deb7..01f631a13fbaaf514ec7fbab15a3ce29aa5ea2b9 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 bcfb38931da7aa210ba0e2693d66f7ebf9fd39c1..54a943a2b263abe583553af1f9728e27a4f816da 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 42ff535443453608870e78fc481d0eb67e3cbde0..0856a4dc20b55dfb0a784ce9ad30973eb37033ff 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 d50df17f287e1a12ba1148e70a8b52a87db69bc6..06f7c69045a598d7a56b39ac5e1d4c22ca05a43b 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 3f107fa2253fdc6479bd3a5fb8cee1059d0ec087..c3adcc5fe530867ca55dfc4e48b3a0741c7a5c31 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 e740f67700395cceb27763722b79e583c5ee45f3..51a28372230be0bd6e8fb9b71cc98be02a2982cf 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 e9722fe4a32d7d054fad5a9b7ca004dd4fe9be95..4ff65e1311819dc0297047b951d5b02c0bf9a2b5 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 91f7f01a17a0c4207fe30f5f92c3e2200c370d62..d61fadaf8207e6911c853d71f6e265b26f54c88b 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 6b333e258420a1e0195337ab85039f7d34d92766..60e543a8a6d5080a001012260d2f94786ba7c68a 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 171e3ee766de5ad0bb94f53785f77034527ab4ae..893366d5b273d3ae7eb1f1abe09f74e4dd8cb069 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 227cb043da168d590a724eba65d0a508b3b6db66..a28857a77a67c26c32fcccb8aeaace1f8bc362dd 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 ad7fecec039041205780f504a19751ab799f4440..e5b50b17bb817dbe15f03bef6b328876e1fd1170 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 fe55d4d5d743ceebe487bdb15e9b73865432d3dc..29671dd7117ef9a416e9daed582aef7ff82983bb 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 d9282880251b093da0285d39b731e9f8667e1318..b85cbfe5ac1609e2e4c24bd842d502f898a321b0 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 f6d58862e342748c35739df0dfa1a135ec6ffea6..afa2f578884cf4b5170a4b5cdd24a5fd6c712f8c 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 e7ebe3ac0b775f7fe3159882625a507b979b0400..fc4128d72270790dcf740b178e0e115964f7701a 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 9a87876ec16b44ee6b977245f5d3fa69e324977e..6077bda1671a369921af889f926e283f6d5e310f 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 4bb31128a374bd926ed2b5453108d95f04522659..84bb1dae1d89e0f243bb7463dd1346f0bbd02436 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 01fcdae5a0d0bde0a634666c790ccffdb50dba7e..375b4778227f17ff724d50630a9ca1634935a0fd 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 a8f037222e4981a6429a8620c4ea849e2a71fde7..de0bfa8727f644c3e76556f16096c8f15f57a570 --- 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 03bb3332e0db8dcaa3beeb67765df3e68b302bed..aaf01421a5bfa74e94479393f55ecade04d7c085 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 679460faa22e312129b75ef4b1e4b748297ffa52..0b0cc4f92e8a621cb857e1cfc5f0a7d164ce0065 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 bf727f8ae0b91d24dd0267498e20651ebb7beae3..e960866cb8aa0f282d92038de544ae054e5ef56c 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 7e7c0683fdcbadccee9bfbef0a96af93d95fa7db..2c2273cd583f2f03ae845818941791d0425d5e8b 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 2efce59a5a1b555c847b024f5752f8236db1a661..45499e358e446f654b56ad6121f11a503fcd1875 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 694fc53d66a47141604e2a960ad340e74a3c28a3..ff8272973edc8abeed2acdc8c0f46cba765d5b9c 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 c211f08d4723849c8c866a7db6b29ac277463ef2..b34014c0932fd51d382aada9fb47aa6cf1084818 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 fcf8879872695e74ff2169d81c0c5eb5aaf8c5df..382e358c6f43bcaf8a74bec5b257b8a6e8477efe 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 1cc189576cde67d7f064f1a6ae8c533f1953a480..83c03b0944afcc48495a475e4cde586a3874d479 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 e54638461519cb0c86da300a8751a11fc411d7e8..db8675307d644694fb5877c2ef86f512e2e962dd 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 af9c5ddec70668325b6ef2206e4597155900b18b..45b642ac15c5834058c84b3e5891f6ce4cd3166d 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 20ac34fb6efcd6f8745cc5295437a9716436b5a5..5a7c7ff7232fbfeb3a49f8dece2c7a799ff707b9 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 30614594cce4dfa917ed4f25dee9ef201165440c..e4b8951d4953a21901122837b58db7eafd7fc5e7 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 eeb44934790daa15cf105ea40ffa258673c8fecc..8b0d9fe866c38c365c428e9b2ba18a5fa63b5aff 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 9538df643698739e6d84cc2452c21fb12104ff8c..659344fe9ae4d74983fb3e720a18cbbed1b54bcf 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 ce374a317ffc89b0cec459751d537241bb41c836..78642e0a42921e8785b8f7ce03c6f141ed781342 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 81c72f12a4e53461baafbd1af05d218799cc0535..9dbcb96813ebe1b54aa966c857b605503cf26b97 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 65198b9d01cdce4e1d3566e6cdffa555b35b9139..e3c53178aee9ee2b003ddfd3fda1ef66ff09b092 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 f2949eb499b1b8a997fdeff67d01caf7d5a343be..45634a0a45ee019552f3f683969bc61650571458 --- 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 0d2bd41230a12259dcf96efe4b0f81efccb4fb42..fa4148407b1540fe6f65e734ab7a95a7468f227a 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 6f9fd0e812da0f880ebdf50e3082c5f0f8a7e174..795b1936665c8f4cddfa85f1680f87c0af9a8444 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 155fded55dbb647cc63635dcb6f9a44fbc89d4d4..ee103cd3ba03010eacb33581138ba0271ed28b3f 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 cce32827396fd18ea0490ec7cf6063eb936ec9e1..1a875f7da17e1a2ba31bd81e12d29ca8b85d7369 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 a983272e7c6a66b719a50642782dae89de7a6acc..0026057af28f5c4b17530758448be5fa3ee33188 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 d2eea72f8b7ac8121e46404e185d56657d691f5a..0f67ad8bc2966a9a129a8f31e85d82d5820f2c2f 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 aaf256bb87c8426e6816cd733cb499ca0c220b54..fb065ef08d2193b813b11ad4efd1468fd5f93287 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 a4a8c1a0c24c5993de0ea13555643c6733142c29..bf0fd36ba4428b66316cbcaa70488b8a43bc79a0 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 a705bdd84295cad5728195e4d67e66c9557548a2..dc0f045ba4b2adfe4a75d99de09fe1db206be8ec 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 a85c44e4984724bb94e7fe43988872e220437caa..62eb8be3673e2b1834933e45bb4173eb47659eea 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 70099a580586d6580d6d4ee301f00be85b8cae1a..87c9a910a3083ecc08d49144f6af8ce6dfdfcf9b 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 93df4a360cbfe4a03cff4aaa69a1e627eb29deaa..cc781fc2af18cc2a305a7c2035875ebbbee1eacb 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 896e410b316d36ca2b194da32a1bac49eec19806..8f7ed57742b875532f93918f4ee83a80e8ea3744 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 10b1c91fd9a7a3b4098aad1e98bc2df3831d86e9..951c3115f075b93a014943355386718209a8c12c 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 bb4d871986f51da52c09bcae63cc598e7a558cb5..ca489992a8904f7bb1af15840ea78c5112722e81 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 0000000000000000000000000000000000000000..23a6007c05f6d41139cae73d3f6928413ea629e0 --- /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 0000000000000000000000000000000000000000..2a29b116142798d3675ce2dcf3e41d5442eb9a1a --- /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 6874ba8dee1eb9d87709ae0c2ac96aaf36188a5b..a3f851074eab50d48560463860cc3ab880f748cd 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 0000000000000000000000000000000000000000..c278f13ecdec138c2e2eae54feec3ffe29ec8106 --- /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 769fbcbe7d202cfa7475f584e0cc1e244c8ab724..3d5dcc76d2da78492f50c22beb00506951fe2cf0 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 0414fd91e4b3e2ecef8a28bc423b18efb45cdbec..25c284e09d1aa1705824335c22c4cc9300a6a4b7 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 cf2b46056cdc40d9e42e44cbf01ace9e6bbc5848..243a7b97047a928f7491446fee75f2c7d793f163 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 a9cfdb9f16c1e207917ea0f99caf745fb94d9cc7..a52c2622f58d810dca57f835fefef481568b11c3 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 7cb9fa3d82b2d8fab174403ef22ad69d2a8293e4..11d8a17858913f72022405a0c27233557d80fa9a 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 716bda8854c807aa151047fa3c679fe2591de9f0..1267649b4beebdaea943494d56c7ea2cb5898238 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 b4998412c527d79150f44c27acd8b1877fc2db72..8885f48c74ea970d37e4a6249e2918e416eb696a 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 cb507e8bfbce1da8734096e87f2b5c3b8b190d81..9ee2b246d1fd68bf83ac6993fce526ac822a137e 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 99ddaa8f1c0580fbeeb76491a66a8acedefebac8..51eacc96d00ba1d0a0e95980f87624330a6bd16b 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 1fe07a1c95d6813449811bdc205b60ce13eb8a82..75c944cddd20da19a6dec4d73e2e7907106c8c71 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 f2477243ebff3d3ff9ed4a973c9c52a0b14a8716..75f98f5b553d5e60a68d6bbce16736d89fe46884 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 263535269d7c29fda6a64e0bf107dfb96ffec6f1..4a1b45687a4a6d2a94f953d64307782022f07e82 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 0000000000000000000000000000000000000000..cc5aada0e32f392f58f7d2f8a6afb98828cdaf5d --- /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 b07e1bc037cc10175418df6d2529e01f5c90b480..c9aaf1f54ef58fe2714a3451b2abe52790c9918b 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 623ac47fe7d6c7b6c362039d25e6dc5d417f9d76..0aecfe183e3ccd9c0d8c74ee746e697f0565fefc 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 8f078f1e8a4a78c2fc30ce62f33ac2efb6bbca16..f421d6475251b29dd1d0c10c03022e9d32c5541b 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 8e8baa1ae33419ddba5fcf18b71a779dccad9fd3..1bd14237a0188938131fc1a7e3f79dbef4255433 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 789fe051dd291b5c35ba0cfe9c72a8ba8294b87e..904076259140ecd7699bc926a19174d5b0afe4e7 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 d51794715464ab060dd65c6d5212095be03f09ec..ed75b50e07170e0e0201e3c4b05905523e439bc7 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 1f213ac43444a86f1f7b06fa43bef096900291f2..02c63de3ca0075009ed03ad40c4b981baefc7787 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 5bf79204eaf77e7a3577c91c20610cf488fb8074..82a7d2cf5784e571e90569d659b6bd31787bf323 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 2581bc8d09a7afef9a7e3116613dfd2c84294385..6492726313d3b3b577d19b1aca1fffeb5604301a 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 73ac085ca8291a87fb0262bbae483614be094518..337e2c92c19b7716c31fc94e73041262607256c5 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 b513adccaf7df54261fc9ed4ce2f3f8619d1506d..543cc4d9b0527e6f282587af009ce686175cd102 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 ae55ce7e9b946bd63bbb080bd9566c9fad0a8438..b1111dd3a3ec8728327b3129c8cb4ba153ace147 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 4aa1d1d3260a53b3621c21ea96ac6a39570b48d0..e38b050f68cdcdf105a8d79ee4f067ecc290e5d9 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 0000000000000000000000000000000000000000..c9cac75bdbfc6b02d0004d3140239a1439a6253e --- /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 a2ebe8efe7ec5ec7a2edcbc169f17cde2e34283c..61524fb2a52b4a9f7f849d0a60cb30f6974bbf2e 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 8696d2c609185d862a3d85c48437b16138a517df..481d0c7b8523c416a26d24e80ff39a36b0419e91 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 d637fda60588c702642d87671c74e479d46702f1..8796002430c89d4ba40495a425ce4ba0ef199c8e 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 c11c89c6aebe2a5c7f706db7735b48c2dd7e9744..1d9d90fcebecbd87d90db254b63bcfc01443a207 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 6dc0d137bb6fb3a0c40674a0ab5882b1e95b1088..b8066e426289e3b83780f6ce5a42c9a8c48d8c8e 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 1e0389ec29bce873d40f2e0cd08b1b564406e876..68b154b1cf8ba6fa97252c71c33aee7de1d03e7d 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 3be02ce6b1f99e70cac08f7a2f18727c306d16f8..217e4afe6413a8619f7a640ffdc696541535a8d6 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 50c8a06bf50dc5ffda491ec72d8270ab0719f9ee..99ff0843590d12a4a4f3b68da43dbbc46612b02a 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 55570be6b73d98ea6142c5713d60cafd3ec7ede1..082ec61e3dfba8919cc298b2a70d6cf916ceba5a 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 595ec2b81f09e12a4508c78308803e09f7bb8c52..7eaf4db7510f86418829d672785681a40ba1ae3c 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 3b9d16d83eb4cfceeb90b6ceced551787440079b..5a72edc0592b6f1d9e556767c6731af6b4c6e603 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 ab83fcc07d1eafcb4e889140bd9852784ce7e410..fefc8aab81d104913bb5658e4e99e3719590b290 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 5c7af25079f857955744808a000401975b7f86ee..9f77b36af0d755b1c7b47e55fc19bfcb0c29616a 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 745865864ea677e2e04453b85d2fed497ab9e9db..b44b68bdcb95c8ae1bc95a9ca9db89e3c997f56a 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 afa1765ff68af4e884e53f71bafb551e5a63f29e..f94707ef0bf7c7afb6639f7788db98e1d403a058 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 4779d2259eb62e95350ef12248c2ea626e29845c..d6a03461b94a826ce02d66aa5995a629b55b310c 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 0000000000000000000000000000000000000000..0fc880834d40b85ac1e2effa1bfcdbecbd3620af --- /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 5a50d326791980ad613b694c4614748dbf1b0a6b..f093ea419d589c600a74c6b3813bb501bb4e2ce6 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 825b8acd7d5e18c55d6966f2b00ded33ad7c9ce3..0f3aea68306919dfeddf541223c8cf0cd6a930b2 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 b8f771f2ae8673018de6154b96bcf670832622f7..dac04577373e0e88f2fe670497625b8446f71b4f 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 d67528a71c30a78adf9d5fb98dbeca78dffc5d0d..ca6b006a449dd3e1ca54e2e155d7c03fa9c57937 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 29d1232211d96e7c44d19428de65daa08cd64c38..55e9da094dbdf27c5eca586337890ee06c8f3e4e 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 553446d23f54f0f0816876d77ce4539960791259..b7f4bcecd86bd05aba08fae8dc949adb77dac87d 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 fbfc6ebc5216387abd4148d622dca1818a2da977..2f57327e227dcc6485c99abb8e26456526ad6bba 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 892e7971f1a240eb8cb12f6e78e0610f93e4da8f..c0b6c6c26b29f7d79865c058ff077261179bade2 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 b1a65e7729c2b815b40e6ef2ebd281372bf8cbb2..45f5fede00341a4c100953570501a9f94d7ffa5e 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 65f6df8543ed7f1b3e3b2998e571f110e29a91d3..a74569586f0f8f7769486aeb230849ef589a525e 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 786aa81df52bc817d0af007a89c37f45d1949b34..e8efadc64b150eb0c20135e0ff0d8bf646531a81 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 0000000000000000000000000000000000000000..3018a17cfbdb067d27f9285c3a55188be16421e0 --- /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 0000000000000000000000000000000000000000..cea59eb22aff7cbe8d1b2b66f960901b31fd18aa --- /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 0000000000000000000000000000000000000000..ba9535c14142fcab397b4f51f5a6c0bad5a80ea0 --- /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 446f2ac31d21d32beb9e333d6efff0144c5abc50..da5f9c61bcb30f3ec6f6fc7d3f912aec8237c07c 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 b1ecb7951b0b8d6827f86395f93b8ddec5b497e5..87ffbc32f8c97b47aa3d0eac42a2e4a3a7057e42 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 ab1ed8f28486845224a455f1743501e06e4c6931..752e41facdd09a728d5a4ea2dc96033e6fcf35cb 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 e4ae96c15501b84c7ad6b48beeb4cb261f8ccd7e..11bcd080cfa0263a383f5f2ba97c4bfc6792b80c 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 694e721ff1c83c34dca670230cd5225efbb79dec..39b76356e9fcf5764911ef371a77997f29f3a362 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 bd732b556c19749c2da2a0398b7753aa7bb2d133..675e435a46b36873216aea3ee054a8b3ca749090 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 0000000000000000000000000000000000000000..4190eadb470643ef540ea5b11e7acf3fb70f1517 --- /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 f4ba7fd1f5186722d45a98ec1aa2b4285e2862ec..c09a9ede880fa64744c00395652111ac9eab9cd8 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 dbf2ebfc25538ed7e6aab02c9c43aa828de0b6ce..df1ca05b6a8c1fa4496ae56877bf3ea5d9ad6430 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 a623ed61d2ba765fc3d223fe63f9c6e62375af4f..893c25a7b0bce4a8bc6be9942763c5e7dec47dc3 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 c9e7050d6446058c36b4c55266ac3651e4d4f6c5..eaade2108c14491d752f976487b68bca40035da5 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 be181908f5ff6536bb9dc9c9fbdcbd7c8aec7555..438ff08069b57b4220eaf543c1c99819aade6337 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 a90f642d2a7d98fc8128e38730e0dd7c99416725..a8e23a028f628d5e49affb2c3b0390ce33753aa6 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 62a151b954aa3d187d19e3b84dbe9ec5816dadd6..5ab5ababa245659294bcfb6a53f2f8d57473fec9 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 58dca6f675304c48cf3aadda91e0792594d159dd..ba143b1c7ab932c6b6a06b754e04a388b8e20e7c 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 f86667d36b63ce259a92d2f734dd391bf68be71e..9d74ae097d939a247a8b0cf6a1a39400ccbc1352 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 2cc3549d7dc68b723aafe1b14155c8bc79f24e0e..381f111c4bb0246b65d93f0d248fb8e4d0479b92 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 6c4e52a9c709411e5e91449ce86ae93ab94b597d..05a76ec29a5ecf5cf88d1c3123a1de64b0eabd33 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 61887d9d920beec82223751928774eff14668060..0000000000000000000000000000000000000000 --- 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 e18ca36854392d1d2c3b3a833d4f895904b8dcc7..0000000000000000000000000000000000000000 --- 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 175663dfd7586523c85d1727739f44a7b66d8351..d44bf548d0a3ba0b793568571ad87b662094d77c 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 bee3892a2c0a1cc981efacc57eb069860191f71b..eb6dd65b12aa5d671fda1aac1592e9d9c36ffc9b 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 818a4d00631f2663003c65f4799620e38ff619a1..620d181d5b57a858fd6f496fa367f6fd980040aa 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 314b8e7734d111fd101d97845e5adbe0f1fb152b..f916d101df83df82786a52fb21033350ce6d051a 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 45e98ee5107251e94c7aef831bb10567957db395..23b8178d2932dbd76dd254008c1fb374de840dbf 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 cf613f2bdf693c0ceb322c5170a02216f8aadf27..2382e8b08bd6e65e75ada6f08793252f9974b29a 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 2d46028c5555681eef6a37491b1137bcf84eae45..840621a43010b5a35a66e02c575a6d922323992c 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 c58ee610dfac7e90346ffc063bae10096e9e28a6..0000000000000000000000000000000000000000 --- 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 e805872b4c145ff3fed47df117b4dfc475cc69c3..0000000000000000000000000000000000000000 --- 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 56a81d113ee929c68d2fe2c069c4e390d6847b56..c194a513938c14964059539e92067c282765b4e5 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 64b37bcfedb9e9941e691e5e4b408641c398b531..0000000000000000000000000000000000000000 --- 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 12699f904fca08d131e0a689320241be5b016ed5..6608b2bb5493d7958ba5fb7c70dac925f532d0cc 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 1dc524ed5114a2bd70157d0f679c742b91941aca..54dee931c2ed3b84bb432f1c1e65fb1352644488 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 91baf268999a8633254be9af2bc23201c8bf6e24..9a4f7c882dfe9b3ea8fd920bcbd50aeba22ba15b 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 f3579691a10389f9de5d860422b6cf399740de59..9915a5d748f2f8f3e7406efd4180fadb071a0e25 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 e7d098913acdc1cd5b87135e6be395f70848d0ff..5e3de87d4834b099279519ef3aa0f49d00f8cc7d 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 5341176d31966d948011ed573b507d5ed0067975..01be0eb5b71993bcdeaf4530a4e9a77e8c70334a 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 b6c35ed236251d7dfd3086b606427d1ca459d73d..66f743e3ba14eaf9d26883488753300c70c5cf4a 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 fc58ce1effb583308300551c6d3ab9672d544cb6..21b498227102ac7548a8b20ac8143146e7696948 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 fabe2429015baccac0929176cb4b0aca07d52c1c..6935f2302ce16b4c45c83fa4f031a138089e1cf8 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 a42b4c0264834a06c12dad7f78d69cb9203c58a9..0000000000000000000000000000000000000000 --- 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 6ee5d141069e83b48b43ffef7140c6de3d89fccf..2b8c6bd9f3f13a641eda048f8d006ac906e46b79 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 55cfcc4a9d378dfb83ab30ee057d7c92222d4a3b..b4fed2b3acc4f9b770e460eea65492eeaae5aa4e 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 a6d4808f6f5301504b735ff100bf031709c1b672..438d4fff6a7e6f45748942708d6816c0385577aa 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 ff18e747a3b8461b60e3c5b33849a7306abb9662..834ffecad5293a6a15d14bc63f5cf1c31db49ecf 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 cfd11ff842a6b25b25ce7e86a9b12537bf58325d..73417bf4839dc88c6a62631321a0ac22789444bb 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 15c63813411527b06c73da764f6bd9a4b755fc17..fa6c9f4f7aa43940e81a061fce578ff4bc84f9e4 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 59473ee21005f28aa1c2dce4ecceb09640471723..2ee7b221b9f0ead3cec1b15e4788476efba08b5a 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 d75cc05143a8279af316e21bd32a8ef2ce1f476e..fa26bd177b1da18955beb40b1af482bf5bcf999c 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 addf094c562f3df59130408aa2d37771193b4706..22ae84110c1a60a1baedc651ffa816669eccae50 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 f4ff2936c745cdd9a15c40117dad402d41a2f91e..5e7643db4f156035da36a3d85418c71072b9a015 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 78494ff4266ea4db53e1e6f6f1434a6c1129bd70..944cb1d5157bcd59c1f66349f01389a4f5bc93a0 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 1acdfc3e0d8c150c007de6393214a9d5df4486e9..c6ba12e62effaa33160615a09e6114405d1ed8ef 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 561b5792b9d5752b0bd510b90a8969af39cacdc7..08e0985156eaf04376c696b2dbdf507c25724791 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 b98c70a83946138ab117ee0b9b0df3a3e65d7d06..ae83f1ac40a7c69a3477c4d347db78025cc75b9f 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 13737325ea358122d6e641a2da3c964cb0802a78..3f9043392368ca044923fc953458a307deff2647 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 1074f70f121cd47f3851dc27a066fc811062a677..6be1a83e831d190d676527ea26fc7b107917981a 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 2e3dae2326a134567a130edc088b11ee5f763927..ba1c89a0412a7e73c97b1dc74048ccdf87fe6a21 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 3b3d6ea7cda9d4b756fd88884882fe1d865b7ff1..31c6735da1808b035a9d8a70b9cb98b2ad16d4a9 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 0bbec8a4ae6a44dc69436c9a7f250a63af6b1ad0..a47d594902ce40cdfca8b3cf36149f7674d886ab 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 5fd59468de68ce1d66dfafda92fc07c012011f72..17d6d18355aac45182ddd2d2e6d7108426c108a5 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 722437eeaf2da4d41f9bdbad4d7175d05dd84073..180cb1023a30c35f3e81bbaeca2ec36c35aaa3b1 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 0f8a79126f3201acfeeee355e68c4914936d7699..b9027c701581b60b17516a865b25a30a29051478 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 e7273ec730515031c26751be351d5514ed2f5687..149e7cb1c817f24fca7b6271c870ba2413cf33f7 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 9b3c2f1ba7583b8ebfbec39e84ccf03ca9b997c0..0e54e1dc455b1ae71fd2437718093305cab59490 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 f83befc12abcf0d0d6835a2f69d6b663b0a37e76..85598fa3bb5efd7e8792bbb59a95441b28bf1232 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 2d8af38253caf1d6026a05a61ae8385b6287e516..c1362995fcd12f1307f6c60f00354db5116e3fd9 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 82aad0da76c0ec7a942e127da32a64e1116f6b2a..9b070b880fe8a5e52d513aee2cdf312b1bc86a85 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 0000000000000000000000000000000000000000..b804bdaf5af4d19a7f49af8683118f00cb035007 --- /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 a2757828d0b40993a4777393fea6f8707e3447dc..7c341350c52ff151f5c97b077743f1ecabcf6c83 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 49e177fd88547dcad3a4cae5b32794cd773e77c9..424bec01c4f80c5c9c95988dde88daaa84396aa2 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 072cdd5716f7cec5a5a0046d2006dc40d3c04c5c..4dce79cce3646cc3d5b82dcd04f3cb4f206677fe 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 904790474ebd1ec5b23cafa4bc11cd21a1b5095a..b8bfebcc3362be8385a138d403f7e492169b310e 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 aef05206178c5d4c6eadf9f2541767837680f2a3..a1a298611d17762166e05a300fe06854e6a64c6e 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 910229d8aecb07ce224f886eccaf2f61f1d414a0..ac44555cfecc5c88b098d677afcac213084ee26b 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 a415bfa1dced82072c29c2d6b6e06930a52c2507..e522066f09111a5fadbf3e2a2871722e45bfe709 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 74c871bbc70844329fa38edcee851dc0e45c2629..e05f22868d8126f895ddb6250d2195d1cc5cb28f 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 a45691563c3769fbb48618f415e6fdcb7875cfcd..1221553bda2b5374bb7e1ff6a83d152140f13aab 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 4dc08a6a01f69dc3a5221d0a6261c3f7ccfb2698..7c3711923e5d2361602e86cd324185ecbabb161a 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 d12ea0886178de5b7db8a10a4dbc1a707fa92b0d..6c29755dc019107176d3029c7eb9ae6e8eea7d2f 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 175f7479ef61c0b1b6887846169403ab208303a0..48d932555bd66691f7119a97a8d348602085d36f 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 a6d30e6fdafafbc815180fdbf5007f62fe99a028..09ff04ac200f132fa7300325fc2bb9f37e843610 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 0000000000000000000000000000000000000000..8f83f27401b0ded78b97843e5880316b808540bb --- /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 c46ef5bfca3347003fa4da4d5db8aca6b72ddbac..a56297b46947f3328fe9da40394c86fe6b5a66fe 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 44675c497670c7af3dd6b4e5ef6d7d7ba3fb6567..f3fd6bc38d239bf19e70b12e33a08d4d6bb04e30 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 db540ea9e5bd7d043956e52a95034dbdbf0d31d7..f2e6d949058e4d79c581881350aea39c3362caab 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 1f1d7d25f104d610406279d3989f745f51aea0be..aeeb454519a63eec87153827eb3c9fb46702cfd6 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 0000000000000000000000000000000000000000..a99f2cc2d0f85a78c675840af1b5a3c0013eb97b --- /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 ffad05c1cf88bf11899e1ae441a574553e1d15e4..826fda5bc241d427a55d5a2958df021edbe1f7c5 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 0000000000000000000000000000000000000000..a269066a79b26fbfd3b5d511cdb3785d1bb0224f --- /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 0000000000000000000000000000000000000000..9bf184e0e98782abe09ff52569c39ba2863721df --- /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 be776ca82a2837f12daf12bdd8cf9c6112416ff3..b5f8f20795f2d77fa063a5a8e3645b16cb5273ab 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 0000000000000000000000000000000000000000..6682fc09f8817603a51df036075ce42eb29cdee3 --- /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 98f0c8a2963ebdec01fdf0cc45f634bdd1b2118a..9592ae473b60a0e980b686ad9c080bb46457c99d 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 64c7c900cc383b3b2be87caff73e378bf6a0eaaf..c5251b81f91a307e136ec4b9e0da5bd6901fc17b 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 ac1433cf70276fbacb2056a0e71a9791580f883f..7e7b2c7cdf654c7abfdc47987f2d7ac20e302ed9 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 c5d0fa6918361357c31bc9a139dde4669d5e0c83..558bafbeae68c2048411b7406e2b09717bed22af 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 f155194467027a12f28c0dccc04537af37a04c9a..9452e3506560ed0d57a5ea0fc3cc783431caa8f4 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 1bf53d50f5a2bd2730a5a08bff7f8f7ff21bc494..6a1af2adbda0f248d4a22d85841c45c6b2ace8fa 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 f61213e0b60b2f8b14f57962f9d0f8dcd5ddc42f..c9002b789f39fd25ec999ee2dce7fd546a8c794a 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 db5b9ff5338f63a69773def716be024e836a2466..986dc54295f58363e6a132bb3cde44ecaedf0a51 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 0000000000000000000000000000000000000000..19b8ba1c7b64415fc78d3005742ecd76818c3677 --- /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 e4a9d1f3ef0c9a5dbc88406a10e500a9ddb999da..6f8336c0498db058cf65bf7acd624acb6e3aa8fb 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 bdaa6471c777bd1e4a2d9851927453bd85b91085..0fa72c2ff9774bc884fab0897b4d808a047a6732 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 00816de234829aca9edaa89c0f1fb75363e51714..5193ceaf53915fc6423c42592720d72abc78ddfd 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 1d50a5493d7ac77758fe0a2add2a5e731fd043cb..ae2dd7ad7444bce6ab3199ba68f261bf84497f36 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 08104b7b172f2ccc0a0138f6b1d3d80b097db70f..1e669db035d84ee2cd787325db346d17f0d43d4b 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 82bff96ae2103a7172537eead39c8e0b3338cbaf..953a5d7049614b1cbc685ca272b762f6ffc2516d 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 d99979c3026bd1409f353005e892a2621bd6d7cc..609299f2eeab3c6ba5d23970f25acbf40488ff91 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 0a0199b431a83b8c26a9ed42da127f0e93cec43c..178e14e648be272d1f6aa39f7031e23fbeaf6cbd 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 087b1967e4019b32d2fad21bf8706fefdaacb058..2f8bf66965e70f62714ecb4d6e1a34317427f7af 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 0000000000000000000000000000000000000000..2ecf87aa5e947cb44d885e882bc58daef2dc9c2b --- /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 acf2757fa0adf3ef6be08719702cc7b37c8d4293..686f4613a32a192d7320ef640607a477487f0af6 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 d395ad7fdfaab28eae97fdcf0068ac0297fb784e..c2fbc3178c38a9b9594334356e200ccc1e509305 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 292f52f32137a41dbe5b00039f351aef44c061f1..80f6966aa6b70d0e01e7ddd57c5b7448c7b2ef12 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 0000000000000000000000000000000000000000..2738acda31651c182e941267a014ce8095fb3b60 --- /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 68002c2e2e40dda280a1ef0a55f3293e2991f112..062e78b26e13f4e55b44cc738e549b9d22b9339f 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 c4a06e8d33349c3ede3335d0c05e064261ce373e..204f617c423b89749e7ed36118c3937419666fc3 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 2567d6683aa9108fd02e1302247fe16c094f07f6..7ddbb9a7979ba501a7f5826f4d3d8c0e7484eb35 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 0aae617c9b05ad0983c6588a13b4221254004fdd..e196fccb4871f799dc28821e364b0cad927f2b3d 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 4eea2372769b408c357608843e1c17012eb0c941..0036ee3ba18f98cfcb66ef0b98d9b1a9f3e81aae 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 ee5a38052acb233d1f112e88a43388269b426016..1aa6f3dfbd8a22faa0908317ac3897d774ccb926 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 bb54f4265e4f23ec59423dfe1df1e7564c67e225..28c6e77cffe90bf75d4dfb4e0779d4274f03ea3e 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 6b2f6c1d6dd9ea8690cfebc4fc9def30117ca775..7da368a13b8331c2c89cde69b0d94c42afc741c0 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 1c1d64b400d68040f98db45bf50e610e42abafd9..ab01b4c38d51e4b4999582cecd73c4602338fecc 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 459bcdd2a9fedfe04bb8eb9d9b7269ed1845e562..a2309eac1aa4e0362cc07af2d80caa5c350ce5dd 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 2990f2804cf69fa41a54eb75aa35beae04d00d2c..466b12dd81fdcc23496f954ed5368fe3c91445ec 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 8f5057bcdb0c0da660e8246def461ae7657c0e08..756e731d310b54dd5afa1d03ff71868cb4617dd9 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 50ae5e931d6fe5da1a7aade7553ebc82127690d3..7e80b469ff08d379fcbbb52fea5ece83fb6a71e8 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 33bfbd827a115be5b46bfbd88e46b594cd6c8b78..e65a34372d40a4470f93b7dd3cc2099c5c10ba4c 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 0d941cb316f6a9f0e87d5463ac6fe724f3c24e13..1e2a03de68a71d84dbb454bea12fe79a847682be 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 c3150c28519a795349df5908a8fe1286d7d47f63..9b2125c8da64d9990b29fc2be94fcf00f7d61745 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 e7659beacc683a81be0039e494313626750efd28..68d549517e21c32c40cacdffb6190e2ee0807611 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 d5a248a971ca75334183fbb3adfc29d235f338de..b3d918e7f0213f9859e9ec5c4485b61487be3063 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 f0da6992b56fa4caaadc07fe7755c0bd37193b1b..c1f1e8b1b267ea2214663d545db2b067368612ed 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 0000000000000000000000000000000000000000..a93c36d6cae7a163ae5078f05121b6388e38611a --- /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 2948ba23173e23cf792fd06ae7012835a726d62e..258e329a2246c6d027270176774cc1528c6dab95 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 bb5dd0c1dc4179b9905a3b5413c06eb8df0234b8..e954f2c866367586c37409bf45c07d746807720d 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 86251b9a0a2302db0bf16bc72f7827a79e5c1f9b..86612d8cc90d180e2df3aca18760b361b1e1afdf 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 99452c5b3d8ef4cb2d34588717c6f7c1c7802ff8..698cffa8afa7ec0311997d4717652988944b5c00 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 c717b4f01c4cba4882de9edc423a8c2cad5da155..bf7eb56ebed4d8d13aba45358333dae9e7f24cae 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 fae23d544a3a115eb6b7c78f76fd2c27a3742d9c..70bafa1e8fb2cb46d8f63d96d698e0a396bf564c 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 37f036eeb3518b553f0f376e43c7f100ec4c2bbd..f0e71f927494a02e1dc261fa0fffccd17bcea14c 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 0000000000000000000000000000000000000000..501ca2b4a07db3009f267d917ab6640f61aa318a --- /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 0000000000000000000000000000000000000000..4ec411000ef9294972a162a61edd78498b30b2cb --- /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 f19cc13e000aa310aa4b5f59b04c385a75ef1b54..ba0cd404f38d1991edd31d74b75b1989b45b9a15 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 8316e7799bb95b8ef67d3832d3346a9c1d07fc65..c29546b11217df367146156eb0596ffd53a8696d 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 2fa477f69236ca055b6c875ee22f85d1999a89e2..eedc09035002eba3180dd2aaa4615da456ab8553 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 36c0e3a80c444f24e5f746de7342ddc79eb1c95d..59b821ca72e9128ea8a79487273e76e1aaed7cfb 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 c8ab1702ef360e4aa56d416baa38a23e00eb5fb1..e2be4261562893fcba3dfae39387c7b242dd973b 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 0e9738f451fec75353843320ce19eaa6a5f1fd2d..ecde91eb864e00ea11929a38d80991a587f060d7 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 2e1b664dcf91870df5cbfe9580aaf247b18d4f8d..ef0c92bd76af7a165e487288c70c39872ceb39c6 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 e984b26233d73191f7d606edbb41cd7f2b330d9f..5bb64340d865851653c8f8ed48d7606e4e3a4505 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 9738deba3bd892efc670d6592f72d3a02662ba0c..777a31cbbd7e00b82b5a357b9bf67a154cec810d 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 0000000000000000000000000000000000000000..ffeaea4f55df74e4fb2123e68e13bc9ee076892d --- /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 f7cdf94007320d114fffebc15f628e13ef12bf4a..163e2106d6661130c29d5796f8c117a86dc4b854 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 9a72e40996d3ff4c603a8affbcdc19ca990b3d7a..3ac8d4fc5695d9adace09f2efcd63f6e0f290a2e 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 6b50299c12c623d810eaed082d60bda5cb3d11ab..cc0d151df705a5b50c2419fab54eca4f48dd5415 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 0000000000000000000000000000000000000000..7463cf95a1616a2fbaf93af37faafeab5726dc60 --- /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 0000000000000000000000000000000000000000..1601473c00f1312ec4166bb97f36145cb30de37e --- /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 d37929cf0c7c7e5a8cd7066a20023775c2c9a8cb..6f2d582c89c14f90d42d9404c5d6e7fc7ce99d8c 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 d2b2a57c727d6ffc19b568815de415e840fe14ea..1dbcff2ba796675821ed3ca5a482719ae2028e7c 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 ed688fac58961f0a86f77ba63f713bfb521412b7..fb9de63549b7f4078f0cd9d72bc9e0ef69c1790f 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 3627ac3b83bfbc5ba6b31950f30efe9b95a8554b..cc0d09a9e762f1ecc2b96a44b30e4b934aa3153c 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 dcd64e2c5494cc561cd3c1e1ed40c0e2734e8160..20edd9ce20b81d18fde8780ee38b5f2ed760f96f 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 66f457b21d5525b3263dc96cf3340800edfc7771..a046321fcd2889fd70629f5e5cec4115c39e6dd6 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 7b6d2d49a4f4a9ec1dfa19aaaf7930fcdb702523..8686bcf46cfecaac4364d3e87c9ca230212e5e0f 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 2de2f297b415fde78e888ac36c59f7fa4a30a51a..672e2581511e881fbe73a3d6f782dd3c40d5291d 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 adb33529536ae0e10e907fdfc12ceaf37fd92242..21fb1b0a2d4d8cdcdb09365ba30914047f84b588 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 2a3f66dfd5880e58e3c6cad5fa70c9c7db788b93..44436096d832435dfaef9ca87235a28ae0c4bc89 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 03ef760eac7066bec26823abfec4a24a1cc8998a..0000000000000000000000000000000000000000 --- 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 3f8f38a1a225b480a0eea4590619482d36ddda73..0000000000000000000000000000000000000000 --- 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 e7cbf8f2f97e1dbac3f67a267dec037837de813e..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..22e9ed07fe7c3f864ed7a323578e4216f3ba45f7 --- /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 0295ac777f5a8b537b4b26ef591b0ba6cdcf8055..0000000000000000000000000000000000000000 --- 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 6f376da7f88d67cf557938c2adcc9a49cef2de6d..0000000000000000000000000000000000000000 --- 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 a9806cc98308f551d57ba59c17cf399bbe6f5e6e..2c9632cf72d0f7eb9ef9dfb53aedc824c147e274 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 c847c52b4add720b6bfe214850f23ac3c1cc4434..43a24b1298ca62dca815b9f6c87cfe8bd6487d29 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 caa581092bceea354643c6f9bdf2d5b8629b9330..5f79ea5bdf42cbb002094b51ebb3322604255268 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 9ede33d440777e86cd422cb59d78c8adae00497b..1884f3e894028666a7d921987691584b8c320fc8 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 46f40839832a24fddba58aa803da6081d0ea6ddd..525540058dff96495542e6cfa612460129296df7 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 773aae35cf9ae4695a7ef589db080e547f2a0d3c..6c4f437bbdbe25aabc12fbd30d1083b49fde9845 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 d5ddb0cb9a2cc639e5b847a9d5e9d3a7d72e79c0..73af387f3f1152acc4d7dd43716d48707c00517d 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 50385b21d8b67e1969dccd86fd4986d92f13a069..83db10f91eeb10b339c369a3ef78a95eae1c224f 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 bec5e36af1adf4659ed205071045654b373cf805..e270f6efa7f3a57d7b80c9850ab7ee13c011d5f0 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 645109741c63ef38be7aaf288b340747ab8ddaca..5ddb4144d87d0012f6d537f328165d460155e86b 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 88cbf1c5002a498880bc43e4ba32f6efb30a8561..c275ed3b4420575da4a8b6de458828df9b5d82f6 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 0000000000000000000000000000000000000000..e3a1237a02dc163730654d848291eef9526811ae --- /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 0000000000000000000000000000000000000000..78555138658cc2fa77b01573d0c9f6c4390d1ab3 --- /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 6d19b5ba4dd076f9af649f1c35c2a08766c2efbf..34fa3c40f74abe10638aeeaa71c9179587ddefbe 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 70c5b615bef93cee85c8c2023f981115e0ce59a0..1801ad8e6e8aa8a14c8941c70b083c7b422eb698 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 0000000000000000000000000000000000000000..ab0dae15f5a957cda9f3a17c00d847d2e0a871f9 --- /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 1a7abe7c06fe29c051220ce3c4a4494f3a005048..d27fcaf8ddb3535ad6a9f00e6d39571be018f51a 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 203ec16261552bace4e9079d812596260c5ad063..34eb0f35838cc6e4cb7feeef9378482847f64933 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 b4b568ef578ccadff86b63a5ed9b613d71babaa4..7eb33a8f1be9c454ae2eaad42c598ab772e33337 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 284f510d564fc2b305ae9e39c7d8b8f9be70b788..7982e9a1ace69e0fc3e87d758a53f44c2c3879d9 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 0ede27560313e90ccf794d23a9e1b131ff11470f..4dbac3f9a576ff6d1b7baec2e41b162ceef88f4c 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 e423d1d171bebdc3cdec805fb6fe73cf90086a67..0cc1ac5f356ac2af4522b4a5c153ba066cc51638 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 64f206403d47ba75131d57e4561efa7f8c207a3c..66ab2d74750b28965d177c923cac65998ad0b76f 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 5b61d944c7fda4b49df1a711b853e537ca6c5d93..4914a8af0a08d8e9e87be48d756978053646bfb6 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 30b161f2bc573eda6abf6c9fb662b2798383bf17..d0d78c66ba09f16101c5fa5a1ffeddec4c5b1560 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 54709c2329e8eed779fcde1bbb36fe7fa980fb0e..9d415b5dde9d77f3f68f57d7b339c0847f4cd2e4 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 85acb90086589d455f310c16f7b33992d0f195ee..2f9893c47851d1dfb9ae970f1421c5efad7e91b8 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 101a712fdcec2a0bbaca722bdc4da154ff29c5b0..537027244978dd440914a33cd877fea928907f76 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 8997f5abbce64db9e04c9c475c59fb5872fd4689..cf174e517e0cfb399018c508ea759c11563ed378 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 d7195a21b03b341d9fdb8fe8e0c46a3b892811af..4c5c2ce325012e73f6d4413ccf7503c899838e37 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 086c14c5a2dec36f28c9f341c0a91a9fa565470f..99b4efa9dfbbcfebcc474e20c5e26d9691d7727d 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 9d05f56746d81ad68271476b10c6e9a81dae8e77..00f70549b10f6125b027a8879685c1e22e516f8f 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 becfc8c2c8d5fffa4045ec9ce48f4e40e908c5e9..3710f83e082aaa7a58de7dc3673558f631ec8ca1 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 7531933b2dff0516d18412ec3ca53474b47a6ec5..ae288284d6a51e9dfe5983804182006784d155f8 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 b2ca7725466347bd3c96496bfad6dbb72c898ebd..b1c8e110e98373d950f3aad7308f3d3824c7cbe4 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 d295f990f4d9319d7ad6e3593efcade4fc8457ab..9384f059cd90889ae1f8caf858e54d42a1d2285c 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 26c4be7dfa0aef0698966de67a0b7e6afa0df509..436b43dde9411d84894930b3c448d751b31269e6 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 7fa171d49a086f4a24f0d31a326ce88f42e9c055..a15e9e0fb44336c92219dcb53c01898897e979ef 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 4ec4b03fd66ad6f514ab657fc96d1f61b4e5e8d5..5a311fb51719a98bef6d155fb881290c16a76766 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 10a05148b81c5c9cd9edc9c3b7ff2ff7d9915301..b8d5713dd7a2926b8ea1ea138ecc75dd7b0472b7 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 60901b588c010bd764f371d5dfe12a1ea74e3e35..3aebae36cc2a73ff6b0564621ed9b12ae61ee5dc 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 0000000000000000000000000000000000000000..81f88ae2a85e541ac21d4f35fafdc61233952a5d --- /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 0590c8061a95b990d26be4198043a395f1679b91..f517f7312cabe27727d37192a7fc4e3a1595a046 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 5107fa87e7bb2d1706b252cb5ac3a1ed21e4fe76..7f73684d7481c0cab596a8daed4c93d23dfdd6a5 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 201386674b3f495599f61972cfb08cd59ac51980..f95a7d478d989ee1945d1d3b5ea4842b7c49b59c 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 2692d6733ce2c860616f7aba67f3f3c0cfdeab11..bff816e6a223ce57d72870551359b5e0ae73de86 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 33774f71a85ae6c60bfddd91abfc2945777d5dfa..8e27581fa00a0f0a26dd8986b94b7e86ee98e79e 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 b9127b680b890a44fe51eb3f4fbd9cef8fcea36f..ee990a34a47c1b76dde6e2c6bd4a98f284c3d6f8 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 4e45a2aa4c028395b2b80c1bef0d7d36ff147b23..685ed40df336a70747aea34dad6e63bbd0e0097a 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 2b286f9fda2186a67ff32cb40096994d2158d99e..87791e78e338080735ee20966ff68c1d66b99652 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 0000000000000000000000000000000000000000..036fe7d94619bc4c6ed14d3afb529e210a897e7c --- /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 0000000000000000000000000000000000000000..719bb9f59b9bee45acd64fb498f83347ed774311 --- /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 078823f755409cfc1d9e659ecf794d5e37791b49..e2d496b48d2a966a89126db3e0027e3c2f68aa26 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 a37173910e40db792db0c1aee2fe5a97b4843293..8b6d56a24670a15bf6d9f6bfa601cf3db3077e17 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 9e4a014af72edb92371579bde7c98570739b41dc..80bf178e7b378b0e13dc2cdf2c01cddf01384da8 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 1f7ced388e36acb7211f77c9dc6c8d82b0479421..3a2833003ae1dd2ef42f79fbc683b7d0bb35d733 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 044dff8ba3dda32494cdbe4bb34eac807b02db93..4ec1466bf5a45d241e1e4efb80ac385fd4c311aa 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 61ec87b3c9365d0dc84ea0aca532a691d4f762be..9c7e232249249d22bda6a3e5823d33ef1e69b9cd 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 38cbb9849255b30d3823acbd2ec7b0d0f0592f8a..b2afaef5ebdb82979aab62db96d06b90d10ff17c 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 4be08a0f8f79c7458d18312bffb65960dfe21e02..9ffbcb230c2c5b8c363df5d0a8d514f77394d2ba 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 6b5db19040b1a2134e14f3d5abcecadb56d96af6..67db12f280af65ce6c4e0fdb8fdbcf1a403ee346 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 a418648f6de3939c9008a8f5ac8988761baf1c10..8b1579ff10aa7fdc071ff1d0e18af4dbc8ed0e40 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 0000000000000000000000000000000000000000..52705bdd5120118ede1d2c6b7cc8cbb31bbda1b4 --- /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 0000000000000000000000000000000000000000..b7fc26953cd454304fa55c6a44fd4e1391c78484 --- /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 2725f3f6bda8af4e78ac0446cee109aa7cca4268..b8fad9bfd42b4dd7a576376688e3e255a555d560 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 b22b22a9c70f644e4e4662eb41093b79431889bb..77bf68adfad935822b83ba27f60bb8dd62b8413f 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 b6ae21f25f2d6cd4ee262dbbec27c149d5ec6211..69329f148fac5250e90ada033af38856232688a4 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 469674dd673ebf31b764fe8241da43eb9e70464c..1b32bb5026bb7a1c5a4a643305cb87366f99b741 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 0000000000000000000000000000000000000000..a04711c59fa349a8843a8003959e64af257e0777 --- /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 0000000000000000000000000000000000000000..b73a5c34855213d13184a63a61c5382f59a9889e --- /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 a3932c7e7ab2a1d8a34c86ef9077eca1db3e7be2..c59af13e45a08796a34936538c794918bb2ffa92 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 0000000000000000000000000000000000000000..25a780f5a0e9f8ba34114f78aa360c0dc9c2df30 --- /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 cbf25ad86d49709de6af8ad232343cd6e5193cfc..bda6b165755fb8f45439f79d493b86aa552680e1 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 ade9cd79699fb849e09449add201d28d2a9d03aa..4e10f4d42e38ba8f4c28c69a5cbf5224d34caa93 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 90323aa1b0e8f807fc5ffe5d9c39990bccba11e4..b777a117a0ea7f851160653499cc80c9b07ff93b 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 7ed0b82a867aa16c02ec09f2e71ceddb98ed479e..9e12ec2ff4714bc1ae25dea8d9c4098737107f69 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 ff7e3df866e9ae0ed3b34cb93b452dcbc96908ea..76c12269bad30c345afd2139230740c5f39ff6ee 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 68cb71f61dd4f5671db583023f50d05d57323c7d..a7ee176d1c807fb2acc19ae26f833275d824f046 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 fe20c579face407943bc749074a8c561f70c8fc2..a98d95e7d290cdbaa26fd00a26aa648fb7ab6319 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 4f9538bf4e228939eb7f5895c02788945e009aa1..138d56503760a64ac53aca78f1dcce008633631e 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 2c55bf0c10a3305f1f62ea335478d2e871fe011a..a93ca6a59ed82c9c2a3f23a683859e6568896a5b 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 e4f8647dd3a841f5b46f648562069711b5ffdde7..d2756f41071788165464b6b441943a45171b12f8 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 5ccd9b2b0c46452f548e0c63bf31b1abf841435d..46946e5d582e04a580524bd8c92ab713d8a65e58 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 01a2a4650628d7d1a3cd8c7098f03995891f6feb..06addf101562c09eff9d4068a4d8dd87f6dc2ce0 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 4cfa309b093633bf6596c17a6662ef74a5d7ad2c..917f1f4c881f96a19556cba38d30c99c4ff25e45 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 6f0052f4e836209576425849bb76893c1b7e8016..ec57f46d6f498a7e1af2a413a2039653f2f8220c 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 e0ade5adbf1879344138dfe4b057ceb490b60c0f..289532919a636a05e4b6f6f432c0825de6f3fff6 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 8b1e81cf3f36b7b8201101c615f0e67f6c66137a..be916a48a173173c4b00117144af9e33b4faffb2 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 99b7991ba81f670e0656f60e1519ea3ee9539e55..a1537f91fdec91be0e036399cc2229e5446434d1 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 563eb5acfef78b5e00dbfb8938a00c8cce9c083d..25a0f42a63750e2825711cdad5686db75dfdb828 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 0677a75ae51882365d5574d8ac4069c087e2e2e9..bc79cade0d8eec69737c0ae8477d43c7ba566476 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 a3805c7540279104a97a828081c2afe79f0e132e..017a54dce448f12ccebc7c42cafe84368e74413a 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 af3a63b059ff394eb3348ef9b8f964cd00b4b4f9..fae6c7eb443b5b4a192058fd240d8d8cb52f6c05 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 104833b51efe17b636c28031bafedca4247e2b41..982a5acca4c3ada3f5c35797adb52e9ee19d62d6 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 4883025480983d848b368f36d8b3af3fbd9aaf4a..fafd0143e8fa92b5d82f2d7887c5c1116115453e 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 5cab041e313d09aa4ba472ab8a8313e98563aa08..e30d6810196d7fee100062f90dee4bc694ddf2ff 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 d420283edce0449bbc657a6ec0a8420ac37a05f0..b928fbd8017cf410bb5e269e247ea686fb7f79cc 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 0000000000000000000000000000000000000000..0ee8287907cf697ea2ad2981b06bfed77be482c4 --- /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 0000000000000000000000000000000000000000..321a35a011d5512bed81ffa9d0a05f844a4a6e8c --- /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 0000000000000000000000000000000000000000..a0b5c781753db7c64dece2542a67f703a885d7ed --- /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 0000000000000000000000000000000000000000..b6857fbf277b4d2222db11b945ff7a27ad09d052 --- /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 0000000000000000000000000000000000000000..beb7a58720f48b4480c216d46644580c63ec745c --- /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 0000000000000000000000000000000000000000..d625aa8386a91662bd21db75e9ad7e20397ae397 --- /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 ea84d01eeb955a9236aaf75d14c70694d7b00473..0f13da35e51c536c7cc03d0298dd18d9934fbe5f 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 0000000000000000000000000000000000000000..7a1d0e0225623714844f64b39cd1fe50d309526d --- /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 0000000000000000000000000000000000000000..28177a502f8b71f0f02662f75f8c8fd873e3123e --- /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 0000000000000000000000000000000000000000..f920563d3c8e5e009ddfbc3c690cc8df6baa6000 --- /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 a825ea9673fbb33e24af252c7b2bfc794dd771b1..31cd640e0983b3e23ca0c5ee6d2c4cb9e06a47fa 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 f549527574e470dc7e9c795bd5660dab936804e6..41dfcad7fd72e31a40975618f9124eced442869d 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 3ca3942abd0836ff6164137aa2912153fbd232eb..de2734889d7dd759f3eaaa937aa1ebfc5b485c08 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 0cea34edff16ae6dd3eae181400769283594479f..6fb50c6ef7cfb2dfaf6c86de7ef425eab4d38896 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 4a80ea280396e7b5c6faadf6164b34374a5c3f3b..8843fe0bb720ad8d250ac5082629e2ed86d2555c 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 fd8f9af4176dba3e164dab39258b1a8de578a884..032c623e4271aeb57f58b1185786f8a66e4b9143 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 c1add5cab67848a1b207bb8879c936c86a7bfaa8..f060d7de630a5939e74162b45fb94fab6545c0a8 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 f75d7f9b8614e96e787108e11f904463fcfb87c4..f7b842b4a3df61d12c17c927942129e84d22a669 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 72cc373a90c639b74f5f0b9c1b90a4bbfe9d5611..eff6b77a08687655182b9be505b0fdb20714f27e 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 9d040a73fce405bed3b880c2c835fa2ba386d740..65ddaf4a2f7a114aad67a8a368a4de742b059712 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 7a4a19cb2bfaf788e679f38ef788dc09bf336df2..d1a0b2591bc578c72eba2004a20c8baa8c98090d 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 0000000000000000000000000000000000000000..b4d18a4c1429edd1d9cffa185b1d21dc4e4dcaeb --- /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 4bcfb6a3ea287911c12b087aab224e576bfefa88..6a05b4f65602c1aa08795e2301ea1ad87eef5f89 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 0000000000000000000000000000000000000000..921343e3f61d27e696669795aad87bd51cddbd50 --- /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 0000000000000000000000000000000000000000..29c7469da464cc126389584b16012bce4e4180e9 --- /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 8adc450c8861b4d2f8a8675917bc09a6c20423c1..eec7102c08d9efb829a19c39ac7a11c31c3451ff 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 eb24668d08183209bf388902c741b12eb69cd2f1..8e42ae61c53f7486615517c72da3fa5687daed0a 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 466b52749614ec6aed5f71ed14d05354bad0f078..77c92404fa0907706e06db75b01dee01d3ec7c67 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 e99fe6be77bafd33f4c33522e2eebec274283044..fab9857a9f8fdadb8187d63480d42b6ca5739115 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 7f2b0d140b8035032ce509dd921aa3647c983f36..84ee6eb5e0dbcd63e865ca6c45f361149b459832 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 332020682b4f50f8217781c462de8b70090d2387..5e0cafb49b7c7923ad0575d0c13c09b051633cc3 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 484cea5ac0bfbb3fb5160ec399a37136948baa29..b592a0d2d75e1114c1a668b711e65ef03a566993 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 cce04cbb09fb39c4d5d12c5ee8169a547737dbf4..fe441b4700677bbf197f676a2fbe408f389b371b 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 c659a916a9ab9ba7c3694b8f5a9be75979fe6d5c..3d34656df783f987ad05211ebaf610ed52366b36 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 d2b7e9f79b4d82ca422e92688e0cc31f9de58daa..943039f24785b4f6ca926770917961889875a9b5 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 034abc2563bbc40104aa7e37748cd35e63094ab9..fe445aa02b1f8a36a41c039456a535e1e8975af2 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 e5a26bc68fcf527db620a0891d5f327d0d91551d..11518754e30451c98df14fb4b8ef452d6b617bf8 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 a1a7a33231fed0059f1f7279dc2b534181f24c2e..0000000000000000000000000000000000000000 --- 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 cf1628be9c56f74aef1d2d637ff28e04ee69938d..0000000000000000000000000000000000000000 --- 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 b245c3e1f998e2bd006516620e37454d51cd98da..0000000000000000000000000000000000000000 --- 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 6b8e5aac41c2dd629503bf0c616a592122c5bc8d..5c117b1d1a12ecbe4deead2f25d5b7f37dfcb4c7 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 78b21cbcf61638270dca57ee8e66da4be1cf28a9..9bb83f5b0a5c87cf70911056502a0c0676b11483 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 2612f63460c9102c553dc1c26b8c690888882910..073dd5173c12ad9b011d5261174081cdea4faf6e 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 d8b6aecde6f37dcc73353396cd1059db732bda9a..23a9ed8b1f7843a4564316034ddd81e1353abc62 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 024ca12e63267738741006534db5e994986fcdc4..a4a7690ee0abed1dbd109c131bbdd9232ae42dc7 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 96caae50c39c237ee0b5b2255c3f3dc87350c7a8..7ccb126dabb99ac19012bb3e157bfedc3d941aba 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 70c62550f21b9855e85b1ff6d4d1a298df1d0d5e..687729fb2e27f049b54320e2987ef846b5f86686 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 de67136846e5bba5f37db103f2f19e97bdf9bedb..61420e4fbf5504ca6b6a962c144fee2b42526612 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 e2875e8c594ffd1c53862e93be9acbc0bfdd7bd9..99c8732ea8a0bd93751778140b8b8d824c113d56 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 9f76c2773ca9e1f2c6ecd22a4e75f6efe0c1dacc..bed2b1ccc361bfaeb5d8bddebc1cd0991e66ec02 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 0000000000000000000000000000000000000000..43f0500495771c8deaab5c297354431556a6c803 --- /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 0000000000000000000000000000000000000000..61bb98a0a4cb6d3c92d35e6d2adbbaf12c9c8d75 --- /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 0000000000000000000000000000000000000000..abd5eda3a5e23e332bac32180766da756def5c89 --- /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 0e47880bb52661f859dbcd851498d11d094b0e15..69fed9536e70e6d21aa8cf11129abbe583c032a1 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 4f99fb87bb5929318b8f6077a265edafddf27c4d..b816d7e9466f63e25caad2c44f84cb28c340f0af 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 cd8b5868fdc793f50b66521529475f3e9e0fdad7..2b52844875a5eff41c61b1ea5ea8cfc42a64c82c 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 699df8567dd3b66a0f2aed39256c26b4a0199192..4ab3a938c44818d46bee26e210540c98c6a428a8 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 e5ccf15dd2e89dce3951f487ea7c555166038902..2aae03849694e2b8b2cf064d9b395f5d4036e3c4 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 50a072059f085487f121ef1218669f44ed6ada91..52eaa22a3d8d81281119d885d5f7de27e67a2546 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 6c60ee691e44216293c05283f2887537e4a2f8db..286df44d10146f78602905f9d13cfbba42190f59 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 5cf53b523286864182554467b725cab378ac450e..78e957e89430b874fd7792e8b931591f13d5a19c 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 98a16870f546e026d0a6a99a112299d011e29c8f..3250327c9b149da067f930302d4560dc09b0980a 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 ecf4d37d96086f8af939296595d9f983cb64787d..b6c8321c7128e70af6f9427de53b9b5390ffb83f 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 442cd9a90e824b61a2118f538504762656d5490e..a5e47995a41d2d64e45e7118441ac060b50c139c 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 530bb8c3c5bd59539501aa20ed1097ce6128f2ef..202899566218dd681fba1d71fadaf55d21fc6887 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 8b139727e944966e0149a4e8e5136840f10fbda7..57d6d0e0fe486bfbaf3195caccff61e65f6ee02e 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 3d2c9070bf1e1e114d07d4fb495ef30a6435bfdf..06ab4a0908af055e9143addf9700958be07a69ca 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 85feba745dba7203e496590b9acc98dfe23f4ce6..54bc8c1a1c4679466e9bf7d09d87a94a69cf8bc4 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 0382710e01bff25baccec591a887b38e76c7fba1..3ecc5b80d44274a5239feff1f0c3691648f2a888 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 bdbcfd55d181c93ed656f8d0c5e0d936baf0d824..512f170167a221e3113a3a2e012b9f0c3aeb8e95 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 24454cc4994303c9720ed55c9ae7a23aeebdce98..77b7a9d205aadc6321de2cb8a7632d7f74f443bb 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 ad009827735c0b9dd785d5b3354280f2d5da10ec..5f4a8de17922f46ece7a0d9e84dd4618cbf7bde7 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 21fa1dec00233bff2a84191aef9c00c9495dbeaa..987e38dbdc7d181fa7bf06e923a8e203cfba6bab 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 53485b60a7fcffd2b67521e3cdfe978db2916383..7e28ead22dd21bbbcdf055d6d3319299d7182b3d 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 af68f02e2fb4d84c147b4e03164e0383919327cd..941d74b776f8deffccb1242527cfb2c7674ea33e 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 b9bae301def54eb6faf0b577985475877c8a224e..c51802ea2fd5dbb89eb556081281aeaa20856108 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 ab7336c705ba99a13e018ba88ddb6ca96019b327..0a84709dc2c7dd4297b6119077580973638e1cee 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 12da259fe46ff562d3efd838a377ca0f123173ee..6d227ccf9c9e48b84f7d94ce7a5131222a3db827 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 3820449b611f1ff69bd189454d12e4b789184f58..423e1bf2c01a6dc48655200b8f433537d7875a26 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 7a411f74dbb0aad4ddf75d13c83a07cca5200b3e..3db8841ecca3867c1b1e27366961920cf82faebb 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 8e3203325601f5b21a0056331500a5434cd6106d..2ab3f4a256bf0173e4f4edfe510fe24f24ddb628 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 e26669f836bf059ad18da014e333572069c5efd5..3004438c1803ac1cf3ff7c2639963afb01de3654 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 373c2cd737dfb1c5a97db9c220d56fffbdeb3ae3..d90d800ce853f763eed570461512177b17b8c815 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 641380edebf4dab32a7139e66d26ab5f468b6ef9..b6aad2235166c0df0938ac4e32b3f6522d42d3ef 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 c3f19189a2a5fc6dd48cf08b577feafb3c9ab7e4..169d53a2ac6ba75eac8f50f6fece5553254197e7 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 eedaeb4b6896ebb410675754eb53baa27e5a2c46..763df07e9986bdf291557016da63070ab3e0488c 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 b3d4f2180a6e6f2392e8fcfc6e73915600c38abd..81262789e83009d7b3d7ef6fcde2a367ca41cdc7 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 48e7f967919aef29ab0f849c6764f032a629ae9a..50575a8ac0de8987ec10d2c65d9d512932549d77 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 289163a4a92611c38939c3f45a8c30d41246fa78..731f6c7988b31bec978e6ad9e107b28c3251c922 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 f9510f5f1e2c8845575742e5f0551350ac8a6eb1..04839b61ebe6afe29d88c8dcbe38f1c35d94f287 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 36731af1b5456786d381e75b8678221d0edbd668..1b89a5e60c8ca92540f0a14040a528c82f1b2706 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 0000000000000000000000000000000000000000..29da8bfdc60d750879ecf6b3c733d53e4c0a3b1d --- /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 0000000000000000000000000000000000000000..73bb7cf5b7702a12ef260b397a2d6efb004421da --- /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 b0882b4ef6a1994791e6ed0134eabe5cf6e6bb74..66a749b43b80ca980ae2dd1ecbcf029f327041bd 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 c5d8d009378a580e7e4f2db9ae65f54c02acbf73..843b1739ada05d8365cefbdec568085a81f45569 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 ad02ec7031c463998e10bd50748def2babfca465..03dfd6d2c65ad5f49b6f78092b5d2ccb9c372185 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 0df60c0c42323193bd581b081d8bebf60c22ff15..c082224d36b54d12d37c8780126e07969e6a9916 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 a1db9455baed05933ddbbe0c28fe84c4360af3ed..e055d5e676c5a70024dfb1ccba59b7b3e615c470 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 9eb0ea8f697ba3b642e6196ede5c6e4195e6f0f6..9cc31ff300da0bcd8462151b8ba6245029d58021 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 3c77735375802f732a28c266ef7700d14d39b0cd..0f40f3f274a5c2ac642d611beaf75793ae2ac8da 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 947c5632c671a1db334e4d4004b34ca9965e8fdc..314c938cb9d9668dcb54fa526b9337d41e99d7a1 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 c0d1f875d6264ff34a573907ae822ae1f621fcf1..ed92a27f0a34659f21485c80497b1db8b5e88770 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 d8859f6e5e767623afd4fa03d6c85185cad8516d..4fde9929e153d305b534d2b6110b509a0f4f5502 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 e14a62d4efae575695bc000a39651bd123f5e40a..4e08be4a30207628e9838af7602b20ffe1aed6c8 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 e2fcca261ce7e07f4ade137652a5eaa1354a9ab1..066fa2ab6e87c8990ef62a6104ea7d135d864cc0 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 032b371aa6a7db7c778e45ec4769bbf6188c8b66..c57d93f721defc708269029f9ee578ecad851db8 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 c06cb2a2d5fd3fddafe2c997899c98242b9ef324..0530f77eb254f31a2c864b0734d3a879f3d3455b 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 2ecb5273c3b2923395564deba00203045b16f564..4c32bf8dff896c08530e8acc55fe8d233f74adf0 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 3ab051d1a48f05a0c4a0957038121b98cff75cd4..9e572bfbe5717e1cdfe41559f9d756fec987d4ee 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 33c43e2f3817ec28ac97016688297947ab5fb71d..6c7d9813c7100c74ccb15835f1047d75fb2e5c28 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 0000000000000000000000000000000000000000..0279803b758938fc0f2acd29769402e11b340160 --- /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 4545930e4d72491ca805cfa5d165e5464b7f322e..46e0e178c3fd4664749a71527085dee5b58cfe0a 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 59bae7fc7831be02823ccea5987ae5db88c25eaa..5c57b65fb3dd818c47bed5e6e17e7707550bae9b 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 d604c5ed5680c981f64b633909a909c06e23d28c..3660883263732007bdced753c98dce29f20fbb70 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 493fd23113217cb02d4134d1e28ca7d09871ce56..96e6afb4d4360b093a9eaa551e8f85dea2d2ca87 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 fad2479cfa19201c63f6c82281409fb8b948f593..5e97108bc8476f7b48c82a8fa097ec3fe4d3a64e 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 6bcf19de44704b67232534c97f95a455f2356405..22cd2e2bcc6f803214339766c4434d92f03969a8 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 7384de456036a03608df9dff18acf4636f7a0b3a..631f4998feb652ef483a05ec7a647f9e45f4b7a5 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 163fb8a7d21da4d6162cd34ad6af03445246d3c2..d9da4fd1ba46e2b93e26630ec7b4388e1080a1d7 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 6f98780f32f6b86a868ade58fb6d3990ae694e1c..1a90c9b58b6bbf1912bc61506ff20b3b89eb396d 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 89e0314cfd5471c3487bff03c5c65b5bc1e7e64e..43a94c5624c56932c010407c70fad6adfc516746 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 2fa113ed01a0be14c51bb8d63abe6e9ad6fac940..8385f278bde590cb83390abb76c21b2696ceed49 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 1c8e0b3876dc88b9f0af1c49539d3c93eca11fe8..3fc512cb9a9a72f3c96d30ad651ec51c65ae6e26 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 ba762136060049c745aa095cb71ec0a89395453b..222763df3ebd8f250812917e42e5935d972aee15 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 a3724d42ca0be32ceaf374c426d72091155ee7a6..d6708192dc5a4c348bedb6f2b65c61151c9c25a8 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 0000000000000000000000000000000000000000..f1921835c4643f6694575bbc8cc0a2e51999025b --- /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 70d6b9f5ef208cb3e4d86fa247321a91e6a86794..708e975ae77ead62f1cd7ac5ac15d4e22929c8bf 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 0fbb38fb37d064456e699928752c1914aa7c7697..ed70dca1f44f98d7e40e373e61a37a88509840ba 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 d6db799e2b9b1497edf4e4619736f36dd3e831ab..721fb6eae2779781810c19ab3029ebda315f377d 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 8971a53f7e44b43cabf90eda747314c12584cdc6..9371395138d9320fcb0632436e783ca31e61ebb9 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 05127e4aa165a053cd4829fcc8d94f186a7330b9..3e0e277bae694259a234ad62f855c0ca0570d643 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 54eebe80ecd64cf021a46fc52f7bf2340b80dcb9..0662cfc0aa7a45243dd1a2f82c333310ba525f61 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 826b2d02fa98209ed2a3194b81ec684f1b4df0fd..87d2870eb8fb0f5294308827ccf7b794004476ba 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 7c731dea201b4002fcb57189ce37175623f45635..ff007bddab1cc23b8e425c18ba0bbb49f12a69e7 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 9e44f05c8cec2bf90c2d7247bf1b19b1ca83d7bd..b677415ad6326d40f5b2ceeba3cbfbfe7c529e13 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 311dbd894b581083b1e1fed8ff1ae8819ae6bae0..ac31b5a5432459098e23fddf83607556f05dc1ec 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 72011f195e4beed21c7b9cb4c294c462c0bb7f4f..1da7304c456fcc4dba26d3fee7a7284169a650ee 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 44ff963f3a330061d6bc6a434420f22f02ef6801..26a465a99c5ede5a3b7ee6e0d357ea68132b3e09 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 e72286610c4eb8f67596de6e8bc7bb4536131404..c1e6fed16e0bc4fb73d57e9d74784f6372792992 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 ff41921d9033312f5c7d8107b77476729d6558a2..604453edde60ae43b768799413098437b60d7a8a 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 043b68cb2148648a08ca60a9b1b45082313d2677..f7cad4a98465840c2f9c7fbb63ae4066a182ebc0 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 d1af016e32a08f552c7f5dc50cefccb18cadad71..a108a10fdcbd11b81e4a76cf88d2e88d6f3f50aa 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 e4fc9c0c0c15db758d451fde60f966ed1cab049b..7b8554fa817fd8e44a6d3cb24e0b37532c1eeb1d 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 5b950fdb35b04ea2b8de962b60d53b717ff6f283..9f0d5894566a971cdab0069415e5a067a3ca0f74 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 64d40641969dca22f87b5885a55253c95bd9022d..20f1ca0a4ddc1a69f9120857bb028659a4de0486 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 8830cc5b523be9bd9d03ec5dd5280d34cfb04e66..e036952fcf67216861078889c844f53c37e253d0 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 f1b713c62d366805b4fc5252d67ddf3b6deacd15..f551d53565f36feb3522e5502112c7dc1b40b705 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 ce6c014192ef32f9f73407bab8a8e8cd370fb76b..81714de2c42420cd8263b027e82b825e9c816c18 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 af1a52311cfeca9ef11de1976ae861311466255e..3e8fd020d416df2ccc678d07474e8a1e71765d13 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 75d6161df414613d283b98ed0207a1757840c435..0368fe0b9a2c9d2d9f341294b7fc391ab125436c 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 4ba4b6b0fec064c326f2c5a9512c9ea8a962d2f2..b93947d83949480c6be4ec924efeb1a2009eb6df 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 d56ad3bd36072d8931a1606025ed2fae0b70ed2b..76811cda2c7e2e896c7c59a691ca69f478484dae 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 f1bc24f8d9a6f649060f1df36d45c46010672961..67dabe8e779c23a473cbe6cb552c74416885f32e 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 638fa06aba600e0c8f9a967c158b1bdf22574ad7..4d92c38f16386b505fe9114a4ad222fae1110b9b 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 233570ddabab70d2c482aa7d0519c6578d7c09fc..1a204c702a87c6808956af24ab606dc6b45487be 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 6f522afca8fd4b1d1cff61bb40bac9d20b205eaa..2c5d6309368a9c7d1ffe44fe0be90e6e0bea595e 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 c5c0b2e2fc8430e502925202d7d807aa824dc135..52c01d001272da1af00597644d0d2c02d6735313 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 29f724f00827c446ad10ad46b14b1484ed51f5f3..abde628f4bea49810496f3f2afbb064e87af61e6 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 98d206ad9422b8928d0e76b8abda732bc72fd2c0..d6bc0b8520990c7aed4ec8387b6f5aca1e552fc6 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 48caa971a9bdad8bd4d3bf67c640834799a5db8a..13e4308301bd059bf5c44a479e011d5b4f75c8dc 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 3a9cd2c431e41616544bc27293e5d09753f2f9be..e4d74ed4775b74c7dd5c676e0face73cc7f9eea4 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 e1e341ef1ab4db38a731839dd33f0ce8654caaeb..35c9434c32e8b25317fd5553018a4a2234f29de0 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 a6aeac83452c0c1c2033351f836af9b7cc476a2c..e40561f301acd42fbf006721beab0b3dc7043110 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 ff1d33c8504aad8260cc31fbd2a728b4af59452d..c82325e7629c8c49cf31d39eb57bc6e079599847 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 c67f934351be7188ef10044e73262f053355c25e..5e77a997ddaac184f1718eba6182c356f9785515 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 126e819b630d1338853a48e6e4505bcba45a87bc..938054214c280616c44ec452fd8e486098b6d5bd 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 9883553eaf6cefeb9b5b76de3a83d6fc625f92df..1d9e69a15ad9a8a04fdfd1b6092e7f7b6d595683 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 85e600badfa4a4d0c8a11bb5ded58bbf999d503d..fd31663ca145455e74629b3dcc38ecb02aeef59b 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 a26f46a5ede4d3273c60c96618f85c38a5c4e06f..4b12ee46eb505843c751cccd9361b56b62b7d3b5 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 5ca434816de9c0e8dd03ba03c0508c5a7b0f8a0c..c6aae962d775bc0505b8a94375966c50a1f8cca3 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 7b9d4cbdf150e5e4f40ca14d08b15d3ecd2047af..3abd7dc055192b8e0f05504cd78e89687df42391 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 8a382178d851a105d166c414475bb9bc8f516662..2e228b57c40ff2b1eacd2f572fab3081e61798a1 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 e1b0411778449b57194eee65ea0f0eb93b13bf0e..790ef0387cd8d402795b5a311b29f57accf24aff 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 a166b631df781b1160259c57fcb0d48efa8a4277..e3f8421e4f5657a80de9d74c443e9a5e2ed1dcc7 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 5b36f49e7e8fc6816025f5792bf876fa3e822dcb..1141f09e2b0fb217003a6bd0e6f400b105bd0bf1 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 ff7df9b2f471f8e022199189aa75b23a89f22cd2..09b97558cf1048486c21c1db29a90bc093945c5a 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 ab270173e01197b15bf823e3862bcf512786dbbe..87d41e50bcb7e5a00067ca2405947c4c1bb72ecc 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 e31f754d85b33a85f6e028d7382c34cbc2bb1829..1a152faff3a08646ea46f42a9d8e19021e883c51 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 474fc67275cb6ac064ed70504289f27db2802dfa..df108933513a36f57ba01051a421c51fbcab19d4 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 4e4de9a96a781c93d4b1e8b95c5a4a7dbfc6556f..913ec49b8e83420985ebba3d2db7ee4ec4b4ada0 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 6d03993545291e5f1d8b8880a675c1e740eebe63..2873f8d66f992334b52ce2ee120707a4be60630e 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 8af5cf7b540a6108b7e600bbcf46f455d27395b7..210434ae2264eeff07270d5f3d9dd7c02284fcfe 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 f748f494d051632c49378c26b63fedbdb84c52e1..5736f89b0e37be09c606c81e58d172d3edbe8069 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 6f90f9e88b702e29b03c2a186aafb3bd9530329d..84bfdf89f0d1f68f360ddeb87ef46353c351a53e 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 53dca7c0865dcd170ab0d15b61b6133488d03354..e0aa2a49aae93801a93f863ad91b11ef679a1a8c 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 89aba510274fac5c7822e94aa5a1b3cbb560bab2..a08091f435e08ff7fbb2ac2f1f75405045d9cee9 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 3fa168f84f918e56ed2c975cf30e8e4c68c893cc..df459eba2554adaffa79292cc99158502342016f 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 ad9736acd2a30345b48f017668a08358553d9930..a5674814e60e9386b709e23cf33a2c62cb2332b7 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 6d680e9b67a934d7fe9955136995d302328dc2a0..c5c787b9fe78c13298967f61b5d66ed7dd81e199 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 04f0eddb940408f9f240e2fc8c73d8de6a198c0c..a4216bfd467ad81ceed469286e628fe310a6618a 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 0354df1a49d5271147f41993059de1ba72cbbef4..9f34b9c32032ddb0a44e4b7ea7e98de573f11d9b 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 3d14c4440033dac13574a36cd675bf486f30b63d..42726a694a867810cca095d042714a2851d924e1 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 70148fbe2f3f67f8683c03cefa992c45c2210345..d248aa704ab01d80479eea1a745f439f236b4077 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 d506caf020a86b1f3ef4fac5e630f0ce3e92829a..83045c8150aacb024a0517364a108316133c69fd 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 67cfe9e1b1a122c0baca805776cd09e811f50b7a..80efefbf5412fee49978e82be24fcab743688be1 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 a299bc4221c50750fb72c8dda87b756b7ec4c79c..c475bdbb61a75df6979d94cb86657f05cfc14ba3 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 fec302f2ebdb32f1bc60922c9a7f3b14b3cb00c7..9024cd7b4e101e36d3dcff6237d9caf10e7fcf65 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 ab224796957c0552c39e5b57d471b26399573ca6..60216893494c268727c009c253b2abdaf8f6fa2f 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 2ad5f8970d53322652c73119e51ab99536f787d1..c2a8e9c49ab88e4e846470406e9c1050a8b3f727 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 c90557a38b6010cd4a7a2a3e828b72084d57ee59..94a23a93c09652e125bc7ee8aa158aa231991ba6 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 a365f36351f78a4377c9be819ab825a0940a5f39..9a06b52410b8d309997aa926d3a0638aafe1fe38 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 869098289462c86820a9af298eeddda25c24c050..dd9cc44925d5ed897f1603337bde9b6683d5f79c 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 36e06f4ad1954c6505126da77067694a6bf935c0..58ed0171c758e606d5a9799d6fb60edb6d6f716b 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 c3b8d676bbe7411e0f75170500717523298a4d05..a4118a4c8344af3f455078528eeb4bb751430af4 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 0e6d432bf63ada79049ad4193515e03274676575..1b617c325d75abaa917800061d636fb01bad36a3 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 0000000000000000000000000000000000000000..d9f3e54975690e4305b503396c79ac5ada9d3ea8 --- /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 58ffe2a8107ac0a59324298f572f46e60bac8806..45469db25b9024b260b171a5bf370ce39cd0d5fd 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 3b001463e15c25071ffd0148dbeffa623699d3ec..8a9efae50d2b1503ce64b3a902d487a8b74ae28a 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 8927a71f58969f25fce700f52498055b9c304a07..0acae8c387ca7e065b3a009606df3f2bda8d560d 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 3850e379728bc8b6c83bd7807710fe549cbca060..6599b6a417781c38e16a4006df18db47bdaeb386 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 165e854de9b4c02f42863e8c27e104db904fa52e..44d7c37abb8e2499107a548ae117ceece11f2ffd 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 9c9bc0888678fd164966e283c94229c0340473d9..4a2a668af3487c59554ec2c40aed441a810f053f 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 b0c0b301e7ad2e0723ebe7f22f966d872861161c..51ade5671632d1beab252d88e72f87cbeecad842 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 a1f283c8a3bbdd3398966b3e4654f4ac2624a8a5..412625067973e2339af38f981eb56ea1e1b441e2 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 d05864e696fa5618cde4e2e7ec62fe750208a8fb..6242db81e24a47b35f94d9273634e3301f51a47a 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 4cca84e3b2dce11cfeb40f864a0e5850a10fbfff..f834712bde3ef1c1807d53601172457adb1252ea 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 0000000000000000000000000000000000000000..780d0b87d84a48f861f99bb5a5c1ed5c93f32266 --- /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 0000000000000000000000000000000000000000..db38ecc79674df317e7075e42a714a533ac63b60 --- /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 0000000000000000000000000000000000000000..459adf2b1f2977f95d2f82c9c0efc23cc33ce283 --- /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 9a91f1a0ffdd2e832de16b19411957dcf7a59b81..d7e374940f32b84fcb01b12853781bb2b49b8c30 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 0000000000000000000000000000000000000000..11ee52e7dbffa89e523c934efb6a047cf83d17e4 --- /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 2440fb057ec78c71b3888941340167cc6900166d..0e1ea95a33e37baa768a0ebc264e650ef331cdc8 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 f856968134f537d0303d700bd6e2709b7bb9bd14..e51ddd8c52e4fff50226f09537c1c3af47cef636 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 0000000000000000000000000000000000000000..56577816c9015f9a826a8f5f7de430399d6055a9 --- /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 73dcabf160bf6c97ee7a61c0d776f9c5caf95150..ee1e3ef179c39449f6fe530dc7fd6d6eb7e99f54 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 daab7b1a216a59d47b2d509016833ddb0d5da388..d3fee9480ced211a446a0bf7b3cec9594cddf5ef 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 e13b2e235fc11e2fecd26b184b7abf19c20c77b9..8064dd715797b4dcfbb3cc33d64659e6dca0e198 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 e84dc1c62771c6068ffd0bc3d89ff19c3cdfaedb..789792002c9d02ef1dafd959ede79d5b4054ae50 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 1ad5811257a51ef72a53accf1fabbb1864dfed06..51ff893546482fda1541f5ad60398560492606d9 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 20d66ecbd5d7219dd67523cfd7278a10ef873d3b..0590ac45b121466373b3267c882453f255f0d8bf 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 69abd0265cfb77edc907a36e2ee338357a41a61e..aeaafeb0008ea74cc1bc071acbad7a4d98d1a4eb 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 d221992d0fadb08a4fb83fa0d72556f9cd97ea94..dc5242b4c1f739629d0573a0bac7564f3bb46b5a 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 af86309c20246ef0ced3eacefc6f47d38b6373f3..443b5716a83d996d98ae5bd387719f08ed0a8fa7 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 20d84adb5f76062c6137094d5bfeb2ecb664478d..0533a1d035d7071bc4bda755e2bdf954bb35c239 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 beccddbbdae829e809b5b4ef222e03b5d4464e5b..7817e67533d50f038c15711fe4830bf308a5f245 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 bd9e3bde633f437690fc4dfacaf170a85f488e5c..2d4c70f5db9cf97018c39b032de1d9b8f4fc07bd 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 ea83b07989928aae8610f031a5d006ed5b163840..7bf52611abd6794e869b0aecd1b77603e4a9a7fc 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 7b35733048688526a55ede20e8c047c06b386d1c..4dabf06278778fcf85506cbe954b87871eb99c30 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 6b1e3e511951fdf1c1fe3250690937aeb3ede667..bf5efb2e2417f3c2f50f445d31b9a518dfe20ea8 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 fc15e4bc5487e94f1e13caaada03654958ae5177..06e3dfaf389c893888c66d544afdf3137a37101c 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 563aca86582d8f8492294f2bb666dda58132d612..190803c495fb25b8f3ef9837fa4b2b06681e8584 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 ffa72db58c1e11c0df6495e010b581db586a8742..16f5fe14a06fbf65d077ddc945d250d494cfdd60 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 de6d22402ca37fbfb8d29e4768bdaed965828861..fb9b7fe97e1108822cae19cb66da1a56ff72d693 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 1504dde3d1dabf66fba91844a6109b4d1da7900b..f5b89bfaf7c96b146614108083d759d68bcec0a1 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 685bff4201c2b3aa7c447a5d410f539cc1606881..09160a8cda5963fb3727d7beca8fb09f6943d828 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 c62089d69c33269b0a5738f32a570ea4ca0abd59..40eccf49ff3883c23a5da9a6cc9721aa8eddd121 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 dc7f01c8d264aafb971aeae9c7b600856d10a7e2..fbcf203212acd2c725004ce1c81f67cfc9881c3a 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 22425ba5493c2cf96e64a9c980fc84adabac57ef..e2e3bc5805496c2012ad2d93d46c5d70d1fd68d6 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 ee301bb298927491b7e0e318e840d949677b5e86..c12c62b0d687f6fd297d17119f6273dce16382bd 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 91f77f733ba82bb345bda2146dd1ee59f5c26a31..743d2994d0b051194d4d741182aff625452cfd76 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 96f6dc0aab3e8b95cb87d799782b39c1e9f93826..fa88458afc2d0fba0bbf7bb0ad24098e83d54fc0 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 a8da23492e89109d9ad37420859955934352da6b..d2e0c3ac66e8706fb387e0cc0bc5f106669b01fe 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 74dd6fb8fe5f83144294c1f72f4149b7314bff5d..c8213abf93de07e853d8e5a71e600fb74e1d7c62 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 1cb71480e45db60e47a68b565f54b5a92d463c5d..fa9251bff41180ef531c157e619e93f21054723f 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 8c441cb861c31fb13be278423a5df8e9b063b4bd..cb2dd9de173b569afa80a663d537b263af87a7b5 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 6d69ec8344b21da52ebb8cacab56fbd251909f5c..49a69bbe5e250ba7463ee9b50843de1538f790cf 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 897dcc929ce37e7d2b1e77603c7bbb4e5217d732..2a6173d3aba5845b6664a87737b14b230c237a5f 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 942b735c3495b83f81f1a0af1eedd718081d5ea1..e6e2d1eaf00b2d2c852925af53adec1b3f0580a0 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 05e5b5f7d35619098d7c5f6967ff04c931073bc4..3265b239fd4b9a897cc04f042d8ebcf8011f4ead 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 491a4f98ea75aa08583c56027911c1c12e36b119..07ae5f5f8d4fcf2cbf417ff2c4dc2f9797f3c9c6 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 5e87fc8aaef8302f92c87de96214821430bd98bf..bcf9588094dfe3491d28da2862b687d6181f192d 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 02d1e1093e8f2afdf3716c98232f17a905a1fe36..8a5d7f7efda2c140c4b3f27bd1241c5b3ec5c2b2 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 46c2611fb07a62e5ded4d9b5799abd5e0af16026..433f23c2d36c58df93b20cf14d3b0054b238ed6c 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 dcba7f8f43bd51fbb1b14972d81b90f8eaef2669..6adf7da5706aabbca9e99f3b8be7fed852b34ad1 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 3e09f7d1203470110aa7ade8ff80ca57836de815..17181444e4f93501df716f467a1c6fac68b2ff9f 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 9e4094f61abda7d106af29f722fac82ac5472f6a..34ce601d1666339ebd44911ec3d6f0ce7e5714b6 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 55cda0de53abcffc3e74f0708eb08f9f3850c9b1..4be46116d78eecec794874713b54c654e954c197 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 0670d45e8e6b0995a8137b6a0eaaefcea77b8bfb..b57b6bdb8433ed3fd713a478692bfd83a7565ca9 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 aad0ad5523f6ea58ce2d488a1c50ebc2840b16f2..5694ff7ce3aab1684e3c0eb9ab46a064ce7e75c6 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 94609d0fe8b1763df2c08bc1a1cb60f3a1edddc2..0176d50cc60c10405f20d7b664c8ecda2ef989c9 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 b41a0c5c65393e2b22aff26c12d3146814bb93b3..b198ac2b346a03e350bb3af7785628e91fc4a451 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 ce99a92947d0f15a8fa3f2b10fa2cae256a8e0d4..e276e7bb62845fcf4e30e899246b05b766045917 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 27f734cf4a7ed969ad5ea8c8912dbcaf81d6873e..2ef0e774f9780dbbe47d1d87abf56d999da494bc 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 8be3c75067fa1f03e2b5c27ca71b62528b7ee633..51cd526e76a867c3339cee0aca559ef5b5abbff0 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 8ac636fdc74c33ab026597f8b0300278c9cebe29..57201dc252f83339c01fa172e65967766058b3a3 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 afa341c4a42e93bc838bebf4e9c3ebffc1fb91e3..e48247ea5ec0a92fc1463b56386aa1e575b0c9da 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 d65db29ca5e85ae2624540fc77a9dc7ecc8e1b19..e764f3a6c17529fc45260c0b248ed974b30fadcf 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 ca7e5cd2c3dfcf8e1eb5bcd8d19a9585d9b7d5c5..0827a70b8075e6730d2994887e53c6fbf6d2e73b 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 658c620e501c070524cc175445f478303479fafe..a88ae1b00a53e7fdb0ecb114277f545af80deae3 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 a1cdf5cb40c9c7e8e347e504cc3f785f98364507..aa544413ca3fee0412cd940f7d443cab43504fb0 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 78168e4a38ad57f3f17fb639c56e4e4f21646bc8..4f102be3d91ae1b542cc8684054150a905541b8f 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 1c78d92540a6ea116558ea42c10f53a5cad0f445..70abc4fd3cfc9c3c573469c773e4f14b190fcaf3 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 4eba2bc89d4ad8f371153be1c8cedc5984aeb3ea..b8c9071c0a51ca79b8dde484e87cbe6c9a307f68 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 445b1eecb330795a6d7195183afb8495d63de6dc..c90a97ea9335a4d93952eff25ba0a759e2bad4f5 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 f358ad66c95e638706a2e3b9069bfde9e4a425d9..b731bca8cbddfe227dcc2a325a52b69bb8856221 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 4aa2f4fe9bbc5524dd167023a91b72df09376dd5..19bbfb89724e3cbda0cbd687cd1adda86514e748 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 fc084514fd9ffff521feacfb32c99f0893b545c7..053a168ec6ef7e7558b2026346b0015a4141e9c1 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 3f2fdf90653546c7e7c8ec7aae656b02b8dcebe0..0e5de17d0c7ab8505806a69b3b32c7279a0c2204 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 70e3d544071bab233091b2a0e2d481ec28d89176..96fd06ed8021513d0ccbaee021d6260dd2567c2c 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 fb72ee6b0d6ad701885b963b03281292be439c26..0000000000000000000000000000000000000000 --- 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 a3a1ee90097053fd3d37b12b235a68ecc73585b8..398116f2a2bc1092f3a8e496945dbe76822d9fce 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 65ef89f443ed604e461ed3f78ed2731dcd94533b..82ea19893028d836caf521a2caff83ad88d74e2e 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 72edf8a0ed7631cac607ae01ef36b118807f991c..4b9ae36f3d0e39c1096be78ce75285dc519472ce 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 372510125493766c6558ecb0c8f79d7668719f9f..d1b4a02a418f06090a1754275596c2bbfe83f530 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 b2ccfc2032d6687706b539d90ca00b1df99de66f..ab3f4296aad981e2be866268fb6ae39e41e84f01 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 511e68a0956fec884a0d02e72b0ba6e748915df0..f3f98e87b194fdd16cc37c9f83a3d765cd096d3a 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 c8aac581478c3f73a2303bbea1106bd5a8669918..078df77a9fbf135194e164035935d0d1174a5b7d 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 43c4c8585542143771357fc53af646da47e60d64..ab6fde099c5d023c263746b74a3523e1ed8c81c5 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 534748d1134f2efe4a5e669890178767e1afec91..dbe1031df7966e71b20d343095921150d6780ca9 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 505a739b1ed5fe039b880f6e2564523e73fb745b..210f1ff10791ded31375437c6e86cc8f84b858d7 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 6036bea70ddcb1e69aa08776a9524dc0c5b6a29a..ac4a10fa8ede75910b04a15319cf74172e5ff553 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 6c0c94a33b3cabb9d71052601b4de820b59e68d1..6136c0c1f1927976fe17f6a770e715cf8b645e65 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 3ceb434c8fa3062d00b45737a7c3b674941a19b7..58ff35f6c33a34a21284dc080bf091af7000ce5a 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 c0b66b6152150c4eda1a34d579f4cb96060f728c..1b515433013204c237d70e9d122bdce92115295e 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 b9106c1918467b4567fa8e0d2a83f747c4f63d04..cdced3f854763e5fae5b9b823c9d2fea1c5037ec 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 1693842f8164b3ab024c283684c38680d3b6a347..133e546b341af871c545de3096858817a427430d 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 ac06ce9c8eb7bf8a6eafeb1ef99ab878082ec200..32c342111b9bb2cc0d14e3c89e16f326c5d7f0ed 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 3f183768a99314146a23f3308e45b7536d442c67..ad5eb8529d1489ab255a78268a1a7719c7601ed5 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 d857304ad60b9a513eb2dd03042ba2d0cbe574a5..69b3506a7def15e60a4eb5437c47ef9b17a844b4 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 88b297c9fe13bc4ee5d7dceb894094ee0f8e3479..c59ccc68a7a7a85d6f9b4b4edd50f21409bc2950 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 49f3bf2588ac3337e0ca2e4a8cd5c9d0e51bf3ff..377d62e64ebb6ccdbb27d0724c517ed159831859 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 20ca149f3abdaad7355376565d9531098e850d28..e834621496dda36340568856a31fe493c7fd9f7b 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 fb019c9925c72782619bae64a60bca1ea33790f2..25c9bc4e68f13d456e21c95b0700f7957d6b6b2b 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 100503d83809534aab8ee01acec1fd28cccf5519..88cb91e801c4664ca1995db2c2a7305a01b8177e 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 eb8bc9fb379db0f70576071383cd8fb5de9ba030..b9ba6b37b6aaab63b91efb4dcc3c9e6d738c65aa 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 9b69d76f1fa40573898d4a41cd7a13d22cb107e8..9d5860476f42b81ffce746d42df6b9bf9779707c 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 c8256a8e1c7aabb9651cd5f09830faafd9b0a746..6f7f7ebac3944e475290290fc8da39e51844a2ba 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 40686e83939efdfe29cd127d830743daf83b8a6c..c8312a3b8e96fcb3494100714f09031380ee5353 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 8eb4fbac150e1d879a21b968b316a642b6293fa1..894049f7a79a0acdf57e2f6be49fb2e80c298d48 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 c1f2c5cfb4edc313518ef83bdbc907ee324ddd2d..0157e2ef781afbeb36d502b013bf23d6617043bc 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 ab03d4e72146aa280a2ce657ada46fbab99d5c3f..615f730816ea8f54db499d7fe51a6b3698db3db8 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 c37a4ffb6509b5a69d085a92abba8673f24d1058..af79d5dc651799fd146d07439e729f5f6203dbae 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 feaba892074173c042b1a7d9b26935404c713298..e5d9edc6ca8c062c5cbfd51b49239bcfb604934b 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 09fc31b368d0b26ca369f4352e89f909a0aefa31..90fa2b29b5795182d0cda0fa43010939d8c69c3c 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 af0b9622f1bc9d2ea4fefb7a95db745edd4b7a88..665847bf24f837928924534bbf7b583bb035587d 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 d693756ac284669b44fdece9578799dde37348bb..fe2473da6e412098c0174ab787bd79a996c8fb15 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 d21c79b69e6e2057a29d777e8349fdabf1874050..65808c09bcb9a93da90d0c742325865148144445 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 7211bb5881721eba8474b45862e83a3b8cb5c20c..c0537f2091dc33e2e46b4e756a582fba6cd855f4 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 ed8b8fe7d07bb1aa91e6b3b2a025005c5e9f2b20..554826624b3ce34435991fbaf5cfa018ecb2bdc1 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 741e3788cdff21547e722c4d539131dd970cb405..84e0c2954d3bfd1533ad5eda19d46ecc56ffb800 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 bc316af10bee9c2f1afa6c978f7ec389a1fe65e6..de6a79900d10e29735bd894f479c705497e77f9a 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 9daf3270a124cc253f4de3d325665a647c49290b..352e7b2bbc4cf0efd5650abf9a39b228c5f425c1 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 371010ce985d6288bf7e094f1ddead723a8421f2..47248dfed805230eb276653d1d64f6c3847ae3cd 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 a9e9a21c41c9e40216a5d8973e70c4c16d85e59a..05621b1184ab5751d9aca277c513b944fc61ec6d 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 ff95725e8bbcd49fd22fecd8767a57f0c2a37af3..cf1eabc15ae4faef65937ef2aa6ebb39fbd2635f 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 25273cf0c8f78b2675959c7ee8c19665acbea548..f37b0ec875fb61eb4c4e62cbb788d3a6ccd65711 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 498cee3db4ed02b7db9b051ab1ebb4289a6b387f..48e3b9530c3be12488c4b214616e987b061dc486 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 43ce3b09682bf85f1b2210b7c8a6e6c0cb511de8..11df3dcd3b4ac0155809d388ae978f7498f54078 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 4778d1fc718e7df6c15c679de63a37ac3739add9..aa3cc7afbe2a2ae63ddeca785683acb4ad754e78 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 70404212c4398c86d607976ee3f0b85d68a0c7ef..5684b7f6cd53e74295fca7bc6a1e906e842dcff6 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 28885cd610a3072fcf9f2203d9e08614ecb88928..e0083d5763b443d7ffa61170a1ea532578fc7630 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 476e45b6d0ba6f10e9f6c851a26ede5b7b155df2..e0257255f51b2902418b4c63455d100318015853 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 70c3df314bf5a254394497e198d3b42e2f4b5011..86d9fc8bbc6c2b04f7f0a3fa0931f5b3ea61e053 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 9fc2d1e8e1b1d69a903171afdac9021562e6dba7..54bf487b19eefc11ca2b78b3140513c963769e05 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 b79e84232cffe8134fa1d718b3b8e1833bc58075..3f8897271b8048a1e06a7f71bef831c44d064a0c 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 dde3e83a83b5dcca03388d5c154e28656fa6967c..cf34678b26dca0d2e91c4e0123bffc1f454e96cc 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 f009c5434d993fc767f6f9e8865fd8a147bb0bc4..c85fbe3946e80306f975fb9f6734bde6031c2c41 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 811b0511921330dd70957a5c9981a2c355256ed1..a31da4335704bdd7e8ba78cd8ad61e628974eb02 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 a73f3355b196f55dc82a1e81d6fa59422400fc08..97b65ee755dba93f734b3cbbc666a1619fc1a2ea 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 b11a54f6036bee17a7f1f1105b1112fd3850779f..120b7777c1cf648747ba6ff1d84daf5486b6506e 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 5c1120a796e074e6428b8ae7c38e1c753d03fda7..1f129736b8a3e7038a928123c99bded2acb27327 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 45c0723f6bcf94d2adc8e2abca63516ca7b6a4b2..3ecaa2be8dfddabcb06f46724836eebda6e10f58 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 aa80ca40f01a5976fc97d6ad378507302c9a0697..27e855fa24c831b736bfe70b9e2774038492823e 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 14fbe31ed68440ecef7583477aeb2a61e6443c03..17ae65ea742cce24086f8baff1835848df27bff2 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 7d2e501ec7bd4e9a7ee1f359ca1245695b27860d..ceafcf6555a70fe8db292ebab4fc86ee4841e1a6 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 619fe2933d9b3bbc46edf70aa355185b3aba72a5..551fb720f26e9a780a2494fe405865c145b4933e 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 ea0dd7bde60bd4e9b0ac01b4180d275a6fefceea..e9fba19fc4512cd11bba79d0b626ed85ed7b63f4 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 6c04ce7b4c15384691ca59ce55d4108c0480c26c..59f9d67d6d9135b719162a0872acac9b3bb040d0 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 06c79665ac659dffcb5c997daa3952bde840bdd7..bf6eb5291ef8a7b9d76d711d80a47aac79d0b31e 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 aeb7ab769abf3ae220acf58a668fa87351d7e0ac..0000000000000000000000000000000000000000 --- 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 4f7445db6ad3d181012c6ec24a7575dd5d01b1a8..0000000000000000000000000000000000000000 --- 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 002005939e8911310820754a55d8d18662362ce2..0000000000000000000000000000000000000000 --- 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 7184461b6d66dae9a86ccf3e00d038970f4ef53c..0000000000000000000000000000000000000000 --- 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 375e909aab82faa55b0c48f6b6c2c40b6f2ea798..42b6e2ee6bda03b3de9de9e4c97b5421e3866fbc 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 19dfb564909341f199a46ed6af4de186a0c61f67..3ca743a88344365e6c1ebf8596bc3be208d6a14b 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 e0db8e2c1e20bec5113779eb5fa2ea4be402fed6..90163146d730cd50d00c2fa3958b77db7f0f8fd3 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 e6055ef637d5e7fdca1836c1b00b50504c85f301..80a9151c4d178dd47fec45ca8c37b33918548f38 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 0000000000000000000000000000000000000000..43ef12adce51836f2d17dc79ab4a6e074a18610d --- /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 309a063f474a511cfbf2d624519d3b1fcf061b33..387a96be8c5a7ab7d10091d39ffce085e57cd0dd 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 2f57b9118006f4a518a3c028c213cb0c0c7abc75..54df7e0c63a311ea3bdc2754dc98b5857b4c89bb 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 dd9eb109d39b79c3d02224ab966d5349b3da04ec..202405160f04a79224229611047bdb748d71338b 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 2f92ac011e409d1ddc6b1e8df1729207de7bac3d..dd6c0e1b5db12d4fab305ed7c47533c1e8a85ff2 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 116fd790774add8591ac6d729008e3a82543c018..35ff37fc2270876da012f57c6d4c0b16f4c36ebb 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 ed87f0806eaddf04e5fb0bde3313896bb1048117..a11579feba7e14f2c77d78c3d4248db7896fc99f 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 0000000000000000000000000000000000000000..26e3b7590c3a97a2d7696478561fedeb2b45750c --- /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 565a6f73842e03192b777a429bd628723356cdf9..2d160e272e55ce52f32b95936fd55f88a9e686c2 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 dc2c9e402a1155524b3b995c8e5d285b8005d3da..ee6edcd86adf692b247e8f32329e44c9686425ce 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 8ecaf4205a836c4884e41a379c2b7558a04f19c5..da80d2bddbaeb30a4e052bc0522808f7f076f9ad 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 f737ee0865daa466d18946d12815e8078f811b5b..157030d87e0d1871ce660954752f022474c1cf5a 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 b057ca1d73b9268386ade9833b359134d2620ab5..73b947636f0485d8c821debee0b79589152cd2c9 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 c408dd4b963671f778974826357f2462cec33543..644c3f1ec7362b5d1046bb42234becdb89f46195 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 c08596f7ad848ef96260d1db42d0dcd7e6ab7c6e..013bc0d7a4b634b9828db2e8c79bd99a8b5e5be6 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 34e15e954abfcd61fafd85d0be84bc114d8826d1..1d3edb6a7548527afc23ed9ca56b2707905ae728 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 8c8762c9e33280622d0d4a66dc646e68265ae2e1..20125b753f2a9f61825271d3b013413b234584ec 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 f9fa019e05e17e18703f1bab8c183a6228fb31e4..4993a68edb0c9615fd5034aca394f056dcf8bcd8 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 17bfa8f061861b2b0ee22887d854e31fdef5f71c..ac4ddf3c48f600d5455d6f09981eb154ea8f7479 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 167476a04b6c65deb9cff45eaf231eb22522fadd..50e3abeae9684086f71a1e039e496884b52c7d1f 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 677c0f27f585a7733270b4174f0a6bced78afcc5..2a1f9806b98fdeb4869f68290b6e909711163e54 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 0000000000000000000000000000000000000000..f5742af567a22ce154e9aa398cbe7d6be232baca --- /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 57f2219646636e8c39c3a3ef7da260be0fbb1dd8..c3f5def939ea5c8a05e41db913b8e49e72e2d10c 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 fe048728f218f5f2403318ecaeca787fd3dbf3a4..477f1226ded0a8801c42dec2eaabde2a4337c50f 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 e1a20ef23d22a77c092a6ef4f84c550f8a7e613c..0000000000000000000000000000000000000000 --- 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 c0348f34ced4d107ef3949bc7de23f1b08d7ff5b..0000000000000000000000000000000000000000 --- 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 bac7b9706f9921152fcbb8e0d5b649c362214447..0000000000000000000000000000000000000000 --- 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 820f8cfbd1a6a74993a09ffc545e24dd16918193..0000000000000000000000000000000000000000 --- 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 8dd26413b873a7ecc6107994bc336b19056c1c78..072cd2e88666c24891052ac0bb7fcaf7cedabe33 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 1ba4fbee989bb306be590f85a5a3e0ff516c7c54..9135ae7bfd5ad98196d4e5d8314dca5c6f08688b 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 13f2fde8caae14916e1667273edd7525eed924ab..07783ac6b4d0915d5f369ee152d6975de72e6d0d 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 3efdf965ca41093ed9621946f720209be85ad579..9d5ae2a675d3676bb44b823e1742a3922dd086a1 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 f2310cd7653f76b110a4890945b6a120a9c4fecd..1e1d5932009714a608a98197f8c52cf3d75cb21f 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 cf82d39f43ac3fd88c97a69f936cd327fb14fcc2..7a1057e3b9fe9827df3f4d6ce9b1cac7fbc5a225 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 e85cd2477509d8be53fabe6e1340f473802e362a..c94bc79518102ad7d9e8b11ebd1882bd4dc25a8a 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 70ab669fc089de8195c4337f63389312594b7226..64ba98097bb699f68d0f89dc29f4ae5298f6ca68 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 cda4c1e0788e775b4b27159c365e685b4383024a..78c3252b5d6b7e5d3472724e99396e2c7a7c28a0 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 0000000000000000000000000000000000000000..a6262ebeded77700609adb90213b0461cd8e5e92 --- /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 0000000000000000000000000000000000000000..a8dad698a8640d7d29a223e6eb8e8a1ee8b3c0fa --- /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 0000000000000000000000000000000000000000..90f2754c93e47d32a813dddaa37b9457aaaeb236 --- /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 0000000000000000000000000000000000000000..4e0c604184c7cdabd49686fa695e5c2062ca6627 --- /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 0000000000000000000000000000000000000000..fdb961cef4f39092b0dd9e23520762c20a453621 --- /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 0000000000000000000000000000000000000000..e2c9e36bbad6914a7368dee562b5816b26c9e02f --- /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 0000000000000000000000000000000000000000..725bd92df8cd1799da4718f7e8a27384106b57ec --- /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 0000000000000000000000000000000000000000..aec53c07fdd386a0ac84c2c2579f2281220b57d5 --- /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 0000000000000000000000000000000000000000..a1b2f2dc99f7e63656b924a58d2c167b0feeb6ca --- /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 0000000000000000000000000000000000000000..0b350824488999e7bc191ff1270e99ae7859b477 --- /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 0000000000000000000000000000000000000000..68c8a2a3b23f3ed7bdc6549dce61937934ed5915 --- /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 0000000000000000000000000000000000000000..50d5514c730cdc4d48dfef4d9cb310bdc6ddecaa --- /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 0000000000000000000000000000000000000000..989674f90131fd567190b12cc3f4734b7d1f014b --- /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 0000000000000000000000000000000000000000..b6f0c497839c5c7ad2257368abd08965f0c5b6f0 --- /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 0000000000000000000000000000000000000000..8728d7d6859dcc7ad92d7c1e57586f1e3f05be85 --- /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 0000000000000000000000000000000000000000..aa2e2b0f2296ccb8875723d70ba486d60499d9a2 --- /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 0000000000000000000000000000000000000000..2d18aac1ed134d2db1113bf972e7f8bd19d913ff --- /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 0000000000000000000000000000000000000000..d16c7328e336cbb097767ee9c7c0e3bf5812168b --- /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 0000000000000000000000000000000000000000..b832e4f7ad98a962be5318bff85144ae90e00e23 --- /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 0000000000000000000000000000000000000000..e84fffff6d1a9d21984dc6b33456aa46a1855d1f --- /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 0000000000000000000000000000000000000000..cc966c1ef7f42f73160b809a334dbbf198ff9435 --- /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 0000000000000000000000000000000000000000..607f7258b8496054d5fd34e1f8aa84d55eaf8b6b --- /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 0000000000000000000000000000000000000000..fb96232829f5e0b4b9210d749ef016ee3c7d484a --- /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 0000000000000000000000000000000000000000..a989d4466d0b70418a49fcde41528b328317c466 --- /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 0000000000000000000000000000000000000000..5d9866a7f0e62015b43abf4dbd7a20419fa83fb9 --- /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 0000000000000000000000000000000000000000..6d4e7c6f45b773fee7bcfcb0d401f8f2bacf72ee --- /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 0000000000000000000000000000000000000000..f5af79484ab686485ecd1600dcd91dde7f4a5ffb --- /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 0000000000000000000000000000000000000000..c1867eeb16d00757fe6e742be41f35ec0cafab5f --- /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 0000000000000000000000000000000000000000..e012124288a3f4291700fc5496eac537c0bd1293 --- /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 0000000000000000000000000000000000000000..fd396cc190e38a2452895923b6a25bcaa05fc3f2 --- /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 0000000000000000000000000000000000000000..2bf80c67f59700d299d41898377303e39f7022e5 --- /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 0000000000000000000000000000000000000000..f95fdac07283e9bd8049b75aa9d2f1f5b5ad8ffe --- /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 0000000000000000000000000000000000000000..9762f7391bca8722b26095b43bba838dfb1a15d7 --- /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 0000000000000000000000000000000000000000..035e453c5f5b074eea0e4df0a9aa1f68b1907aec --- /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 0000000000000000000000000000000000000000..35561532a691d2e7179baeced1803184b2d69d1c --- /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 0000000000000000000000000000000000000000..3a5c965602c8d08d8cdd385b8cdc378027d8febc --- /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 0000000000000000000000000000000000000000..007e4cf9d42fd0c965998a3f5876e5d59e99f9d2 --- /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 0000000000000000000000000000000000000000..d499a18cdadac00d9b332d356fe512dfd8f01e33 --- /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 0000000000000000000000000000000000000000..23d48a8fc391bf5e26e0b3b2965232a68dce1cfe --- /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 0000000000000000000000000000000000000000..2354c5b88bd926604b3029a76d51b3a0e4381c15 --- /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 0000000000000000000000000000000000000000..ad4be014d09c22bb0fb35f4809b398a16e7a6b6e --- /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 0000000000000000000000000000000000000000..3cf5fd554e23e6f2126f93e5f34904ca2dd33240 --- /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 0000000000000000000000000000000000000000..6d5090f38718a200f8e80e9eda081fa2160aee45 --- /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 0000000000000000000000000000000000000000..48a848a7497d30efa28d9466bcdd8a873a33c522 --- /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 0000000000000000000000000000000000000000..01a9777e14f214f1ca8fdce6dea5cc75d6956c4e --- /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 0000000000000000000000000000000000000000..a45191a1ce8d1dbcc10bcdc57566b76543fac891 --- /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 0000000000000000000000000000000000000000..50529ebed9e0efd1b4af7c93f1197f3e2dc3b5e1 --- /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 0000000000000000000000000000000000000000..27264030101ddcb4f091b129d36143dba4e7fa33 --- /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 0000000000000000000000000000000000000000..1c9b82121ee6b5f47d8c6a5f07e7c6086508c3d6 --- /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 0000000000000000000000000000000000000000..c8e994d6196e3b3cca0dbe16d9f03611d91d1130 --- /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 0000000000000000000000000000000000000000..fd2c6ebd9d41252be4b5454aa73031b53d06c3ec --- /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 0000000000000000000000000000000000000000..38d5769bc5d11fabb79419195c8b446e7541bfa7 --- /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 0000000000000000000000000000000000000000..79019d5b179f014c28988cf796e1b907cea9e793 --- /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 0000000000000000000000000000000000000000..f3478aa003c3d6ee32ab6ccbdc32dd3ee521e6e5 --- /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 0000000000000000000000000000000000000000..c2479b5a7b561b8deef76e8d46f3c2e35eadf052 --- /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 0000000000000000000000000000000000000000..0792809617c8110f4fc196a2dff915ac43a27750 --- /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 0000000000000000000000000000000000000000..ab9b704c70680406cafea0cc6710706cff3a928b --- /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 0000000000000000000000000000000000000000..d6edad6052efedd2a29b204d1ae6f6d1ecf79e6b --- /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 0000000000000000000000000000000000000000..6800ba56356c8c2540783cbda439adb5bd895758 --- /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 0000000000000000000000000000000000000000..769287f6d25fded1bc07fc5b936c161964f9045c --- /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 0000000000000000000000000000000000000000..ab8c1da9d2de84815c37850ddb96d978dce9848b --- /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 6e6a8c6dfbf602e94362bfb3eb8cf2ac8d5999b3..c786bf70e46510655786b6847f9f974246cb3875 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 0000000000000000000000000000000000000000..68b1955935e540eac39fefcf179dfeea907e9202 --- /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 0000000000000000000000000000000000000000..2f66a76e0eaad55d53158377acc85f31d94ac47e --- /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 0000000000000000000000000000000000000000..035a9b0efd4ff7596197a669cc48f2cc03cc488a --- /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 0000000000000000000000000000000000000000..abbe60b2461af9cb95b539d19e117a30b0c119e0 --- /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 0000000000000000000000000000000000000000..e93858c4514e70b1c6e27e407ef5029beebad67b --- /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 0000000000000000000000000000000000000000..9bf93d08d9e3e7aac95806ea0c1ff433f396f9ea --- /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 0000000000000000000000000000000000000000..e20d4a5868e247c95e7c06026c3f3368ea6b1717 --- /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 0000000000000000000000000000000000000000..ae91169918766db0458ad76b0446e0c4078e1570 --- /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 0000000000000000000000000000000000000000..1a74ca2ae31b0a10eb2d42b659aa4112214870e9 --- /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 0000000000000000000000000000000000000000..17f0f09229a115146e585184f54daf215a33f3db --- /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 0000000000000000000000000000000000000000..d57613413e82214eda5e130260676bf6c43bb952 --- /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 0000000000000000000000000000000000000000..27e46c36c73beeb829018fe850ffaa4656b3845e --- /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 0000000000000000000000000000000000000000..b661d38163575d1f329a14c43acfc72e800495ef --- /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 0000000000000000000000000000000000000000..5a717c39429751a64e7dee8c579518a812b36586 --- /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 0000000000000000000000000000000000000000..f24c19e9517d34547ff9c7cf29a6ada86ea7149e --- /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 0000000000000000000000000000000000000000..5ef9cd09130c34d85432920cdffec851baa5d73a --- /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 0000000000000000000000000000000000000000..450e746c82fe3180ae13d9790fd3cc864c1e2a4f --- /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 0000000000000000000000000000000000000000..e1ad74793f8fec27ed24cb0645ee4bf55387eb74 --- /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 0000000000000000000000000000000000000000..80daf2c202b5579676b3c00952154fddc15635f3 --- /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 0000000000000000000000000000000000000000..8353f378b5c5132d347a6f4cb949735abca43866 --- /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 0000000000000000000000000000000000000000..300557182e0b69def1800c267053c95ee301a166 --- /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 0000000000000000000000000000000000000000..85de10b6ff269555788d3ba6a574a48ce2f5973e --- /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 0000000000000000000000000000000000000000..1523f780285997f1b4651fd563bcd9921c30ddea --- /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 0000000000000000000000000000000000000000..3590f287123e93b9aa200712ae8f720398e83c88 --- /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 0000000000000000000000000000000000000000..e0df42ea469b878b4c48c04fb4e760ad4bc2b3b0 --- /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 fffac84a06af607dacfae3a09e2da2a96284d07b..e51bd60cd97e9f7efb3c0763968adbe654827a58 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 52634635d1e009f75d0f4648205f88ee289206a8..d5908c5d3c365a404d231ec8341d562a18633b10 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 93c542aaa77c3600e193e4b5bcf10ab65c06748b..64b24973ae6ebbb8af556757b8fab939768cf2d7 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 531f90c037d1763f975fe5a8f3560feef52ff276..2e30a8cd3eed6133ef42d10f26248e4d8dd5dd05 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 2e2a383497804fe8f18f650e4c21f2dda0894065..97c8956b6758ad23190d5112856dbcc9d91a94f3 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 e704719fe8c16bb80f2c46f60d24aff6cac3317d..0ae121ae122d6b3e8bacfe37cd268fa3f6dcb2d3 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 84f7b2fe7ee54f7cc6eda763c05fcdf51c06da4b..bac91d219ce86156ce88e1cc5e4ea4d205877533 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 4c741841affda56e40705be1888b23080899237b..b03303f92734efdd64a304de483c26d1bfb797da 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 b484bc05a6b6ab623083e3f94906248af6042b5e..811e608b511a3cbedaabd8fd8df280f69164578b 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 245fc56e0fa27ec701560a7e926dc86e47b5fc1a..de5fc310fff7f03ada47543d3d3440b5f1b0914f 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 59a4ca9872fcf67f8bef8d269e41317272d8fca0..c6f2b7b560a25bb54ef4383ec2d77a1b11777e57 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 499c4f8bfdc19dcaf35c62509859ad3cd25df6c9..9febf2f089113b79770583c896ea9e0711957fb8 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 5484dbff0ad0fd6ca1a6a74da8703c5ff5f4f48b..27b8841325602b0476354192e7f1a2304c260765 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 2377f2656587f4c477b8e69f5d56eca728c69fa4..6e849bc17d1ac4238a2936188eccf1ab6fa8edd7 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 947f7215d84c145d2bd28e968af7d926d60c231e..5f594f047c04c42950e99c27ebf7e816a5cc2a32 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 70c50b7c99c4096cae7a865459b22187cf1b2a6d..0fdb3e584ef674853c66ff47e6901c3b33c614c6 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 a03886fb3525a3bf0bd229527f23d00c374c9944..7154dc337ce08e818f461570ec2e901810a79cfd 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 df5166111420c4f5f2f32b654dfb69312fa314f0..0cc45b87cc1adc615fdf2a64fd4cfb92d94c7e1b 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 24ff8549d81cef397960369637ee269b81ed765b..39cec94137ad8c4b0043871997763a296ebf7c7e 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 95046c2847e7dd90c9825518a84446b0f5d24dfe..f30cd3e8860a76a7ebc52f87b13d72e52cf3bb9b 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 efcf804306ca449cd7395d55a899b6a9835b8f4a..c9437d989369add9f6143f59b235c97faa404900 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 47f649263ad98ee1a3c8ced5603517f15292f890..537dbb6f3932bf8cbe9c680413c370ffb8870f79 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 d621a5babf1393cc288c52dd8904030e0c6a11f0..12797366c1f2e5ca56d9a7f7ca53660e27459a86 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 bacc129779b4e341972930c1451b17fcbdd56a97..4c4bd8754926393251b6e0588b1639cbc635a11f 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 42d827f0a5b33509f52bc87ecff3809d80de2fc9..a4e523a5520dbfb70c8f37ffc79206bbbbff8a02 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 bc20f1d7ec51ff40b49b995ebd5d784527444c7a..12058a01514fe3fff72b678bec8c4028d4964b06 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 f9571538f5e4162239156ddcf9c68b383a1bbc02..7ddc2817c41919ff7b04e5d1255e778dc470b67d 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 0706a68821c58949803a640721162d01f73c98c8..a4d9b5a66bd504544b233c361cb1192ae3fc3aac 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 a39949deb2ba3e3cdf22ee8850b5cedfc53b303d..fbf1b1300643cd64011777a643ddd3418c976629 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 82409d25e7bf768e47473ca4cf4773cd8d687614..343d11d2edb4f8d9200c02543d93553ab248991c 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 c6cfa7520a3e480c4cfad351f541f5b3c7d63d6b..c2ef874c38804222dba95c3d17bcaa5ca5c25c2d 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 4394fac57952929343f9b8e5f1b83f444f7112a9..9a8210bc86b4d3b7a7275c24da37926d7ad943ba 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 e38db2b163edaa50bf0d0cff3eb44e2ed277beb5..38d73acc27130fe68e4506cf48140319c1c2a80a 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 0000000000000000000000000000000000000000..57102299c9d4610ff120fd1c1815aa60208f1ce5 --- /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 0000000000000000000000000000000000000000..26d8979bcf13bb18ebcfae7db0d3177c6374e521 --- /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 0000000000000000000000000000000000000000..b8294cf0f4159ee0a981be02815203d054ae4eeb --- /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 0000000000000000000000000000000000000000..4a6ceeb72d11f3dcd313e485eb8814799295173c --- /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 8f5aed9810883326535a8c63084538814eaaa90f..dff7373e1d15611dd367b92407bd9cd54c58bfcb 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 afc5e08c65a4180a0032510ba0fb312086cc7b04..02cd55f95b0a254564af53d55fe83126cf760d87 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 67ff8378297c92afb2b38e2543c917139a0f7688..76c2b1d6174ec9e5087ef50057f894c4ebcf720b 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 133fb83b4748bf42066aa94290ac8d6d46fc2dbd..3eb55db28bf91d34e6d081931b60144deb374a54 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 a24d4f0902ff64ff89b3dd4314a668ea2c9cfdb3..a5f1ddc11cbec42ea3c3aa612360a3dd6db89ed5 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 ffdec97ee7bb594149a010392a6c24bc8f647ebf..36b48f153de0bf57a258ecf05cc0fa0c157a4d9a 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 69237641327a5b076b7420a1fa9389bcaccd82d0..64f3282d999b16fe7162ce88a4fb11138b66260e 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 1fec4fe6221c813a290a9bf8d97e37ce38745312..d8a9885a9998319538713ff61ce6ff106402f3be 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 35886842ff7bfcd855bc1bff837028fa739b4c89..012093800b729137ad9974f1a5d71073050fa3ed 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 10a5bc6f608e40254886393fd94661c8c31666d1..2d4d75d383eb8de4c44a38d36646317b93bdab0c 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 3862ff091aaa643b55d38343e57c210f6130a7b2..90471b3df06c1ec7826f3a8de6eb3a8788936ace 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 a877c85a3c35a1efb6b7c0a03703335b36a27dd9..7cf23df8f174238f785526f713768dbb021968c3 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 193dbab9fb275a804d2307a3dd87a73494a4e698..aa1d3052ffde549ff1a5f40e3fd5cf75bf444ef4 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 56e5c3f581a003f7b13c101444de0931e53101e0..2061532367552886a10859c2b3ba5c1fc72d34d8 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 e1d186db1203824931780d8ff61e45507434a8e6..92dd0700131ca307db7b1f26c45ea9ac4e3d7e3a 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 69eabaa4fa1e02e3bae41d3e2051087903bc7e85..1dac15fe7f5e06a0300fc3f86058b082e4d19f09 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 6f34a14b448f3385102872bab5657297131db086..4bc86f122846a740a0a91cc8d8a5c184b0724874 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 16a78a0d5a9848277f8375f6571340d33c89d4b4..4d43d83742087fa32b492391555395cdbc2307b8 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 bcd591e6ca37841b1d282983017c6bc7466f5a7a..03b7536b5d24d6981906ea9867679986fbf36c2c 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 d07d4e7c2dab8580323250b32e665e12e8caba63..3c8303469329c569cac13a418e2c5d1e4adb2821 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 c3981835cfd7cb3d97672305337142621309c403..8605d41a9c498386cfac1fc193810d47ff057d4c 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 49e047aa8ed298448afb002f0f4589dfae1cf580..91b1c2e1a103c7b198407d311d25f8cdc743f282 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 22ab6a5796e09e27de9fc3cd13689a826c454a16..0028ad2a317ee6d630eb5af7357f5e898e3275a4 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 a9f505b4e94c6cc44717c8a3ba70087b4be6ea16..487cac2b3d1bd53fded5528aab4f3d6d5df21f37 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 313acc600b793397d959df6c70d19b2cd8c544eb..6f440a73769dcc4cc99f547b49be2b7f4a93ce78 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 96f7092ab924fc02fa3d8a47cdac37880672c060..6d017dc63297a98076fb8497c39e64fb8a5f6f7a 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 6e3c650ed5b65cdcf57a7b597646139269f505e0..03d5f0d80bdf9458d009b6955dc7f590b1e15a2e 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 95e3e95bf3b176cb014f0ccca0db9b99fbf5f32a..8e515b980071c5ff78b0825ebbd8710e45c8d612 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 41fdc82e8f28163ad7ef8a8f67f01fbddbe8966d..fe754ca58dad3b9a30f1c6f21ba7f17df7cc07e9 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 5e6cefb7124d09b70870e1c5d35cda43da05ec12..92de70db293475cbf63815e204cce5b6d8318d98 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 f026b353fd51772d85c3b0a6a72ebba60ecf0c77..344a868551df7018086b1a80612d08a75811b6f8 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 98f53df31e1efe523e3ae03754b42f38b54edd7e..8572bd7866f804c1c9bba1edb1fcbb9893769062 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 5401ac9cb3ec85e391586772ee057c141d486c27..a26dca495951687a30d66e68e27fae66fa234ced 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 76d12266b41d378093392ed11c86fdd16b1129fd..339caf59fc6131267c7a53f003917f2d4ec17714 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 afb1a437a71257729f128afd294d3df62701f9bb..786e723a985135274b622a98bb88a4f2b86a9eec 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 afa5610683090d50013851778f23a7f6d56176ce..8095ecf9ebbf029a3275082bd4bf8f48dfd6b858 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 da7263184347cd98d3ad77920b05af6b8e4befc0..a516c903fa2d31a7621190d06777f4ecdc3f8274 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 8e1b1c5e154e792a4b98693f831e10d5ace76dac..a4a0c9e3ba4cf0d1e2d20ce8fc982c31eb19c080 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 c04df4ca4499d785e363635f68bbf352e04ccf12..afd5d38bd5b1f667c8f6e1146a13bebc6005ac96 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 4f225e8d7f3a96fd6f793967ea4a896f394f427c..24881b7a8e8e7eb3a1f6c7edf50e8d65021c38ae 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 5a5f0d4d048d745ac96ac3055c3a526a0f43e399..79643b5cc2406490ecd8694338f1db5e17c650c1 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 6d890ec4759e0fa4e665933dcd6dfd53d1461a23..0bf79c883143e3f3103edf89acbfd6ced2bfa7e6 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 35e585321b471adbdc4dda5c4aa53e5525836fb7..3f27ba090b432c26e96557653d01e731b079dc88 --- 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 0000000000000000000000000000000000000000..d1cf82368e560b785d3345a4a78df1691ee24f14 --- /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 0000000000000000000000000000000000000000..1a16bcb2cce906f03999da92775fd780c25b57cc --- /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 308013a51562b1756fbefe308d86f7fab337e7e9..84c8030d67d7321fe06973f69563794c0df2a478 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 7ca97c62bca48760efa6713d191363137b388103..cc6074117f1f73bc3f3e5e26c473aba967b69c48 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 0e9e7b5be2feafdf09c6a65343edf7f7d4896cfc..a136696f2735f60ba4fab661e2fc0c9097e71bf9 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 45de45f7f90b8eed8222fd46c1b02e37ecb83eda..0021be1dfa3ecd226cce28b130ff3eafe047ec7d 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 e505c7d6dda434abd648d370b6193ea33cda2281..1085f301fcd68f532bd9528e4399548c998ba0eb 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 2e54c5edf1edbb360c79d4348b9a417e436fa944..f30e16eb1d44d735efffa2504a9575bed9919ca9 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 0f788857ff90c9465228c3c9ccf3d7fb28d86a53..543303fd95357906bf033a5165d6947043929351 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 923cbe12414092ab8371c4d8be708b1db2b49dab..b9a0c89fbdd6fc9a31a7207ed06f73c7e078b3a4 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 3b20052d072fcd4638b700d735bfb99c851f85a6..0afbab10163d12d923c36c6fefabb3b73c49664e 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 c5de9fb47e1e7afca18f79933c0bfa9c4724ba92..ec4c2fb6a135e6f7bae6d04ec5cf3ba43233b664 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 2f69abc24b0a92ba2978052817170bba0b157213..c3f6a47a826e36f40a5627c35ab23c725f67443c 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 0000000000000000000000000000000000000000..a69539d8136cb2fb1c6942f13cb9456da626c9e8 --- /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 0000000000000000000000000000000000000000..502c80f405479a9b9e2af8d32161b65c088b3188 --- /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 0000000000000000000000000000000000000000..4ac23389d0c4e149449b4699a166b67e0b3ff78c --- /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 0000000000000000000000000000000000000000..a3b98d37355d81472a66d8befa7a3d9c44abde4b --- /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 0000000000000000000000000000000000000000..8044f90a1a897ee3c68c2e229c7caee49e239383 --- /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 0000000000000000000000000000000000000000..15d087c500b6e41c76211dd64a52044715e4c52b --- /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 0000000000000000000000000000000000000000..e8818bb9c648dfd9bb230eb84d32c993aa46bf7a --- /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 0000000000000000000000000000000000000000..5e75e2fbe24e97ff07540db19a5ae35bcd7b8dc6 --- /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 62b362066e1bd5e6d66f0dde00967cd8dbd947ba..fd7852c7fa75cd58ee4a514ddd85f76cf27c341d 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 0000000000000000000000000000000000000000..07366045f8f5cc80ab57b2e7adba7461fa8800f6 --- /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 0000000000000000000000000000000000000000..41590b1f518cf486ecea86e7c26eaa13c10aca02 --- /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 0000000000000000000000000000000000000000..7bec6831d8d8f817048a79a0fb65f17775d2b8ca --- /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 0000000000000000000000000000000000000000..6319ffec8e0858789ac6cee92bbe9b47e12d5109 --- /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 0000000000000000000000000000000000000000..644d85abdfece825e6fb50d379cfa639488915fd --- /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 0000000000000000000000000000000000000000..55d1ecb6c285935a6870b1287395015ff91e3557 --- /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 0000000000000000000000000000000000000000..f2b435321e66779a511cbaaa79ff48683bba0cef --- /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 0000000000000000000000000000000000000000..258f4c02b50f88fb64dce3e332ef823b024f7783 --- /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 0000000000000000000000000000000000000000..b201aa0f371ba73cf913bb3d0e784d2a2406d0e8 --- /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 0000000000000000000000000000000000000000..78e2c4b5a9c7e74328d8f70cb66fcfa9871caea0 --- /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 0000000000000000000000000000000000000000..51def6cc1fd000ed84ad844eae28c1cf6bcf1a74 --- /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 0000000000000000000000000000000000000000..64179a75ff2af137448fe878d3686925f0b8fcd3 --- /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 0000000000000000000000000000000000000000..885bb93efc6af962c5ac720b67786d3b1589f44f --- /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 0000000000000000000000000000000000000000..ac41e85ff33820c659195c5e0aa16ad074fe8e9d --- /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 0000000000000000000000000000000000000000..80cc5ee7fa4d90364a5ff48ceb2839572329c35b --- /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 0000000000000000000000000000000000000000..ee15e051d159e2bc7296199f87926b2325e6b785 --- /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 0000000000000000000000000000000000000000..1209a201c2b22087f2a0ee553ce9a3fc531dccd3 --- /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 0000000000000000000000000000000000000000..88d447123f5b8728d9e5883637ca803b3df6bb7e --- /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 0000000000000000000000000000000000000000..19e92db11de2cbac61cb701821e2ab1fdace2864 --- /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 0000000000000000000000000000000000000000..4f91a9095051fed72fa52570a41d8f9a7edf5418 --- /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 0000000000000000000000000000000000000000..73b5e54084afe6124d50aa1dc6d9a857a62dcf15 --- /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 0000000000000000000000000000000000000000..e28b8264225510e98eb12c164980a6ef7e5e9aee --- /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 0000000000000000000000000000000000000000..8ffd1367dad5e5821378408f0586369cb81c6b61 --- /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 0000000000000000000000000000000000000000..9230ff217348ff3ce5e6beddc6997d36448b0c19 --- /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 0000000000000000000000000000000000000000..410b5ec92349210d917aec5b60b402a2b9748b16 --- /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 0000000000000000000000000000000000000000..7f3c19e041f838cedf5fea86318f353613f83393 --- /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 0000000000000000000000000000000000000000..a75c0974d6883894c3003da88929f5133059a1ab --- /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 0000000000000000000000000000000000000000..5decfe17956014976044f867ca555823b74c5308 --- /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 0000000000000000000000000000000000000000..0ba16010d4f73636d2d272fe628cceac2651f455 --- /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 0000000000000000000000000000000000000000..e31c78d3a539bbce4be82a67bfac72dfac57ab6d --- /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 0000000000000000000000000000000000000000..2f8b61b10900ee1fc17ccfacf22ba7a96e27b436 --- /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 0000000000000000000000000000000000000000..7741261bf17f21a8067172aaf70b22f1dd491589 --- /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 0000000000000000000000000000000000000000..829820f60f5aa42bd4c9cce25707548d7c78a2c3 --- /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 0000000000000000000000000000000000000000..0ca5cb37ad7854961311cd3ed2bb1a946827b9a6 --- /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 0000000000000000000000000000000000000000..ec2ab0bd09f886ac93c4ae37afd467b7eb286103 --- /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 0000000000000000000000000000000000000000..a19df22ac6bf1d148940e215d14ede6ec180aeb7 --- /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 0000000000000000000000000000000000000000..f42a6d97cc4dcc2a3cc62b0c42556814f9250838 --- /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 0000000000000000000000000000000000000000..68718ecd7b3602f4120dddb10d58237dbed44051 --- /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 0000000000000000000000000000000000000000..3733785f42e41e5b40f709fad148a5b198ba4b73 --- /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 0000000000000000000000000000000000000000..b5871cb7df0240d918908467e720a8cb17f76c05 --- /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 0000000000000000000000000000000000000000..391071cd1a1e1f323227016b2c44d3cbcac3623d --- /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 0000000000000000000000000000000000000000..aff0d9ba626db889a311b3438cc90adcd7e44d5c --- /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 0000000000000000000000000000000000000000..21c880661da19b1fdf6786e46f000909025d97fe --- /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 0000000000000000000000000000000000000000..41f2f20f61abb3db5ed6e3b5dd86ddabf746799b --- /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 0000000000000000000000000000000000000000..d1cf82368e560b785d3345a4a78df1691ee24f14 --- /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 0000000000000000000000000000000000000000..1a16bcb2cce906f03999da92775fd780c25b57cc --- /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 0000000000000000000000000000000000000000..e5cbb8d7636d6b1d36bf035518fe46ea3b94e0c1 --- /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 0000000000000000000000000000000000000000..11c34134e97a5f0fa790c612450bc149d0af6ace --- /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 0000000000000000000000000000000000000000..f3cb13668da08e0aa40c7763dbb403609f2235c7 --- /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 0000000000000000000000000000000000000000..e05dc09668f0772dd0bea8d99ea0a531558b7e33 --- /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 0000000000000000000000000000000000000000..6ddb4d073a39e75e7011355072329a4c0736052d --- /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 0000000000000000000000000000000000000000..f3e5ef09e84e4d6ba00d32bd3d1ee31e21761f19 --- /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 0000000000000000000000000000000000000000..8550c3cbc36fc22b31f545ea8774aedda45a8dd6 --- /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 0000000000000000000000000000000000000000..acc0ac185077f12b759b3dc4a5ee1f0c330a9eab --- /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 0000000000000000000000000000000000000000..faf10ebdfb7c77490c8866ffa811ea925d485598 --- /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 0000000000000000000000000000000000000000..3bf619f30bfb396ae91a911a502639c680f4312d --- /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 0000000000000000000000000000000000000000..b211f197bcad20aeed3c0e6c58a2459120c099d7 --- /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 0000000000000000000000000000000000000000..7c9624b55b31d4795993e1db71bc1a68840f54c0 --- /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 0000000000000000000000000000000000000000..5206b1c3a2da8f484a5446a875f2f8166f2d35f4 --- /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 0000000000000000000000000000000000000000..d5b531572b3550b271cbf6e416d9e1c74ae3c656 --- /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 0000000000000000000000000000000000000000..ae9f709dbfd29ba4ffd28688154f331823267240 --- /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 0000000000000000000000000000000000000000..73f034adb55fe0a9763500edfcae484df548fb15 --- /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 0000000000000000000000000000000000000000..7d5f247577947cbefcbd9415c2f36634997f5a4b --- /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 0000000000000000000000000000000000000000..a91f2b9f31f7af99e0c261730fe9c7dd1f39a98e --- /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 0000000000000000000000000000000000000000..3760d1d3c2f011f2f15dbf9c0424a95fd840d68e --- /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 0000000000000000000000000000000000000000..471527a5ce5f7cff7be2c4b35030b5feb4ca9016 --- /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 0000000000000000000000000000000000000000..c3f6a47a826e36f40a5627c35ab23c725f67443c --- /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 0000000000000000000000000000000000000000..ea522e5f92e13a481ec4edb3722b849c2c6e23de --- /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 0000000000000000000000000000000000000000..1a1912d28f5914f864c8192df24bbd61fb901c48 --- /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 0000000000000000000000000000000000000000..76f2f3f4886e3677eed64cd3a0a7c1958872accc --- /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 0000000000000000000000000000000000000000..99b95c0994218d03067b777ad09c1e4832bca1e5 --- /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 0000000000000000000000000000000000000000..e8a1abaca541ca027baa58251d5096d88e091d34 --- /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 c3ae1e9d0463bdb2a74d87938f79bd295c5c262d..a9e4401fd4720f9956ed7368da84b4de8a0fc25a 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 ab461b564c8afdf34d400c3162a12fa1b87b3837..b5fbab3a1b35fc5e35da2be46d0ee99faedcdd19 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 5f1c0e9777e3082c033615eddb814151ddb041f9..8c4b1966d85a7be1d2c22d08057d2d0738986934 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 2022dfefd0ff2ab2bb5cb1cabe9fcdc0200f6851..c5b2feb6f9cdba40c0b997e8717534ce6b3b8fe6 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 469b14750861c2e1114590d3a6f3cbe9acc38510..d5253b5abe36beb868f979459b64511d4771af10 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 2336b64fb5b1653a8170ee31479562f9de59093b..2e8b962a8c6b59443978e5d2e0ba1233ab091046 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 7294a470409ec81aaef54e8fa1a507fa6bc83723..a6a75784e988a063f78fc8994fd26fb059cce0d3 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 a27e7505e7706faf516f3c9bfbd34ca3a8dcc351..c266306cf0dd5603ce603947b91df299b0b64240 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 781748017a3d02e44388b806a833774ae0c1647c..0d566023cd30c823dd8cefdf7342f3bee22f0743 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 0eaf95279ce3e21834880c088e6e7c06e929b7e3..5e13b07c430a4c90f05d6a5d1a4395838e2e2195 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 f19d0161bb0d9c3cb2d39f43ad6231bd1ad04526..425916b48d44b30553e983cfc88beaee75b39aad 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 acd04861c5a06c6c2907106ee4a125d019e61526..a65108968c3e0dd1984b09eb14a39257274aa12f 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 5ed024f010ada6f12bb21912ebb13f9ef68dbfaf..81c6ce20477117bc234e143c85ee0f6e12803135 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 ecba0ed6cf76abf0bce9d2c60405c8474d59ff01..3c481cdbabea70524144745d378964a9dfbfd39e 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 98702bb324dff942d2544dd96d31fc9ca3621cd3..a0de2d62291cbe4927992be1b7e73b9b4bd37312 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 55291067b60b45ca780e65eb4026e62f5c8936dc..cf2e64e2effe07412d6f966fc115c7fc4e54fe40 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 8437bd1a430db769128339ebc870b42b263e7a81..07f4c4ad433781eb574817b632027531f880327a 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 0239b9889e1d0e14b33ead0dcf9050d845cd290a..7e21ea93c1e05b2bb606914bf5e5cc9b066ec09e 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 99af7ca528eba8a3fd3ca55bee21b1c9e432916a..4dd8b98d387ed5f8533d0730a23855d41a5aca4a 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 e0e07e5d6dee4de2d54715c056a7adfdb465080e..f0b3dcf025006256b3728d6ec47224730d6a2b44 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 70dc27bd664a5090faf1067d7b6b7cfd7a04c049..8e92223df0763a95f74ff8abcaf655e48a5ad27f 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 be662ce9a543b6ebfd26583c0dc094741b63dea9..d6493ab586877ab1d4f29eefa975469a363f0a5b 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 55862a333f27b2fca067b10481eabd968b58856e..a1bac1a25b8f554464fd8867bb514c87bffc3df3 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 a62b5d728680ea3678e946454299fcd125e339b3..f8f73746eca93e66f956f141468451181a0e5659 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 b51cc1ef3c7c4705f62ea9ba1b8fae19cca70d3a..c5efe8ab103d28ff4293e60880d3fda96bf0058f 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 1bc76398215cc233e7e4a932c4550177f5e5ae71..fecb5af10ac8748080117fee0fbdd1944d149afb 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 f068f42ae118f7bf20c3115f945f43d241c44ded..62151c4c3bfa2c0fa77347a61e6dee0490b29756 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 8f213bb1e609367cc5ebed7510a1dad7855a788c..440b1293db5de04b6e4c85b519de5d988b3ec04f 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 910c33157c5e1061b01d212271334c417331c656..5b27886e8adc33062ebb57add562d3422834bf9e 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 82a918a79807289521f4bbf870379c7b62f4f6c4..89a245a52eb46a1e44b5e5c061d8f623d720aa5e 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 289860b9427ddbcfc086a1b06d18cabdf955f188..b665508c6603d6cb42725b6136a9e70eaa7b852a 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 72c2f1d18544d912fd05e4b0883cdcd4c4580253..51cc300a6c12db0c240d9b922605ca01c1f8a73f 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 9e65771ef3235bc0aa16472f6ebd3223a0f97420..397e953b9f9cf444a65805a306c2de5823ba2fc6 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 07acae990bd0336c7975681103328645065759bd..897d70da81dbe81598976ce8ec735a7b53e714d7 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 b14c78cf77e9f6d54b684b585d5155923cbd7410..9d06c3e7d424ea63128d20dd0014860760b344a7 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 fb8a065f014de7f8c8b6ff3ffddcbf8d05ad92b4..12de1ee616b13d7a9b4150815795ef9b9a61a247 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 07caba561f82a3a99bc440ee98ab79b0920efac7..847fff0a8990ad45b445e26f914240c4d4ab71de 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 a45feff5f96105defbbccf0fb24c75a2f04821c7..235b523a558250305a7109849ab48ac164877d4d 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 83345ed2bae9c8a61a2af8cd57f4b01e043e35be..ad25e4ec13fea1ea9bac53ddb16a4f8ad6e741eb 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 fc61dcb875d7fb28793ab5b453627f171e686f11..3b126cc776a2b4b393aa066a935f43d721d06984 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 07c9e1eeb63fd5e7e1054ece3a4c5f505fc105fe..e7a1093334633edf5d3da1f0fa5f4a9ccd82fac9 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 e77056157960584b7a1c32fa3a19ca4cf37f23c6..50fef952b5b5faf3b5aa839a3fad4ec71f03967b 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 8510426ffd74b1b00198c78cfc3053afbb635823..0930afbb7c6d34015eeaa975bb74f689f46cea34 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 f3398d69a7539023163198e41e67265c4f4efb26..e94118dce287d4f2501c2fd08f9b931d5b3cf223 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 46fe0b7273bdda98e90a78491ed1b173b7cebba3..d62ac471e5b0d544cf265d9b92fb95349079dc47 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 845017f50e71112564ed6c29dc1cc767228336f3..1d0bcd33f8abffbd448cdea9c63d0d9140ab4e79 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 3b25965b62ee30ceef5e060192e5cbec1283da73..ae0cf508eb02003da8a2c118090ab624703a0bfb 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 c3c4a633beb44972aec9f74579486c860098d1dc..72da0c782d58df15d511fad828afb2979ef5aafd 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 34cb1fe48c1202599217315abf1603bcda1eb4a7..12baf1d02748506f73f4222884f994aafda0b2ac 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 ca5ebf2cec76e343ddb2634a10425bcd1ad2a510..b5c6cae1082a3341fc6e3d0cb848bf362f9a2e7a 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 275d0447200af95504bd8e3c917162f8ef0821fd..760fc8aa4f2c14593d57efd20bfa1559aebddf4e 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 b5ad400f7309785725fcd313d7121b19f62a4efd..803a92afdbcc6d31fd412878e4c000654f00fd3c 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 b4eda69c319cc64877d91b7a553470924e46542c..5d8ec8f9a161f9743cfdd132c47718dbd8f14fae 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 85415b1b00a4f375c4da5ffae81216c44d273113..ca67167fec8dec41b7a6e47bd403086e5104a7cd 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 d013faffb58b3b240a4aaa09c4713f05fdc9e25c..7408a223578c084e565b84950a5527f5edf9099a 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 7d89038e9c7429a6264b9a3828159a5cc40a8435..fcd6a9593dc15900335275cdf8ba65bcc5a3ac43 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 9d5bc6eae98ac0f8eb99cd73119e95734e2753ef..4e0670ff1621cd589ad5e6c8e86280cd2208e0e1 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 99b5a29dbbcbad6084910285f6b4d52c5606c041..eed68d24bc86ef73686ef52c618bcce53dc2b2c2 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 7031a141cf1b243863440e4f1f39bfda5f6609e6..85242fddeb68dab0c9bc73da8e83dfbfc3bbe5ff 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 e2e9b258731967a9bbb8874abb336c3862ec6be3..ee933a3387f3cb0795d25674c15939e2d96bb360 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 817094f4a2e5c3557d1eb1a30a8e599bedc93545..e7c2351fa672587abc5d5119d7e1f42d56d6d2c1 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 008ad1cd9732ad45b47b4d92ae75f616a5b3bb39..ff0403f4cf8bb6254c1c1b4c8840c2ad1f253b2d 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 5e3f0a01d04d9593326fe8c1272efbe9790df6e8..aa5fa7771fb3a44f30d0d13f9d28373ab753e90b 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 163d196e53db2b3eee6ec799a21114d1c96487a8..d1c4f9fac6056e4076d08f96492b23a7f8b7e43f 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 93b81552b6b769aa2f51a51e3aef37d4cf27507e..9adb407348932bc29da578afbdce37814e432e73 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 7bb958623527bf307355c2bd7f40a01dd395b524..70ff1a69a8eb225f78ea3a9c4384c4e760b88c12 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 2db8aa6227be7621b27e203b68ae993e1e015d09..67c1612fb7b030013a5d55747d270b9fd35da338 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 b19fd21bc95120ce0087623dc35f765ce9ffa9d0..06050bcc4452beb845ec61b96c678e903c88f889 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 77456d173b03560b85e69db34b4a247ebb11e92a..51ab05fd80eff78a4cfb1239b915f46f249384f9 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 ddec82e5134b7cdb7cf8d56dddd03f0fe8d118c0..1925010dd34c69e87195119e598e077fdbb949b8 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 832e141b09f9c51eccc23b6c5537337d6e530add..ab83f1f0fa64d2cccda76bd2050c7ad4c28b808e 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 43569ce0a8ffee54a0bc15c63548515e5b9f261f..c59e1844de7bc2965ca264c349cc83aa97697d90 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 1f5869e470b6717ba5a2a431275d38d6fb6460de..7a569b0b22184b82c006278dfd531cd488b21cf6 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 ac8ac2cf803bad2d813e876680f839563a71fe69..70751633e47dd5cc47ba54d919286435e09bea6c 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 a687f96004b86faa35f1c98ba4476f2aa4a2bff0..7d1c5865d076e48478933f415c6416cba1c765c2 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 e6c4edf1bb0064fc4934d1189f7fa0df4a850c32..fd6846e293ef3dee57af973721391d5cea29de09 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 4ad2b65dae5b9ac9933392c81569b8c5d38aa044..f83ca6d29325b5101f4f5c7b2ebc3a16f85039ec 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 35316ded7d20febc2420aaf7600c40315996965d..e51a1cbc1167b22e45ecc1af8c9e604131d63806 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 3e82cbe9ec7d1d30e036770d3f4793ed002bcdb8..183a88daefe59ee3dbe1d54f8e12ec3473098715 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 cce8d334a48f360e54a8cad03f46cecc3ced5884..b51598fb06d17625be1f80f835b35bbccfe07f39 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 4b0b4738d01fd4d11b40ef032fbc38839f6cbb40..0b69f2fe1abcef249fd2067faeae15d62f6df80a 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 d7130bbb0a20c4df837ae81adcbaff0837f6df73..bf519dfc64b7513d021dbcac3b414f9be87cb392 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 6668e1928e5d37ee5d9ad486efaa6796ea74db0a..41fa6c18a87cc32ce7aae163bb83d6b1eaf02a30 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 32b582ccc384002eb951b71d02d8905f297331ba..57c904ee4181dd3e2cc81d85015775e8e2165ab2 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 0000000000000000000000000000000000000000..cb7355ceb77f9037fccf18f34371d32e9d4dcda6 --- /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 540ae100e7579edbf5fcd387d76103aa03641894..3a0368061c1ed0d8c5b5ec49815f14d0a4899a95 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 0000000000000000000000000000000000000000..e7c1beaca60e702d40b777dc56d76de3564054f5 --- /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 31a304680fceb65d64324e39fca67b200677c9cf..b6eef62537c1a6dbbd5582e454599d7083368eb4 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 1567d23d25a85bc67d81ecdd0f909ab59b112152..2bff3dab23721f932ab949f054da00cb5b9a0476 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 b7ba47a8eed5b74a36902ae4b056e782755e0c43..666627ef8ab3592032dac7be5838d905fea58cdd 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 f98e28a6ef0f9b7e3be3c0fbcc97cd6b3ff844e7..6d24a783593d9a27a6a45a2e85f6a597d84a6ff3 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 fcfab56a55ebab155726e66ca5ac8a419a9b2e62..31f67387ccaf5890a9e69d16c1b1549bd80cebfa 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 fdf73ca0f6a3f335573ca059151fdce7a8cfc93a..0f27eb8805c647c648686b02beba5fd365d12272 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 09177465a609c2b2b9017b82d909749139f4d5aa..2ca67317e9b39b97aabc723a9c62bba7b0f9b119 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 ec7c77bd791174beacfad80cf1e937b68f14017a..eadc037623007dcd6d4daa33b5e11bab33944546 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 1b99db920db8b68cb1b0204d24fd51d9eae401ce..c3b29945216c15320411ddad66d84db2288d5438 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 874146b5d0e0e9c801b9e59792dac39ba716002d..becbc965f1f35df0b244c8b9b90e3edd930e3907 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 d5dbd3c34b26663ab3c83fc9fa004fb4fa3f74c1..5cc7f6f340b051b671269cc9d9dbd0d6d7193306 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 ca9b0c79449e9f8694d964bb6fa6ce478297bbc3..4579b175ac64cd6463f004a4112a507d0f95fa22 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 4155a747fe7beb0f02839a2cc3eea7dbbe047095..8ad224ad9078a9891e54c143b92e899939d219bb 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 4e689303548a76941e34a56e1bd4a0191569b559..c9c771a1d3e2137814d610d3f4b14a98d8f57e9c 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 b499e46cf87418fc3eb188b6c34bb436b51c21ab..46840aa0f0b595f31f51f24d1a8a5141678143bb 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 865632538f731871833b11d9885b4599901fa966..342b6db99621237fd4466bbdc7e4238ee7bf356e 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 11bb30db7ebe72aa4ea488ebd1f38fe8337d0926..294f8fe24f206402bfa6237003983d840f1f4ee2 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 bf351fa5bc361504ea6fd4b20c24c73912664721..7a44ecbe98101bb987da54b64c1c7eb3b6d63b81 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 81d1b1b503726e9e6d9ea20fa676e1b4c186571b..44b39111c07749ff150806a9636184c8c69b8825 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 fcc7547713a4b4c51f8d5f59203ff4e38099410d..d621fa7f124ce22c159ada47bbcf55a631d2de5c 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 68913cc003f281380cec03a75e85698decc9c7f5..ee30f05171eeeb963aff420a8dbe92316b7b2e97 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 d55479c62ed622bb7933b1be0073cd06c1e9dfe3..802dff3d82e68015200502c870ac6a80f3a96557 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 8ea53aecc4a78bef88bbf76bc73a8299e3c24596..8fe1fb03f1ce29d22acd48b19e29093349580742 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 d45a98f6b70d00d3cc1d4ef429755f55b25ce91b..ef433aae3b1aecdf4f73e0a8f21583889ae4a09b 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 4fa296b12d8eff3f21803d01cc41a6cb71575f85..42bf44fd170611bf6104be8f8441d2430b74532a 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 a5c2313f39bd5df957ce31159ed14ab8f56cbf8c..5526ad052ea14ccfbd4c99f08e506c729592edb3 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 e732b295b774d56d5d9109387b1e5a217d3b811c..56c139b26e00c7798e51f89963fa84bd42a73fc5 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 bd5595c3c2433597919ccd104d19fa086110bec0..f49201f5a94f3f1275816a07d30a40158fc9b54b 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 7b19fa019b2174082c0e186efb0335f83ef70f43..fedce00d0c87a2a718e9f0a0f53c0e9c31a23615 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 7ebccd091e83e999e430486d9a30c3acc6db4c24..89cdf6d96d75d878b94240c1adc2195ce80e74c2 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 0000000000000000000000000000000000000000..b254807143481fb38cf6e7c6c9bc0157866ffe6b --- /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 0000000000000000000000000000000000000000..e76025b9c602fb65e4f27f3076da2b1e83dd0b87 --- /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 1ba8c70725e66a74b9434201542d2c770fb42a7a..3850193128315f7a48d52b638d15d27ca07a9a88 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 0000000000000000000000000000000000000000..7eb3ddca9ea0ed9d1a8b43d5c580c4d2ef74b1bd --- /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 0fc6bfcb16e56edab6256b3374ea97011e3924a5..f0bb5e2a9cdb51bcbeb0a2dd1bfc31b3b3fe9fb7 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 3b268684026c640c8e00e79f4af7e4b65ac5727e..9f94198894668f4287897a5ffeb941db16dba86e 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 4dbb7427c0ac3b04d4043db524cb4642370c0656..907e680258498ada160a9386c515f7e298f881b4 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 caae832086db72275d9e25098b6c1261242db161..54da294d30ce7864c8825e7ccf5d7ecb589c7fb9 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 8871c12577a0d9815e532e193f63082401d0fec9..b9063579e7bf615674cf05fda25cae69c3f31d63 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 71afd922fe8f75092547ec4ff8b72aafd0c2193d..526e160f429deab9d75e6c264030019d1a81a930 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 315d787dc2f595f960295f78ad5b930e65460e14..809b7337805ac3146ab9a4ba30d22f8b7fc1b5f7 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 02db2ae8277f3bbb31936ae18c86a462e7dc3f25..8b535592ed2805808bf532bb5069a8a91bb16dd0 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 002f509970d4d173c9f55ac3cfb5447ff51ed151..bdfc09d82dd82ef5b9e64fdaa89dfb4803415733 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 b8571aae9268d793e1375838e2214a8b4cbfab95..9dda10aa1beb3140bc25aa8616a0556122163257 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 aff4c328ef521c532e5691ccb3d61913bfbb4236..b310911c63448404d81e720c902b9f08564b61b9 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 5fd435eaee86d76c93f0b4b6c186061a3be839a0..225ff9db77d89df95fa00056f447ce647ed635af 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 1a317397cf39143c7824edd4ca636587863a2177..8a78cc1797a97fbdd44aff8c24a4003fc5b5f80c 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 e33d203c8a8bebb01d2feaa9c2e1e16b90b11f60..44a3461c8179b6fc1be1820df3fbfb893efd4975 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 413e534368db4cf7f7cafb7d6a83421844e7179b..359ede6102f6c599ff9e66ea8f3f298363ec3876 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 06ddf45af067b7f72dd9706776e808ba7d9e94c2..419c3a12b5d958a36a48468b666e58192e4449bd 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 6dc8178f92386f970d00bacde81ed1bb55b2b6f6..af2aa57cbafa85569159143b2e3e092670c65660 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 815a032f4adb2a00aba328a7a32f3a06fe2ed619..554c7d5f628f96b5117d8213c94cf7266f290054 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 a7a84df517cce062da4f3301c1e91ea6b6274078..b99de9b656b00d33f627ea99df51774017f47af7 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 2ad4b14c5796066b1e1ef25d4c9e605a0df5d7f7..792eebffa566e038ed3bb7b12d9e46251194d36c 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 04db161d536d113ec09b1911a3612d3386c8e2e7..de70125b3f30b22f002c26aef6aa8961715d6c63 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 c49dfe49b787ce6f994a4f962857e3ef85d74678..93dccc4f5c1259e9276e059ebff2b59476a816fa 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 ff1c02761964d05061b2b1d97506b4540ecd2e6c..aedda612f757299781ef790747ba3a6ab2087da2 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 87a86585d577f6fbe83f98736f658315749661e9..b61e9283e727e3b76d591b410a01fa2602b7a943 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 0000000000000000000000000000000000000000..2221146808f85d65e0c0eeaadfe2a0603b75445d --- /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 0000000000000000000000000000000000000000..3499a2b170065967efa85ee4f86c9b622b251841 --- /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 0000000000000000000000000000000000000000..aed3b0494cf5d4a6ad9a09911d83a88ef51c81b0 --- /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 0000000000000000000000000000000000000000..1bc013fbcc140b7fe9585c42ec3d74e98fcddd1b --- /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 0000000000000000000000000000000000000000..d5c8da1fbac331324c54db788bd04d42d459b6dd --- /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 660b68d6d9cfe177b730c218583ec3ca35101bbb..b17024f6a8d854683e2ecb62514cbafc96864eea 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 cb5311ff760e710b801ccb0354747ab3e9517438..83ff6c9a0bb44c6d717580ee1131ad1f67d15d41 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 0000000000000000000000000000000000000000..bb0f44462cdd623ccbfe430847308fa9baaf9cec --- /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 0000000000000000000000000000000000000000..dba22395527d44ec384ab0b6b9d810a08e8b2647 --- /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 0000000000000000000000000000000000000000..38c1e72a08957559fa32201bd6a447f925f35a0e --- /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 0000000000000000000000000000000000000000..78da5007fda7be2cf971d44b6364cfdb551447d4 --- /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 0000000000000000000000000000000000000000..676284d0ea2a83a45fa8c48d2c5279017c605151 --- /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 0000000000000000000000000000000000000000..4f543068a7e1102e2be056c2a8161a888d90fff0 --- /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 0000000000000000000000000000000000000000..c7ae3453dbf42df85bcb38fefa8a76854f8d2c5c --- /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 0000000000000000000000000000000000000000..25af5dbb64a4fdd811d57b78666aa82585cf4c9b --- /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 0000000000000000000000000000000000000000..184cdc608b59f0fda6a6c4bf07fc193fcb31bfa2 --- /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 0000000000000000000000000000000000000000..81c65a819db36d5d9ff63410fde1f29a3bd6db69 --- /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 0000000000000000000000000000000000000000..7c58ac0f46a5bbf89d8097fd8e9c1a45d3a77f05 --- /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 0000000000000000000000000000000000000000..e261c7a896904431e550131cf2a26c8c41071bc2 --- /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 0000000000000000000000000000000000000000..93fca56223b9eb996621966f29a1e5ea9a34d195 --- /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 0000000000000000000000000000000000000000..04b5a2569a0c36be6b498544f621a1208f9c0ef6 --- /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 0000000000000000000000000000000000000000..e07aea64185d29c0d29feac86d794dcd955b3cf9 --- /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 0000000000000000000000000000000000000000..fbdd29aee0cc9e83b149b4f7a2c364456bf45b41 --- /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 0000000000000000000000000000000000000000..6d943e72e0b0fe7c15e1fa303b40d8d106f9588c --- /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 0000000000000000000000000000000000000000..d09eef4c6b6484b7c6647799b78b2e625eece1c1 --- /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 0000000000000000000000000000000000000000..d3bede8feffcb150639d4e686d063bb6d3a09d60 --- /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 0000000000000000000000000000000000000000..b8e554d3fc47311d721c8b362ca1eaeacc62192f --- /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 0000000000000000000000000000000000000000..f29f5d2f5b72fcb91c66d9598e89f142221423d9 --- /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 0000000000000000000000000000000000000000..1d394cb4bcd49934f952a3b8a793f36092bec0a8 --- /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 0000000000000000000000000000000000000000..104286bf05dfd9a6256856646fdeae2ae3f2346f --- /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 0000000000000000000000000000000000000000..6ca5b5230af592f0507a57df8bd0bef561770544 --- /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 0000000000000000000000000000000000000000..fdd8389b699276632e1cca2c37369174cc3e6dd1 --- /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 0000000000000000000000000000000000000000..b8b464aca67ef577dd64d0c0914db3331c51b9af --- /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 0000000000000000000000000000000000000000..5122031de9e3e91cf1f239f8d1d07480f8415c10 --- /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 0000000000000000000000000000000000000000..07f3a0ad59c8a526b66c49045ab2a4ad4f6ab92f --- /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 0000000000000000000000000000000000000000..35d8c0550584d824d58c400a2cf0f6fba4f930fb --- /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 0000000000000000000000000000000000000000..5345458e5576510768111b7d6717a3efe897b1b8 --- /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 0000000000000000000000000000000000000000..67cd85ec5fc14e8b48c08ef7c8cfc531f668be78 --- /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 0000000000000000000000000000000000000000..0d18d122db0fcc20ab95ae638310e73e75005772 --- /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 0000000000000000000000000000000000000000..eff3922337c75a0157a313d2aa2e551346f465d4 --- /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 b01bba159f34a6d05c2756060681f1c338fe2f07..93ebe20e1baf5b96d30c93c6036233ebc78392ad 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 0000000000000000000000000000000000000000..d75196ee2e1dbe344d7aba66694fe08eedacb085 --- /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 0000000000000000000000000000000000000000..b0946a22a42aab37c8c6b3f288d97dfd95505a42 --- /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 0000000000000000000000000000000000000000..e730496730ae0807f9e6b189087555d76109bf2d --- /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 0000000000000000000000000000000000000000..a02935b5475136838d1844353778f7959c7cfd2b --- /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 0000000000000000000000000000000000000000..a1b71600c22ffa860585cb409a71861522e25712 --- /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 0000000000000000000000000000000000000000..bc184e534f4f84547d98306bdedc79fc73f08c42 --- /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 0000000000000000000000000000000000000000..0184c54b0c3f9852c1efbbbe8fa687f0073a6dee --- /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 93e9bb6dccf15e4c5617b75ce95e4c36b03e8133..fd694b4e26be1612bdc2dc88da0cbd7d0c951e5d 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 0000000000000000000000000000000000000000..24eb5ab2c3576a4abafd719784655a11e430c1c8 --- /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 0000000000000000000000000000000000000000..0e04fcc0b4acc1fad218f7e3a0af056b3a65ea2e --- /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 0000000000000000000000000000000000000000..b26d3770603fe00bdf6840789ce0ebaddd93c0ad --- /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 0000000000000000000000000000000000000000..603d3b5da5463db13be18dbc7d2a05e262451ee5 --- /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 0000000000000000000000000000000000000000..ea59fac90fe4d1e42917064937eac80e61259673 --- /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 0000000000000000000000000000000000000000..136153c671e1cbbd3dbe6bfd05c795b733399a21 --- /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 0000000000000000000000000000000000000000..dae048be7613b48ffa08dfa1389b69091308a3b2 --- /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 0000000000000000000000000000000000000000..95b848b046eb93ae96077d5dd20dea801aca5219 --- /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 0000000000000000000000000000000000000000..87b99dd53fa7b51139d71c8b0c48ab25db12c82c --- /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 0000000000000000000000000000000000000000..92085e31d1620d08f8d2d5702aeb70ef84564cde --- /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 0000000000000000000000000000000000000000..a995e6f2050058b756b3a8f2968ff2fbbff13f14 --- /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 0000000000000000000000000000000000000000..869928b07bc9927103ee1ace14a8e3138a4057c5 --- /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 0000000000000000000000000000000000000000..8da1e289c17299f3abddc7ee77ecfcb8887c1b4b --- /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 0000000000000000000000000000000000000000..dea5c6fb4bc49cd976cc39dcf04d0d074d1966e2 --- /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 0000000000000000000000000000000000000000..75a26a7bd8e8dee651aaf03ac108818ebb685d79 --- /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 0000000000000000000000000000000000000000..dea5c6fb4bc49cd976cc39dcf04d0d074d1966e2 --- /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 0000000000000000000000000000000000000000..1379bdcbf21c8aa1712594e9b159834f90704a18 --- /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 0000000000000000000000000000000000000000..b829491a1a6c5f2f16c36cf389cd928121375a1e --- /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 0000000000000000000000000000000000000000..283229ff8c2ec003ea2b77fef10bcc8bb7bec4c5 --- /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 0000000000000000000000000000000000000000..a82760e6730f0248f665ffbfd20a406f17b3ae15 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..de420f0b9a83b52a1f82e36b7fff9379520c3689 --- /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 0c498e13107782a7e40b4d454d048407fcfcb8a8..08e3c45af6f479cd34676ea66343ba1caec145f4 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 330ae3e73e79b202465fca8989450ae42da6434a..d9eadf243285c6845c455a015470444d33b4562c 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 0000000000000000000000000000000000000000..fd3396dcca7cfd62380372462aece9747629513a --- /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 0000000000000000000000000000000000000000..d3372a8265f6da12ebf3010b3279b1860510f2eb --- /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 0000000000000000000000000000000000000000..c98e5f64bfba15972aad2b30344c1edda688f987 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..74ad22575d33fb8db6e3b88b2d28c009d348a827 --- /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 0000000000000000000000000000000000000000..3dd6ff261f59091a1342b832fdd2b392b60cde61 --- /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 0000000000000000000000000000000000000000..60bc2cda87d1ae87af6d1a6350a5da21678840ce --- /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 0000000000000000000000000000000000000000..ccbedd4692061919bf6fc9e5da03e82293e78af2 --- /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 0000000000000000000000000000000000000000..5285260e1fe99d17d153fcc8a6b410a4a281583d --- /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 0000000000000000000000000000000000000000..d12504ead1e7074eb3b62d1ab2ada0fb9488548c --- /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 0000000000000000000000000000000000000000..3ac7007ee8eb19d2183b52f81c95d6bff296f583 --- /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 9ba95f2dca8d71242da0b7651cdf24b522b4c52a..361367275024e9629f29c155d1227341cc029294 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 48b0ea1420eda6bb033605171903faa1102bab84..fef246459a37e9856d1bbe02c48e2df9a7994923 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 33a46cc1163ed1d092ab0029c4fcbaa7c416848e..5fd27778900e87b0e388ce8da3f328ad829c853f 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 0000000000000000000000000000000000000000..c1f0fba3665fbe24f654ec0c39b020589dcdcb55 --- /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 0000000000000000000000000000000000000000..960ea26688f6923339ab0753fb6120587430ecb7 --- /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 0000000000000000000000000000000000000000..4794255e55a7bbfd89ba2011af6ce4de32d218b1 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..07b92d48a45de620e03b10ea15a83f66fa9804db --- /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 0000000000000000000000000000000000000000..f2567c2742996856d316c010165302644dffbccf --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..3ed1959d0e219e5eb113f38f4838fd91cc6582f9 --- /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 0000000000000000000000000000000000000000..05bbf02f015fa2c4bf142aeb63094c4ac6752799 --- /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 0000000000000000000000000000000000000000..454d47285fef442e7c172c29eff5cf7906136ce8 --- /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 0000000000000000000000000000000000000000..5eefe10a6e50a1fa7676a369adf5642fb96bb6bb --- /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 3012f72487a75b7fca738e7cbe281fd6140be212..301eeac5f2a87a7062b57b0f92bda1a84dbe0968 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 7585829ef3d7dbc2a2f52a78e44b59946a8623f6..3189760b30636ccbb95b378e57c7b800ba0b776b 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 30889bf94eafd65fb538de5468978c29c4a8a0c2..c38bf787aa5f0199b040eee8dc143a84ad9f263f 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 bf46feecd239883e273cfd19c8f22129fde36a23..e8a83b74806993718ebeae3042f7584d232b1dcd 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 2dde3147798799ded1472a25fbaeb47f74c29ad8..24a265388f7a8be35cbd1afdd0689938c37600a9 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 40bde336a247b505058c59c10a9ace5025694528..80b60c8514946b615133648a78d78996dbc0850f 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 558319752041d8622831eaaf93df22ca5e30a74b..272d80f0c6c24761a5f5e665a9e7236ed8783a56 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 0e1ce6aaf94087f5c966fa85a22b60303d0ce6e4..48f99fff5803a29722acb58ac313d70a1b50ff97 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 f6eb1a1d571f68014f6944dc2cfd7734a9b959c1..e6d3abae227238f8f174384b633af3c3cdedc79d 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 ffa975f260a74d38ef48c2b26686515abf7fd6f3..7a9269e4272276aa54d0e56be3f468a1a5ffe17c 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 0000000000000000000000000000000000000000..7f71b9dbc16684543bdd5da25e24db0bc7e2b04d --- /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 0000000000000000000000000000000000000000..af6028cf8864734d97a2c4b66fc0efdfdd5bae38 --- /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 0000000000000000000000000000000000000000..5bebd1d23856d905158c8c6b7a832431a78bb8c6 --- /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 0000000000000000000000000000000000000000..3dd9fe55dc3b955121ade6cbe0200748785e2198 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..b5b1cdcea45f57de1e84b0cc381082395f60bd7b --- /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 e266668ccd9720680f0eb547dfa1cd960a445196..1634feb4cc13fa0e19379b2fa45890d59ff60a9b 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 01bb3a6baaad78b23297e2f98472babd5e5dc8fb..ee387e25c8e1e85651e54bd1ff3b0ddd7a2b37e4 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 9de8589678812649523acf05c71c46effc776349..8b8ec7dd4997dd2b5e55730e5191a0960753e9db 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 4fc1cf8743ab9537301d17033bde2bd79e4fb661..e293759b3877d0c77cc8a416aaf4521e657a93d3 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 730656609b73b038440fb26ba8f87d1f5d787e8b..525260d68d7e16240657035836c5c69cdea017d2 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 38c756dddf192938361af308486fc45bbdb22fda..2b0ed960ffb9f43e051044241202272849e8a6ad 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 6e24c23200acf7b3b9e7d9f9bb35bd6acadd6c7b..0d7e46bcb1940e6fcc1c5b4cffafffb6922d1c98 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 9630a64ce0076d77004bff6382a11526ffa21b29..6f008abb2f413a4faafc1b520c0d77c50ffa7c96 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 36280f545d852d1931499bf6e5bba78eebe504a0..03227affb2fe30717dfc79dfbccf21c600e5bdaa 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 0000000000000000000000000000000000000000..3eb7380dc54edace4ffa3a77388a0adbd8dab25c --- /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 0000000000000000000000000000000000000000..f3f58b6c1c30810ebb46ccc2ee999d89e2cad06f --- /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 0000000000000000000000000000000000000000..f736cdd0203b8162bcc8d595a16b423b2e46dde2 --- /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 0708bb16bbd3790293ba9c60a181c524acb9653b..780277f3b5e6faae9ee1a498a2daeda2c488cde2 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 d94a480459e71fc2a985db0c5fec002a2963d2e6..dd81bd5fc08ea2d6ba7104e354be4fc824aadd7b 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 298bccb672a0fb29f2c78c60709c6069219b4f71..03441858c675c0c5afd18c20a058a864b77848c9 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 0000000000000000000000000000000000000000..a86414bc47839254ae3d177e4b979b750663921f --- /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 0000000000000000000000000000000000000000..1508bfdbb3f55ed122027c148f0c457d38de4ab9 --- /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 0000000000000000000000000000000000000000..6443a2fdd99ec0666fc8000f26b6778d7743586c --- /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 0000000000000000000000000000000000000000..d6958e1af2165f3032a1db8deda8d6f1b45a5a71 --- /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 0000000000000000000000000000000000000000..1555ee2cb1db769a9b23f4588ee69fbd152cd73e --- /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 0000000000000000000000000000000000000000..7d081018dacbd8ca01840d451c353fe79fbf9dda --- /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 0000000000000000000000000000000000000000..7108fd5321b36ba9803eb7093fda1396ed143213 --- /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 09f4f18179c1ffca14574e8462866d1ab74c2dbc..bfde2d4056a2751442b1091f58e1013b56459199 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 346c89ba491869c68674084d0336a3cb501f089b..7a6b76605d72f58280996440ca14ae8a90a7a884 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 0000000000000000000000000000000000000000..6bbb4f7aa26693abf72f2b222f1dc1ea5a1cbe4e --- /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 0000000000000000000000000000000000000000..31c8a033905c79d22f458b505874d430f7bbe2e8 --- /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 0000000000000000000000000000000000000000..316c35ebc49e2b95aa06f6f5db40a63117c4b485 --- /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 0000000000000000000000000000000000000000..d113ca87ce7ece7549c6eed72589ecfb6755d2d4 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..1b788684ab70b787c38ac1ac5cacd27bc3635cae --- /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 0000000000000000000000000000000000000000..65ca6aeac5b1f884b3fdb886b095d20ed0ac7f98 --- /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 0000000000000000000000000000000000000000..81537789c36c2103ccbd0bf626e2902459d8bc35 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..90443b2310311c77236e22cf46d7b8b7b15b2ac3 --- /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 0000000000000000000000000000000000000000..e51d89523e9584910fb3fc3b978161dc7163b3f0 --- /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 0000000000000000000000000000000000000000..f91c028fd55bd7184cff352850c12aaab67ac90f --- /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 0000000000000000000000000000000000000000..9dd0b4bcfdcfb6373452cb8ef7568bfccbdc7911 --- /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 0000000000000000000000000000000000000000..19102815663d23f8b75a47e7a01965dcdc96468c --- /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 0000000000000000000000000000000000000000..af6c0542e0b2d37b1b742ef95c1c999a218ee50e --- /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 0000000000000000000000000000000000000000..b5bb20a764d9cd039b8ba9ab9837de63eb98dac1 --- /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 0000000000000000000000000000000000000000..07699b8874a209c9cb32340a9234f7386d043252 --- /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 0000000000000000000000000000000000000000..591a8d3ccd3d231a2e88193b1f559a6567f71b0f --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..9b7d02ce35f92343cc595b9c6fa1a5fa8bd3fb0e --- /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 0000000000000000000000000000000000000000..2c6b557f59e6211515eac4e2438a319f09536013 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..150f69ecea94d2871eb069199c77cb0293962850 --- /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 0000000000000000000000000000000000000000..20e9432d60f97e618791025c41e83ac3b9ef7163 --- /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 0000000000000000000000000000000000000000..31c8a033905c79d22f458b505874d430f7bbe2e8 --- /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 0000000000000000000000000000000000000000..c2a24a7e60900b64d4b65de794c2201174bd2baf --- /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 0000000000000000000000000000000000000000..485959c6e5e0f0e5581c4a0d11816c0ddc3203dd --- /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 0000000000000000000000000000000000000000..67e6961a9ec88d6e735cc7ecb18a64f8bfb83b34 --- /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 0000000000000000000000000000000000000000..5532082cfccd09e9b1dc70142e71b2c10213d59b --- /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 0000000000000000000000000000000000000000..2b8d7b184e3af53f6030fce7f604c002a4eeab90 --- /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 0000000000000000000000000000000000000000..290a0eb01c1f7eb20452e56b571b82eaf4e9561c --- /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 0000000000000000000000000000000000000000..5bd422d9621fd526e0f8c710dae8467d365405c4 --- /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 0000000000000000000000000000000000000000..2b748f2edbb4c213084ee762447e39fb18c95ffa --- /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 0000000000000000000000000000000000000000..2f1ead1c8f54401ba046ac3c50148a40fe2eaee9 --- /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 0000000000000000000000000000000000000000..99710c323364506cd3cd4af226ac79e773e59137 --- /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 0000000000000000000000000000000000000000..339eb30caf0ff57f8c64011b15c152807ab3af26 --- /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 0000000000000000000000000000000000000000..f8df10b83b9d7bed51dcdbd53c1ddefae6490ca4 --- /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 0000000000000000000000000000000000000000..22ce876fab64cf1fcaca6b1c8bcf3168ef8c85c1 --- /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 0000000000000000000000000000000000000000..77cb5f5286125f441a571950c43df7f6b85dc0b3 --- /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 0000000000000000000000000000000000000000..ba49480c28d325e2b2fe13fbfa13879aa13a2d84 --- /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 0000000000000000000000000000000000000000..be6c20e5b3984511e6d030941c2fdf642fb12c92 --- /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 0000000000000000000000000000000000000000..8fcfd68830ed72843b0f0ee6b03321f5a4212935 --- /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 0000000000000000000000000000000000000000..733358afb3b9fc608d325684122b64ef3fb0a3f7 --- /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 0000000000000000000000000000000000000000..0c17c1bb61af6280f5b1c3c829a057675c0a1115 --- /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 0000000000000000000000000000000000000000..63595ad1fe82174f7805774048f6ac7046357866 --- /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 0000000000000000000000000000000000000000..bff9d7213716e1dcb498b6567183ddc791c2803b --- /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 0000000000000000000000000000000000000000..e1992f6628ddb3eb3f31e239c39bc606aab51cea --- /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 0000000000000000000000000000000000000000..7d1609a76152b6ee6804a3739a4eadeb1f0d919d --- /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 0000000000000000000000000000000000000000..454d47285fef442e7c172c29eff5cf7906136ce8 --- /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 0000000000000000000000000000000000000000..3140f336a8667dfc0058a9bf99b7ceeca3f5a99b --- /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 0000000000000000000000000000000000000000..92727a35cd1ac71343f1b0d2dbb1877df491235e --- /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 0000000000000000000000000000000000000000..345e6aef713208c8d50cdea23b85e6ad831f0449 --- /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 0000000000000000000000000000000000000000..f14d3e285112c3a79dab7a163f0d2d89784f65e3 --- /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 0000000000000000000000000000000000000000..092e4c3517a4b103d672b2a1470281ac3ab8ce61 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..5d3cd2e7ed900447a3f0533a1f0337f8e0f4657f --- /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 0000000000000000000000000000000000000000..467144995b0f31b6607b2836d2e7a137ce2b2965 --- /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 0000000000000000000000000000000000000000..31c8a033905c79d22f458b505874d430f7bbe2e8 --- /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 0000000000000000000000000000000000000000..56a6051ca2b02b04ef92d5150c9ef600403cb1de --- /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 0000000000000000000000000000000000000000..876b73ce0e8af49137abd532f5be31adc164546b --- /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 0000000000000000000000000000000000000000..15b04b4e4123775bc997ee703ffe905ddb565e98 --- /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 0000000000000000000000000000000000000000..6270ef1fb6ac8c93cab024677456968304ea8d12 --- /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 0000000000000000000000000000000000000000..c568584970f9e90de89901e2245034e8a6d3c319 --- /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 0000000000000000000000000000000000000000..c7b94e5e46a3bede81f5bf24f6c7c55f73a7499c --- /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 0000000000000000000000000000000000000000..931e949853da8a4e172ffffdc1fede768ca0d12f --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/misc/projects/Issue4404/src/Macro.hx b/tests/misc/projects/Issue4404/src/Macro.hx new file mode 100644 index 0000000000000000000000000000000000000000..622b175c718aa3d80233cb34b8c09780ba1426f2 --- /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 0000000000000000000000000000000000000000..7807c42ac7827e56016b35ce189229b89f7476a7 --- /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 0000000000000000000000000000000000000000..2eb888fdff2c2bf199ceb3e8b3221dc7b44e8652 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..7358f10f79ac0ceb8a8f98266cd4ef33fd2ab972 --- /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 0000000000000000000000000000000000000000..dd732e7d68728a306d3a6d378f00473f06f4d379 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..d1d333e899a4c0046fdf637586e01b15211f6b4a --- /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 0000000000000000000000000000000000000000..e727700208033c9808eccd9b3c273d19fdf29b42 --- /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 0000000000000000000000000000000000000000..31c8a033905c79d22f458b505874d430f7bbe2e8 --- /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 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /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 0000000000000000000000000000000000000000..9bea66fae22306bcc4f7f5b045cb38e5bce30cfc --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..8f16a624ee07ae21153f122d3b9d3843d50fd5da --- /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 0000000000000000000000000000000000000000..44d091308abe642fb97fb0f734c534de4dc3c1e5 --- /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 0000000000000000000000000000000000000000..f014a353141e2be93236ed258ba839c0d91df7c6 --- /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 0000000000000000000000000000000000000000..86d2aec3f7d904be131e08fbd2cd2f5eef052011 --- /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 0000000000000000000000000000000000000000..c30020b138eb34b12c568601ab5d23658b5fef24 --- /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 0000000000000000000000000000000000000000..31c8a033905c79d22f458b505874d430f7bbe2e8 --- /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 0000000000000000000000000000000000000000..029d0855dbddb3099fda08189c9aa5bfe64342e7 --- /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 0000000000000000000000000000000000000000..f908e06665290c0e25fc07dce5753b5c078ce4d6 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..c0483b938fb32a3c52b30ab4f894400da0a7406f --- /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 0000000000000000000000000000000000000000..d5e8fc642c8aa9dd47a0cd3fca8ad4b702ced9ec --- /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 0000000000000000000000000000000000000000..5c7e0d6b62e5e7b27d459c23f9fd83dfd10e9c3b --- /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 0000000000000000000000000000000000000000..3c783dccd0e556fe81ecf6b477ef84a9c599ee70 --- /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 0000000000000000000000000000000000000000..7f246faa5ea248c7f14745b36a0448682491e04d --- /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 0000000000000000000000000000000000000000..1637ed7cc55d14181a7fa91f8a1376a921fd60b5 --- /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 0000000000000000000000000000000000000000..1015330537a2d670ef9765ae00b8f87a2ae75831 --- /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 0000000000000000000000000000000000000000..1637ed7cc55d14181a7fa91f8a1376a921fd60b5 --- /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 0000000000000000000000000000000000000000..f738186b4317f080aa950c31716656e84a3b508d --- /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 0000000000000000000000000000000000000000..35faf9725d5fbf574240fad4aab045de0d375ed8 --- /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 0000000000000000000000000000000000000000..34c9a3273dfecb06f1e22049f4219394adf006fa --- /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 0000000000000000000000000000000000000000..b66bb85d1cbe24a53f79eaef3d3b71d5a2855c2f --- /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 0000000000000000000000000000000000000000..1ef241259edab94cb7fe56c6584d7d64b5c43ec1 --- /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 0000000000000000000000000000000000000000..12c14c5bb41d1390c790bee6bb85a5ffd0448429 --- /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 0000000000000000000000000000000000000000..10471e9b4fb45fc337d0bbb81a73cd991c82031d --- /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 0000000000000000000000000000000000000000..34c9a3273dfecb06f1e22049f4219394adf006fa --- /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 0000000000000000000000000000000000000000..1061b66d911e344180c88bf36ba03e89dcb157c8 --- /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 0000000000000000000000000000000000000000..de8e60c3bd214b1d29c2540abaf07b0ba92fbc66 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..5b6a0b6752ce2c9d3dd6b28f20d937d76b42897f --- /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 0000000000000000000000000000000000000000..e51d89523e9584910fb3fc3b978161dc7163b3f0 --- /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 0000000000000000000000000000000000000000..4abddcbda65e14b96135f2c16ad5c15cf22fb615 --- /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 0000000000000000000000000000000000000000..921789a35a8f30df06ea98e5f5068cbd7059a403 --- /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 0000000000000000000000000000000000000000..fbbea3aa53aa1548f969efa291927e289ea576c8 --- /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 0000000000000000000000000000000000000000..01e79c32a8c99c557f0757da7cb6d65b3414466d --- /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 0000000000000000000000000000000000000000..38082416ad36ad3a1ba096253aaaaca32cb76af5 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..800c07cd3348bb6d5b7c5f19739020eb3dd8d1a1 --- /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 0000000000000000000000000000000000000000..d6840f536d1c180bbb4faae871ce7ea4ce424522 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..075bb0f08348ff4ad61e1d037cf476ab201c2d9c --- /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 0000000000000000000000000000000000000000..41d36097f90060102c76285f15dbddb42d22762e --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..ada21cd56a5c1c38f256a41288015110a3c5a746 --- /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 0000000000000000000000000000000000000000..3312d35e38b4b7249fc98ad7c6f11f5da3172470 --- /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 0000000000000000000000000000000000000000..e5ddcfe1b8a187887b1a6b58e55aa154d9fc5376 --- /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 0000000000000000000000000000000000000000..121e488c40b13881f25538e1b272e291556f44fc --- /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 0000000000000000000000000000000000000000..454d47285fef442e7c172c29eff5cf7906136ce8 --- /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 0000000000000000000000000000000000000000..db1964c5bea69a9d9c38d1a09fa6d9ba79469698 --- /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 0000000000000000000000000000000000000000..1c65d40362e3215c168a85c83d44ba01c6de2156 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..a4dfe45e3c923e582411c02862af0ca8550b42b3 --- /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 0000000000000000000000000000000000000000..75638c66f262ed30cde5ecfb317ef6f4726b013c --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..4ab6e51122dc5e05a97b74ff16d8bc5411067e98 --- /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 0000000000000000000000000000000000000000..934834db0d2cd1a2c923c2d62beb11e1e1941309 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..9d5d90f004f63088c3dd447e6bec04a1f3cdc558 --- /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 0000000000000000000000000000000000000000..373608c47c70b592805e855100f95b8249f89208 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..2b300d69d5f9b41987e910aa074d0cd7d3e4d204 --- /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 0000000000000000000000000000000000000000..7fe6d4ec0eb40b6c30b38af32ea19eb07af0cb8e --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..d81bcc17100175262281fa6c53805b7cd8a63b2b --- /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 0000000000000000000000000000000000000000..78133cb82d4e03592b36c36552cc5925cd5efa13 --- /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 0000000000000000000000000000000000000000..4a11f68bc376640fcb0088a00e7acb4c9040ee0a --- /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 0000000000000000000000000000000000000000..600ff2496d0373b6ba58e3eceeb08c17e8150230 --- /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 0000000000000000000000000000000000000000..5bfe3295d1fe3c86f110433ccc60264cc47dc4df --- /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 0000000000000000000000000000000000000000..ff09158c1b797901ba55d42d49428f273f05cc55 --- /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 0000000000000000000000000000000000000000..1f914b4caffc7ef01632b849b98e1b700e5bad06 --- /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 0000000000000000000000000000000000000000..f1062202676164001ee970a599db953dc4c544e6 --- /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 0000000000000000000000000000000000000000..600ff2496d0373b6ba58e3eceeb08c17e8150230 --- /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 0000000000000000000000000000000000000000..647dcb39588f0063f2b17c2e8f555e9ebc398f57 --- /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 0000000000000000000000000000000000000000..10934d6b9b33a58c804b3feb06fc9f5ce9f1a083 --- /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 0000000000000000000000000000000000000000..d7a4672bb8b25917bd7d613af362454db43c6aad --- /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 0000000000000000000000000000000000000000..21bd6df2bcd3be600114e38e22cdf38791e8cb38 --- /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 0000000000000000000000000000000000000000..e5ab17724cef99536286226913237f3dfdfdbd22 --- /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 0000000000000000000000000000000000000000..ddf37d0dd6397abf56c4b55bffeab15af7bbafb9 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..34700622fc2759972e331baba3b4623e296d6073 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..505065a403c8ac128720dd1a048a6f483d67e6e2 --- /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 0000000000000000000000000000000000000000..0ba9813128adba4fd19712b55baea06415431c3f --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..958af15ddad8361ee91766e6f4a1411ad0797538 --- /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 0000000000000000000000000000000000000000..a41c1f1ad13f896ea01be5c7214aa269d069bf0b --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..584396cc91cfbb0d8ca44c888659802ec9f4a24b --- /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 0000000000000000000000000000000000000000..881198ec4acd8a3f3b0f90d37b32e44d9242c881 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..390045552e6b8604408469c1de75cd82c7599a36 --- /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 0000000000000000000000000000000000000000..8904b6f5ab0d62cf074adae1e1362fc164d54062 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..cf9577db1a584d6b5c1e27937573a1ed6f248a87 --- /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 0000000000000000000000000000000000000000..6c69db95af4befa0ddcc5d60be66244e3c6c43a6 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..f15628e247c84b0f7edf18944f45a98ae0c51032 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..474f60d1c3bae1bc0e8bd3053c2db721ffdbe0c3 --- /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 0000000000000000000000000000000000000000..68d81ff14e9913ab41737ff6fecd467309222d70 --- /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 0000000000000000000000000000000000000000..2d506b09180ec81eceb2776e8d72fb55b049ac98 --- /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 0000000000000000000000000000000000000000..65fd706d7a2b12db4d33146e9e71197698de09e1 --- /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 0000000000000000000000000000000000000000..f173f6e5cbf093d0076fe93f65908802345d9125 --- /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 0000000000000000000000000000000000000000..90cb3769017b1b50c08f840102b25d50e65afc21 --- /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 0000000000000000000000000000000000000000..91e74b60cb0bbd3157319195a28c35cb84f0bf03 --- /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 0000000000000000000000000000000000000000..b745b3c36ab833b10b3a837138e06a406185d7bc --- /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 0000000000000000000000000000000000000000..d8857c0890e906feaba0ecd7a8638f9bef9bcfd3 --- /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 0000000000000000000000000000000000000000..0fb77bea0fe2d545003617cd8eba151d6e2ddbbe --- /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 0000000000000000000000000000000000000000..7bbe8b385cdd8b06c8473ea73614e1849ef2f90f --- /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 0000000000000000000000000000000000000000..85c4556ec278f83bb69cc6dc34250642fbedd855 --- /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 0000000000000000000000000000000000000000..9a29b0cf4196e27ad70a89f4594e5d5ba1821025 --- /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 0000000000000000000000000000000000000000..143779798764a319031c8de751ff76f1d1654b33 --- /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 0000000000000000000000000000000000000000..d90986d9d8214c1bd6a5e07ae9204bb6d803256e --- /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 0000000000000000000000000000000000000000..295a388c40a1b45e9ee212a3dab6d01dd92a53c7 --- /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 0000000000000000000000000000000000000000..454d47285fef442e7c172c29eff5cf7906136ce8 --- /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 0000000000000000000000000000000000000000..29d1eb830f337b82876438f9233b4dd3913f0be6 --- /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 0000000000000000000000000000000000000000..1d6e01d2eab96f40e39b41d9a0022e8e39ff8171 --- /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 0000000000000000000000000000000000000000..1c03efad92c061c22f413c5d2136e9d74d370121 --- /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 0000000000000000000000000000000000000000..09b11470b1be39be96a8ea08da7f15085eeb9120 --- /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 0000000000000000000000000000000000000000..fd631631160df7fa88f7991fcc7abf727f21d1a5 --- /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 0000000000000000000000000000000000000000..d25fbf334bb54895fca0bbab6a03f94b15c8f989 --- /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 0000000000000000000000000000000000000000..06410203359ee2b05c42ada9b1654b89ee8be1da --- /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 0000000000000000000000000000000000000000..e58624a46ef9064ddc9bfa5ed206818fc7c00491 --- /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 0000000000000000000000000000000000000000..df3c17599f0ddfdd52aa366ad4cd4231022859b8 --- /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 0000000000000000000000000000000000000000..e2eee30c39d559155913e7f9e5aec8bf72924c7f --- /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 0000000000000000000000000000000000000000..58f08e75b2506b24748b5c0403975ed99235fd7c --- /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 0000000000000000000000000000000000000000..6e11be47ff0549b74570c1116cf3a980967e211b --- /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 0000000000000000000000000000000000000000..8ad78ef63ed51e18ec67c73394c3f0034e6d71bf --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..32017e21ea87ac6071fe141b8ea5c01796da5426 --- /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 0000000000000000000000000000000000000000..66446e6b994f36fc49a38c78696e99d2aadbd34b --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..9390a86487b9704017dd784dfeda606b5d265dd8 --- /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 0000000000000000000000000000000000000000..93055061cc47a6526340a8446f8d3f69618b7c27 --- /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 0000000000000000000000000000000000000000..00da00584a81142f14567cbc2dc225f5d08fbede --- /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 0000000000000000000000000000000000000000..e0a42e1be8263e2401b5ccdeb7a27bd08fbd9cc0 --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..e077603f8e33680d1ebeb3e8c3da42529a4879ac --- /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 0000000000000000000000000000000000000000..c717a2877a53df954ea3d984474ca0fededfaab7 --- /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 0000000000000000000000000000000000000000..0b9db02c40f182c8ce7d2ee07f845a1b76801cbb --- /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 0000000000000000000000000000000000000000..c267f89bb02378ceb5fe24d1ef1def3daa848704 --- /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 0000000000000000000000000000000000000000..c125a223cffca64d657ebd5bb66b78897d596e59 --- /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 0000000000000000000000000000000000000000..5c7ada514fbaa16a1ec2717b2e580e2876042a4c --- /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 0000000000000000000000000000000000000000..b412521962b93291570254ec0d37f93dd51e9d87 --- /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 0000000000000000000000000000000000000000..04b6b882672cd2a0945670c5670ae7ce157ee0c9 --- /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 0000000000000000000000000000000000000000..e481acea4f96638de2f68afec90ebbd2865428e7 --- /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 0000000000000000000000000000000000000000..7d5ff3f00d7f9eee5510bd63a90a7183c388d63c --- /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 0000000000000000000000000000000000000000..74d6c3731d8dcfdb8353bba6db76f61ea7db84bb --- /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 0000000000000000000000000000000000000000..8541e37174930a2c619a7377189cdae8361b313d --- /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 0000000000000000000000000000000000000000..f488bcbfa0c4ae1d60d7c6216fe8bd65c5a0a9de --- /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 0000000000000000000000000000000000000000..74d6c3731d8dcfdb8353bba6db76f61ea7db84bb --- /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 0000000000000000000000000000000000000000..2c349f5484620017fff8ec872d523e28b61d2433 --- /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 0000000000000000000000000000000000000000..8ca8276f0b7bab103b9d7b6f3b3a8d7877ad1869 --- /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 0000000000000000000000000000000000000000..74d6c3731d8dcfdb8353bba6db76f61ea7db84bb --- /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 0000000000000000000000000000000000000000..8e5174ab69ebc7ee45ddec372138910c69fcaba7 --- /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 0000000000000000000000000000000000000000..74d6c3731d8dcfdb8353bba6db76f61ea7db84bb --- /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 0000000000000000000000000000000000000000..106becd9f887d547f20d093705a39ce0ef8c9de9 --- /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 0000000000000000000000000000000000000000..ef11ada198e35bd673ea96c9801675a687da6816 --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/misc/projects/display-package/compile2.hxml b/tests/misc/projects/display-package/compile2.hxml new file mode 100644 index 0000000000000000000000000000000000000000..8ed15bf57b4d84c79e58dee3b55b5fbed4cb7245 --- /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 0000000000000000000000000000000000000000..33dbcf7f241c9d3ccefd3fe1147d8471b762f61f --- /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 0000000000000000000000000000000000000000..329f3c10745f9abb619ee9ff247fbeac23e15439 --- /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 0000000000000000000000000000000000000000..b2c2c1bf503756ae22935b8242d8577f63b86afe --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/misc/projects/display-type/compile.hxml.stderr b/tests/misc/projects/display-type/compile.hxml.stderr index d649766b12c95c54372634631ba2277fb8b94f0c..062727479eb797edd97c63865d4f99888520c078 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 12aff7e237a9698800f2dc60903168242e5ab486..1d2775b8e60654cefc0815bccecf1b51dfc8bb9c 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 87118c7ca6cde14f70c48efd9a185654e6cf0ed5..5792d910fcfbeb443abf9b9346ce348d999d673e 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 7aaebbef5c8d8ecc27551087345faf2e8d91a3ac..408ad22c8455f130d6907dab6a08824f7af01068 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 1ae96149f9bd7bf71ce8419efa746f00ecddb430..153e91d097331d197055bb3bfe5aeedd155acaa2 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 838662c09250f82714b7dbe35f7aad2dc4d3ddb1..80749638310bcb3ac99867cd1d77de7bb2bdcd4d 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 68e26184885d63a39e9b2b80999e66254355652e..e8deb5959d87c40359e324c7842db11f2968c65b 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 e5324ee8a3acad97c9232c215bdd81251be2d1be..e49b1df741c86091f6dd660d7d67587eb4b25ae4 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 3e64e7f27976e267ec9a381218498482cc3e9505..a3baad93ed338feaf20e40f25af441bd3a941297 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 f890354fec4ade46feffe2aa52e6ec6ede0405ea..75c97b0606afe50cee434e0bad96777ff2b556ec 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 3aa70ca4a7bb8474e39bf7101207a1d042d99a6f..88ce1e4fb527dad84de05c13e97f5727e23045ec 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 a8241556f16db230a0e5d446306ecbb3fdf00723..9b52d9c273061576126c4d61a79d81ccdcad732b 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 0000000000000000000000000000000000000000..476b64c6942f19e1bc7ffdd0a8cb6c56436010cf --- /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 0000000000000000000000000000000000000000..12806b3f917bfd6206f6d0a41b89ceca377264df --- /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 0000000000000000000000000000000000000000..c3bbdc853c08e05f8b80da3e392d8add30d36638 --- /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 0000000000000000000000000000000000000000..f5217be6f8bd8e92d03e6e1f582206cdd38c67bd --- /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 0000000000000000000000000000000000000000..600349c007fd8b1aeb28a5b5b6aedbe392d246e6 --- /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 0000000000000000000000000000000000000000..15929511195da8b3a65ff003e55beb084f2c1f69 --- /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 0000000000000000000000000000000000000000..da6d2a332b66e163272bf84083222ee446704418 --- /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 3fc42ee9bfd4f2b15576cbf4321a996068ccd9dd..0000000000000000000000000000000000000000 --- 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 4ad809bfac9362bde50cf9ef7052a5f1c9211794..cb69b2be0b3ccb421bb1a880ff7f2b70964b6680 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 0000000000000000000000000000000000000000..fa1557d035783862ffe1091d63b19262fcb3ad27 --- /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 0000000000000000000000000000000000000000..b49002b294993206e1ed78e0c16d4ce97affb08c --- /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 7d2306e817b77aee8a55a340fb604b61c60d7a16..b8a2fa7fdd70238d1eee5f3589c225dcb3940f7c 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 0000000000000000000000000000000000000000..54533cd0987d0d33e2e8e92e50f93267e7f89bdf --- /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 7c31ad4323f4ad6d6a4625a743ed4c9051b4bba8..6460bebf273dfb89e5a2e3517e14b0646a4da356 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 0000000000000000000000000000000000000000..c8175f8adaf94e1c504d194f8c8e0981b8e11273 --- /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 fb243816108093655eaa0305c26781f4a776ecff..32a55afadcc65967949f0fbab010758b5fdba878 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 0000000000000000000000000000000000000000..f4486cf7351fe0f1678311a3d8eaf54f0130c02d --- /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 6c01a37b63ce44c3dc840e5d64682198407a7fe3..e1d690229c713861b6c76d47ad50c6e18598c04b 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 2b236ed5b4b08ff4a71f5566e41d8e26780c3601..a4c4a12a7336377e90a21a5417801bb2053757ec 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 f81aae7ce1fa5430407ff2fa6e9e2c661567ef02..066e63bcc71d30188ef4330175f366079f05773d 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 0000000000000000000000000000000000000000..5232e9310e120d93aeb301946bdab87b5b0fbfc8 --- /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 d485326f9ef8bd662a5988131aa24a57f4466f84..450fbcf89153b95eaef271f95299db1b80dd90b1 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 a860ee6875a2a9d60dc287923b420f9d5e94a346..afb16f1e9127347877efdd40250c92b4ea774b2d 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 3dc3a38405353a6551541236827f3cdada652eda..f8393732c857bfe63997f4d313b9438958a1cbac 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 ae09966fa6f4a2b1fcd82fb1e87aa903b4dad817..a74f0c6b65ca666e8a8974f5fab2f0d595b588db 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 4593f40cfd2355b6d75544008ff23e94244f6787..fe9a4a1bb1b3786290c48c0df3265c394da442f4 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 458da551402e369fbd40a0b5ee0e1b4f2277ecd5..82e7494c0acd56ae4e5291914c756f08886da421 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 f17dcbd80e393e1c524731b014e61b991a572003..21108aaa398e8fd077501332f92de1344c20d7a7 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 cc2b19cdbee72d46cc9181fa33b9d9faf58207e6..02646f14bb9570f7160124a8b817cd9aa1b92ae6 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 58529e2d18c6a22acf9085cba7f325475409a5c3..8667cd18b46c0ec5652836092f442a7411bc0ccc 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 dd18b815cc3615c1c65be7e0153ec07e59669079..5f800332a24520bf53d2c159ffbf3f35139ba7f2 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 e9d4c18b8109ed9be525fd13dc1656de17871e9c..a015b5ef141d23d5d9af834fd82778b34c86900c 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 66523fb7b5696b6a8b0f6625a3a6dd38295ba345..bb5c10af57d6386ec2b16db8cf404a472b7db823 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 662a07398c5a2a5739c93d91c279805d552ee2d9..611299ad0e3b8b2618b22e4f133a5f55ff6fc7a7 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 0000000000000000000000000000000000000000..89cbcf8da3acc6d48bc8158e03cfc542074efb5c --- /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 0060519318073bd0298e5fdd5c7c6e04bcc6783f..82e75733f11ea5ec15519f86d65b6f4cf309c6a9 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 16667398efd0035e100a620f5701cafec2841da3..0e298e04dbdf820aca7b4a13c03fdcdc5dddf4f7 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 0000000000000000000000000000000000000000..9c1ab5c564ad1c730252203f09be0c752dc58cf7 --- /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 094c87388cfb4bce0f0a76ddb2a96f314b8a5cb7..7a4374568e0a75c67ecce00a688719fcd0648abf 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 c3cd2019a83d1a963e703ddb5de6ab3d0ac17918..f569988dc755d361998ce6cccfb2e9a55e8111fa 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 71ed464df43e716cc8a84dd833649ecb511d0ce9..0a295c6825a032bb26d9a6db765e81ca6572dac9 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 0000000000000000000000000000000000000000..72e0be116edfb133436adb318c9d293a4295600a --- /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 4fcb80d07ed3bfaa370efefc4ed7cbbfeead56c6..60e66237b2f2d0774b31516b50f741579c4912b2 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 d1eb9f60d9594b0bf84ae06d6bd950cf859be937..2fd3fc97a2505df7bf4ccd757377b6e6c0c0cdcb 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 4bead634da6ddb653d2fc801f130f03d6ae81a0e..4a90d8599ad1f5af1f255d1385d7ddd9438f5f0e 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 80a5a6d9365e5b16c418ca2a196649afe7915574..822665b0979f9e6f9ebe4cb276471b381ec714b9 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 e4b5286f3857b4d1e64eb974a81de88ba287f1c1..acbde2b3e6321daddedcc17920b1a9018190e533 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 4a92c1c1bfa5e5d96921f90af094a056c59d5ae0..f9a0ccbe45e9e298ad4c11da8f314c709ee90d71 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 12b653cfcf6a6a792ab3032e03a89d20c2b7ef9c..8de87da41b6e7ff9f0c600c981c22704b6450ebd 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 0000000000000000000000000000000000000000..f5a56eb46c5b08de67bae40a52bc422d59557539 --- /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 0000000000000000000000000000000000000000..200c1028dda199a58a6cfdcd52ff9c716cad11bc --- /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 f4b38ac3f0c7dfcb4858558f4e0d5a96ed068242..2bebbea74ae2191a4c26efa701814b5511ce64d1 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 1450727b83c73b1dcf6b785ae940e8e514890280..307b86b0c1d9cdbd0ceb99b43477501d4b200c6e 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 0a47d85c1cb22d7f60dcfddbfaf976ff95ac9c27..2523368855b5d4c3b184e8ce042c3399eb862a5e 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 0654a2f16baf7e8b64ce3f534da0aaf279f8c368..1f245132bcd2bf869b0a35976a992c66c1495181 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 bc235c6d28074e0c57bcc7f8ce8655789294464c..3f6774b54c5d9cbb386d9c18aefb494583c46ffe 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 5f88e27df93aa0d45beb66c6242c9f39ce002547..97a9857c3a0172ea82f907ba3d66182b4a49943d 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 c0bdfcda951e56ae1730d405e1eb9b7093c3069e..a91c64b74b14519ec98f1cb1c766e3581520bcdf 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 243c13c056656befa6f199b0fc845e74b0bf0f2e..033263398adc20605ab402c573131f2413fca082 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 06a47379937b6f4f21c628401dacc3eb0f67f421..75a0f670345b5cc63e9189ad0069b39e6a485c85 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 4a29878940fc8b8b68b73ec094ca43717b7c887a..fb8948ccd75675506f85bf344bcf9738879b0517 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 ddd64b501d04d46de02542b0718afb6f151555d5..a00d76c56260b257f922e133ef504cce31f42d97 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 0000000000000000000000000000000000000000..f51c5bf54cba297e69192655c31f07ca7e98abc0 --- /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 5afa11def598195cee7f23aa7941677369b4140a..14c19789264bf05513863b59a35f8b17e9cc2f2d 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 c383ee86a62fc26a357bd41b93005d3e49aa47dd..b4d96ee62fe2e1ec4bb5af26c9534a15e424e691 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 0000000000000000000000000000000000000000..aa84d50aa7e14506b3850cc143343b3e19d9d7b2 --- /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 6dde35883aaf6530ef7521ac1aec8005afe32ddc..9c8a3d1662635c91c07ef5a1c3dce18b11eb4f7c 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 83ec3e529f01a9e5f5d70eba8ba389caf276f2b1..7c82b857dd1316d8db3c0d961c1f1402326d40d1 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 0000000000000000000000000000000000000000..dc1ff71270a1c8d4236d4aea2ce76ee087aeec7f --- /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 0000000000000000000000000000000000000000..70c602df216a718280fdf1993881dcb86f45b29d --- /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 a60fe8b20980d27afa5639e18c6f6d13ce17d183..0699f97f88cf6f8303e1750aa2923b9cc8029b2f 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 39f843672517d84b1723bb70ed60efee3ef6fac1..32d5cd87a64e0cfe4c14b63ac034b89afc360c09 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 c5a81a73b98fccd412642f017fdf50b8ad174c0e..6f81a3d8c1779285af9ac3a078d11a05f3668744 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 f481f5fa03b442248de1fa36b2cc51df43d1bdbe..227c90a2349dd8c8f33a0dd62ffe763dc8f06312 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 a29c0356690a966de33e412b442cc1988f364b97..3558c8c876a0d934e1355bbc49db502638f7b94c 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 b77a41f2448c9cfe94c2f0c701f6124300c39842..4c4f28ddcdeb2618a7a3d37e55c9ede590b85b7b 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 ce32730776fc0aa2b6040b2244606bc9d977c6e5..1e1f2db23b5f7d26b17968aef91cae12b59ab189 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 a466a39d83ba7586d06c7cb020e4c36a3e2e10bb..8c29e0aefab236bc85cb8741c52339023125e822 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 498c62c17a163285f94b11501707701701360620..338745d3c2af8a35b3b6b8ddf09a7a84dedb674b 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 433fc70dd7d66640ae97b3916ff34e6d7d9f22fa..b5f7bb2c64914d38f9b92da3df336c7892cb4788 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 2d94a4948f481c66612256e890af529134ba1d11..32c58471b4ecd9a641f875937aac17d8f3b0c0b1 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 d507aae9ec25037d5c279685443ed604cbf528c4..39e7cd8e7572134abb8a26c550e775b4a1f4bcf1 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 311be36bf6712a3251b6e03b7d010fddecbccd60..c5b7982ba7426e971f53a2a8c484067c6516a007 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 caf7d3f67053ce491db2fea6bb15cab817a2a7a7..3bc81b8eb3ef88bbfe0bf01932067ad735c6bea4 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 fbad39da91542a9e73e51ddb84a8441a1c1234f8..6a96840cdad41d524600f862f6dcf3c5e13376d3 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 7a277a544586bb5a58b7ef2b2017a7a84e2bcaa2..0af8b8e8a61a9143110575dad0b73cdbab15f090 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 1f90ef48a544bb8cddf067e647afa7a94be0c02c..5d1474b3d7389a2905a0d6a5a1cd28b1e5e96df5 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 0bf119b5aeb73d72cd4adbba10d3155e9d0181d5..4c851a1f01fc06b55b177c4ccb41a1f997734ef9 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 1b2457916d4164979568df088e699ed510000047..869be2894b1cbeb0cd048b663052ab8a840409a5 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 e92963ce0f469301dea1531e5320284c6327be1f..615ae8ac6e102fab913a19697f22e3a5c3074b4d 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 0000000000000000000000000000000000000000..f2f00452416ae34d9f9a55ee37528bd29d70a7b7 --- /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 6bc6e18c900ee1ef6ba45f1e319aeae9104cebee..99556fad2292b58a7465e3eaf9a6ee9cf7d97b99 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 a1aeb260ef039ffa42d8f1d3573a7a91e06a1a02..00063c1668ab968c3eb63d92798f0d59654ee435 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 0000000000000000000000000000000000000000..c018ef3b015cfebcf97405780b4e3dcf963da23e --- /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 fab54b8d5c889c5b9319a9ad8985b24c69fa502e..a799a36b3d420cedd341206bbca1340aff2d4de6 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 7d7d8d105111e4daa71366f3e6bfad86158832ce..4fca95d7ec7a3e23948c8edee651de0578b15801 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 d6e33c072b8298cf16d7871b91b280889e45df02..be87f81e75f59a427676961ad64f86d11d505670 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 93a71a2bee5b92548f691dddfad11c1ec9805b3e..1f3779c469dcd02b5da273949d7d3b5fc508ec25 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 d4010393789ad22e7534946fd89d8b2defccbe32..50959d4b743c795f4de7db29206718439e4bd1ec 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 25e24eef0ce42b097b90d386499e410875ee58af..a5975b9aeaa9da7d8a6f8743eb39a7319b683aed 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 a4fe2b0a4deb7bfba20ae239cce819466fc9778f..406865a51c5b5cb5b0d04a30db4012c9ffbada21 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 accd20425dba357f3bb767ad6bfd7aa096362388..5df0218e0e7a33edf9e25203f5ca041da212a7f4 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 9613eaa182a18bc90995d827417fa39d4bfa9d49..4ea123979403b4fc5dfc36e4b656e02ac44e303a 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 25655fc95a446667b54b8380ee7c9fadf9b9ba44..fa4b70b14fbdd95ea94053b1777e9308580dc734 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 cade349823cfef737beae0afac359204fd812ec5..a49aeb108d4cf34ef25e3afba1636c4f953411b6 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 436949438c04e9e6f5a038e0bace54e4727f89c8..837088ee94854eb6fc9b56ea9e630d6bf78bd48b 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 0000000000000000000000000000000000000000..47c05e527cc6fc1b97c96be0393f66c9536872f1 --- /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 6fc472e01d652270f928b128bfd0f5cf3334d397..8d2ab87ef43def6f96f781fc99904e6d69170bb4 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 fa17849c56baf14b71f2cda31d029fbfeaff9e9f..35fac7b4bac44978a1f6674f9f8bdd752906beb1 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 b99059aaedcf320b68fa41b612f36e172f94ad4a..b77cf2fb6fa03b25cb0d144c4238797e924f9dab 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 305fd43e4e8a5dfc180a83b97137fbe373c9d1c3..d9cbc3a5994cd0973d5cb277b6c55e78d4374214 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 c9fa0c922a53456b443aaff0ec0903bf81291ac4..ab301b4f0d4db70cb5049fb9d1decb44db6e50a3 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 598335a9df0ce52fa75ece325aaf0dfc9776697f..bd0ce86eeafee2b945d86e48cdfaf45c93921a68 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 af20e4c5bbfdb51380c31540510600355ff42113..473c3923e0c37e6e13736cd87dd414ed81453949 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 cfb085c1daacb7c93c587fdaa99fcfc772caa6a6..dc171062d3f3458abb459a8e439af470da6942bf 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 8bd9ef454144251bdc53e5525f7e721ed2ab8556..864d99227aa09ebf85c5ae02adef3f952239e89b 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 194c94f1d31e7cc5314d416638587fe358c72043..93b215a452e0e50e7a97fca8444a98156ecd2408 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 97bce4edf267c3b3151e9630db7656157087642f..7ce683df5d10e16a7d5f77fbaa79c216c7b60a00 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 a4911e94a9bf6b329926acb542ddf05697ea9a43..35574a7c586d652d712df728d27d74c3d76185dd 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 d417e047df685fae8215bcf5d7c1c53830269ddd..2dd27ff44bee30d25a42a7fca40f3a6f3f068139 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 e3f7a86a90e72f053a3a4a105948b163656e3268..29464a77dbbdb1e8a57405e282f5c0aabce4edf5 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 0000000000000000000000000000000000000000..5df9d669f45f01fa698e6d2fcab7e8e271a0a537 --- /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 05245a9026b57d9240143ccd05f7393c8ecf6fcd..5ac86f70afb019752ecba7fb63ffadc631ff54bb 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 3f1f1cd8c0fc672439a63942188e6494bed82591..6c0b582486fbfa60369ad4af758ae5c929837aa6 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 e8735ef58a3cf639c5356d41af4345bc38553861..d10fd8f418377b3cd8744fe79e591bd37e144371 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 8709f243a5e2324a5a40da25a2637bbf18da6fd8..ec974b3da44c79cec98aaff54c3f3590ea65865a 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 57a0a0124d5c9da4cf819e0964e49d66c1d190e1..3e36160992282e0018ca19a73a7c9285ea9e4515 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 8f7cb3d6d4e31c05c9a26dc11cf4d73a1c3d1504..37cf05a618faabd5dcea01f39b630d6959b512f5 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 d8c52193f4642bee8ff77539e0b2d38155b680b4..820ac7309331b7ab8f7bd5300ce7eff65f102160 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 d0c936a1332d2db7182b149a8a8fe1d31ad9e8b7..26521529bbb68e61ed9052eb8f5a71f4696dafe4 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 37a5363d0fa5e59ba73c52a6e8b88abf3eed5633..4dbf3a8eb406e07642cfaca56093d602bce095c1 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 acf18ed410dcdaaa0036cbe096420ffa2b7decb0..43726076f4fde04065e944c9321d316693278d11 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 6a1775a7808db05895dd7597f45b74210b2354ec..f1a4bf2745e90fde07a6ed2588be5c3b72b63d43 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 c4ac2703fdcc6b9465c70069e0430385f69d593e..6722a30ea36165df3be951a7b8ffcc488a5e5de8 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 93e35d4dd246d96045f01c958a1f53fac1346ecb..51541a8b91c2312563f0d84fb30e85376c1441c7 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 ea4421ee7841b124db80ffc7faebd4a1a9bf9b67..9dd3049c9686356dbbafece1da959d5c23219ff4 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 f1dc7d43a7562ae788b32dfc06f870db09efda99..315554741ad6d741f0c2a859bca74a0aac7f1a93 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 1a6e8ac1b7b8582a077adb412c8636eade568798..b758c9b948c33d3eefdeb08eaebd58bb2bd5bbd7 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 57cea3bd63dae4f2fff8e1548f2cc9e818f4f168..ba004dd1e88f878a0865944abff47f92e7f99842 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 2abd5705104a807fa113dec8690aa13107d23ab7..a28df7038c847779cc07fd6d822f1b87ceab73ad 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 93bddc37452563be690cc39399e2d0b0fd719857..c675271d9525f3de44341c27566576915dfb4b11 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 0bed74778df9ce8bedd7e70a97d56a543841f831..578faa49faa10f1cddb1cc27d1f53e0ec1eb6e9e 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 a9f694b4adbab2f94907ead9bd5ec8453f496730..7e8c38d252a041fd0808e52b1105e618cd2dde13 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 0000000000000000000000000000000000000000..0b6e9592b3e3cad6fb346d9a49cd6f454716d0e3 --- /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 7fd9e28aa109155566e66fa626a6e205a866f274..93057399195786552db89428f9994ae153c1a486 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 3f603a96a972baf0ea8c31399c071be0b78d790a..cd03d23c4258afccf1d6252a2d12d631c1607087 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 f31f2ef68e591b5f47c617b6ef57c602242557c3..4c52059420876abf3abd345776a4c4fa8e915e42 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 f28ff005d9f749be47c4964f54988a0820ca0f1d..d9aae20cad9310638e9210ff5292afb17c70fa51 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 0590553c9329046f855447d5224a48ee3adc7172..4b28e8878ffb5bb7dad9a4b0ac1d315dea454d13 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 dfb2680f8c12b12921298a57059d75871005ad21..b49918d46d0a6682ef746bb169a1c0adb803220c 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 7fcfb8e90a77eabbf4a576c23fbeed662ef8ec70..36d42d491b70c6a56e8c8ebf3cc5b30af3090988 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 316a19f352eedf0c028d55692f7a91e84926fd84..aacece748c90b3bacfffe7bcd39f95e0451db885 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 fe83c70ce4e68fd8fcb3e1bbba0f5d79a10def9b..64e5402f29829db3d3b32cc8abc180c8a8c0866d 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 d558adffcffabe08c267bb294b82a45a214183df..024ad84599b17aab135f67c72a30f869fda4d2d7 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 9a5dce71da511389f56b7a75ab93b967da8fae98..7dee0dc8396b23785c4ca08da8f9c763ccfe87e9 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 833f3d0222c98c77238845ac98dbf4ac55ee8910..f9b56fd95186ca853065c99511dbe90c889d1696 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 4e044e84116c2f5df2ca45de13505ea8872299f0..ebfbc6efb9742439a65d4bd081428dd04d9cfd46 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 b64be6cdb991428333b951902174ef60a7d378a3..33cdf92f28734b16058ed7810c4b9805802c2e99 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 6120bbefde7ca07e47a8273219186ac89eb3df88..8de2c0236b8f6165effb668e28f60591f785fd2a 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 4734faf7e2586a764042b7aefe0fae49d1f84b16..87ed64a8ab4e599f58b901447709704109767a56 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 03862449e0c5b919e0380cc6cd2bb1628bfe32b5..74fc807c51ec238cadbf850189e956f972825039 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 98738d6a67420b24ce7821bbf21fbdad7920c9f6..964509841814e940eb4e3b8b174abe3df5cb4067 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 3cf25b463fcf4c3ba54df03f3c03d2117adc37f4..56df7d155b473fdc49ae0f3779fe083d11c7f4c5 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 f9bb32d849bd9897e7906d374ae59f31538d9c3c..b0489e69da06cde9bdc9c429992d98913707a495 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 f7f135fcc4e427e5d94362c65de34603f4ca1b41..812865e1937daccf87fa66d03011e6ced3e19a46 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 7c6444f984beb0d492e3aecba4fdd814bef3534e..4a3488ae867f4341a0280edbf166dc5ef059fdeb 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 4d4ae2ac5456bff4c423fc8bb23a6a4ae69dc5c4..4983c56ef80cf7f616481756aef32f3bd5e847a8 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 5933b989a31740587a03fcc63273b6f3f7a35038..0ba88b5c0e0eeed4419716f2bea6cbd55547a3ab 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 4d22a9211617c812957569b50fa7f13e294245da..28af2bfdfeeddf63eb5e5ad9dfebc1ac9c023f08 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 73e4bb699b7164559b1270dadc616d6314f28946..83486711ddc9c699bda96361cec0738e85cfe097 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 c009ca2435a050767dc0ca78f5fadc3e608d8c73..86863ee2e3ae442aece136d3cf33e33f1e5ec95b 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 1d4038a1c09040d8614f7ee8c18d8bef1a6c80fe..67ee3e298a207dd4984cb82a11bbb24fddf53ca9 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 59df78d666742f741c1f2294ef891f24d3a9f61f..e6789d44d47579fbcbf087d7ca3f81f21c591be5 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 b98e121507b7c1c1643f22bc4c0b16c90c3f322b..8c004cdbf7e1ea8c339fbfc2f8e1ab4cbd7c9f1f 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 e9a49b61e008015ca172fcc674ad3bc4d6a05332..68456ebf8dfea4085b76cd866983b8dce81b0319 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 351cabcc68522686782fdf455fcb3a0d98c30738..e597dd69f8bd404725760c08a58feb23392c421e 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 0562cb0754e59980ea2570df055359a81c22f41b..70aaa02fc4648fe7512f727f15c47229a11be55a 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 15c4227bda3e97d408419f445301518e36949817..0b6ce8228f6fc588041a781823cf53a4f9c5fa52 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 5870ca84c912cde5072454aa00e9e00e32f0240d..f67710202dd9839ffacef64dbf6a2b976acdb6ab 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 a5e7d721d82bdfbd493ceba2aa11dc146548553e..66c55b6698da3b606b6bdc2335440a996dc66bf9 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 5705e83a3f20dae5f7097581455237ea97f25d0b..3204124e4bb4b0415877ea29fd8dc60104de1e15 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 fac38d1aa98e439d12c4a18f76b7aa1c60eebfc8..2f63e4fc1e8876c07d3a21983dd4e2ea3b76e77b 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 0a2de38f5dced7099a87fe729489d566b7c4da36..31f23eda73d9f1da45f81a406f41e89a8e109baf 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 df824fc9d4db6f61dabd3377c4fbebd9eb7c1cfd..71b40c74ae8e8721f5fa1c7849d423520dc5864f 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 192737f17ce1b4f46ef7a6b2d7e7bfc41cba8cc5..339026d81299fd638e2ea6641cadb48da0542944 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 3864c4446f61eb05c63c6e9d7dd4c3e3a9f9d5b2..1c0c412857e61107f174948b84d3c7adfbcac012 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 4b02c68694987c15974c8615235a58c7ac31b0d6..924918113e7556d36e54d9bfa688c6be65568c3c 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 e5f7a69c2777f802153c08674d1bea0e14bb3a06..780de313d4f04a3c142bec858da6ab2c576d92ce 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 cbf7c9520294c3ed667f34366a6c8fed62c6505b..4689b2dd0215c564fe35cd64c05d49e85088bbad 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 9a74a780b8675fa65f18b2d776f3b3cb2ec0331f..a16c14f28333f08e3bd8bcdcc0671bd8d7a9995d 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 e9777e4204df743d5e8bc3c4731e9962f26579f3..f02b081f4264acbb51aacc217c29f77b2ecbbb85 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 7a7843d5e6d999251f92c775973dbe1a339f2761..f9b5a9a86b94866e79148493dbff27d8c3818552 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 5b4200848371c769ff1c182e9f3da3df92937847..4cfdb3762fe3943947444ee4e7cd44a3681fad82 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 0000000000000000000000000000000000000000..e49b10b3aa8a0942a1ac6dcd6090aad3ba248bf2 --- /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 a88e0a7b6f45b48754dcb4c1a1cadd84233f0568..30955d686c912f147b2238a3c03dd634a4263309 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 c31f06c31cc6c2e0a19a4d23f4162f12048e6990..18a1245e38581eeeaf962d828bbfffd907bfc309 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 5928ce33d86207143497b94c73e380a1b36048b0..e671ec3e274c74db1fb937e807cf1c37b29a9c19 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 bf46343b847a1eb6a91251eb450458252da21588..9ddfd4cadf29e584375a0b135d754eb3c5eb172b 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 a89abbec0beda3d0aa691ec8ada9695373a1ab6e..783062b7bf685f17f90d2aee0239e5f20dbee633 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 b6709077d3f0b3150ca882f0c7d40c6f4f4de20a..2b4eec3af5babdb9e934dd101958100370ea38c9 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 0000000000000000000000000000000000000000..3f89df538c417a444854585d2271cb3d31ffa434 --- /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 f436df0b91e014cefac8040ac7f4b2824b648123..94e54876eb9156fb95dd92455f67d228009bcfe7 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 f9985b70a8b2e5a7a4ce44314b88e22eda5c324f..5957845b0bf6878c154dfca929fdca2b7e4d32e2 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 848bfa145c0c7bc7a6b5d24f781bf518f13f466f..fb9e08f4baf29cd4b001404f06983dd9a2feafb3 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 641c5472d840aa3a57c51dc828af22d94707bc26..121bde5d52393c99938897854ff7b68f0ea95a87 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 d1e57b18cdffc5de34ed6c2305f1cb59c5e61e7b..9fdea6e641c3e0d2d58c62d60a55a89621436c13 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 33b01b109620d96c0c0ea87faa1930c3b28d965d..b1ae7dfef425166f8aff66d94487410d87b66c2e 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 711a0a2f1cc35d766c4cbf53dfeb1b40310be981..2f32a961fc1028b8ef2de58abd23db443f9ec511 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 199ab07b9c5f66bb325ec9de4f7ae99df7198386..1304e459d299166529ad7924c053a24f774086c2 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 6ba7171a8047c4ad137af748512d43c9ebbf52c5..c1852130d48fa1f035232c355a527748428db03f 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 0000000000000000000000000000000000000000..9345f2f7749b9f736d2fcc9713b42a10d9fb74d8 --- /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 360d13e409abb5ce9967dbdf4e2fb88ac623ce83..a9118f82ded34146266dfc6ad1f5c18c275bfa60 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 8259d34f54fa54ab8af1628981864c0c0a743206..3ee3714cbd53517e48ab82b6a1e3b74c7ac1ad68 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 efa28367cbcb78d59cbd2e7000be8b751aec1cd9..64691e05a9af04286c389a8421617ef96512f5ce 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 62280a545e9727ca23a52fbb804158b95f587e25..7d57a4c7166d2fbff0873242ca2fb51cbb4575ab 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 f26d10b6bf2adb5fd19bb5a982d9e77507333ea8..a343dc88732374e5a87b0327de512dde3872ade8 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 1da2d07e32ee4f88be78cd4f17caec3476e689e3..9155a192c586d07cf321455b6ef18733aa60af79 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 00fbdbbe7d88ec61f7e0fade2052faa1533709ab..30d839c49d16f07f856eebca8713d2afb211e023 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 bff8d60c6e2aa470a3448cd015ca707c8ec9b2d2..847ed8ef4287880a3b81c55ba152164d22814273 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 8702d6ce6a6866904453d095b335d341ebd672ff..08248834a4c9938f6414374137f3b849f1e5ca5a 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 2488968f9787cd8a485d13c80f961d5ef77cf557..ab2c983dbfc6d1beb655ff6cd5ad9ad0a7275b14 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 6a55790366c39c6f4d6861245b9f0967e47d290f..fc666ccf033fd899cd9f36b8e774ab14e37ecb34 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 29712d7ba69741d0d291322737b5846303841785..eda294e62eb900322cc7d408bb59361fc58c2ab3 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 0000000000000000000000000000000000000000..f032cc544f66b5a793f862b6d20d70c549eac26a --- /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 0000000000000000000000000000000000000000..89e26efcf79f33ea7bc7848b7f05fc7e2335726f --- /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 a230afaf773e33210f153880d4860c69cf3384ac..d3690bff9e119e6568091ae8690eb94fc63a4b98 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 5123a66dc46d36381e6b358a13ecea0c4e5e6203..32d675abbdc2da40f0a589a2d069cb442fd4ebc0 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 081699ec18628f6a6d3c246e8f9f3febc1a0ba43..7a9ebe54ad2ecf8f140ca4dbf8601beaff4962d5 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 8240f0493894f4139d02408f7d0174ce964be4a7..fed9fb98bad541f66ab391d7c4693c4c499d73f8 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 0000000000000000000000000000000000000000..90e7e9a13f8e016da1c1333ed710c6512bbfcba3 --- /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 f9de47059b6cafa9c45b89d33eafa98e0a58ac6c..3cb9f6b6e5839046c4ef60060426768e5e895539 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 519a988e83eb12e27f2714f3e45025b8be456559..a363edeace2b3f33b4fec19c2bd08c0969561add 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 710f95721d2fca1af29cf923a37ddb5f258cfdda..f316e63501ca1f85277f01b4068b9870151b29d4 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 dcb3fcd961accfb63bea5d4a303a759489c51ac3..792eb63aeacd7f10638ce4079d17851bf421c1d9 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 528b7cf4c6c18d456642a8e8dc3ec2e021fbea0d..efc9a6407a2e6e94b82041dc229f00635ff82da8 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 0000000000000000000000000000000000000000..014273c006b5413b064e607229fbc72fa3aafdcb --- /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 0000000000000000000000000000000000000000..73e5e4455c6df17172e2af68f0ab9f7c7a1024e5 --- /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 573698e60293517bbb308d97faf9be31d2e2d5b2..81a431a3d93bba94f0a4a6257bc3a8f133707d7b 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 4cec49f74cafd3c8b1b799704d1e1e2cb10b516c..49bc8966c276fad380157a81f324602b6570dd84 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 c612541c597e4c747927d512fe6090488e5567b3..0933dfbcec2fb9522f247c970d086249bc91ceae 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 0000000000000000000000000000000000000000..fe20bd2b92a1a3537bf22349f0329c124b9c46b6 --- /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 0000000000000000000000000000000000000000..59554e281f4c321b57718aa3df71ba2d590e8d0f --- /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 0e57514d3339d5f738dd9716c45c4abc2f1b501b..58bea8bc292b924901d6eecf89c78028f93a3356 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 223f11cf2daa5f49806f88e639beefff7e59f594..a4304d5ff15353c373de72a437ffe5299168de02 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 612ca7e8df802e13beeaa3905532df2c80f20fbd..b168d4ae05d2e2ec47ded82cb4f9b6a59c6c82b7 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 dedaf4b9d4bb12995234dd285a4050c129afd843..e4cb593c98934e76bde66c41eeda740906f11cab 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 4bc239dd03598876edf4397145c4f96e40644102..343711adbec0013982b16cb120b2447ff92620c6 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 74a9eb14e07b4322ebd4f7fd7de565466ff1dc87..9439fedc2aee9a61bd61271194ce773c2c2542eb 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 5de70c5adae70f5a358ad7aa22c75dc3521e4754..439ef16ae49be8b1f547eb0c65ddc6bedaedf51f 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 c791a14005e55ad503ea8c5ae743c6ee2274e0f9..5dbb46bc2ab3dd925890533a0c7172fbbae36c58 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 568b747cd71b1ff9fc26154312413987c24f88fc..3b43a748d2aa4906450950088b29764075a6ae7b 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 2a612bfc99e2c28267fc5fc5d31e0c3f5dd09725..0b1fe56b8f7c68ec86b8b7690b59016c72a3306d 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 452a063c8cb2ea446d6dfd2096e7eb8738a8b2f9..0fdcaee6ba43b8000239c032e08504d35bb04b71 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 709093604bc80ffad4f3aeec5387a3e8b8e949fb..aff31ba5ac53e90f808f96442d90ca523b14ea7b 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 0000000000000000000000000000000000000000..710093685f743b0a3e603ce1eedb700d71275ba7 --- /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 f280e7315507f64dad2f6d7cb98b14e3413ccc20..321620753a760e04cdacaab8d8ec8c1566ba3ab7 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 74e35eec0c05ddbd823bdfdbf800542a0278414e..d67b7caeb9e75b298672bf5348b20ebad24cffdd 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 b896b843bfc4f9a9e03cf2d6803b2a46a30d60ad..bc6a47a9e0ece9ffdb66959ea251dee359f73fd5 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 1e4b1578fb83c1d61ca15bffd40dc63cb1bad32e..bdcda530234edaa1c3a69006f326c09a914b369f 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 56eefafe510231c7be945f0672fbee37f6dcc297..c9ea05a60bec158df356be2e943ae8a4146ff412 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 b7c6ac9844fefbcd5cca23de20ea373f2d5953ca..ae50c0b219f67f6dbddd0327098be8d9f5b4a97e 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 0000000000000000000000000000000000000000..ca3c9d385ede7d50c46371894d56127a826d49ff --- /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 1cc9a0114036d1f4b3c5e066e2a9de3c1c45bf6e..98cd47d449d553174e3c1ec49d13dfc67aadad84 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 0000000000000000000000000000000000000000..909f1d46e72dad2b66b929a57a89c841a1f523f4 --- /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 0000000000000000000000000000000000000000..e0457dec2c5c0f19c1ff760123d59e938ceea5a4 --- /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 4c64ace249c74d26de3dc14763288066eae1ed21..53c40693fd76d6dda031cae8908c65fc94cdbc4c 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 53266408da0007ab73ad7b4507f7ebdd78a67291..2110e95bda6a96fc7e380498d35ad49cea998a49 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 7ed9e46581f6ff56c429605f2449a547a47c2b4c..a240bd6cc5816c107af084787179b6d2ffeefe5b 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 0609559201b77a03228239f601a5675966ac0cba..d09d2a4bbc27b603ac89d01591a81eb0db6e3a2f 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 2a4019ff573fbf5e495181b80c847d2a5fae8d7f..6dc72022d48a72d5c93320d2d2e65242c0512124 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 e2d9cbf4da707d958101d2198559fd5a2e326ead..471df73be48316f57dd5d328c83f0c40daf7eb50 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 84fc42d81070354a3f0fa11670d2317fe5270464..b36af79655fa2aee86c659148f6334587de88f4e 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 69e649b5ce4f0629c695ef77e88f44347927cfbd..d09292d42db0fb901df9419097be302cd02697fd 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 4b128661ff6b71cd346ecb5e5d9fa8c358a68d53..8ec088acf84420db84e2898882e08f2f4be73882 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 0000000000000000000000000000000000000000..75915b5fca2b574dc55f869d77a519ce44b3e8bc --- /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 3af912957d8ed684c5154d19f4fe6b1b45199653..a6c48d6c1ddbae712e568258251bf28f7b198b85 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 3b4bff39c22be8eef013204cef1f5873cecece82..5f2e52cc950cda733e259da45df195afded7b8ac 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 0000000000000000000000000000000000000000..a571183ef95f1fad85e7fc7db17e4d33d03322c4 --- /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 8914cab0733e607681bb2d5de42ef6fa281d3030..1c08881fe24fac0743299884a725cdb92b1c82ee 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 c2c7cee7537f4228509ca0537cafb4cf92cdd2bd..085fa1c8b4491287abc71066cf151890ce022685 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 e3dbcba2daf4a2923343b8bc4866a2db45344dfd..0000000000000000000000000000000000000000 --- 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 94af815c3d15324b9d162cb3025f12674a405662..bc2736b6a0e756320674fa796cfc4d9e828c2449 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 0000000000000000000000000000000000000000..89c4f42b905b2922fd8799b4e0d8b1ca3a1bd65b --- /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 0000000000000000000000000000000000000000..367f089b37429a3aafc754265174df55184e004a --- /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 e106aa98fe35e79e17c438170d5d005225d02983..468b164c86ce34bad69b66d7051ce4539791f2a6 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 0000000000000000000000000000000000000000..a1d840389ed3511e299fbd5277146822dc9f5a1d --- /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 0000000000000000000000000000000000000000..1607357dd1d2068bef681a1d1683d031237edd75 --- /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 0000000000000000000000000000000000000000..d4ac928c498c9bfbace114caf88e1c971132504e --- /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 baa24fc4196fee6ad4e14906afd3846ebe51e5a2..d842e7438ebda0e5bdfba067b03996f20ec09f55 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 0000000000000000000000000000000000000000..1005c8f967a61aa37517c511193d54236158029b --- /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 0000000000000000000000000000000000000000..0db085e6c1d63071b298614a1778ce3a5f71fdec --- /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 0000000000000000000000000000000000000000..551eb91274dcfd3e64a663672fd841b7ef89fe6f --- /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 0000000000000000000000000000000000000000..57941ccd512c16f0326150c6a1c32812507c6c86 --- /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 0000000000000000000000000000000000000000..3fcee8da04203bb53726720b954cbf4adbb2e95f --- /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 0000000000000000000000000000000000000000..bf4ff92b49ada72c6cee40524fe077b054f2e603 --- /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 0000000000000000000000000000000000000000..3fc0133060095234a5fe28c656ec14d653112673 --- /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 0000000000000000000000000000000000000000..bd484faae08a993a4d9bed467028b7080b8923a8 --- /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 0000000000000000000000000000000000000000..85774fc60dfd6011bea087416eed9f152998dbb3 --- /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 0000000000000000000000000000000000000000..6e1e220c9a04aa3cea5b1c0b4910d06561a14700 --- /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 0000000000000000000000000000000000000000..bef99db3f3d059c3b3e2e89da5d8a04c90334d22 --- /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 0000000000000000000000000000000000000000..9e37516519594d7cd8da52630747fba99c810f79 --- /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 0000000000000000000000000000000000000000..309ff56757f48496407bd98de6c0103f4eb91f55 --- /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 0000000000000000000000000000000000000000..4c1fa2341266473ddcffdc5d177f33631ea31620 --- /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 0000000000000000000000000000000000000000..d47e36187134dfb3a350449d40928a4f421785b3 --- /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 0000000000000000000000000000000000000000..234d97c576be04570fe1aefa3c5f9b02bc455037 --- /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 0000000000000000000000000000000000000000..64681fcea6120b0793351c0107b9ffafdefbf388 --- /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 0000000000000000000000000000000000000000..3e0f1c515aebffe5b3eecb4167df4b920a8fc7c7 --- /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 0000000000000000000000000000000000000000..6868fbf4109b1ea211e559f0417b929f0cdcc076 --- /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 0000000000000000000000000000000000000000..de36ce112574c31ce4d271739eded109b6e268c8 --- /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 0000000000000000000000000000000000000000..c999207435513e78060e89912437ede0e489dba1 --- /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 0000000000000000000000000000000000000000..b47006c4538a3f5004aebcf11214d861743a71da --- /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 0000000000000000000000000000000000000000..c2c75327720c7204b5a9b90036c9cb04d873a88a --- /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 0000000000000000000000000000000000000000..2ed9994900b1f58b81b71a5e2912bec4a354d249 --- /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 0000000000000000000000000000000000000000..38cf0b0b39074e7d401fca8198e2d458094c0663 --- /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 0000000000000000000000000000000000000000..c036272997a0fbd9d93212458f581301c94a37f4 --- /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 0000000000000000000000000000000000000000..8e0f7cd17fdcd5dc71d1aecfca7ad95644d923a1 --- /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 0000000000000000000000000000000000000000..adf4e957c3d21ecc43272abda740c5d080393e81 --- /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 0000000000000000000000000000000000000000..e8c4c80a1cb6639c64607efb3d258ac6b44bf4d7 --- /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 0000000000000000000000000000000000000000..eda6374fe529ef5d79c7b727b252bdebac572ad9 --- /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 0000000000000000000000000000000000000000..5d3b3297781795028206d13954b522de0039c5f7 --- /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 0000000000000000000000000000000000000000..a81c7878ee98886a71f42d048f39712890393490 --- /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 0000000000000000000000000000000000000000..b8878977ecf9988ef4e834a10ede2193330667ec --- /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 933dcaea5c587e9407d3f1c310562ec5a3e58499..ce43db9097b5da10abda2503fb1bf41bbf919692 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 0000000000000000000000000000000000000000..0dff4f8239ab7d83f41742719032d80e90d1e911 --- /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 0000000000000000000000000000000000000000..756b2f033de2f1a51c7efac3b427ec58975ee9b3 --- /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 0000000000000000000000000000000000000000..6baba3035dfc80f4405280e21f40173389d53a37 --- /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 0000000000000000000000000000000000000000..19eb48ef4c06508c25d85155365aa225e7f479b6 --- /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 0000000000000000000000000000000000000000..924b337199167b66d085d193918c49ab2be4bf18 --- /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 0000000000000000000000000000000000000000..551d0c7d556f9cdb365e1669ad97b6391954363d --- /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 10773d32b9e1e1614a508a2d0adb8c5ac8714f0b..0a951e940f53799cfccd7cc5c9058d7fdc1023cb 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 0000000000000000000000000000000000000000..6333fb90fa6e5026d7d1a89a3279af29f0f6601b --- /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 0000000000000000000000000000000000000000..5c21ace0c3e4ace55e7f1201f47345f1f91d9475 --- /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 0000000000000000000000000000000000000000..8e002cccf81d7e438591c8370cfac8a77a132910 --- /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 0000000000000000000000000000000000000000..2f94bbc5f3076d5dce5d671a9e503602a5fbac8d --- /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 0000000000000000000000000000000000000000..06a44ac5a2a235ddafcf1bc5c843bc1acbe2f1d6 --- /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 0000000000000000000000000000000000000000..7b04f983326b7da1d09cb41e2465c75805770b6f --- /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 0000000000000000000000000000000000000000..4526d6be785a862b2afc13e5081510fd87e1f803 --- /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 0000000000000000000000000000000000000000..59960150a606a95774b6e35c7520c96aebce445b --- /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 0000000000000000000000000000000000000000..f9d6c9d81a5e487251c6bc42332f320ed35777f9 --- /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 0000000000000000000000000000000000000000..5cb0528f311848358b1e76d08f62696210267cb1 --- /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 0000000000000000000000000000000000000000..43b18957728f7cbed51917e280ce9cdedcf61a41 --- /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 0000000000000000000000000000000000000000..904a56e6b7bcf472c6d9883659a05cf8f3590a25 --- /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 0000000000000000000000000000000000000000..b748f5055f9e6a639552098c0d258eedb5c764b7 --- /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 0000000000000000000000000000000000000000..1bcebf7df6c6878354a1c494e07c3bd1ab652c6e --- /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 0000000000000000000000000000000000000000..1535d2ac3b7518a7272c30080d35ca7a630241cf --- /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 0000000000000000000000000000000000000000..2b034a51f3cd40812dd2ccffb3ad7c65a00f5ddd --- /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 0000000000000000000000000000000000000000..e212702a8ee4cf7e64df8044cb1d320788a2b276 --- /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 0000000000000000000000000000000000000000..e82ad02a8cb479d3a12a42e1ad5dd260e9cf356f --- /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 0000000000000000000000000000000000000000..661670f1415df3673fe72a1ad8a1ba1a4a883bc8 --- /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 0000000000000000000000000000000000000000..aff3a3a615214d6d94276bc96af58f3ff9f7bbd7 --- /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 0000000000000000000000000000000000000000..69665c2802f04fca19838d646f00a98f51b38e69 --- /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 0000000000000000000000000000000000000000..46d0882172f2eae148225f7f804364f44574265f --- /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 0000000000000000000000000000000000000000..2a7f77fab911bb92bffa37e9c4fd45330a0ea712 --- /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 0000000000000000000000000000000000000000..95152c3bb5d889f2138d7d60832ade0af36a1673 --- /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 0000000000000000000000000000000000000000..0665b386628d65f24754f72364ab4c4ab064235e --- /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 0000000000000000000000000000000000000000..9a41b7eea9318a5273e5a1264c7550e3eef8e67b --- /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 0000000000000000000000000000000000000000..ddee85b8a7302b80c13371f1040f854e26e0cc0f --- /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 0000000000000000000000000000000000000000..0ab27f52263fd014caa0bc9023baa61dfb959756 --- /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 0000000000000000000000000000000000000000..7a984d3179ec284789bd4210c23cc0ba50e5531f --- /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 0000000000000000000000000000000000000000..f644bbacdb8c7d96e79332e9adae5e0355eac061 --- /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 0000000000000000000000000000000000000000..e2529899f27faa8a7bb2e2488f38c132f406af39 --- /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 0000000000000000000000000000000000000000..ee8b3179aa6a5c31730d8228be2228ba78720ab5 --- /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 0000000000000000000000000000000000000000..2bad56bf959795c8b84555dcc1a449b0ece8e1f2 --- /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 0000000000000000000000000000000000000000..d5f230e47a90bb96fa1403142b2cf79b49f2baae --- /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 0000000000000000000000000000000000000000..df7b6c502d23e79b60ffd015c773ff97c5beadcf --- /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 0000000000000000000000000000000000000000..9478d3ed197ba6a49e5a7cc9f560659fe3840415 --- /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 0000000000000000000000000000000000000000..78758683d1b509d1d0f8aceb3a263343039c25a5 --- /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 0000000000000000000000000000000000000000..a2ab73448c2289ae22d916b6db54c6f1312ae4de --- /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 0000000000000000000000000000000000000000..67011e4f3cad4e2be483899d00e79698d0543262 --- /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 0000000000000000000000000000000000000000..ce231f2089eb8ff1426961bdc94fc9e32b47faf7 --- /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 0000000000000000000000000000000000000000..52bc99d305ece2b5c31e558c09f2509e86e38206 --- /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 0000000000000000000000000000000000000000..ce1d0c0ae2d244c1cca449910184cfbb377fdc65 --- /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 0000000000000000000000000000000000000000..aba4e852776d0e5efe9eb9044c307f0e9e8e9f03 --- /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 0000000000000000000000000000000000000000..728ec385eab466123da1d94ab5c7643905074f0f --- /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 0000000000000000000000000000000000000000..3a51d043f7bfc5441af0ef32addd92965b52a8f3 --- /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 0000000000000000000000000000000000000000..182b5e3c218c34936e74c0be68774ca77d5078df --- /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 0000000000000000000000000000000000000000..d5711657298fbea6108b452173669021260aa4cf --- /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 0000000000000000000000000000000000000000..6f0d282911c7e2bdb889c23ace8e15f45de3b390 --- /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 0000000000000000000000000000000000000000..76c5bc679337e8f4f73a891d2a34be3195e33b0a --- /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 0000000000000000000000000000000000000000..8817bb144e0cfb14432d85114951be8e69e1ece7 --- /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 0000000000000000000000000000000000000000..a62891d23e9eaddf7492df7a1818d681263c1bf1 --- /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 0000000000000000000000000000000000000000..5a24ad1ff158950b08b3ea724f7c09474dcd0ea2 --- /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 0000000000000000000000000000000000000000..37cc820147623af1f7bdbe55143bb3b282338bc6 --- /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 0000000000000000000000000000000000000000..4d188a146b25da0920f0a818439f5a24e2ac8eef --- /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 0000000000000000000000000000000000000000..7c4bfe27b76fcc5fb6bffe303f7d4d991125dd04 --- /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 0000000000000000000000000000000000000000..15168e1ded16889dd48289e430add0252305f483 --- /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 0000000000000000000000000000000000000000..d85a04a141f31890a87bc07deea17b42b00efd8e --- /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 0000000000000000000000000000000000000000..7be6ac341b577d4ef8a5a8d12b32cf89b81dba98 --- /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 0000000000000000000000000000000000000000..56540129a104d152caff2295cb0c94bc8fb676ef --- /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 0000000000000000000000000000000000000000..361293c7762a61c4508dce9f04625b7bcb35e18a --- /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 0000000000000000000000000000000000000000..8e57444339f15228bec8dd759f071decc04fa04a --- /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 0000000000000000000000000000000000000000..1672296fab1ac0e39d5eebd098182ca025a50e8f --- /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 0000000000000000000000000000000000000000..3b6e71701ea2ab6fa56242a2bc9c661ca0aaeb5b --- /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 0000000000000000000000000000000000000000..27873c5716e42570d7ba2be59bd899ce99896e86 --- /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 0000000000000000000000000000000000000000..70f216214ab815f7e9dc637a8419a887b98a7ec2 --- /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 0000000000000000000000000000000000000000..386b78d4023278bdf2169b3fde357a56a9ac9c0e --- /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 0000000000000000000000000000000000000000..05e80faca189a6f954b666aabfad927a76418b5a --- /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 0000000000000000000000000000000000000000..c12b38941e623d2c2b473ed402bd7f08b3ac96af --- /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 0000000000000000000000000000000000000000..02d548157437cad6f42cefabf1133b1c2f35ee9a --- /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 0000000000000000000000000000000000000000..6aebd627332ecb27aaee4396bbc6b4a3c0fc12fb --- /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 0000000000000000000000000000000000000000..f11376bdbe3cfa1e9b360ac52d327b1066a80312 --- /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 0000000000000000000000000000000000000000..ce169156040aa0cc831532ae609861eb9d8f28d0 --- /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 0000000000000000000000000000000000000000..0378b8a4caeff0d9e918223d59cb3e65e80ec2f8 --- /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 0000000000000000000000000000000000000000..e7b293698de8b989a5e4b9ff800458f8734ec73b --- /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 0000000000000000000000000000000000000000..0a3b25f661f9049298f913832b2caeeb685b2475 --- /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 0000000000000000000000000000000000000000..3b5b343e4438b07da1cae6573fa73da0d16a2f13 --- /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 0000000000000000000000000000000000000000..3763e90f528f3f881be5dc880b64d45876b5bb0b --- /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 0000000000000000000000000000000000000000..c775d4646877354719e13551ad6fd6a5990541fb --- /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 0000000000000000000000000000000000000000..24a1bc901df47ffa5c6b9c2e927452463de6e91b --- /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 0000000000000000000000000000000000000000..0e18638082cf0ecd840dad86a06fc499e9f16e0a --- /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 0000000000000000000000000000000000000000..6662458e34f366068ee6bc81fab3b1ad7618d308 --- /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 0000000000000000000000000000000000000000..b3a1c007e915cf28baf60f88095fb8733bddb870 --- /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 0000000000000000000000000000000000000000..4b5f4a27cad4f074589e7de1a4a91c9d32f83813 --- /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 0000000000000000000000000000000000000000..3932fec1a55da345af525717775f6a87c854abb6 --- /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 0000000000000000000000000000000000000000..7c348486584a3a18a3a2efe70d44a3e9bb786f62 --- /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 0000000000000000000000000000000000000000..b19e2c5662dd735b907569aade3a1f3d962b5224 --- /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 0000000000000000000000000000000000000000..18aef9d6cfc61739139ca39b3a49e5aebce4397e --- /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 0000000000000000000000000000000000000000..265c86e7508bc04710649c0b2e5ac7b3d5475beb --- /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 0000000000000000000000000000000000000000..7d12e5f45854fa349861ee45fc476c9f0270a9a3 --- /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 0000000000000000000000000000000000000000..0a8e18f8263d61959dfc8cc74d8fa33e016b7d52 --- /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 0000000000000000000000000000000000000000..1d5845eae33e7d148f047fa501bc88f14d2ad6b6 --- /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 0000000000000000000000000000000000000000..7a3e3a3736cd7bf9d799677927b4e0fcb8daa690 --- /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 0000000000000000000000000000000000000000..121ccaf8014796e50b0723e12e734c2635512d82 --- /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 0000000000000000000000000000000000000000..ca68ee423ef0ce4fc075b7725e24477d19e8db3d --- /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 0000000000000000000000000000000000000000..8c5636fb7c3a66efd8e6c90a6df4f85ad5eb9f69 --- /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 0000000000000000000000000000000000000000..f9566498095f45881de4edef853ec7938d2f5bdf --- /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 0000000000000000000000000000000000000000..4967e92bcbf81d36064c864bc5baf6e179e1bf86 --- /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 0000000000000000000000000000000000000000..e36b15841cb1f4aab21108b9cbb3d4a71ee6bc16 --- /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 0000000000000000000000000000000000000000..9bd1c3c3484394b9f057ced86a2881324db7f8f2 --- /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 0000000000000000000000000000000000000000..3bdb008c58507ca5394e1f493a33fa36456efa44 --- /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 0000000000000000000000000000000000000000..11314ec87150836da3557330e0fbf22a0afdc39b --- /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 0000000000000000000000000000000000000000..aa6b5d2a75c6925e5d3059599cefb5ae70d21808 --- /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 0000000000000000000000000000000000000000..b3b78068cd4f19930883a694ac22179e2859e525 --- /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 0000000000000000000000000000000000000000..77090f53199694d56a23d2711b082f5002a55060 --- /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 0000000000000000000000000000000000000000..01aa895aa022af14ba8e354613e3505dc0859c97 --- /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 0000000000000000000000000000000000000000..c7596573a72c1ef3e79159c2f36459a0307930e3 --- /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 0000000000000000000000000000000000000000..cf43b02d98eb5b289fc271e3182bd1a89d233071 --- /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 0000000000000000000000000000000000000000..4d5b3dcf37fcc084efcb66534101ad28c1ef83d3 --- /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 0000000000000000000000000000000000000000..d8d09914403d52b67b432ec0b15297cd6f977fc1 --- /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 0000000000000000000000000000000000000000..22ba3591a6fc7b768a04210706ef3b711cc8db19 --- /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 0000000000000000000000000000000000000000..8c677f2402f6b86ee1b4c4fdc92673b0534424ec --- /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 0000000000000000000000000000000000000000..a0eb18a1793bdd1d0913ed9871996f61cb12d1a8 --- /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 0000000000000000000000000000000000000000..47d5dbc37a6572c382ea94cc79c50a60a8ef6b15 --- /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 0000000000000000000000000000000000000000..b9ae1672970af02b5f9c39b05b8511a367b56330 --- /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 0000000000000000000000000000000000000000..368058d74a4c7109e1946757337abe88f37bf5d9 --- /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 0000000000000000000000000000000000000000..1f2ef72b886b2546bfe0d6d298e1fb1fbfe9a606 --- /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 0000000000000000000000000000000000000000..25feaf85312b7bd2b319771b539180fcbc81d7c3 --- /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 0000000000000000000000000000000000000000..4c6a3cdbc70a127393c4214ad01b740ba9d98593 --- /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 0000000000000000000000000000000000000000..72ac70ae3fcbc4e687a94e746cfcce0922230658 --- /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 0000000000000000000000000000000000000000..5d0ec42d0fe73e4369a95f457d6a1d50099c609b --- /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 0000000000000000000000000000000000000000..12344700b5e3bac76d28e9ca219abf31229ed6eb --- /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 0000000000000000000000000000000000000000..ef31e9c7bc594aa870d392b5a7bd5651eaa61a0d --- /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 0000000000000000000000000000000000000000..c2a1453c98b1f75e8918ca511d6a7edb2b562440 --- /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 0000000000000000000000000000000000000000..1c349b6b6468b49399acbec423c297fa11fd966b --- /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 0000000000000000000000000000000000000000..1b677b2e4e08f8a495949c3f89e8f1ca63e4f192 --- /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 0000000000000000000000000000000000000000..0000ce252a5cb133fb7c5aa316eed1c26fbdd17c --- /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 0000000000000000000000000000000000000000..219fdbead85c120508b108cf2bb180fbb65e7530 --- /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 0000000000000000000000000000000000000000..5ab924438f90e3f95833c442629248eead688991 --- /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 0000000000000000000000000000000000000000..25bf829d3499cdee65fb006513572f2d3047da63 --- /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 0000000000000000000000000000000000000000..d44b86918ce2a54dfff05d914f87ce1ead87e5fd --- /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 0000000000000000000000000000000000000000..7f99908cb4ace1f111a93535b11306fc0e6c0b45 --- /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 0000000000000000000000000000000000000000..46de51aa147c6b9e696c39469bf91ed6cbb6ae9b --- /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 0000000000000000000000000000000000000000..121718a1a3900a09a9fce98929b230d59a477268 --- /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 0000000000000000000000000000000000000000..42eb384293a90af54d98b924c889e38ec6d5b976 --- /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 0000000000000000000000000000000000000000..03934f7bcb6bd43a7d2aad545b7d3770db355831 --- /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 0000000000000000000000000000000000000000..e49947fe0d2179ecc2a183a1e7eacfb598bab6ce --- /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 0000000000000000000000000000000000000000..cb5e312dd33559858667968692e006d0ca1cbf67 --- /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 0000000000000000000000000000000000000000..ac829e5750ff552b62229bebe64088378632cbfe --- /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 0000000000000000000000000000000000000000..7dc9addcb0ddc8c72167fa0057a066d96def268b --- /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 0000000000000000000000000000000000000000..f6a3db562a2b5e8b8041d8170c2fd21bba6711f8 --- /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 0000000000000000000000000000000000000000..eafa04a11c2ef0a7b852d6cc8958915911ccf589 --- /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 0000000000000000000000000000000000000000..597f590f2d728b560242b18a1eb236412878d52f --- /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 0000000000000000000000000000000000000000..48d79cc6c8a22e9a71d160d11a77c4cc57c4cdbf --- /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 0000000000000000000000000000000000000000..30f2ceae468acbaef67e988262db40d25c837591 --- /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 0000000000000000000000000000000000000000..a8d41f5d6e68c5e7c5ee7a0fa9d139524b39d9b9 --- /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 0000000000000000000000000000000000000000..8e5713e7d35b70d73528729c11f32f3e0161b1e6 --- /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 0000000000000000000000000000000000000000..cbfa1323e19612e1227f952ee2cf22d362242730 --- /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 0000000000000000000000000000000000000000..ce0feb4e26fc470d0bfb458944700e384b53d43b --- /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 0000000000000000000000000000000000000000..75ab778e7024d64259165207ca45e077e1164e45 --- /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 0000000000000000000000000000000000000000..65fda8d4ecfa1d8bc43ead1044d6e3d7feb5e29e --- /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 0000000000000000000000000000000000000000..be991ea8a5d11779e2cec7d9613170bb01366c5e --- /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 0000000000000000000000000000000000000000..ef7bad6e1cb341519b3bc7ad1e888e26819c929a --- /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 0000000000000000000000000000000000000000..db52c4232a3af26228dc6a7557663c56b728c5d4 --- /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 0000000000000000000000000000000000000000..514842a539a141ce7307fd3a961d15955a19ae2c --- /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 0000000000000000000000000000000000000000..ae5258e3ff64b0a871a334793831fc5672684bc5 --- /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 0000000000000000000000000000000000000000..e55c5f1789f02a0ea83ec2b264bda31cd49c063f --- /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 0000000000000000000000000000000000000000..4090bb158b653b973b41d5d0cbd6413426eabca5 --- /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 0000000000000000000000000000000000000000..9058472ced20016c81404e3b3de19a606fb7a317 --- /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 0000000000000000000000000000000000000000..89f8c4637b917cde2b3a47697cd3be6955c30a99 --- /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 0000000000000000000000000000000000000000..1b37517725364b67f3a070fd9e176dd0ef70d146 --- /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 0000000000000000000000000000000000000000..98c096e76a278e8ba7ea47262550a34428eb5e92 --- /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 0000000000000000000000000000000000000000..e90b909d448e36dccb2c30a0acee9eeb62d6a1f9 --- /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 0000000000000000000000000000000000000000..889ea257f4c0681df12d90207675c19044fc7615 --- /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 4b8049da7364eb798906963a2da2cd4250faa4b8..36284f50d03b415680e67b7ccf7fa9acccd215fe 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 264928769fb452e372cccd36535ae336688b9e34..8ae74b89737f8d512e0f1619f0f644e567adcfb7 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 b1f4452f6dce5397f58748e292022ed2122c8d3f..0b5f6e6882a88e5dbc4a0e6350ab1f3876b7f100 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 e31094d28ee8b29f45e0ef14cc085e1e8a3bc0f4..b98282524004cf79b3a9d258eb33ed36cc6288b6 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 a877cc634a026345d2a35786d09575238f72d8ac..7a4056f67e07410fce7d65c5efeadf249bb677c4 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 0000000000000000000000000000000000000000..e00bb819727eab32710e59afb288f8b19887a4e2 --- /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 0000000000000000000000000000000000000000..c2a9f0ebbdf7a1b787415b53e09397988067a64c --- /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 0000000000000000000000000000000000000000..47ffe267b617d111dda700788f192312bc5cea2b --- /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 0000000000000000000000000000000000000000..b23acac5ad309bc1857f0830ea7b53a6980e478f --- /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 0000000000000000000000000000000000000000..6b8db83c4fcd55043c2f7a82564c25048f91dc0b --- /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 0000000000000000000000000000000000000000..00f6893c5f3a674bf3f175c95e0c1e8965c005b2 --- /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 0000000000000000000000000000000000000000..b248092dca33a26d4890c045b8adbbb6b68bb4c2 --- /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 0000000000000000000000000000000000000000..136b29de91f7a027c4f988c339ffd1d47a1dd824 --- /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 cdbdee5b93419fc21143bdd9309e7db303be8927..91add125c16e5e25e35f54d74c3090d1def4994b 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 3e6938011be4954cb577a0a115b5996560e99b7a..2bd98bd480043b19df25f6e88bdfc37fd088c031 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 6f6ed1f9abe6a81e94db2519cb2001cc03138892..a685a3b8f7b7082ca9945600bed4f24e50f4b3a6 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 62743fc8c5d44b25dd9662d31e98e721f05ed9c0..f718eb290800a9b332328e294dd1c9d0c7816d29 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 0000000000000000000000000000000000000000..7e16cbefa2ea335ec47361bfcf588d42bfb3c14d --- /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 0000000000000000000000000000000000000000..00b7550c64af9c19e2a4033e2922591e4a655969 --- /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 702996787bcadad680ddebcbece8ca425df88985..fa572d67694fee83fbc9297911393a025c70b7bd 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 b35ec1eebdeaa1f70092ccb1a292bf95b3275eed..dde4bda57db6f4c7d5678915034d3ea49f6761ce 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 c9f4e50c3806c5e7e503dfb47c8ff4fb803df51a..848285b4f68e4c900ec1075368b96a534c6a4026 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 b74cbeee6c292e614e1a14c3eb31a2a1fe2d7483..55b2fe0974042f1d50109bcac766c5e6becab3c5 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 0000000000000000000000000000000000000000..e97ae0ce97ddfe24987dbab7fac0d888290943c2 --- /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 985ffcfb3fa2a7f4b5d603a8bbb4e19282cf5985..14b59305d46eb2c4d006161f2ba1ab6830272654 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 594541e4d69614fc2c0a8cf80a5c0fdab949c54d..f2f95b5bdf2336635a15d87fbbb701793f28d433 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 96933b0c85ea3d3df03e1903403a04cf4d0159f4..4ed46d4b3fccc8f6340a1a36351828cc4c4060b3 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 54f6f3246793494937f4c32ff5572433acd51402..960b9c10f61479a7ccf828a002fdc455f34c7a28 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 641e95b5b1394785720f2cf29488baf9123dfabc..ddf33f9d72c8e35984ba84dac4753be36fee1c9f 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 275edf57cdcb20dedaf2f94ce8e71b4894b860d0..20809ca2f9acae210a860d92a3d5f771bb3f0cb9 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 c5324eb68b53346e8efe3e3f1a4fea79e615ce95..bc2876a412930d99db0b1ff4ccf1ef424c75fca6 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 4d0401b7f5b088c8a645231a5015e1d08fd0de8e..8eed5327d81a03494244421904f47771aef96d0f 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 cbb7c0b6efaf459383432ab08bc6e6116376addb..8b30be1a2e80e08c9b0de6e89d94839bfb2c4e1d 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 d35981c2919eef79357a9d6e139557541f62e6ba..4095d241c63004de44e4efd2f2dfeee0a7f25ca3 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 0000000000000000000000000000000000000000..924fa25f1ffb50a71a43ec22002da47618bac4d3 --- /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 0000000000000000000000000000000000000000..a5f6fbcf4f8ad9918c2b0887052309287b396f7d --- /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 5f23fded5acdc865288c8cf8b76785f25664a895..7b3a7d33caff7a3df7f9fda4efe95f6a8993ec64 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 50771eee600b2339d0fe0dc1bf7cfaff6485374f..71da94f6f8cdf4f941bce064ce42b6932f73d2e8 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 e712f226c15908b93be0d7e58b9179adc4fc927f..d975ccb9c932ac8392b2a862210a39b2e976b454 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 1e5c08ee221dd3c8c37347b8dc04fb1539ae0043..3bde5bddc5d508dd6ff91c707d3798120a11f249 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 7b740a830d2a9d53ec45dfd3d06f3d2ebb97b64e..0000000000000000000000000000000000000000 --- 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 2e1ca3ca513acdac359c969965db1902c6f26851..0000000000000000000000000000000000000000 --- 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