浏览代码

Merge branch 'development' into genpy

Conflicts:
	.gitignore
	.travis.yml
	Makefile
	tests/RunTravis.hx
	tests/sys/src/Main.hx
	tests/sys/testsys.hxproj
Simon Krajewski 11 年之前
父节点
当前提交
a1fedbbcfa
共有 61 个文件被更改,包括 1012 次插入297 次删除
  1. 2 0
      .gitignore
  2. 9 1
      .travis.yml
  3. 79 59
      Makefile
  4. 15 7
      README.md
  5. 34 42
      codegen.ml
  6. 5 0
      common.ml
  7. 10 1
      extra/CHANGES.txt
  8. 1 1
      extra/haxelib_src
  9. 3 1
      extra/release-checklist.txt
  10. 4 2
      filters.ml
  11. 12 1
      gencommon.ml
  12. 18 9
      gencpp.ml
  13. 3 6
      gencs.ml
  14. 9 6
      genjava.ml
  15. 8 11
      genjs.ml
  16. 1 0
      genneko.ml
  17. 3 0
      genphp.ml
  18. 14 3
      interp.ml
  19. 1 1
      libs
  20. 1 1
      main.ml
  21. 8 3
      matcher.ml
  22. 16 8
      optimizer.ml
  23. 3 3
      std/Map.hx
  24. 16 11
      std/UInt.hx
  25. 4 0
      std/cpp/NativeArray.hx
  26. 3 1
      std/cpp/vm/Debugger.hx
  27. 1 1
      std/cpp/zip/Compress.hx
  28. 1 1
      std/cpp/zip/Flush.hx
  29. 1 1
      std/cpp/zip/Uncompress.hx
  30. 1 1
      std/flash/_std/EReg.hx
  31. 2 2
      std/flash/_std/haxe/Json.hx
  32. 5 2
      std/haxe/Json.hx
  33. 28 10
      std/haxe/ds/Vector.hx
  34. 45 13
      std/haxe/format/JsonPrinter.hx
  35. 11 1
      std/haxe/macro/Context.hx
  36. 16 2
      std/haxe/macro/Printer.hx
  37. 2 2
      std/js/_std/haxe/Json.hx
  38. 1 1
      std/neko/zip/Compress.hx
  39. 1 1
      std/neko/zip/Flush.hx
  40. 1 1
      std/neko/zip/Uncompress.hx
  41. 6 6
      std/php/_std/haxe/Json.hx
  42. 93 42
      tests/RunTravis.hx
  43. 3 0
      tests/sys/compile-each.hxml
  44. 2 0
      tests/sys/compile-neko.hxml
  45. 1 0
      tests/sys/compile.hxml
  46. 0 8
      tests/sys/run.hxml
  47. 3 1
      tests/sys/src/Main.hx
  48. 218 0
      tests/sys/src/io/TestFileInput.hx
  49. 1 1
      tests/sys/testsys.hxproj
  50. 23 0
      tests/unit/issues/Issue2580.hx
  51. 0 0
      tests/unit/issues/Issue2750.hx
  52. 25 0
      tests/unit/issues/Issue2786.hx
  53. 33 0
      tests/unit/issues/Issue2828.hx
  54. 37 0
      tests/unit/issues/Issue2835.hx
  55. 12 0
      tests/unit/issues/Issue2871.hx
  56. 44 0
      tests/unit/issues/Issue2874.hx
  57. 9 0
      tests/unit/issues/Issue2881.hx
  58. 10 0
      tests/unit/issues/Issue2900.hx
  59. 28 0
      tests/unit/issues/Issue2907.hx
  60. 1 0
      typeload.ml
  61. 65 22
      typer.ml

+ 2 - 0
.gitignore

@@ -60,3 +60,5 @@ tests/optimization/testopt.js
 tests/unit/unit.py
 tests/unit/unit.py
 tests/unit/unit.py.res1.txt
 tests/unit/unit.py.res1.txt
 tests/unit/unit.py.res2.bin
 tests/unit/unit.py.res2.bin
+*.cmo
+tests/sys/bin/

+ 9 - 1
.travis.yml

@@ -9,11 +9,19 @@ env:
   matrix:
   matrix:
     - TARGET=python
     - TARGET=python
     - TARGET=polygonal-ds
     - TARGET=polygonal-ds
+    - TARGET=flambe
+    - TARGET=hxtemplo
+    - TARGET=munit
+    - TARGET=openfl-samples
+    - TARGET=flixel-demos
+    - TARGET=neko-sys
+    - TARGET=bytecode
 
 
 matrix:
 matrix:
   fast_finish: true
   fast_finish: true
   allow_failures:
   allow_failures:
     - env: TARGET=flash8
     - env: TARGET=flash8
+    - env: TARGET=flixel-demos
 
 
 before_install:
 before_install:
   - travis_retry sudo apt-get update
   - travis_retry sudo apt-get update
@@ -22,7 +30,7 @@ before_install:
   - cd ~/neko && make && sudo make install && cd $TRAVIS_BUILD_DIR
   - cd ~/neko && make && sudo make install && cd $TRAVIS_BUILD_DIR
 
 
 script:
 script:
-  - make
+  - /bin/sh -c '[ $TARGET = "bytecode" ] && make BYTECODE=1 || make'
   - make tools
   - make tools
   - sudo make install
   - sudo make install
   - cd tests/
   - cd tests/

+ 79 - 59
Makefile

@@ -18,31 +18,44 @@ OUTPUT=haxe
 EXTENSION=
 EXTENSION=
 OCAMLOPT=ocamlopt
 OCAMLOPT=ocamlopt
 OCAMLC=ocamlc
 OCAMLC=ocamlc
+LFLAGS=
 
 
 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= -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
 
 
-CC_CMD = $(OCAMLOPT) $(CFLAGS) -c $<
-CC_PARSER_CMD = $(OCAMLOPT) -pp camlp4o $(CFLAGS) -c parser.ml
-
-LIBS=unix.cmxa str.cmxa libs/extlib/extLib.cmxa libs/xml-light/xml-light.cmxa libs/swflib/swflib.cmxa \
-	libs/extc/extc.cmxa libs/neko/neko.cmxa libs/javalib/java.cmxa libs/ziplib/zip.cmxa \
-	libs/ttflib/ttf.cmxa libs/ilib/il.cmxa libs/objsize/objsize.cmxa
+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
 
 
 NATIVE_LIBS=-cclib libs/extc/extc_stubs.o -cclib -lz -cclib libs/objsize/c_objsize.o
 NATIVE_LIBS=-cclib libs/extc/extc_stubs.o -cclib -lz -cclib libs/objsize/c_objsize.o
 
 
+ifeq ($(BYTECODE),1)
+	TARGET_FLAG = bytecode
+	CC_CMD = $(OCAMLC)
+	LIB_EXT = cma
+	MODULE_EXT = cmo
+	NATIVE_LIB_FLAG = -custom
+else
+	TARGET_FLAG = native
+	CC_CMD = $(OCAMLOPT)
+	LIB_EXT = cmxa
+	MODULE_EXT = cmx
+endif
+
+CC_PARSER_CMD = $(CC_CMD) -pp camlp4o $(CFLAGS) -c parser.ml
+
 RELDIR=../../..
 RELDIR=../../..
 
 
 MODULES=ast type lexer common genxml parser typecore optimizer typeload \
 MODULES=ast type lexer common genxml parser typecore optimizer typeload \
-codegen gencommon genas3 gencpp genjs genneko genphp genswf8 \
+	codegen gencommon genas3 gencpp genjs genneko genphp genswf8 \
 	genswf9 genswf genjava gencs genpy interp dce filters typer matcher version main
 	genswf9 genswf genjava gencs genpy interp dce filters typer matcher version main
 
 
 ADD_REVISION=0
 ADD_REVISION=0
 
 
 # using $(CURDIR) on Windows will not work since it might be a Cygwin path
 # using $(CURDIR) on Windows will not work since it might be a Cygwin path
 ifdef SYSTEMROOT
 ifdef SYSTEMROOT
-EXTENSION=.exe
+	EXTENSION=.exe
 else
 else
-export HAXE_STD_PATH=$(CURDIR)/std
+	export HAXE_STD_PATH=$(CURDIR)/std
 endif
 endif
 
 
 ifneq ($(ADD_REVISION),0)
 ifneq ($(ADD_REVISION),0)
@@ -53,24 +66,20 @@ endif
 
 
 all: libs haxe
 all: libs haxe
 
 
-version.cmx:
-	echo $(VERSION_EXTRA) > version.ml
-	$(OCAMLOPT) $(CFLAGS) -c version.ml
-
 libs:
 libs:
-	make -C libs/extlib opt OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-	make -C libs/extc native OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-	make -C libs/neko OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-	make -C libs/javalib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-	make -C libs/ilib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-	make -C libs/ziplib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-	make -C libs/swflib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-	make -C libs/xml-light xml-light.cmxa OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-	make -C libs/ttflib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-	make -C libs/objsize OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC)
-
-haxe: $(MODULES:=.cmx)
-	$(OCAMLOPT) -o $(OUTPUT) $(NATIVE_LIBS) $(LIBS) $(MODULES:=.cmx)
+	make -C libs/extlib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG)
+	make -C libs/extc OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG)
+	make -C libs/neko OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG)
+	make -C libs/javalib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG)
+	make -C libs/ilib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG)
+	make -C libs/ziplib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG)
+	make -C libs/swflib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG)
+	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)
+
+haxe: $(MODULES:=.$(MODULE_EXT))
+	$(CC_CMD) -o $(OUTPUT) $(NATIVE_LIBS) $(NATIVE_LIB_FLAG) $(LFLAGS) $(LIBS:=.$(LIB_EXT)) $(MODULES:=.$(MODULE_EXT))
 
 
 haxelib:
 haxelib:
 	(cd $(CURDIR)/extra/haxelib_src && $(CURDIR)/$(OUTPUT) haxelib.hxml && nekotools boot bin/haxelib.n)
 	(cd $(CURDIR)/extra/haxelib_src && $(CURDIR)/$(OUTPUT) haxelib.hxml && nekotools boot bin/haxelib.n)
@@ -103,63 +112,72 @@ install_tools: tools
 uninstall:
 uninstall:
 	rm -rf $(INSTALL_BIN_DIR)/haxe $(INSTALL_BIN_DIR)/haxelib $(INSTALL_LIB_DIR)
 	rm -rf $(INSTALL_BIN_DIR)/haxe $(INSTALL_BIN_DIR)/haxelib $(INSTALL_LIB_DIR)
 
 
-codegen.cmx: optimizer.cmx typeload.cmx typecore.cmx type.cmx genxml.cmx common.cmx ast.cmx
+# Modules
+
+codegen.$(MODULE_EXT): optimizer.$(MODULE_EXT) typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) genxml.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-common.cmx: type.cmx ast.cmx
+common.$(MODULE_EXT): type.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-dce.cmx: ast.cmx common.cmx codegen.cmx type.cmx
+dce.$(MODULE_EXT): ast.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) type.$(MODULE_EXT)
 
 
-filters.cmx: ast.cmx common.cmx type.cmx dce.cmx codegen.cmx typecore.cmx
+filters.$(MODULE_EXT): ast.$(MODULE_EXT) common.$(MODULE_EXT) type.$(MODULE_EXT) dce.$(MODULE_EXT) codegen.$(MODULE_EXT) typecore.$(MODULE_EXT)
 
 
-genas3.cmx: type.cmx common.cmx codegen.cmx ast.cmx
+genas3.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-gencommon.cmx: type.cmx common.cmx codegen.cmx ast.cmx
+gencommon.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-gencpp.cmx: type.cmx lexer.cmx common.cmx codegen.cmx ast.cmx
+gencpp.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-gencs.cmx: type.cmx lexer.cmx gencommon.cmx common.cmx codegen.cmx ast.cmx
+gencs.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) gencommon.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-genjava.cmx: type.cmx gencommon.cmx common.cmx codegen.cmx ast.cmx
+genjava.$(MODULE_EXT): type.$(MODULE_EXT) gencommon.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-genjs.cmx: type.cmx optimizer.cmx lexer.cmx common.cmx codegen.cmx ast.cmx
+genjs.$(MODULE_EXT): type.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-genneko.cmx: type.cmx lexer.cmx common.cmx codegen.cmx ast.cmx
+genneko.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-genphp.cmx: type.cmx lexer.cmx common.cmx codegen.cmx ast.cmx
+genphp.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-genpy.cmx: type.cmx lexer.cmx common.cmx codegen.cmx ast.cmx
+genpy.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-genswf.cmx: type.cmx genswf9.cmx genswf8.cmx common.cmx ast.cmx
+genswf.$(MODULE_EXT): type.$(MODULE_EXT) genswf9.$(MODULE_EXT) genswf8.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-genswf8.cmx: type.cmx lexer.cmx common.cmx codegen.cmx ast.cmx
+genswf8.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-genswf9.cmx: type.cmx lexer.cmx genswf8.cmx common.cmx codegen.cmx ast.cmx
+genswf9.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) genswf8.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-genxml.cmx: type.cmx lexer.cmx common.cmx ast.cmx
+genxml.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-interp.cmx: typecore.cmx type.cmx lexer.cmx genneko.cmx common.cmx codegen.cmx ast.cmx genswf.cmx genjava.cmx parser.cmx
+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) parser.$(MODULE_EXT)
 
 
-matcher.cmx: optimizer.cmx codegen.cmx typecore.cmx type.cmx typer.cmx common.cmx ast.cmx
+matcher.$(MODULE_EXT): optimizer.$(MODULE_EXT) codegen.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) typer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-main.cmx: filters.cmx matcher.cmx typer.cmx typeload.cmx typecore.cmx type.cmx parser.cmx optimizer.cmx lexer.cmx interp.cmx genxml.cmx genswf.cmx genphp.cmx genneko.cmx genjs.cmx gencpp.cmx genas3.cmx common.cmx codegen.cmx ast.cmx gencommon.cmx genjava.cmx gencs.cmx genpy.cmx version.cmx
+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)
 
 
-optimizer.cmx: typecore.cmx type.cmx parser.cmx common.cmx ast.cmx
+optimizer.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-parser.cmx: parser.ml lexer.cmx common.cmx ast.cmx
+parser.$(MODULE_EXT): parser.ml lexer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 	$(CC_PARSER_CMD)
 	$(CC_PARSER_CMD)
 
 
-type.cmx: ast.cmx
+type.$(MODULE_EXT): ast.$(MODULE_EXT)
+
+typecore.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-typecore.cmx: type.cmx common.cmx ast.cmx
+typeload.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 
-typeload.cmx: typecore.cmx type.cmx parser.cmx optimizer.cmx lexer.cmx common.cmx ast.cmx
+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)
 
 
-typer.cmx: typeload.cmx typecore.cmx type.cmx parser.cmx optimizer.cmx lexer.cmx interp.cmx genneko.cmx genjs.cmx common.cmx codegen.cmx ast.cmx filters.cmx
+lexer.$(MODULE_EXT): lexer.ml
 
 
-lexer.cmx: lexer.ml
+lexer.$(MODULE_EXT): ast.$(MODULE_EXT)
 
 
-lexer.cmx: ast.cmx
+ast.$(MODULE_EXT):
 
 
+version.$(MODULE_EXT):
+	echo $(VERSION_EXTRA) > version.ml
+	$(CC_CMD) $(CFLAGS) -c version.ml
+
+# Clean
 
 
 clean: clean_libs clean_haxe clean_tools
 clean: clean_libs clean_haxe clean_tools
 
 
@@ -173,21 +191,23 @@ clean_libs:
 	make -C libs/swflib clean
 	make -C libs/swflib clean
 	make -C libs/xml-light clean
 	make -C libs/xml-light clean
 	make -C libs/ttflib clean
 	make -C libs/ttflib clean
+	make -C libs/objsize clean
 
 
 clean_haxe:
 clean_haxe:
-	rm -f $(MODULES:=.obj) $(MODULES:=.o) $(MODULES:=.cmx) $(MODULES:=.cmi) lexer.ml $(OUTPUT)
+	rm -f $(MODULES:=.obj) $(MODULES:=.o) $(MODULES:=.cmx) $(MODULES:=.cmi) $(MODULES:=.cmo) lexer.ml $(OUTPUT)
 
 
 clean_tools:
 clean_tools:
 	rm -f $(OUTPUT) haxelib
 	rm -f $(OUTPUT) haxelib
 
 
 # SUFFIXES
 # SUFFIXES
+
 .ml.cmx:
 .ml.cmx:
-	$(CC_CMD)
+	$(CC_CMD) $(CFLAGS) -c $<
 
 
-.mli.cmi:
-	$(CC_CMD)
+.ml.cmo:
+	$(CC_CMD) $(CFLAGS) -c $<
 
 
 .mll.ml:
 .mll.ml:
 	ocamllex $<
 	ocamllex $<
 
 
-.PHONY: haxe libs version.cmx haxelib
+.PHONY: haxe libs version.cmx version.cmo haxelib

+ 15 - 7
README.md

@@ -35,14 +35,14 @@ For the complete Haxe licenses, please see http://haxe.org/doc/license or [extra
 
 
 ## Installing Haxe
 ## Installing Haxe
 
 
-The latest stable release is [Haxe v3.1.2](http://haxe.org/download). Pre-built binaries are available for your platform:
+The latest stable release is [Haxe v3.1.3](http://haxe.org/download). Pre-built binaries are available for your platform:
 
 
- * **[Windows installer](http://haxe.org/file/haxe-3.1.2-win.exe)**
- * **[Windows binaries](http://haxe.org/file/haxe-3.1.2-win.zip)**
- * **[OSX installer](http://haxe.org/file/haxe-3.1.2-osx-installer.pkg)**
- * **[OSX binaries](http://haxe.org/file/haxe-3.1.2-osx.tar.gz)**
- * **[Linux 32-bit binaries](http://haxe.org/file/haxe-3.1.2-linux32.tar.gz)**
- * **[Linux 64-bit binaries](http://haxe.org/file/haxe-3.1.2-linux64.tar.gz)**
+ * **[Windows installer](http://haxe.org/file/haxe-3.1.3-win.exe)**
+ * **[Windows binaries](http://haxe.org/file/haxe-3.1.3-win.zip)**
+ * **[OSX installer](http://haxe.org/file/haxe-3.1.3-osx-installer.pkg)**
+ * **[OSX binaries](http://haxe.org/file/haxe-3.1.3-osx.tar.gz)**
+ * **[Linux 32-bit binaries](http://haxe.org/file/haxe-3.1.3-linux32.tar.gz)**
+ * **[Linux 64-bit binaries](http://haxe.org/file/haxe-3.1.3-linux64.tar.gz)**
 
 
 Automated development builds are available from [build.haxe.org](http://build.haxe.org).
 Automated development builds are available from [build.haxe.org](http://build.haxe.org).
 
 
@@ -70,3 +70,11 @@ You can get help and talk with fellow Haxers from around the world via:
 
 
  * the [official Haxe Google Group](https://groups.google.com/forum/#!forum/haxelang)
  * the [official Haxe Google Group](https://groups.google.com/forum/#!forum/haxelang)
  * the [Haxe IRC chatroom](http://unic0rn.github.io/tiramisu/haxe/), #haxe on chat.freenode.net
  * the [Haxe IRC chatroom](http://unic0rn.github.io/tiramisu/haxe/), #haxe on chat.freenode.net
+
+## Version compatibility
+
+Haxe   | neko
+----   | -----
+2.*    | 1.*
+3.0.0  | 2.0.0
+3.1.3  | 2.0.0

+ 34 - 42
codegen.ml

@@ -681,9 +681,6 @@ module Abstract = struct
 		make_static_call ctx c cf (apply_params a.a_types pl) args t p
 		make_static_call ctx c cf (apply_params a.a_types pl) args t p
 
 
 	let rec do_check_cast ctx tleft eright p =
 	let rec do_check_cast ctx tleft eright p =
-		let tright = follow eright.etype in
-		let tleft = follow tleft in
-		if tleft == tright then eright else
 		let recurse cf f =
 		let recurse cf f =
 			if cf == ctx.curfield || List.mem cf !cast_stack then error "Recursive implicit cast" p;
 			if cf == ctx.curfield || List.mem cf !cast_stack then error "Recursive implicit cast" p;
 			cast_stack := cf :: !cast_stack;
 			cast_stack := cf :: !cast_stack;
@@ -691,43 +688,38 @@ module Abstract = struct
 			cast_stack := List.tl !cast_stack;
 			cast_stack := List.tl !cast_stack;
 			r
 			r
 		in
 		in
-		try (match tright,tleft with
-			| (TAbstract({a_impl = Some c1} as a1,pl1) as t1),(TAbstract({a_impl = Some c2} as a2,pl2) as t2) ->
-				if a1 == a2 then
-					eright
-				else begin
-					let c,cfo,a,pl = try
-						if Meta.has Meta.MultiType a1.a_meta then raise Not_found;
-						c1,snd (find_to a1 pl1 t2),a1,pl1
-					with Not_found ->
-						if Meta.has Meta.MultiType a2.a_meta then raise Not_found;
-						c2,snd (find_from a2 pl2 t1 t2),a2,pl2
-					in
-					match cfo with
-					| None -> eright
-					| Some cf ->
-						recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
-				end
-			| _, TMono _ | TMono _, _ ->
-				eright
-			| TAbstract({a_impl = Some c} as a,pl),t2 when not (Meta.has Meta.MultiType a.a_meta) ->
-				begin match find_to a pl t2 with
-					| tcf,None ->
-						let tcf = apply_params a.a_types pl tcf in
-						if type_iseq tcf tleft then eright else do_check_cast ctx tcf eright p
-					| _,Some cf ->
-						recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
-				end
-			| t1,(TAbstract({a_impl = Some c} as a,pl) as t2) when not (Meta.has Meta.MultiType a.a_meta) ->
-				begin match find_from a pl t1 t2 with
-					| tcf,None ->
-						let tcf = apply_params a.a_types pl tcf in
-						if type_iseq tcf tleft then eright else do_check_cast ctx tcf eright p
-					| _,Some cf ->
-						recurse cf (fun () -> make_static_call ctx c cf a pl [eright] tleft p)
-				end
-			| _ ->
-				eright)
+		let find a tl f =
+			let tcf,cfo = f() in
+			match cfo,a.a_impl with
+				| None,_ ->
+					let tcf = apply_params a.a_types tl tcf in
+					if type_iseq tcf tleft then
+						eright
+					else
+						(* TODO: causes Java overload issues *)
+						(* let eright = mk (TCast(eright,None)) tleft p in *)
+						do_check_cast ctx tcf eright p
+				| Some cf,Some c ->
+					recurse cf (fun () -> make_static_call ctx c cf a tl [eright] tleft p)
+				| _ ->
+					assert false
+		in
+		if type_iseq tleft eright.etype then
+			eright
+		else try
+			begin match follow eright.etype with
+				| TAbstract(a,tl) ->
+					find a tl (fun () -> find_to a tl tleft)
+				| _ ->
+					raise Not_found
+			end
+		with Not_found -> try
+			begin match follow tleft with
+				| TAbstract(a,tl) ->
+					find a tl (fun () -> find_from a tl eright.etype tleft)
+				| _ ->
+					raise Not_found
+			end
 		with Not_found ->
 		with Not_found ->
 			eright
 			eright
 
 
@@ -770,10 +762,10 @@ module Abstract = struct
 				{e with etype = m}
 				{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) ->
 			| 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
 				begin match follow e1.etype with
-					| TAbstract({a_impl = Some c} as a,_) ->
+					| TAbstract({a_impl = Some c} as a,tl) ->
 						begin try
 						begin try
 							let cf = PMap.find "toString" c.cl_statics in
 							let cf = PMap.find "toString" c.cl_statics in
-							make_static_call ctx c cf a [] [e1] ctx.t.tstring e.epos
+							make_static_call ctx c cf a tl [e1] ctx.t.tstring e.epos
 						with Not_found ->
 						with Not_found ->
 							e
 							e
 						end
 						end

+ 5 - 0
common.ml

@@ -937,6 +937,11 @@ let rec mkdir_recursive base dir_list =
 				Unix.mkdir path 0o755;
 				Unix.mkdir path 0o755;
 		mkdir_recursive (if (path = "") then "/" else path) remaining
 		mkdir_recursive (if (path = "") then "/" else path) remaining
 
 
+let mkdir_from_path path =
+	let parts = Str.split_delim (Str.regexp "[\\/]+") path in
+	let dir_list = List.rev (List.tl (List.rev parts)) in
+	mkdir_recursive "" dir_list
+
 let mem_size v =
 let mem_size v =
 	Objsize.size_with_headers (Objsize.objsize v [] [])
 	Objsize.size_with_headers (Objsize.objsize v [] [])
 
 

+ 10 - 1
extra/CHANGES.txt

@@ -1,18 +1,27 @@
-2014-??-??: 3.1.3
+2014-??-??: 3.2.0
+
+	all : fixed nullability of abstracts over functions
+
+2014-04-13: 3.1.3
 
 
 	Bugfixes:
 	Bugfixes:
 
 
+	all : fixed handling of abstract variance
 	flash : ensure correct endianess in haxe.io.BytesBuffer
 	flash : ensure correct endianess in haxe.io.BytesBuffer
+	cpp : fixed issue involving class paths with spaces
+	php : fixed >>>
 	macro : fixed haxe.macro.Compiler.keep
 	macro : fixed haxe.macro.Compiler.keep
 
 
 	General improvements and optimizations:
 	General improvements and optimizations:
 
 
 	all : give @:deprecated warnings by default, allow -D no-deprecation-warnings
 	all : give @:deprecated warnings by default, allow -D no-deprecation-warnings
+	cpp : optimized Vector implementation
 
 
 	Standard Library:
 	Standard Library:
 
 
 	all : renamed Bytes.readDouble/Float to getDouble/Float to avoid inheritance issues
 	all : renamed Bytes.readDouble/Float to getDouble/Float to avoid inheritance issues
 	all : deprecated Bytes.readString in favor of getString
 	all : deprecated Bytes.readString in favor of getString
+	all : added pretty-printing to haxe.format.JsonPrinter (and haxe.Json)
 
 
 2014-03-29: 3.1.2
 2014-03-29: 3.1.2
 
 

+ 1 - 1
extra/haxelib_src

@@ -1 +1 @@
-Subproject commit 2d2252dc3ad44a62834a029b8bdcef84d72db8f4
+Subproject commit 8c5fb02d784ad257ac4684ffc443c719a96f3020

+ 3 - 1
extra/release-checklist.txt

@@ -9,8 +9,10 @@
 - Run it with the fileName corresponding to the latest master file name on builds.haxe.org.
 - Run it with the fileName corresponding to the latest master file name on builds.haxe.org.
 - Upload generated files to some place.
 - Upload generated files to some place.
 - Update Haxe download page.
 - Update Haxe download page.
+- Update Github README page.
 - Double-check that you got the links right.
 - Double-check that you got the links right.
 - Regenerate and upload API documentation.
 - Regenerate and upload API documentation.
 - Update http://haxe.org/file/CHANGES.txt
 - Update http://haxe.org/file/CHANGES.txt
 - Write announcement post.
 - Write announcement post.
-- Post announcement post.
+- Post announcement post.
+

+ 4 - 2
filters.ml

@@ -1118,12 +1118,14 @@ let run com tctx main =
 	if not (Common.defined com Define.As3 || dce_mode = "no" || Common.defined com Define.DocGen) then Dce.run com main (dce_mode = "full" && not (Common.defined com Define.Interp));
 	if not (Common.defined com Define.As3 || dce_mode = "no" || Common.defined com Define.DocGen) then Dce.run com main (dce_mode = "full" && not (Common.defined com Define.Interp));
 	(* always filter empty abstract implementation classes (issue #1885) *)
 	(* always filter empty abstract implementation classes (issue #1885) *)
 	List.iter (fun mt -> match mt with
 	List.iter (fun mt -> match mt with
-		| TClassDecl({cl_kind = KAbstractImpl _} as c) ->
+		| 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 =
 			let is_runtime_field cf =
 				not (Meta.has Meta.Enum cf.cf_meta)
 				not (Meta.has Meta.Enum cf.cf_meta)
 			in
 			in
 			(* also filter abstract implementation classes that have only @:enum fields (issue #2858) *)
 			(* also filter abstract implementation classes that have only @:enum fields (issue #2858) *)
-			if not (Meta.has Meta.Used c.cl_meta) || not (List.exists is_runtime_field c.cl_ordered_statics) then
+			if not (Meta.has Meta.Used c.cl_meta || Common.defined com Define.As3) || not (List.exists is_runtime_field c.cl_ordered_statics) then
 				c.cl_extern <- true
 				c.cl_extern <- true
 		| _ -> ()
 		| _ -> ()
 	) com.types;
 	) com.types;

+ 12 - 1
gencommon.ml

@@ -5714,6 +5714,9 @@ struct
         mk_cast to_t e)
         mk_cast to_t e)
       | TAbstract (a_to, _), TAbstract(a_from, _) when a_to == a_from ->
       | TAbstract (a_to, _), TAbstract(a_from, _) when a_to == a_from ->
         e
         e
+      | TAbstract _, TInst({ cl_kind = KTypeParameter _ }, _)
+      | TInst({ cl_kind = KTypeParameter _ }, _), TAbstract _ ->
+        do_unsafe_cast()
       | TAbstract _, _
       | TAbstract _, _
       | _, TAbstract _ ->
       | _, TAbstract _ ->
         (try
         (try
@@ -7358,6 +7361,14 @@ struct
         let do_field cf cf_type is_static =
         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, cf)); etype = cf_type; epos = pos } in
           let get_field ethis = { eexpr = TField (ethis, if is_static then FStatic (cl, cf) else FInstance(cl, 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 this = if is_static then mk_classtype_access cl pos else { 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
+            | _ ->
+              value_local
+            else
+              value_local
+          in
 
 
           let ret =
           let ret =
           {
           {
@@ -7450,7 +7461,7 @@ struct
         let do_field cf cf_type static =
         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 this = if static then mk_classtype_access cl pos else { eexpr = TConst(TThis); etype = t; epos = pos } in
           match is_float, follow cf_type with
           match is_float, follow cf_type with
-            | true, TInst( { cl_kind = KTypeParameter _ }, [] ) ->
+            | 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 (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 ))
               mk_return (maybe_cast (get_field cf cf_type this cl cf.cf_name ))

+ 18 - 9
gencpp.ml

@@ -1379,7 +1379,6 @@ and define_local_return_block_ctx ctx expression name retval =
    let output_i = writer#write_i in
    let output_i = writer#write_i in
    let output = ctx.ctx_output in
    let output = ctx.ctx_output in
    let check_this = function | "this" when not ctx.ctx_real_this_ptr -> "__this" | x -> x in
    let check_this = function | "this" when not ctx.ctx_real_this_ptr -> "__this" | x -> x in
-   let reference = function | "this" -> " *__this" | "_this" -> " _this" | name -> " &" ^name in
    let rec define_local_return_block expression  =
    let rec define_local_return_block expression  =
       let declarations = Hashtbl.create 0 in
       let declarations = Hashtbl.create 0 in
       let undeclared = Hashtbl.create 0 in
       let undeclared = Hashtbl.create 0 in
@@ -1399,8 +1398,17 @@ and define_local_return_block_ctx ctx expression name retval =
          | TObjectDecl _ -> "Dynamic"
          | TObjectDecl _ -> "Dynamic"
          | _ -> type_string expression.etype in
          | _ -> type_string expression.etype in
       output_i ("inline static " ^ ret_type ^ " Block( ");
       output_i ("inline static " ^ ret_type ^ " Block( ");
-      output (String.concat "," ( (List.map (fun var ->
-            (Hashtbl.find undeclared var) ^ (reference var)) ) vars));
+      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"
+               | "_this" -> var_type ^ " _this"
+               | name -> var_type ^ " &" ^name
+            ) vars) ) );
       output (")");
       output (")");
       let return_data = ret_type <> "Void" in
       let return_data = ret_type <> "Void" in
       writer#begin_block;
       writer#begin_block;
@@ -3023,7 +3031,8 @@ let generate_class_files common_ctx member_types super_deps constructor_deps cla
                   if has_meta_key definition.cf_meta Meta.NoDebug then ctx.ctx_debug_level <- 0;
                   if has_meta_key definition.cf_meta Meta.NoDebug then ctx.ctx_debug_level <- 0;
                   if ctx.ctx_debug_level >0 then begin
                   if ctx.ctx_debug_level >0 then begin
                      hx_stack_push ctx output_cpp dot_name "new" function_def.tf_expr.epos;
                      hx_stack_push ctx output_cpp dot_name "new" function_def.tf_expr.epos;
-                     List.iter (fun (a,(t,o)) -> output_cpp ("\nHX_STACK_ARG(" ^ (keyword_remap o) ^ ",\"" ^ a ^"\")\n") ) constructor_arg_var_list;
+                     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;
                   end;
 
 
                   if (has_default_values function_def.tf_args) then begin
                   if (has_default_values function_def.tf_args) then begin
@@ -3829,7 +3838,7 @@ and s_fun t void =
 
 
 and s_type_params = function
 and s_type_params = function
    | [] -> ""
    | [] -> ""
-   | l -> "<" ^ String.concat ", " (List.map s_type  l) ^ ">"
+   | l -> "< " ^ String.concat ", " (List.map s_type  l) ^ " >"
 
 
 ;;
 ;;
 
 
@@ -3866,7 +3875,7 @@ let gen_extern_class common_ctx class_def file_info =
    in
    in
 
 
 
 
-   let params = function [] -> "" | l ->  "<" ^ (String.concat "," (List.map (fun (n,t) -> n) l) ^ ">")  in
+   let params = function [] -> "" | l ->  "< " ^ (String.concat "," (List.map (fun (n,t) -> n) l) ^ " >")  in
    let output = file#write in
    let output = file#write in
 
 
    let print_field stat f =
    let print_field stat f =
@@ -3909,8 +3918,8 @@ let gen_extern_class common_ctx class_def file_info =
             ^ " " ^ (snd path) ^ (params c.cl_types) );
             ^ " " ^ (snd path) ^ (params c.cl_types) );
    (match c.cl_super with None -> () | Some (c,pl) -> output (" extends " ^  (s_type (TInst (c,pl)))));
    (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);
    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) ^ ">"));
+   (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";
    output "{\n";
    (match c.cl_constructor with
    (match c.cl_constructor with
    | None -> ()
    | None -> ()
@@ -3931,7 +3940,7 @@ let gen_extern_enum common_ctx enum_def file_info =
    let file = new_source_file common_ctx common_ctx.file  "extern" ".hx" path in
    let file = new_source_file common_ctx common_ctx.file  "extern" ".hx" path in
    let output = file#write in
    let output = file#write in
 
 
-   let params = function [] -> "" | l ->  "<" ^ (String.concat "," (List.map (fun (n,t) -> n) l) ^ ">")  in
+   let params = function [] -> "" | l ->  "< " ^ (String.concat "," (List.map (fun (n,t) -> n) l) ^ " >")  in
    output ( "package " ^ (String.concat "." (fst path)) ^ ";\n" );
    output ( "package " ^ (String.concat "." (fst path)) ^ ";\n" );
    output ( "@:include extern " ^ (if enum_def.e_private then "private " else "")
    output ( "@:include extern " ^ (if enum_def.e_private then "private " else "")
             ^ " enum " ^ (snd path) ^ (params enum_def.e_types) );
             ^ " enum " ^ (snd path) ^ (params enum_def.e_types) );

+ 3 - 6
gencs.ml

@@ -1055,7 +1055,7 @@ let configure gen =
 						write w " += ";
 						write w " += ";
 						expr_s w ev
 						expr_s w ev
 					end else
 					end else
-						do_call w e []
+						do_call w e [ev]
 				| TCall( ({ eexpr = TField(ef,f) } as e), [ev] ) when String.starts_with (field_name f) "remove_" ->
 				| TCall( ({ eexpr = TField(ef,f) } as e), [ev] ) when String.starts_with (field_name f) "remove_" ->
 					let name = field_name f in
 					let name = field_name f in
 					let propname = String.sub name 7 (String.length name - 7) in
 					let propname = String.sub name 7 (String.length name - 7) in
@@ -1066,7 +1066,7 @@ let configure gen =
 						write w " -= ";
 						write w " -= ";
 						expr_s w ev
 						expr_s w ev
 					end else
 					end else
-						do_call w e []
+						do_call w e [ev]
 				| TCall( ({ eexpr = TField(ef,f) } as e), [] ) when String.starts_with (field_name f) "get_" ->
 				| TCall( ({ eexpr = TField(ef,f) } as e), [] ) when String.starts_with (field_name f) "get_" ->
 					let name = field_name f in
 					let name = field_name f in
 					let propname = String.sub name 4 (String.length name - 4) in
 					let propname = String.sub name 4 (String.length name - 4) in
@@ -2657,10 +2657,7 @@ let configure gen =
     mkdir (gen.gcon.file ^ "/src/Resources");
     mkdir (gen.gcon.file ^ "/src/Resources");
     Hashtbl.iter (fun name v ->
     Hashtbl.iter (fun name v ->
       let full_path = gen.gcon.file ^ "/src/Resources/" ^ name in
       let full_path = gen.gcon.file ^ "/src/Resources/" ^ name in
-      let parts = Str.split_delim (Str.regexp "[\\/]+") full_path in
-      let dir_list = List.rev (List.tl (List.rev parts)) in
-
-      Common.mkdir_recursive "" dir_list;
+      mkdir_from_path full_path;
 
 
       let f = open_out full_path in
       let f = open_out full_path in
       output_string f v;
       output_string f v;

+ 9 - 6
genjava.ml

@@ -1624,7 +1624,13 @@ let configure gen =
     print w "%s %s %s %s" access (String.concat " " modifiers) clt (change_clname (snd cl.cl_path));
     print w "%s %s %s %s" access (String.concat " " modifiers) clt (change_clname (snd cl.cl_path));
     (* type parameters *)
     (* type parameters *)
     let params, _ = get_string_params cl.cl_types in
     let params, _ = get_string_params cl.cl_types in
-    let cl_p_to_string (c,p) = path_param_s cl.cl_pos (TClassDecl c) c.cl_path p in
+    let cl_p_to_string (c,p) =
+      let p = List.map (fun t -> match follow t with
+        | TMono _ | TDynamic _ -> t_empty
+        | _ -> t) p
+      in
+      path_param_s cl.cl_pos (TClassDecl c) c.cl_path p
+    in
     print w "%s" params;
     print w "%s" params;
     (if is_some cl.cl_super then print w " extends %s" (cl_p_to_string (get cl.cl_super)));
     (if is_some cl.cl_super then print w " extends %s" (cl_p_to_string (get cl.cl_super)));
     (match cl.cl_implements with
     (match cl.cl_implements with
@@ -2135,10 +2141,7 @@ let configure gen =
       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 = Ast.null_pos } :: !res;
 
 
       let full_path = gen.gcon.file ^ "/src/" ^ name in
       let full_path = gen.gcon.file ^ "/src/" ^ name in
-      let parts = Str.split_delim (Str.regexp "[\\/]+") full_path in
-      let dir_list = List.rev (List.tl (List.rev parts)) in
-
-      Common.mkdir_recursive "" dir_list;
+      mkdir_from_path full_path;
 
 
       let f = open_out full_path in
       let f = open_out full_path in
       output_string f v;
       output_string f v;
@@ -2455,7 +2458,7 @@ let convert_java_enum ctx p pe =
     ) field.jf_flags;
     ) field.jf_flags;
 
 
     List.iter (function
     List.iter (function
-      | AttrDeprecated -> cff_meta := (Meta.Deprecated, [], p) :: !cff_meta
+      | AttrDeprecated when jc.cpath <> (["java";"util"],"Date") -> cff_meta := (Meta.Deprecated, [], p) :: !cff_meta
       (* TODO: pass anotations as @:meta *)
       (* TODO: pass anotations as @:meta *)
       | AttrVisibleAnnotations ann ->
       | AttrVisibleAnnotations ann ->
         List.iter (function
         List.iter (function

+ 8 - 11
genjs.ml

@@ -1223,7 +1223,7 @@ let generate com =
 
 
 		(* Wrap output in a closure *)
 		(* Wrap output in a closure *)
 		if (anyExposed && (Common.defined com Define.ShallowExpose)) then (
 		if (anyExposed && (Common.defined com Define.ShallowExpose)) then (
-			print ctx "var $hx_exports = {}";
+			print ctx "var $hx_exports = $hx_exports || {}";
 			ctx.separator <- true;
 			ctx.separator <- true;
 			newline ctx
 			newline ctx
 		);
 		);
@@ -1231,18 +1231,15 @@ let generate com =
 		if (anyExposed && not (Common.defined com Define.ShallowExpose)) then print ctx "$hx_exports";
 		if (anyExposed && not (Common.defined com Define.ShallowExpose)) then print ctx "$hx_exports";
 		print ctx ") { \"use strict\"";
 		print ctx ") { \"use strict\"";
 		newline ctx;
 		newline ctx;
-		let rec print_obj { os_fields = fields } = (
-			print ctx "{";
-			concat ctx "," (fun ({ os_name = name } as f) -> print ctx "%s" (name ^ ":"); print_obj f) fields;
-			print 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
 		in
-		List.iter (fun f ->
-			print ctx "$hx_exports.%s = " f.os_name;
-			print_obj f;
-			ctx.separator <- true;
-			newline ctx
-		) exposedObject.os_fields;
+		List.iter (fun f -> print_obj f "$hx_exports") exposedObject.os_fields;
 	end;
 	end;
 
 
 	(* TODO: fix $estr *)
 	(* TODO: fix $estr *)

+ 1 - 0
genneko.ml

@@ -848,6 +848,7 @@ let generate com =
 	let use_nekoc = Common.defined com Define.UseNekoc in
 	let use_nekoc = Common.defined com Define.UseNekoc in
 	if not use_nekoc then begin
 	if not use_nekoc then begin
 		try
 		try
+			mkdir_from_path com.file;
 			let ch = IO.output_channel (open_out_bin com.file) in
 			let ch = IO.output_channel (open_out_bin com.file) in
 			Nbytecode.write ch (Ncompile.compile ctx.version e);
 			Nbytecode.write ch (Ncompile.compile ctx.version e);
 			IO.close_out ch;
 			IO.close_out ch;

+ 3 - 0
genphp.ml

@@ -1517,6 +1517,9 @@ and gen_expr ctx e =
 		print ctx "while($%s->hasNext()) {" tmp;
 		print ctx "while($%s->hasNext()) {" tmp;
 		let bend = open_block ctx in
 		let bend = open_block ctx in
 		newline ctx;
 		newline ctx;
+		(* unset loop variable (issue #2900) *)
+		print ctx "unset($%s)" v;
+		newline ctx;
 		print ctx "$%s = $%s->next()" v tmp;
 		print ctx "$%s = $%s->next()" v tmp;
 		gen_while_expr ctx e;
 		gen_while_expr ctx e;
 		bend();
 		bend();

+ 14 - 3
interp.ml

@@ -202,6 +202,7 @@ let dec_array_ref = ref (fun v -> assert false)
 let enc_string_ref = ref (fun s -> assert false)
 let enc_string_ref = ref (fun s -> assert false)
 let make_ast_ref = ref (fun _ -> assert false)
 let make_ast_ref = ref (fun _ -> assert false)
 let make_complex_type_ref = ref (fun _ -> assert false)
 let make_complex_type_ref = ref (fun _ -> assert false)
+let encode_tvar_ref = ref (fun _ -> assert false)
 let get_ctx() = (!get_ctx_ref)()
 let get_ctx() = (!get_ctx_ref)()
 let enc_array (l:value list) : value = (!enc_array_ref) l
 let enc_array (l:value list) : value = (!enc_array_ref) l
 let dec_array (l:value) : value list = (!dec_array_ref) l
 let dec_array (l:value) : value list = (!dec_array_ref) l
@@ -217,6 +218,7 @@ 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 make_ast (e:texpr) : Ast.expr = (!make_ast_ref) e
 let enc_string (s:string) : value = (!enc_string_ref) s
 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 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 to_int f = Int32.of_float (mod_float f 2147483648.0)
 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 need_32_bits i = Int32.compare (Int32.logand (Int32.add i 0x40000000l) 0x80000000l) Int32.zero <> 0
@@ -2426,10 +2428,18 @@ let macro_lib =
 		"local_using", Fun0 (fun() ->
 		"local_using", Fun0 (fun() ->
 			enc_array (List.map encode_clref ((get_ctx()).curapi.get_local_using()))
 			enc_array (List.map encode_clref ((get_ctx()).curapi.get_local_using()))
 		);
 		);
-		"local_vars", Fun0 (fun() ->
+		"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 vars = (get_ctx()).curapi.get_local_vars() in
 			let h = Hashtbl.create 0 in
 			let h = Hashtbl.create 0 in
-			PMap.iter (fun n v -> Hashtbl.replace h (VString n) (encode_type v.v_type)) vars;
+			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
 			enc_hash h
 		);
 		);
 		"follow", Fun2 (fun v once ->
 		"follow", Fun2 (fun v once ->
@@ -4954,4 +4964,5 @@ encode_clref_ref := encode_clref;
 enc_string_ref := enc_string;
 enc_string_ref := enc_string;
 enc_hash_ref := enc_hash;
 enc_hash_ref := enc_hash;
 encode_texpr_ref := encode_texpr;
 encode_texpr_ref := encode_texpr;
-decode_texpr_ref := decode_texpr
+decode_texpr_ref := decode_texpr;
+encode_tvar_ref := encode_tvar;

+ 1 - 1
libs

@@ -1 +1 @@
-Subproject commit 3a4b14d06216b5fe3aef666acc5cc436ce76dd86
+Subproject commit 7c8941a5567ff0b705ffa2748795072bc9844d84

+ 1 - 1
main.ml

@@ -45,7 +45,7 @@ exception Abort
 exception Completion of string
 exception Completion of string
 
 
 
 
-let version = 3103
+let version = 3200
 let version_major = version / 1000
 let version_major = version / 1000
 let version_minor = (version mod 1000) / 100
 let version_minor = (version mod 1000) / 100
 let version_revision = (version mod 100)
 let version_revision = (version mod 100)

+ 8 - 3
matcher.ml

@@ -798,7 +798,7 @@ let rec is_explicit_null = function
 
 
 let rec all_ctors mctx t =
 let rec all_ctors mctx t =
 	let h = ref PMap.empty in
 	let h = ref PMap.empty in
-	(* if is_explicit_null t then h := PMap.add (CConst TNull) Ast.null_pos !h; *)
+	if is_explicit_null t then h := PMap.add (CConst TNull) Ast.null_pos !h;
 	match follow t with
 	match follow t with
 	| TAbstract({a_path = [],"Bool"},_) ->
 	| TAbstract({a_path = [],"Bool"},_) ->
 		h := PMap.add (CConst(TBool true)) Ast.null_pos !h;
 		h := PMap.add (CConst(TBool true)) Ast.null_pos !h;
@@ -1032,7 +1032,11 @@ let convert_switch mctx st cases loop =
 		| _ -> DTSwitch(e, List.map (fun (c,dt) -> convert_con ctx c, loop dt) cases, !def)
 		| _ -> DTSwitch(e, List.map (fun (c,dt) -> convert_con ctx c, loop dt) cases, !def)
 	in
 	in
 	match !null with
 	match !null with
-	| None -> dt
+	| None when is_explicit_null st.st_type ->
+		let econd = mk (TBinop(OpNotEq,e_st,mk (TConst TNull) (mk_mono()) p)) ctx.t.tbool p in
+		DTGuard(econd,dt,!def)
+	| None ->
+		dt
 	| Some dt_null ->
 	| Some dt_null ->
 		let econd = mk (TBinop(OpEq,e_st,mk (TConst TNull) (mk_mono()) p)) ctx.t.tbool p in
 		let econd = mk (TBinop(OpEq,e_st,mk (TConst TNull) (mk_mono()) p)) ctx.t.tbool p in
 		DTGuard(econd,dt_null,Some dt)
 		DTGuard(econd,dt_null,Some dt)
@@ -1097,7 +1101,8 @@ let transform_extractors eval cases p =
 		| [] ->
 		| [] ->
 			[]
 			[]
 	in
 	in
-	loop cases,!has_extractor
+	let cases = loop cases in
+	cases,!has_extractor
 
 
 let extractor_depth = ref 0
 let extractor_depth = ref 0
 
 

+ 16 - 8
optimizer.ml

@@ -774,11 +774,16 @@ let sanitize_expr com e =
 	in
 	in
 	match e.eexpr with
 	match e.eexpr with
 	| TConst TNull ->
 	| TConst TNull ->
-		if com.config.pf_static && not (is_nullable e.etype) then
-			(match follow e.etype with
-			| TMono _ -> () (* in these cases the null will cast to default value *)
-			| TFun _ -> () (* this is a bit a particular case, maybe flash-specific actually *)
-			| _ -> com.error ("On static platforms, null can't be used as basic type " ^ s_type (print_context()) e.etype) e.epos);
+		if com.config.pf_static && not (is_nullable e.etype) then begin
+			let rec loop t = match follow t with
+				| TMono _ -> () (* in these cases the null will cast to default value *)
+				| TFun _ -> () (* this is a bit a particular case, maybe flash-specific actually *)
+				(* TODO: this should use get_underlying_type, but we do not have access to Codegen here.  *)
+				| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> loop (apply_params a.a_types tl a.a_this)
+				| _ -> com.error ("On static platforms, null can't be used as basic type " ^ s_type (print_context()) e.etype) e.epos
+			in
+			loop e.etype
+		end;
 		e
 		e
 	| TBinop (op,e1,e2) ->
 	| TBinop (op,e1,e2) ->
 		let swap op1 op2 =
 		let swap op1 op2 =
@@ -1266,23 +1271,26 @@ let inline_constructors ctx e =
 			) ([],PMap.empty) assigns),el_init
 			) ([],PMap.empty) assigns),el_init
 		) vars in
 		) vars in
 		let el_b = ref [] in
 		let el_b = ref [] in
+		let append e = el_b := e :: !el_b in
 		let rec subst e =
 		let rec subst e =
 			match e.eexpr with
 			match e.eexpr with
 			| TBlock el ->
 			| TBlock el ->
 				let old = !el_b in
 				let old = !el_b in
 				el_b := [];
 				el_b := [];
-				List.iter (fun e -> el_b := (subst e) :: !el_b) el;
+				List.iter (fun e -> append (subst e)) el;
 				let n = !el_b in
 				let n = !el_b in
 				el_b := old;
 				el_b := old;
 				{e with eexpr = TBlock (List.rev n)}
 				{e with eexpr = TBlock (List.rev n)}
 			| TVar (v,Some e) when v.v_id < 0 ->
 			| TVar (v,Some e) when v.v_id < 0 ->
 				let (vars, _),el_init = PMap.find (-v.v_id) vfields in
 				let (vars, _),el_init = PMap.find (-v.v_id) vfields in
-				el_b := (List.rev_map subst el_init) @ !el_b;
+				List.iter (fun e ->
+					append (subst e)
+				) el_init;
 				let (v_first,e_first),vars = match vars with
 				let (v_first,e_first),vars = match vars with
 					| v :: vl -> v,vl
 					| v :: vl -> v,vl
 					| [] -> assert false
 					| [] -> assert false
 				in
 				in
-				List.iter (fun (v,e) -> el_b := (mk (TVar(v,Some (subst e))) ctx.t.tvoid e.epos) :: !el_b) (List.rev vars);
+				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
 				mk (TVar (v_first, Some (subst e_first))) ctx.t.tvoid e.epos
 			| TField ({ eexpr = TLocal v },FInstance (c,cf)) when v.v_id < 0 ->
 			| TField ({ eexpr = TLocal v },FInstance (c,cf)) when v.v_id < 0 ->
 				let (_, vars),el_init = PMap.find (-v.v_id) vfields in
 				let (_, vars),el_init = PMap.find (-v.v_id) vfields in

+ 3 - 3
std/Map.hx

@@ -150,15 +150,15 @@ abstract Map<K,V>(IMap<K,V> ) {
 	}
 	}
 
 
 	@:from static inline function fromStringMap<V>(map:StringMap<V>):Map< String, V > {
 	@:from static inline function fromStringMap<V>(map:StringMap<V>):Map< String, V > {
-		return map;
+		return cast map;
 	}
 	}
 
 
 	@:from static inline function fromIntMap<V>(map:IntMap<V>):Map< Int, V > {
 	@:from static inline function fromIntMap<V>(map:IntMap<V>):Map< Int, V > {
-		return map;
+		return cast map;
 	}
 	}
 
 
 	@:from static inline function fromObjectMap<K:{ }, V>(map:ObjectMap<K,V>):Map<K,V> {
 	@:from static inline function fromObjectMap<K:{ }, V>(map:ObjectMap<K,V>):Map<K,V> {
-		return map;
+		return cast map;
 	}
 	}
 }
 }
 
 

+ 16 - 11
std/UInt.hx

@@ -20,7 +20,7 @@
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
 
 
-#if (flash9 || flash9doc || cs || doc_gen)
+#if ((flash9 || flash9doc || cs) && !doc_gen)
 /**
 /**
 	The unsigned Int type is only defined for Flash9 and C#. It's currently
 	The unsigned Int type is only defined for Flash9 and C#. It's currently
 	handled the same as a normal Int.
 	handled the same as a normal Int.
@@ -31,8 +31,7 @@
 	The unsigned Int type is only defined for Flash9 and C#.
 	The unsigned Int type is only defined for Flash9 and C#.
 	Simulate it for other platforms.
 	Simulate it for other platforms.
 **/
 **/
-@:coreType
-abstract UInt from Int {
+abstract UInt(Int) from Int to Int {
 
 
 	@:op(A + B) private static inline function add(a:UInt, b:UInt):UInt {
 	@:op(A + B) private static inline function add(a:UInt, b:UInt):UInt {
 		return a.toInt() + b.toInt();
 		return a.toInt() + b.toInt();
@@ -130,11 +129,19 @@ abstract UInt from Int {
 		return a.toFloat() > b;
 		return a.toFloat() > b;
 	}
 	}
 
 
-	@:commutative @:op(A == B) private static inline function equalsFloat(a:UInt, b:Float):Bool {
+	@:commutative @:op(A == B) private static inline function equalsInt<T:Int>(a:UInt, b:T):Bool {
+		return a.toInt() == b;
+	}
+
+	@:commutative @:op(A != B) private static inline function notEqualsInt<T:Int>(a:UInt, b:T):Bool {
+		return a.toInt() != b;
+	}
+
+	@:commutative @:op(A == B) private static inline function equalsFloat<T:Float>(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:Float):Bool {
+    @:commutative @:op(A != B) private static inline function notEqualsFloat<T:Float>(a:UInt, b:T):Bool {
         return a.toFloat() != b;
         return a.toFloat() != b;
     }
     }
 
 
@@ -159,7 +166,6 @@ abstract UInt from Int {
 		return a.toFloat() <= b;
 		return a.toFloat() <= b;
 	}
 	}
 
 
-
 	@:op(A < B) private static inline function floatLt(a:Float, b:UInt):Bool {
 	@:op(A < B) private static inline function floatLt(a:Float, b:UInt):Bool {
 		return a < b.toFloat();
 		return a < b.toFloat();
 	}
 	}
@@ -201,6 +207,10 @@ abstract UInt from Int {
 		return Std.string(toFloat());
 		return Std.string(toFloat());
 	}
 	}
 
 
+	private inline function toInt():Int {
+		return this;
+	}
+
 	@:to private inline function toFloat():Float {
 	@:to private inline function toFloat():Float {
 		var int = toInt();
 		var int = toInt();
 		if (int < 0) {
 		if (int < 0) {
@@ -212,10 +222,5 @@ abstract UInt from Int {
 			return int + 0.0;
 			return int + 0.0;
 		}
 		}
 	}
 	}
-
-	@:to private inline function toInt():Int {
-		return cast this;
-	}
-
 }
 }
 #end
 #end

+ 4 - 0
std/cpp/NativeArray.hx

@@ -22,4 +22,8 @@ class NativeArray {
 	public static inline function memcmp<T>( inArrayA:Array<T>, inArrayB:Array<T>) : Int {
 	public static inline function memcmp<T>( inArrayA:Array<T>, inArrayB:Array<T>) : Int {
 		return untyped inArrayA.memcmp(inArrayB);
 		return untyped inArrayA.memcmp(inArrayB);
 	}
 	}
+
+	public static inline function setSize<T>( ioArray:Array<T>, inSize:Int) : Array<T> {
+		return untyped ioArray.__SetSizeExact(inSize);
+   }
 }
 }

+ 3 - 1
std/cpp/vm/Debugger.hx

@@ -140,6 +140,8 @@ class Debugger
      *          - threadNumber, the thread number of the event
      *          - threadNumber, the thread number of the event
      *          - event, one of THREAD_CREATED, THREAD_TERMINATED,
      *          - event, one of THREAD_CREATED, THREAD_TERMINATED,
      *            THREAD_STARTED, or THREAD_STOPPED
      *            THREAD_STARTED, or THREAD_STOPPED
+     *          - stackFrame, the stack frame number at which the thread is stopped,
+     *            undefined if event is not THREAD_STOPPED
      *          - className, the class name at which the thread is stopped,
      *          - className, the class name at which the thread is stopped,
      *            undefined if event is not THREAD_STOPPED
      *            undefined if event is not THREAD_STOPPED
      *          - functionName, the function name at which the thread is
      *          - functionName, the function name at which the thread is
@@ -150,7 +152,7 @@ class Debugger
      *            undefined if event is not THREAD_STOPPED
      *            undefined if event is not THREAD_STOPPED
      **/
      **/
     public static function setEventNotificationHandler(
     public static function setEventNotificationHandler(
-             handler : Int -> Int -> String -> String -> String -> Int -> Void)
+             handler : Int -> Int -> Int -> String -> String -> String -> Int -> Void)
     {
     {
         untyped __global__.__hxcpp_dbg_setEventNotificationHandler(handler);
         untyped __global__.__hxcpp_dbg_setEventNotificationHandler(handler);
     }
     }

+ 1 - 1
std/cpp/zip/Compress.hx

@@ -1,5 +1,5 @@
 package cpp.zip;
 package cpp.zip;
 
 
-#if (haxe_ver < 3.2)
+#if (haxe_ver < 3.4)
 typedef Compress = haxe.zip.Compress;
 typedef Compress = haxe.zip.Compress;
 #end
 #end

+ 1 - 1
std/cpp/zip/Flush.hx

@@ -1,5 +1,5 @@
 package cpp.zip;
 package cpp.zip;
 
 
-#if (haxe_ver < 3.2)
+#if (haxe_ver < 3.4)
 typedef Flush = haxe.zip.FlushMode;
 typedef Flush = haxe.zip.FlushMode;
 #end
 #end

+ 1 - 1
std/cpp/zip/Uncompress.hx

@@ -1,5 +1,5 @@
 package cpp.zip;
 package cpp.zip;
 
 
-#if (haxe_ver < 3.2)
+#if (haxe_ver < 3.4)
 typedef Uncompress = haxe.zip.Uncompress;
 typedef Uncompress = haxe.zip.Uncompress;
 #end
 #end

+ 1 - 1
std/flash/_std/EReg.hx

@@ -22,7 +22,7 @@
 @:coreApi class EReg {
 @:coreApi class EReg {
 
 
 	var r : flash.utils.RegExp;
 	var r : flash.utils.RegExp;
-	var result : {> Array<String>, index : Int, input : String };
+	var result : Dynamic;
 
 
 	public function new( r : String, opt : String ) : Void {
 	public function new( r : String, opt : String ) : Void {
 		this.r = new flash.utils.RegExp(r,opt);
 		this.r = new flash.utils.RegExp(r,opt);

+ 2 - 2
std/flash/_std/haxe/Json.hx

@@ -33,7 +33,7 @@ class Json {
 	}
 	}
 
 
 	#if (haxeJSON || !flash11) inline #end
 	#if (haxeJSON || !flash11) inline #end
-	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
-		return haxe.format.JsonPrinter.print(value, replacer);
+	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String {
+		return haxe.format.JsonPrinter.print(value, replacer, space);
 	}
 	}
 }
 }

+ 5 - 2
std/haxe/Json.hx

@@ -46,9 +46,12 @@ class Json {
 		If `replacer` is given and is not null, it is used to retrieve
 		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 two parameters,
 		the key and the value being encoded. Initial key value is an empty string.
 		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.
 	**/
 	**/
-	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
-		return haxe.format.JsonPrinter.print(value, replacer);
+	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space : String ) : String {
+		return haxe.format.JsonPrinter.print(value, replacer, space);
 	}
 	}
 
 
 }
 }

+ 28 - 10
std/haxe/ds/Vector.hx

@@ -21,6 +21,10 @@
  */
  */
 package haxe.ds;
 package haxe.ds;
 
 
+#if cpp
+using cpp.NativeArray;
+#end
+
 private typedef VectorData<T> = #if flash10
 private typedef VectorData<T> = #if flash10
 	flash.Vector<T>
 	flash.Vector<T>
 #elseif neko
 #elseif neko
@@ -80,7 +84,11 @@ abstract Vector<T>(VectorData<T>) {
 		unspecified.
 		unspecified.
 	**/
 	**/
 	@:arrayAccess public inline function get(index:Int):Null<T> {
 	@:arrayAccess public inline function get(index:Int):Null<T> {
+		#if cpp
+		return this.unsafeGet(index);
+		#else
 		return this[index];
 		return this[index];
+		#end
 	}
 	}
 
 
 	/**
 	/**
@@ -90,7 +98,11 @@ abstract Vector<T>(VectorData<T>) {
 		unspecified.
 		unspecified.
 	**/
 	**/
 	@:arrayAccess public inline function set(index:Int, val:T):T {
 	@:arrayAccess public inline function set(index:Int, val:T):T {
+		#if cpp
+		return this.unsafeSet(index,val);
+		#else
 		return this[index] = val;
 		return this[index] = val;
+		#end
 	}
 	}
 
 
 	/**
 	/**
@@ -119,7 +131,7 @@ abstract Vector<T>(VectorData<T>) {
 		The results are unspecified if `length` results in out-of-bounds access,
 		The results are unspecified if `length` results in out-of-bounds access,
 		or if `src` or `dest` are null
 		or if `src` or `dest` are null
 	**/
 	**/
-	public static #if (cs || java || neko) inline #end function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void
+	public static #if (cs || java || neko || cpp) inline #end function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void
 	{
 	{
 		#if neko
 		#if neko
 			untyped __dollar__ablit(dest,destPos,src,srcPos,len);
 			untyped __dollar__ablit(dest,destPos,src,srcPos,len);
@@ -127,6 +139,8 @@ abstract Vector<T>(VectorData<T>) {
 			java.lang.System.arraycopy(src, srcPos, dest, destPos, len);
 			java.lang.System.arraycopy(src, srcPos, dest, destPos, len);
 		#elseif cs
 		#elseif cs
 			cs.system.Array.Copy(cast src, srcPos,cast dest, destPos, len);
 			cs.system.Array.Copy(cast src, srcPos,cast dest, destPos, len);
+		#elseif cpp
+			dest.toData().blit(destPos,src.toData(), srcPos,len);
 		#else
 		#else
 			for (i in 0...len)
 			for (i in 0...len)
 			{
 			{
@@ -138,16 +152,20 @@ abstract Vector<T>(VectorData<T>) {
 	/**
 	/**
 		Creates a new Array, copy the content from the Vector to it, and returns it.
 		Creates a new Array, copy the content from the Vector to it, and returns it.
 	**/
 	**/
-	public #if flash inline #end function toArray():Array<T> {
-		var a = new Array();
-		var len = length;
-		#if (cpp || neko)
-		// prealloc good size
-		if( len > 0 ) a[len - 1] = get(0);
+	public #if (flash || cpp) inline #end function toArray():Array<T> {
+		#if cpp
+			return this.copy();
+		#else
+			var a = new Array();
+			var len = length;
+			#if (neko)
+			// prealloc good size
+			if( len > 0 ) a[len - 1] = get(0);
+			#end
+			for( i in 0...len )
+				a[i] = get(i);
+			return a;
 		#end
 		#end
-		for( i in 0...len )
-			a[i] = get(i);
-		return a;
 	}
 	}
 
 
 	/**
 	/**

+ 45 - 13
std/haxe/format/JsonPrinter.hx

@@ -2,17 +2,23 @@ package haxe.format;
 
 
 class JsonPrinter {
 class JsonPrinter {
 
 
-	static public function print(o:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic) : String {
-		var printer = new JsonPrinter(replacer);
+	static public function print(o:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String) : String {
+		var printer = new JsonPrinter(replacer, space);
 		printer.write("", o);
 		printer.write("", o);
 		return printer.buf.toString();
 		return printer.buf.toString();
 	}
 	}
 
 
 	var buf : #if flash9 flash.utils.ByteArray #else StringBuf #end;
 	var buf : #if flash9 flash.utils.ByteArray #else StringBuf #end;
 	var replacer : Dynamic -> Dynamic -> Dynamic;
 	var replacer : Dynamic -> Dynamic -> Dynamic;
-
-	function new(replacer:Dynamic -> Dynamic -> Dynamic) {
+	var indent:String;
+	var pretty:Bool;
+	var nind:Int;
+	
+	function new(replacer:Dynamic -> Dynamic -> Dynamic, space:String) {
 		this.replacer = replacer;
 		this.replacer = replacer;
+		this.indent = space;
+		this.pretty = space != null;
+		this.nind = 0;
 
 
 		#if flash9
 		#if flash9
 		buf = new flash.utils.ByteArray();
 		buf = new flash.utils.ByteArray();
@@ -22,6 +28,14 @@ class JsonPrinter {
 		buf = new StringBuf();
 		buf = new StringBuf();
 		#end
 		#end
 	}
 	}
+	
+	inline function ipad ():Void {
+		if (pretty) add(StringTools.lpad('', indent, nind * indent.length));
+	}
+	
+	inline function newl ():Void {
+		if (pretty) addChar('\n'.code);
+	}
 
 
 	function write(k:Dynamic, v:Dynamic) {
 	function write(k:Dynamic, v:Dynamic) {
 		if (replacer != null) v = replacer(k, v);
 		if (replacer != null) v = replacer(k, v);
@@ -42,13 +56,20 @@ class JsonPrinter {
 			else if( c == Array ) {
 			else if( c == Array ) {
 				var v : Array<Dynamic> = v;
 				var v : Array<Dynamic> = v;
 				addChar('['.code);
 				addChar('['.code);
+
 				var len = v.length;
 				var len = v.length;
-				if( len > 0 ) {
-					write(0, v[0]);
-					var i = 1;
-					while( i < len ) {
-						addChar(','.code);
-						write(i, v[i++]);
+				var last = len - 1;
+				for (i in 0...len)
+				{
+					if (i > 0) addChar(','.code) else nind++;
+					newl();
+					ipad();
+					write(i, v[i]);
+					if (i == last)
+					{
+						nind--;
+						newl();
+						ipad();
 					}
 					}
 				}
 				}
 				addChar(']'.code);
 				addChar(']'.code);
@@ -105,15 +126,26 @@ class JsonPrinter {
 	}
 	}
 
 
 	function fieldsString( v : Dynamic, fields : Array<String> ) {
 	function fieldsString( v : Dynamic, fields : Array<String> ) {
-		var first = true;
 		addChar('{'.code);
 		addChar('{'.code);
-		for( f in fields ) {
+		var len = fields.length;
+		var last = len - 1;
+		for( i in 0...len ) {
+			var f = fields[i];
 			var value = Reflect.field(v,f);
 			var value = Reflect.field(v,f);
 			if( Reflect.isFunction(value) ) continue;
 			if( Reflect.isFunction(value) ) continue;
-			if( first ) first = false else addChar(','.code);
+			if( i > 0 ) addChar(','.code) else nind++;
+			newl();
+			ipad();
 			quote(f);
 			quote(f);
 			addChar(':'.code);
 			addChar(':'.code);
+			if (pretty) addChar(' '.code);
 			write(f, value);
 			write(f, value);
+			if (i == last)
+			{
+				nind--;
+				newl();
+				ipad();
+			}
 		}
 		}
 		addChar('}'.code);
 		addChar('}'.code);
 	}
 	}

+ 11 - 1
std/haxe/macro/Context.hx

@@ -175,10 +175,20 @@ class Context {
 
 
 		Modifying the returned map has no effect on the compiler.
 		Modifying the returned map has no effect on the compiler.
 	**/
 	**/
+	@:deprecated("Use Context.getLocalTVars() instead")
 	public static function getLocalVars() : haxe.ds.StringMap<Type> {
 	public static function getLocalVars() : haxe.ds.StringMap<Type> {
-		return load("local_vars", 0)();
+		return load("local_vars", 1)(false);
 	}
 	}
 
 
+	/**
+		Similar to `getLocalVars`, but returns elements of type `TVar` instead
+		of `Type`.
+	**/
+	@:require(haxe_ver >= 3.102)
+	public static function getLocalTVars() : haxe.ds.StringMap<Type.TVar> {
+		return load("local_vars", 1)(true);
+	}
+	
 	/**
 	/**
 		Tells if compiler directive `s` has been set.
 		Tells if compiler directive `s` has been set.
 
 

+ 16 - 2
std/haxe/macro/Printer.hx

@@ -24,6 +24,7 @@ package haxe.macro;
 
 
 import haxe.macro.Expr;
 import haxe.macro.Expr;
 using Lambda;
 using Lambda;
+using StringTools;
 
 
 class Printer {
 class Printer {
 	var tabs:String;
 	var tabs:String;
@@ -69,9 +70,19 @@ class Printer {
 			printBinop(op)
 			printBinop(op)
 			+ "=";
 			+ "=";
 	}
 	}
+
+	function escapeString(s:String,delim:String) {
+		return delim + s.replace("\n","\\n").replace("\t","\\t").replace("'","\\'").replace('"',"\\\"") #if sys .replace("\x00","\\x00") #end + delim;
+	}
+
+	public function printFormatString(s:String) {
+		return escapeString(s,"'");
+	}
+
 	public function printString(s:String) {
 	public function printString(s:String) {
-		return '"' + s.split("\n").join("\\n").split("\t").join("\\t").split("'").join("\\'").split('"').join("\\\"") #if sys .split("\x00").join("\\x00") #end + '"';
+		return escapeString(s,'"');
 	}
 	}
+
 	public function printConstant(c:Constant) return switch(c) {
 	public function printConstant(c:Constant) return switch(c) {
 		case CString(s): printString(s);
 		case CString(s): printString(s);
 		case CIdent(s),
 		case CIdent(s),
@@ -150,6 +161,9 @@ class Printer {
 
 
 
 
 	public function printExpr(e:Expr) return e == null ? "#NULL" : switch(e.expr) {
 	public function printExpr(e:Expr) return e == null ? "#NULL" : switch(e.expr) {
+		#if macro
+		case EConst(CString(s)): haxe.macro.MacroStringTools.isFormatExpr(e) ? printFormatString(s) : printString(s);
+		#end
 		case EConst(c): printConstant(c);
 		case EConst(c): printConstant(c);
 		case EArray(e1, e2): '${printExpr(e1)}[${printExpr(e2)}]';
 		case EArray(e1, e2): '${printExpr(e1)}[${printExpr(e2)}]';
 		case EBinop(op, e1, e2): '${printExpr(e1)} ${printBinop(op)} ${printExpr(e2)}';
 		case EBinop(op, e1, e2): '${printExpr(e1)} ${printBinop(op)} ${printExpr(e2)}';
@@ -292,4 +306,4 @@ class Printer {
 	}
 	}
 
 
 	function opt<T>(v:T, f:T->String, prefix = "") return v == null ? "" : (prefix + f(v));
 	function opt<T>(v:T, f:T->String, prefix = "") return v == null ? "" : (prefix + f(v));
-}
+}

+ 2 - 2
std/js/_std/haxe/Json.hx

@@ -33,8 +33,8 @@ class Json {
 	}
 	}
 
 
 	#if haxeJSON inline #end
 	#if haxeJSON inline #end
-	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
-		return haxe.format.JsonPrinter.print(value, replacer);
+	public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String {
+		return haxe.format.JsonPrinter.print(value, replacer, space);
 	}
 	}
 
 
 	#if (!haxeJSON && old_browser)
 	#if (!haxeJSON && old_browser)

+ 1 - 1
std/neko/zip/Compress.hx

@@ -1,5 +1,5 @@
 package neko.zip;
 package neko.zip;
 
 
-#if (haxe_ver < 3.2)
+#if (haxe_ver < 3.4)
 typedef Compress = haxe.zip.Compress;
 typedef Compress = haxe.zip.Compress;
 #end
 #end

+ 1 - 1
std/neko/zip/Flush.hx

@@ -1,5 +1,5 @@
 package neko.zip;
 package neko.zip;
 
 
-#if (haxe_ver < 3.2)
+#if (haxe_ver < 3.4)
 typedef Flush = haxe.zip.FlushMode;
 typedef Flush = haxe.zip.FlushMode;
 #end
 #end

+ 1 - 1
std/neko/zip/Uncompress.hx

@@ -1,5 +1,5 @@
 package neko.zip;
 package neko.zip;
 
 
-#if (haxe_ver < 3.2)
+#if (haxe_ver < 3.4)
 typedef Uncompress = haxe.zip.Uncompress;
 typedef Uncompress = haxe.zip.Uncompress;
 #end
 #end

+ 6 - 6
std/php/_std/haxe/Json.hx

@@ -32,11 +32,11 @@ class Json {
 		#end
 		#end
 	}
 	}
 
 
-	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic ) : String {
+	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String {
 		#if !haxeJSON
 		#if !haxeJSON
-		return phpJsonEncode(value, replacer);
+		return phpJsonEncode(value, replacer, space);
 		#else
 		#else
-		return haxe.format.JsonPrinter.print(value, replacer);
+		return haxe.format.JsonPrinter.print(value, replacer, space);
 		#end
 		#end
 	}
 	}
 
 
@@ -59,9 +59,9 @@ class Json {
 			return val;
 			return val;
 	}
 	}
 
 
-	static function phpJsonEncode(val:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic):String {
-		if(null != replacer)
-			return haxe.format.JsonPrinter.print(val, replacer);
+	static function phpJsonEncode(val:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String):String {
+		if(null != replacer || null != space)
+			return haxe.format.JsonPrinter.print(val, replacer, space);
 		var json = untyped __call__("json_encode", convertBeforeEncode(val));
 		var json = untyped __call__("json_encode", convertBeforeEncode(val));
 		if (untyped __physeq__(json, false))
 		if (untyped __physeq__(json, false))
 			return throw "invalid json";
 			return throw "invalid json";

+ 93 - 42
tests/RunTravis.hx

@@ -41,6 +41,27 @@ class RunTravis {
 		Sys.exit(exitCode);
 		Sys.exit(exitCode);
 	}
 	}
 
 
+	static function haxelibInstallGit(account:String, repository:String, ?branch:String, ?srcPath:String, useRetry:Bool = false, ?altName:String):Void {
+		var name:String = (altName == null) ? repository : altName;
+		var args:Array<String> = ["git", name, 'https://github.com/$account/$repository'];
+		if (branch != null) {
+			args.push(branch);
+		}
+		if (srcPath != null) {
+			args.push(srcPath);
+		}
+
+		runCommand("haxelib", args, useRetry);
+	}
+
+	static function haxelibInstall(library:String):Void {
+		runCommand("haxelib", ["install", library]);
+	}
+
+	static function haxelibRun(args:Array<String>, useRetry:Bool = false):Void {
+		runCommand("haxelib", ["run"].concat(args), useRetry);
+	}
+
 	static function getHaxelibPath(libName:String) {
 	static function getHaxelibPath(libName:String) {
 		var proc = new sys.io.Process("haxelib", ["path", libName]);
 		var proc = new sys.io.Process("haxelib", ["path", libName]);
 		var result;
 		var result;
@@ -178,19 +199,35 @@ class RunTravis {
 		runCommand("sudo", ["apt-get", "install", "gcc-multilib", "g++-multilib", "-y"], true);
 		runCommand("sudo", ["apt-get", "install", "gcc-multilib", "g++-multilib", "-y"], true);
 
 
 		//install and build hxcpp
 		//install and build hxcpp
-		runCommand("haxelib", ["git", "hxcpp", "https://github.com/HaxeFoundation/hxcpp.git"], true);
+		haxelibInstallGit("HaxeFoundation", "hxcpp", true);
 		Sys.setCwd(Sys.getEnv("HOME") + "/haxelib/hxcpp/git/project/");
 		Sys.setCwd(Sys.getEnv("HOME") + "/haxelib/hxcpp/git/project/");
 		runCommand("neko", ["build.n"]);
 		runCommand("neko", ["build.n"]);
 		Sys.setCwd(unitDir);
 		Sys.setCwd(unitDir);
 	}
 	}
 
 
 	static function getJavaDependencies() {
 	static function getJavaDependencies() {
-		runCommand("haxelib", ["git", "hxjava", "https://github.com/HaxeFoundation/hxjava.git"], true);
+		haxelibInstallGit("HaxeFoundation", "hxjava", true);
 	}
 	}
 
 
 	static function getCsDependencies() {
 	static function getCsDependencies() {
 		runCommand("sudo", ["apt-get", "install", "mono-devel", "mono-mcs", "-y"], true);
 		runCommand("sudo", ["apt-get", "install", "mono-devel", "mono-mcs", "-y"], true);
-		runCommand("haxelib", ["git", "hxcs", "https://github.com/HaxeFoundation/hxcs.git"], true);
+		haxelibInstallGit("HaxeFoundation", "hxcs", true);
+	}
+
+	static function getOpenFLDependencies(unitDir:String) {
+		getCppDependencies(unitDir);
+
+		haxelibInstallGit("HaxeFoundation", "format");
+		haxelibInstallGit("haxenme", "nme");
+		haxelibInstallGit("haxenme", "nme-dev");
+		haxelibInstallGit("openfl", "svg");
+		haxelibInstallGit("openfl", "lime");
+		haxelibInstallGit("openfl", "lime-tools");
+		haxelibInstallGit("openfl", "openfl-native");
+		haxelibInstallGit("openfl", "openfl");
+
+		haxelibRun(["openfl", "rebuild", "linux"]);
+		haxelibRun(["openfl", "rebuild", "tools"]);
 	}
 	}
 
 
 	static function getPythonDependencies() {
 	static function getPythonDependencies() {
@@ -205,24 +242,24 @@ class RunTravis {
 
 
 		Sys.setCwd(unitDir);
 		Sys.setCwd(unitDir);
 		switch (Sys.getEnv("TARGET")) {
 		switch (Sys.getEnv("TARGET")) {
-			case "macro", null:
+			case "macro", "bytecode", null:
 				runCommand("haxe", ["compile-macro.hxml"]);
 				runCommand("haxe", ["compile-macro.hxml"]);
 
 
 				//generate documentation
 				//generate documentation
-				runCommand("haxelib", ["git", "hxparse", "https://github.com/Simn/hxparse", "development", "src"], true);
-				runCommand("haxelib", ["git", "hxtemplo", "https://github.com/Simn/hxtemplo", "master", "src"], true);
-				runCommand("haxelib", ["git", "hxargs", "https://github.com/Simn/hxargs.git"], true);
-				runCommand("haxelib", ["git", "markdown", "https://github.com/dpeek/haxe-markdown.git", "master", "src"], true);
+				haxelibInstallGit("Simn", "hxparse", "development", "src", true);
+				haxelibInstallGit("Simn", "hxtemplo", "master", "src", true);
+				haxelibInstallGit("Simn", "hxargs", true);
+				haxelibInstallGit("dpeek", "haxe-markdown", "master", "src", true, "markdown");
 
 
-				runCommand("haxelib", ["git", "hxcpp", "https://github.com/HaxeFoundation/hxcpp.git"], true);
-				runCommand("haxelib", ["git", "hxjava", "https://github.com/HaxeFoundation/hxjava.git"], true);
-				runCommand("haxelib", ["git", "hxcs", "https://github.com/HaxeFoundation/hxcs.git"], true);
+				haxelibInstallGit("HaxeFoundation", "hxcpp", true);
+				haxelibInstallGit("HaxeFoundation", "hxjava", true);
+				haxelibInstallGit("HaxeFoundation", "hxcs", true);
 
 
-				runCommand("haxelib", ["git", "dox", "https://github.com/dpeek/dox.git"], true);
+				haxelibInstallGit("dpeek", "dox", true);
 				Sys.setCwd(Sys.getEnv("HOME") + "/haxelib/dox/git/");
 				Sys.setCwd(Sys.getEnv("HOME") + "/haxelib/dox/git/");
 				runCommand("haxe", ["run.hxml"]);
 				runCommand("haxe", ["run.hxml"]);
 				runCommand("haxe", ["gen.hxml"]);
 				runCommand("haxe", ["gen.hxml"]);
-				runCommand("haxelib", ["run", "dox", "-o", "bin/api.zip", "-i", "bin/xml"]);
+				haxelibRun(["dox", "-o", "bin/api.zip", "-i", "bin/xml"]);
 			case "neko":
 			case "neko":
 				runCommand("haxe", ["compile-neko.hxml"]);
 				runCommand("haxe", ["compile-neko.hxml"]);
 				runCommand("neko", ["unit.n"]);
 				runCommand("neko", ["unit.n"]);
@@ -251,7 +288,7 @@ class RunTravis {
 					//https://saucelabs.com/opensource/travis
 					//https://saucelabs.com/opensource/travis
 					runCommand("npm", ["install", "wd"], true);
 					runCommand("npm", ["install", "wd"], true);
 					runCommand("curl", ["https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh", "-L", "|", "bash"], true);
 					runCommand("curl", ["https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh", "-L", "|", "bash"], true);
-					runCommand("haxelib", ["git", "nodejs", "https://github.com/dionjwa/nodejs-std.git", "master", "src"], true);
+					haxelibInstallGit("dionjwa", "nodejs-std", "master", "src", true, "nodejs");
 					runCommand("haxe", ["compile-saucelabs-runner.hxml"]);
 					runCommand("haxe", ["compile-saucelabs-runner.hxml"]);
 					runCommand("nekotools", ["server", "&"]);
 					runCommand("nekotools", ["server", "&"]);
 					runCommand("node", ["RunSauceLabs.js"]);
 					runCommand("node", ["RunSauceLabs.js"]);
@@ -296,23 +333,20 @@ class RunTravis {
 
 
 				runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"]);
 				runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"]);
 				runFlash("unit9_as3.swf");
 				runFlash("unit9_as3.swf");
+			case "neko-sys":
+				Sys.setCwd("../sys");
+				runCommand("haxe", ["compile-neko.hxml"]);
+				Sys.setCwd("bin/neko");
+				runCommand("neko", ["sys.n"]);
 			case "openfl-samples":
 			case "openfl-samples":
-				getCppDependencies(unitDir);
-				runCommand("haxelib", ["git", "hxlibc", "https://github.com/openfl/hxlibc"]);
-				runCommand("haxelib", ["git", "actuate", "https://github.com/jgranick/actuate"]);
-				runCommand("haxelib", ["git", "box2d", "https://github.com/jgranick/box2d"]);
-				runCommand("haxelib", ["git", "swf", "https://github.com/openfl/swf"]);
-				runCommand("haxelib", ["git", "layout", "https://github.com/jgranick/layout"]);
-				runCommand("haxelib", ["git", "format", "https://github.com/HaxeFoundation/format"]);
-				runCommand("haxelib", ["git", "svg", "https://github.com/openfl/svg"]);
-				runCommand("haxelib", ["git", "lime", "https://github.com/openfl/lime"]);
-				runCommand("haxelib", ["git", "lime-build", "https://github.com/openfl/lime-build"]);
-				runCommand("haxelib", ["git", "lime-tools", "https://github.com/openfl/lime-tools"]);
-				runCommand("haxelib", ["git", "openfl-native", "https://github.com/openfl/openfl-native"]);
-				runCommand("haxelib", ["git", "openfl", "https://github.com/openfl/openfl"]);
-				runCommand("haxelib", ["git", "openfl-samples", "https://github.com/Simn/openfl-samples"]);
-				runCommand("haxelib", ["run", "openfl", "rebuild", "linux"]);
-				runCommand("haxelib", ["run", "openfl", "rebuild", "tools"]);
+				getOpenFLDependencies(unitDir);
+
+				haxelibInstallGit("jgranick", "actuate");
+				haxelibInstallGit("jgranick", "box2d");
+				haxelibInstallGit("jgranick", "layout");
+				haxelibInstallGit("openfl", "swf");
+				haxelibInstallGit("openfl", "openfl-samples");
+
 				var path = getHaxelibPath("openfl-samples");
 				var path = getHaxelibPath("openfl-samples");
 				var old = Sys.getEnv("pwd");
 				var old = Sys.getEnv("pwd");
 				Sys.putEnv("pwd", path);
 				Sys.putEnv("pwd", path);
@@ -321,10 +355,9 @@ class RunTravis {
 					Sys.putEnv("pwd", old);
 					Sys.putEnv("pwd", old);
 				}
 				}
 			case "polygonal-ds":
 			case "polygonal-ds":
-				getPythonDependencies();
-				runCommand("haxelib", ["git", "polygonal-ds", "https://github.com/Simn/ds", "python-support"]);
-				runCommand("haxelib", ["git", "polygonal-core", "https://github.com/polygonal/core", "master", "src"]);
-				runCommand("haxelib", ["git", "polygonal-printf", "https://github.com/polygonal/printf", "master", "src"]);
+				haxelibInstallGit("Simn", "ds", "python-support", null, false, "polygonal-ds");
+				haxelibInstallGit("polygonal", "core", "master", "src", false, "polygonal-core");
+				haxelibInstallGit("polygonal", "printf", "master", "src", false, "polygonal-printf");
 				changeDirectory(getHaxelibPath("polygonal-ds"));
 				changeDirectory(getHaxelibPath("polygonal-ds"));
 				runCommand("haxe", ["build.hxml"]);
 				runCommand("haxe", ["build.hxml"]);
 				runCommand("node", ["unit.js"]);
 				runCommand("node", ["unit.js"]);
@@ -336,8 +369,8 @@ class RunTravis {
 				getJavaDependencies();
 				getJavaDependencies();
 				getPhpDependencies();
 				getPhpDependencies();
 				getCppDependencies(unitDir);
 				getCppDependencies(unitDir);
-				runCommand("haxelib", ["git", "hxparse", "https://github.com/Simn/hxparse", "development", "src"]);
-				runCommand("haxelib", ["git", "hxtemplo", "https://github.com/Simn/hxtemplo"]);
+				haxelibInstallGit("Simn", "hxparse", "development", "src");
+				haxelibInstallGit("Simn", "hxtemplo");
 
 
 				changeDirectory(getHaxelibPath("hxtemplo"));
 				changeDirectory(getHaxelibPath("hxtemplo"));
 				runCommand("haxe", ["build.hxml"]);
 				runCommand("haxe", ["build.hxml"]);
@@ -348,15 +381,33 @@ class RunTravis {
 				runCommand("php", ["bin/php/index.php"]);
 				runCommand("php", ["bin/php/index.php"]);
 				runCommand("./bin/cpp/Test", []);
 				runCommand("./bin/cpp/Test", []);
 			case "munit":
 			case "munit":
-				runCommand("haxelib", ["git", "mconsole", "https://github.com/massiveinteractive/mconsole", "master", "src"]);
-				runCommand("haxelib", ["git", "mcover", "https://github.com/massiveinteractive/MassiveCover", "master", "src"]);
-				runCommand("haxelib", ["git", "mlib", "https://github.com/massiveinteractive/MassiveLib", "master", "src"]);
-				runCommand("haxelib", ["git", "munit", "https://github.com/massiveinteractive/MassiveUnit", "master", "src"]);
+				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");
 				changeDirectory(haxe.io.Path.join([getHaxelibPath("munit"), "..", "tool"]));
 				changeDirectory(haxe.io.Path.join([getHaxelibPath("munit"), "..", "tool"]));
 				runCommand("haxe", ["build.hxml"]);
 				runCommand("haxe", ["build.hxml"]);
-				runCommand("haxelib", ["run", "munit", "test", "-result-exit-code", "-neko"]);
+				haxelibRun(["munit", "test", "-result-exit-code", "-neko"]);
 				changeDirectory("../");
 				changeDirectory("../");
-				runCommand("haxelib", ["run", "munit", "test", "-result-exit-code", "-neko"]);
+				haxelibRun(["munit", "test", "-result-exit-code", "-neko"]);
+			case "flixel-demos":
+				getOpenFLDependencies(unitDir);
+
+				haxelibInstall("systools");
+				haxelibInstall("spinehx");
+				haxelibInstall("nape");
+				haxelibInstall("task");
+
+				haxelibInstallGit("larsiusprime", "firetongue");
+
+				haxelibInstallGit("HaxeFlixel", "flixel");
+				haxelibInstallGit("HaxeFlixel", "flixel-addons");
+				haxelibInstallGit("HaxeFlixel", "flixel-ui");
+				haxelibInstallGit("HaxeFlixel", "flixel-demos");
+				haxelibInstallGit("HaxeFlixel", "flixel-tools");
+
+				haxelibRun(["flixel-tools", "testdemos", "-flash"]);
+				haxelibRun(["flixel-tools", "testdemos", "-neko"]);
 			case target:
 			case target:
 				throw "unknown target: " + target;
 				throw "unknown target: " + target;
 		}
 		}

+ 3 - 0
tests/sys/compile-each.hxml

@@ -0,0 +1,3 @@
+-debug
+-cp src
+-main Main

+ 2 - 0
tests/sys/compile-neko.hxml

@@ -0,0 +1,2 @@
+compile-each.hxml
+-neko bin/neko/sys.n

+ 1 - 0
tests/sys/compile.hxml

@@ -0,0 +1 @@
+compile-neko.hxml

+ 0 - 8
tests/sys/run.hxml

@@ -1,8 +0,0 @@
--cp src
--main Main
-
---each
--neko bin/sys.n
-
---next
--python bin/sys.py

+ 3 - 1
tests/sys/src/Main.hx

@@ -2,6 +2,8 @@ class Main {
 	static public function main() {
 	static public function main() {
 		var runner = new haxe.unit.TestRunner();
 		var runner = new haxe.unit.TestRunner();
 		runner.add(new TestSys());
 		runner.add(new TestSys());
-		runner.run();
+		runner.add(new io.TestFileInput());
+		var code = runner.run() ? 0 : 1;
+		Sys.exit(code);
 	}
 	}
 }
 }

+ 218 - 0
tests/sys/src/io/TestFileInput.hx

@@ -0,0 +1,218 @@
+package io;
+
+import sys.io.FileInput;
+import sys.FileSystem;
+import sys.io.File;
+import sys.io.FileSeek;
+
+/**
+ * Class TestFileInput
+ *
+ * @author        Maximilian Ruta <[email protected]>
+ */
+class TestFileInput extends haxe.unit.TestCase {
+
+	private var path : String;
+
+	public function new() {
+		super();
+		path = 'testcase-test-file';
+	}
+
+	override public function setup() {
+		File.saveContent(path, "test\n1234");
+	}
+
+	override public function tearDown() {
+		FileSystem.deleteFile(path);
+	}
+
+	public function testRead() {
+		var file : FileInput = File.read(path, false);
+		assertEquals(0, file.tell());
+		assertEquals(116, file.readByte());
+		assertEquals(1, file.tell());
+		assertEquals(101, file.readByte());
+		assertEquals(2, file.tell());
+		assertEquals(115, file.readByte());
+		assertEquals(3, file.tell());
+		assertEquals(116, file.readByte());
+		assertEquals(4, file.tell());
+		file.close();
+	}
+
+	public function testSeekBeginCur() {
+		var file : FileInput = File.read(path, false);
+		assertEquals(116, file.readByte());
+		assertEquals(101, file.readByte());
+		assertEquals(115, file.readByte());
+		assertEquals(116, file.readByte());
+
+		file.seek(-4, FileSeek.SeekCur);
+		assertEquals(0, file.tell());
+		assertEquals(116, file.readByte());
+		assertEquals(1, file.tell());
+		file.close();
+	}
+
+	public function testSeekBeginEnd() {
+		var file : FileInput = File.read(path, false);
+		assertEquals(116, file.readByte());
+		assertEquals(101, file.readByte());
+		assertEquals(115, file.readByte());
+		assertEquals(116, file.readByte());
+
+		file.seek(-9, FileSeek.SeekEnd);
+		assertEquals(0, file.tell());
+		assertEquals(116, file.readByte());
+		assertEquals(1, file.tell());
+		file.close();
+	}
+
+	public function testSeekBegin() {
+		var file : FileInput = File.read(path, false);
+		assertEquals(116, file.readByte());
+		assertEquals(101, file.readByte());
+		assertEquals(115, file.readByte());
+		assertEquals(116, file.readByte());
+
+		file.seek(0, FileSeek.SeekBegin);
+		assertEquals(0, file.tell());
+		assertEquals(116, file.readByte());
+		assertEquals(1, file.tell());
+		file.close();
+	}
+
+	public function testSeekPosBegin() {
+		var file : FileInput = File.read(path, false);
+		assertEquals(116, file.readByte());
+		assertEquals(101, file.readByte());
+		assertEquals(115, file.readByte());
+		assertEquals(116, file.readByte());
+
+		file.seek(1, FileSeek.SeekBegin);
+		assertEquals(1, file.tell());
+		assertEquals(101, file.readByte());
+		assertEquals(2, file.tell());
+		file.close();
+	}
+
+	public function testSeekPosBeginMulti() {
+		var file : FileInput = File.read(path, false);
+		assertEquals(116, file.readByte());
+		assertEquals(101, file.readByte());
+		assertEquals(115, file.readByte());
+		assertEquals(116, file.readByte());
+
+		file.seek(1, FileSeek.SeekBegin);
+		assertEquals(1, file.tell());
+		assertEquals(101, file.readByte());
+		assertEquals(2, file.tell());
+		file.seek(3, FileSeek.SeekBegin);
+		assertEquals(3, file.tell());
+		assertEquals(116, file.readByte());
+		assertEquals(4, file.tell());
+		file.close();
+	}
+
+	public function testSeekEnd() {
+		var file : FileInput = File.read(path, false);
+		assertEquals(116, file.readByte());
+		assertEquals(101, file.readByte());
+		assertEquals(115, file.readByte());
+		assertEquals(116, file.readByte());
+
+		file.seek(-1, FileSeek.SeekEnd);
+		assertEquals(8, file.tell());
+		assertEquals(52, file.readByte());
+		assertEquals(9, file.tell());
+		file.close();
+	}
+
+	public function testSeekEofLast() {
+		var file : FileInput = File.read(path, false);
+		assertEquals(116, file.readByte());
+		assertEquals(101, file.readByte());
+		assertEquals(115, file.readByte());
+		assertEquals(116, file.readByte());
+
+		file.seek(0, FileSeek.SeekEnd);
+		assertEquals(9, file.tell());
+		assertFalse(file.eof());
+		try {
+			file.readByte();
+			assertTrue(false);
+		} catch(e : haxe.io.Eof) {
+			assertTrue(true);
+		}
+		assertTrue(file.eof());
+		file.close();
+	}
+
+	public function testSeekEof() {
+		var file : FileInput = File.read(path, false);
+		assertEquals(116, file.readByte());
+		assertEquals(101, file.readByte());
+		assertEquals(115, file.readByte());
+		assertEquals(116, file.readByte());
+
+		file.seek(0, FileSeek.SeekEnd);
+		assertEquals(9, file.tell());
+		assertFalse(file.eof());
+		try {
+			file.readByte();
+			assertTrue(false);
+		} catch(e : haxe.io.Eof) {
+			assertTrue(true);
+		}
+		assertTrue(file.eof());
+		assertEquals(9, file.tell());
+		file.seek(-1, FileSeek.SeekCur);
+		assertEquals(8, file.tell());
+		assertEquals(52, file.readByte());
+		assertEquals(9, file.tell());
+		assertFalse(file.eof());
+		try {
+			file.readByte();
+			assertTrue(false);
+		} catch(e : haxe.io.Eof) {
+			assertTrue(true);
+		}
+		assertTrue(file.eof());
+		assertEquals(9, file.tell());
+		try {
+			file.readByte();
+			assertTrue(false);
+		} catch(e : haxe.io.Eof) {
+			assertTrue(true);
+		}
+
+		file.seek(5, FileSeek.SeekEnd);
+		assertFalse(file.eof());
+		try {
+			file.readByte();
+			assertTrue(false);
+		} catch(e : haxe.io.Eof) {
+			assertTrue(true);
+		}
+		assertTrue(file.eof());
+		file.seek(1, FileSeek.SeekEnd);
+		assertFalse(file.eof());
+		try {
+			file.readByte();
+			assertTrue(false);
+		} catch(e : haxe.io.Eof) {
+			assertTrue(true);
+		}
+		assertTrue(file.eof());
+		try {
+			file.readByte();
+			assertTrue(false);
+		} catch(e : haxe.io.Eof) {
+			assertTrue(true);
+		}
+		file.close();
+	}
+
+}
+

+ 1 - 1
tests/sys/testsys.hxproj

@@ -39,7 +39,7 @@
     <hidden path="obj" />
     <hidden path="obj" />
   </hiddenPaths>
   </hiddenPaths>
   <!-- Executed before build -->
   <!-- Executed before build -->
-  <preBuildCommand>haxe run.hxml</preBuildCommand>
+  <preBuildCommand>haxe compile.hxml</preBuildCommand>
   <!-- Executed after build -->
   <!-- Executed after build -->
   <postBuildCommand alwaysRun="False" />
   <postBuildCommand alwaysRun="False" />
   <!-- Other project options -->
   <!-- Other project options -->

+ 23 - 0
tests/unit/issues/Issue2580.hx

@@ -0,0 +1,23 @@
+package unit.issues;
+
+private enum T {
+    T1(x:Null<T>);
+    T2(x:Int);
+}
+
+class Issue2580 extends Test {
+	function test() {
+		function match(t) {
+			return switch (t) {
+				case T1(T1(_)): 0;
+				case T1(T2(_)): 1;
+				case T1(_): 2;
+				case T2(_): 3;
+			}
+		}
+		eq(0, match(T1(T1(null))));
+		eq(1, match(T1(T2(1))));
+		eq(2, match(T1(null)));
+		eq(3, match(T2(2)));
+	}
+}

+ 0 - 0
tests/unit/issues/Issue2750.hx.disabled → tests/unit/issues/Issue2750.hx


+ 25 - 0
tests/unit/issues/Issue2786.hx

@@ -0,0 +1,25 @@
+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;
+}
+
+@: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;
+}
+
+class Issue2786 extends Test {
+	function test() {
+		var a:E = A | B;
+		eq(3, a);
+
+		t(unit.TestType.typeError((A | B : E2)));
+	}
+}

+ 33 - 0
tests/unit/issues/Issue2828.hx

@@ -0,0 +1,33 @@
+package unit.issues;
+
+class Issue2828 extends unit.Test
+{
+	public function test()
+	{
+		var u:T1<Dynamic> = new U1();
+		u.foo(1,1);
+		t(u.call());
+	}
+}
+
+private interface T1<X>
+{
+  public function foo <A>(a:X, c:A):Void;
+	public function call():Bool;
+}
+
+private class U1 implements T1<Dynamic>
+{
+  public function new () {}
+	public var didCall:Bool = false;
+
+	public function call()
+	{
+		return didCall;
+	}
+
+  public function foo <A>(a:Dynamic, c:A):Void
+	{
+		didCall = true;
+	}
+}

+ 37 - 0
tests/unit/issues/Issue2835.hx

@@ -0,0 +1,37 @@
+package unit.issues;
+
+class Issue2835 extends unit.Test
+{
+	private function test()
+	{
+		var t = new Test(42);
+		eq(42,t.get());
+		t.fromFloat(12);
+		eq(12,t.get());
+		eq(12.0,t.toFloat());
+	}
+}
+
+private class Test<T:(Float)>
+{
+	public var value:T;
+	public function new(value)
+	{
+		this.value = value;
+	}
+
+	public function toFloat():Float
+	{
+		return value;
+	}
+
+	public function fromFloat(v:Float)
+	{
+		this.value = cast v;
+	}
+
+	public function get():T
+	{
+		return value;
+	}
+}

+ 12 - 0
tests/unit/issues/Issue2871.hx

@@ -0,0 +1,12 @@
+package unit.issues;
+
+class Issue2871 extends Test {
+    function call(myUInt:Null<UInt> = null):Int {
+        return myUInt == null ? 0 : myUInt;
+    }
+
+	function test() {
+		eq(0, call(null));
+		eq(1, call((1:UInt)));
+	}
+}

+ 44 - 0
tests/unit/issues/Issue2874.hx

@@ -0,0 +1,44 @@
+package unit.issues;
+
+class Issue2874 extends unit.Test
+{
+	private function test()
+	{
+		var a = new Arr(["1","2"]);
+		var a2 = a.map(function(v) return Std.parseInt(v));
+		eq(1,a2[0]);
+		eq(2,a2[1]);
+		// var a3:Arr<Int> = a.map(function(v) return Std.parseInt(v));
+		// eq(1,a3[0]);
+		// eq(2,a3[1]);
+	}
+
+	private function testArray()
+	{
+		var a = ["1","2"];
+		var a2 = a.map(function(v) return Std.parseInt(v));
+		eq(1,a2[0]);
+		eq(2,a2[1]);
+		// var a3:Array<Int> = a.map(function(v) return Std.parseInt(v));
+		// eq(1,a3[0]);
+		// eq(2,a3[1]);
+	}
+}
+
+@:arrayAccess abstract Arr<T>(Array<T>)
+{
+	@:extern inline public function new(a)
+	{
+		this = a;
+	}
+
+	@:extern inline public function map<X>(fn:T->X):Arr<X>
+	{
+		var arr2 = [];
+		for (v in this)
+		{
+			arr2.push(fn(v));
+		}
+		return new Arr(arr2);
+	}
+}

+ 9 - 0
tests/unit/issues/Issue2881.hx

@@ -0,0 +1,9 @@
+package unit.issues;
+
+private abstract Callback<T>(T->Void) from (T->Void) {}
+
+class Issue2881 extends Test {
+	function test() {
+		var cb:Callback<Int> = null;
+	}
+}

+ 10 - 0
tests/unit/issues/Issue2900.hx

@@ -0,0 +1,10 @@
+package unit.issues;
+
+class Issue2900 extends Test {
+	function test() {
+		var objs:Iterable<Int> = [10, 20];
+		var fns = [for (obj in objs) function() return obj];
+		eq(10, fns[0]());
+		eq(20, fns[1]());
+	}
+}

+ 28 - 0
tests/unit/issues/Issue2907.hx

@@ -0,0 +1,28 @@
+package unit.issues;
+
+private class MyTestClass {
+	public function new() { }
+}
+
+class Issue2907 extends Test {
+
+	@:generic function catchGeneric<T>(t:T) {
+		try {
+			throw "foo";
+		} catch(e:T) {
+			return e;
+		} catch(e:Dynamic) {
+			return null;
+		}
+		return null;
+	}
+
+	function test<T>() {
+		t(unit.TestType.typeError(
+			try { }
+			catch(e:T) { }
+		));
+		eq("foo", catchGeneric("foo"));
+		eq(null, catchGeneric(new MyTestClass()));
+	}
+}

+ 1 - 0
typeload.ml

@@ -419,6 +419,7 @@ and load_complex_type ctx p t =
 				| TInst ({cl_kind = KTypeParameter _},_) ->
 				| TInst ({cl_kind = KTypeParameter _},_) ->
 					error "Cannot structurally extend type parameters" p
 					error "Cannot structurally extend type parameters" p
 				| TInst (c,tl) ->
 				| 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
 					let c2 = mk_class null_module (fst c.cl_path,"+" ^ snd c.cl_path) p in
 					c2.cl_private <- true;
 					c2.cl_private <- true;
 					PMap.iter (fun f _ ->
 					PMap.iter (fun f _ ->

+ 65 - 22
typer.ml

@@ -161,26 +161,35 @@ let rec is_pos_infos = function
 	| _ ->
 	| _ ->
 		false
 		false
 
 
-let check_constraints ctx tname tpl tl map p =
+let check_constraints ctx tname tpl tl map delayed p =
 	List.iter2 (fun m (name,t) ->
 	List.iter2 (fun m (name,t) ->
 		match follow t with
 		match follow t with
 		| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
 		| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
-			delay ctx PCheckConstraint (fun() ->
+			let f = (fun() ->
 				List.iter (fun ct ->
 				List.iter (fun ct ->
 					try
 					try
 						Type.unify (map m) (map ct)
 						Type.unify (map m) (map ct)
 					with Unify_error l ->
 					with Unify_error l ->
-						display_error ctx (error_msg (Unify (Constraint_failure (tname ^ "." ^ name) :: l))) p;
+						let l = Constraint_failure (tname ^ "." ^ name) :: l in
+						raise (Unify_error l)
 				) constr
 				) constr
-			);
+			) in
+			if delayed then
+				delay ctx PCheckConstraint f
+			else
+				f()
 		| _ ->
 		| _ ->
 			()
 			()
 	) tl tpl
 	) tl tpl
 
 
 let enum_field_type ctx en ef tl_en tl_ef p =
 let enum_field_type ctx en ef tl_en tl_ef p =
 	let map t = apply_params en.e_types tl_en (apply_params ef.ef_params tl_ef t) in
 	let map t = apply_params en.e_types tl_en (apply_params ef.ef_params tl_ef t) in
-	check_constraints ctx (s_type_path en.e_path) en.e_types tl_en map p;
-	check_constraints ctx ef.ef_name ef.ef_params tl_ef map p;
+	begin try
+		check_constraints ctx (s_type_path en.e_path) en.e_types tl_en map true p;
+		check_constraints ctx ef.ef_name ef.ef_params tl_ef map true p;
+	with Unify_error l ->
+		display_error ctx (error_msg (Unify l)) p
+	end;
 	map ef.ef_type
 	map ef.ef_type
 
 
 let add_constraint_checks ctx ctypes pl f tl p =
 let add_constraint_checks ctx ctypes pl f tl p =
@@ -698,7 +707,8 @@ let make_call ctx e params t p =
 				begin match t with
 				begin match t with
 					| TAbstract(a,pl) ->
 					| TAbstract(a,pl) ->
 						let has_params = a.a_types <> [] || f.cf_params <> [] in
 						let has_params = a.a_types <> [] || f.cf_params <> [] in
-						let map_type = fun t -> apply_params a.a_types pl (monomorphs f.cf_params t) in
+						let monos = List.map (fun _ -> mk_mono()) f.cf_params in
+						let map_type = fun t -> apply_params a.a_types pl (apply_params f.cf_params monos t) in
 						Some (has_params,map_type)
 						Some (has_params,map_type)
 					| _ ->
 					| _ ->
 						None
 						None
@@ -1512,7 +1522,7 @@ let call_to_string ctx c e =
 	let cf = PMap.find "toString" c.cl_statics 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
 	make_call ctx (mk (TField(et,FStatic(c,cf))) cf.cf_type e.epos) [e] ctx.t.tstring e.epos
 
 
-let rec type_binop ctx op e1 e2 is_assign_op p =
+let rec type_binop ctx op e1 e2 is_assign_op with_type p =
 	match op with
 	match op with
 	| OpAssign ->
 	| OpAssign ->
 		let e1 = type_access ctx (fst e1) (snd e1) MSet in
 		let e1 = type_access ctx (fst e1) (snd e1) MSet in
@@ -1563,7 +1573,7 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 		(match type_access ctx (fst e1) (snd e1) MSet with
 		(match type_access ctx (fst e1) (snd e1) MSet with
 		| AKNo s -> error ("Cannot access field or identifier " ^ s ^ " for writing") p
 		| AKNo s -> error ("Cannot access field or identifier " ^ s ^ " for writing") p
 		| AKExpr e ->
 		| AKExpr e ->
-			let eop = type_binop ctx op e1 e2 true p in
+			let eop = type_binop ctx op e1 e2 true with_type p in
 			(match eop.eexpr with
 			(match eop.eexpr with
 			| TBinop (_,_,e2) ->
 			| TBinop (_,_,e2) ->
 				unify ctx eop.etype e.etype p;
 				unify ctx eop.etype e.etype p;
@@ -1581,7 +1591,7 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 			let l = save_locals ctx in
 			let l = save_locals ctx in
 			let v = gen_local ctx e.etype in
 			let v = gen_local ctx e.etype in
 			let ev = mk (TLocal v) e.etype p 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 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
 			unify ctx get.etype t p;
 			unify ctx get.etype t p;
 			l();
 			l();
 			mk (TBlock [
 			mk (TBlock [
@@ -1600,7 +1610,7 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 			let ev = mk (TLocal v) ta p in
 			let ev = mk (TLocal v) ta p in
 			(* this relies on the fact that cf_name is set_name *)
 			(* this relies on the fact that cf_name is set_name *)
 			let getter_name = String.sub cf.cf_name 4 (String.length cf.cf_name - 4) in
 			let getter_name = String.sub cf.cf_name 4 (String.length cf.cf_name - 4) in
-			let get = type_binop ctx op (EField ((EConst (Ident v.v_name),p),getter_name),p) e2 true p in
+			let get = type_binop ctx op (EField ((EConst (Ident v.v_name),p),getter_name),p) e2 true with_type p in
 			unify ctx get.etype ret p;
 			unify ctx get.etype ret p;
 			l();
 			l();
 			mk (TBlock [
 			mk (TBlock [
@@ -1625,7 +1635,7 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 			in
 			in
 			let ast_call = ECall((EField(Interp.make_ast ebase,cf_get.cf_name),p),[Interp.make_ast ekey]),p in
 			let ast_call = ECall((EField(Interp.make_ast ebase,cf_get.cf_name),p),[Interp.make_ast ekey]),p in
 			let ast_call = (EMeta((Meta.PrivateAccess,[],pos ast_call),ast_call),pos ast_call) in
 			let ast_call = (EMeta((Meta.PrivateAccess,[],pos ast_call),ast_call),pos ast_call) in
-			let eget = type_binop ctx op ast_call e2 true p in
+			let eget = type_binop ctx op ast_call e2 true with_type p in
 			unify ctx eget.etype r_get p;
 			unify ctx eget.etype r_get p;
 			let cf_set,tf_set,r_set =
 			let cf_set,tf_set,r_set =
 				try find_array_access a pl ekey.etype eget.etype true
 				try find_array_access a pl ekey.etype eget.etype true
@@ -1650,8 +1660,24 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 		| AKInline _ | AKMacro _ ->
 		| AKInline _ | AKMacro _ ->
 			assert false)
 			assert false)
 	| _ ->
 	| _ ->
-	let e1 = type_expr ctx e1 Value in
-	let e2 = type_expr ctx e2 (if op == OpEq || op == OpNotEq then WithType e1.etype else Value) in
+	(* 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 ->
+			begin match follow t with
+				| TAbstract(a,_) ->
+					begin match List.filter (fun (o,_) -> o = OpAssignOp(op) || o == op) a.a_ops with
+						| [_] -> with_type
+						| _ -> Value
+					end
+				| _ ->
+					Value
+			end
+		| _ ->
+			Value
+	in
+	let e1 = type_expr ctx e1 wt in
+	let e2 = type_expr ctx e2 (if op == OpEq || op == OpNotEq then WithType e1.etype else wt) in
 	let tint = ctx.t.tint in
 	let tint = ctx.t.tint in
 	let tfloat = ctx.t.tfloat in
 	let tfloat = ctx.t.tfloat in
 	let tstring = ctx.t.tstring in
 	let tstring = ctx.t.tstring in
@@ -1833,7 +1859,8 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 			| [] -> raise Not_found
 			| [] -> raise Not_found
 			| (o,cf) :: ops when is_assign_op && o = OpAssignOp(op) || o == op ->
 			| (o,cf) :: ops when is_assign_op && o = OpAssignOp(op) || o == op ->
 				let impl = Meta.has Meta.Impl cf.cf_meta in
 				let impl = Meta.has Meta.Impl cf.cf_meta in
-				let tcf = monomorphs cf.cf_params cf.cf_type in
+				let monos = List.map (fun _ -> mk_mono()) cf.cf_params in
+				let tcf = apply_params cf.cf_params monos cf.cf_type in
 				let tcf = if impl then apply_params a.a_types pl tcf else tcf in
 				let tcf = if impl then apply_params a.a_types pl tcf else tcf in
 				(match follow tcf with
 				(match follow tcf with
 				| TFun([(_,_,t1);(_,_,t2)],r) ->
 				| TFun([(_,_,t1);(_,_,t2)],r) ->
@@ -1847,7 +1874,16 @@ let rec type_binop ctx op e1 e2 is_assign_op p =
 								else
 								else
 									type_eq EqStrict (TAbstract(a,pl)) t1;
 									type_eq EqStrict (TAbstract(a,pl)) t1;
 							end;
 							end;
+							(* 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. *)
+							begin match op,follow t with
+								| (OpEq | OpNotEq),TMono _ ->
+									Type.unify (if left then e1.etype else e2.etype) t
+								| _ ->
+									()
+							end;
 							Type.unify t t2;
 							Type.unify t t2;
+							check_constraints ctx "" cf.cf_params monos (apply_params a.a_types pl) false cf.cf_pos;
 							cf,t2,r,o = OpAssignOp(op),Meta.has Meta.Commutative cf.cf_meta
 							cf,t2,r,o = OpAssignOp(op),Meta.has Meta.Commutative cf.cf_meta
 						with Unify_error _ ->
 						with Unify_error _ ->
 							loop ops
 							loop ops
@@ -2005,7 +2041,7 @@ and type_unop ctx op flag e p =
 		let eget = (EField ((EConst (Ident v.v_name),p),cf.cf_name),p) in
 		let eget = (EField ((EConst (Ident v.v_name),p),cf.cf_name),p) in
 		match flag with
 		match flag with
 		| Prefix ->
 		| Prefix ->
-			let get = type_binop ctx op eget one false p in
+			let get = type_binop ctx op eget one false Value p in
 			unify ctx get.etype t p;
 			unify ctx get.etype t p;
 			l();
 			l();
 			mk (TBlock [
 			mk (TBlock [
@@ -2016,7 +2052,7 @@ and type_unop ctx op flag e p =
 			let v2 = gen_local ctx t in
 			let v2 = gen_local ctx t in
 			let ev2 = mk (TLocal v2) t p in
 			let ev2 = mk (TLocal v2) t p in
 			let get = type_expr ctx eget Value in
 			let get = type_expr ctx eget Value in
-			let plusone = type_binop ctx op (EConst (Ident v2.v_name),p) one false p in
+			let plusone = type_binop ctx op (EConst (Ident v2.v_name),p) one false Value p in
 			unify ctx get.etype t p;
 			unify ctx get.etype t p;
 			l();
 			l();
 			mk (TBlock [
 			mk (TBlock [
@@ -2447,8 +2483,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 	| EField(_,n) when n.[0] = '$' ->
 	| EField(_,n) when n.[0] = '$' ->
 		error "Field names starting with $ are not allowed" p
 		error "Field names starting with $ are not allowed" p
 	| EConst (Ident s) ->
 	| EConst (Ident s) ->
-		(* TODO: let's deal with this later *)
-		(* if s = "super" && with_type <> NoValue then error "Cannot use super as value" p; *)
+		if s = "super" && with_type <> NoValue then error "Cannot use super as value" p;
 		(try
 		(try
 			acc_get ctx (type_ident_raise ~imported_enums:false ctx s p MGet) p
 			acc_get ctx (type_ident_raise ~imported_enums:false ctx s p MGet) p
 		with Not_found -> try
 		with Not_found -> try
@@ -2491,7 +2526,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 	| EConst c ->
 	| EConst c ->
 		Codegen.type_constant ctx.com c p
 		Codegen.type_constant ctx.com c p
     | EBinop (op,e1,e2) ->
     | EBinop (op,e1,e2) ->
-		type_binop ctx op e1 e2 false p
+		type_binop ctx op e1 e2 false with_type p
 	| EBlock [] when with_type <> NoValue ->
 	| EBlock [] when with_type <> NoValue ->
 		type_expr ctx (EObjectDecl [],p) with_type
 		type_expr ctx (EObjectDecl [],p) with_type
 	| EBlock l ->
 	| EBlock l ->
@@ -2845,7 +2880,10 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		let catches = List.fold_left (fun acc (v,t,e) ->
 		let catches = List.fold_left (fun acc (v,t,e) ->
 			let t = Typeload.load_complex_type ctx (pos e) t in
 			let t = Typeload.load_complex_type ctx (pos e) t in
 			let rec loop t = match follow t with
 			let rec loop t = match follow t with
-				| TInst ({ cl_path = path },params) | TEnum ({ e_path = path },params) ->
+				| 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) ->
 					List.iter (fun pt ->
 					List.iter (fun pt ->
 						if pt != t_dynamic then error "Catch class parameter must be Dynamic" p;
 						if pt != t_dynamic then error "Catch class parameter must be Dynamic" p;
 					) params;
 					) params;
@@ -3325,7 +3363,12 @@ and type_expr ctx (e,p) (with_type:with_type) =
 					| 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 c e
 					| _ -> e)
 					| _ -> e)
 			| (Meta.This,_,_) ->
 			| (Meta.This,_,_) ->
-				List.hd ctx.this_stack
+				let e = List.hd ctx.this_stack in
+				let rec loop e = match e.eexpr with
+					| TConst TThis -> get_this ctx e.epos
+					| _ -> Type.map_expr loop e
+				in
+				loop e
 			| _ -> e()
 			| _ -> e()
 		in
 		in
 		ctx.meta <- old;
 		ctx.meta <- old;