From da2e7251cc03ee87cb61d5e059dcff99784e9bb6 Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Thu, 13 Oct 2016 15:17:11 +0300 Subject: [PATCH 01/12] [js] inline Array.map when possible --- std/js/_std/Array.hx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/std/js/_std/Array.hx b/std/js/_std/Array.hx index c215a83fa8b..ceb0feb216c 100644 --- a/std/js/_std/Array.hx +++ b/std/js/_std/Array.hx @@ -64,7 +64,11 @@ extern class Array { return (cast this).slice(); } - function map(f:T->S):Array; + @:runtime inline function map(f:T->S):Array { + var a:Array = untyped __new__(Array, length); + for (i in 0...length) a[i] = f(this[i]); + return a; + } function filter(f:T->Bool):Array; @:runtime inline function iterator() : Iterator { From fc90f9c55b0826be45793cdb52edac1b4d52d6d2 Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Thu, 13 Oct 2016 15:23:44 +0300 Subject: [PATCH 02/12] [js] inline Array.filter too --- std/js/_std/Array.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/std/js/_std/Array.hx b/std/js/_std/Array.hx index ceb0feb216c..d770223b97e 100644 --- a/std/js/_std/Array.hx +++ b/std/js/_std/Array.hx @@ -69,7 +69,9 @@ extern class Array { for (i in 0...length) a[i] = f(this[i]); return a; } - function filter(f:T->Bool):Array; + @:runtime inline function filter(f:T->Bool):Array { + return [for (v in this) if (f(v)) v]; + } @:runtime inline function iterator() : Iterator { return @:privateAccess HxOverrides.iter(this); From ef9f1e729a10293551f64fa40b85c3f5a38f686a Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Thu, 13 Oct 2016 15:28:59 +0300 Subject: [PATCH 03/12] inline map/filter by default --- std/Array.hx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/std/Array.hx b/std/Array.hx index f8f4d1d3457..1667a3fe361 100644 --- a/std/Array.hx +++ b/std/Array.hx @@ -274,7 +274,9 @@ extern class Array { If `f` is null, the result is unspecified. **/ - function map( f : T -> S ) : Array; + @:runtime inline function map( f : T -> S ) : Array { + return [for (v in this) f(v)]; + } /** Returns an Array containing those elements of `this` for which `f` @@ -284,5 +286,7 @@ extern class Array { If `f` is null, the result is unspecified. **/ - function filter( f : T -> Bool ) : Array; + @:runtime inline function filter( f : T -> Bool ) : Array { + return [for (v in this) if (f(v)) v]; + } } From b374c34204689b3acbc0720330b1651034ab839c Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Thu, 13 Oct 2016 15:38:33 +0300 Subject: [PATCH 04/12] [cpp] optimize Array.map --- std/Array.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/std/Array.hx b/std/Array.hx index 1667a3fe361..90ca20706b9 100644 --- a/std/Array.hx +++ b/std/Array.hx @@ -275,7 +275,14 @@ extern class Array { If `f` is null, the result is unspecified. **/ @:runtime inline function map( f : T -> S ) : Array { + #if cpp + var result = []; + cpp.NativeArray.setSize(result, length); + for (i in 0...length) cpp.NativeArray.unsafeSet(result, i, f(cpp.NativeArray.unsafeGet(this, i))); + return result; + #else return [for (v in this) f(v)]; + #end } /** From 3076f8ec30742e7f5f416b4ca1a25a9f0129c39b Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Thu, 13 Oct 2016 17:17:13 +0300 Subject: [PATCH 05/12] [cs] inline (also optimize a bit) Array.map/filter --- std/cs/_std/Array.hx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/std/cs/_std/Array.hx b/std/cs/_std/Array.hx index 5ed8d0f0abe..d593ec5f80f 100644 --- a/std/cs/_std/Array.hx +++ b/std/cs/_std/Array.hx @@ -399,18 +399,20 @@ import cs.NativeArray; return false; } - public function map( f : T -> S ) : Array { - var ret = []; - for (elt in this) - ret.push(f(elt)); + public inline function map( f : T -> S ) : Array { + var ret = alloc(length); + for (i in 0...length) + ret.__unsafe_set(i, f(__unsafe_get(i))); return ret; } - public function filter( f : T -> Bool ) : Array { + public inline function filter( f : T -> Bool ) : Array { var ret = []; - for (elt in this) + for (i in 0...length) { + var elt = __unsafe_get(i); if (f(elt)) ret.push(elt); + } return ret; } From a747e257b7745ff332b5166b3e04b3ca5133b12f Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Thu, 13 Oct 2016 17:34:19 +0300 Subject: [PATCH 06/12] [java] inline Array.map/filter (use slower `__get/__set` for now, since unsafe versions fail, issue incoming) --- std/java/_std/Array.hx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/std/java/_std/Array.hx b/std/java/_std/Array.hx index cac869ead11..2ae10a28225 100644 --- a/std/java/_std/Array.hx +++ b/std/java/_std/Array.hx @@ -407,18 +407,20 @@ import java.NativeArray; return new ArrayIterator(this); } - public function map( f : T -> S ) : Array { - var ret = []; - for (elt in this) - ret.push(f(elt)); + public inline function map( f : T -> S ) : Array { + var ret = alloc(length); + for (i in 0...length) + ret.__set(i, f(__get(i))); return ret; } - public function filter( f : T -> Bool ) : Array { + public inline function filter( f : T -> Bool ) : Array { var ret = []; - for (elt in this) + for (i in 0...length) { + var elt = __get(i); if (f(elt)) ret.push(elt); + } return ret; } From c0a273c122904dba860cc19361919630875920e8 Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Thu, 13 Oct 2016 18:00:44 +0300 Subject: [PATCH 07/12] [lua] inline Array.map/filter --- std/lua/_std/Array.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/lua/_std/Array.hx b/std/lua/_std/Array.hx index 4ea3e231c45..ee4e83c8158 100644 --- a/std/lua/_std/Array.hx +++ b/std/lua/_std/Array.hx @@ -200,10 +200,10 @@ class Array { public inline function copy() : Array { return [for (i in this) i]; } - public function map(f:T->S):Array { + public inline function map(f:T->S):Array { return [for (i in this) f(i)]; } - public function filter(f:T->Bool):Array { + public inline function filter(f:T->Bool):Array { return [for (i in this) if (f(i)) i]; } public inline function iterator() : Iterator { From 210e3f32341e09211b244fdb10197198859c0c1a Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Thu, 13 Oct 2016 18:27:33 +0300 Subject: [PATCH 08/12] [neko] inline Array.map/filter --- std/neko/_std/Array.hx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/std/neko/_std/Array.hx b/std/neko/_std/Array.hx index b03303f9273..0a90d36bcb7 100644 --- a/std/neko/_std/Array.hx +++ b/std/neko/_std/Array.hx @@ -269,14 +269,16 @@ return ret; } - public function map( f : T -> S ) : Array { - var ret = []; - for (elt in this) - ret.push(f(elt)); + public inline function map( f : T -> S ) : Array { + var l = length; + var ret = new1(neko.NativeArray.alloc(l), l); + for (i in 0...l) { + ret[i] = f(this[i]); + } return ret; } - public function filter( f : T -> Bool ) : Array { + public inline function filter( f : T -> Bool ) : Array { var ret = []; for (elt in this) if (f(elt)) From f0f8389f2f873e203adf28e9c928e92b165c399a Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Thu, 13 Oct 2016 19:29:16 +0300 Subject: [PATCH 09/12] use the new NativeArray.create function --- std/Array.hx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/std/Array.hx b/std/Array.hx index 90ca20706b9..d1e07538171 100644 --- a/std/Array.hx +++ b/std/Array.hx @@ -276,8 +276,7 @@ extern class Array { **/ @:runtime inline function map( f : T -> S ) : Array { #if cpp - var result = []; - cpp.NativeArray.setSize(result, length); + var result = cpp.NativeArray.create(length); for (i in 0...length) cpp.NativeArray.unsafeSet(result, i, f(cpp.NativeArray.unsafeGet(this, i))); return result; #else From 4df256bc408110584339c6047a2fffa88b104370 Mon Sep 17 00:00:00 2001 From: Aleksandr Kuzmenko Date: Sun, 18 Aug 2019 18:43:55 +0300 Subject: [PATCH 10/12] Merge development into array_map_inline --- .github/FUNDING.yml | 4 + .gitignore | 22 +- .gitmodules | 3 - .merlin | 6 +- .travis.yml | 259 -- .vscode/settings.json | 23 +- CONTRIBUTING.md | 52 +- Makefile | 124 +- Makefile.version_extra | 2 +- Makefile.win | 35 +- README.md | 75 +- appveyor.yml | 83 - azure-pipelines.yml | 300 ++ extra/BUILDING.md | 79 + extra/CHANGES.txt | 358 +- extra/ImportAll.hx | 33 +- extra/all.hxml | 10 +- extra/azure-pipelines/build-linux.yml | 61 + extra/azure-pipelines/build-mac.yml | 46 + extra/azure-pipelines/build-windows.yml | 68 + .../install-neko-snapshot.yaml | 33 + extra/azure-pipelines/test-windows.yml | 87 + extra/doc.hxml | 56 + extra/extract.hxml | 8 +- extra/haxelib_src | 2 +- extra/images/Readme.png | Bin 0 -> 8453 bytes extra/installer.nsi | 4 +- extra/release-checklist.txt | 11 +- haxe.hxproj | 436 -- opam | 34 + src-json/define.json | 639 +++ src-json/meta.json | 1196 +++++ src/codegen/codegen.ml | 350 +- src/codegen/dotnet.ml | 234 +- .../gencommon/abstractImplementationFix.ml | 2 +- src/codegen/gencommon/arrayDeclSynf.ml | 2 +- .../gencommon/arraySpliceOptimization.ml | 40 + src/codegen/gencommon/castDetect.ml | 19 +- src/codegen/gencommon/classInstance.ml | 2 +- src/codegen/gencommon/closuresToClass.ml | 110 +- src/codegen/gencommon/dynamicFieldAccess.ml | 8 +- src/codegen/gencommon/dynamicOperators.ml | 25 +- src/codegen/gencommon/enumToClass.ml | 17 +- src/codegen/gencommon/enumToClass2.ml | 34 +- src/codegen/gencommon/expressionUnwrap.ml | 6 +- src/codegen/gencommon/filterClosures.ml | 2 +- src/codegen/gencommon/fixOverrides.ml | 14 +- src/codegen/gencommon/gencommon.ml | 48 +- src/codegen/gencommon/hardNullableSynf.ml | 2 +- src/codegen/gencommon/initFunction.ml | 19 +- src/codegen/gencommon/intDivisionSynf.ml | 44 +- src/codegen/gencommon/interfaceProps.ml | 2 +- .../gencommon/interfaceVarsDeleteModf.ml | 2 +- src/codegen/gencommon/normalize.ml | 4 +- src/codegen/gencommon/objectDeclMap.ml | 2 +- .../gencommon/overloadingConstructor.ml | 41 +- src/codegen/gencommon/realTypeParams.ml | 182 +- src/codegen/gencommon/reflectionCFs.ml | 273 +- src/codegen/gencommon/renameTypeParameters.ml | 2 +- src/codegen/gencommon/setHXGen.ml | 2 +- src/codegen/gencommon/switchToIf.ml | 4 +- src/codegen/gencommon/tArrayTransform.ml | 2 +- .../gencommon/unnecessaryCastsRemoval.ml | 2 +- .../unreachableCodeEliminationSynf.ml | 4 +- src/codegen/genxml.ml | 277 +- src/codegen/java.ml | 565 +-- src/codegen/swfLoader.ml | 278 +- src/compiler/displayOutput.ml | 834 ++-- src/compiler/main.ml | 942 ++-- src/compiler/server.ml | 504 +-- src/compiler/serverConfig.ml | 1 + src/compiler/serverMessage.ml | 192 + src/context/abstractCast.ml | 290 ++ src/context/common.ml | 780 ++-- src/context/compilationServer.ml | 297 ++ src/context/display.ml | 935 ---- src/context/display/deprecationCheck.ml | 95 + src/context/display/diagnostics.ml | 219 + src/context/display/display.ml | 254 ++ src/context/display/displayEmitter.ml | 309 ++ src/context/display/displayException.ml | 188 + src/context/display/displayFields.ml | 287 ++ src/context/display/displayJson.ml | 305 ++ src/context/display/displayToplevel.ml | 460 ++ src/context/display/documentSymbols.ml | 123 + src/context/display/findReferences.ml | 192 + src/context/display/importHandling.ml | 59 + src/context/display/statistics.ml | 292 ++ src/context/displayTypes.ml | 59 - src/context/nativeLibraries.ml | 60 + src/context/nativeLibraryHandler.ml | 39 + src/context/purityState.ml | 67 + src/context/sourcemaps.ml | 2 +- src/context/typecore.ml | 483 +- src/core/abstract.ml | 63 +- src/core/ast.ml | 298 +- src/core/define.ml | 247 +- src/core/display/completionItem.ml | 718 +++ src/core/display/displayPosition.ml | 58 + src/core/displayTypes.ml | 295 ++ src/core/error.ml | 210 +- src/core/globals.ml | 11 +- src/core/json/genjson.ml | 710 +++ src/core/{ => json}/json.ml | 7 +- src/core/json/jsonRequest.ml | 19 + src/core/json/jsonRpc.ml | 79 + src/core/json/jsonRpcSocket.ml | 7 + src/core/json/jsonrpc_handler.ml | 86 + src/core/meta.ml | 387 +- src/core/numeric.ml | 74 + src/core/path.ml | 103 +- src/core/socket.ml | 63 + src/core/stringError.ml | 73 + src/core/stringHelper.ml | 42 + src/core/texpr.ml | 535 +++ src/core/timer.ml | 171 + src/core/type.ml | 1023 +++-- src/core/withType.ml | 31 + src/filters/ES6Ctors.ml | 243 + src/filters/capturedVars.ml | 24 +- src/filters/defaultArguments.ml | 15 +- src/filters/filters.ml | 238 +- src/filters/filtersCommon.ml | 68 + src/filters/jsExceptions.ml | 212 + src/filters/localUsage.ml | 2 +- src/filters/tryCatchWrapper.ml | 14 +- src/filters/varLazifier.ml | 4 +- src/generators/flashProps.ml | 60 + src/generators/genas3.ml | 123 +- src/generators/gencpp.ml | 850 ++-- src/generators/gencs.ml | 482 +- src/generators/genhl.ml | 665 ++- src/generators/genhxold.ml | 303 ++ src/generators/genjava.ml | 200 +- src/generators/genjs.ml | 918 ++-- src/generators/genjvm.ml | 3092 +++++++++++++ src/generators/genlua.ml | 383 +- src/generators/genneko.ml | 10 +- src/generators/genphp7.ml | 1003 +++-- src/generators/genpy.ml | 170 +- src/generators/genswf.ml | 43 +- src/generators/genswf9.ml | 621 ++- src/generators/hl2c.ml | 937 ++-- src/generators/hlcode.ml | 66 +- src/generators/hlinterp.ml | 170 +- src/generators/hlopt.ml | 431 +- src/generators/jvm/jvmAttribute.ml | 248 ++ src/generators/jvm/jvmBuilder.ml | 89 + src/generators/jvm/jvmClass.ml | 188 + src/generators/jvm/jvmCode.ml | 566 +++ src/generators/jvm/jvmConstantPool.ml | 192 + src/generators/jvm/jvmData.ml | 294 ++ src/generators/jvm/jvmDebug.ml | 281 ++ src/generators/jvm/jvmGlobals.ml | 166 + src/generators/jvm/jvmMethod.ml | 844 ++++ src/generators/jvm/jvmSignature.ml | 294 ++ src/generators/jvm/jvmVerificationTypeInfo.ml | 56 + src/generators/jvm/jvmWriter.ml | 341 ++ src/macro/eval/bytes/evalBytesLower.ml | 23 + src/macro/eval/bytes/evalBytesUpper.ml | 24 + src/macro/eval/bytes/evalBytes_E_L79.ml | 41 + src/macro/eval/bytes/evalBytes_L1020.ml | 42 + src/macro/eval/bytes/evalBytes_U1021.ml | 44 + src/macro/eval/bytes/evalBytes_U79.ml | 40 + src/macro/eval/evalArray.ml | 39 +- src/macro/eval/evalBytes.ml | 160 + src/macro/eval/evalContext.ml | 441 +- src/macro/eval/evalDebug.ml | 99 +- src/macro/eval/evalDebugCLI.ml | 389 -- src/macro/eval/evalDebugMisc.ml | 351 +- src/macro/eval/evalDebugSocket.ml | 1105 +++-- src/macro/eval/evalDecode.ml | 14 +- src/macro/eval/evalEmitter.ml | 1267 ++---- src/macro/eval/evalEncode.ml | 151 +- src/macro/eval/evalExceptions.ml | 64 +- src/macro/eval/evalField.ml | 11 +- src/macro/eval/evalHash.ml | 215 +- src/macro/eval/evalJit.ml | 695 ++- src/macro/eval/evalJitContext.ml | 41 +- src/macro/eval/evalMain.ml | 263 +- src/macro/eval/evalMisc.ml | 143 +- src/macro/eval/evalPrinting.ml | 106 +- src/macro/eval/evalPrototype.ml | 104 +- src/macro/eval/evalStdLib.ml | 1625 ++++--- src/macro/eval/evalString.ml | 282 ++ src/macro/eval/evalThread.ml | 92 + src/macro/eval/evalValue.ml | 120 +- src/macro/hlmacro.ml | 557 --- src/macro/macroApi.ml | 438 +- src/optimization/analyzer.ml | 93 +- src/optimization/analyzerConfig.ml | 24 +- src/optimization/analyzerTexpr.ml | 200 +- src/optimization/analyzerTexprTransformer.ml | 33 +- src/optimization/analyzerTypes.ml | 2 +- src/optimization/dce.ml | 219 +- src/optimization/inline.ml | 780 ++++ src/optimization/inlineConstructors.ml | 28 +- src/optimization/optimizer.ml | 1036 +---- src/optimization/optimizerTexpr.ml | 64 +- src/prebuild/main.ml | 218 + src/syntax/grammar.mly | 1420 +++--- src/syntax/lexer.ml | 186 +- src/syntax/parser.ml | 252 +- src/syntax/parserEntry.ml | 142 +- src/syntax/reification.ml | 35 +- src/syntax/semver.ml | 114 + src/typing/calls.ml | 794 ++++ src/typing/fields.ml | 623 +++ src/typing/finalization.ml | 166 + src/typing/forLoop.ml | 506 +++ src/typing/generic.ml | 309 ++ src/typing/instanceBuilder.ml | 103 + src/typing/macroContext.ml | 356 +- src/typing/magicTypes.ml | 11 +- src/typing/matcher.ml | 667 +-- src/typing/nullSafety.ml | 1516 +++++++ src/typing/typeload.ml | 3903 ++--------------- src/typing/typeloadCheck.ml | 545 +++ src/typing/typeloadFields.ml | 1528 +++++++ src/typing/typeloadFunction.ml | 310 ++ src/typing/typeloadModule.ml | 989 +++++ src/typing/typeloadParse.ml | 218 + src/typing/typer.ml | 3617 ++++----------- src/typing/typerBase.ml | 212 + src/typing/typerDisplay.ml | 606 +++ std/Any.hx | 13 +- std/Array.hx | 62 +- std/Class.hx | 6 +- std/Date.hx | 183 +- std/DateTools.hx | 136 +- std/EReg.hx | 27 +- std/Enum.hx | 5 +- std/EnumValue.hx | 33 +- std/IntIterator.hx | 12 +- std/Lambda.hx | 133 +- std/List.hx | 23 +- std/Map.hx | 23 +- std/Math.hx | 83 +- std/Reflect.hx | 53 +- std/Std.hx | 35 +- std/StdTypes.hx | 53 +- std/String.hx | 50 +- std/StringBuf.hx | 17 +- std/StringTools.hx | 457 +- std/Sys.hx | 123 +- std/Type.hx | 58 +- std/UInt.hx | 152 +- std/UnicodeString.hx | 443 ++ std/Xml.hx | 103 +- std/cpp/ArrayBase.hx | 19 +- std/cpp/AtomicInt.hx | 50 +- std/cpp/AutoCast.hx | 5 +- std/cpp/Callable.hx | 76 +- std/cpp/CastCharStar.hx | 22 +- std/cpp/Char.hx | 5 +- std/cpp/ConstCharStar.hx | 25 +- std/cpp/ConstPointer.hx | 65 +- std/cpp/ConstStar.hx | 12 +- std/cpp/EnumBase.hx | 79 +- std/cpp/ErrorConstants.hx | 26 +- std/cpp/FILE.hx | 5 +- std/cpp/FastIterator.hx | 7 +- std/cpp/Finalizable.hx | 42 +- std/cpp/Float32.hx | 5 +- std/cpp/Float64.hx | 5 +- std/cpp/Function.hx | 63 +- std/cpp/Int16.hx | 5 +- std/cpp/Int32.hx | 5 +- std/cpp/Int64.hx | 5 +- std/cpp/Int8.hx | 5 +- std/cpp/Lib.hx | 79 +- std/cpp/Native.hx | 103 + std/cpp/NativeArc.hx | 35 +- std/cpp/NativeArray.hx | 112 +- std/cpp/NativeFile.hx | 99 +- std/cpp/NativeGc.hx | 86 +- std/cpp/NativeMath.hx | 66 +- std/cpp/NativeProcess.hx | 70 +- std/cpp/NativeRandom.hx | 47 +- std/cpp/NativeSocket.hx | 212 +- std/cpp/NativeSsl.hx | 170 +- std/cpp/NativeString.hx | 75 +- std/cpp/NativeSys.hx | 160 +- std/cpp/NativeXml.hx | 905 ++-- std/cpp/NativeXmlImport.cpp | 21 + std/cpp/Object.hx | 6 +- std/cpp/ObjectType.hx | 52 +- std/cpp/Pointer.hx | 91 +- std/cpp/Prime.hx | 159 +- std/cpp/Random.hx | 17 +- std/cpp/RawConstPointer.hx | 12 +- std/cpp/RawPointer.hx | 12 +- std/cpp/Reference.hx | 12 +- std/cpp/SizeT.hx | 8 +- std/cpp/Star.hx | 12 +- std/cpp/StdString.hx | 49 +- std/cpp/StdStringRef.hx | 38 +- std/cpp/Stdio.hx | 28 +- std/cpp/Stdlib.hx | 71 +- std/cpp/Struct.hx | 10 +- std/cpp/UInt16.hx | 5 +- std/cpp/UInt32.hx | 5 +- std/cpp/UInt64.hx | 5 +- std/cpp/UInt8.hx | 5 +- std/cpp/VarArg.hx | 11 +- std/cpp/VirtualArray.hx | 174 +- std/cpp/Void.hx | 8 +- std/cpp/_std/Date.hx | 103 +- std/cpp/_std/EReg.hx | 239 +- std/cpp/_std/Reflect.hx | 154 +- std/cpp/_std/Std.hx | 29 +- std/cpp/_std/StringBuf.hx | 122 +- std/cpp/_std/Sys.hx | 73 +- std/cpp/_std/Type.hx | 200 +- std/cpp/_std/haxe/Int64.hx | 563 ++- std/cpp/_std/haxe/Log.hx | 32 +- std/cpp/_std/haxe/Resource.hx | 16 +- std/cpp/_std/haxe/Utf8.hx | 70 +- std/cpp/_std/haxe/ds/IntMap.hx | 85 +- std/cpp/_std/haxe/ds/ObjectMap.hx | 84 +- std/cpp/_std/haxe/ds/StringMap.hx | 84 +- std/cpp/_std/haxe/ds/WeakMap.hx | 43 +- std/cpp/_std/haxe/zip/Compress.hx | 50 +- std/cpp/_std/haxe/zip/Uncompress.hx | 48 +- std/cpp/_std/sys/FileSystem.hx | 61 +- std/cpp/_std/sys/db/Mysql.hx | 181 +- std/cpp/_std/sys/db/Sqlite.hx | 142 +- std/cpp/_std/sys/io/File.hx | 38 +- std/cpp/_std/sys/io/FileInput.hx | 35 +- std/cpp/_std/sys/io/FileOutput.hx | 31 +- std/cpp/_std/sys/io/Process.hx | 73 +- std/cpp/_std/sys/net/Host.hx | 35 +- std/cpp/_std/sys/net/Socket.hx | 470 +- std/cpp/_std/sys/net/UdpSocket.hx | 26 +- std/cpp/_std/sys/ssl/Certificate.hx | 125 +- std/cpp/_std/sys/ssl/Digest.hx | 41 +- std/cpp/_std/sys/ssl/Key.hx | 53 +- std/cpp/_std/sys/ssl/Socket.hx | 265 +- std/cpp/_std/sys/thread/Deque.hx | 44 + .../Log.hx => cpp/_std/sys/thread/Lock.hx} | 26 +- std/cpp/_std/sys/thread/Mutex.hx | 44 + std/cpp/_std/sys/thread/Thread.hx | 58 + std/cpp/_std/sys/thread/Tls.hx | 45 + std/cpp/abi/Abi.hx | 7 +- std/cpp/abi/CDecl.hx | 7 +- std/cpp/abi/FastCall.hx | 7 +- std/cpp/abi/StdCall.hx | 7 +- std/cpp/abi/ThisCall.hx | 7 +- std/cpp/abi/Winapi.hx | 7 +- std/cpp/cppia/Host.hx | 77 +- std/cpp/cppia/HostClasses.hx | 445 +- std/cpp/cppia/Module.hx | 21 +- std/cpp/link/StaticMysql.hx | 21 +- std/cpp/link/StaticRegexp.hx | 21 +- std/cpp/link/StaticSqlite.hx | 21 +- std/cpp/link/StaticStd.hx | 21 +- std/cpp/link/StaticZlib.hx | 22 +- std/cpp/net/Poll.hx | 31 +- std/cpp/net/ThreadServer.hx | 695 ++- std/cpp/objc/NSData.hx | 37 +- std/cpp/objc/NSDictionary.hx | 28 +- std/cpp/objc/NSError.hx | 9 +- std/cpp/objc/NSLog.hx | 17 +- std/cpp/objc/NSObject.hx | 27 +- std/cpp/objc/NSString.hx | 29 +- std/cpp/objc/ObjcBlock.hx | 5 +- std/cpp/objc/Protocol.hx | 7 +- std/cpp/rtti/FieldIntegerLookup.hx | 6 +- std/cpp/rtti/FieldNumericIntegerLookup.hx | 6 +- std/cpp/vm/Debugger.hx | 684 ++- std/cpp/vm/Deque.hx | 21 +- std/cpp/vm/ExecutionTrace.hx | 31 +- std/cpp/vm/Gc.hx | 197 +- std/cpp/vm/Lock.hx | 18 +- std/cpp/vm/Mutex.hx | 21 +- std/cpp/vm/Profiler.hx | 24 +- std/cpp/vm/Thread.hx | 51 +- std/cpp/vm/Tls.hx | 25 +- std/cpp/vm/Unsafe.hx | 16 +- std/cpp/vm/WeakRef.hx | 32 +- std/cpp/zip/Compress.hx | 7 +- std/cpp/zip/Flush.hx | 7 +- std/cpp/zip/Uncompress.hx | 7 +- std/cs/Boot.hx | 14 +- std/cs/Constraints.hx | 55 + std/cs/Flags.hx | 73 +- std/cs/Lib.hx | 98 +- std/cs/NativeArray.hx | 34 +- std/cs/Out.hx | 7 +- std/cs/Pointer.hx | 100 +- std/cs/Ref.hx | 7 +- std/cs/StdTypes.hx | 163 +- std/cs/_std/Array.hx | 293 +- std/cs/_std/Date.hx | 137 +- std/cs/_std/EReg.hx | 86 +- std/cs/_std/Math.hx | 88 +- std/cs/_std/Reflect.hx | 107 +- std/cs/_std/Std.hx | 129 +- std/cs/_std/String.hx | 33 +- std/cs/_std/StringBuf.hx | 35 +- std/cs/_std/Sys.hx | 138 +- std/cs/_std/Type.hx | 176 +- std/cs/_std/haxe/Int64.hx | 177 +- std/cs/_std/haxe/Resource.hx | 16 +- std/cs/_std/haxe/ds/IntMap.hx | 335 +- std/cs/_std/haxe/ds/ObjectMap.hx | 326 +- std/cs/_std/haxe/ds/StringMap.hx | 336 +- std/cs/_std/haxe/ds/WeakMap.hx2 | 569 --- std/cs/_std/sys/FileSystem.hx | 88 +- std/cs/_std/sys/db/Sqlite.hx | 36 +- std/cs/_std/sys/io/File.hx | 46 +- std/cs/_std/sys/io/FileInput.hx | 6 +- std/cs/_std/sys/io/FileOutput.hx | 6 +- std/cs/_std/sys/io/Process.hx | 38 +- std/cs/_std/sys/net/Host.hx | 48 +- std/cs/_std/sys/net/Socket.hx | 204 +- std/cs/_std/sys/thread/Deque.hx | 60 + std/cs/_std/sys/thread/Lock.hx | 79 + std/cs/_std/sys/thread/Mutex.hx | 43 + std/cs/_std/sys/thread/Thread.hx | 112 + std/cs/_std/sys/thread/Tls.hx | 45 + std/cs/db/AdoNet.hx | 232 +- std/cs/internal/BoxedPointer.hx | 14 +- std/cs/internal/Exceptions.hx | 29 +- std/cs/internal/FieldLookup.hx | 245 +- std/cs/internal/Function.hx | 48 +- std/cs/internal/HxObject.hx | 248 +- std/cs/internal/Null.hx | 27 +- std/cs/internal/Runtime.hx | 519 +-- std/cs/internal/StringExt.hx | 119 +- std/cs/io/NativeInput.hx | 43 +- std/cs/io/NativeOutput.hx | 44 +- std/cs/types/Char16.hx | 3 +- std/cs/types/Int16.hx | 3 +- std/cs/types/Int64.hx | 4 +- std/cs/types/Int8.hx | 3 +- std/cs/types/UInt16.hx | 3 +- std/cs/types/UInt64.hx | 3 +- std/cs/types/UInt8.hx | 3 +- std/eval/Vector.hx | 7 +- std/eval/_std/EReg.hx | 28 +- std/eval/_std/StringBuf.hx | 17 +- std/eval/_std/Sys.hx | 82 +- std/eval/_std/haxe/Resource.hx | 9 +- std/eval/_std/haxe/Utf8.hx | 28 +- std/eval/_std/haxe/io/Bytes.hx | 57 +- std/eval/_std/haxe/io/BytesBuffer.hx | 7 +- std/eval/_std/haxe/io/BytesData.hx | 12 +- std/eval/_std/haxe/zip/Compress.hx | 7 +- std/eval/_std/haxe/zip/Uncompress.hx | 5 +- std/eval/_std/sys/FileSystem.hx | 39 +- std/eval/_std/sys/io/File.hx | 25 +- std/eval/_std/sys/io/FileInput.hx | 21 +- std/eval/_std/sys/io/FileOutput.hx | 21 +- std/eval/_std/sys/io/Process.hx | 20 +- std/eval/_std/sys/net/Host.hx | 20 +- std/eval/_std/sys/net/Socket.hx | 39 +- .../_std/sys/thread/Thread.hx} | 52 +- std/eval/vm/Context.hx | 33 +- std/eval/vm/Gc.hx | 113 +- std/eval/vm/NativeThread.hx | 79 + std/flash/AnyType.hx | 9 + std/flash/Boot.hx | 419 +- std/flash/Lib.hx | 68 +- std/flash/Memory.hx | 61 +- std/flash/NativeXml.hx | 364 +- std/flash/Vector.hx | 81 +- std/flash/_std/EReg.hx | 73 +- std/flash/_std/Reflect.hx | 178 +- std/flash/_std/Std.hx | 40 +- std/flash/_std/String.hx | 41 + std/flash/_std/Type.hx | 419 +- std/flash/_std/haxe/Http.hx | 106 + std/flash/_std/haxe/Json.hx | 29 +- std/flash/_std/haxe/Log.hx | 28 +- std/flash/_std/haxe/Resource.hx | 54 +- std/flash/_std/haxe/ds/IntMap.hx | 84 +- std/flash/_std/haxe/ds/ObjectMap.hx | 47 +- std/flash/_std/haxe/ds/StringMap.hx | 129 +- std/flash/_std/haxe/ds/UnsafeStringMap.hx | 83 +- std/flash/_std/haxe/ds/WeakMap.hx | 47 +- std/flash/_std/haxe/zip/Compress.hx | 27 +- std/flash/_std/haxe/zip/Uncompress.hx | 19 +- std/flash/accessibility/Accessibility.hx | 3 +- std/flash/accessibility/ISearchableText.hx | 3 +- .../accessibility/ISimpleTextSelection.hx | 6 +- std/flash/automation/AutomationAction.hx | 4 +- std/flash/automation/Configuration.hx | 7 +- .../automation/KeyboardAutomationAction.hx | 8 +- std/flash/automation/MouseAutomationAction.hx | 28 +- std/flash/automation/StageCapture.hx | 28 +- std/flash/automation/StageCaptureEvent.hx | 11 +- std/flash/concurrent/Condition.hx | 8 +- std/flash/concurrent/Mutex.hx | 5 +- std/flash/desktop/Clipboard.hx | 6 +- std/flash/desktop/ClipboardFormats.hx | 24 +- std/flash/desktop/ClipboardTransferMode.hx | 10 +- std/flash/display/AVM1Movie.hx | 2 +- std/flash/display/ActionScriptVersion.hx | 6 +- std/flash/display/Bitmap.hx | 12 +- std/flash/display/BitmapCompressColorSpace.hx | 11 +- std/flash/display/BitmapData.hx | 12 +- std/flash/display/BitmapEncodingColorSpace.hx | 10 +- std/flash/display/BlendMode.hx | 32 +- std/flash/display/CapsStyle.hx | 8 +- std/flash/display/ColorCorrection.hx | 8 +- std/flash/display/ColorCorrectionSupport.hx | 8 +- std/flash/display/DisplayObject.hx | 119 +- std/flash/display/DisplayObjectContainer.hx | 14 +- std/flash/display/FocusDirection.hx | 8 +- std/flash/display/FrameLabel.hx | 8 +- std/flash/display/GradientType.hx | 6 +- std/flash/display/Graphics.hx | 2 +- std/flash/display/GraphicsBitmapFill.hx | 2 +- std/flash/display/GraphicsGradientFill.hx | 14 +- std/flash/display/GraphicsPath.hx | 6 +- std/flash/display/GraphicsPathWinding.hx | 6 +- std/flash/display/GraphicsShaderFill.hx | 2 +- std/flash/display/GraphicsSolidFill.hx | 2 +- std/flash/display/GraphicsStroke.hx | 14 +- std/flash/display/GraphicsTrianglePath.hx | 6 +- std/flash/display/InteractiveObject.hx | 36 +- std/flash/display/InterpolationMethod.hx | 6 +- std/flash/display/JPEGCompressOptions.hx | 2 +- std/flash/display/JPEGEncoderOptions.hx | 2 +- std/flash/display/JPEGXRCompressOptions.hx | 2 +- std/flash/display/JPEGXREncoderOptions.hx | 2 +- std/flash/display/JointStyle.hx | 8 +- std/flash/display/LineScaleMode.hx | 10 +- std/flash/display/Loader.hx | 9 +- std/flash/display/LoaderInfo.hx | 71 +- std/flash/display/MovieClip.hx | 37 +- std/flash/display/NativeMenuItem.hx | 4 +- std/flash/display/PNGEncoderOptions.hx | 2 +- std/flash/display/PixelSnapping.hx | 8 +- std/flash/display/SWFVersion.hx | 24 +- std/flash/display/Scene.hx | 11 +- std/flash/display/Shader.hx | 11 +- std/flash/display/ShaderInput.hx | 20 +- std/flash/display/ShaderJob.hx | 19 +- std/flash/display/ShaderParameter.hx | 12 +- std/flash/display/ShaderParameterType.hx | 32 +- std/flash/display/ShaderPrecision.hx | 6 +- std/flash/display/Shape.hx | 3 +- std/flash/display/SimpleButton.hx | 32 +- std/flash/display/SpreadMethod.hx | 8 +- std/flash/display/Sprite.hx | 22 +- std/flash/display/Stage.hx | 94 +- std/flash/display/Stage3D.hx | 15 +- std/flash/display/StageAlign.hx | 18 +- std/flash/display/StageDisplayState.hx | 8 +- std/flash/display/StageQuality.hx | 18 +- std/flash/display/StageScaleMode.hx | 10 +- std/flash/display/StageWorker.hx | 2 +- std/flash/display/TriangleCulling.hx | 8 +- std/flash/display/Worker.hx | 2 +- std/flash/display3D/Context3D.hx | 32 +- std/flash/display3D/Context3DBlendFactor.hx | 22 +- std/flash/display3D/Context3DBufferUsage.hx | 6 +- std/flash/display3D/Context3DClearMask.hx | 8 +- std/flash/display3D/Context3DCompareMode.hx | 18 +- std/flash/display3D/Context3DFillMode.hx | 6 +- std/flash/display3D/Context3DMipFilter.hx | 8 +- std/flash/display3D/Context3DProfile.hx | 14 +- std/flash/display3D/Context3DProgramType.hx | 6 +- std/flash/display3D/Context3DRenderMode.hx | 6 +- std/flash/display3D/Context3DStencilAction.hx | 18 +- std/flash/display3D/Context3DTextureFilter.hx | 14 +- std/flash/display3D/Context3DTextureFormat.hx | 14 +- std/flash/display3D/Context3DTriangleFace.hx | 10 +- .../display3D/Context3DVertexBufferFormat.hx | 12 +- std/flash/display3D/Context3DWrapMode.hx | 10 +- std/flash/display3D/IndexBuffer3D.hx | 2 +- std/flash/display3D/Program3D.hx | 2 +- std/flash/display3D/textures/CubeTexture.hx | 2 +- .../display3D/textures/RectangleTexture.hx | 2 +- std/flash/display3D/textures/Texture.hx | 2 +- std/flash/display3D/textures/VideoTexture.hx | 8 +- std/flash/errors/DRMManagerError.hx | 3 +- std/flash/errors/Error.hx | 7 +- std/flash/events/AVDictionaryDataEvent.hx | 8 +- std/flash/events/AVHTTPStatusEvent.hx | 13 +- std/flash/events/AVLoadInfoEvent.hx | 5 +- std/flash/events/AVManifestLoadEvent.hx | 14 +- std/flash/events/AVPauseAtPeriodEndEvent.hx | 5 +- std/flash/events/AVPlayStateEvent.hx | 5 +- std/flash/events/AVStatusEvent.hx | 43 +- std/flash/events/AVStreamSwitchEvent.hx | 21 +- std/flash/events/AccelerometerEvent.hx | 18 +- std/flash/events/ActivityEvent.hx | 6 +- std/flash/events/AsyncErrorEvent.hx | 2 +- std/flash/events/AudioOutputChangeEvent.hx | 8 + std/flash/events/ContextMenuEvent.hx | 16 +- std/flash/events/DRMAuthenticateEvent.hx | 24 +- .../events/DRMAuthenticationCompleteEvent.hx | 14 +- .../events/DRMAuthenticationErrorEvent.hx | 14 +- std/flash/events/DRMDeviceGroupErrorEvent.hx | 18 +- std/flash/events/DRMDeviceGroupEvent.hx | 8 +- std/flash/events/DRMErrorEvent.hx | 17 +- std/flash/events/DRMLicenseRequestEvent.hx | 6 +- std/flash/events/DRMMetadataEvent.hx | 8 +- .../events/DRMReturnVoucherCompleteEvent.hx | 18 +- .../events/DRMReturnVoucherErrorEvent.hx | 18 +- std/flash/events/DRMStatusEvent.hx | 14 +- std/flash/events/DataEvent.hx | 8 +- std/flash/events/ErrorEvent.hx | 5 +- std/flash/events/Event.hx | 106 +- std/flash/events/EventPhase.hx | 8 +- std/flash/events/FocusEvent.hx | 24 +- std/flash/events/FullScreenEvent.hx | 10 +- std/flash/events/GameInputEvent.hx | 11 +- std/flash/events/GeolocationEvent.hx | 34 +- std/flash/events/GestureEvent.hx | 32 +- std/flash/events/GesturePhase.hx | 10 +- std/flash/events/HTTPStatusEvent.hx | 19 +- std/flash/events/IMEEvent.hx | 8 +- std/flash/events/IOErrorEvent.hx | 8 +- std/flash/events/KeyboardEvent.hx | 28 +- std/flash/events/MouseEvent.hx | 86 +- std/flash/events/NetDataEvent.hx | 8 +- std/flash/events/NetMonitorEvent.hx | 5 +- std/flash/events/NetStatusEvent.hx | 6 +- std/flash/events/OutputProgressEvent.hx | 10 +- std/flash/events/PressAndTapGestureEvent.hx | 16 +- std/flash/events/ProgressEvent.hx | 12 +- std/flash/events/SampleDataEvent.hx | 10 +- std/flash/events/SecurityErrorEvent.hx | 2 +- std/flash/events/ShaderEvent.hx | 14 +- std/flash/events/SoftKeyboardEvent.hx | 13 +- std/flash/events/SoftKeyboardTrigger.hx | 4 +- .../events/StageVideoAvailabilityEvent.hx | 9 +- std/flash/events/StageVideoEvent.hx | 16 +- std/flash/events/StatusEvent.hx | 10 +- std/flash/events/SyncEvent.hx | 6 +- std/flash/events/TextEvent.hx | 8 +- std/flash/events/ThrottleEvent.hx | 8 +- std/flash/events/ThrottleType.hx | 8 +- std/flash/events/TimerEvent.hx | 4 +- std/flash/events/TouchEvent.hx | 84 +- std/flash/events/TransformGestureEvent.hx | 32 +- std/flash/events/UncaughtErrorEvent.hx | 5 +- std/flash/events/VideoEvent.hx | 13 +- std/flash/events/VideoTextureEvent.hx | 10 +- std/flash/external/ExternalInterface.hx | 8 +- std/flash/filters/BevelFilter.hx | 50 +- std/flash/filters/BitmapFilterType.hx | 8 +- std/flash/filters/BlurFilter.hx | 14 +- std/flash/filters/ColorMatrixFilter.hx | 6 +- std/flash/filters/ConvolutionFilter.hx | 36 +- std/flash/filters/DisplacementMapFilter.hx | 38 +- .../filters/DisplacementMapFilterMode.hx | 10 +- std/flash/filters/DropShadowFilter.hx | 46 +- std/flash/filters/GlowFilter.hx | 34 +- std/flash/filters/GradientBevelFilter.hx | 46 +- std/flash/filters/GradientGlowFilter.hx | 46 +- std/flash/filters/ShaderFilter.hx | 20 +- std/flash/geom/ColorTransform.hx | 4 +- std/flash/geom/Matrix3D.hx | 11 +- std/flash/geom/Orientation3D.hx | 8 +- std/flash/geom/PerspectiveProjection.hx | 12 +- std/flash/geom/Point.hx | 3 +- std/flash/geom/Rectangle.hx | 28 +- std/flash/geom/Transform.hx | 25 +- std/flash/geom/Vector3D.hx | 12 +- std/flash/globalization/Collator.hx | 35 +- std/flash/globalization/CollatorMode.hx | 6 +- std/flash/globalization/CurrencyFormatter.hx | 61 +- .../globalization/CurrencyParseResult.hx | 8 +- std/flash/globalization/DateTimeFormatter.hx | 11 +- .../globalization/DateTimeNameContext.hx | 6 +- std/flash/globalization/DateTimeNameStyle.hx | 8 +- std/flash/globalization/DateTimeStyle.hx | 12 +- .../globalization/LastOperationStatus.hx | 36 +- std/flash/globalization/LocaleID.hx | 10 +- std/flash/globalization/NationalDigitsType.hx | 66 +- std/flash/globalization/NumberFormatter.hx | 51 +- std/flash/globalization/NumberParseResult.hx | 11 +- std/flash/globalization/StringTools.hx | 11 +- std/flash/media/AVABRParameters.hx | 22 +- std/flash/media/AVABRProfileInfo.hx | 9 +- std/flash/media/AVCaptionStyle.hx | 122 +- std/flash/media/AVCuePoint.hx | 6 +- std/flash/media/AVInsertionResult.hx | 6 +- std/flash/media/AVNetworkingParams.hx | 20 +- std/flash/media/AVPeriodInfo.hx | 30 +- std/flash/media/AVPlayState.hx | 21 +- std/flash/media/AVResult.hx | 205 +- std/flash/media/AVSegmentedSource.hx | 36 +- std/flash/media/AVStream.hx | 60 +- std/flash/media/AVTagData.hx | 6 +- std/flash/media/AVTimeline.hx | 24 +- std/flash/media/AVTrackInfo.hx | 30 +- std/flash/media/AVURLLoader.hx | 3 +- std/flash/media/AVURLStream.hx | 3 +- std/flash/media/AudioDecoder.hx | 12 +- std/flash/media/AudioDeviceManager.hx | 14 + std/flash/media/AudioOutputChangeReason.hx | 7 + std/flash/media/Camera.hx | 55 +- std/flash/media/H264Level.hx | 32 +- std/flash/media/H264Profile.hx | 4 +- std/flash/media/H264VideoStreamSettings.hx | 6 +- std/flash/media/ID3Info.hx | 2 +- std/flash/media/Microphone.hx | 65 +- std/flash/media/MicrophoneEnhancedMode.hx | 12 +- std/flash/media/MicrophoneEnhancedOptions.hx | 22 +- std/flash/media/Sound.hx | 21 +- std/flash/media/SoundChannel.hx | 15 +- std/flash/media/SoundCodec.hx | 10 +- std/flash/media/SoundMixer.hx | 16 +- std/flash/media/SoundTransform.hx | 26 +- std/flash/media/StageVideo.hx | 25 +- std/flash/media/StageVideoAvailability.hx | 4 +- .../media/StageVideoAvailabilityReason.hx | 10 +- std/flash/media/Video.hx | 14 +- std/flash/media/VideoCodec.hx | 6 +- std/flash/media/VideoStatus.hx | 6 +- std/flash/media/VideoStreamSettings.hx | 21 +- std/flash/net/FileFilter.hx | 14 +- std/flash/net/FileReference.hx | 21 +- std/flash/net/FileReferenceList.hx | 3 +- std/flash/net/GroupSpecifier.hx | 35 +- std/flash/net/LocalConnection.hx | 20 +- std/flash/net/NetConnection.hx | 54 +- std/flash/net/NetGroup.hx | 23 +- std/flash/net/NetGroupInfo.hx | 26 +- std/flash/net/NetGroupReceiveMode.hx | 4 +- std/flash/net/NetGroupReplicationStrategy.hx | 4 +- std/flash/net/NetGroupSendMode.hx | 4 +- std/flash/net/NetGroupSendResult.hx | 6 +- std/flash/net/NetStream.hx | 147 +- std/flash/net/NetStreamAppendBytesAction.hx | 6 +- std/flash/net/NetStreamInfo.hx | 77 +- std/flash/net/NetStreamMulticastInfo.hx | 59 +- std/flash/net/ObjectEncoding.hx | 10 +- std/flash/net/SecureSocket.hx | 9 +- std/flash/net/SharedObject.hx | 27 +- std/flash/net/SharedObjectFlushStatus.hx | 4 +- std/flash/net/Socket.hx | 21 +- std/flash/net/URLLoaderDataFormat.hx | 8 +- std/flash/net/URLRequest.hx | 26 +- std/flash/net/URLRequestHeader.hx | 2 +- std/flash/net/URLRequestMethod.hx | 12 +- std/flash/net/URLStream.hx | 24 +- std/flash/net/XMLSocket.hx | 7 +- std/flash/net/drm/AddToDeviceGroupSetting.hx | 6 +- std/flash/net/drm/AuthenticationMethod.hx | 4 +- std/flash/net/drm/DRMAuthenticationContext.hx | 3 +- std/flash/net/drm/DRMContentData.hx | 12 +- std/flash/net/drm/DRMDeviceGroup.hx | 15 +- std/flash/net/drm/DRMManager.hx | 11 +- std/flash/net/drm/DRMManagerSession.hx | 12 +- std/flash/net/drm/DRMPlaybackTimeWindow.hx | 9 +- std/flash/net/drm/DRMVoucher.hx | 27 +- .../net/drm/DRMVoucherDownloadContext.hx | 3 +- std/flash/net/drm/DRMVoucherStoreContext.hx | 3 +- std/flash/net/drm/LoadVoucherSetting.hx | 6 +- std/flash/net/drm/VoucherAccessInfo.hx | 17 +- std/flash/printing/PrintJob.hx | 18 +- std/flash/printing/PrintJobOrientation.hx | 6 +- std/flash/profiler/Telemetry.hx | 6 +- std/flash/sampler/ClassFactory.hx | 8 +- std/flash/sampler/DeleteObjectSample.hx | 6 +- std/flash/sampler/NewObjectSample.hx | 12 +- std/flash/sampler/Sample.hx | 4 +- std/flash/sampler/StackFrame.hx | 10 +- std/flash/security/CertificateStatus.hx | 18 +- std/flash/security/X500DistinguishedName.hx | 18 +- std/flash/security/X509Certificate.hx | 39 +- std/flash/sensors/Accelerometer.hx | 6 +- std/flash/sensors/Geolocation.hx | 6 +- std/flash/system/ApplicationDomain.hx | 15 +- std/flash/system/ApplicationInstaller.hx | 5 +- std/flash/system/ApplicationInstallerMode.hx | 8 +- std/flash/system/AuthorizedFeatures.hx | 6 +- std/flash/system/AuthorizedFeaturesLoader.hx | 7 +- std/flash/system/Capabilities.hx | 104 +- std/flash/system/ConnexionsClient.hx | 2 +- std/flash/system/IME.hx | 11 +- std/flash/system/IMEConversionMode.hx | 18 +- std/flash/system/ImageDecodingPolicy.hx | 6 +- std/flash/system/LoaderContext.hx | 4 +- std/flash/system/MessageChannel.hx | 8 +- std/flash/system/MessageChannelState.hx | 9 +- std/flash/system/Security.hx | 32 +- std/flash/system/SecurityDomain.hx | 6 +- std/flash/system/SecurityPanel.hx | 16 +- std/flash/system/System.hx | 25 +- std/flash/system/SystemUpdaterType.hx | 6 +- std/flash/system/TouchscreenType.hx | 8 +- std/flash/system/Worker.hx | 14 +- std/flash/system/WorkerDomain.hx | 8 +- std/flash/system/WorkerState.hx | 8 +- std/flash/text/AntiAliasType.hx | 6 +- std/flash/text/CSMSettings.hx | 2 +- std/flash/text/Font.hx | 9 +- std/flash/text/FontStyle.hx | 10 +- std/flash/text/FontType.hx | 8 +- std/flash/text/GridFitType.hx | 8 +- std/flash/text/StaticText.hx | 5 +- std/flash/text/StyleSheet.hx | 3 +- std/flash/text/TextColorType.hx | 6 +- std/flash/text/TextDisplayMode.hx | 8 +- std/flash/text/TextField.hx | 152 +- std/flash/text/TextFieldAutoSize.hx | 10 +- std/flash/text/TextFieldType.hx | 6 +- std/flash/text/TextFormat.hx | 76 +- std/flash/text/TextFormatAlign.hx | 14 +- std/flash/text/TextFormatDisplay.hx | 6 +- std/flash/text/TextInteractionMode.hx | 6 +- std/flash/text/TextRenderer.hx | 12 +- std/flash/text/TextSnapshot.hx | 3 +- std/flash/text/engine/BreakOpportunity.hx | 10 +- std/flash/text/engine/CFFHinting.hx | 6 +- std/flash/text/engine/ContentElement.hx | 29 +- std/flash/text/engine/DigitCase.hx | 8 +- std/flash/text/engine/DigitWidth.hx | 8 +- std/flash/text/engine/EastAsianJustifier.hx | 10 +- std/flash/text/engine/ElementFormat.hx | 74 +- std/flash/text/engine/FontDescription.hx | 30 +- std/flash/text/engine/FontLookup.hx | 6 +- std/flash/text/engine/FontMetrics.hx | 2 +- std/flash/text/engine/FontPosture.hx | 6 +- std/flash/text/engine/FontWeight.hx | 6 +- std/flash/text/engine/GraphicElement.hx | 14 +- std/flash/text/engine/GroupElement.hx | 5 +- std/flash/text/engine/JustificationStyle.hx | 8 +- std/flash/text/engine/Kerning.hx | 8 +- std/flash/text/engine/LigatureLevel.hx | 12 +- std/flash/text/engine/LineJustification.hx | 10 +- std/flash/text/engine/RenderingMode.hx | 6 +- std/flash/text/engine/SpaceJustifier.hx | 18 +- std/flash/text/engine/TabAlignment.hx | 10 +- std/flash/text/engine/TabStop.hx | 14 +- std/flash/text/engine/TextBaseline.hx | 16 +- std/flash/text/engine/TextBlock.hx | 50 +- std/flash/text/engine/TextElement.hx | 3 +- std/flash/text/engine/TextJustifier.hx | 7 +- std/flash/text/engine/TextLine.hx | 62 +- .../text/engine/TextLineCreationResult.hx | 10 +- std/flash/text/engine/TextLineMirrorRegion.hx | 20 +- std/flash/text/engine/TextLineValidity.hx | 10 +- std/flash/text/engine/TextRotation.hx | 12 +- std/flash/text/engine/TypographicCase.hx | 16 +- .../text/ime/CompositionAttributeRange.hx | 2 +- std/flash/text/ime/IIMEClient.hx | 15 +- std/flash/trace/Trace.hx | 14 +- std/flash/ui/ContextMenu.hx | 25 +- std/flash/ui/ContextMenuBuiltInItems.hx | 34 +- std/flash/ui/ContextMenuClipboardItems.hx | 22 +- std/flash/ui/ContextMenuItem.hx | 14 +- std/flash/ui/GameInput.hx | 6 +- std/flash/ui/GameInputControl.hx | 15 +- std/flash/ui/GameInputControlType.hx | 14 +- std/flash/ui/GameInputDevice.hx | 21 +- std/flash/ui/GameInputFinger.hx | 10 +- std/flash/ui/GameInputHand.hx | 8 +- std/flash/ui/KeyLocation.hx | 12 +- std/flash/ui/Keyboard.hx | 566 +-- std/flash/ui/KeyboardType.hx | 8 +- std/flash/ui/Mouse.hx | 10 +- std/flash/ui/MouseCursor.hx | 10 +- std/flash/ui/MouseCursorData.hx | 14 +- std/flash/ui/Multitouch.hx | 20 +- std/flash/ui/MultitouchInputMode.hx | 8 +- std/flash/utils/ByteArray.hx | 27 +- std/flash/utils/CompressionAlgorithm.hx | 8 +- std/flash/utils/Endian.hx | 6 +- std/flash/utils/IDataInput.hx | 11 +- std/flash/utils/IDataOutput.hx | 8 +- std/flash/utils/Namespace.hx | 8 +- std/flash/utils/Object.hx | 3 +- std/flash/utils/ObjectInput.hx | 11 +- std/flash/utils/ObjectOutput.hx | 8 +- std/flash/utils/Proxy.hx | 2 +- std/flash/utils/QName.hx | 8 +- std/flash/utils/RegExp.hx | 22 +- std/flash/utils/SetIntervalTimer.hx | 6 +- std/flash/utils/Timer.hx | 14 +- std/flash/xml/XML.hx | 22 +- std/flash/xml/XMLList.hx | 2 +- std/flash/xml/XMLNode.hx | 16 +- std/flash/xml/XMLNodeType.hx | 16 +- std/flash/xml/XMLParser.hx | 2 +- std/flash/xml/XMLTag.hx | 18 +- std/haxe/CallStack.hx | 531 +-- std/haxe/Constraints.hx | 20 +- std/haxe/DynamicAccess.hx | 52 +- std/haxe/EntryPoint.hx | 92 +- std/haxe/EnumFlags.hx | 14 +- std/haxe/EnumTools.hx | 47 +- std/haxe/Http.hx | 829 +--- std/haxe/Int32.hx | 140 +- std/haxe/Int64.hx | 310 +- std/haxe/Int64Helper.hx | 15 +- std/haxe/Json.hx | 11 +- std/haxe/Log.hx | 33 +- std/haxe/MainLoop.hx | 91 +- std/haxe/PosInfos.hx | 15 +- std/haxe/Resource.hx | 31 +- std/haxe/Serializer.hx | 676 +-- std/haxe/SysTools.hx | 106 + std/haxe/Template.hx | 481 +- std/haxe/Timer.hx | 101 +- std/haxe/Ucs2.hx | 45 +- std/haxe/Unserializer.hx | 642 +-- std/haxe/Utf8.hx | 38 +- std/haxe/crypto/Adler32.hx | 28 +- std/haxe/crypto/Base64.hx | 50 +- std/haxe/crypto/BaseCode.hx | 67 +- std/haxe/crypto/Crc32.hx | 58 +- std/haxe/crypto/Hmac.hx | 47 +- std/haxe/crypto/Md5.hx | 264 +- std/haxe/crypto/Sha1.hx | 89 +- std/haxe/crypto/Sha224.hx | 343 +- std/haxe/crypto/Sha256.hx | 143 +- std/haxe/display/Display.hx | 507 +++ std/haxe/display/FsPath.hx | 33 + std/haxe/display/JsonModuleTypes.hx | 371 ++ std/haxe/display/Position.hx | 47 +- std/haxe/display/Protocol.hx | 111 + std/haxe/display/Server.hx | 142 + std/haxe/ds/ArraySort.hx | 23 +- std/haxe/ds/BalancedTree.hx | 116 +- std/haxe/ds/Either.hx | 4 +- std/haxe/ds/EnumValueMap.hx | 25 +- std/haxe/ds/GenericStack.hx | 98 +- std/haxe/ds/HashMap.hx | 14 +- std/haxe/ds/IntMap.hx | 44 +- std/haxe/ds/List.hx | 117 +- std/haxe/ds/ListSort.hx | 57 +- std/haxe/ds/Map.hx | 70 +- std/haxe/ds/ObjectMap.hx | 28 +- std/haxe/ds/Option.hx | 4 +- std/haxe/ds/ReadOnlyArray.hx | 45 + std/haxe/ds/StringMap.hx | 43 +- std/haxe/ds/Vector.hx | 164 +- std/haxe/ds/WeakMap.hx | 21 +- std/haxe/extern/AsVar.hx | 6 +- std/haxe/extern/EitherType.hx | 7 +- std/haxe/extern/Rest.hx | 4 +- std/haxe/format/JsonParser.hx | 369 +- std/haxe/format/JsonPrinter.hx | 271 +- std/haxe/http/HttpBase.hx | 250 ++ std/haxe/http/HttpJs.hx | 160 + std/haxe/http/HttpMethod.hx | 84 + std/haxe/http/HttpNodeJs.hx | 119 + std/haxe/http/HttpStatus.hx | 68 + std/haxe/io/ArrayBufferView.hx | 82 +- std/haxe/io/BufferInput.hx | 27 +- std/haxe/io/Bytes.hx | 498 ++- std/haxe/io/BytesBuffer.hx | 141 +- std/haxe/io/BytesData.hx | 63 +- std/haxe/io/BytesInput.hx | 179 +- std/haxe/io/BytesOutput.hx | 59 +- .../Environ.hx => haxe/io/Encoding.hx} | 21 +- std/haxe/io/Eof.hx | 6 +- std/haxe/io/Error.hx | 8 +- std/haxe/io/FPHelper.hx | 494 ++- std/haxe/io/Float32Array.hx | 50 +- std/haxe/io/Float64Array.hx | 50 +- std/haxe/io/Input.hx | 173 +- std/haxe/io/Int32Array.hx | 50 +- std/haxe/io/Mime.hx | 321 ++ std/haxe/io/Output.hx | 144 +- std/haxe/io/Path.hx | 170 +- std/haxe/io/Scheme.hx | 18 + std/haxe/io/StringInput.hx | 13 +- std/haxe/io/UInt16Array.hx | 50 +- std/haxe/io/UInt32Array.hx | 50 +- std/haxe/io/UInt8Array.hx | 47 +- std/haxe/iterators/DynamicAccessIterator.hx | 52 + .../DynamicAccessKeyValueIterator.hx | 53 + std/haxe/iterators/MapKeyValueIterator.hx | 54 + std/haxe/iterators/StringIterator.hx | 55 + std/haxe/iterators/StringIteratorUnicode.hx | 73 + std/haxe/iterators/StringKeyValueIterator.hx | 55 + .../StringKeyValueIteratorUnicode.hx | 76 + std/haxe/macro/CompilationServer.hx | 40 +- std/haxe/macro/Compiler.hx | 299 +- std/haxe/macro/ComplexTypeTools.hx | 13 +- std/haxe/macro/Context.hl.hx | 243 - std/haxe/macro/Context.hx | 309 +- std/haxe/macro/ExampleJSGenerator.hx | 161 +- std/haxe/macro/Expr.hx | 253 +- std/haxe/macro/ExprTools.hx | 179 +- std/haxe/macro/Format.hx | 68 +- std/haxe/macro/JSGenApi.hx | 39 +- std/haxe/macro/MacroStringTools.hx | 34 +- std/haxe/macro/MacroType.hx | 6 +- std/haxe/macro/PositionTools.hx | 18 +- std/haxe/macro/Printer.hx | 627 ++- std/haxe/macro/Tools.hx | 7 +- std/haxe/macro/Type.hx | 254 +- std/haxe/macro/TypeTools.hx | 273 +- std/haxe/macro/TypedExprTools.hx | 63 +- std/haxe/remoting/AMFConnection.hx | 90 - std/haxe/remoting/AsyncDebugConnection.hx | 88 - std/haxe/remoting/Context.hx | 64 - std/haxe/remoting/ContextAll.hx | 63 - std/haxe/remoting/DelayedConnection.hx | 90 - std/haxe/remoting/ExternalConnection.hx | 142 - std/haxe/remoting/FlashJsConnection.hx | 156 - std/haxe/remoting/HttpAsyncConnection.hx | 80 - std/haxe/remoting/HttpConnection.hx | 113 - std/haxe/remoting/LocalConnection.hx | 141 - std/haxe/remoting/SocketConnection.hx | 178 - std/haxe/remoting/SocketProtocol.hx | 209 - std/haxe/remoting/SocketWrapper.hx | 75 - std/haxe/remoting/SyncSocketConnection.hx | 82 - std/haxe/rtti/CType.hx | 357 +- std/haxe/rtti/Meta.hx | 51 +- std/haxe/rtti/Rtti.hx | 20 +- std/haxe/rtti/XmlParser.hx | 702 +-- std/haxe/xml/Access.hx | 243 + std/haxe/xml/Check.hx | 470 +- std/haxe/xml/Fast.hx | 208 +- std/haxe/xml/Parser.hx | 239 +- std/haxe/xml/Printer.hx | 8 +- std/haxe/xml/Proxy.hx | 11 +- std/haxe/zip/Compress.hx | 17 +- std/haxe/zip/Entry.hx | 26 +- std/haxe/zip/FlushMode.hx | 3 +- std/haxe/zip/Huffman.hx | 98 +- std/haxe/zip/InflateImpl.hx | 410 +- std/haxe/zip/Reader.hx | 126 +- std/haxe/zip/Tools.hx | 13 +- std/haxe/zip/Uncompress.hx | 19 +- std/haxe/zip/Writer.hx | 145 +- std/hl/Abstract.hx | 6 +- std/hl/Api.hx | 37 +- std/hl/BaseType.hx | 43 +- std/hl/Boot.hx | 6 +- std/hl/Bytes.hx | 135 +- std/hl/BytesAccess.hx | 28 +- std/hl/F32.hx | 5 +- std/hl/F64.hx | 3 +- std/hl/Format.hx | 85 +- std/hl/Gc.hx | 48 +- std/hl/I64.hx | 3 +- std/hl/NativeArray.hx | 36 +- std/hl/Profile.hx | 230 +- std/hl/Ref.hx | 22 +- std/hl/Type.hx | 44 +- std/hl/UI.hx | 166 +- std/hl/UI16.hx | 3 +- std/hl/UI8.hx | 3 +- std/hl/_std/Date.hx | 120 +- std/hl/_std/EReg.hx | 118 +- std/hl/_std/Math.hx | 113 +- std/hl/_std/Reflect.hx | 117 +- std/hl/_std/Std.hx | 141 +- std/hl/_std/String.hx | 199 +- std/hl/_std/StringBuf.hx | 73 +- std/hl/_std/Sys.hx | 190 +- std/hl/_std/Type.hx | 213 +- std/hl/_std/UInt.hx | 24 +- std/hl/_std/haxe/Resource.hx | 29 +- .../Log.hx => hl/_std/haxe/crypto/Md5.hx} | 29 +- std/hl/_std/haxe/crypto/Sha1.hx | 37 + std/hl/_std/haxe/ds/IntMap.hx | 41 +- std/hl/_std/haxe/ds/ObjectMap.hx | 41 +- std/hl/_std/haxe/ds/StringMap.hx | 59 +- std/hl/_std/haxe/ds/Vector.hx | 11 +- std/hl/_std/haxe/io/Bytes.hx | 206 +- std/hl/_std/haxe/io/BytesBuffer.hx | 81 +- std/hl/_std/haxe/io/FPHelper.hx | 23 +- std/hl/_std/haxe/zip/Compress.hx | 42 +- std/hl/_std/haxe/zip/Uncompress.hx | 46 +- std/hl/_std/sys/FileSystem.hx | 118 +- std/hl/_std/sys/db/Connection.hx | 36 + std/hl/_std/sys/db/Mysql.hx | 250 ++ std/hl/_std/sys/db/ResultSet.hx | 36 + std/hl/_std/sys/db/Sqlite.hx | 297 +- std/hl/_std/sys/io/File.hx | 65 +- std/hl/_std/sys/io/FileInput.hx | 65 +- std/hl/_std/sys/io/FileOutput.hx | 55 +- std/hl/_std/sys/io/Process.hx | 143 +- std/hl/_std/sys/net/Host.hx | 39 +- std/hl/_std/sys/net/Socket.hx | 262 +- std/hl/_std/sys/net/UdpSocket.hx | 81 + std/hl/_std/sys/ssl/Certificate.hx | 182 +- std/hl/_std/sys/ssl/Context.hx | 98 + std/hl/_std/sys/ssl/Digest.hx | 59 +- std/hl/_std/sys/ssl/Key.hx | 60 +- std/hl/_std/sys/ssl/Lib.hx | 28 +- std/hl/_std/sys/ssl/Socket.hx | 271 +- std/hl/_std/sys/thread/Deque.hx | 52 + .../Log.hx => hl/_std/sys/thread/Lock.hx} | 41 +- std/hl/_std/sys/thread/Mutex.hx | 52 + .../_std/sys/thread/Thread.hx} | 64 +- std/hl/_std/sys/thread/Tls.hx | 58 + std/hl/hl_version | 1 + std/hl/types/ArrayBase.hx | 62 +- std/hl/types/ArrayBytes.hx | 246 +- std/hl/types/ArrayDyn.hx | 140 +- std/hl/types/ArrayObj.hx | 241 +- std/hl/types/BytesMap.hx | 38 +- std/hl/types/IntMap.hx | 38 +- std/hl/types/ObjectMap.hx | 38 +- std/hl/uv/Handle.hx | 33 +- std/hl/uv/HandleData.hx | 22 + std/hl/uv/Loop.hx | 61 +- std/hl/uv/Stream.hx | 63 +- std/hl/uv/Tcp.hx | 57 +- std/java/Boot.hx | 14 +- std/java/Init.hx | 31 + std/java/Lib.hx | 73 +- std/java/NativeArray.hx | 12 +- std/java/NativeString.hx | 99 + std/java/StdTypes.hx | 89 +- std/java/_std/Array.hx | 287 +- std/java/_std/Date.hx | 143 +- std/java/_std/EReg.hx | 101 +- std/java/_std/Math.hx | 30 +- std/java/_std/Reflect.hx | 69 +- std/java/_std/Std.hx | 92 +- std/java/_std/String.hx | 44 +- std/java/_std/StringBuf.hx | 39 +- std/java/_std/Sys.hx | 102 +- std/java/_std/Type.hx | 131 +- std/java/_std/haxe/Int64.hx | 179 +- std/java/_std/haxe/Resource.hx | 12 +- std/java/_std/haxe/ds/IntMap.hx | 323 +- std/java/_std/haxe/ds/ObjectMap.hx | 326 +- std/java/_std/haxe/ds/StringMap.hx | 341 +- std/java/_std/haxe/ds/WeakMap.hx | 366 +- std/java/_std/haxe/zip/Compress.hx | 26 +- std/java/_std/haxe/zip/Uncompress.hx | 36 +- std/java/_std/sys/FileSystem.hx | 64 +- std/java/_std/sys/db/Mysql.hx | 27 +- std/java/_std/sys/db/Sqlite.hx | 30 +- std/java/_std/sys/io/File.hx | 84 +- std/java/_std/sys/io/FileInput.hx | 80 +- std/java/_std/sys/io/FileOutput.hx | 81 +- std/java/_std/sys/io/Process.hx | 96 +- std/java/_std/sys/net/Host.hx | 33 +- std/java/_std/sys/net/Socket.hx | 130 +- .../Log.hx => java/_std/sys/thread/Deque.hx} | 38 +- std/java/_std/sys/thread/Lock.hx | 78 + std/java/_std/sys/thread/Mutex.hx | 46 + std/java/_std/sys/thread/Thread.hx | 111 + .../Log.hx => java/_std/sys/thread/Tls.hx} | 28 +- std/java/db/Jdbc.hx | 261 +- std/java/internal/Exceptions.hx | 45 +- std/java/internal/FieldLookup.hx | 72 +- std/java/internal/Function.hx | 42 +- std/java/internal/HxObject.hx | 246 +- std/java/internal/IEquatable.hx | 8 +- std/java/internal/Runtime.hx | 87 +- std/java/internal/StringExt.hx | 74 +- std/java/io/NativeInput.hx | 45 +- std/java/io/NativeOutput.hx | 44 +- std/java/lang/Boolean.hx | 50 +- std/java/lang/Byte.hx | 58 +- std/java/lang/Character.hx | 765 ++-- std/java/lang/Double.hx | 76 +- std/java/lang/Float.hx | 80 +- std/java/lang/Integer.hx | 92 +- std/java/lang/Long.hx | 92 +- std/java/lang/Short.hx | 60 +- std/java/net/SslSocket.hx | 14 +- std/java/types/Char16.hx | 5 +- std/java/types/Int16.hx | 5 +- std/java/types/Int8.hx | 5 +- std/java/vm/AtomicList.hx | 46 +- std/java/vm/Deque.hx | 75 +- std/java/vm/Gc.hx | 16 +- std/java/vm/Lock.hx | 86 +- std/java/vm/Mutex.hx | 43 +- std/java/vm/Thread.hx | 92 +- std/java/vm/Tls.hx | 29 +- std/js/Boot.hx | 309 +- std/js/Browser.hx | 56 +- std/js/Cookie.hx | 37 +- std/js/Error.hx | 55 +- std/js/Function.hx | 32 +- std/js/JsIterator.hx | 26 + std/js/Lib.hx | 62 +- std/js/Object.hx | 49 +- std/js/Promise.hx | 35 +- std/js/RegExp.hx | 28 +- std/js/Selection.hx | 49 +- std/js/Set.hx | 25 + std/js/Symbol.hx | 42 +- std/js/Syntax.hx | 86 + std/js/_std/Array.hx | 68 +- std/js/_std/Date.hx | 44 +- std/js/_std/EReg.hx | 65 +- std/js/_std/HxOverrides.hx | 124 +- std/js/_std/Math.hx | 35 +- std/js/_std/Reflect.hx | 108 +- std/js/_std/Std.hx | 109 +- std/js/_std/String.hx | 35 +- std/js/_std/Type.hx | 390 +- std/js/_std/haxe/Json.hx | 37 +- std/js/_std/haxe/Log.hx | 35 - std/js/_std/haxe/ds/IntMap.hx | 66 +- std/js/_std/haxe/ds/ObjectMap.hx | 86 +- std/js/_std/haxe/ds/StringMap.hx | 111 +- std/js/_std/haxe/io/ArrayBufferView.hx | 44 +- std/js/_std/haxe/io/Bytes.hx | 218 +- std/js/_std/haxe/io/BytesBuffer.hx | 88 +- std/js/_std/haxe/io/Float32Array.hx | 53 +- std/js/_std/haxe/io/Float64Array.hx | 53 +- std/js/_std/haxe/io/Int32Array.hx | 54 +- std/js/_std/haxe/io/UInt16Array.hx | 52 +- std/js/_std/haxe/io/UInt32Array.hx | 52 +- std/js/_std/haxe/io/UInt8Array.hx | 52 +- std/js/html/AbortController.hx | 49 + std/js/html/AbortSignal.hx | 47 + std/js/html/AddEventListenerOptions.hx | 30 + std/js/html/AlignSetting.hx | 7 +- std/js/html/AnchorElement.hx | 16 +- std/js/html/Animation.hx | 65 +- ...ApplicationCache.hx => AnimationEffect.hx} | 39 +- std/js/html/AnimationEffectTimingReadOnly.hx | 78 - std/js/html/AnimationEvent.hx | 5 +- std/js/html/AnimationEventInit.hx | 12 +- .../{CSSUnknownRule.hx => AnimationFilter.hx} | 9 +- std/js/html/AnimationPlayState.hx | 6 +- ...ectTiming.hx => AnimationPlaybackEvent.hx} | 20 +- std/js/html/AnimationPlaybackEventInit.hx | 30 + std/js/html/AnimationTimeline.hx | 5 +- std/js/html/AreaElement.hx | 10 +- std/js/html/ArrayBuffer.hx | 18 +- std/js/html/ArrayBufferView.hx | 20 +- std/js/html/AssignedNodesOptions.hx | 29 + std/js/html/Attr.hx | 46 +- std/js/html/Audio.hx | 5 +- std/js/html/AudioElement.hx | 5 +- std/js/html/AudioStreamTrack.hx | 5 +- std/js/html/AudioTrack.hx | 32 +- std/js/html/AudioTrackList.hx | 16 +- std/js/html/AutoKeyword.hx | 29 + std/js/html/BRElement.hx | 5 +- std/js/html/BarProp.hx | 5 +- std/js/html/BaseElement.hx | 5 +- std/js/html/BatteryManager.hx | 5 +- std/js/html/BeforeUnloadEvent.hx | 7 +- std/js/html/BinaryType.hx | 5 +- std/js/html/Blob.hx | 11 +- std/js/html/BlobEvent.hx | 44 + std/js/html/BlobEventInit.hx | 29 + std/js/html/BlobPropertyBag.hx | 9 +- std/js/html/BodyElement.hx | 8 +- std/js/html/BroadcastChannel.hx | 14 +- std/js/html/ButtonElement.hx | 31 +- std/js/html/CDATASection.hx | 7 +- std/js/html/CSS.hx | 15 +- std/js/html/CSSAnimation.hx | 5 +- ...ntRegistrationOptions.hx => CSSBoxType.hx} | 14 +- std/js/html/CSSConditionRule.hx | 42 + std/js/html/CSSCounterStyleRule.hx | 92 + std/js/html/CSSFontFaceRule.hx | 7 +- std/js/html/CSSFontFeatureValuesRule.hx | 32 + std/js/html/CSSGroupingRule.hx | 42 + std/js/html/CSSImportRule.hx | 7 +- std/js/html/{Rect.hx => CSSKeyframeRule.hx} | 22 +- std/js/html/CSSKeyframesRule.hx | 62 + std/js/html/CSSMediaRule.hx | 10 +- std/js/html/CSSMozDocumentRule.hx | 29 + std/js/html/CSSNamespaceRule.hx | 47 + std/js/html/CSSPageRule.hx | 12 +- std/js/html/CSSPrimitiveValue.hx | 225 - std/js/html/CSSPseudoElement.hx | 10 +- std/js/html/CSSRule.hx | 16 +- std/js/html/CSSRuleList.hx | 5 +- std/js/html/CSSStyleDeclaration.hx | 257 +- std/js/html/CSSStyleRule.hx | 15 +- std/js/html/CSSStyleSheet.hx | 33 +- std/js/html/CSSSupportsRule.hx | 36 + std/js/html/CSSTransition.hx | 5 +- std/js/html/CSSValue.hx | 78 - std/js/html/Cache.hx | 51 + std/js/html/CacheQueryOptions.hx | 32 + std/js/html/CacheStorage.hx | 66 + std/js/html/CacheStorageNamespace.hx | 30 + std/js/html/CanvasCaptureMediaStream.hx | 32 + std/js/html/CanvasElement.hx | 29 +- std/js/html/CanvasGradient.hx | 7 +- std/js/html/CanvasPattern.hx | 7 +- std/js/html/CanvasRenderingContext2D.hx | 109 +- std/js/html/CanvasWindingRule.hx | 5 +- std/js/html/CaretPosition.hx | 5 +- std/js/html/ChannelPixelLayout.hx | 34 + ...Event.hx => ChannelPixelLayoutDataType.hx} | 19 +- std/js/html/CharacterData.hx | 26 +- std/js/html/Client.hx | 20 +- std/js/html/ClientQueryOptions.hx | 9 +- std/js/html/ClientType.hx | 33 + std/js/html/Clients.hx | 26 +- std/js/html/Clipboard.hx | 62 + std/js/html/ClipboardEvent.hx | 5 +- std/js/html/ClipboardEventInit.hx | 10 +- std/js/html/CloseEvent.hx | 237 +- std/js/html/CloseEventInit.hx | 12 +- std/js/html/Comment.hx | 7 +- std/js/html/CompositeOperation.hx | 7 +- std/js/html/CompositionEvent.hx | 21 +- ...orEventInit.hx => CompositionEventInit.hx} | 10 +- ...agePortList.hx => ComputedEffectTiming.hx} | 16 +- std/js/html/Console.hx | 104 +- std/js/html/ConsoleInstance.hx | 154 + std/js/html/ConstrainBooleanParameters.hx | 30 + std/js/html/ConstrainDOMStringParameters.hx | 30 + std/js/html/ConstrainDoubleRange.hx | 32 + std/js/html/ConstrainLongRange.hx | 32 + std/js/html/ConvertCoordinateOptions.hx | 9 +- std/js/html/Coordinates.hx | 8 +- std/js/html/Crypto.hx | 13 +- std/js/html/CryptoKey.hx | 5 +- std/js/html/CustomEvent.hx | 8 +- std/js/html/CustomEventInit.hx | 8 +- std/js/html/DListElement.hx | 5 +- std/js/html/DOMElement.hx | 389 +- std/js/html/DOMError.hx | 11 +- std/js/html/DOMException.hx | 27 +- std/js/html/DOMImplementation.hx | 15 +- std/js/html/DOMMatrix.hx | 21 +- std/js/html/DOMMatrixReadOnly.hx | 115 +- std/js/html/DOMParser.hx | 10 +- std/js/html/DOMPoint.hx | 11 +- std/js/html/DOMPointInit.hx | 36 +- std/js/html/DOMPointReadOnly.hx | 23 +- std/js/html/DOMQuad.hx | 26 +- std/js/html/DOMQuadJSON.hx | 32 + std/js/html/DOMRect.hx | 8 +- std/js/html/DOMRectList.hx | 5 +- std/js/html/DOMRectReadOnly.hx | 8 +- std/js/html/DOMRequest.hx | 7 +- std/js/html/DOMRequestReadyState.hx | 5 +- std/js/html/DOMStringList.hx | 5 +- std/js/html/DOMStringMap.hx | 5 +- std/js/html/DOMTokenList.hx | 40 +- std/js/html/DataElement.hx | 5 +- std/js/html/DataListElement.hx | 5 +- std/js/html/DataTransfer.hx | 23 +- std/js/html/DataTransferItem.hx | 59 + std/js/html/DataTransferItemList.hx | 61 + std/js/html/DataView.hx | 30 +- std/js/html/DedicatedWorkerGlobalScope.hx | 26 +- .../{ContentElement.hx => DetailsElement.hx} | 24 +- std/js/html/DeviceAcceleration.hx | 6 +- std/js/html/DeviceAccelerationInit.hx | 11 +- std/js/html/DeviceMotionEvent.hx | 9 +- std/js/html/DeviceMotionEventInit.hx | 14 +- std/js/html/DeviceOrientationEvent.hx | 9 +- std/js/html/DeviceOrientationEventInit.hx | 14 +- std/js/html/DeviceRotationRate.hx | 18 +- std/js/html/DeviceRotationRateInit.hx | 11 +- std/js/html/DirectionSetting.hx | 5 +- std/js/html/Directory.hx | 14 +- std/js/html/DirectoryElement.hx | 5 +- std/js/html/DisplayNameOptions.hx | 30 + std/js/html/DisplayNameResult.hx | 31 + std/js/html/DivElement.hx | 5 +- std/js/html/Document.hx | 295 +- std/js/html/DocumentFragment.hx | 17 +- std/js/html/DocumentTimeline.hx | 7 +- std/js/html/DocumentTimelineOptions.hx | 29 + std/js/html/DocumentType.hx | 20 +- std/js/html/DragEvent.hx | 11 +- std/js/html/DragEventInit.hx | 8 +- std/js/html/EffectTiming.hx | 75 + std/js/html/Element.hx | 22 +- std/js/html/ElementCreationOptions.hx | 29 + std/js/html/EmbedElement.hx | 9 +- .../{CSSCharsetRule.hx => EndingTypes.hx} | 12 +- std/js/html/ErrorCallback.hx | 29 + std/js/html/ErrorEvent.hx | 5 +- std/js/html/ErrorEventInit.hx | 16 +- std/js/html/Event.hx | 40 +- std/js/html/EventInit.hx | 10 +- std/js/html/EventListener.hx | 14 +- std/js/html/EventListenerOptions.hx | 29 + std/js/html/EventModifierInit.hx | 32 +- std/js/html/EventSource.hx | 19 +- std/js/html/EventSourceInit.hx | 7 +- std/js/html/EventTarget.hx | 19 +- std/js/html/Exception.hx | 10 +- std/js/html/ExtendableEvent.hx | 7 +- std/js/html/ExtendableEventInit.hx | 6 +- std/js/html/ExtendableMessageEvent.hx | 7 +- std/js/html/ExtendableMessageEventInit.hx | 16 +- std/js/html/External.hx | 7 +- std/js/html/FetchEvent.hx | 29 +- std/js/html/FetchEventInit.hx | 10 +- ...LifecycleCallbacks.hx => FetchObserver.hx} | 17 +- std/js/html/FetchState.hx | 33 + std/js/html/FieldSetElement.hx | 48 +- std/js/html/File.hx | 15 +- ...ransactionEventInit.hx => FileCallback.hx} | 10 +- std/js/html/FileList.hx | 5 +- std/js/html/FileMode.hx | 5 +- std/js/html/FilePropertyBag.hx | 9 +- std/js/html/FileReader.hx | 30 +- std/js/html/FileReaderSync.hx | 7 +- std/js/html/FileSystem.hx | 47 + std/js/html/FileSystemDirectoryEntry.hx | 43 + std/js/html/FileSystemDirectoryReader.hx | 40 + std/js/html/FileSystemEntriesCallback.hx | 29 + std/js/html/FileSystemEntry.hx | 65 + std/js/html/FileSystemEntryCallback.hx | 29 + std/js/html/FileSystemFileEntry.hx | 39 + std/js/html/FileSystemFlags.hx | 45 + std/js/html/FillMode.hx | 7 +- std/js/html/Float32Array.hx | 24 +- std/js/html/Float64Array.hx | 24 +- std/js/html/FocusEvent.hx | 5 +- std/js/html/FocusEventInit.hx | 8 +- std/js/html/FontElement.hx | 24 +- std/js/html/FontFace.hx | 49 +- std/js/html/FontFaceDescriptors.hx | 20 +- std/js/html/FontFaceLoadStatus.hx | 5 +- std/js/html/FontFaceSet.hx | 34 +- std/js/html/FontFaceSetIterator.hx | 6 +- std/js/html/FontFaceSetIteratorResult.hx | 5 +- std/js/html/FontFaceSetLoadEvent.hx | 44 + std/js/html/FontFaceSetLoadEventInit.hx | 29 + std/js/html/FontFaceSetLoadStatus.hx | 5 +- std/js/html/FormData.hx | 30 +- std/js/html/FormDataIterator.hx | 6 +- std/js/html/FormElement.hx | 74 +- std/js/html/FrameElement.hx | 5 +- std/js/html/FrameSetElement.hx | 12 +- std/js/html/FrameType.hx | 5 +- std/js/html/Gamepad.hx | 7 +- std/js/html/GamepadButton.hx | 6 +- .../html/{CSSValueList.hx => GamepadEvent.hx} | 26 +- ...nterfaceWorkers.hx => GamepadEventInit.hx} | 9 +- std/js/html/GamepadMappingType.hx | 5 +- std/js/html/Geolocation.hx | 10 +- std/js/html/GetNotificationOptions.hx | 29 + std/js/html/GetRootNodeOptions.hx | 29 + std/js/html/GetUserMediaRequest.hx | 9 +- std/js/html/HRElement.hx | 5 +- std/js/html/HTMLAllCollection.hx | 5 +- std/js/html/HTMLCollection.hx | 5 +- std/js/html/HTMLDocument.hx | 169 +- std/js/html/HTMLFormControlsCollection.hx | 12 +- std/js/html/HTMLOptionsCollection.hx | 5 +- std/js/html/HTMLPropertiesCollection.hx | 8 +- std/js/html/HashChangeEvent.hx | 17 +- std/js/html/HashChangeEventInit.hx | 10 +- std/js/html/HeadElement.hx | 5 +- std/js/html/Headers.hx | 46 +- std/js/html/HeadersIterator.hx | 6 +- std/js/html/HeadingElement.hx | 7 +- std/js/html/History.hx | 23 +- std/js/html/HitRegionOptions.hx | 11 +- std/js/html/HtmlElement.hx | 5 +- std/js/html/IFrameElement.hx | 19 +- std/js/html/Image.hx | 5 +- std/js/html/ImageBitmap.hx | 5 +- std/js/html/ImageBitmapFormat.hx | 41 + std/js/html/ImageBitmapRenderingContext.hx | 8 +- std/js/html/ImageCapture.hx | 18 +- ...{AppletElement.hx => ImageCaptureError.hx} | 27 +- ...ansaction.hx => ImageCaptureErrorEvent.hx} | 17 +- std/js/html/ImageCaptureErrorEventInit.hx | 29 + std/js/html/ImageData.hx | 9 +- std/js/html/ImageElement.hx | 21 +- std/js/html/InputElement.hx | 21 +- std/js/html/InputEvent.hx | 5 +- std/js/html/InputEventInit.hx | 8 +- std/js/html/Int16Array.hx | 21 +- std/js/html/Int32Array.hx | 21 +- std/js/html/Int8Array.hx | 21 +- std/js/html/IntersectionObserver.hx | 74 + std/js/html/IntersectionObserverEntry.hx | 72 + std/js/html/IntersectionObserverInit.hx | 31 + .../{DOMTransactionEvent.hx => IntlUtils.hx} | 14 +- std/js/html/IterationCompositeOperation.hx | 5 +- std/js/html/KeyEvent.hx | 8 +- std/js/html/KeyboardEvent.hx | 25 +- std/js/html/KeyboardEventInit.hx | 22 +- std/js/html/KeyframeAnimationOptions.hx | 29 + std/js/html/KeyframeEffect.hx | 26 +- std/js/html/KeyframeEffectOptions.hx | 30 + std/js/html/KeyframeEffectReadOnly.hx | 62 - std/js/html/LIElement.hx | 7 +- std/js/html/LabelElement.hx | 5 +- std/js/html/LegendElement.hx | 5 +- std/js/html/LineAlignSetting.hx | 31 + std/js/html/LinkElement.hx | 19 +- std/js/html/LocalMediaStream.hx | 11 +- std/js/html/LocaleInfo.hx | 30 + std/js/html/Location.hx | 15 +- std/js/html/MapElement.hx | 5 +- std/js/html/MediaDeviceInfo.hx | 58 + std/js/html/MediaDeviceKind.hx | 31 + std/js/html/MediaDevices.hx | 49 + std/js/html/MediaElement.hx | 125 +- std/js/html/MediaError.hx | 46 +- std/js/html/MediaKeyStatusMapIterator.hx | 6 +- std/js/html/MediaList.hx | 5 +- std/js/html/MediaQueryList.hx | 38 +- std/js/html/MediaQueryListEvent.hx | 49 + std/js/html/MediaQueryListEventInit.hx | 30 + std/js/html/MediaRecorder.hx | 25 +- std/js/html/MediaRecorderErrorEvent.hx | 44 + std/js/html/MediaRecorderErrorEventInit.hx | 29 + std/js/html/MediaRecorderOptions.hx | 13 +- std/js/html/MediaSource.hx | 48 +- std/js/html/MediaSourceEndOfStreamError.hx | 5 +- std/js/html/MediaSourceReadyState.hx | 5 +- std/js/html/MediaStream.hx | 34 +- std/js/html/MediaStreamConstraints.hx | 28 +- std/js/html/MediaStreamError.hx | 6 +- std/js/html/MediaStreamEvent.hx | 44 + std/js/html/MediaStreamEventInit.hx | 29 + std/js/html/MediaStreamTrack.hx | 78 +- std/js/html/MediaStreamTrackEvent.hx | 44 + std/js/html/MediaStreamTrackEventInit.hx | 29 + std/js/html/MediaStreamTrackState.hx | 30 + std/js/html/MediaTrackConstraintSet.hx | 34 +- std/js/html/MediaTrackConstraints.hx | 8 +- std/js/html/MediaTrackSettings.hx | 87 + std/js/html/MediaTrackSupportedConstraints.hx | 117 + std/js/html/MenuElement.hx | 5 +- std/js/html/MenuItemElement.hx | 5 +- std/js/html/MessageChannel.hx | 5 +- std/js/html/MessageEvent.hx | 29 +- std/js/html/MessageEventInit.hx | 16 +- std/js/html/MessagePort.hx | 8 +- std/js/html/MetaElement.hx | 5 +- std/js/html/MeterElement.hx | 34 +- std/js/html/MimeType.hx | 28 +- std/js/html/MimeTypeArray.hx | 24 +- std/js/html/ModElement.hx | 9 +- std/js/html/MouseEvent.hx | 25 +- std/js/html/MouseEventInit.hx | 24 +- std/js/html/MouseScrollEvent.hx | 7 +- std/js/html/MutationEvent.hx | 7 +- std/js/html/MutationObserver.hx | 7 +- std/js/html/MutationObserverInit.hx | 56 +- std/js/html/MutationRecord.hx | 5 +- std/js/html/NamedNodeMap.hx | 13 +- std/js/html/NavigationType.hx | 32 + std/js/html/Navigator.hx | 63 +- std/js/html/Node.hx | 80 +- std/js/html/NodeFilter.hx | 47 +- std/js/html/NodeIterator.hx | 161 +- std/js/html/NodeList.hx | 7 +- std/js/html/Notification.hx | 27 +- std/js/html/NotificationDirection.hx | 5 +- std/js/html/NotificationEvent.hx | 16 +- std/js/html/NotificationEventInit.hx | 6 +- std/js/html/NotificationOptions.hx | 18 +- std/js/html/NotificationPermission.hx | 7 +- std/js/html/OListElement.hx | 5 +- std/js/html/ObjectElement.hx | 6 +- std/js/html/ObserverCallback.hx | 29 + .../html/OfflineAudioCompletionEventInit.hx | 29 + std/js/html/OptGroupElement.hx | 5 +- .../html/{RecordErrorEvent.hx => Option.hx} | 13 +- std/js/html/OptionElement.hx | 5 +- ...udioChannel.hx => OptionalEffectTiming.hx} | 23 +- std/js/html/OrientationLockType.hx | 5 +- std/js/html/OrientationType.hx | 5 +- std/js/html/OutputElement.hx | 59 +- std/js/html/PageTransitionEvent.hx | 11 +- std/js/html/PageTransitionEventInit.hx | 9 +- std/js/html/PaintRequest.hx | 5 +- std/js/html/PaintRequestList.hx | 5 +- std/js/html/PaintWorkletGlobalScope.hx | 30 + std/js/html/ParagraphElement.hx | 9 +- std/js/html/ParamElement.hx | 5 +- std/js/html/Path2D.hx | 9 +- std/js/html/Performance.hx | 75 +- std/js/html/PerformanceEntry.hx | 10 +- std/js/html/PerformanceEntryFilterOptions.hx | 31 + std/js/html/PerformanceMark.hx | 7 +- std/js/html/PerformanceMeasure.hx | 7 +- std/js/html/PerformanceNavigation.hx | 83 +- std/js/html/PerformanceNavigationTiming.hx | 92 + std/js/html/PerformanceObserver.hx | 41 + std/js/html/PerformanceObserverEntryList.hx | 39 + std/js/html/PerformanceObserverInit.hx | 30 + std/js/html/PerformanceResourceTiming.hx | 86 +- ...ReadOnly.hx => PerformanceServerTiming.hx} | 29 +- std/js/html/PerformanceTiming.hx | 58 +- std/js/html/PermissionState.hx | 5 +- std/js/html/PermissionStatus.hx | 5 +- std/js/html/Permissions.hx | 17 +- std/js/html/PictureElement.hx | 5 +- std/js/html/PlaybackDirection.hx | 7 +- std/js/html/Plugin.hx | 21 +- std/js/html/PluginArray.hx | 11 +- std/js/html/PointerEvent.hx | 52 +- std/js/html/PointerEventInit.hx | 25 +- std/js/html/PopStateEvent.hx | 5 +- std/js/html/PopStateEventInit.hx | 8 +- std/js/html/PopupBlockedEvent.hx | 5 +- std/js/html/PopupBlockedEventInit.hx | 14 +- std/js/html/Position.hx | 6 +- std/js/html/PositionAlignSetting.hx | 32 + std/js/html/PositionError.hx | 5 +- std/js/html/PositionOptions.hx | 17 +- std/js/html/PreElement.hx | 5 +- std/js/html/ProcessingInstruction.hx | 8 +- std/js/html/ProgressElement.hx | 10 +- std/js/html/ProgressEvent.hx | 5 +- std/js/html/ProgressEventInit.hx | 12 +- ...tURLOptions.hx => PromiseNativeHandler.hx} | 7 +- std/js/html/PropertyNodeList.hx | 7 +- std/js/html/QuoteElement.hx | 5 +- std/js/html/RadioNodeList.hx | 5 +- std/js/html/Range.hx | 135 +- std/js/html/RecordingState.hx | 5 +- std/js/html/ReferrerPolicy.hx | 10 +- std/js/html/RegistrationOptions.hx | 30 + std/js/html/Request.hx | 49 +- std/js/html/RequestCache.hx | 8 +- std/js/html/RequestCredentials.hx | 5 +- std/js/html/RequestDestination.hx | 53 + std/js/html/RequestInit.hx | 26 +- std/js/html/RequestMode.hx | 5 +- std/js/html/RequestRedirect.hx | 5 +- std/js/html/Response.hx | 50 +- std/js/html/ResponseInit.hx | 11 +- std/js/html/ResponseType.hx | 7 +- std/js/html/Screen.hx | 7 +- std/js/html/ScreenOrientation.hx | 40 +- std/js/html/ScriptElement.hx | 7 +- std/js/html/ScrollAreaEvent.hx | 7 +- std/js/html/ScrollBehavior.hx | 31 + std/js/html/ScrollIntoViewOptions.hx | 10 +- std/js/html/ScrollLogicalPosition.hx | 32 + std/js/html/ScrollOptions.hx | 7 +- std/js/html/ScrollRestoration.hx | 5 +- std/js/html/ScrollSetting.hx | 30 + std/js/html/ScrollToOptions.hx | 10 +- std/js/html/SecurityPolicyViolationEvent.hx | 99 + ...SecurityPolicyViolationEventDisposition.hx | 30 + ...hx => SecurityPolicyViolationEventInit.hx} | 27 +- std/js/html/SelectElement.hx | 52 +- std/js/html/Selection.hx | 84 +- std/js/html/SelectionMode.hx | 5 +- std/js/html/ServiceWorker.hx | 5 +- std/js/html/ServiceWorkerContainer.hx | 75 + std/js/html/ServiceWorkerGlobalScope.hx | 36 +- std/js/html/ServiceWorkerRegistration.hx | 49 +- std/js/html/ServiceWorkerState.hx | 6 +- std/js/html/ServiceWorkerUpdateViaCache.hx | 31 + std/js/html/ShadowRoot.hx | 26 +- std/js/html/ShadowRootInit.hx | 29 + std/js/html/ShadowRootMode.hx | 30 + std/js/html/SharedWorker.hx | 8 +- std/js/html/SharedWorkerGlobalScope.hx | 12 +- std/js/html/SimpleGestureEvent.hx | 43 - std/js/html/SlotElement.hx | 47 + std/js/html/SourceBuffer.hx | 52 +- std/js/html/SourceBufferAppendMode.hx | 5 +- std/js/html/SourceBufferList.hx | 15 +- std/js/html/SourceElement.hx | 9 +- std/js/html/SpanElement.hx | 5 +- std/js/html/SpeechGrammar.hx | 5 +- std/js/html/SpeechGrammarList.hx | 11 +- std/js/html/SpeechRecognition.hx | 7 +- std/js/html/SpeechRecognitionAlternative.hx | 5 +- std/js/html/SpeechRecognitionError.hx | 5 +- std/js/html/SpeechRecognitionErrorCode.hx | 5 +- std/js/html/SpeechRecognitionErrorInit.hx | 10 +- std/js/html/SpeechRecognitionEvent.hx | 5 +- std/js/html/SpeechRecognitionEventInit.hx | 14 +- std/js/html/SpeechRecognitionResult.hx | 5 +- std/js/html/SpeechRecognitionResultList.hx | 5 +- std/js/html/SpeechSynthesis.hx | 10 +- std/js/html/SpeechSynthesisErrorCode.hx | 5 +- std/js/html/SpeechSynthesisErrorEvent.hx | 5 +- std/js/html/SpeechSynthesisErrorEventInit.hx | 6 +- std/js/html/SpeechSynthesisEvent.hx | 8 +- std/js/html/SpeechSynthesisEventInit.hx | 13 +- std/js/html/SpeechSynthesisUtterance.hx | 5 +- std/js/html/SpeechSynthesisVoice.hx | 9 +- std/js/html/Storage.hx | 17 +- std/js/html/StorageEstimate.hx | 45 + std/js/html/StorageEvent.hx | 9 +- std/js/html/StorageEventInit.hx | 16 +- std/js/html/StorageManager.hx | 56 + std/js/html/StorageType.hx | 31 + std/js/html/StyleElement.hx | 10 +- std/js/html/StyleSheet.hx | 5 +- std/js/html/StyleSheetList.hx | 5 +- std/js/html/SubtleCrypto.hx | 79 +- std/js/html/SupportedType.hx | 5 +- std/js/html/TableCaptionElement.hx | 5 +- std/js/html/TableCellElement.hx | 49 +- std/js/html/TableColElement.hx | 5 +- std/js/html/TableElement.hx | 11 +- std/js/html/TableRowElement.hx | 11 +- std/js/html/TableSectionElement.hx | 11 +- std/js/html/TemplateElement.hx | 16 +- std/js/html/Text.hx | 19 +- std/js/html/TextAreaElement.hx | 11 +- std/js/html/TextDecodeOptions.hx | 7 +- std/js/html/TextDecoder.hx | 19 +- std/js/html/TextDecoderOptions.hx | 8 +- std/js/html/TextEncoder.hx | 9 +- std/js/html/TextMetrics.hx | 5 +- std/js/html/TextTrack.hx | 48 +- std/js/html/TextTrackCue.hx | 5 +- std/js/html/TextTrackCueList.hx | 5 +- std/js/html/TextTrackKind.hx | 5 +- std/js/html/TextTrackList.hx | 5 +- std/js/html/TextTrackMode.hx | 5 +- std/js/html/TimeElement.hx | 5 +- std/js/html/TimeEvent.hx | 7 +- std/js/html/TimeRanges.hx | 9 +- std/js/html/TitleElement.hx | 5 +- std/js/html/Touch.hx | 53 +- std/js/html/TouchEvent.hx | 35 +- std/js/html/TouchEventInit.hx | 12 +- std/js/html/TouchInit.hx | 25 +- std/js/html/TouchList.hx | 10 +- std/js/html/TrackElement.hx | 23 +- std/js/html/TrackEvent.hx | 5 +- std/js/html/TrackEventInit.hx | 8 +- std/js/html/TransitionEvent.hx | 7 +- std/js/html/TransitionEventInit.hx | 12 +- std/js/html/TreeWalker.hx | 31 +- std/js/html/UIEvent.hx | 17 +- std/js/html/UIEventInit.hx | 10 +- std/js/html/UListElement.hx | 5 +- std/js/html/URL.hx | 16 +- std/js/html/URLSearchParams.hx | 31 +- std/js/html/URLSearchParamsIterator.hx | 6 +- std/js/html/Uint16Array.hx | 21 +- std/js/html/Uint32Array.hx | 21 +- std/js/html/Uint8Array.hx | 24 +- std/js/html/Uint8ClampedArray.hx | 21 +- std/js/html/UnknownElement.hx | 5 +- std/js/html/VTTCue.hx | 22 +- std/js/html/VTTRegion.hx | 8 +- std/js/html/ValidityState.hx | 10 +- std/js/html/VideoElement.hx | 5 +- std/js/html/VideoPlaybackQuality.hx | 5 +- std/js/html/VideoStreamTrack.hx | 5 +- std/js/html/VideoTrack.hx | 5 +- std/js/html/VideoTrackList.hx | 5 +- std/js/html/VisibilityState.hx | 5 +- std/js/html/VisualViewport.hx | 72 + std/js/html/WebSocket.hx | 49 +- std/js/html/WheelEvent.hx | 5 +- std/js/html/WheelEventInit.hx | 14 +- std/js/html/Window.hx | 351 +- std/js/html/WindowClient.hx | 23 +- std/js/html/Worker.hx | 14 +- std/js/html/WorkerDebuggerGlobalScope.hx | 11 +- std/js/html/WorkerGlobalScope.hx | 102 +- std/js/html/WorkerLocation.hx | 7 +- std/js/html/WorkerNavigator.hx | 6 +- std/js/html/WorkerOptions.hx | 29 + ...lePropertyBag.hx => WorkletGlobalScope.hx} | 12 +- std/js/html/XMLDocument.hx | 7 +- std/js/html/XMLHttpRequest.hx | 84 +- std/js/html/XMLHttpRequestEventTarget.hx | 12 +- std/js/html/XMLHttpRequestResponseType.hx | 12 +- std/js/html/XMLHttpRequestUpload.hx | 5 +- std/js/html/XMLSerializer.hx | 12 +- std/js/html/XPathEvaluator.hx | 14 +- std/js/html/XPathExpression.hx | 13 +- std/js/html/XPathNSResolver.hx | 6 +- std/js/html/XPathResult.hx | 30 +- std/js/html/XSLTProcessor.hx | 15 +- std/js/html/audio/AnalyserNode.hx | 15 +- std/js/html/audio/AnalyserOptions.hx | 32 + std/js/html/audio/AudioBuffer.hx | 17 +- std/js/html/audio/AudioBufferOptions.hx | 31 + std/js/html/audio/AudioBufferSourceNode.hx | 36 +- std/js/html/audio/AudioBufferSourceOptions.hx | 34 + std/js/html/audio/AudioContext.hx | 175 +- .../AudioContextOptions.hx} | 20 +- std/js/html/{ => audio}/AudioContextState.hx | 9 +- std/js/html/audio/AudioDestinationNode.hx | 9 +- std/js/html/audio/AudioListener.hx | 17 +- std/js/html/audio/AudioNode.hx | 29 +- std/js/html/audio/AudioNodeOptions.hx | 52 + std/js/html/audio/AudioParam.hx | 45 +- std/js/html/audio/AudioProcessingEvent.hx | 5 +- .../AudioScheduledSourceNode.hx} | 27 +- .../AudioWorkletGlobalScope.hx} | 21 +- .../AudioWorkletNodeOptions.hx} | 19 +- .../AudioWorkletProcessor.hx} | 16 +- std/js/html/audio/BaseAudioContext.hx | 190 + std/js/html/audio/BiquadFilterNode.hx | 153 +- std/js/html/audio/BiquadFilterOptions.hx | 33 + std/js/html/audio/BiquadFilterType.hx | 5 +- std/js/html/audio/ChannelCountMode.hx | 5 +- std/js/html/audio/ChannelInterpretation.hx | 5 +- std/js/html/audio/ChannelMergerNode.hx | 7 +- std/js/html/audio/ChannelMergerOptions.hx | 29 + std/js/html/audio/ChannelSplitterNode.hx | 7 +- std/js/html/audio/ChannelSplitterOptions.hx | 29 + std/js/html/audio/ConstantSourceNode.hx | 44 + std/js/html/audio/ConstantSourceOptions.hx | 29 + std/js/html/audio/ConvolverNode.hx | 9 +- std/js/html/audio/ConvolverOptions.hx | 30 + std/js/html/audio/DelayNode.hx | 9 +- std/js/html/audio/DelayOptions.hx | 30 + std/js/html/audio/DistanceModelType.hx | 5 +- std/js/html/audio/DynamicsCompressorNode.hx | 19 +- .../html/audio/DynamicsCompressorOptions.hx | 33 + std/js/html/audio/GainNode.hx | 11 +- std/js/html/audio/GainOptions.hx | 29 + std/js/html/audio/IIRFilterNode.hx | 39 + std/js/html/audio/IIRFilterOptions.hx | 30 + .../html/audio/MediaElementAudioSourceNode.hx | 7 +- .../audio/MediaElementAudioSourceOptions.hx | 29 + .../audio/MediaStreamAudioDestinationNode.hx | 7 +- .../html/audio/MediaStreamAudioSourceNode.hx | 9 +- .../audio/MediaStreamAudioSourceOptions.hx | 29 + .../html/audio/OfflineAudioCompletionEvent.hx | 12 +- std/js/html/audio/OfflineAudioContext.hx | 21 +- .../html/audio/OfflineAudioContextOptions.hx | 31 + std/js/html/audio/OscillatorNode.hx | 28 +- std/js/html/audio/OscillatorOptions.hx | 32 + std/js/html/audio/OscillatorType.hx | 5 +- std/js/html/audio/OverSampleType.hx | 5 +- std/js/html/audio/PannerNode.hx | 42 +- std/js/html/audio/PannerOptions.hx | 42 + std/js/html/audio/PanningModelType.hx | 5 +- std/js/html/audio/PeriodicWave.hx | 9 +- std/js/html/audio/PeriodicWaveConstraints.hx | 29 + std/js/html/audio/PeriodicWaveOptions.hx | 30 + std/js/html/audio/ScriptProcessorNode.hx | 5 +- std/js/html/audio/StereoPannerNode.hx | 7 +- std/js/html/audio/StereoPannerOptions.hx | 29 + std/js/html/audio/WaveShaperNode.hx | 9 +- std/js/html/audio/WaveShaperOptions.hx | 30 + std/js/html/compat/DataView.hx | 154 - std/js/html/compat/Float32Array.hx | 111 - std/js/html/compat/Float64Array.hx | 118 - std/js/html/compat/Uint8Array.hx | 102 - .../MediaEncryptedEvent.hx} | 17 +- std/js/html/eme/MediaKeyError.hx | 31 + std/js/html/eme/MediaKeyMessageEvent.hx | 49 + std/js/html/eme/MediaKeyMessageEventInit.hx | 30 + std/js/html/eme/MediaKeyMessageType.hx | 32 + std/js/html/eme/MediaKeyNeededEventInit.hx | 30 + std/js/html/eme/MediaKeySession.hx | 99 + std/js/html/eme/MediaKeySessionType.hx | 30 + std/js/html/eme/MediaKeyStatusMap.hx | 79 + std/js/html/eme/MediaKeySystemAccess.hx | 54 + .../html/eme/MediaKeySystemConfiguration.hx | 62 + .../html/eme/MediaKeySystemMediaCapability.hx | 30 + std/js/html/eme/MediaKeys.hx | 52 + std/js/html/eme/MediaKeysRequirement.hx | 31 + std/js/html/idb/Cursor.hx | 30 +- std/js/html/idb/CursorDirection.hx | 5 +- std/js/html/idb/CursorWithValue.hx | 5 +- std/js/html/idb/Database.hx | 21 +- std/js/html/idb/Factory.hx | 5 +- std/js/html/idb/FileHandle.hx | 15 +- std/js/html/idb/FileMetadataParameters.hx | 9 +- std/js/html/idb/FileRequest.hx | 5 +- std/js/html/idb/Index.hx | 25 +- std/js/html/idb/IndexParameters.hx | 11 +- std/js/html/idb/KeyRange.hx | 31 +- std/js/html/idb/MutableFile.hx | 7 +- std/js/html/idb/ObjectStore.hx | 56 +- std/js/html/idb/ObjectStoreParameters.hx | 9 +- std/js/html/idb/OpenDBOptions.hx | 9 +- std/js/html/idb/OpenDBRequest.hx | 7 +- std/js/html/idb/Request.hx | 9 +- std/js/html/idb/RequestReadyState.hx | 5 +- std/js/html/idb/Transaction.hx | 19 +- std/js/html/idb/TransactionMode.hx | 5 +- std/js/html/idb/VersionChangeEvent.hx | 13 +- std/js/html/idb/VersionChangeEventInit.hx | 10 +- std/js/html/midi/MIDIAccess.hx | 57 + std/js/html/midi/MIDIConnectionEvent.hx | 44 + std/js/html/midi/MIDIConnectionEventInit.hx | 29 + std/js/html/midi/MIDIInput.hx | 42 + std/js/html/midi/MIDIInputMap.hx | 52 + std/js/html/midi/MIDIMessageEvent.hx | 33 + std/js/html/midi/MIDIMessageEventInit.hx | 29 + std/js/html/midi/MIDIOptions.hx | 30 + .../MIDIOutput.hx} | 16 +- std/js/html/midi/MIDIOutputMap.hx | 52 + std/js/html/{RGBColor.hx => midi/MIDIPort.hx} | 29 +- std/js/html/midi/MIDIPortConnectionState.hx | 31 + std/js/html/midi/MIDIPortDeviceState.hx | 30 + std/js/html/midi/MIDIPortType.hx | 30 + std/js/html/push/PushEncryptionKeyName.hx | 30 + std/js/html/push/PushEvent.hx | 44 + std/js/html/push/PushEventInit.hx | 29 + std/js/html/push/PushManager.hx | 58 + std/js/html/push/PushMessageData.hx | 59 + std/js/html/push/PushPermissionState.hx | 31 + std/js/html/push/PushSubscription.hx | 69 + std/js/html/push/PushSubscriptionInit.hx | 33 + std/js/html/push/PushSubscriptionJSON.hx | 30 + std/js/html/push/PushSubscriptionKeys.hx | 30 + .../PushSubscriptionOptions.hx} | 14 +- .../html/push/PushSubscriptionOptionsInit.hx | 29 + std/js/html/rtc/AnswerOptions.hx | 6 +- std/js/html/rtc/BundlePolicy.hx | 31 + std/js/html/rtc/Certificate.hx | 5 +- std/js/html/rtc/Configuration.hx | 15 +- std/js/html/rtc/DTMFSender.hx | 41 + std/js/html/rtc/DTMFToneChangeEvent.hx | 44 + std/js/html/rtc/DTMFToneChangeEventInit.hx | 29 + std/js/html/rtc/DataChannel.hx | 23 +- std/js/html/rtc/DataChannelEvent.hx | 40 + std/js/html/rtc/DataChannelEventInit.hx | 29 + std/js/html/rtc/DataChannelInit.hx | 22 +- std/js/html/rtc/DataChannelState.hx | 7 +- std/js/html/rtc/DataChannelType.hx | 7 +- .../DegradationPreference.hx} | 15 +- std/js/html/rtc/FecParameters.hx | 29 + std/js/html/rtc/IceCandidate.hx | 16 +- std/js/html/rtc/IceCandidateInit.hx | 11 +- std/js/html/rtc/IceConnectionState.hx | 7 +- std/js/html/rtc/IceCredentialType.hx | 30 + std/js/html/rtc/IceGatheringState.hx | 7 +- .../IceServer.hx} | 17 +- std/js/html/rtc/IceTransportPolicy.hx | 30 + std/js/html/rtc/IdentityAssertion.hx | 9 +- std/js/html/rtc/IdentityAssertionResult.hx | 7 +- std/js/html/rtc/IdentityProvider.hx | 12 +- std/js/html/rtc/IdentityProviderDetails.hx | 30 + std/js/html/rtc/IdentityProviderOptions.hx | 31 + std/js/html/rtc/IdentityProviderRegistrar.hx | 6 +- std/js/html/rtc/IdentityValidationResult.hx | 5 +- std/js/html/rtc/OfferAnswerOptions.hx | 5 +- std/js/html/rtc/OfferOptions.hx | 13 +- std/js/html/rtc/PeerConnection.hx | 49 +- .../PeerConnectionIceEvent.hx} | 25 +- std/js/html/rtc/PeerConnectionIceEventInit.hx | 29 + std/js/html/rtc/PriorityType.hx | 32 + std/js/html/rtc/RtcpParameters.hx | 30 + std/js/html/rtc/RtpCodecParameters.hx | 33 + std/js/html/rtc/RtpContributingSource.hx | 31 + std/js/html/rtc/RtpEncodingParameters.hx | 37 + .../html/rtc/RtpHeaderExtensionParameters.hx | 31 + std/js/html/rtc/RtpParameters.hx | 13 +- std/js/html/rtc/RtpReceiver.hx | 35 +- std/js/html/rtc/RtpSender.hx | 28 +- std/js/html/rtc/RtpSynchronizationSource.hx | 29 + std/js/html/rtc/RtpTransceiver.hx | 69 + std/js/html/rtc/RtpTransceiverDirection.hx | 32 + std/js/html/rtc/RtpTransceiverInit.hx | 30 + std/js/html/rtc/RtxParameters.hx | 29 + std/js/html/rtc/SdpType.hx | 5 +- std/js/html/rtc/SessionDescription.hx | 12 +- std/js/html/rtc/SessionDescriptionInit.hx | 9 +- std/js/html/rtc/SignalingState.hx | 5 +- std/js/html/rtc/StatsReport.hx | 24 +- std/js/html/rtc/TrackEvent.hx | 59 + std/js/html/rtc/TrackEventInit.hx | 32 + std/js/html/svg/AElement.hx | 50 +- std/js/html/svg/Angle.hx | 25 +- std/js/html/svg/AnimateElement.hx | 5 +- std/js/html/svg/AnimateMotionElement.hx | 5 +- std/js/html/svg/AnimateTransformElement.hx | 5 +- std/js/html/svg/AnimatedAngle.hx | 5 +- std/js/html/svg/AnimatedBoolean.hx | 5 +- std/js/html/svg/AnimatedEnumeration.hx | 5 +- std/js/html/svg/AnimatedInteger.hx | 5 +- std/js/html/svg/AnimatedLength.hx | 5 +- std/js/html/svg/AnimatedLengthList.hx | 5 +- std/js/html/svg/AnimatedNumber.hx | 5 +- std/js/html/svg/AnimatedNumberList.hx | 5 +- .../html/svg/AnimatedPreserveAspectRatio.hx | 5 +- std/js/html/svg/AnimatedRect.hx | 5 +- std/js/html/svg/AnimatedString.hx | 7 +- std/js/html/svg/AnimatedTransformList.hx | 5 +- std/js/html/svg/AnimationElement.hx | 55 +- std/js/html/svg/BoundingBoxOptions.hx | 13 +- std/js/html/svg/CircleElement.hx | 31 +- std/js/html/svg/ClipPathElement.hx | 11 +- .../svg/ComponentTransferFunctionElement.hx | 40 +- std/js/html/svg/DefsElement.hx | 5 +- std/js/html/svg/DescElement.hx | 5 +- std/js/html/svg/Element.hx | 17 +- std/js/html/svg/EllipseElement.hx | 21 +- std/js/html/svg/FEBlendElement.hx | 24 +- std/js/html/svg/FEColorMatrixElement.hx | 24 +- std/js/html/svg/FEComponentTransferElement.hx | 16 +- std/js/html/svg/FECompositeElement.hx | 19 +- std/js/html/svg/FEConvolveMatrixElement.hx | 60 +- std/js/html/svg/FEDiffuseLightingElement.hx | 32 +- std/js/html/svg/FEDisplacementMapElement.hx | 32 +- std/js/html/svg/FEDistantLightElement.hx | 20 +- std/js/html/svg/FEDropShadowElement.hx | 36 +- std/js/html/svg/FEFloodElement.hx | 12 +- std/js/html/svg/FEFuncAElement.hx | 12 +- std/js/html/svg/FEFuncBElement.hx | 12 +- std/js/html/svg/FEFuncGElement.hx | 12 +- std/js/html/svg/FEFuncRElement.hx | 12 +- std/js/html/svg/FEGaussianBlurElement.hx | 28 +- std/js/html/svg/FEImageElement.hx | 16 +- std/js/html/svg/FEMergeElement.hx | 12 +- std/js/html/svg/FEMergeNodeElement.hx | 16 +- std/js/html/svg/FEMorphologyElement.hx | 31 +- std/js/html/svg/FEOffsetElement.hx | 24 +- std/js/html/svg/FEPointLightElement.hx | 24 +- std/js/html/svg/FESpecularLightingElement.hx | 36 +- std/js/html/svg/FESpotLightElement.hx | 32 +- std/js/html/svg/FETileElement.hx | 16 +- std/js/html/svg/FETurbulenceElement.hx | 36 +- std/js/html/svg/FilterElement.hx | 31 +- std/js/html/svg/ForeignObjectElement.hx | 21 +- std/js/html/svg/GElement.hx | 5 +- ...{AltGlyphElement.hx => GeometryElement.hx} | 30 +- std/js/html/svg/GradientElement.hx | 20 +- std/js/html/svg/GraphicsElement.hx | 30 +- std/js/html/svg/ImageElement.hx | 26 +- std/js/html/svg/Length.hx | 5 +- std/js/html/svg/LengthList.hx | 5 +- std/js/html/svg/LineElement.hx | 21 +- std/js/html/svg/LinearGradientElement.hx | 21 +- std/js/html/svg/MPathElement.hx | 5 +- std/js/html/svg/MarkerElement.hx | 5 +- std/js/html/svg/MaskElement.hx | 32 +- std/js/html/svg/Matrix.hx | 81 +- std/js/html/svg/MetadataElement.hx | 12 +- std/js/html/svg/Number.hx | 16 +- std/js/html/svg/NumberList.hx | 5 +- std/js/html/svg/PathElement.hx | 32 +- std/js/html/svg/PathSeg.hx | 5 +- std/js/html/svg/PathSegArcAbs.hx | 6 +- std/js/html/svg/PathSegArcRel.hx | 6 +- std/js/html/svg/PathSegClosePath.hx | 6 +- std/js/html/svg/PathSegCurvetoCubicAbs.hx | 6 +- std/js/html/svg/PathSegCurvetoCubicRel.hx | 6 +- .../html/svg/PathSegCurvetoCubicSmoothAbs.hx | 6 +- .../html/svg/PathSegCurvetoCubicSmoothRel.hx | 6 +- std/js/html/svg/PathSegCurvetoQuadraticAbs.hx | 6 +- std/js/html/svg/PathSegCurvetoQuadraticRel.hx | 6 +- .../svg/PathSegCurvetoQuadraticSmoothAbs.hx | 6 +- .../svg/PathSegCurvetoQuadraticSmoothRel.hx | 6 +- std/js/html/svg/PathSegLinetoAbs.hx | 6 +- std/js/html/svg/PathSegLinetoHorizontalAbs.hx | 6 +- std/js/html/svg/PathSegLinetoHorizontalRel.hx | 6 +- std/js/html/svg/PathSegLinetoRel.hx | 6 +- std/js/html/svg/PathSegLinetoVerticalAbs.hx | 6 +- std/js/html/svg/PathSegLinetoVerticalRel.hx | 6 +- std/js/html/svg/PathSegList.hx | 17 +- std/js/html/svg/PathSegMovetoAbs.hx | 6 +- std/js/html/svg/PathSegMovetoRel.hx | 6 +- std/js/html/svg/PatternElement.hx | 35 +- std/js/html/svg/Point.hx | 5 +- std/js/html/svg/PointList.hx | 5 +- std/js/html/svg/PolygonElement.hx | 5 +- std/js/html/svg/PolylineElement.hx | 5 +- std/js/html/svg/PreserveAspectRatio.hx | 5 +- std/js/html/svg/RadialGradientElement.hx | 24 +- std/js/html/svg/Rect.hx | 19 +- std/js/html/svg/RectElement.hx | 29 +- std/js/html/svg/SVGElement.hx | 128 +- std/js/html/svg/ScriptElement.hx | 13 +- std/js/html/svg/SetElement.hx | 5 +- std/js/html/svg/StopElement.hx | 9 +- std/js/html/svg/StringList.hx | 5 +- std/js/html/svg/StyleElement.hx | 18 +- std/js/html/svg/SwitchElement.hx | 5 +- std/js/html/svg/SymbolElement.hx | 5 +- std/js/html/svg/TSpanElement.hx | 7 +- std/js/html/svg/TextContentElement.hx | 72 +- std/js/html/svg/TextElement.hx | 5 +- std/js/html/svg/TextPathElement.hx | 24 +- std/js/html/svg/TextPositioningElement.hx | 27 +- std/js/html/svg/TitleElement.hx | 5 +- std/js/html/svg/Transform.hx | 5 +- std/js/html/svg/TransformList.hx | 5 +- std/js/html/svg/UnitTypes.hx | 12 +- std/js/html/svg/UseElement.hx | 23 +- std/js/html/svg/ViewElement.hx | 6 +- std/js/html/svg/ZoomAndPan.hx | 16 +- std/js/html/svg/ZoomEvent.hx | 35 - std/js/html/webgl/ActiveInfo.hx | 5 +- std/js/html/webgl/Buffer.hx | 5 +- std/js/html/webgl/ContextAttributes.hx | 20 +- std/js/html/webgl/ContextEvent.hx | 7 +- std/js/html/webgl/ContextEventInit.hx | 10 +- std/js/html/webgl/Extension.hx | 59 + .../webgl/ExtensionTextureHalfFloatLinear.hx | 37 - std/js/html/webgl/Framebuffer.hx | 5 +- std/js/html/webgl/GL.hx | 2 +- std/js/html/webgl/GL2.hx | 26 + std/js/html/webgl/PowerPreference.hx | 31 + std/js/html/webgl/Program.hx | 5 +- .../webgl/{ExtensionFragDepth.hx => Query.hx} | 13 +- std/js/html/webgl/Renderbuffer.hx | 5 +- std/js/html/webgl/RenderingContext.hx | 570 ++- .../{ExtensionTextureFloat.hx => Sampler.hx} | 15 +- std/js/html/webgl/Shader.hx | 5 +- std/js/html/webgl/ShaderPrecisionFormat.hx | 5 +- std/js/html/webgl/Sync.hx | 36 + std/js/html/webgl/Texture.hx | 5 +- std/js/html/webgl/TimerQueryEXT.hx | 37 - ...aderTextureLod.hx => TransformFeedback.hx} | 15 +- std/js/html/webgl/UniformLocation.hx | 5 +- ...ementIndexUint.hx => VertexArrayObject.hx} | 13 +- std/js/html/webgl/WebGL2RenderingContext.hx | 1180 +++++ .../ANGLEInstancedArrays.hx} | 11 +- .../EXTBlendMinmax.hx} | 15 +- .../webgl/extension/EXTColorBufferFloat.hx | 28 + .../EXTColorBufferHalfFloat.hx} | 23 +- .../EXTDisjointTimerQuery.hx} | 53 +- std/js/html/webgl/extension/EXTFragDepth.hx | 28 + .../webgl/extension/EXTShaderTextureLod.hx | 28 + .../EXTSrgb.hx} | 23 +- .../EXTTextureFilterAnisotropic.hx} | 15 +- .../webgl/extension/OESElementIndexUint.hx | 28 + .../OESStandardDerivatives.hx} | 11 +- .../html/webgl/extension/OESTextureFloat.hx | 28 + .../webgl/extension/OESTextureFloatLinear.hx | 28 + .../OESTextureHalfFloat.hx} | 11 +- .../extension/OESTextureHalfFloatLinear.hx | 28 + .../OESVertexArrayObject.hx} | 35 +- .../WEBGLColorBufferFloat.hx} | 23 +- .../extension/WEBGLCompressedTextureAstc.hx | 66 + .../WEBGLCompressedTextureAtc.hx} | 19 +- .../WEBGLCompressedTextureEtc.hx} | 55 +- .../WEBGLCompressedTextureEtc1.hx} | 11 +- .../WEBGLCompressedTexturePvrtc.hx} | 23 +- .../WEBGLCompressedTextureS3tc.hx} | 23 +- .../WEBGLCompressedTextureS3tcSrgb.hx | 57 + .../WEBGLDebugRendererInfo.hx} | 7 +- .../html/webgl/extension/WEBGLDebugShaders.hx | 29 + .../WEBGLDepthTexture.hx} | 11 +- .../WEBGLDrawBuffers.hx} | 23 +- .../html/webgl/extension/WEBGLLoseContext.hx | 30 + std/js/jquery/Callbacks.hx | 53 - std/js/jquery/Deferred.hx | 84 - std/js/jquery/Event.hx | 151 - std/js/jquery/Helper.hx | 16 - std/js/jquery/JQuery.hx | 1106 ----- std/js/jquery/JqEltsIterator.hx | 21 - std/js/jquery/JqIterator.hx | 21 - std/js/jquery/JqXHR.hx | 46 - std/js/jquery/Promise.hx | 46 - .../{html/DOMCursor.hx => lib/ArrayBuffer.hx} | 46 +- std/js/lib/ArrayBufferView.hx | 36 + std/js/lib/BufferSource.hx | 42 + std/js/lib/DataView.hx | 58 + std/js/lib/Date.hx | 285 ++ std/js/lib/Error.hx | 62 + std/js/lib/Float32Array.hx | 265 ++ std/js/lib/Float64Array.hx | 265 ++ std/js/lib/Function.hx | 52 + std/js/lib/Int16Array.hx | 264 ++ std/js/lib/Int32Array.hx | 264 ++ std/js/lib/Int8Array.hx | 263 ++ std/js/lib/Intl.hx | 40 + .../_std/haxe/Log.hx => js/lib/Iterator.hx} | 16 +- std/js/lib/Map.hx | 118 + std/js/lib/Math.hx | 251 ++ std/js/lib/Object.hx | 258 ++ std/js/lib/Promise.hx | 109 + std/js/lib/Proxy.hx | 120 + std/js/lib/Reflect.hx | 110 + std/js/lib/RegExp.hx | 47 + std/js/lib/Set.hx | 100 + std/js/lib/Symbol.hx | 63 + std/js/lib/Uint16Array.hx | 264 ++ std/js/lib/Uint32Array.hx | 264 ++ std/js/lib/Uint8Array.hx | 263 ++ std/js/lib/Uint8ClampedArray.hx | 265 ++ std/js/lib/WeakMap.hx | 66 + std/js/lib/WeakSet.hx | 59 + std/js/lib/WebAssembly.hx | 80 + std/js/lib/intl/Collator.hx | 183 + std/js/lib/intl/DateTimeFormat.hx | 386 ++ std/js/lib/intl/LocaleMatcher.hx | 27 + std/js/lib/intl/NumberFormat.hx | 283 ++ std/js/lib/intl/PluralRules.hx | 124 + std/js/lib/intl/RelativeTimeFormat.hx | 163 + std/js/lib/webassembly/CompileError.hx | 34 + std/js/lib/webassembly/Global.hx | 62 + std/js/lib/webassembly/Instance.hx | 43 + .../webassembly/LinkError.hx} | 23 +- std/js/lib/webassembly/Memory.hx | 63 + std/js/lib/webassembly/Module.hx | 72 + std/js/lib/webassembly/RuntimeError.hx | 34 + std/js/lib/webassembly/Table.hx | 81 + std/js/swfobject/SWFObject.hx | 128 - std/jvm/DynamicObject.hx | 93 + std/jvm/EmptyConstructor.hx | 27 + std/{java/_std/haxe/Log.hx => jvm/Enum.hx} | 37 +- std/jvm/Exception.hx | 60 + std/jvm/Jvm.hx | 531 +++ std/jvm/NativeTools.hx | 49 + .../remoting/AsyncProxy.hx => jvm/Object.hx} | 25 +- std/jvm/StringExt.hx | 129 + std/jvm/_std/Reflect.hx | 182 + std/jvm/_std/Std.hx | 111 + std/jvm/_std/String.hx | 76 + std/jvm/_std/Type.hx | 332 ++ .../annotation/ClassReflectionInformation.hx | 30 + .../annotation/EnumReflectionInformation.hx | 30 + .../EnumValueReflectionInformation.hx | 30 + std/lua/Bit.hx | 24 +- std/lua/Boot.hx | 477 +- std/lua/Coroutine.hx | 29 +- std/lua/Debug.hx | 111 +- std/lua/Ffi.hx | 42 +- std/lua/FileHandle.hx | 19 +- std/lua/HaxeIterator.hx | 22 +- std/lua/Io.hx | 84 +- std/lua/Jit.hx | 22 +- std/lua/Lib.hx | 62 +- std/lua/LocaleCategory.hx | 36 +- std/lua/Lua.hx | 128 +- std/lua/Math.hx | 82 +- std/lua/NativeIterator.hx | 14 +- std/lua/NativeStringTools.hx | 148 +- std/lua/Os.hx | 131 +- std/lua/Package.hx | 31 +- std/lua/PairTools.hx | 98 +- std/lua/Result.hx | 27 +- std/lua/Table.hx | 71 +- std/lua/TableTools.hx | 29 +- std/lua/Thread.hx | 7 +- std/lua/Time.hx | 27 +- std/lua/UserData.hx | 23 + std/lua/_lua/_hx_apply.lua | 6 - std/lua/_lua/_hx_apply_self.lua | 3 + std/lua/_lua/_hx_bind.lua | 14 + std/lua/_lua/_hx_bit.lua | 11 + std/lua/_lua/_hx_bit_clamp.lua | 10 + std/lua/_lua/_hx_box_mr.lua | 7 + std/lua/_lua/_hx_dyn_add.lua | 7 + std/lua/_lua/_hx_func_to_field.lua | 9 + std/lua/_lua/_hx_print.lua | 1 + std/lua/_lua/_hx_random_init.lua | 1 + std/lua/_lua/_hx_static_to_instance.lua | 13 + std/lua/_lua/_hx_table.lua | 12 + std/lua/_lua/_hx_wrap_if_string_field.lua | 11 + std/lua/_std/Array.hx | 203 +- std/lua/_std/Date.hx | 106 +- std/lua/_std/EReg.hx | 133 +- std/lua/_std/Math.hx | 109 +- std/lua/_std/Reflect.hx | 165 +- std/lua/_std/Std.hx | 74 +- std/lua/_std/String.hx | 142 +- std/lua/_std/StringBuf.hx | 68 +- std/lua/_std/Sys.hx | 109 +- std/lua/_std/Type.hx | 238 +- std/lua/_std/haxe/Json.hx | 9 +- std/lua/_std/haxe/Utf8.hx | 250 -- std/lua/_std/haxe/ds/IntMap.hx | 59 +- std/lua/_std/haxe/ds/ObjectMap.hx | 98 +- std/lua/_std/haxe/ds/StringMap.hx | 95 +- std/lua/_std/sys/FileSystem.hx | 86 +- std/lua/_std/sys/io/File.hx | 48 +- std/lua/_std/sys/io/FileInput.hx | 52 +- std/lua/_std/sys/io/FileOutput.hx | 29 +- std/lua/_std/sys/io/Process.hx | 149 +- std/lua/_std/sys/net/Host.hx | 55 +- std/lua/_std/sys/net/Socket.hx | 234 + std/lua/lib/lrexlib/Rex.hx | 78 +- std/lua/lib/luasocket/Socket.hx | 16 +- std/lua/lib/luasocket/socket/AddrInfo.hx | 28 + std/lua/lib/luasocket/socket/Dns.hx | 7 +- .../lib/luasocket/socket/ReceivePattern.hx | 28 + std/lua/lib/luasocket/socket/SelectResult.hx | 28 + std/lua/lib/luasocket/socket/ShutdownMode.hx | 29 + .../lib/luasocket/socket/TcpClient.hx} | 19 +- std/lua/lib/luasocket/socket/TcpMaster.hx | 33 + .../lib/luasocket/socket/TcpOption.hx} | 13 +- .../lib/luasocket/socket/TcpServer.hx} | 20 +- std/lua/lib/luasocket/socket/TimeoutMode.hx | 28 + std/lua/lib/luautf8/Utf8.hx | 115 + std/lua/lib/luv/Async.hx | 8 +- std/lua/lib/luv/Check.hx | 11 +- std/lua/lib/luv/Handle.hx | 20 +- std/lua/lib/luv/Idle.hx | 10 +- std/lua/lib/luv/Loop.hx | 18 +- std/lua/lib/luv/Misc.hx | 115 +- std/lua/lib/luv/Pipe.hx | 21 +- std/lua/lib/luv/Poll.hx | 10 +- std/lua/lib/luv/Prepare.hx | 10 +- std/lua/lib/luv/Process.hx | 16 +- std/lua/lib/luv/Request.hx | 4 +- std/lua/lib/luv/Signal.hx | 11 +- std/lua/lib/luv/Stream.hx | 29 +- std/lua/lib/luv/Thread.hx | 14 +- std/lua/lib/luv/Timer.hx | 16 +- std/lua/lib/luv/Tty.hx | 17 +- std/lua/lib/luv/Work.hx | 8 +- std/lua/lib/luv/fs/FileDescriptor.hx | 2 +- std/lua/lib/luv/fs/FileSystem.hx | 273 +- std/lua/lib/luv/fs/FileSystemEvent.hx | 18 +- std/lua/lib/luv/fs/FileSystemPoll.hx | 13 +- std/lua/lib/luv/fs/Open.hx | 29 +- std/lua/lib/luv/net/Dns.hx | 21 +- std/lua/lib/luv/net/Tcp.hx | 26 +- std/lua/lib/luv/net/Udp.hx | 32 +- std/neko/Boot.hx | 103 +- std/neko/Lib.hx | 184 +- std/neko/NativeArray.hx | 27 +- std/neko/NativeString.hx | 17 +- std/neko/NativeXml.hx | 350 +- std/neko/Random.hx | 34 +- std/neko/Utf8.hx | 106 + std/neko/Web.hx | 264 +- std/neko/_std/Array.hx | 227 +- std/neko/_std/Date.hx | 116 +- std/neko/_std/EReg.hx | 168 +- std/neko/_std/Math.hx | 141 +- std/neko/_std/Reflect.hx | 160 +- std/neko/_std/Std.hx | 93 +- std/neko/_std/String.hx | 153 +- std/neko/_std/StringBuf.hx | 43 +- std/neko/_std/Sys.hx | 8 +- std/neko/_std/Type.hx | 2 +- std/neko/_std/haxe/Utf8.hx | 88 +- std/neko/_std/haxe/ds/IntMap.hx | 56 +- std/neko/_std/haxe/ds/ObjectMap.hx | 70 +- std/neko/_std/haxe/ds/StringMap.hx | 56 +- std/neko/_std/haxe/zip/Compress.hx | 39 +- std/neko/_std/haxe/zip/Uncompress.hx | 40 +- std/neko/_std/sys/FileSystem.hx | 70 +- std/neko/_std/sys/db/Mysql.hx | 134 +- std/neko/_std/sys/db/Sqlite.hx | 116 +- std/neko/_std/sys/io/File.hx | 46 +- std/neko/_std/sys/io/FileInput.hx | 50 +- std/neko/_std/sys/io/FileOutput.hx | 46 +- std/neko/_std/sys/io/Process.hx | 93 +- std/neko/_std/sys/net/Host.hx | 29 +- std/neko/_std/sys/net/Socket.hx | 192 +- std/neko/_std/sys/net/UdpSocket.hx | 29 +- std/neko/_std/sys/ssl/Certificate.hx | 153 +- std/neko/_std/sys/ssl/Digest.hx | 46 +- std/neko/_std/sys/ssl/Key.hx | 54 +- std/neko/_std/sys/ssl/Socket.hx | 309 +- std/neko/_std/sys/thread/Deque.hx | 49 + std/neko/_std/sys/thread/Lock.hx | 44 + std/neko/_std/sys/thread/Mutex.hx | 49 + std/neko/_std/sys/thread/Thread.hx | 124 + std/neko/_std/sys/thread/Tls.hx | 47 + std/neko/net/Poll.hx | 89 - std/neko/net/ProxyDetect.hx | 202 - std/neko/net/ServerLoop.hx | 231 - std/neko/net/ThreadRemotingServer.hx | 114 - std/neko/net/ThreadServer.hx | 360 -- std/neko/vm/Deque.hx | 44 +- std/neko/vm/Gc.hx | 19 +- std/neko/vm/Loader.hx | 60 +- std/neko/vm/Lock.hx | 36 +- std/neko/vm/Module.hx | 136 +- std/neko/vm/Mutex.hx | 50 +- std/neko/vm/Thread.hx | 117 +- std/neko/vm/Tls.hx | 41 +- std/neko/vm/Ui.hx | 49 +- std/neko/zip/Compress.hx | 7 +- std/neko/zip/Flush.hx | 7 +- std/neko/zip/Uncompress.hx | 7 +- std/php/ArrayAccess.hx | 34 +- std/php/Boot.hx | 571 ++- std/php/Closure.hx | 30 +- std/php/Const.hx | 593 ++- std/php/Error.hx | 32 +- std/php/ErrorException.hx | 25 +- std/php/Exception.hx | 32 +- std/php/Generator.hx | 91 + std/php/Global.hx | 745 ++-- std/php/IteratorAggregate.hx | 8 +- std/php/Lib.hx | 84 +- std/php/NativeArray.hx | 47 +- std/php/NativeAssocArray.hx | 33 +- std/php/NativeIndexedArray.hx | 57 +- std/php/NativeString.hx | 49 +- std/php/NativeStructArray.hx | 3 +- std/php/Ref.hx | 25 +- std/php/Resource.hx | 26 +- std/php/RuntimeException.hx | 24 +- std/php/Scalar.hx | 27 +- std/php/Session.hx | 83 +- std/php/SessionHandlerInterface.hx | 36 +- std/php/StdClass.hx | 26 +- std/php/SuperGlobal.hx | 149 +- std/php/Syntax.hx | 452 +- std/php/Throwable.hx | 42 +- std/php/Traversable.hx | 26 +- std/php/Web.hx | 377 +- std/php/_polyfills.php | 53 + std/php/_std/Array.hx | 130 +- std/php/_std/Date.hx | 88 +- std/php/_std/EReg.hx | 146 +- std/php/_std/Math.hx | 106 +- std/php/_std/Reflect.hx | 88 +- std/php/_std/Std.hx | 31 +- std/php/_std/String.hx | 43 +- std/php/_std/StringBuf.hx | 32 +- std/php/_std/StringTools.hx | 205 +- std/php/_std/Sys.hx | 73 +- std/php/_std/Type.hx | 232 +- std/php/_std/haxe/CallStack.hx | 100 +- std/php/_std/haxe/Json.hx | 22 +- std/php/_std/haxe/Resource.hx | 34 +- std/php/_std/haxe/Utf8.hx | 37 +- std/php/_std/haxe/crypto/Base64.hx | 75 + std/php/_std/haxe/crypto/Md5.hx | 13 +- std/php/_std/haxe/crypto/Sha1.hx | 11 +- std/php/_std/haxe/crypto/Sha224.hx | 11 +- std/php/_std/haxe/crypto/Sha256.hx | 11 +- std/php/_std/haxe/ds/IntMap.hx | 58 +- std/php/_std/haxe/ds/ObjectMap.hx | 31 +- std/php/_std/haxe/ds/StringMap.hx | 37 +- std/php/_std/haxe/ds/Vector.hx | 133 + std/php/_std/haxe/format/JsonParser.hx | 273 ++ std/php/_std/haxe/io/Bytes.hx | 139 +- std/php/_std/haxe/io/BytesBuffer.hx | 54 +- std/php/_std/haxe/io/BytesData.hx | 44 +- std/php/_std/haxe/io/BytesInput.hx | 53 +- std/php/_std/haxe/io/BytesOutput.hx | 23 +- std/php/_std/haxe/io/FPHelper.hx | 26 +- .../haxe/iterators/StringIteratorUnicode.hx} | 65 +- .../StringKeyValueIteratorUnicode.hx | 67 + std/php/_std/haxe/xml/Parser.hx | 401 ++ std/php/_std/haxe/zip/Compress.hx | 26 +- std/php/_std/haxe/zip/Uncompress.hx | 27 +- std/php/_std/sys/FileSystem.hx | 81 +- std/php/_std/sys/db/Mysql.hx | 179 +- std/php/_std/sys/db/Sqlite.hx | 93 +- std/php/_std/sys/io/File.hx | 28 +- std/php/_std/sys/io/FileInput.hx | 63 +- std/php/_std/sys/io/FileOutput.hx | 52 +- std/php/_std/sys/io/Process.hx | 168 +- std/php/_std/sys/net/Host.hx | 25 +- std/php/_std/sys/net/Socket.hx | 187 +- std/php/db/Mysqli.hx | 147 +- std/php/db/Mysqli_driver.hx | 40 +- std/php/db/Mysqli_result.hx | 76 +- std/php/db/Mysqli_stmt.hx | 76 +- std/php/db/Mysqli_warning.hx | 32 +- std/php/db/PDO.hx | 161 +- std/php/db/PDOException.hx | 26 +- std/php/db/PDOStatement.hx | 62 +- std/php/db/SQLite3.hx | 62 +- std/php/db/SQLite3Result.hx | 36 +- std/php/db/SQLite3Stmt.hx | 40 +- std/php/net/Socket.hx | 149 + std/php/net/SslSocket.hx | 9 +- std/php/reflection/ReflectionClass.hx | 132 +- .../reflection/ReflectionFunctionAbstract.hx | 80 +- std/php/reflection/ReflectionMethod.hx | 73 +- std/php/reflection/ReflectionProperty.hx | 63 +- std/php/reflection/Reflector.hx | 26 +- std/python/Boot.hx | 225 +- std/python/Bytearray.hx | 30 +- std/python/Bytes.hx | 9 +- std/python/Dict.hx | 19 +- std/python/Exceptions.hx | 293 +- std/python/HaxeIterable.hx | 10 +- std/python/HaxeIterator.hx | 8 +- std/python/KwArgs.hx | 14 +- std/python/Lib.hx | 85 +- std/python/NativeArrayTools.hx | 15 +- std/python/NativeIterable.hx | 28 +- std/python/NativeIterator.hx | 24 +- std/python/NativeStringTools.hx | 25 +- std/python/Set.hx | 5 +- std/python/Syntax.hx | 77 +- std/python/Tuple.hx | 73 +- std/python/VarArgs.hx | 3 +- std/python/_std/Array.hx | 86 +- std/python/_std/Date.hx | 151 +- std/python/_std/EReg.hx | 74 +- std/python/_std/Math.hx | 90 +- std/python/_std/Reflect.hx | 88 +- std/python/_std/Std.hx | 122 +- std/python/_std/String.hx | 38 +- std/python/_std/StringBuf.hx | 15 +- std/python/_std/Sys.hx | 68 +- std/python/_std/Type.hx | 169 +- std/python/_std/haxe/Json.hx | 12 +- std/python/_std/haxe/Resource.hx | 17 +- std/python/_std/haxe/ds/IntMap.hx | 42 +- std/python/_std/haxe/ds/ObjectMap.hx | 38 +- std/python/_std/haxe/ds/StringMap.hx | 43 +- std/python/_std/sys/FileSystem.hx | 51 +- std/python/_std/sys/io/File.hx | 32 +- std/python/_std/sys/io/FileInput.hx | 47 +- std/python/_std/sys/io/FileOutput.hx | 49 +- std/python/_std/sys/io/Process.hx | 44 +- std/python/_std/sys/net/Host.hx | 31 +- std/python/_std/sys/net/Socket.hx | 431 +- std/python/internal/AnonObject.hx | 3 +- std/python/internal/ArrayImpl.hx | 102 +- std/python/internal/EnumImpl.hx | 9 +- std/python/internal/HxException.hx | 4 +- std/python/internal/HxOverrides.hx | 71 +- std/python/internal/Internal.hx | 94 +- std/python/internal/MethodClosure.hx | 31 +- std/python/internal/StringImpl.hx | 62 +- std/python/internal/UBuiltins.hx | 49 +- std/python/io/FileBytesInput.hx | 7 +- std/python/io/FileBytesOutput.hx | 7 +- std/python/io/FileTextInput.hx | 5 +- std/python/io/FileTextOutput.hx | 7 +- std/python/io/IFileInput.hx | 13 +- std/python/io/IFileOutput.hx | 11 +- std/python/io/IInput.hx | 31 +- std/python/io/IOutput.hx | 39 +- std/python/io/IoTools.hx | 50 +- std/python/io/NativeBytesInput.hx | 26 +- std/python/io/NativeBytesOutput.hx | 24 +- std/python/io/NativeInput.hx | 29 +- std/python/io/NativeOutput.hx | 31 +- std/python/io/NativeTextInput.hx | 26 +- std/python/io/NativeTextOutput.hx | 23 +- std/python/lib/Builtins.hx | 178 +- std/python/lib/Codecs.hx | 5 +- std/python/lib/FileDescriptor.hx | 7 +- std/python/lib/FileObject.hx | 5 +- std/python/lib/Functools.hx | 8 +- std/python/lib/Glob.hx | 12 +- std/python/lib/Hashlib.hx | 12 +- std/python/lib/Inspect.hx | 9 +- std/python/lib/Io.hx | 9 +- std/python/lib/Json.hx | 36 +- std/python/lib/Math.hx | 9 +- std/python/lib/Msvcrt.hx | 12 +- std/python/lib/Os.hx | 41 +- std/python/lib/Pprint.hx | 12 +- std/python/lib/Random.hx | 3 +- std/python/lib/Re.hx | 94 +- std/python/lib/Select.hx | 7 +- std/python/lib/Shutil.hx | 15 +- std/python/lib/Socket.hx | 288 ++ std/python/lib/Ssl.hx | 63 + std/python/lib/Subprocess.hx | 12 +- std/python/lib/Sys.hx | 11 +- std/python/lib/Tempfile.hx | 7 +- std/python/lib/Termios.hx | 17 +- std/python/lib/ThreadLowLevel.hx | 7 +- std/python/lib/Threading.hx | 7 +- std/python/lib/Time.hx | 12 +- std/python/lib/Timeit.hx | 25 +- std/python/lib/Traceback.hx | 5 +- std/python/lib/Tty.hx | 9 +- std/python/lib/codecs/Codec.hx | 3 +- std/python/lib/codecs/StreamReader.hx | 5 +- std/python/lib/codecs/StreamReaderWriter.hx | 6 +- std/python/lib/codecs/StreamWriter.hx | 6 +- std/python/lib/datetime/Datetime.hx | 61 +- std/python/lib/datetime/Timedelta.hx | 16 +- std/python/lib/datetime/Timezone.hx | 6 +- std/python/lib/datetime/Tzinfo.hx | 6 +- std/python/lib/io/BlockingIOError.hx | 7 +- std/python/lib/io/BufferedIOBase.hx | 20 +- std/python/lib/io/BufferedRWPair.hx | 9 +- std/python/lib/io/BufferedRandom.hx | 9 +- std/python/lib/io/BufferedReader.hx | 11 +- std/python/lib/io/BufferedWriter.hx | 8 +- std/python/lib/io/BytesIO.hx | 9 +- std/python/lib/io/FileIO.hx | 10 +- std/python/lib/io/IOBase.hx | 17 +- std/python/lib/io/RawIOBase.hx | 9 +- std/python/lib/io/StringIO.hx | 10 +- std/python/lib/io/TextIOBase.hx | 22 +- std/python/lib/io/TextIOWrapper.hx | 22 +- std/python/lib/io/UnsupportedOperation.hx | 9 +- std/python/lib/json/JSONDecoder.hx | 21 +- std/python/lib/json/JSONEncoder.hx | 26 +- std/python/lib/net/Address.hx | 6 +- std/python/lib/net/Socket.hx | 363 +- std/python/lib/os/Path.hx | 63 +- std/python/lib/socket/Address.hx | 25 + std/python/lib/socket/Socket.hx | 113 + std/python/lib/ssl/Purpose.hx | 30 + std/python/lib/ssl/SSLContext.hx | 50 + std/python/lib/ssl/SSLSession.hx | 27 + std/python/lib/ssl/SSLSocket.hx | 26 + std/python/lib/subprocess/Popen.hx | 73 +- std/python/lib/threading/Lock.hx | 11 +- std/python/lib/threading/RLock.hx | 11 +- std/python/lib/threading/Thread.hx | 33 +- std/python/lib/time/StructTime.hx | 12 +- std/python/lib/urllib/Parse.hx | 5 +- std/python/lib/xml/etree/ElementTree.hx | 40 +- std/python/net/SslSocket.hx | 58 + std/sys/FileStat.hx | 32 +- std/sys/FileSystem.hx | 62 +- std/sys/Http.hx | 498 +++ std/sys/db/Connection.hx | 25 +- std/sys/db/Mysql.hx | 21 +- std/sys/db/ResultSet.hx | 24 +- std/sys/db/Sqlite.hx | 16 +- std/sys/io/File.hx | 29 +- std/sys/io/FileInput.hx | 11 +- std/sys/io/FileOutput.hx | 9 +- std/sys/io/FileSeek.hx | 3 +- std/sys/io/Process.hx | 36 +- std/sys/net/Address.hx | 21 +- std/sys/net/Host.hx | 17 +- std/sys/net/Socket.hx | 61 +- std/sys/net/UdpSocket.hx | 16 +- std/sys/ssl/Certificate.hx | 70 +- std/sys/ssl/Digest.hx | 32 +- std/sys/ssl/DigestAlgorithm.hx | 25 +- std/sys/ssl/Key.hx | 30 +- std/sys/ssl/Socket.hx | 50 +- .../thread/Deque.hx} | 46 +- std/sys/thread/Lock.hx | 80 + std/sys/thread/Mutex.hx | 59 + std/sys/thread/Thread.hx | 50 + std/sys/thread/Tls.hx | 45 + tests/Brewfile | 5 +- tests/Indexer.hx | 112 - tests/RunCi.hx | 31 +- tests/RunCi.hxml | 2 +- tests/TestMakefile.hxml | 2 +- tests/benchs/build.hxml | 6 + tests/benchs/ds/src/Main.hx | 143 - tests/benchs/ds/tests.hxml | 3 - tests/benchs/mandelbrot/compile-cpp.hxml | 4 +- tests/benchs/mandelbrot/compile-cppia.hxml | 4 +- tests/benchs/mandelbrot/compile-hl.hxml | 19 +- tests/benchs/mandelbrot/compile-java.hxml | 4 +- tests/benchs/mandelbrot/compile-js.hxml | 4 +- tests/benchs/mandelbrot/compile-jvm.hxml | 9 + tests/benchs/mandelbrot/compile-macro.hxml | 4 +- tests/benchs/mandelbrot/compile-neko.hxml | 4 +- tests/benchs/mandelbrot/compile-php.hxml | 4 +- tests/benchs/mtnetwork/MTNetwork.hx | 271 -- tests/benchs/src/Macro.hx | 59 + tests/benchs/src/Main.hx | 17 + tests/benchs/src/TestCase.hx | 11 + tests/benchs/src/cases/Access.hx | 102 + tests/benchs/src/cases/Calls.hx | 146 + tests/benchs/src/cases/CharacterAccess.hx | 106 + tests/benchs/src/cases/CustomIterator.hx | 102 + tests/benchs/src/cases/Ds.hx | 131 + tests/benchs/src/cases/StringIterator.hx | 71 + tests/benchs/src/cases/StringScan.hx | 21 + tests/benchs/src/hxbenchmark/CaseResult.hx | 6 + tests/benchs/src/hxbenchmark/ResultPrinter.hx | 66 + tests/benchs/src/hxbenchmark/Suite.hx | 54 + tests/benchs/src/hxbenchmark/SuiteResult.hx | 6 + tests/display/.gitignore | 1 + tests/display/build.hxml | 7 +- tests/display/src-shared/Marker.hx | 21 + tests/display/src/Diagnostic.hx | 29 + tests/display/src/DisplayTestCase.hx | 134 +- tests/display/src/DisplayTestContext.hx | 69 +- tests/display/src/File.hx | 63 +- tests/display/src/Macro.hx | 75 +- tests/display/src/Main.hx | 34 +- tests/display/src/ModuleSymbolEntry.hx | 33 +- tests/display/src/SignatureHelp.hx | 18 +- tests/display/src/Types.hx | 11 +- tests/display/src/cases/Abstract.hx | 43 +- .../display/src/cases/ArrayAccessSignature.hx | 117 + tests/display/src/cases/ArrowFunctions.hx | 80 +- tests/display/src/cases/Basic.hx | 90 +- tests/display/src/cases/BuildMacro.hx | 34 +- tests/display/src/cases/Completion.hx | 62 +- tests/display/src/cases/DocumentSymbols.hx | 106 +- tests/display/src/cases/IImport.hx | 42 +- tests/display/src/cases/InMacro.hx | 36 + tests/display/src/cases/Issue4155.hx | 33 + tests/display/src/cases/Issue4345.hx | 35 + tests/display/src/cases/Issue5141.hx | 34 +- tests/display/src/cases/Issue5166.hx | 10 +- tests/display/src/cases/Issue5171.hx | 10 +- tests/display/src/cases/Issue5172.hx | 14 +- tests/display/src/cases/Issue5173.hx | 14 +- tests/display/src/cases/Issue5306.hx | 38 + tests/display/src/cases/Issue5649.hx | 13 + tests/display/src/cases/Issue5684.hx | 10 +- tests/display/src/cases/Issue5712.hx | 18 +- tests/display/src/cases/Issue5729.hx | 20 +- tests/display/src/cases/Issue5767.hx | 109 + tests/display/src/cases/Issue5775.hx | 12 +- tests/display/src/cases/Issue5796.hx | 16 +- tests/display/src/cases/Issue5967.hx | 15 + tests/display/src/cases/Issue5988.hx | 12 +- tests/display/src/cases/Issue5999.hx | 16 + tests/display/src/cases/Issue6004.hx | 12 +- tests/display/src/cases/Issue6020.hx | 27 + tests/display/src/cases/Issue6029.hx | 4 +- tests/display/src/cases/Issue6068.hx | 23 +- tests/display/src/cases/Issue6227.hx | 19 + tests/display/src/cases/Issue6265.hx | 26 + tests/display/src/cases/Issue6275.hx | 16 +- tests/display/src/cases/Issue6381.hx | 16 +- tests/display/src/cases/Issue6396.hx | 14 +- tests/display/src/cases/Issue6399.hx | 12 +- tests/display/src/cases/Issue6405.hx | 27 + tests/display/src/cases/Issue6416.hx | 14 +- tests/display/src/cases/Issue6417.hx | 10 +- tests/display/src/cases/Issue6421.hx | 18 +- tests/display/src/cases/Issue6422.hx | 16 +- tests/display/src/cases/Issue6423.hx | 14 +- tests/display/src/cases/Issue6434.hx | 16 +- tests/display/src/cases/Issue6442.hx | 6 +- tests/display/src/cases/Issue6740.hx | 26 + tests/display/src/cases/Issue6756.hx | 12 + tests/display/src/cases/Issue6779.hx | 18 + tests/display/src/cases/Issue6923.hx | 34 + tests/display/src/cases/Issue6943.hx | 14 + tests/display/src/cases/Issue6951.hx | 21 + tests/display/src/cases/Issue6997.hx | 17 + tests/display/src/cases/Issue7020.hx | 18 + tests/display/src/cases/Issue7022.hx | 16 + tests/display/src/cases/Issue7023.hx | 16 + tests/display/src/cases/Issue7027.hx | 11 + tests/display/src/cases/Issue7029.hx | 133 + tests/display/src/cases/Issue7046.hx | 12 + tests/display/src/cases/Issue7047.hx | 14 + tests/display/src/cases/Issue7050.hx | 14 + tests/display/src/cases/Issue7051.hx | 43 + tests/display/src/cases/Issue7053.hx | 188 + tests/display/src/cases/Issue7055.hx | 35 + tests/display/src/cases/Issue7057.hx | 17 + tests/display/src/cases/Issue7059.hx | 16 + tests/display/src/cases/Issue7060.hx | 14 + tests/display/src/cases/Issue7061.hx | 31 + tests/display/src/cases/Issue7063.hx | 19 + tests/display/src/cases/Issue7066.hx | 27 + tests/display/src/cases/Issue7068.hx | 33 + tests/display/src/cases/Issue7069.hx | 26 + tests/display/src/cases/Issue7071.hx | 19 + tests/display/src/cases/Issue7072.hx | 27 + tests/display/src/cases/Issue7075.hx | 26 + tests/display/src/cases/Issue7082.hx | 16 + tests/display/src/cases/Issue7084.hx | 34 + tests/display/src/cases/Issue7086.hx | 14 + tests/display/src/cases/Issue7089.hx | 18 + tests/display/src/cases/Issue7092.hx | 18 + tests/display/src/cases/Issue7098.hx | 16 + tests/display/src/cases/Issue7102.hx | 15 + tests/display/src/cases/Issue7111.hx | 14 + tests/display/src/cases/Issue7114.hx | 66 + tests/display/src/cases/Issue7133.hx | 16 + tests/display/src/cases/Issue7136.hx | 25 + tests/display/src/cases/Issue7137.hx | 32 + tests/display/src/cases/Issue7148.hx | 19 + tests/display/src/cases/Issue7158.hx | 14 + tests/display/src/cases/Issue7171.hx | 14 + tests/display/src/cases/Issue7172.hx | 35 + tests/display/src/cases/Issue7211.hx | 12 + tests/display/src/cases/Issue7219.hx | 60 + tests/display/src/cases/Issue7224.hx | 24 + tests/display/src/cases/Issue7248.hx | 19 + tests/display/src/cases/Issue7252.hx | 17 + tests/display/src/cases/Issue7281.hx | 47 + tests/display/src/cases/Issue7319.hx | 21 + tests/display/src/cases/Issue7320.hx | 63 + tests/display/src/cases/Issue7326.hx | 23 + tests/display/src/cases/Issue7327.hx | 71 + tests/display/src/cases/Issue7328.hx | 19 + tests/display/src/cases/Issue7471.hx | 11 + tests/display/src/cases/Issue7577.hx | 17 + tests/display/src/cases/Issue7627.hx | 19 + tests/display/src/cases/Issue7650.hx | 19 + tests/display/src/cases/Issue7751.hx | 12 + tests/display/src/cases/Issue7752.hx | 21 + tests/display/src/cases/Issue7761.hx | 21 + tests/display/src/cases/Issue7777.hx | 26 + tests/display/src/cases/Issue7877.hx | 15 + tests/display/src/cases/Issue7878.hx | 14 + tests/display/src/cases/Issue7906.hx | 24 + tests/display/src/cases/Issue7911.hx | 10 + tests/display/src/cases/Issue7932.hx | 19 + tests/display/src/cases/Issue7935.hx | 47 + tests/display/src/cases/Issue7937.hx | 18 + tests/display/src/cases/Issue7938.hx | 19 + tests/display/src/cases/Issue7939.hx | 17 + tests/display/src/cases/Issue7940.hx | 21 + tests/display/src/cases/Issue7943.hx | 27 + tests/display/src/cases/Issue7945.hx | 31 + tests/display/src/cases/Issue7946.hx | 31 + tests/display/src/cases/Issue7947.hx | 55 + tests/display/src/cases/Issue7972.hx | 20 + tests/display/src/cases/Issue7998.hx | 16 + tests/display/src/cases/Issue8007.hx | 23 + tests/display/src/cases/Issue8014.hx | 24 + tests/display/src/cases/Issue8046.hx | 18 + tests/display/src/cases/Issue8078.hx | 21 + tests/display/src/cases/Issue8180.hx | 25 + tests/display/src/cases/Issue8217.hx | 22 + tests/display/src/cases/Issue8345.hx | 21 + tests/display/src/cases/Issue8359.hx | 25 + tests/display/src/cases/Issue8383.hx | 15 + tests/display/src/cases/Issue8396.hx | 19 + tests/display/src/cases/Issue8420.hx | 16 + tests/display/src/cases/Issue8459.hx | 14 + tests/display/src/cases/Issue8558.hx | 25 + tests/display/src/cases/IssueTemplate.hx | 14 + tests/display/src/cases/Metadata.hx | 75 +- tests/display/src/cases/Override.hx | 56 + tests/display/src/cases/PropertyAccessors.hx | 16 +- tests/display/src/cases/Resuming.hx | 22 + tests/display/src/cases/Signature.hx | 203 +- tests/display/src/cases/StaticExtension.hx | 70 + .../display/src/cases/StructureCompletion.hx | 186 +- tests/display/src/cases/Super.hx | 30 +- tests/display/src/cases/Toplevel.hx | 273 +- tests/display/src/cases/Type.hx | 4 +- tests/display/src/cases/TypeHints.hx | 83 + tests/display/src/cases/VsHaxeIssue198.hx | 13 + .../display/src/cases/_issue5417/Issue5417.hx | 15 + tests/display/src/cases/import.hx | 3 + tests/display/src/import.hx | 1 + .../display/src/misc/ModuleWithPrivateType.hx | 4 +- tests/display/src/misc/issue7098/Bar.hx | 9 + tests/display/src/misc/issue7777/Foo.hx | 11 + tests/display/src/misc/issue7777/Thing.hx | 5 + .../src/misc/issue7877/ProcessMacro.hx | 40 + .../src/misc/issue7877/ProcessedClass.hx | 9 + tests/display/src/misc/issue7911/Test.hx | 2 + tests/display/src/misc/issue7911/import.hx | 2 + tests/echoServer/.gitignore | 1 + tests/echoServer/EchoServer.hx | 6 + tests/echoServer/build.hxml | 2 + tests/echoServer/www/crossdomain.xml | 7 + tests/misc/README.md | 31 + tests/misc/compile.hxml | 4 +- .../projects/Issue5189/Main.hx} | 0 .../projects/Issue5189/compile-fail.hxml | 1 + .../Issue5189/compile-fail.hxml.stderr | 3 + .../compiler_loops/projects/Issue5345/Main.hx | 5 + .../projects/Issue5345/Main2.hx | 6 + .../projects/Issue5345/Main3.hx | 6 + .../projects/Issue5345/compile-fail.hxml | 1 + .../Issue5345/compile-fail.hxml.stderr | 1 + .../projects/Issue5345/compile2-fail.hxml | 1 + .../Issue5345/compile2-fail.hxml.stderr | 1 + .../projects/Issue5345/compile3-fail.hxml | 1 + .../Issue5345/compile3-fail.hxml.stderr | 1 + .../projects/Issue5785/Main1.hx | 16 + .../projects/Issue5785/Main2.hx | 10 + .../projects/Issue5785/Main3.hx | 9 + .../projects/Issue5785/compile1.hxml | 1 + .../projects/Issue5785/compile2.hxml | 1 + .../projects/Issue5785/compile3.hxml | 1 + .../compiler_loops/projects/Issue6038/Main.hx | 14 + .../projects/Issue6038/compile.hxml | 1 + .../compiler_loops/projects/Issue7733/Main.hx | 11 + .../projects/Issue7733/compile.hxml | 1 + .../compiler_loops/projects/Issue8588/Main.hx | 9 + .../projects/Issue8588/Main2.hx | 9 + .../projects/Issue8588/Main3.hx | 9 + .../projects/Issue8588/Main4.hx | 9 + .../projects/Issue8588/Main5.hx | 9 + .../projects/Issue8588/compile-fail.hxml | 1 + .../Issue8588/compile-fail.hxml.stderr | 1 + .../projects/Issue8588/compile2-fail.hxml | 1 + .../Issue8588/compile2-fail.hxml.stderr | 1 + .../projects/Issue8588/compile3-fail.hxml | 1 + .../Issue8588/compile3-fail.hxml.stderr | 1 + .../projects/Issue8588/compile4-fail.hxml | 1 + .../Issue8588/compile4-fail.hxml.stderr | 1 + .../projects/Issue8588/compile5-fail.hxml | 1 + .../Issue8588/compile5-fail.hxml.stderr | 1 + tests/misc/compiler_loops/run.hxml | 3 + tests/misc/cppObjc/build.hxml | 4 +- tests/misc/{ => cs}/csTwoLibs/.gitignore | 0 tests/misc/{ => cs}/csTwoLibs/Lib1.hx | 0 tests/misc/{ => cs}/csTwoLibs/Main.hx | 0 tests/misc/cs/csTwoLibs/compile-1.hxml | 15 + tests/misc/{ => cs}/csTwoLibs/compile-2.hxml | 12 +- tests/misc/{ => cs}/csTwoLibs/compile-3.hxml | 12 +- tests/misc/{ => cs}/csTwoLibs/compile-4.hxml | 12 +- tests/misc/cs/projects/Issue3526/.gitignore | 1 + .../Issue3526/IncompatibleCombinations.hx | 28 + tests/misc/cs/projects/Issue3526/Main.hx | 72 + .../cs/projects/Issue3526/compile-7.3.hxml | 4 + tests/misc/cs/projects/Issue3526/compile.hxml | 2 + .../incompatible-combinations-fail.hxml | 4 + ...incompatible-combinations-fail.hxml.stderr | 8 + tests/misc/cs/projects/Issue3703/Main.hx | 15 + tests/misc/cs/projects/Issue3703/Test.hx | 15 + tests/misc/cs/projects/Issue3703/compile.hxml | 3 + tests/misc/cs/projects/Issue4002/Main.hx | 19 + tests/misc/cs/projects/Issue4002/compile.hxml | 3 + .../{ => cs}/projects/Issue4116/.gitignore | 0 .../{ => cs}/projects/Issue4116/base/A.hx | 0 .../{ => cs}/projects/Issue4116/compile.hxml | 0 .../projects/Issue4151/Main.hx} | 0 tests/misc/cs/projects/Issue4151/compile.hxml | 3 + tests/misc/cs/projects/Issue4598/Main.hx | 16 + tests/misc/cs/projects/Issue4598/Run.hx | 11 + tests/misc/cs/projects/Issue4598/compile.hxml | 4 + tests/misc/cs/projects/Issue4623/Main.hx | 59 + tests/misc/cs/projects/Issue4623/Run.hx | 11 + tests/misc/cs/projects/Issue4623/compile.hxml | 4 + tests/misc/cs/projects/Issue5434/Main.hx | 6 + tests/misc/cs/projects/Issue5434/compile.hxml | 2 + tests/misc/cs/projects/Issue5915/Test.hx | 20 + tests/misc/cs/projects/Issue5915/compile.hxml | 2 + tests/misc/cs/projects/Issue5953/Main.hx | 17 + tests/misc/cs/projects/Issue5953/Reduced.hx | 10 + tests/misc/cs/projects/Issue5953/compile.hxml | 3 + tests/misc/cs/projects/Issue7875/Main.hx | 23 + tests/misc/cs/projects/Issue7875/compile.hxml | 3 + tests/misc/cs/projects/Issue8361/Main.hx | 22 + tests/misc/cs/projects/Issue8361/compile.hxml | 2 + tests/misc/cs/projects/Issue8366/Main.hx | 22 + tests/misc/cs/projects/Issue8366/compile.hxml | 3 + tests/misc/cs/run.hxml | 2 + tests/misc/csTwoLibs/compile-1.hxml | 15 - tests/misc/es6/.gitignore | 1 + tests/misc/es6/Test.hx | 156 + tests/misc/es6/extern.js | 1 + tests/misc/es6/run.hxml | 4 + tests/misc/eventLoop/all.hxml | 6 +- tests/misc/java/projects/Issue8322/Main.hx | 7 + .../misc/java/projects/Issue8322/compile.hxml | 3 + tests/misc/java/projects/Issue8444/Main.hx | 15 + .../misc/java/projects/Issue8444/compile.hxml | 3 + tests/misc/java/run.hxml | 2 + .../luaDeadCode/stringReflection/compile.hxml | 4 +- tests/misc/php/projects/.gitignore | 1 + .../misc/php/projects/Issue7725/compile.hxml | 17 + tests/misc/php/projects/Issue7725/run.php | 6 + tests/misc/php/projects/Issue7725/src/App1.hx | 7 + tests/misc/php/projects/Issue7725/src/App2.hx | 7 + .../misc/php/projects/Issue8249/compile.hxml | 4 + tests/misc/php/projects/Issue8249/src/Main.hx | 10 + tests/misc/php/run.hxml | 2 + tests/misc/projects/Issue1138/compile1.hxml | 6 +- tests/misc/projects/Issue1138/compile2.hxml | 6 +- .../projects/Issue1138/compile3-fail.hxml | 6 +- .../Issue1138/compile3-fail.hxml.stderr | 2 +- .../projects/Issue1138/compile4-fail.hxml | 4 +- .../projects/Issue1310/compile1-fail.hxml | 2 +- tests/misc/projects/Issue1968/compile.hxml | 2 +- .../projects/Issue1968/compile.hxml.stderr | 2 +- .../misc/projects/Issue2087/compile-fail.hxml | 2 +- .../projects/Issue2148/compile1-fail.hxml | 2 +- .../projects/Issue2232/compile1-fail.hxml | 2 +- .../projects/Issue2232/compile2-fail.hxml | 2 +- .../Issue2263/import-completion.hxml.stderr | 4 +- .../Issue2263/type-completion.hxml.stderr | 4 +- tests/misc/projects/Issue2508/compile.hxml | 2 +- .../projects/Issue2508/compile.hxml.stderr | 14 +- .../misc/projects/Issue2538/compile-fail.hxml | 2 +- tests/misc/projects/Issue2991/compile.hxml | 2 +- tests/misc/projects/Issue2993/compile.hxml | 2 +- tests/misc/projects/Issue2995/position.hxml | 2 +- .../projects/Issue2995/position.hxml.stderr | 2 +- tests/misc/projects/Issue2995/usage.hxml | 2 +- tests/misc/projects/Issue2997/Main.hx | 2 +- tests/misc/projects/Issue2997/compile1.hxml | 2 +- .../projects/Issue2997/compile1.hxml.stderr | 2 +- .../misc/projects/Issue3102/compile-each.hxml | 7 +- .../projects/Issue3102/compile2-each.hxml | 7 +- tests/misc/projects/Issue3129/compile.hxml | 3 +- tests/misc/projects/Issue3181/Main.hx | 8 + .../misc/projects/Issue3181/compile-fail.hxml | 3 + .../Issue3181/compile-fail.hxml.stderr | 1 + .../projects/Issue3192/compile1-fail.hxml | 2 +- tests/misc/projects/Issue3256/Main.hx | 10 - tests/misc/projects/Issue3256/compile.hxml | 1 - .../projects/Issue3256/compile.hxml.stderr | 4 - tests/misc/projects/Issue3261/Main.hx | 11 - tests/misc/projects/Issue3261/compile.hxml | 1 - .../projects/Issue3261/compile.hxml.stderr | 4 - .../Issue3361/compile1-fail.hxml.stderr | 7 +- .../Issue3361/compile2-fail.hxml.stderr | 9 +- .../Issue3417/compile-fail.hxml.stderr | 4 +- .../Issue3457/compile-fail.hxml.stderr | 2 +- tests/misc/projects/Issue3542/compile.hxml | 2 +- .../Issue3607/compile-fail.hxml.stderr | 2 +- tests/misc/projects/Issue3621/Main1.hx | 2 +- .../misc/projects/Issue3621/compile-fail.hxml | 2 +- .../Issue3678/compile-fail.hxml.stderr | 4 +- .../Issue3699/compile-var-fail.hxml.stderr | 3 +- .../misc/projects/Issue3714/compile-fail.hxml | 2 +- .../Issue3726/compile-2-fail.hxml.stderr | 2 +- .../misc/projects/Issue3783/compile-fail.hxml | 2 +- tests/misc/projects/Issue3830/Main.hx | 12 - .../misc/projects/Issue3830/compile-fail.hxml | 2 +- tests/misc/projects/Issue3830/compile.hxml | 2 - .../projects/Issue3830/compile.hxml.stderr | 3 - tests/misc/projects/Issue3911/Main1.hx | 7 - tests/misc/projects/Issue3911/Main2.hx | 7 - tests/misc/projects/Issue3911/Main3.hx | 7 - tests/misc/projects/Issue3911/compile1.hxml | 1 - .../projects/Issue3911/compile1.hxml.stderr | 3 - tests/misc/projects/Issue3911/compile2.hxml | 1 - .../projects/Issue3911/compile2.hxml.stderr | 3 - tests/misc/projects/Issue3911/compile3.hxml | 1 - .../projects/Issue3911/compile3.hxml.stderr | 3 - .../projects/Issue3931/compile2.hxml.stderr | 4 +- tests/misc/projects/Issue3956/compile.hxml | 3 +- .../misc/projects/Issue3975/compile-fail.hxml | 2 +- .../projects/Issue4114/compile1-fail.hxml | 2 +- .../projects/Issue4114/compile2-fail.hxml | 2 +- tests/misc/projects/Issue4160/compile.hxml | 2 +- .../misc/projects/Issue4247/compile-fail.hxml | 2 +- .../misc/projects/Issue4250/compile-fail.hxml | 2 +- .../Issue4250/compile-fail.hxml.stderr | 8 +- tests/misc/projects/Issue4265/compile.hxml | 3 +- .../misc/projects/Issue4364/compile-fail.hxml | 2 +- .../misc/projects/Issue4378/compile-fail.hxml | 2 +- .../Issue4378/compile-fail.hxml.stderr | 5 +- tests/misc/projects/Issue4399/compile.hxml | 3 +- tests/misc/projects/Issue4404/compile1.hxml | 4 +- .../projects/Issue4448/compile1-fail.hxml | 2 +- tests/misc/projects/Issue4454/compile.hxml | 2 +- tests/misc/projects/Issue4456/compile.hxml | 3 +- tests/misc/projects/Issue4458/Main.hx | 7 + .../projects/Issue4458/compile-pass1.hxml | 2 + .../projects/Issue4458/compile-pass2.hxml | 2 + .../projects/Issue4458/compile1-fail.hxml | 2 + .../Issue4458/compile1-fail.hxml.stderr | 1 + .../projects/Issue4458/compile2-fail.hxml | 3 + .../Issue4458/compile2-fail.hxml.stderr | 1 + .../misc/projects/Issue4466/compile-fail.hxml | 2 +- tests/misc/projects/Issue4540/Main.hx | 2 +- .../misc/projects/Issue4540/compile-fail.hxml | 2 +- .../Issue4540/compile-fail.hxml.stderr | 6 +- tests/misc/projects/Issue4563/compile.hxml | 3 +- .../misc/projects/Issue4580/compile-fail.hxml | 2 +- .../Issue4580/compile-fail.hxml.stderr | 2 +- .../projects/Issue4671/compile1-fail.hxml | 2 +- .../Issue4671/compile1-fail.hxml.stderr | 2 +- .../projects/Issue4671/compile2-fail.hxml | 2 +- .../Issue4671/compile2-fail.hxml.stderr | 2 +- tests/misc/projects/Issue4679/compile.hxml | 5 +- .../misc/projects/Issue4689/compile-fail.hxml | 2 +- tests/misc/projects/Issue4712/compile.hxml | 2 +- tests/misc/projects/Issue4720/compile.hxml | 2 +- .../projects/Issue4720/compile.hxml.stderr | 2 + tests/misc/projects/Issue4720/compile2.hxml | 3 + .../projects/Issue4720/compile2.hxml.stderr | 0 .../misc/projects/Issue4742/compile-fail.hxml | 2 +- .../projects/Issue4754/compile1-fail.hxml | 2 +- .../projects/Issue4761/compile1-fail.hxml | 2 +- .../projects/Issue4764/compile1-fail.hxml | 2 +- .../projects/Issue4766/compile1-fail.hxml | 2 +- .../projects/Issue4775/compile1-fail.hxml | 2 +- tests/misc/projects/Issue4803/Main.hx | 14 +- .../misc/projects/Issue4803/compile-fail.hxml | 2 +- .../Issue4803/compile-fail.hxml.stderr | 17 +- .../projects/Issue4816/compile1-fail.hxml | 2 +- .../Issue4816/compile1-fail.hxml.stderr | 2 +- tests/misc/projects/Issue4825/compile.hxml | 2 +- tests/misc/projects/Issue4891/Main.hx | 8 + .../misc/projects/Issue4891/compile-fail.hxml | 2 + .../Issue4891/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue4904/Main.hx | 3 +- .../misc/projects/Issue4904/compile-fail.hxml | 2 +- .../Issue4904/compile-fail.hxml.stderr | 2 +- tests/misc/projects/Issue4907/Main.hx | 3 +- .../misc/projects/Issue4907/compile-fail.hxml | 2 +- .../misc/projects/Issue4954/compile-fail.hxml | 2 +- .../misc/projects/Issue4957/compile-fail.hxml | 2 +- .../misc/projects/Issue4982/compile-fail.hxml | 2 +- tests/misc/projects/Issue5005/compile.hxml | 2 +- tests/misc/projects/Issue5008/Main.hx | 17 + .../misc/projects/Issue5008/compile-fail.hxml | 1 + .../Issue5008/compile-fail.hxml.stderr | 4 + .../misc/projects/Issue5010/compile-fail.hxml | 2 +- tests/misc/projects/Issue5039/Main.hx | 5 + tests/misc/projects/Issue5039/Main2.hx | 6 + .../misc/projects/Issue5039/compile-fail.hxml | 2 + .../Issue5039/compile-fail.hxml.stderr | 1 + .../projects/Issue5039/compile2-fail.hxml | 2 + .../Issue5039/compile2-fail.hxml.stderr | 1 + .../projects/Issue5118/compile1.hxml.stderr | 2 +- tests/misc/projects/Issue5122/compile.hxml | 2 +- .../projects/Issue5123/compile.hxml.stderr | 2 +- .../misc/projects/Issue5126/compile-fail.hxml | 2 +- tests/misc/projects/Issue5145/compile.hxml | 2 +- tests/misc/projects/Issue5205/Main.hx | 9 + .../misc/projects/Issue5205/compile-fail.hxml | 1 + .../Issue5205/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue5206/Main.hx | 4 +- .../misc/projects/Issue5206/compile-fail.hxml | 2 +- .../Issue5206/compile-fail.hxml.stderr | 4 - .../misc/projects/Issue5268/compile-fail.hxml | 2 +- tests/misc/projects/Issue5321/compile.hxml | 2 +- .../misc/projects/Issue5375/compile-fail.hxml | 2 +- .../Issue5375/compile-fail.hxml.stderr | 2 +- tests/misc/projects/Issue5525/Main.hx | 26 + .../misc/projects/Issue5525/compile-fail.hxml | 1 + .../Issue5525/compile-fail.hxml.stderr | 3 + tests/misc/projects/Issue5559/build.hxml | 4 +- .../misc/projects/Issue5644/compile-fail.hxml | 2 +- tests/misc/projects/Issue5833/Main.hx | 2 +- .../misc/projects/Issue5833/compile-fail.hxml | 2 +- tests/misc/projects/Issue5843/Data.hx | 8 + tests/misc/projects/Issue5843/Macro.hx | 45 + tests/misc/projects/Issue5843/Main.hx | 15 + tests/misc/projects/Issue5843/Transform.hx | 4 + tests/misc/projects/Issue5843/compile.hxml | 2 + tests/misc/projects/Issue5856/compile.hxml | 2 +- tests/misc/projects/Issue5871/Main.hx | 14 + tests/misc/projects/Issue5871/Main2.hx | 15 + .../Issue5871/parent-constructor-fail.hxml | 2 + .../parent-constructor-fail.hxml.stderr | 1 + .../Issue5871/parent-no-constructor-fail.hxml | 2 + .../parent-no-constructor-fail.hxml.stderr | 1 + .../misc/projects/Issue5888/compile-fail.hxml | 2 +- .../Issue5888/compile-fail.hxml.stderr | 2 +- tests/misc/projects/Issue5924/Main.hx | 21 + .../misc/projects/Issue5924/compile-fail.hxml | 2 + .../Issue5924/compile-fail.hxml.stderr | 1 + .../misc/projects/Issue5940/compile-fail.hxml | 2 +- .../Issue5940/compile-fail.hxml.stderr | 2 +- tests/misc/projects/Issue5946/Main.hx | 13 + .../misc/projects/Issue5946/compile-fail.hxml | 1 + .../Issue5946/compile-fail.hxml.stderr | 4 + tests/misc/projects/Issue5949/Main.hx | 12 + .../misc/projects/Issue5949/compile-fail.hxml | 1 + .../Issue5949/compile-fail.hxml.stderr | 3 + tests/misc/projects/Issue6005/Main.hx | 11 + tests/misc/projects/Issue6005/compile1.hxml | 1 + tests/misc/projects/Issue6006/Macro.hx | 27 + tests/misc/projects/Issue6006/Main.hx | 8 + tests/misc/projects/Issue6006/compile.hxml | 1 + tests/misc/projects/Issue6030/Main1.hx | 6 +- .../misc/projects/Issue6030/compile-fail.hxml | 2 +- .../Issue6030/compile-fail.hxml.stderr | 2 +- tests/misc/projects/Issue6201/Main1.hx | 5 + tests/misc/projects/Issue6201/Main2.hx | 5 + .../Issue6201/compile1-fail.hxml.disabled | 1 + .../Issue6201/compile1-fail.hxml.stderr | 1 + .../projects/Issue6201/compile2-fail.hxml | 1 + .../Issue6201/compile2-fail.hxml.stderr | 1 + tests/misc/projects/Issue6226/Main.hx | 9 + tests/misc/projects/Issue6226/compile.hxml | 1 + .../projects/Issue6226/compile.hxml.stderr | 1 + tests/misc/projects/Issue6340/Main.hx | 13 + .../misc/projects/Issue6340/compile-fail.hxml | 1 + .../Issue6340/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue6402/compile.hxml | 2 +- tests/misc/projects/Issue6427/E.hx | 3 + tests/misc/projects/Issue6427/Main.hx | 6 + tests/misc/projects/Issue6427/T.hx | 2 + tests/misc/projects/Issue6427/compile.hxml | 2 + .../projects/Issue6427/compile.hxml.stderr | 1 + .../misc/projects/Issue6445/compile-fail.hxml | 2 +- tests/misc/projects/Issue6525/Main.hx | 23 + .../misc/projects/Issue6525/compile-fail.hxml | 1 + .../Issue6525/compile-fail.hxml.stderr | 2 + .../misc/projects/Issue6525/pack/BasePack.hx | 12 + tests/misc/projects/Issue6525/pack/IPack.hx | 3 + tests/misc/projects/Issue6525/pack/Pvt.hx | 17 + .../Issue6525/pack/sub/AccessSubPvt.hx | 7 + .../projects/Issue6525/pack/sub/ExtSubPvt.hx | 5 + .../projects/Issue6525/pack/sub/SubPvt.hx | 6 + .../misc/projects/Issue6542/compile-fail.hxml | 2 +- .../misc/projects/Issue6550/compile-fail.hxml | 2 +- tests/misc/projects/Issue6583/compile.hxml | 2 +- .../Issue6584/compile1-fail.hxml.stderr | 2 +- tests/misc/projects/Issue6699/Main.hx | 16 + .../misc/projects/Issue6699/compile-fail.hxml | 2 + .../Issue6699/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue6707/Main.hx | 7 + .../misc/projects/Issue6707/compile-fail.hxml | 2 + .../Issue6707/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue6714/Main.hx | 19 + .../misc/projects/Issue6714/compile-fail.hxml | 2 + .../Issue6714/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue6757/Test.hx | 12 + .../misc/projects/Issue6757/compile-fail.hxml | 2 + .../Issue6757/compile-fail.hxml.stderr | 4 + tests/misc/projects/Issue6765/Main.hx | 10 + .../misc/projects/Issue6765/compile-fail.hxml | 2 + .../Issue6765/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue6772/Main.hx | 9 + tests/misc/projects/Issue6772/compile.hxml | 2 + tests/misc/projects/Issue6780/Main.hx | 6 + tests/misc/projects/Issue6780/compile.hxml | 3 + .../Issue6780/double quotes/Double.hx | 1 + .../Issue6780/single quotes/Single.hx | 1 + tests/misc/projects/Issue6790/Main.hx | 24 + tests/misc/projects/Issue6790/Mismatch.hx | 8 + .../misc/projects/Issue6790/compile-fail.hxml | 3 + .../Issue6790/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue6790/compile.hxml | 3 + .../projects/Issue6790/compile.hxml.stderr | 29 + tests/misc/projects/Issue6826/Main.hx | 7 + .../misc/projects/Issue6826/compile-fail.hxml | 2 + .../Issue6826/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue6841/Main.hx | 13 + tests/misc/projects/Issue6841/Test.hx | 19 + tests/misc/projects/Issue6841/compile.hxml | 1 + tests/misc/projects/Issue6846/Main.hx | 12 + tests/misc/projects/Issue6846/compile.hxml | 1 + .../projects/Issue6846/compile.hxml.stderr | 1 + tests/misc/projects/Issue6878/Main.hx | 13 + tests/misc/projects/Issue6878/Main1.hx | 8 + .../misc/projects/Issue6878/compile-fail.hxml | 2 + .../Issue6878/compile-fail.hxml.stderr | 2 + .../projects/Issue6878/compile1-fail.hxml | 2 + .../Issue6878/compile1-fail.hxml.stderr | 2 + tests/misc/projects/Issue6903/Main.hx | 9 + .../misc/projects/Issue6903/compile-fail.hxml | 1 + .../Issue6903/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue6922/Test.hx | 5 + tests/misc/projects/Issue6922/compile.hxml | 2 + tests/misc/projects/Issue6950/Main.hx | 11 + .../misc/projects/Issue6950/compile-fail.hxml | 2 + .../Issue6950/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue6965/Main.hx | 8 + .../misc/projects/Issue6965/compile-fail.hxml | 2 + .../Issue6965/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue6992/Main.hx | 7 + tests/misc/projects/Issue6992/compile.hxml | 3 + tests/misc/projects/Issue7017/Main.hx | 5 + tests/misc/projects/Issue7017/compile.hxml | 2 + .../projects/Issue7017/compile.hxml.stderr | 3 + tests/misc/projects/Issue7039/Main.hx | 6 + .../misc/projects/Issue7039/compile-fail.hxml | 2 + .../Issue7039/compile-fail.hxml.stderr | 3 + tests/misc/projects/Issue7076/Main.hx | 9 + .../misc/projects/Issue7076/compile-fail.hxml | 2 + .../Issue7076/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue7096/Main.hx | 7 + tests/misc/projects/Issue7096/compile.hxml | 2 + .../projects/Issue7096/compile.hxml.stderr | 1 + tests/misc/projects/Issue7108/Main.hx | 12 + .../misc/projects/Issue7108/compile-fail.hxml | 1 + .../Issue7108/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue7210/compile.hxml | 1 + .../projects/Issue7210/compile.hxml.stderr | 1 + tests/misc/projects/Issue7210/macro/Utils.hx | 8 + tests/misc/projects/Issue7227/Main.hx | 16 + .../misc/projects/Issue7227/compile-fail.hxml | 2 + .../Issue7227/compile-fail.hxml.stderr | 3 + tests/misc/projects/Issue7333/Main.hx | 13 + .../misc/projects/Issue7333/compile-fail.hxml | 2 + .../Issue7333/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue7363/Main.hx | 25 + .../misc/projects/Issue7363/compile-fail.hxml | 1 + .../Issue7363/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue7453/Main.hx | 7 + tests/misc/projects/Issue7453/Main.macro.hx | 3 + tests/misc/projects/Issue7453/compile.hxml | 4 + tests/misc/projects/Issue7526/Main.hx | 20 + .../misc/projects/Issue7526/compile-fail.hxml | 2 + .../Issue7526/compile-fail.hxml.stderr | 4 + tests/misc/projects/Issue7614/Main.hx | 13 + .../misc/projects/Issue7614/compile-fail.hxml | 1 + .../Issue7614/compile-fail.hxml.stderr | 3 + tests/misc/projects/Issue7638/Main.hx | 15 + .../misc/projects/Issue7638/compile-fail.hxml | 1 + .../Issue7638/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue7655/Main.hx | 28 + tests/misc/projects/Issue7655/Mismatch.hx | 8 + .../misc/projects/Issue7655/compile-fail.hxml | 3 + .../Issue7655/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue7655/compile.hxml | 3 + .../projects/Issue7655/compile.hxml.stderr | 29 + tests/misc/projects/Issue7734/Main.hx | 7 + .../misc/projects/Issue7734/compile-fail.hxml | 2 + .../Issue7734/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue7747/Main.hx | 13 + .../misc/projects/Issue7747/compile-fail.hxml | 2 + .../Issue7747/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue7752/Main.hx | 9 + tests/misc/projects/Issue7752/Main2.hx | 9 + .../misc/projects/Issue7752/compile-fail.hxml | 2 + .../Issue7752/compile-fail.hxml.stderr | 1 + .../projects/Issue7752/compile2-fail.hxml | 2 + .../Issue7752/compile2-fail.hxml.stderr | 1 + tests/misc/projects/Issue7796/Main.hx | 4 + tests/misc/projects/Issue7796/compile.hxml | 4 + tests/misc/projects/Issue7796/glsl2agal.swc | Bin 0 -> 658672 bytes tests/misc/projects/Issue7824/Main.hx | 16 + .../misc/projects/Issue7824/compile-fail.hxml | 2 + .../Issue7824/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue7905/Main.hx | 25 + tests/misc/projects/Issue7905/compile.hxml | 1 + .../projects/Issue7905/compile.hxml.stderr | 1 + tests/misc/projects/Issue7920/Main.hx | 6 + .../misc/projects/Issue7920/compile-fail.hxml | 1 + .../Issue7920/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue7921/Main.hx | 16 + .../misc/projects/Issue7921/compile-fail.hxml | 2 + .../Issue7921/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue7935/Main.hx | 5 + tests/misc/projects/Issue7935/Main2.hx | 5 + tests/misc/projects/Issue7935/Main3.hx | 5 + .../misc/projects/Issue7935/compile-fail.hxml | 2 + .../Issue7935/compile-fail.hxml.stderr | 1 + .../projects/Issue7935/compile2-fail.hxml | 2 + .../Issue7935/compile2-fail.hxml.stderr | 1 + .../projects/Issue7935/compile3-fail.hxml | 2 + .../Issue7935/compile3-fail.hxml.stderr | 1 + tests/misc/projects/Issue7936/.gitignore | 1 + tests/misc/projects/Issue7936/compile.hxml | 44 + tests/misc/projects/Issue7936/run.js | 11 + .../misc/projects/Issue7936/src/Closures1.hx | 21 + .../misc/projects/Issue7936/src/Closures2.hx | 16 + .../misc/projects/Issue7936/src/ObjectMap1.hx | 9 + .../misc/projects/Issue7936/src/ObjectMap2.hx | 10 + tests/misc/projects/Issue7997/Main.hx | 8 + .../misc/projects/Issue7997/compile-fail.hxml | 1 + .../Issue7997/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue8088/Fail.hx | 14 + tests/misc/projects/Issue8088/Success.hx | 27 + .../misc/projects/Issue8088/compile-fail.hxml | 1 + .../Issue8088/compile-fail.hxml.stderr | 6 + tests/misc/projects/Issue8088/compile.hxml | 2 + tests/misc/projects/Issue8119/Main.hx | 5 + tests/misc/projects/Issue8119/Main2.hx | 5 + .../misc/projects/Issue8119/compile-fail.hxml | 1 + .../Issue8119/compile-fail.hxml.stderr | 1 + .../projects/Issue8119/compile2-fail.hxml | 1 + .../Issue8119/compile2-fail.hxml.stderr | 1 + tests/misc/projects/Issue8159/Macro.macro.hx | 5 + tests/misc/projects/Issue8159/Main.hx | 4 + tests/misc/projects/Issue8159/compile.hxml | 1 + tests/misc/projects/Issue8173/Main.hx | 12 + .../misc/projects/Issue8173/compile-fail.hxml | 1 + .../Issue8173/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue8191/U1.hx | 3 + tests/misc/projects/Issue8191/U2.hx | 3 + tests/misc/projects/Issue8191/U3.hx | 3 + tests/misc/projects/Issue8191/U4.hx | 3 + tests/misc/projects/Issue8191/U5.hx | 3 + tests/misc/projects/Issue8191/X1.hx | 3 + tests/misc/projects/Issue8191/X2.hx | 3 + .../misc/projects/Issue8191/compile-fail.hxml | 1 + .../Issue8191/compile-fail.hxml.stderr | 1 + .../projects/Issue8191/compile2-fail.hxml | 1 + .../Issue8191/compile2-fail.hxml.stderr | 1 + .../projects/Issue8191/compile3-fail.hxml | 1 + .../Issue8191/compile3-fail.hxml.stderr | 1 + .../projects/Issue8191/compile4-fail.hxml | 1 + .../Issue8191/compile4-fail.hxml.stderr | 1 + .../projects/Issue8191/compile5-fail.hxml | 1 + .../Issue8191/compile5-fail.hxml.stderr | 1 + .../projects/Issue8191/compile6-fail.hxml | 1 + .../Issue8191/compile6-fail.hxml.stderr | 1 + .../projects/Issue8191/compile7-fail.hxml | 1 + .../Issue8191/compile7-fail.hxml.stderr | 1 + .../misc/projects/Issue8202/Builder.macro.hx | 12 + tests/misc/projects/Issue8202/Main.hx | 6 + tests/misc/projects/Issue8202/compile.hxml | 1 + tests/misc/projects/Issue8205/Main.hx | 6 + .../misc/projects/Issue8205/compile-fail.hxml | 2 + .../Issue8205/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8219/Main.hx | 8 + .../misc/projects/Issue8219/compile-fail.hxml | 2 + .../Issue8219/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8231/Main.hx | 15 + tests/misc/projects/Issue8231/compile.hxml | 5 + tests/misc/projects/Issue8241/Main.hx | 8 + .../misc/projects/Issue8241/compile-fail.hxml | 2 + .../Issue8241/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8277/Main1.hx | 22 + tests/misc/projects/Issue8277/Main2.hx | 17 + .../projects/Issue8277/compile1-fail.hxml | 1 + .../Issue8277/compile1-fail.hxml.stderr | 1 + .../projects/Issue8277/compile2-fail.hxml | 1 + .../Issue8277/compile2-fail.hxml.stderr | 1 + tests/misc/projects/Issue8283/Main.hx | 16 + .../misc/projects/Issue8283/compile-fail.hxml | 1 + .../Issue8283/compile-fail.hxml.stderr | 4 + tests/misc/projects/Issue8303/Main.hx | 13 + tests/misc/projects/Issue8303/MainCatch.hx | 19 + .../misc/projects/Issue8303/compile-fail.hxml | 3 + .../Issue8303/compile-fail.hxml.stderr | 6 + tests/misc/projects/Issue8303/compile.hxml | 3 + tests/misc/projects/Issue8336/Main.hx | 16 + .../misc/projects/Issue8336/compile-fail.hxml | 1 + .../Issue8336/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8354/FailFrom.hx | 10 + tests/misc/projects/Issue8354/FailTo.hx | 10 + tests/misc/projects/Issue8354/Success.hx | 10 + tests/misc/projects/Issue8354/compile.hxml | 1 + .../projects/Issue8354/compile1-fail.hxml | 1 + .../Issue8354/compile1-fail.hxml.stderr | 1 + .../projects/Issue8354/compile2-fail.hxml | 1 + .../Issue8354/compile2-fail.hxml.stderr | 1 + tests/misc/projects/Issue8364/Main.hx | 15 + tests/misc/projects/Issue8364/compile.hxml | 4 + tests/misc/projects/Issue8393/Main.hx | 9 + tests/misc/projects/Issue8393/Main2.hx | 11 + .../misc/projects/Issue8393/compile-fail.hxml | 1 + .../Issue8393/compile-fail.hxml.stderr | 1 + .../Issue8393/compile2-fail.hxml.disabled | 2 + .../Issue8393/compile2-fail.hxml.stderr | 1 + tests/misc/projects/Issue8404/Main.hx | 13 + tests/misc/projects/Issue8404/compile.hxml | 1 + tests/misc/projects/Issue8466/Main.hx | 7 + tests/misc/projects/Issue8466/compile.hxml | 1 + tests/misc/projects/Issue8471/Macro.hx | 27 + tests/misc/projects/Issue8471/Macro2.hx | 35 + tests/misc/projects/Issue8471/compile.hxml | 2 + .../projects/Issue8471/compile.hxml.stderr | 3 + tests/misc/projects/Issue8471/compile2.hxml | 2 + .../projects/Issue8471/compile2.hxml.stderr | 5 + tests/misc/projects/Issue8488/Main.hx | 9 + .../misc/projects/Issue8488/compile-fail.hxml | 1 + .../Issue8488/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue8517/Fail.hx | 7 + tests/misc/projects/Issue8517/Foo.hx | 4 + tests/misc/projects/Issue8517/Macro.hx | 4 + tests/misc/projects/Issue8517/Main.hx | 5 + .../misc/projects/Issue8517/compile-fail.hxml | 1 + .../Issue8517/compile-fail.hxml.stderr | 4 + tests/misc/projects/Issue8517/compile.hxml | 1 + tests/misc/projects/Issue8527/Main.hx | 3 + .../misc/projects/Issue8527/compile-fail.hxml | 1 + .../Issue8527/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8530/Main.hx | 13 + tests/misc/projects/Issue8530/compile.hxml | 1 + tests/misc/projects/Issue8533/Main.hx | 36 + tests/misc/projects/Issue8533/Main.hx.txt | 36 + tests/misc/projects/Issue8533/compile.hxml | 1 + tests/misc/projects/Issue8534/Main.hx | 5 + .../misc/projects/Issue8534/compile-fail.hxml | 1 + .../Issue8534/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8550/Fail.hx | 7 + tests/misc/projects/Issue8550/Success.hx | 5 + .../misc/projects/Issue8550/compile-fail.hxml | 1 + .../Issue8550/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8550/compile.hxml | 1 + tests/misc/projects/Issue8551/Main.hx | 9 + .../misc/projects/Issue8551/compile-fail.hxml | 1 + .../Issue8551/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8565/Main.hx | 6 + .../misc/projects/Issue8565/compile-fail.hxml | 1 + .../Issue8565/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8567/compile.hxml | 3 + tests/misc/projects/Issue8567/src/Main.hx | 4 + tests/misc/projects/Issue8567/src/test.txt | 0 tests/misc/projects/Issue8579/Main.hx | 14 + .../misc/projects/Issue8579/compile-fail.hxml | 1 + .../Issue8579/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8608/Main.hx | 11 + .../misc/projects/Issue8608/compile-fail.hxml | 1 + .../Issue8608/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue8618/Main.hx | 6 + tests/misc/projects/Issue8618/Main2.hx | 5 + tests/misc/projects/Issue8618/Main3.hx | 5 + tests/misc/projects/Issue8618/Main4.hx | 5 + .../misc/projects/Issue8618/NoClosureClass.hx | 6 + tests/misc/projects/Issue8618/NormalClass.hx | 6 + .../misc/projects/Issue8618/compile-fail.hxml | 1 + .../Issue8618/compile-fail.hxml.stderr | 2 + .../projects/Issue8618/compile2-fail.hxml | 1 + .../Issue8618/compile2-fail.hxml.stderr | 2 + .../projects/Issue8618/compile3-fail.hxml | 1 + .../Issue8618/compile3-fail.hxml.stderr | 2 + .../projects/Issue8618/compile4-fail.hxml | 1 + .../Issue8618/compile4-fail.hxml.stderr | 2 + tests/misc/projects/Issue8650/Main.hx | 6 + .../misc/projects/Issue8650/compile-fail.hxml | 2 + .../Issue8650/compile-fail.hxml.stderr | 1 + tests/misc/projects/_semver/InvalidVersion.hx | 5 + tests/misc/projects/_semver/Main.hx | 38 + tests/misc/projects/_semver/compile-fail.hxml | 1 + .../projects/_semver/compile-fail.hxml.stderr | 1 + tests/misc/projects/_semver/compile.hxml | 1 + .../projects/display-package/compile1.hxml | 2 +- .../projects/display-package/compile2.hxml | 2 +- tests/misc/projects/display-type/compile.hxml | 2 +- tests/misc/projects/es6/A.hx | 9 + tests/misc/projects/es6/B.hx | 10 + tests/misc/projects/es6/C.hx | 7 + tests/misc/projects/es6/D.hx | 9 + tests/misc/projects/es6/compile-a-fail.hxml | 3 + .../projects/es6/compile-a-fail.hxml.stderr | 1 + tests/misc/projects/es6/compile-b-fail.hxml | 3 + .../projects/es6/compile-b-fail.hxml.stderr | 1 + tests/misc/projects/es6/compile-c-fail.hxml | 3 + .../projects/es6/compile-c-fail.hxml.stderr | 1 + tests/misc/projects/es6/compile-d-fail.hxml | 3 + .../projects/es6/compile-d-fail.hxml.stderr | 1 + .../projects/Issue4218/.gitignore | 0 .../{ => python}/projects/Issue4218/Main.hx | 0 .../projects/Issue4218/build.hxml | 2 +- tests/misc/python/projects/Issue8542/Main.hx | 9 + .../misc/python/projects/Issue8542/build.hxml | 3 + tests/misc/python/pythonImport/.gitignore | 2 + tests/misc/{ => python}/pythonImport/Main.hx | 4 +- .../{ => python}/pythonImport/compile.hxml | 2 +- .../pythonImport/native_python/__init__.py | 0 .../pythonImport/native_python/sample.py | 0 tests/misc/python/run.hxml | 2 + tests/misc/pythonImport/.gitignore | 1 - tests/misc/src/Main.hx | 37 +- tests/misc/weakmap/compile-cs.hxml | 4 +- tests/misc/weakmap/compile-java.hxml | 2 +- tests/nullsafety/src/Validator.hx | 89 + tests/nullsafety/src/cases/TestAbstract.hx | 8 + tests/nullsafety/src/cases/TestLoose.hx | 87 + .../src/cases/TestSafeFieldInUnsafeClass.hx | 9 + tests/nullsafety/src/cases/TestStrict.hx | 905 ++++ tests/nullsafety/test-js-es6.hxml | 3 + tests/nullsafety/test.hxml | 10 + tests/optimization/run.hxml | 8 +- tests/optimization/src/Macro.hx | 4 +- tests/optimization/src/Test.hx | 2 +- tests/optimization/src/TestJs.hx | 38 +- tests/optimization/src/TestLocalDce.hx | 65 +- tests/optimization/src/issues/Issue3524.hx | 25 + tests/optimization/src/issues/Issue3881.hx | 28 + tests/optimization/src/issues/Issue5436.hx | 20 + tests/optimization/src/issues/Issue5582.hx | 16 + tests/optimization/src/issues/Issue6015.hx | 2 +- tests/optimization/src/issues/Issue6047.hx | 23 + tests/optimization/src/issues/Issue6225.hx | 30 + tests/optimization/src/issues/Issue6283.hx | 1 - tests/optimization/src/issues/Issue6672.hx | 30 + tests/optimization/src/issues/Issue6715.hx | 84 + tests/optimization/src/issues/Issue7113.hx | 19 + tests/optimization/src/issues/Issue7704.hx | 25 + tests/optimization/src/issues/Issue8072.hx | 18 + tests/optimization/src/issues/Issue8128.hx | 15 + tests/optimization/src/issues/Issue8226.hx | 24 + tests/optimization/src/issues/IssueInline.hx | 122 + tests/runci/Config.hx | 18 + tests/runci/Deployment.hx | 283 +- tests/runci/Indexer.hx | 9 + tests/runci/Linux.hx | 4 +- tests/runci/System.hx | 24 +- tests/runci/TestTarget.hx | 4 +- tests/runci/targets/As3.hx | 23 +- tests/runci/targets/Cpp.hx | 29 +- tests/runci/targets/Cs.hx | 23 +- tests/runci/targets/Flash.hx | 106 +- tests/runci/targets/Hl.hx | 80 + tests/runci/targets/Java.hx | 21 +- tests/runci/targets/Js.hx | 67 +- tests/runci/targets/Jvm.hx | 24 + tests/runci/targets/Lua.hx | 54 +- tests/runci/targets/Macro.hx | 28 +- tests/runci/targets/Neko.hx | 7 +- tests/runci/targets/Php.hx | 62 +- tests/runci/targets/Python.hx | 18 +- tests/server/.gitignore | 4 + tests/server/build.hxml | 8 +- tests/server/src/AsyncMacro.hx | 60 +- tests/server/src/DisplayTests.hx | 153 + tests/server/src/HaxeServer.hx | 267 -- tests/server/src/HaxeServerTestCase.hx | 202 +- tests/server/src/Main.hx | 238 +- tests/server/src/Vfs.hx | 7 +- tests/server/test/templates/BrokenSyntax.hx | 6 + tests/server/test/templates/BuildMacro.hx | 5 + tests/server/test/templates/BuiltClass.hx | 4 + tests/server/test/templates/Dependency.hx | 2 +- tests/server/test/templates/Empty.hx | 3 + .../server/test/templates/GlobalBuildMacro.hx | 11 + tests/server/test/templates/HelloJvm.hx | 5 + tests/server/test/templates/HelloWorld.hx | 2 +- tests/server/test/templates/Macro.hx | 8 + tests/server/test/templates/MacroMain.hx | 5 + .../test/templates/MutuallyDependent1.hx | 3 + .../test/templates/MutuallyDependent2.hx | 3 + tests/server/test/templates/Vector.hx | 14 + tests/server/test/templates/VectorInliner.hx | 5 + tests/server/test/templates/WithDependency.hx | 2 +- tests/sourcemaps/run.hxml | 4 + tests/sourcemaps/src/Test.hx | 87 + tests/sourcemaps/src/Validator.hx | 163 + tests/sourcemaps/src/cases/Trace.hx | 7 + tests/sourcemaps/src/cases/import.hx | 1 + tests/sourcemaps/src/validation/Exception.hx | 17 + tests/sourcemaps/src/validation/Lines.hx | 13 + tests/sourcemaps/src/validation/Target.hx | 6 + .../src/validation/ValidationError.hx | 17 + .../src/validation/ValidationReport.hx | 10 + tests/sys/compile-cpp.hxml | 11 +- tests/sys/compile-cs.hxml | 11 +- tests/sys/compile-each.hxml | 8 +- tests/sys/compile-hl.hxml | 13 +- tests/sys/compile-java.hxml | 11 +- tests/sys/compile-jvm.hxml | 22 + tests/sys/compile-lua.hxml | 11 +- tests/sys/compile-macro.hxml | 2 +- tests/sys/compile-neko.hxml | 9 +- tests/sys/compile-php.hxml | 13 +- tests/sys/compile-php7.hxml | 13 - tests/sys/compile-python.hxml | 13 +- tests/sys/genTestRes.py | 82 + tests/sys/lua | 1 - tests/sys/run.hxml | 4 +- tests/sys/src/ExitCode.hx | 6 + tests/sys/src/FileNames.hx | 8 +- tests/sys/src/Main.hx | 18 +- tests/sys/src/TestArguments.hx | 14 +- tests/sys/src/TestCommandBase.hx | 19 +- tests/sys/src/TestFileSystem.hx | 36 +- tests/sys/src/TestSys.hx | 4 +- tests/sys/src/TestUnicode.hx | 425 ++ tests/sys/src/UnicodeSequences.hx | 139 + tests/sys/src/UtilityProcess.hx | 152 + tests/sys/src/io/TestFile.hx | 14 +- tests/sys/src/io/TestFileInput.hx | 130 +- tests/sys/src/net/TestSocket.hx | 27 + tests/threads/build.hxml | 4 + tests/threads/res/tree1.txt | 29 + tests/threads/src/Main.hx | 13 + tests/threads/src/cases/DequeBrackets.hx | 85 + tests/threads/src/cases/Issue3767.hx | 51 + tests/threads/src/cases/Issue4878.hx | 32 + tests/threads/src/cases/Issue8063.hx | 19 + .../unit => threads/src/cases}/TestThreads.hx | 49 +- tests/threads/src/cases/WeirdTreeSum.hx | 180 + tests/threads/src/import.hx | 5 + tests/unit/.gitignore | 1 + tests/unit/compile-as3.hxml | 9 +- tests/unit/compile-cpp.hxml | 2 +- tests/unit/compile-cppia-host.hxml | 8 +- tests/unit/compile-cppia.hxml | 2 +- tests/unit/compile-cs-travis.hxml | 6 +- tests/unit/compile-cs-unsafe-travis.hxml | 6 +- tests/unit/compile-cs-unsafe.hxml | 4 +- tests/unit/compile-cs.hxml | 4 +- tests/unit/compile-each.hxml | 15 +- tests/unit/compile-exe-runner.hxml | 4 +- tests/unit/compile-flash9.hxml | 12 +- tests/unit/compile-hl.hxml | 5 +- tests/unit/compile-java-runner.hxml | 4 +- tests/unit/compile-java.hxml | 8 +- tests/unit/compile-js.hxml | 7 - tests/unit/compile-jvm.hxml | 10 + tests/unit/compile-lua.hxml | 2 +- tests/unit/compile-macro.hxml | 2 +- tests/unit/compile-neko.hxml | 2 +- tests/unit/compile-php.hxml | 2 +- tests/unit/compile-python.hxml | 2 +- tests/unit/compile-remoting.hxml | 4 +- tests/unit/compile-saucelabs-runner.hxml | 6 +- tests/unit/compile.hxml | 1 + tests/unit/compiler_loops/All.hx | 11 - tests/unit/compiler_loops/Issue5345.hx | 1 - tests/unit/compiler_loops/Issue5345b.hx | 2 - tests/unit/compiler_loops/Issue5345c.hx | 2 - tests/unit/compiler_loops/Issue5785.hx | 16 - tests/unit/compiler_loops/Issue6038.hx | 14 - tests/unit/native_swf/.gitignore | 1 + tests/unit/native_swf/Lib.as | 17 + tests/unit/native_swf/Lib2.as | 4 + tests/unit/native_swf/NsCls.as | 15 + tests/unit/native_swf/PropClass.as | 13 + tests/unit/native_swf/PropIface.as | 6 + tests/unit/native_swf/ns1.as | 3 + tests/unit/native_swf/ns2.as | 3 + tests/unit/serializedValues.txt | 1 + tests/unit/src/Macro.hx | 12 + tests/unit/src/RootEnum.hx | 3 + tests/unit/src/RunSauceLabs.hx | 69 +- tests/unit/src/RunSerializerOutput.hx | 51 + tests/unit/src/scripthost/Issue8502.hx | 42 + tests/unit/src/unit/HelperMacros.hx | 69 +- tests/unit/src/unit/MyAbstract.hx | 5 +- tests/unit/src/unit/MyClass.hx | 26 +- tests/unit/src/unit/Test.hx | 256 +- tests/unit/src/unit/TestArrowFunctions.hx | 14 +- tests/unit/src/unit/TestBasetypes.hx | 8 +- tests/unit/src/unit/TestBytes.hx | 11 +- tests/unit/src/unit/TestCasts.hx | 41 + tests/unit/src/unit/TestDCE.hx | 32 +- tests/unit/src/unit/TestFieldVariance.hx | 124 + tests/unit/src/unit/TestGeneric.hx | 19 +- tests/unit/src/unit/TestHttp.hx | 79 + tests/unit/src/unit/TestIO.hx | 2 - tests/unit/src/unit/TestInt64.hx | 29 +- tests/unit/src/unit/TestInterface.hx | 2 +- tests/unit/src/unit/TestJQuery.hx | 39 - tests/unit/src/unit/TestJava.hx | 8 +- tests/unit/src/unit/TestJson.hx | 27 +- tests/unit/src/unit/TestKeyValueIterator.hx | 110 + tests/unit/src/unit/TestMacro.hx | 9 + tests/unit/src/unit/TestMain.hx | 99 +- tests/unit/src/unit/TestMisc.hx | 24 +- tests/unit/src/unit/TestNaN.hx | 1 + tests/unit/src/unit/TestNull.hx | 10 + tests/unit/src/unit/TestOps.hx | 3 + tests/unit/src/unit/TestPhp.hx | 168 + tests/unit/src/unit/TestPython.hx | 32 +- tests/unit/src/unit/TestReflect.hx | 14 +- tests/unit/src/unit/TestResource.hx | 6 +- tests/unit/src/unit/TestSerialize.hx | 1 - .../src/unit/TestSerializerCrossTarget.hx | 108 + tests/unit/src/unit/TestSyntaxModule.hx | 56 + tests/unit/src/unit/TestType.hx | 15 +- tests/unit/src/unit/TestXML.hx | 33 +- tests/unit/src/unit/UnitBuilder.hx | 51 +- tests/unit/src/unit/hxcpp_issues/Issue192.hx | 4 +- tests/unit/src/unit/issues/Issue1810.hx | 2 +- tests/unit/src/unit/issues/Issue1827.hx | 4 +- tests/unit/src/unit/issues/Issue2085.hx | 2 +- tests/unit/src/unit/issues/Issue2086.hx | 8 +- tests/unit/src/unit/issues/Issue2152.hx | 15 - tests/unit/src/unit/issues/Issue2224.hx | 2 + tests/unit/src/unit/issues/Issue2236.hx | 1 + tests/unit/src/unit/issues/Issue2581.hx | 1 + tests/unit/src/unit/issues/Issue2633.hx | 2 +- tests/unit/src/unit/issues/Issue2648.hx | 1 + tests/unit/src/unit/issues/Issue2750.hx | 5 +- tests/unit/src/unit/issues/Issue2754.hx | 3 - tests/unit/src/unit/issues/Issue2785.hx | 2 +- tests/unit/src/unit/issues/Issue2786.hx | 9 +- tests/unit/src/unit/issues/Issue2813.hx | 2 +- tests/unit/src/unit/issues/Issue2861.hx | 2 +- tests/unit/src/unit/issues/Issue2874.hx | 4 +- tests/unit/src/unit/issues/Issue2881.hx | 1 + tests/unit/src/unit/issues/Issue2939.hx | 3 +- tests/unit/src/unit/issues/Issue2951.hx | 1 + tests/unit/src/unit/issues/Issue2957.hx | 1 + tests/unit/src/unit/issues/Issue2958.hx | 9 +- tests/unit/src/unit/issues/Issue2960.hx | 1 + tests/unit/src/unit/issues/Issue2980.hx | 1 + tests/unit/src/unit/issues/Issue2989.hx | 1 + tests/unit/src/unit/issues/Issue3005.hx | 1 + tests/unit/src/unit/issues/Issue3008.hx | 1 + tests/unit/src/unit/issues/Issue3024.hx | 1 + tests/unit/src/unit/issues/Issue3063.hx | 6 +- tests/unit/src/unit/issues/Issue3084.hx | 7 +- tests/unit/src/unit/issues/Issue3090.hx | 1 + tests/unit/src/unit/issues/Issue3118.hx | 3 +- tests/unit/src/unit/issues/Issue3132.hx | 1 + tests/unit/src/unit/issues/Issue3133.hx | 1 + tests/unit/src/unit/issues/Issue3138.hx | 1 + tests/unit/src/unit/issues/Issue3181.hx | 19 +- tests/unit/src/unit/issues/Issue3198.hx | 7 + tests/unit/src/unit/issues/Issue3345.hx | 26 +- tests/unit/src/unit/issues/Issue3348.hx | 8 +- tests/unit/src/unit/issues/Issue3383.hx | 1 + tests/unit/src/unit/issues/Issue3388.hx | 10 +- tests/unit/src/unit/issues/Issue3390.hx | 1 + tests/unit/src/unit/issues/Issue3400.hx | 1 + tests/unit/src/unit/issues/Issue3403.hx | 10 +- tests/unit/src/unit/issues/Issue3451.hx | 4 +- tests/unit/src/unit/issues/Issue3460.hx | 2 +- tests/unit/src/unit/issues/Issue3480.hx | 1 + tests/unit/src/unit/issues/Issue3486.hx | 1 + tests/unit/src/unit/issues/Issue3499.hx | 4 +- tests/unit/src/unit/issues/Issue3528.hx | 1 + tests/unit/src/unit/issues/Issue3539.hx | 21 + tests/unit/src/unit/issues/Issue3545.hx | 4 +- tests/unit/src/unit/issues/Issue3547.hx | 1 + tests/unit/src/unit/issues/Issue3585.hx | 2 +- tests/unit/src/unit/issues/Issue3592.hx | 2 +- tests/unit/src/unit/issues/Issue3615.hx | 2 +- tests/unit/src/unit/issues/Issue3639.hx | 1 + tests/unit/src/unit/issues/Issue3649.hx | 3 +- tests/unit/src/unit/issues/Issue3665.hx | 3 +- tests/unit/src/unit/issues/Issue3713.hx | 1 + tests/unit/src/unit/issues/Issue3767.hx | 50 - tests/unit/src/unit/issues/Issue3771.hx | 4 +- tests/unit/src/unit/issues/Issue3777.hx | 1 + tests/unit/src/unit/issues/Issue3781.hx | 1 + tests/unit/src/unit/issues/Issue3792.hx | 13 + tests/unit/src/unit/issues/Issue3804.hx | 1 + tests/unit/src/unit/issues/Issue3826.hx | 67 + tests/unit/src/unit/issues/Issue3844.hx | 1 + tests/unit/src/unit/issues/Issue3846.hx | 6 +- tests/unit/src/unit/issues/Issue3894.hx | 1 + tests/unit/src/unit/issues/Issue3935.hx | 2 + tests/unit/src/unit/issues/Issue3979.hx | 4 +- tests/unit/src/unit/issues/Issue4051.hx | 4 +- tests/unit/src/unit/issues/Issue4076.hx | 1 + tests/unit/src/unit/issues/Issue4086.hx | 1 + tests/unit/src/unit/issues/Issue4103.hx | 3 +- tests/unit/src/unit/issues/Issue4122.hx | 3 +- tests/unit/src/unit/issues/Issue4138.hx | 37 - tests/unit/src/unit/issues/Issue4149.hx | 1 + tests/unit/src/unit/issues/Issue4222.hx | 1 + tests/unit/src/unit/issues/Issue4232.hx | 4 +- tests/unit/src/unit/issues/Issue4246.hx | 1 + tests/unit/src/unit/issues/Issue4277.hx | 2 +- tests/unit/src/unit/issues/Issue4287.hx | 16 + tests/unit/src/unit/issues/Issue4310.hx | 1 + tests/unit/src/unit/issues/Issue4312.hx | 2 +- tests/unit/src/unit/issues/Issue4322.hx | 2 +- ...27.hx.disabled.because.hl => Issue4327.hx} | 0 tests/unit/src/unit/issues/Issue4329.hx | 1 + tests/unit/src/unit/issues/Issue4343.hx | 1 + tests/unit/src/unit/issues/Issue4397.hx | 1 + tests/unit/src/unit/issues/Issue4457.hx | 1 + tests/unit/src/unit/issues/Issue4481.hx | 21 + tests/unit/src/unit/issues/Issue4501.hx | 1 + .../issues/{Issue4581.hx => Issue4581.hx.wtf} | 0 tests/unit/src/unit/issues/Issue4591.hx | 1 + tests/unit/src/unit/issues/Issue4639.hx | 11 + tests/unit/src/unit/issues/Issue4644.hx | 3 +- tests/unit/src/unit/issues/Issue4649.hx | 14 + tests/unit/src/unit/issues/Issue4672.hx | 1 + tests/unit/src/unit/issues/Issue4695.hx | 6 +- tests/unit/src/unit/issues/Issue4703.hx | 1 + tests/unit/src/unit/issues/Issue4705.hx | 19 + tests/unit/src/unit/issues/Issue4751.hx | 2 + tests/unit/src/unit/issues/Issue4799.hx | 29 + tests/unit/src/unit/issues/Issue4819.hx | 6 +- tests/unit/src/unit/issues/Issue4843.hx | 1 + tests/unit/src/unit/issues/Issue4862.hx | 2 +- tests/unit/src/unit/issues/Issue4867.hx | 3 +- tests/unit/src/unit/issues/Issue4878.hx | 24 - tests/unit/src/unit/issues/Issue4886.hx | 2 +- tests/unit/src/unit/issues/Issue4904.hx | 3 +- tests/unit/src/unit/issues/Issue4918.hx | 1 + tests/unit/src/unit/issues/Issue4940.hx | 3 +- tests/unit/src/unit/issues/Issue4949.hx | 1 + tests/unit/src/unit/issues/Issue4973.hx | 8 +- tests/unit/src/unit/issues/Issue4986.hx | 1 + tests/unit/src/unit/issues/Issue4987.hx | 1 + tests/unit/src/unit/issues/Issue4997.hx | 1 + tests/unit/src/unit/issues/Issue5009.hx | 10 + tests/unit/src/unit/issues/Issue5016.hx | 4 +- tests/unit/src/unit/issues/Issue5025.hx | 2 +- tests/unit/src/unit/issues/Issue5027.hx | 1 + tests/unit/src/unit/issues/Issue5031.hx | 1 + tests/unit/src/unit/issues/Issue5039.hx | 51 + tests/unit/src/unit/issues/Issue5073.hx | 1 + tests/unit/src/unit/issues/Issue5078.hx | 2 + tests/unit/src/unit/issues/Issue5108.hx | 3 +- tests/unit/src/unit/issues/Issue5168.hx | 8 + tests/unit/src/unit/issues/Issue5179.hx | 5 +- tests/unit/src/unit/issues/Issue5255.hx | 7 + tests/unit/src/unit/issues/Issue5270.hx | 8 +- tests/unit/src/unit/issues/Issue5303.hx | 1 + tests/unit/src/unit/issues/Issue5323.hx | 2 +- tests/unit/src/unit/issues/Issue5384.hx | 21 + tests/unit/src/unit/issues/Issue5432.hx | 2 +- tests/unit/src/unit/issues/Issue5449.hx | 19 + tests/unit/src/unit/issues/Issue5486.hx | 32 + tests/unit/src/unit/issues/Issue5505.hx | 4 +- tests/unit/src/unit/issues/Issue5543.hx | 1 + tests/unit/src/unit/issues/Issue5544.hx | 2 +- tests/unit/src/unit/issues/Issue5556.hx | 2 + tests/unit/src/unit/issues/Issue5565.hx | 6 +- tests/unit/src/unit/issues/Issue5572.hx | 6 +- tests/unit/src/unit/issues/Issue5584.hx | 2 + tests/unit/src/unit/issues/Issue5599.hx | 16 + tests/unit/src/unit/issues/Issue5608.hx | 2 +- tests/unit/src/unit/issues/Issue5691.hx | 31 + tests/unit/src/unit/issues/Issue5693.hx | 5 +- tests/unit/src/unit/issues/Issue5783.hx | 1 + tests/unit/src/unit/issues/Issue5816.hx | 13 + tests/unit/src/unit/issues/Issue5848.hx | 1 + tests/unit/src/unit/issues/Issue5851.hx | 1 + tests/unit/src/unit/issues/Issue5859.hx | 10 + tests/unit/src/unit/issues/Issue5923.hx | 2 +- tests/unit/src/unit/issues/Issue6016.hx | 25 + tests/unit/src/unit/issues/Issue6036.hx | 33 + tests/unit/src/unit/issues/Issue6039.hx | 31 + tests/unit/src/unit/issues/Issue6059.hx | 36 + tests/unit/src/unit/issues/Issue6062.hx | 25 + tests/unit/src/unit/issues/Issue6106.hx | 14 + tests/unit/src/unit/issues/Issue6133.hx | 2 + tests/unit/src/unit/issues/Issue6145.hx | 4 +- tests/unit/src/unit/issues/Issue6169.hx | 1 + tests/unit/src/unit/issues/Issue6175.hx | 2 +- tests/unit/src/unit/issues/Issue6215.hx | 1 + tests/unit/src/unit/issues/Issue6259.hx | 5 +- tests/unit/src/unit/issues/Issue6276.hx | 4 +- tests/unit/src/unit/issues/Issue6291.hx | 35 + tests/unit/src/unit/issues/Issue6315.hx | 2 +- tests/unit/src/unit/issues/Issue6376.hx | 9 + tests/unit/src/unit/issues/Issue6379.hx | 13 + tests/unit/src/unit/issues/Issue6430.hx | 220 + tests/unit/src/unit/issues/Issue6482.hx | 4 +- tests/unit/src/unit/issues/Issue6486.hx | 23 + tests/unit/src/unit/issues/Issue6499.hx | 21 + tests/unit/src/unit/issues/Issue6503.hx | 11 + tests/unit/src/unit/issues/Issue6520.hx | 60 + tests/unit/src/unit/issues/Issue6533.hx | 36 + tests/unit/src/unit/issues/Issue6548.hx | 1 + tests/unit/src/unit/issues/Issue6549.hx | 32 + tests/unit/src/unit/issues/Issue6551.hx | 9 + tests/unit/src/unit/issues/Issue6560.hx | 14 + tests/unit/src/unit/issues/Issue6562.hx | 1 + tests/unit/src/unit/issues/Issue6587.hx | 13 + tests/unit/src/unit/issues/Issue6609.hx | 1 + tests/unit/src/unit/issues/Issue6635.hx | 24 + tests/unit/src/unit/issues/Issue6656.hx | 17 + tests/unit/src/unit/issues/Issue6674.hx | 19 + tests/unit/src/unit/issues/Issue6675.hx | 19 + tests/unit/src/unit/issues/Issue6703.hx | 25 + tests/unit/src/unit/issues/Issue6706.hx | 13 + tests/unit/src/unit/issues/Issue6707.hx | 19 + tests/unit/src/unit/issues/Issue6710.hx | 28 + tests/unit/src/unit/issues/Issue6711.hx | 35 + tests/unit/src/unit/issues/Issue6717.hx | 23 + tests/unit/src/unit/issues/Issue6720.hx | 11 + tests/unit/src/unit/issues/Issue6722.hx | 23 + tests/unit/src/unit/issues/Issue6724.hx | 11 + tests/unit/src/unit/issues/Issue6751.hx | 21 + tests/unit/src/unit/issues/Issue6752.hx | 13 + tests/unit/src/unit/issues/Issue6754.hx | 9 + tests/unit/src/unit/issues/Issue6772.hx | 9 + tests/unit/src/unit/issues/Issue6776.hx | 19 + tests/unit/src/unit/issues/Issue6784.hx | 10 + tests/unit/src/unit/issues/Issue6801.hx | 44 + tests/unit/src/unit/issues/Issue6807.hx | 17 + tests/unit/src/unit/issues/Issue6822.hx | 19 + tests/unit/src/unit/issues/Issue6830.hx | 14 + tests/unit/src/unit/issues/Issue6833.hx | 37 + tests/unit/src/unit/issues/Issue6836.hx | 19 + tests/unit/src/unit/issues/Issue6838.hx | 12 + tests/unit/src/unit/issues/Issue6845.hx | 17 + tests/unit/src/unit/issues/Issue6848.hx | 11 + tests/unit/src/unit/issues/Issue6871.hx | 30 + tests/unit/src/unit/issues/Issue6873.hx | 12 + tests/unit/src/unit/issues/Issue6896.hx | 14 + tests/unit/src/unit/issues/Issue6942.hx | 42 + tests/unit/src/unit/issues/Issue6948.hx | 11 + tests/unit/src/unit/issues/Issue6952.hx | 24 + tests/unit/src/unit/issues/Issue6972.hx | 43 + tests/unit/src/unit/issues/Issue6979.hx | 18 + tests/unit/src/unit/issues/Issue7007.hx | 18 + tests/unit/src/unit/issues/Issue7032.hx | 15 + tests/unit/src/unit/issues/Issue7106.hx | 40 + tests/unit/src/unit/issues/Issue7115.hx | 100 + tests/unit/src/unit/issues/Issue7120.hx | 22 + tests/unit/src/unit/issues/Issue7132.hx | 9 + tests/unit/src/unit/issues/Issue7139.hx | 37 + tests/unit/src/unit/issues/Issue7142.hx | 24 + tests/unit/src/unit/issues/Issue7179.hx | 10 + tests/unit/src/unit/issues/Issue7182.hx | 17 + tests/unit/src/unit/issues/Issue7187.hx | 14 + tests/unit/src/unit/issues/Issue7207.hx | 7 + tests/unit/src/unit/issues/Issue7209.hx | 19 + tests/unit/src/unit/issues/Issue7220.hx | 19 + tests/unit/src/unit/issues/Issue7230.hx | 8 + tests/unit/src/unit/issues/Issue7233.hx | 18 + tests/unit/src/unit/issues/Issue7247.hx | 24 + tests/unit/src/unit/issues/Issue7286.hx | 18 + tests/unit/src/unit/issues/Issue7298.hx | 12 + tests/unit/src/unit/issues/Issue7332.hx | 15 + tests/unit/src/unit/issues/Issue7334.hx | 19 + tests/unit/src/unit/issues/Issue7335.hx | 32 + tests/unit/src/unit/issues/Issue7359.hx | 24 + tests/unit/src/unit/issues/Issue7367.hx | 21 + tests/unit/src/unit/issues/Issue7376.hx | 72 + tests/unit/src/unit/issues/Issue7388.hx | 11 + tests/unit/src/unit/issues/Issue7389.hx | 13 + tests/unit/src/unit/issues/Issue7391.hx | 14 + tests/unit/src/unit/issues/Issue7394.hx | 18 + tests/unit/src/unit/issues/Issue7443.hx | 7 + tests/unit/src/unit/issues/Issue7449.hx | 12 + tests/unit/src/unit/issues/Issue7466.hx | 8 + tests/unit/src/unit/issues/Issue7476.hx | 15 + tests/unit/src/unit/issues/Issue7492.hx | 10 + tests/unit/src/unit/issues/Issue7499.hx | 14 + tests/unit/src/unit/issues/Issue7531.hx | 16 + tests/unit/src/unit/issues/Issue7533.hx | 23 + tests/unit/src/unit/issues/Issue7536.hx | 9 + tests/unit/src/unit/issues/Issue7540.hx | 16 + tests/unit/src/unit/issues/Issue7546.hx | 13 + tests/unit/src/unit/issues/Issue7579.hx | 39 + tests/unit/src/unit/issues/Issue7590.hx | 12 + tests/unit/src/unit/issues/Issue7600.hx | 11 + tests/unit/src/unit/issues/Issue7603.hx | 19 + tests/unit/src/unit/issues/Issue7630.hx | 20 + tests/unit/src/unit/issues/Issue7642.hx | 20 + tests/unit/src/unit/issues/Issue7653.hx | 30 + tests/unit/src/unit/issues/Issue7659.hx | 18 + tests/unit/src/unit/issues/Issue7661.hx | 26 + tests/unit/src/unit/issues/Issue7671.hx | 49 + tests/unit/src/unit/issues/Issue7674.hx | 16 + tests/unit/src/unit/issues/Issue7688.hx | 16 + tests/unit/src/unit/issues/Issue7716.hx | 9 + tests/unit/src/unit/issues/Issue7727.hx | 26 + tests/unit/src/unit/issues/Issue7728.hx | 22 + tests/unit/src/unit/issues/Issue7743.hx | 8 + tests/unit/src/unit/issues/Issue7827.hx | 22 + tests/unit/src/unit/issues/Issue7844.hx | 28 + tests/unit/src/unit/issues/Issue7867.hx | 16 + tests/unit/src/unit/issues/Issue7869.hx | 23 + tests/unit/src/unit/issues/Issue7883.hx | 17 + tests/unit/src/unit/issues/Issue7890.hx | 8 + tests/unit/src/unit/issues/Issue7903.hx | 43 + tests/unit/src/unit/issues/Issue7922.hx | 29 + tests/unit/src/unit/issues/Issue7981.hx | 16 + tests/unit/src/unit/issues/Issue8032.hx | 22 + tests/unit/src/unit/issues/Issue8050.hx | 21 + tests/unit/src/unit/issues/Issue8053.hx | 29 + tests/unit/src/unit/issues/Issue8075.hx | 14 + tests/unit/src/unit/issues/Issue8079.hx | 11 + tests/unit/src/unit/issues/Issue8101.hx | 15 + tests/unit/src/unit/issues/Issue8118.hx | 11 + tests/unit/src/unit/issues/Issue8185.hx | 18 + tests/unit/src/unit/issues/Issue8187.hx | 13 + tests/unit/src/unit/issues/Issue8188.hx | 51 + tests/unit/src/unit/issues/Issue8200.hx | 20 + tests/unit/src/unit/issues/Issue8203.hx | 16 + tests/unit/src/unit/issues/Issue8211.hx | 9 + tests/unit/src/unit/issues/Issue8212.hx | 12 + tests/unit/src/unit/issues/Issue8213.hx | 13 + tests/unit/src/unit/issues/Issue8218.hx | 56 + tests/unit/src/unit/issues/Issue8220.hx | 16 + tests/unit/src/unit/issues/Issue8221.hx | 19 + tests/unit/src/unit/issues/Issue8227.hx | 59 + tests/unit/src/unit/issues/Issue8240.hx | 13 + tests/unit/src/unit/issues/Issue8241.hx | 70 + tests/unit/src/unit/issues/Issue8243.hx | 11 + tests/unit/src/unit/issues/Issue8248.hx | 39 + tests/unit/src/unit/issues/Issue8257.hx | 14 + tests/unit/src/unit/issues/Issue8261.hx | 19 + tests/unit/src/unit/issues/Issue8286.hx | 7 + tests/unit/src/unit/issues/Issue8296.hx | 20 + tests/unit/src/unit/issues/Issue8299.hx | 11 + tests/unit/src/unit/issues/Issue8337.hx | 17 + tests/unit/src/unit/issues/Issue8341.hx | 14 + tests/unit/src/unit/issues/Issue8343.hx | 40 + tests/unit/src/unit/issues/Issue8376.hx | 17 + tests/unit/src/unit/issues/Issue8425.hx | 14 + tests/unit/src/unit/issues/Issue8435.hx | 8 + tests/unit/src/unit/issues/Issue8489.hx | 15 + tests/unit/src/unit/issues/Issue8493.hx | 22 + tests/unit/src/unit/issues/Issue8502.hx | 54 + tests/unit/src/unit/issues/Issue8506.hx | 11 + tests/unit/src/unit/issues/Issue8513.hx | 12 + tests/unit/src/unit/issues/Issue8528.hx | 30 + tests/unit/src/unit/issues/Issue8537.hx | 27 + tests/unit/src/unit/issues/Issue8538.hx | 9 + tests/unit/src/unit/issues/Issue8549.hx | 17 + tests/unit/src/unit/issues/Issue8560.hx | 15 + tests/unit/src/unit/issues/misc/ISSUE7716.hx | 10 + .../src/unit/issues/misc/Issue5009Assert.hx | 7 + .../src/unit/issues/misc/Issue5255Class.hx | 9 + .../src/unit/issues/misc/Issue6873Macro.hx | 26 + .../src/unit/issues/misc/Issue7466Macro.hx | 20 + .../src/unit/{ => spec}/TestSpecification.hx | 38 +- tests/unit/src/unit/spec/import.hx | 1 + tests/unit/src/unitstd/Array.unit.hx | 21 +- tests/unit/src/unitstd/Date.unit.hx | 168 +- tests/unit/src/unitstd/EReg.unit.hx | 12 +- .../{Https.unit.hx => Https.unit.hx.no} | 2 +- tests/unit/src/unitstd/InlineXml.unit.hx | 49 + tests/unit/src/unitstd/Lambda.unit.hx | 8 +- tests/unit/src/unitstd/List.unit.hx | 13 +- tests/unit/src/unitstd/Map.unit.hx | 104 +- tests/unit/src/unitstd/Math.unit.hx | 6 + tests/unit/src/unitstd/Reflect.unit.hx | 7 +- tests/unit/src/unitstd/Ssl.unit.hx | 4 +- tests/unit/src/unitstd/Std.unit.hx | 13 +- tests/unit/src/unitstd/String.unit.hx | 33 +- tests/unit/src/unitstd/StringBuf.unit.hx | 17 + tests/unit/src/unitstd/StringTools.unit.hx | 27 +- tests/unit/src/unitstd/Sys.unit.hx | 3 - tests/unit/src/unitstd/Type.unit.hx | 16 +- tests/unit/src/unitstd/Unicode.unit.hx | 306 ++ tests/unit/src/unitstd/UnicodeString.unit.hx | 164 + .../src/unitstd/haxe/DynamicAccess.unit.hx | 29 + tests/unit/src/unitstd/haxe/Int32.unit.hx | 7 +- tests/unit/src/unitstd/haxe/Log.unit.hx | 5 +- tests/unit/src/unitstd/haxe/Utf8.unit.hx | 29 +- tests/unit/src/unitstd/haxe/crypto/Crc32.hx | 2 - .../src/unitstd/haxe/crypto/Crc32.unit.hx | 2 + .../unit/src/unitstd/haxe/crypto/Hmac.unit.hx | 2 +- .../src/unitstd/haxe/ds/BalancedTree.unit.hx | 10 + tests/unit/src/unitstd/haxe/ds/IntMap.unit.hx | 71 + .../src/unitstd/haxe/ds/StringMap.unit.hx | 67 + tests/unit/src/unitstd/haxe/ds/Vector.unit.hx | 18 +- .../unit/src/unitstd/haxe/ds/WeakMap.unit.hx | 4 +- .../src/unitstd/haxe/io/Float32Array.unit.hx | 32 +- .../src/unitstd/haxe/io/Float64Array.unit.hx | 23 +- .../src/unitstd/haxe/io/Int32Array.unit.hx | 23 +- tests/unit/src/unitstd/haxe/io/Path.unit.hx | 5 + .../src/unitstd/haxe/io/UInt16Array.unit.hx | 23 +- .../src/unitstd/haxe/io/UInt32Array.unit.hx | 23 +- .../src/unitstd/haxe/io/UInt8Array.unit.hx | 23 +- .../iterators/StringIteratorUnicode.unit.hx | 30 + .../StringKeyValueIteratorUnicode.unit.hx | 39 + .../haxe/macro/ComplexTypeTools.macro.unit.hx | 2 + .../src/unitstd/haxe/macro/ExprTools.unit.hx | 2 +- tests/unit/src/unitstd/haxe/rtti/Rtti.unit.hx | 4 +- .../src/unitstd/haxe/zip/Compress.unit.hx | 23 +- .../src/unitstd/haxe/zip/Uncompress.unit.hx | 32 + tests/unit/src/unitstd/sys/io/File.unit.hx | 45 + tests/unit/src/unitstd/sys/net/Socket.unit.hx | 70 + tests/unit/unit-js.html | 2 +- tests/unit/unit.hxproj | 1 + tests/unit/unit_hl.hxproj | 2 +- 4069 files changed, 142055 insertions(+), 73787 deletions(-) create mode 100644 .github/FUNDING.yml delete mode 100644 .travis.yml delete mode 100644 appveyor.yml create mode 100644 azure-pipelines.yml create mode 100644 extra/BUILDING.md create mode 100644 extra/azure-pipelines/build-linux.yml create mode 100644 extra/azure-pipelines/build-mac.yml create mode 100644 extra/azure-pipelines/build-windows.yml create mode 100644 extra/azure-pipelines/install-neko-snapshot.yaml create mode 100644 extra/azure-pipelines/test-windows.yml create mode 100644 extra/doc.hxml create mode 100644 extra/images/Readme.png delete mode 100644 haxe.hxproj create mode 100644 opam create mode 100644 src-json/define.json create mode 100644 src-json/meta.json create mode 100644 src/codegen/gencommon/arraySpliceOptimization.ml create mode 100644 src/compiler/serverConfig.ml create mode 100644 src/compiler/serverMessage.ml create mode 100644 src/context/abstractCast.ml create mode 100644 src/context/compilationServer.ml delete mode 100644 src/context/display.ml create mode 100644 src/context/display/deprecationCheck.ml create mode 100644 src/context/display/diagnostics.ml create mode 100644 src/context/display/display.ml create mode 100644 src/context/display/displayEmitter.ml create mode 100644 src/context/display/displayException.ml create mode 100644 src/context/display/displayFields.ml create mode 100644 src/context/display/displayJson.ml create mode 100644 src/context/display/displayToplevel.ml create mode 100644 src/context/display/documentSymbols.ml create mode 100644 src/context/display/findReferences.ml create mode 100644 src/context/display/importHandling.ml create mode 100644 src/context/display/statistics.ml delete mode 100644 src/context/displayTypes.ml create mode 100644 src/context/nativeLibraries.ml create mode 100644 src/context/nativeLibraryHandler.ml create mode 100644 src/context/purityState.ml create mode 100644 src/core/display/completionItem.ml create mode 100644 src/core/display/displayPosition.ml create mode 100644 src/core/displayTypes.ml create mode 100644 src/core/json/genjson.ml rename src/core/{ => json}/json.ml (98%) create mode 100644 src/core/json/jsonRequest.ml create mode 100644 src/core/json/jsonRpc.ml create mode 100644 src/core/json/jsonRpcSocket.ml create mode 100644 src/core/json/jsonrpc_handler.ml create mode 100644 src/core/numeric.ml create mode 100644 src/core/socket.ml create mode 100644 src/core/stringError.ml create mode 100644 src/core/stringHelper.ml create mode 100644 src/core/texpr.ml create mode 100644 src/core/timer.ml create mode 100644 src/core/withType.ml create mode 100644 src/filters/ES6Ctors.ml create mode 100644 src/filters/filtersCommon.ml create mode 100644 src/filters/jsExceptions.ml create mode 100644 src/generators/flashProps.ml create mode 100644 src/generators/genhxold.ml create mode 100644 src/generators/genjvm.ml create mode 100644 src/generators/jvm/jvmAttribute.ml create mode 100644 src/generators/jvm/jvmBuilder.ml create mode 100644 src/generators/jvm/jvmClass.ml create mode 100644 src/generators/jvm/jvmCode.ml create mode 100644 src/generators/jvm/jvmConstantPool.ml create mode 100644 src/generators/jvm/jvmData.ml create mode 100644 src/generators/jvm/jvmDebug.ml create mode 100644 src/generators/jvm/jvmGlobals.ml create mode 100644 src/generators/jvm/jvmMethod.ml create mode 100644 src/generators/jvm/jvmSignature.ml create mode 100644 src/generators/jvm/jvmVerificationTypeInfo.ml create mode 100644 src/generators/jvm/jvmWriter.ml create mode 100644 src/macro/eval/bytes/evalBytesLower.ml create mode 100644 src/macro/eval/bytes/evalBytesUpper.ml create mode 100644 src/macro/eval/bytes/evalBytes_E_L79.ml create mode 100644 src/macro/eval/bytes/evalBytes_L1020.ml create mode 100644 src/macro/eval/bytes/evalBytes_U1021.ml create mode 100644 src/macro/eval/bytes/evalBytes_U79.ml create mode 100644 src/macro/eval/evalBytes.ml delete mode 100644 src/macro/eval/evalDebugCLI.ml create mode 100644 src/macro/eval/evalString.ml create mode 100644 src/macro/eval/evalThread.ml delete mode 100644 src/macro/hlmacro.ml create mode 100644 src/optimization/inline.ml create mode 100644 src/prebuild/main.ml create mode 100644 src/syntax/semver.ml create mode 100644 src/typing/calls.ml create mode 100644 src/typing/fields.ml create mode 100644 src/typing/finalization.ml create mode 100644 src/typing/forLoop.ml create mode 100644 src/typing/generic.ml create mode 100644 src/typing/instanceBuilder.ml create mode 100644 src/typing/nullSafety.ml create mode 100644 src/typing/typeloadCheck.ml create mode 100644 src/typing/typeloadFields.ml create mode 100644 src/typing/typeloadFunction.ml create mode 100644 src/typing/typeloadModule.ml create mode 100644 src/typing/typeloadParse.ml create mode 100644 src/typing/typerBase.ml create mode 100644 src/typing/typerDisplay.ml create mode 100644 std/UnicodeString.hx create mode 100644 std/cpp/Native.hx create mode 100644 std/cpp/_std/sys/thread/Deque.hx rename std/{neko/_std/haxe/Log.hx => cpp/_std/sys/thread/Lock.hx} (74%) create mode 100644 std/cpp/_std/sys/thread/Mutex.hx create mode 100644 std/cpp/_std/sys/thread/Thread.hx create mode 100644 std/cpp/_std/sys/thread/Tls.hx create mode 100644 std/cs/Constraints.hx delete mode 100644 std/cs/_std/haxe/ds/WeakMap.hx2 create mode 100644 std/cs/_std/sys/thread/Deque.hx create mode 100644 std/cs/_std/sys/thread/Lock.hx create mode 100644 std/cs/_std/sys/thread/Mutex.hx create mode 100644 std/cs/_std/sys/thread/Thread.hx create mode 100644 std/cs/_std/sys/thread/Tls.hx rename std/{haxe/remoting/AsyncAdapter.hx => eval/_std/sys/thread/Thread.hx} (56%) create mode 100644 std/eval/vm/NativeThread.hx create mode 100644 std/flash/AnyType.hx create mode 100644 std/flash/_std/String.hx create mode 100644 std/flash/_std/haxe/Http.hx create mode 100644 std/flash/events/AudioOutputChangeEvent.hx create mode 100644 std/flash/media/AudioDeviceManager.hx create mode 100644 std/flash/media/AudioOutputChangeReason.hx create mode 100644 std/haxe/SysTools.hx create mode 100644 std/haxe/display/Display.hx create mode 100644 std/haxe/display/FsPath.hx create mode 100644 std/haxe/display/JsonModuleTypes.hx create mode 100644 std/haxe/display/Protocol.hx create mode 100644 std/haxe/display/Server.hx create mode 100644 std/haxe/ds/ReadOnlyArray.hx create mode 100644 std/haxe/http/HttpBase.hx create mode 100644 std/haxe/http/HttpJs.hx create mode 100644 std/haxe/http/HttpMethod.hx create mode 100644 std/haxe/http/HttpNodeJs.hx create mode 100644 std/haxe/http/HttpStatus.hx rename std/{lua/lib/environ/Environ.hx => haxe/io/Encoding.hx} (79%) create mode 100644 std/haxe/io/Mime.hx create mode 100644 std/haxe/io/Scheme.hx create mode 100644 std/haxe/iterators/DynamicAccessIterator.hx create mode 100644 std/haxe/iterators/DynamicAccessKeyValueIterator.hx create mode 100644 std/haxe/iterators/MapKeyValueIterator.hx create mode 100644 std/haxe/iterators/StringIterator.hx create mode 100644 std/haxe/iterators/StringIteratorUnicode.hx create mode 100644 std/haxe/iterators/StringKeyValueIterator.hx create mode 100644 std/haxe/iterators/StringKeyValueIteratorUnicode.hx delete mode 100644 std/haxe/macro/Context.hl.hx delete mode 100644 std/haxe/remoting/AMFConnection.hx delete mode 100644 std/haxe/remoting/AsyncDebugConnection.hx delete mode 100644 std/haxe/remoting/Context.hx delete mode 100644 std/haxe/remoting/ContextAll.hx delete mode 100644 std/haxe/remoting/DelayedConnection.hx delete mode 100644 std/haxe/remoting/ExternalConnection.hx delete mode 100644 std/haxe/remoting/FlashJsConnection.hx delete mode 100644 std/haxe/remoting/HttpAsyncConnection.hx delete mode 100644 std/haxe/remoting/HttpConnection.hx delete mode 100644 std/haxe/remoting/LocalConnection.hx delete mode 100644 std/haxe/remoting/SocketConnection.hx delete mode 100644 std/haxe/remoting/SocketProtocol.hx delete mode 100644 std/haxe/remoting/SocketWrapper.hx delete mode 100644 std/haxe/remoting/SyncSocketConnection.hx create mode 100644 std/haxe/xml/Access.hx rename std/{cs/_std/haxe/Log.hx => hl/_std/haxe/crypto/Md5.hx} (71%) create mode 100644 std/hl/_std/haxe/crypto/Sha1.hx create mode 100644 std/hl/_std/sys/db/Connection.hx create mode 100644 std/hl/_std/sys/db/Mysql.hx create mode 100644 std/hl/_std/sys/db/ResultSet.hx create mode 100644 std/hl/_std/sys/net/UdpSocket.hx create mode 100644 std/hl/_std/sys/ssl/Context.hx create mode 100644 std/hl/_std/sys/thread/Deque.hx rename std/{lua/_std/haxe/Log.hx => hl/_std/sys/thread/Lock.hx} (67%) create mode 100644 std/hl/_std/sys/thread/Mutex.hx rename std/{js/XMLSocket.hx => hl/_std/sys/thread/Thread.hx} (52%) create mode 100644 std/hl/_std/sys/thread/Tls.hx create mode 100644 std/hl/hl_version create mode 100644 std/java/Init.hx create mode 100644 std/java/NativeString.hx rename std/{python/_std/haxe/Log.hx => java/_std/sys/thread/Deque.hx} (68%) create mode 100644 std/java/_std/sys/thread/Lock.hx create mode 100644 std/java/_std/sys/thread/Mutex.hx create mode 100644 std/java/_std/sys/thread/Thread.hx rename std/{hl/_std/haxe/Log.hx => java/_std/sys/thread/Tls.hx} (72%) create mode 100644 std/js/JsIterator.hx create mode 100644 std/js/Set.hx create mode 100644 std/js/Syntax.hx delete mode 100644 std/js/_std/haxe/Log.hx create mode 100644 std/js/html/AbortController.hx create mode 100644 std/js/html/AbortSignal.hx create mode 100644 std/js/html/AddEventListenerOptions.hx rename std/js/html/{ApplicationCache.hx => AnimationEffect.hx} (53%) delete mode 100644 std/js/html/AnimationEffectTimingReadOnly.hx rename std/js/html/{CSSUnknownRule.hx => AnimationFilter.hx} (86%) rename std/js/html/{AnimationEffectTiming.hx => AnimationPlaybackEvent.hx} (59%) create mode 100644 std/js/html/AnimationPlaybackEventInit.hx create mode 100644 std/js/html/AssignedNodesOptions.hx create mode 100644 std/js/html/AutoKeyword.hx create mode 100644 std/js/html/BlobEvent.hx create mode 100644 std/js/html/BlobEventInit.hx rename std/js/html/{ElementRegistrationOptions.hx => CSSBoxType.hx} (82%) create mode 100644 std/js/html/CSSConditionRule.hx create mode 100644 std/js/html/CSSCounterStyleRule.hx create mode 100644 std/js/html/CSSFontFeatureValuesRule.hx create mode 100644 std/js/html/CSSGroupingRule.hx rename std/js/html/{Rect.hx => CSSKeyframeRule.hx} (55%) create mode 100644 std/js/html/CSSKeyframesRule.hx create mode 100644 std/js/html/CSSMozDocumentRule.hx create mode 100644 std/js/html/CSSNamespaceRule.hx delete mode 100644 std/js/html/CSSPrimitiveValue.hx create mode 100644 std/js/html/CSSSupportsRule.hx delete mode 100644 std/js/html/CSSValue.hx create mode 100644 std/js/html/Cache.hx create mode 100644 std/js/html/CacheQueryOptions.hx create mode 100644 std/js/html/CacheStorage.hx create mode 100644 std/js/html/CacheStorageNamespace.hx create mode 100644 std/js/html/CanvasCaptureMediaStream.hx create mode 100644 std/js/html/ChannelPixelLayout.hx rename std/js/html/{CommandEvent.hx => ChannelPixelLayoutDataType.hx} (75%) create mode 100644 std/js/html/ClientType.hx create mode 100644 std/js/html/Clipboard.hx rename std/js/html/{RecordErrorEventInit.hx => CompositionEventInit.hx} (85%) rename std/js/html/{MessagePortList.hx => ComputedEffectTiming.hx} (79%) create mode 100644 std/js/html/ConsoleInstance.hx create mode 100644 std/js/html/ConstrainBooleanParameters.hx create mode 100644 std/js/html/ConstrainDOMStringParameters.hx create mode 100644 std/js/html/ConstrainDoubleRange.hx create mode 100644 std/js/html/ConstrainLongRange.hx create mode 100644 std/js/html/DOMQuadJSON.hx create mode 100644 std/js/html/DataTransferItem.hx create mode 100644 std/js/html/DataTransferItemList.hx rename std/js/html/{ContentElement.hx => DetailsElement.hx} (57%) create mode 100644 std/js/html/DisplayNameOptions.hx create mode 100644 std/js/html/DisplayNameResult.hx create mode 100644 std/js/html/DocumentTimelineOptions.hx create mode 100644 std/js/html/EffectTiming.hx create mode 100644 std/js/html/ElementCreationOptions.hx rename std/js/html/{CSSCharsetRule.hx => EndingTypes.hx} (84%) create mode 100644 std/js/html/ErrorCallback.hx create mode 100644 std/js/html/EventListenerOptions.hx rename std/js/html/{LifecycleCallbacks.hx => FetchObserver.hx} (74%) create mode 100644 std/js/html/FetchState.hx rename std/js/html/{DOMTransactionEventInit.hx => FileCallback.hx} (85%) create mode 100644 std/js/html/FileSystem.hx create mode 100644 std/js/html/FileSystemDirectoryEntry.hx create mode 100644 std/js/html/FileSystemDirectoryReader.hx create mode 100644 std/js/html/FileSystemEntriesCallback.hx create mode 100644 std/js/html/FileSystemEntry.hx create mode 100644 std/js/html/FileSystemEntryCallback.hx create mode 100644 std/js/html/FileSystemFileEntry.hx create mode 100644 std/js/html/FileSystemFlags.hx create mode 100644 std/js/html/FontFaceSetLoadEvent.hx create mode 100644 std/js/html/FontFaceSetLoadEventInit.hx rename std/js/html/{CSSValueList.hx => GamepadEvent.hx} (54%) rename std/js/html/{DummyInterfaceWorkers.hx => GamepadEventInit.hx} (86%) create mode 100644 std/js/html/GetNotificationOptions.hx create mode 100644 std/js/html/GetRootNodeOptions.hx create mode 100644 std/js/html/ImageBitmapFormat.hx rename std/js/html/{AppletElement.hx => ImageCaptureError.hx} (71%) rename std/js/html/{DOMTransaction.hx => ImageCaptureErrorEvent.hx} (73%) create mode 100644 std/js/html/ImageCaptureErrorEventInit.hx create mode 100644 std/js/html/IntersectionObserver.hx create mode 100644 std/js/html/IntersectionObserverEntry.hx create mode 100644 std/js/html/IntersectionObserverInit.hx rename std/js/html/{DOMTransactionEvent.hx => IntlUtils.hx} (77%) create mode 100644 std/js/html/KeyframeAnimationOptions.hx create mode 100644 std/js/html/KeyframeEffectOptions.hx delete mode 100644 std/js/html/KeyframeEffectReadOnly.hx create mode 100644 std/js/html/LineAlignSetting.hx create mode 100644 std/js/html/LocaleInfo.hx create mode 100644 std/js/html/MediaDeviceInfo.hx create mode 100644 std/js/html/MediaDeviceKind.hx create mode 100644 std/js/html/MediaDevices.hx create mode 100644 std/js/html/MediaQueryListEvent.hx create mode 100644 std/js/html/MediaQueryListEventInit.hx create mode 100644 std/js/html/MediaRecorderErrorEvent.hx create mode 100644 std/js/html/MediaRecorderErrorEventInit.hx create mode 100644 std/js/html/MediaStreamEvent.hx create mode 100644 std/js/html/MediaStreamEventInit.hx create mode 100644 std/js/html/MediaStreamTrackEvent.hx create mode 100644 std/js/html/MediaStreamTrackEventInit.hx create mode 100644 std/js/html/MediaStreamTrackState.hx create mode 100644 std/js/html/MediaTrackSettings.hx create mode 100644 std/js/html/MediaTrackSupportedConstraints.hx create mode 100644 std/js/html/NavigationType.hx create mode 100644 std/js/html/ObserverCallback.hx create mode 100644 std/js/html/OfflineAudioCompletionEventInit.hx rename std/js/html/{RecordErrorEvent.hx => Option.hx} (78%) rename std/js/html/{AudioChannel.hx => OptionalEffectTiming.hx} (73%) create mode 100644 std/js/html/PaintWorkletGlobalScope.hx create mode 100644 std/js/html/PerformanceEntryFilterOptions.hx create mode 100644 std/js/html/PerformanceNavigationTiming.hx create mode 100644 std/js/html/PerformanceObserver.hx create mode 100644 std/js/html/PerformanceObserverEntryList.hx create mode 100644 std/js/html/PerformanceObserverInit.hx rename std/js/html/{AnimationEffectReadOnly.hx => PerformanceServerTiming.hx} (52%) create mode 100644 std/js/html/PositionAlignSetting.hx rename std/js/html/{ObjectURLOptions.hx => PromiseNativeHandler.hx} (88%) create mode 100644 std/js/html/RegistrationOptions.hx create mode 100644 std/js/html/RequestDestination.hx create mode 100644 std/js/html/ScrollBehavior.hx create mode 100644 std/js/html/ScrollLogicalPosition.hx create mode 100644 std/js/html/ScrollSetting.hx create mode 100644 std/js/html/SecurityPolicyViolationEvent.hx create mode 100644 std/js/html/SecurityPolicyViolationEventDisposition.hx rename std/js/html/{AnimationEffectTimingProperties.hx => SecurityPolicyViolationEventInit.hx} (66%) create mode 100644 std/js/html/ServiceWorkerContainer.hx create mode 100644 std/js/html/ServiceWorkerUpdateViaCache.hx create mode 100644 std/js/html/ShadowRootInit.hx create mode 100644 std/js/html/ShadowRootMode.hx delete mode 100644 std/js/html/SimpleGestureEvent.hx create mode 100644 std/js/html/SlotElement.hx create mode 100644 std/js/html/StorageEstimate.hx create mode 100644 std/js/html/StorageManager.hx create mode 100644 std/js/html/StorageType.hx create mode 100644 std/js/html/VisualViewport.hx create mode 100644 std/js/html/WorkerOptions.hx rename std/js/html/{ChromeFilePropertyBag.hx => WorkletGlobalScope.hx} (82%) create mode 100644 std/js/html/audio/AnalyserOptions.hx create mode 100644 std/js/html/audio/AudioBufferOptions.hx create mode 100644 std/js/html/audio/AudioBufferSourceOptions.hx rename std/js/html/{webgl/ExtensionDebugShaders.hx => audio/AudioContextOptions.hx} (54%) rename std/js/html/{ => audio}/AudioContextState.hx (86%) create mode 100644 std/js/html/audio/AudioNodeOptions.hx rename std/js/html/{webgl/ExtensionTextureFloatLinear.hx => audio/AudioScheduledSourceNode.hx} (51%) rename std/js/html/{ComputedTimingProperties.hx => audio/AudioWorkletGlobalScope.hx} (71%) rename std/js/html/{NotifyPaintEvent.hx => audio/AudioWorkletNodeOptions.hx} (75%) rename std/js/html/{DesktopNotification.hx => audio/AudioWorkletProcessor.hx} (76%) create mode 100644 std/js/html/audio/BaseAudioContext.hx create mode 100644 std/js/html/audio/BiquadFilterOptions.hx create mode 100644 std/js/html/audio/ChannelMergerOptions.hx create mode 100644 std/js/html/audio/ChannelSplitterOptions.hx create mode 100644 std/js/html/audio/ConstantSourceNode.hx create mode 100644 std/js/html/audio/ConstantSourceOptions.hx create mode 100644 std/js/html/audio/ConvolverOptions.hx create mode 100644 std/js/html/audio/DelayOptions.hx create mode 100644 std/js/html/audio/DynamicsCompressorOptions.hx create mode 100644 std/js/html/audio/GainOptions.hx create mode 100644 std/js/html/audio/IIRFilterNode.hx create mode 100644 std/js/html/audio/IIRFilterOptions.hx create mode 100644 std/js/html/audio/MediaElementAudioSourceOptions.hx create mode 100644 std/js/html/audio/MediaStreamAudioSourceOptions.hx create mode 100644 std/js/html/audio/OfflineAudioContextOptions.hx create mode 100644 std/js/html/audio/OscillatorOptions.hx create mode 100644 std/js/html/audio/PannerOptions.hx create mode 100644 std/js/html/audio/PeriodicWaveConstraints.hx create mode 100644 std/js/html/audio/PeriodicWaveOptions.hx create mode 100644 std/js/html/audio/StereoPannerOptions.hx create mode 100644 std/js/html/audio/WaveShaperOptions.hx delete mode 100644 std/js/html/compat/DataView.hx delete mode 100644 std/js/html/compat/Float32Array.hx delete mode 100644 std/js/html/compat/Float64Array.hx delete mode 100644 std/js/html/compat/Uint8Array.hx rename std/js/html/{DesktopNotificationCenter.hx => eme/MediaEncryptedEvent.hx} (72%) create mode 100644 std/js/html/eme/MediaKeyError.hx create mode 100644 std/js/html/eme/MediaKeyMessageEvent.hx create mode 100644 std/js/html/eme/MediaKeyMessageEventInit.hx create mode 100644 std/js/html/eme/MediaKeyMessageType.hx create mode 100644 std/js/html/eme/MediaKeyNeededEventInit.hx create mode 100644 std/js/html/eme/MediaKeySession.hx create mode 100644 std/js/html/eme/MediaKeySessionType.hx create mode 100644 std/js/html/eme/MediaKeyStatusMap.hx create mode 100644 std/js/html/eme/MediaKeySystemAccess.hx create mode 100644 std/js/html/eme/MediaKeySystemConfiguration.hx create mode 100644 std/js/html/eme/MediaKeySystemMediaCapability.hx create mode 100644 std/js/html/eme/MediaKeys.hx create mode 100644 std/js/html/eme/MediaKeysRequirement.hx create mode 100644 std/js/html/midi/MIDIAccess.hx create mode 100644 std/js/html/midi/MIDIConnectionEvent.hx create mode 100644 std/js/html/midi/MIDIConnectionEventInit.hx create mode 100644 std/js/html/midi/MIDIInput.hx create mode 100644 std/js/html/midi/MIDIInputMap.hx create mode 100644 std/js/html/midi/MIDIMessageEvent.hx create mode 100644 std/js/html/midi/MIDIMessageEventInit.hx create mode 100644 std/js/html/midi/MIDIOptions.hx rename std/js/html/{XMLStylesheetProcessingInstruction.hx => midi/MIDIOutput.hx} (78%) create mode 100644 std/js/html/midi/MIDIOutputMap.hx rename std/js/html/{RGBColor.hx => midi/MIDIPort.hx} (62%) create mode 100644 std/js/html/midi/MIDIPortConnectionState.hx create mode 100644 std/js/html/midi/MIDIPortDeviceState.hx create mode 100644 std/js/html/midi/MIDIPortType.hx create mode 100644 std/js/html/push/PushEncryptionKeyName.hx create mode 100644 std/js/html/push/PushEvent.hx create mode 100644 std/js/html/push/PushEventInit.hx create mode 100644 std/js/html/push/PushManager.hx create mode 100644 std/js/html/push/PushMessageData.hx create mode 100644 std/js/html/push/PushPermissionState.hx create mode 100644 std/js/html/push/PushSubscription.hx create mode 100644 std/js/html/push/PushSubscriptionInit.hx create mode 100644 std/js/html/push/PushSubscriptionJSON.hx create mode 100644 std/js/html/push/PushSubscriptionKeys.hx rename std/js/html/{svg/Document.hx => push/PushSubscriptionOptions.hx} (79%) create mode 100644 std/js/html/push/PushSubscriptionOptionsInit.hx create mode 100644 std/js/html/rtc/BundlePolicy.hx create mode 100644 std/js/html/rtc/DTMFSender.hx create mode 100644 std/js/html/rtc/DTMFToneChangeEvent.hx create mode 100644 std/js/html/rtc/DTMFToneChangeEventInit.hx create mode 100644 std/js/html/rtc/DataChannelEvent.hx create mode 100644 std/js/html/rtc/DataChannelEventInit.hx rename std/js/html/{DummyInterface.hx => rtc/DegradationPreference.hx} (78%) create mode 100644 std/js/html/rtc/FecParameters.hx create mode 100644 std/js/html/rtc/IceCredentialType.hx rename std/js/html/{UncaughtRejectionObserver.hx => rtc/IceServer.hx} (77%) create mode 100644 std/js/html/rtc/IceTransportPolicy.hx create mode 100644 std/js/html/rtc/IdentityProviderDetails.hx create mode 100644 std/js/html/rtc/IdentityProviderOptions.hx rename std/js/html/{webgl/VertexArrayObjectOES.hx => rtc/PeerConnectionIceEvent.hx} (55%) create mode 100644 std/js/html/rtc/PeerConnectionIceEventInit.hx create mode 100644 std/js/html/rtc/PriorityType.hx create mode 100644 std/js/html/rtc/RtcpParameters.hx create mode 100644 std/js/html/rtc/RtpCodecParameters.hx create mode 100644 std/js/html/rtc/RtpContributingSource.hx create mode 100644 std/js/html/rtc/RtpEncodingParameters.hx create mode 100644 std/js/html/rtc/RtpHeaderExtensionParameters.hx create mode 100644 std/js/html/rtc/RtpSynchronizationSource.hx create mode 100644 std/js/html/rtc/RtpTransceiver.hx create mode 100644 std/js/html/rtc/RtpTransceiverDirection.hx create mode 100644 std/js/html/rtc/RtpTransceiverInit.hx create mode 100644 std/js/html/rtc/RtxParameters.hx create mode 100644 std/js/html/rtc/TrackEvent.hx create mode 100644 std/js/html/rtc/TrackEventInit.hx rename std/js/html/svg/{AltGlyphElement.hx => GeometryElement.hx} (54%) delete mode 100644 std/js/html/svg/ZoomEvent.hx create mode 100644 std/js/html/webgl/Extension.hx delete mode 100644 std/js/html/webgl/ExtensionTextureHalfFloatLinear.hx create mode 100644 std/js/html/webgl/GL2.hx create mode 100644 std/js/html/webgl/PowerPreference.hx rename std/js/html/webgl/{ExtensionFragDepth.hx => Query.hx} (66%) rename std/js/html/webgl/{ExtensionTextureFloat.hx => Sampler.hx} (62%) create mode 100644 std/js/html/webgl/Sync.hx delete mode 100644 std/js/html/webgl/TimerQueryEXT.hx rename std/js/html/webgl/{ExtensionShaderTextureLod.hx => TransformFeedback.hx} (58%) rename std/js/html/webgl/{ExtensionElementIndexUint.hx => VertexArrayObject.hx} (66%) create mode 100644 std/js/html/webgl/WebGL2RenderingContext.hx rename std/js/html/webgl/{ExtensionInstancedArrays.hx => extension/ANGLEInstancedArrays.hx} (90%) rename std/js/html/webgl/{ExtensionBlendMinMax.hx => extension/EXTBlendMinmax.hx} (86%) create mode 100644 std/js/html/webgl/extension/EXTColorBufferFloat.hx rename std/js/html/webgl/{ExtensionColorBufferHalfFloat.hx => extension/EXTColorBufferHalfFloat.hx} (87%) rename std/js/html/webgl/{ExtensionDisjointTimerQuery.hx => extension/EXTDisjointTimerQuery.hx} (69%) create mode 100644 std/js/html/webgl/extension/EXTFragDepth.hx create mode 100644 std/js/html/webgl/extension/EXTShaderTextureLod.hx rename std/js/html/webgl/{ExtensionSRGB.hx => extension/EXTSrgb.hx} (83%) rename std/js/html/webgl/{ExtensionTextureFilterAnisotropic.hx => extension/EXTTextureFilterAnisotropic.hx} (79%) create mode 100644 std/js/html/webgl/extension/OESElementIndexUint.hx rename std/js/html/webgl/{ExtensionStandardDerivatives.hx => extension/OESStandardDerivatives.hx} (87%) create mode 100644 std/js/html/webgl/extension/OESTextureFloat.hx create mode 100644 std/js/html/webgl/extension/OESTextureFloatLinear.hx rename std/js/html/webgl/{ExtensionTextureHalfFloat.hx => extension/OESTextureHalfFloat.hx} (91%) create mode 100644 std/js/html/webgl/extension/OESTextureHalfFloatLinear.hx rename std/js/html/webgl/{ExtensionVertexArrayObject.hx => extension/OESVertexArrayObject.hx} (70%) rename std/js/html/webgl/{ExtensionColorBufferFloat.hx => extension/WEBGLColorBufferFloat.hx} (87%) create mode 100644 std/js/html/webgl/extension/WEBGLCompressedTextureAstc.hx rename std/js/html/webgl/{ExtensionCompressedTextureATC.hx => extension/WEBGLCompressedTextureAtc.hx} (83%) rename std/js/html/webgl/{ExtensionCompressedTextureES3.hx => extension/WEBGLCompressedTextureEtc.hx} (60%) rename std/js/html/webgl/{ExtensionCompressedTextureETC1.hx => extension/WEBGLCompressedTextureEtc1.hx} (90%) rename std/js/html/webgl/{ExtensionCompressedTexturePVRTC.hx => extension/WEBGLCompressedTexturePvrtc.hx} (82%) rename std/js/html/webgl/{ExtensionCompressedTextureS3TC.hx => extension/WEBGLCompressedTextureS3tc.hx} (77%) create mode 100644 std/js/html/webgl/extension/WEBGLCompressedTextureS3tcSrgb.hx rename std/js/html/webgl/{ExtensionDebugRendererInfo.hx => extension/WEBGLDebugRendererInfo.hx} (94%) create mode 100644 std/js/html/webgl/extension/WEBGLDebugShaders.hx rename std/js/html/webgl/{ExtensionDepthTexture.hx => extension/WEBGLDepthTexture.hx} (90%) rename std/js/html/webgl/{ExtensionDrawBuffers.hx => extension/WEBGLDrawBuffers.hx} (91%) create mode 100644 std/js/html/webgl/extension/WEBGLLoseContext.hx delete mode 100644 std/js/jquery/Callbacks.hx delete mode 100644 std/js/jquery/Deferred.hx delete mode 100644 std/js/jquery/Event.hx delete mode 100644 std/js/jquery/Helper.hx delete mode 100644 std/js/jquery/JQuery.hx delete mode 100644 std/js/jquery/JqEltsIterator.hx delete mode 100644 std/js/jquery/JqIterator.hx delete mode 100644 std/js/jquery/JqXHR.hx delete mode 100644 std/js/jquery/Promise.hx rename std/js/{html/DOMCursor.hx => lib/ArrayBuffer.hx} (57%) create mode 100644 std/js/lib/ArrayBufferView.hx create mode 100644 std/js/lib/BufferSource.hx create mode 100644 std/js/lib/DataView.hx create mode 100644 std/js/lib/Date.hx create mode 100644 std/js/lib/Error.hx create mode 100644 std/js/lib/Float32Array.hx create mode 100644 std/js/lib/Float64Array.hx create mode 100644 std/js/lib/Function.hx create mode 100644 std/js/lib/Int16Array.hx create mode 100644 std/js/lib/Int32Array.hx create mode 100644 std/js/lib/Int8Array.hx create mode 100644 std/js/lib/Intl.hx rename std/{php/_std/haxe/Log.hx => js/lib/Iterator.hx} (85%) create mode 100644 std/js/lib/Map.hx create mode 100644 std/js/lib/Math.hx create mode 100644 std/js/lib/Object.hx create mode 100644 std/js/lib/Promise.hx create mode 100644 std/js/lib/Proxy.hx create mode 100644 std/js/lib/Reflect.hx create mode 100644 std/js/lib/RegExp.hx create mode 100644 std/js/lib/Set.hx create mode 100644 std/js/lib/Symbol.hx create mode 100644 std/js/lib/Uint16Array.hx create mode 100644 std/js/lib/Uint32Array.hx create mode 100644 std/js/lib/Uint8Array.hx create mode 100644 std/js/lib/Uint8ClampedArray.hx create mode 100644 std/js/lib/WeakMap.hx create mode 100644 std/js/lib/WeakSet.hx create mode 100644 std/js/lib/WebAssembly.hx create mode 100644 std/js/lib/intl/Collator.hx create mode 100644 std/js/lib/intl/DateTimeFormat.hx create mode 100644 std/js/lib/intl/LocaleMatcher.hx create mode 100644 std/js/lib/intl/NumberFormat.hx create mode 100644 std/js/lib/intl/PluralRules.hx create mode 100644 std/js/lib/intl/RelativeTimeFormat.hx create mode 100644 std/js/lib/webassembly/CompileError.hx create mode 100644 std/js/lib/webassembly/Global.hx create mode 100644 std/js/lib/webassembly/Instance.hx rename std/js/{html/ShadowElement.hx => lib/webassembly/LinkError.hx} (61%) create mode 100644 std/js/lib/webassembly/Memory.hx create mode 100644 std/js/lib/webassembly/Module.hx create mode 100644 std/js/lib/webassembly/RuntimeError.hx create mode 100644 std/js/lib/webassembly/Table.hx delete mode 100644 std/js/swfobject/SWFObject.hx create mode 100644 std/jvm/DynamicObject.hx create mode 100644 std/jvm/EmptyConstructor.hx rename std/{java/_std/haxe/Log.hx => jvm/Enum.hx} (64%) create mode 100644 std/jvm/Exception.hx create mode 100644 std/jvm/Jvm.hx create mode 100644 std/jvm/NativeTools.hx rename std/{haxe/remoting/AsyncProxy.hx => jvm/Object.hx} (75%) create mode 100644 std/jvm/StringExt.hx create mode 100644 std/jvm/_std/Reflect.hx create mode 100644 std/jvm/_std/Std.hx create mode 100644 std/jvm/_std/String.hx create mode 100644 std/jvm/_std/Type.hx create mode 100644 std/jvm/annotation/ClassReflectionInformation.hx create mode 100644 std/jvm/annotation/EnumReflectionInformation.hx create mode 100644 std/jvm/annotation/EnumValueReflectionInformation.hx delete mode 100644 std/lua/_lua/_hx_apply.lua create mode 100644 std/lua/_lua/_hx_apply_self.lua create mode 100644 std/lua/_lua/_hx_bind.lua create mode 100644 std/lua/_lua/_hx_bit.lua create mode 100644 std/lua/_lua/_hx_bit_clamp.lua create mode 100644 std/lua/_lua/_hx_box_mr.lua create mode 100644 std/lua/_lua/_hx_dyn_add.lua create mode 100644 std/lua/_lua/_hx_func_to_field.lua create mode 100644 std/lua/_lua/_hx_print.lua create mode 100644 std/lua/_lua/_hx_random_init.lua create mode 100644 std/lua/_lua/_hx_static_to_instance.lua create mode 100644 std/lua/_lua/_hx_table.lua create mode 100644 std/lua/_lua/_hx_wrap_if_string_field.lua delete mode 100644 std/lua/_std/haxe/Utf8.hx create mode 100644 std/lua/_std/sys/net/Socket.hx create mode 100644 std/lua/lib/luasocket/socket/AddrInfo.hx create mode 100644 std/lua/lib/luasocket/socket/ReceivePattern.hx create mode 100644 std/lua/lib/luasocket/socket/SelectResult.hx create mode 100644 std/lua/lib/luasocket/socket/ShutdownMode.hx rename std/{haxe/remoting/AsyncConnection.hx => lua/lib/luasocket/socket/TcpClient.hx} (65%) create mode 100644 std/lua/lib/luasocket/socket/TcpMaster.hx rename std/{haxe/remoting/Connection.hx => lua/lib/luasocket/socket/TcpOption.hx} (82%) rename std/{haxe/remoting/Proxy.hx => lua/lib/luasocket/socket/TcpServer.hx} (78%) create mode 100644 std/lua/lib/luasocket/socket/TimeoutMode.hx create mode 100644 std/lua/lib/luautf8/Utf8.hx create mode 100644 std/neko/Utf8.hx create mode 100644 std/neko/_std/sys/thread/Deque.hx create mode 100644 std/neko/_std/sys/thread/Lock.hx create mode 100644 std/neko/_std/sys/thread/Mutex.hx create mode 100644 std/neko/_std/sys/thread/Thread.hx create mode 100644 std/neko/_std/sys/thread/Tls.hx delete mode 100644 std/neko/net/Poll.hx delete mode 100644 std/neko/net/ProxyDetect.hx delete mode 100644 std/neko/net/ServerLoop.hx delete mode 100644 std/neko/net/ThreadRemotingServer.hx delete mode 100644 std/neko/net/ThreadServer.hx create mode 100644 std/php/Generator.hx create mode 100644 std/php/_polyfills.php create mode 100644 std/php/_std/haxe/crypto/Base64.hx create mode 100644 std/php/_std/haxe/ds/Vector.hx create mode 100644 std/php/_std/haxe/format/JsonParser.hx rename std/{js/html/compat/ArrayBuffer.hx => php/_std/haxe/iterators/StringIteratorUnicode.hx} (52%) create mode 100644 std/php/_std/haxe/iterators/StringKeyValueIteratorUnicode.hx create mode 100644 std/php/_std/haxe/xml/Parser.hx create mode 100644 std/php/net/Socket.hx create mode 100644 std/python/lib/Socket.hx create mode 100644 std/python/lib/Ssl.hx create mode 100644 std/python/lib/socket/Address.hx create mode 100644 std/python/lib/socket/Socket.hx create mode 100644 std/python/lib/ssl/Purpose.hx create mode 100644 std/python/lib/ssl/SSLContext.hx create mode 100644 std/python/lib/ssl/SSLSession.hx create mode 100644 std/python/lib/ssl/SSLSocket.hx create mode 100644 std/python/net/SslSocket.hx create mode 100644 std/sys/Http.hx rename std/{js/html/webgl/ExtensionLoseContext.hx => sys/thread/Deque.hx} (54%) create mode 100644 std/sys/thread/Lock.hx create mode 100644 std/sys/thread/Mutex.hx create mode 100644 std/sys/thread/Thread.hx create mode 100644 std/sys/thread/Tls.hx delete mode 100644 tests/Indexer.hx create mode 100644 tests/benchs/build.hxml delete mode 100644 tests/benchs/ds/src/Main.hx delete mode 100644 tests/benchs/ds/tests.hxml create mode 100644 tests/benchs/mandelbrot/compile-jvm.hxml delete mode 100644 tests/benchs/mtnetwork/MTNetwork.hx create mode 100644 tests/benchs/src/Macro.hx create mode 100644 tests/benchs/src/Main.hx create mode 100644 tests/benchs/src/TestCase.hx create mode 100644 tests/benchs/src/cases/Access.hx create mode 100644 tests/benchs/src/cases/Calls.hx create mode 100644 tests/benchs/src/cases/CharacterAccess.hx create mode 100644 tests/benchs/src/cases/CustomIterator.hx create mode 100644 tests/benchs/src/cases/Ds.hx create mode 100644 tests/benchs/src/cases/StringIterator.hx create mode 100644 tests/benchs/src/cases/StringScan.hx create mode 100644 tests/benchs/src/hxbenchmark/CaseResult.hx create mode 100644 tests/benchs/src/hxbenchmark/ResultPrinter.hx create mode 100644 tests/benchs/src/hxbenchmark/Suite.hx create mode 100644 tests/benchs/src/hxbenchmark/SuiteResult.hx create mode 100644 tests/display/.gitignore create mode 100644 tests/display/src-shared/Marker.hx create mode 100644 tests/display/src/Diagnostic.hx create mode 100644 tests/display/src/cases/ArrayAccessSignature.hx create mode 100644 tests/display/src/cases/InMacro.hx create mode 100644 tests/display/src/cases/Issue4155.hx create mode 100644 tests/display/src/cases/Issue4345.hx create mode 100644 tests/display/src/cases/Issue5306.hx create mode 100644 tests/display/src/cases/Issue5649.hx create mode 100644 tests/display/src/cases/Issue5767.hx create mode 100644 tests/display/src/cases/Issue5967.hx create mode 100644 tests/display/src/cases/Issue5999.hx create mode 100644 tests/display/src/cases/Issue6020.hx create mode 100644 tests/display/src/cases/Issue6227.hx create mode 100644 tests/display/src/cases/Issue6265.hx create mode 100644 tests/display/src/cases/Issue6405.hx create mode 100644 tests/display/src/cases/Issue6740.hx create mode 100644 tests/display/src/cases/Issue6756.hx create mode 100644 tests/display/src/cases/Issue6779.hx create mode 100644 tests/display/src/cases/Issue6923.hx create mode 100644 tests/display/src/cases/Issue6943.hx create mode 100644 tests/display/src/cases/Issue6951.hx create mode 100644 tests/display/src/cases/Issue6997.hx create mode 100644 tests/display/src/cases/Issue7020.hx create mode 100644 tests/display/src/cases/Issue7022.hx create mode 100644 tests/display/src/cases/Issue7023.hx create mode 100644 tests/display/src/cases/Issue7027.hx create mode 100644 tests/display/src/cases/Issue7029.hx create mode 100644 tests/display/src/cases/Issue7046.hx create mode 100644 tests/display/src/cases/Issue7047.hx create mode 100644 tests/display/src/cases/Issue7050.hx create mode 100644 tests/display/src/cases/Issue7051.hx create mode 100644 tests/display/src/cases/Issue7053.hx create mode 100644 tests/display/src/cases/Issue7055.hx create mode 100644 tests/display/src/cases/Issue7057.hx create mode 100644 tests/display/src/cases/Issue7059.hx create mode 100644 tests/display/src/cases/Issue7060.hx create mode 100644 tests/display/src/cases/Issue7061.hx create mode 100644 tests/display/src/cases/Issue7063.hx create mode 100644 tests/display/src/cases/Issue7066.hx create mode 100644 tests/display/src/cases/Issue7068.hx create mode 100644 tests/display/src/cases/Issue7069.hx create mode 100644 tests/display/src/cases/Issue7071.hx create mode 100644 tests/display/src/cases/Issue7072.hx create mode 100644 tests/display/src/cases/Issue7075.hx create mode 100644 tests/display/src/cases/Issue7082.hx create mode 100644 tests/display/src/cases/Issue7084.hx create mode 100644 tests/display/src/cases/Issue7086.hx create mode 100644 tests/display/src/cases/Issue7089.hx create mode 100644 tests/display/src/cases/Issue7092.hx create mode 100644 tests/display/src/cases/Issue7098.hx create mode 100644 tests/display/src/cases/Issue7102.hx create mode 100644 tests/display/src/cases/Issue7111.hx create mode 100644 tests/display/src/cases/Issue7114.hx create mode 100644 tests/display/src/cases/Issue7133.hx create mode 100644 tests/display/src/cases/Issue7136.hx create mode 100644 tests/display/src/cases/Issue7137.hx create mode 100644 tests/display/src/cases/Issue7148.hx create mode 100644 tests/display/src/cases/Issue7158.hx create mode 100644 tests/display/src/cases/Issue7171.hx create mode 100644 tests/display/src/cases/Issue7172.hx create mode 100644 tests/display/src/cases/Issue7211.hx create mode 100644 tests/display/src/cases/Issue7219.hx create mode 100644 tests/display/src/cases/Issue7224.hx create mode 100644 tests/display/src/cases/Issue7248.hx create mode 100644 tests/display/src/cases/Issue7252.hx create mode 100644 tests/display/src/cases/Issue7281.hx create mode 100644 tests/display/src/cases/Issue7319.hx create mode 100644 tests/display/src/cases/Issue7320.hx create mode 100644 tests/display/src/cases/Issue7326.hx create mode 100644 tests/display/src/cases/Issue7327.hx create mode 100644 tests/display/src/cases/Issue7328.hx create mode 100644 tests/display/src/cases/Issue7471.hx create mode 100644 tests/display/src/cases/Issue7577.hx create mode 100644 tests/display/src/cases/Issue7627.hx create mode 100644 tests/display/src/cases/Issue7650.hx create mode 100644 tests/display/src/cases/Issue7751.hx create mode 100644 tests/display/src/cases/Issue7752.hx create mode 100644 tests/display/src/cases/Issue7761.hx create mode 100644 tests/display/src/cases/Issue7777.hx create mode 100644 tests/display/src/cases/Issue7877.hx create mode 100644 tests/display/src/cases/Issue7878.hx create mode 100644 tests/display/src/cases/Issue7906.hx create mode 100644 tests/display/src/cases/Issue7911.hx create mode 100644 tests/display/src/cases/Issue7932.hx create mode 100644 tests/display/src/cases/Issue7935.hx create mode 100644 tests/display/src/cases/Issue7937.hx create mode 100644 tests/display/src/cases/Issue7938.hx create mode 100644 tests/display/src/cases/Issue7939.hx create mode 100644 tests/display/src/cases/Issue7940.hx create mode 100644 tests/display/src/cases/Issue7943.hx create mode 100644 tests/display/src/cases/Issue7945.hx create mode 100644 tests/display/src/cases/Issue7946.hx create mode 100644 tests/display/src/cases/Issue7947.hx create mode 100644 tests/display/src/cases/Issue7972.hx create mode 100644 tests/display/src/cases/Issue7998.hx create mode 100644 tests/display/src/cases/Issue8007.hx create mode 100644 tests/display/src/cases/Issue8014.hx create mode 100644 tests/display/src/cases/Issue8046.hx create mode 100644 tests/display/src/cases/Issue8078.hx create mode 100644 tests/display/src/cases/Issue8180.hx create mode 100644 tests/display/src/cases/Issue8217.hx create mode 100644 tests/display/src/cases/Issue8345.hx create mode 100644 tests/display/src/cases/Issue8359.hx create mode 100644 tests/display/src/cases/Issue8383.hx create mode 100644 tests/display/src/cases/Issue8396.hx create mode 100644 tests/display/src/cases/Issue8420.hx create mode 100644 tests/display/src/cases/Issue8459.hx create mode 100644 tests/display/src/cases/Issue8558.hx create mode 100644 tests/display/src/cases/IssueTemplate.hx create mode 100644 tests/display/src/cases/Override.hx create mode 100644 tests/display/src/cases/Resuming.hx create mode 100644 tests/display/src/cases/StaticExtension.hx create mode 100644 tests/display/src/cases/TypeHints.hx create mode 100644 tests/display/src/cases/VsHaxeIssue198.hx create mode 100644 tests/display/src/cases/_issue5417/Issue5417.hx create mode 100644 tests/display/src/cases/import.hx create mode 100644 tests/display/src/import.hx create mode 100644 tests/display/src/misc/issue7098/Bar.hx create mode 100644 tests/display/src/misc/issue7777/Foo.hx create mode 100644 tests/display/src/misc/issue7777/Thing.hx create mode 100644 tests/display/src/misc/issue7877/ProcessMacro.hx create mode 100644 tests/display/src/misc/issue7877/ProcessedClass.hx create mode 100644 tests/display/src/misc/issue7911/Test.hx create mode 100644 tests/display/src/misc/issue7911/import.hx create mode 100644 tests/echoServer/.gitignore create mode 100644 tests/echoServer/EchoServer.hx create mode 100644 tests/echoServer/build.hxml create mode 100644 tests/echoServer/www/crossdomain.xml create mode 100644 tests/misc/README.md rename tests/{unit/compiler_loops/Issue5189.hx => misc/compiler_loops/projects/Issue5189/Main.hx} (100%) create mode 100644 tests/misc/compiler_loops/projects/Issue5189/compile-fail.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue5189/compile-fail.hxml.stderr create mode 100644 tests/misc/compiler_loops/projects/Issue5345/Main.hx create mode 100644 tests/misc/compiler_loops/projects/Issue5345/Main2.hx create mode 100644 tests/misc/compiler_loops/projects/Issue5345/Main3.hx create mode 100644 tests/misc/compiler_loops/projects/Issue5345/compile-fail.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue5345/compile-fail.hxml.stderr create mode 100644 tests/misc/compiler_loops/projects/Issue5345/compile2-fail.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue5345/compile2-fail.hxml.stderr create mode 100644 tests/misc/compiler_loops/projects/Issue5345/compile3-fail.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue5345/compile3-fail.hxml.stderr create mode 100644 tests/misc/compiler_loops/projects/Issue5785/Main1.hx create mode 100644 tests/misc/compiler_loops/projects/Issue5785/Main2.hx create mode 100644 tests/misc/compiler_loops/projects/Issue5785/Main3.hx create mode 100644 tests/misc/compiler_loops/projects/Issue5785/compile1.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue5785/compile2.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue5785/compile3.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue6038/Main.hx create mode 100644 tests/misc/compiler_loops/projects/Issue6038/compile.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue7733/Main.hx create mode 100644 tests/misc/compiler_loops/projects/Issue7733/compile.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue8588/Main.hx create mode 100644 tests/misc/compiler_loops/projects/Issue8588/Main2.hx create mode 100644 tests/misc/compiler_loops/projects/Issue8588/Main3.hx create mode 100644 tests/misc/compiler_loops/projects/Issue8588/Main4.hx create mode 100644 tests/misc/compiler_loops/projects/Issue8588/Main5.hx create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile-fail.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile-fail.hxml.stderr create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile2-fail.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile2-fail.hxml.stderr create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile3-fail.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile3-fail.hxml.stderr create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile4-fail.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile4-fail.hxml.stderr create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile5-fail.hxml create mode 100644 tests/misc/compiler_loops/projects/Issue8588/compile5-fail.hxml.stderr create mode 100644 tests/misc/compiler_loops/run.hxml rename tests/misc/{ => cs}/csTwoLibs/.gitignore (100%) rename tests/misc/{ => cs}/csTwoLibs/Lib1.hx (100%) rename tests/misc/{ => cs}/csTwoLibs/Main.hx (100%) create mode 100644 tests/misc/cs/csTwoLibs/compile-1.hxml rename tests/misc/{ => cs}/csTwoLibs/compile-2.hxml (52%) rename tests/misc/{ => cs}/csTwoLibs/compile-3.hxml (56%) rename tests/misc/{ => cs}/csTwoLibs/compile-4.hxml (60%) create mode 100644 tests/misc/cs/projects/Issue3526/.gitignore create mode 100644 tests/misc/cs/projects/Issue3526/IncompatibleCombinations.hx create mode 100644 tests/misc/cs/projects/Issue3526/Main.hx create mode 100644 tests/misc/cs/projects/Issue3526/compile-7.3.hxml create mode 100644 tests/misc/cs/projects/Issue3526/compile.hxml create mode 100644 tests/misc/cs/projects/Issue3526/incompatible-combinations-fail.hxml create mode 100644 tests/misc/cs/projects/Issue3526/incompatible-combinations-fail.hxml.stderr create mode 100644 tests/misc/cs/projects/Issue3703/Main.hx create mode 100644 tests/misc/cs/projects/Issue3703/Test.hx create mode 100644 tests/misc/cs/projects/Issue3703/compile.hxml create mode 100644 tests/misc/cs/projects/Issue4002/Main.hx create mode 100644 tests/misc/cs/projects/Issue4002/compile.hxml rename tests/misc/{ => cs}/projects/Issue4116/.gitignore (100%) rename tests/misc/{ => cs}/projects/Issue4116/base/A.hx (100%) rename tests/misc/{ => cs}/projects/Issue4116/compile.hxml (100%) rename tests/misc/{pythonImport/native_python/__init__.py => cs/projects/Issue4151/Main.hx} (100%) create mode 100644 tests/misc/cs/projects/Issue4151/compile.hxml create mode 100644 tests/misc/cs/projects/Issue4598/Main.hx create mode 100644 tests/misc/cs/projects/Issue4598/Run.hx create mode 100644 tests/misc/cs/projects/Issue4598/compile.hxml create mode 100644 tests/misc/cs/projects/Issue4623/Main.hx create mode 100644 tests/misc/cs/projects/Issue4623/Run.hx create mode 100644 tests/misc/cs/projects/Issue4623/compile.hxml create mode 100644 tests/misc/cs/projects/Issue5434/Main.hx create mode 100644 tests/misc/cs/projects/Issue5434/compile.hxml create mode 100644 tests/misc/cs/projects/Issue5915/Test.hx create mode 100644 tests/misc/cs/projects/Issue5915/compile.hxml create mode 100644 tests/misc/cs/projects/Issue5953/Main.hx create mode 100644 tests/misc/cs/projects/Issue5953/Reduced.hx create mode 100644 tests/misc/cs/projects/Issue5953/compile.hxml create mode 100644 tests/misc/cs/projects/Issue7875/Main.hx create mode 100644 tests/misc/cs/projects/Issue7875/compile.hxml create mode 100644 tests/misc/cs/projects/Issue8361/Main.hx create mode 100644 tests/misc/cs/projects/Issue8361/compile.hxml create mode 100644 tests/misc/cs/projects/Issue8366/Main.hx create mode 100644 tests/misc/cs/projects/Issue8366/compile.hxml create mode 100644 tests/misc/cs/run.hxml delete mode 100644 tests/misc/csTwoLibs/compile-1.hxml create mode 100644 tests/misc/es6/.gitignore create mode 100644 tests/misc/es6/Test.hx create mode 100644 tests/misc/es6/extern.js create mode 100644 tests/misc/es6/run.hxml create mode 100644 tests/misc/java/projects/Issue8322/Main.hx create mode 100644 tests/misc/java/projects/Issue8322/compile.hxml create mode 100644 tests/misc/java/projects/Issue8444/Main.hx create mode 100644 tests/misc/java/projects/Issue8444/compile.hxml create mode 100644 tests/misc/java/run.hxml create mode 100644 tests/misc/php/projects/.gitignore create mode 100644 tests/misc/php/projects/Issue7725/compile.hxml create mode 100644 tests/misc/php/projects/Issue7725/run.php create mode 100644 tests/misc/php/projects/Issue7725/src/App1.hx create mode 100644 tests/misc/php/projects/Issue7725/src/App2.hx create mode 100644 tests/misc/php/projects/Issue8249/compile.hxml create mode 100644 tests/misc/php/projects/Issue8249/src/Main.hx create mode 100644 tests/misc/php/run.hxml create mode 100644 tests/misc/projects/Issue3181/Main.hx create mode 100644 tests/misc/projects/Issue3181/compile-fail.hxml create mode 100644 tests/misc/projects/Issue3181/compile-fail.hxml.stderr delete mode 100644 tests/misc/projects/Issue3256/Main.hx delete mode 100644 tests/misc/projects/Issue3256/compile.hxml delete mode 100644 tests/misc/projects/Issue3256/compile.hxml.stderr delete mode 100644 tests/misc/projects/Issue3261/Main.hx delete mode 100644 tests/misc/projects/Issue3261/compile.hxml delete mode 100644 tests/misc/projects/Issue3261/compile.hxml.stderr delete mode 100644 tests/misc/projects/Issue3830/Main.hx delete mode 100644 tests/misc/projects/Issue3830/compile.hxml delete mode 100644 tests/misc/projects/Issue3830/compile.hxml.stderr delete mode 100644 tests/misc/projects/Issue3911/Main1.hx delete mode 100644 tests/misc/projects/Issue3911/Main2.hx delete mode 100644 tests/misc/projects/Issue3911/Main3.hx delete mode 100644 tests/misc/projects/Issue3911/compile1.hxml delete mode 100644 tests/misc/projects/Issue3911/compile1.hxml.stderr delete mode 100644 tests/misc/projects/Issue3911/compile2.hxml delete mode 100644 tests/misc/projects/Issue3911/compile2.hxml.stderr delete mode 100644 tests/misc/projects/Issue3911/compile3.hxml delete mode 100644 tests/misc/projects/Issue3911/compile3.hxml.stderr create mode 100644 tests/misc/projects/Issue4458/Main.hx create mode 100644 tests/misc/projects/Issue4458/compile-pass1.hxml create mode 100644 tests/misc/projects/Issue4458/compile-pass2.hxml create mode 100644 tests/misc/projects/Issue4458/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4458/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4458/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue4458/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4720/compile2.hxml create mode 100644 tests/misc/projects/Issue4720/compile2.hxml.stderr create mode 100644 tests/misc/projects/Issue4891/Main.hx create mode 100644 tests/misc/projects/Issue4891/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4891/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5008/Main.hx create mode 100644 tests/misc/projects/Issue5008/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5008/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5039/Main.hx create mode 100644 tests/misc/projects/Issue5039/Main2.hx create mode 100644 tests/misc/projects/Issue5039/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5039/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5039/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue5039/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5205/Main.hx create mode 100644 tests/misc/projects/Issue5205/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5205/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5525/Main.hx create mode 100644 tests/misc/projects/Issue5525/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5525/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5843/Data.hx create mode 100644 tests/misc/projects/Issue5843/Macro.hx create mode 100644 tests/misc/projects/Issue5843/Main.hx create mode 100644 tests/misc/projects/Issue5843/Transform.hx create mode 100644 tests/misc/projects/Issue5843/compile.hxml create mode 100644 tests/misc/projects/Issue5871/Main.hx create mode 100644 tests/misc/projects/Issue5871/Main2.hx create mode 100644 tests/misc/projects/Issue5871/parent-constructor-fail.hxml create mode 100644 tests/misc/projects/Issue5871/parent-constructor-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5871/parent-no-constructor-fail.hxml create mode 100644 tests/misc/projects/Issue5871/parent-no-constructor-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5924/Main.hx create mode 100644 tests/misc/projects/Issue5924/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5924/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5946/Main.hx create mode 100644 tests/misc/projects/Issue5946/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5946/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5949/Main.hx create mode 100644 tests/misc/projects/Issue5949/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5949/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6005/Main.hx create mode 100644 tests/misc/projects/Issue6005/compile1.hxml create mode 100644 tests/misc/projects/Issue6006/Macro.hx create mode 100644 tests/misc/projects/Issue6006/Main.hx create mode 100644 tests/misc/projects/Issue6006/compile.hxml create mode 100644 tests/misc/projects/Issue6201/Main1.hx create mode 100644 tests/misc/projects/Issue6201/Main2.hx create mode 100644 tests/misc/projects/Issue6201/compile1-fail.hxml.disabled create mode 100644 tests/misc/projects/Issue6201/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6201/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue6201/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6226/Main.hx create mode 100644 tests/misc/projects/Issue6226/compile.hxml create mode 100644 tests/misc/projects/Issue6226/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue6340/Main.hx create mode 100644 tests/misc/projects/Issue6340/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6340/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6427/E.hx create mode 100644 tests/misc/projects/Issue6427/Main.hx create mode 100644 tests/misc/projects/Issue6427/T.hx create mode 100644 tests/misc/projects/Issue6427/compile.hxml create mode 100644 tests/misc/projects/Issue6427/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue6525/Main.hx create mode 100644 tests/misc/projects/Issue6525/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6525/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6525/pack/BasePack.hx create mode 100644 tests/misc/projects/Issue6525/pack/IPack.hx create mode 100644 tests/misc/projects/Issue6525/pack/Pvt.hx create mode 100644 tests/misc/projects/Issue6525/pack/sub/AccessSubPvt.hx create mode 100644 tests/misc/projects/Issue6525/pack/sub/ExtSubPvt.hx create mode 100644 tests/misc/projects/Issue6525/pack/sub/SubPvt.hx create mode 100644 tests/misc/projects/Issue6699/Main.hx create mode 100644 tests/misc/projects/Issue6699/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6699/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6707/Main.hx create mode 100644 tests/misc/projects/Issue6707/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6707/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6714/Main.hx create mode 100644 tests/misc/projects/Issue6714/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6714/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6757/Test.hx create mode 100644 tests/misc/projects/Issue6757/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6757/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6765/Main.hx create mode 100644 tests/misc/projects/Issue6765/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6765/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6772/Main.hx create mode 100644 tests/misc/projects/Issue6772/compile.hxml create mode 100644 tests/misc/projects/Issue6780/Main.hx create mode 100644 tests/misc/projects/Issue6780/compile.hxml create mode 100644 tests/misc/projects/Issue6780/double quotes/Double.hx create mode 100644 tests/misc/projects/Issue6780/single quotes/Single.hx create mode 100644 tests/misc/projects/Issue6790/Main.hx create mode 100644 tests/misc/projects/Issue6790/Mismatch.hx create mode 100644 tests/misc/projects/Issue6790/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6790/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6790/compile.hxml create mode 100644 tests/misc/projects/Issue6790/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue6826/Main.hx create mode 100644 tests/misc/projects/Issue6826/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6826/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6841/Main.hx create mode 100644 tests/misc/projects/Issue6841/Test.hx create mode 100644 tests/misc/projects/Issue6841/compile.hxml create mode 100644 tests/misc/projects/Issue6846/Main.hx create mode 100644 tests/misc/projects/Issue6846/compile.hxml create mode 100644 tests/misc/projects/Issue6846/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue6878/Main.hx create mode 100644 tests/misc/projects/Issue6878/Main1.hx create mode 100644 tests/misc/projects/Issue6878/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6878/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6878/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue6878/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6903/Main.hx create mode 100644 tests/misc/projects/Issue6903/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6903/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6922/Test.hx create mode 100644 tests/misc/projects/Issue6922/compile.hxml create mode 100644 tests/misc/projects/Issue6950/Main.hx create mode 100644 tests/misc/projects/Issue6950/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6950/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6965/Main.hx create mode 100644 tests/misc/projects/Issue6965/compile-fail.hxml create mode 100644 tests/misc/projects/Issue6965/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue6992/Main.hx create mode 100644 tests/misc/projects/Issue6992/compile.hxml create mode 100644 tests/misc/projects/Issue7017/Main.hx create mode 100644 tests/misc/projects/Issue7017/compile.hxml create mode 100644 tests/misc/projects/Issue7017/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue7039/Main.hx create mode 100644 tests/misc/projects/Issue7039/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7039/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7076/Main.hx create mode 100644 tests/misc/projects/Issue7076/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7076/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7096/Main.hx create mode 100644 tests/misc/projects/Issue7096/compile.hxml create mode 100644 tests/misc/projects/Issue7096/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue7108/Main.hx create mode 100644 tests/misc/projects/Issue7108/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7108/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7210/compile.hxml create mode 100644 tests/misc/projects/Issue7210/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue7210/macro/Utils.hx create mode 100644 tests/misc/projects/Issue7227/Main.hx create mode 100644 tests/misc/projects/Issue7227/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7227/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7333/Main.hx create mode 100644 tests/misc/projects/Issue7333/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7333/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7363/Main.hx create mode 100644 tests/misc/projects/Issue7363/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7363/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7453/Main.hx create mode 100644 tests/misc/projects/Issue7453/Main.macro.hx create mode 100644 tests/misc/projects/Issue7453/compile.hxml create mode 100644 tests/misc/projects/Issue7526/Main.hx create mode 100644 tests/misc/projects/Issue7526/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7526/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7614/Main.hx create mode 100644 tests/misc/projects/Issue7614/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7614/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7638/Main.hx create mode 100644 tests/misc/projects/Issue7638/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7638/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7655/Main.hx create mode 100644 tests/misc/projects/Issue7655/Mismatch.hx create mode 100644 tests/misc/projects/Issue7655/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7655/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7655/compile.hxml create mode 100644 tests/misc/projects/Issue7655/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue7734/Main.hx create mode 100644 tests/misc/projects/Issue7734/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7734/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7747/Main.hx create mode 100644 tests/misc/projects/Issue7747/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7747/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7752/Main.hx create mode 100644 tests/misc/projects/Issue7752/Main2.hx create mode 100644 tests/misc/projects/Issue7752/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7752/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7752/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue7752/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7796/Main.hx create mode 100644 tests/misc/projects/Issue7796/compile.hxml create mode 100644 tests/misc/projects/Issue7796/glsl2agal.swc create mode 100644 tests/misc/projects/Issue7824/Main.hx create mode 100644 tests/misc/projects/Issue7824/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7824/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7905/Main.hx create mode 100644 tests/misc/projects/Issue7905/compile.hxml create mode 100644 tests/misc/projects/Issue7905/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue7920/Main.hx create mode 100644 tests/misc/projects/Issue7920/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7920/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7921/Main.hx create mode 100644 tests/misc/projects/Issue7921/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7921/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7935/Main.hx create mode 100644 tests/misc/projects/Issue7935/Main2.hx create mode 100644 tests/misc/projects/Issue7935/Main3.hx create mode 100644 tests/misc/projects/Issue7935/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7935/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7935/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue7935/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7935/compile3-fail.hxml create mode 100644 tests/misc/projects/Issue7935/compile3-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue7936/.gitignore create mode 100644 tests/misc/projects/Issue7936/compile.hxml create mode 100644 tests/misc/projects/Issue7936/run.js create mode 100644 tests/misc/projects/Issue7936/src/Closures1.hx create mode 100644 tests/misc/projects/Issue7936/src/Closures2.hx create mode 100644 tests/misc/projects/Issue7936/src/ObjectMap1.hx create mode 100644 tests/misc/projects/Issue7936/src/ObjectMap2.hx create mode 100644 tests/misc/projects/Issue7997/Main.hx create mode 100644 tests/misc/projects/Issue7997/compile-fail.hxml create mode 100644 tests/misc/projects/Issue7997/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8088/Fail.hx create mode 100644 tests/misc/projects/Issue8088/Success.hx create mode 100644 tests/misc/projects/Issue8088/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8088/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8088/compile.hxml create mode 100644 tests/misc/projects/Issue8119/Main.hx create mode 100644 tests/misc/projects/Issue8119/Main2.hx create mode 100644 tests/misc/projects/Issue8119/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8119/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8119/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue8119/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8159/Macro.macro.hx create mode 100644 tests/misc/projects/Issue8159/Main.hx create mode 100644 tests/misc/projects/Issue8159/compile.hxml create mode 100644 tests/misc/projects/Issue8173/Main.hx create mode 100644 tests/misc/projects/Issue8173/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8173/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8191/U1.hx create mode 100644 tests/misc/projects/Issue8191/U2.hx create mode 100644 tests/misc/projects/Issue8191/U3.hx create mode 100644 tests/misc/projects/Issue8191/U4.hx create mode 100644 tests/misc/projects/Issue8191/U5.hx create mode 100644 tests/misc/projects/Issue8191/X1.hx create mode 100644 tests/misc/projects/Issue8191/X2.hx create mode 100644 tests/misc/projects/Issue8191/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8191/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8191/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue8191/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8191/compile3-fail.hxml create mode 100644 tests/misc/projects/Issue8191/compile3-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8191/compile4-fail.hxml create mode 100644 tests/misc/projects/Issue8191/compile4-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8191/compile5-fail.hxml create mode 100644 tests/misc/projects/Issue8191/compile5-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8191/compile6-fail.hxml create mode 100644 tests/misc/projects/Issue8191/compile6-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8191/compile7-fail.hxml create mode 100644 tests/misc/projects/Issue8191/compile7-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8202/Builder.macro.hx create mode 100644 tests/misc/projects/Issue8202/Main.hx create mode 100644 tests/misc/projects/Issue8202/compile.hxml create mode 100644 tests/misc/projects/Issue8205/Main.hx create mode 100644 tests/misc/projects/Issue8205/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8205/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8219/Main.hx create mode 100644 tests/misc/projects/Issue8219/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8219/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8231/Main.hx create mode 100644 tests/misc/projects/Issue8231/compile.hxml create mode 100644 tests/misc/projects/Issue8241/Main.hx create mode 100644 tests/misc/projects/Issue8241/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8241/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8277/Main1.hx create mode 100644 tests/misc/projects/Issue8277/Main2.hx create mode 100644 tests/misc/projects/Issue8277/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue8277/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8277/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue8277/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8283/Main.hx create mode 100644 tests/misc/projects/Issue8283/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8283/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8303/Main.hx create mode 100644 tests/misc/projects/Issue8303/MainCatch.hx create mode 100644 tests/misc/projects/Issue8303/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8303/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8303/compile.hxml create mode 100644 tests/misc/projects/Issue8336/Main.hx create mode 100644 tests/misc/projects/Issue8336/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8336/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8354/FailFrom.hx create mode 100644 tests/misc/projects/Issue8354/FailTo.hx create mode 100644 tests/misc/projects/Issue8354/Success.hx create mode 100644 tests/misc/projects/Issue8354/compile.hxml create mode 100644 tests/misc/projects/Issue8354/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue8354/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8354/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue8354/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8364/Main.hx create mode 100644 tests/misc/projects/Issue8364/compile.hxml create mode 100644 tests/misc/projects/Issue8393/Main.hx create mode 100644 tests/misc/projects/Issue8393/Main2.hx create mode 100644 tests/misc/projects/Issue8393/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8393/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8393/compile2-fail.hxml.disabled create mode 100644 tests/misc/projects/Issue8393/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8404/Main.hx create mode 100644 tests/misc/projects/Issue8404/compile.hxml create mode 100644 tests/misc/projects/Issue8466/Main.hx create mode 100644 tests/misc/projects/Issue8466/compile.hxml create mode 100644 tests/misc/projects/Issue8471/Macro.hx create mode 100644 tests/misc/projects/Issue8471/Macro2.hx create mode 100644 tests/misc/projects/Issue8471/compile.hxml create mode 100644 tests/misc/projects/Issue8471/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue8471/compile2.hxml create mode 100644 tests/misc/projects/Issue8471/compile2.hxml.stderr create mode 100644 tests/misc/projects/Issue8488/Main.hx create mode 100644 tests/misc/projects/Issue8488/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8488/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8517/Fail.hx create mode 100644 tests/misc/projects/Issue8517/Foo.hx create mode 100644 tests/misc/projects/Issue8517/Macro.hx create mode 100644 tests/misc/projects/Issue8517/Main.hx create mode 100644 tests/misc/projects/Issue8517/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8517/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8517/compile.hxml create mode 100644 tests/misc/projects/Issue8527/Main.hx create mode 100644 tests/misc/projects/Issue8527/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8527/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8530/Main.hx create mode 100644 tests/misc/projects/Issue8530/compile.hxml create mode 100644 tests/misc/projects/Issue8533/Main.hx create mode 100644 tests/misc/projects/Issue8533/Main.hx.txt create mode 100644 tests/misc/projects/Issue8533/compile.hxml create mode 100644 tests/misc/projects/Issue8534/Main.hx create mode 100644 tests/misc/projects/Issue8534/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8534/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8550/Fail.hx create mode 100644 tests/misc/projects/Issue8550/Success.hx create mode 100644 tests/misc/projects/Issue8550/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8550/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8550/compile.hxml create mode 100644 tests/misc/projects/Issue8551/Main.hx create mode 100644 tests/misc/projects/Issue8551/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8551/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8565/Main.hx create mode 100644 tests/misc/projects/Issue8565/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8565/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8567/compile.hxml create mode 100644 tests/misc/projects/Issue8567/src/Main.hx create mode 100644 tests/misc/projects/Issue8567/src/test.txt create mode 100644 tests/misc/projects/Issue8579/Main.hx create mode 100644 tests/misc/projects/Issue8579/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8579/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8608/Main.hx create mode 100644 tests/misc/projects/Issue8608/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8608/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8618/Main.hx create mode 100644 tests/misc/projects/Issue8618/Main2.hx create mode 100644 tests/misc/projects/Issue8618/Main3.hx create mode 100644 tests/misc/projects/Issue8618/Main4.hx create mode 100644 tests/misc/projects/Issue8618/NoClosureClass.hx create mode 100644 tests/misc/projects/Issue8618/NormalClass.hx create mode 100644 tests/misc/projects/Issue8618/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8618/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8618/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue8618/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8618/compile3-fail.hxml create mode 100644 tests/misc/projects/Issue8618/compile3-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8618/compile4-fail.hxml create mode 100644 tests/misc/projects/Issue8618/compile4-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue8650/Main.hx create mode 100644 tests/misc/projects/Issue8650/compile-fail.hxml create mode 100644 tests/misc/projects/Issue8650/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/_semver/InvalidVersion.hx create mode 100644 tests/misc/projects/_semver/Main.hx create mode 100644 tests/misc/projects/_semver/compile-fail.hxml create mode 100644 tests/misc/projects/_semver/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/_semver/compile.hxml create mode 100644 tests/misc/projects/es6/A.hx create mode 100644 tests/misc/projects/es6/B.hx create mode 100644 tests/misc/projects/es6/C.hx create mode 100644 tests/misc/projects/es6/D.hx create mode 100644 tests/misc/projects/es6/compile-a-fail.hxml create mode 100644 tests/misc/projects/es6/compile-a-fail.hxml.stderr create mode 100644 tests/misc/projects/es6/compile-b-fail.hxml create mode 100644 tests/misc/projects/es6/compile-b-fail.hxml.stderr create mode 100644 tests/misc/projects/es6/compile-c-fail.hxml create mode 100644 tests/misc/projects/es6/compile-c-fail.hxml.stderr create mode 100644 tests/misc/projects/es6/compile-d-fail.hxml create mode 100644 tests/misc/projects/es6/compile-d-fail.hxml.stderr rename tests/misc/{ => python}/projects/Issue4218/.gitignore (100%) rename tests/misc/{ => python}/projects/Issue4218/Main.hx (100%) rename tests/misc/{ => python}/projects/Issue4218/build.hxml (75%) create mode 100644 tests/misc/python/projects/Issue8542/Main.hx create mode 100644 tests/misc/python/projects/Issue8542/build.hxml create mode 100644 tests/misc/python/pythonImport/.gitignore rename tests/misc/{ => python}/pythonImport/Main.hx (96%) rename tests/misc/{ => python}/pythonImport/compile.hxml (68%) create mode 100644 tests/misc/python/pythonImport/native_python/__init__.py rename tests/misc/{ => python}/pythonImport/native_python/sample.py (100%) create mode 100644 tests/misc/python/run.hxml delete mode 100644 tests/misc/pythonImport/.gitignore create mode 100644 tests/nullsafety/src/Validator.hx create mode 100644 tests/nullsafety/src/cases/TestAbstract.hx create mode 100644 tests/nullsafety/src/cases/TestLoose.hx create mode 100644 tests/nullsafety/src/cases/TestSafeFieldInUnsafeClass.hx create mode 100644 tests/nullsafety/src/cases/TestStrict.hx create mode 100644 tests/nullsafety/test-js-es6.hxml create mode 100644 tests/nullsafety/test.hxml create mode 100644 tests/optimization/src/issues/Issue3524.hx create mode 100644 tests/optimization/src/issues/Issue3881.hx create mode 100644 tests/optimization/src/issues/Issue5436.hx create mode 100644 tests/optimization/src/issues/Issue5582.hx create mode 100644 tests/optimization/src/issues/Issue6047.hx create mode 100644 tests/optimization/src/issues/Issue6225.hx create mode 100644 tests/optimization/src/issues/Issue6672.hx create mode 100644 tests/optimization/src/issues/Issue6715.hx create mode 100644 tests/optimization/src/issues/Issue7113.hx create mode 100644 tests/optimization/src/issues/Issue7704.hx create mode 100644 tests/optimization/src/issues/Issue8072.hx create mode 100644 tests/optimization/src/issues/Issue8128.hx create mode 100644 tests/optimization/src/issues/Issue8226.hx create mode 100644 tests/optimization/src/issues/IssueInline.hx create mode 100644 tests/runci/targets/Hl.hx create mode 100644 tests/runci/targets/Jvm.hx create mode 100644 tests/server/.gitignore create mode 100644 tests/server/src/DisplayTests.hx delete mode 100644 tests/server/src/HaxeServer.hx create mode 100644 tests/server/test/templates/BrokenSyntax.hx create mode 100644 tests/server/test/templates/BuildMacro.hx create mode 100644 tests/server/test/templates/BuiltClass.hx create mode 100644 tests/server/test/templates/Empty.hx create mode 100644 tests/server/test/templates/GlobalBuildMacro.hx create mode 100644 tests/server/test/templates/HelloJvm.hx create mode 100644 tests/server/test/templates/Macro.hx create mode 100644 tests/server/test/templates/MacroMain.hx create mode 100644 tests/server/test/templates/MutuallyDependent1.hx create mode 100644 tests/server/test/templates/MutuallyDependent2.hx create mode 100644 tests/server/test/templates/Vector.hx create mode 100644 tests/server/test/templates/VectorInliner.hx create mode 100644 tests/sourcemaps/run.hxml create mode 100644 tests/sourcemaps/src/Test.hx create mode 100644 tests/sourcemaps/src/Validator.hx create mode 100644 tests/sourcemaps/src/cases/Trace.hx create mode 100644 tests/sourcemaps/src/cases/import.hx create mode 100644 tests/sourcemaps/src/validation/Exception.hx create mode 100644 tests/sourcemaps/src/validation/Lines.hx create mode 100644 tests/sourcemaps/src/validation/Target.hx create mode 100644 tests/sourcemaps/src/validation/ValidationError.hx create mode 100644 tests/sourcemaps/src/validation/ValidationReport.hx create mode 100644 tests/sys/compile-jvm.hxml delete mode 100644 tests/sys/compile-php7.hxml create mode 100755 tests/sys/genTestRes.py delete mode 100644 tests/sys/lua create mode 100644 tests/sys/src/TestUnicode.hx create mode 100644 tests/sys/src/UnicodeSequences.hx create mode 100644 tests/sys/src/UtilityProcess.hx create mode 100644 tests/sys/src/net/TestSocket.hx create mode 100644 tests/threads/build.hxml create mode 100644 tests/threads/res/tree1.txt create mode 100644 tests/threads/src/Main.hx create mode 100644 tests/threads/src/cases/DequeBrackets.hx create mode 100644 tests/threads/src/cases/Issue3767.hx create mode 100644 tests/threads/src/cases/Issue4878.hx create mode 100644 tests/threads/src/cases/Issue8063.hx rename tests/{unit/src/unit => threads/src/cases}/TestThreads.hx (89%) create mode 100644 tests/threads/src/cases/WeirdTreeSum.hx create mode 100644 tests/threads/src/import.hx create mode 100644 tests/unit/.gitignore create mode 100644 tests/unit/compile-jvm.hxml delete mode 100644 tests/unit/compiler_loops/All.hx delete mode 100644 tests/unit/compiler_loops/Issue5345.hx delete mode 100644 tests/unit/compiler_loops/Issue5345b.hx delete mode 100644 tests/unit/compiler_loops/Issue5345c.hx delete mode 100644 tests/unit/compiler_loops/Issue5785.hx delete mode 100644 tests/unit/compiler_loops/Issue6038.hx create mode 100644 tests/unit/native_swf/.gitignore create mode 100644 tests/unit/native_swf/Lib.as create mode 100644 tests/unit/native_swf/Lib2.as create mode 100644 tests/unit/native_swf/NsCls.as create mode 100644 tests/unit/native_swf/PropClass.as create mode 100644 tests/unit/native_swf/PropIface.as create mode 100644 tests/unit/native_swf/ns1.as create mode 100644 tests/unit/native_swf/ns2.as create mode 100644 tests/unit/serializedValues.txt create mode 100644 tests/unit/src/Macro.hx create mode 100644 tests/unit/src/RootEnum.hx create mode 100644 tests/unit/src/RunSerializerOutput.hx create mode 100644 tests/unit/src/scripthost/Issue8502.hx create mode 100644 tests/unit/src/unit/TestCasts.hx create mode 100644 tests/unit/src/unit/TestFieldVariance.hx create mode 100644 tests/unit/src/unit/TestHttp.hx delete mode 100644 tests/unit/src/unit/TestJQuery.hx create mode 100644 tests/unit/src/unit/TestKeyValueIterator.hx create mode 100644 tests/unit/src/unit/TestNull.hx create mode 100644 tests/unit/src/unit/TestSerializerCrossTarget.hx create mode 100644 tests/unit/src/unit/TestSyntaxModule.hx delete mode 100644 tests/unit/src/unit/issues/Issue2152.hx create mode 100644 tests/unit/src/unit/issues/Issue3539.hx delete mode 100644 tests/unit/src/unit/issues/Issue3767.hx create mode 100644 tests/unit/src/unit/issues/Issue3792.hx create mode 100644 tests/unit/src/unit/issues/Issue3826.hx delete mode 100644 tests/unit/src/unit/issues/Issue4138.hx create mode 100644 tests/unit/src/unit/issues/Issue4287.hx rename tests/unit/src/unit/issues/{Issue4327.hx.disabled.because.hl => Issue4327.hx} (100%) create mode 100644 tests/unit/src/unit/issues/Issue4481.hx rename tests/unit/src/unit/issues/{Issue4581.hx => Issue4581.hx.wtf} (100%) create mode 100644 tests/unit/src/unit/issues/Issue4639.hx create mode 100644 tests/unit/src/unit/issues/Issue4649.hx create mode 100644 tests/unit/src/unit/issues/Issue4705.hx create mode 100644 tests/unit/src/unit/issues/Issue4799.hx delete mode 100644 tests/unit/src/unit/issues/Issue4878.hx create mode 100644 tests/unit/src/unit/issues/Issue5009.hx create mode 100644 tests/unit/src/unit/issues/Issue5039.hx create mode 100644 tests/unit/src/unit/issues/Issue5168.hx create mode 100644 tests/unit/src/unit/issues/Issue5255.hx create mode 100644 tests/unit/src/unit/issues/Issue5384.hx create mode 100644 tests/unit/src/unit/issues/Issue5449.hx create mode 100644 tests/unit/src/unit/issues/Issue5486.hx create mode 100644 tests/unit/src/unit/issues/Issue5599.hx create mode 100644 tests/unit/src/unit/issues/Issue5691.hx create mode 100644 tests/unit/src/unit/issues/Issue5816.hx create mode 100644 tests/unit/src/unit/issues/Issue5859.hx create mode 100644 tests/unit/src/unit/issues/Issue6016.hx create mode 100644 tests/unit/src/unit/issues/Issue6036.hx create mode 100644 tests/unit/src/unit/issues/Issue6039.hx create mode 100644 tests/unit/src/unit/issues/Issue6059.hx create mode 100644 tests/unit/src/unit/issues/Issue6062.hx create mode 100644 tests/unit/src/unit/issues/Issue6106.hx create mode 100644 tests/unit/src/unit/issues/Issue6291.hx create mode 100644 tests/unit/src/unit/issues/Issue6376.hx create mode 100644 tests/unit/src/unit/issues/Issue6379.hx create mode 100644 tests/unit/src/unit/issues/Issue6430.hx create mode 100644 tests/unit/src/unit/issues/Issue6486.hx create mode 100644 tests/unit/src/unit/issues/Issue6499.hx create mode 100644 tests/unit/src/unit/issues/Issue6503.hx create mode 100644 tests/unit/src/unit/issues/Issue6520.hx create mode 100644 tests/unit/src/unit/issues/Issue6533.hx create mode 100644 tests/unit/src/unit/issues/Issue6549.hx create mode 100644 tests/unit/src/unit/issues/Issue6551.hx create mode 100644 tests/unit/src/unit/issues/Issue6560.hx create mode 100644 tests/unit/src/unit/issues/Issue6587.hx create mode 100644 tests/unit/src/unit/issues/Issue6635.hx create mode 100644 tests/unit/src/unit/issues/Issue6656.hx create mode 100644 tests/unit/src/unit/issues/Issue6674.hx create mode 100644 tests/unit/src/unit/issues/Issue6675.hx create mode 100644 tests/unit/src/unit/issues/Issue6703.hx create mode 100644 tests/unit/src/unit/issues/Issue6706.hx create mode 100644 tests/unit/src/unit/issues/Issue6707.hx create mode 100644 tests/unit/src/unit/issues/Issue6710.hx create mode 100644 tests/unit/src/unit/issues/Issue6711.hx create mode 100644 tests/unit/src/unit/issues/Issue6717.hx create mode 100644 tests/unit/src/unit/issues/Issue6720.hx create mode 100644 tests/unit/src/unit/issues/Issue6722.hx create mode 100644 tests/unit/src/unit/issues/Issue6724.hx create mode 100644 tests/unit/src/unit/issues/Issue6751.hx create mode 100644 tests/unit/src/unit/issues/Issue6752.hx create mode 100644 tests/unit/src/unit/issues/Issue6754.hx create mode 100644 tests/unit/src/unit/issues/Issue6772.hx create mode 100644 tests/unit/src/unit/issues/Issue6776.hx create mode 100644 tests/unit/src/unit/issues/Issue6784.hx create mode 100644 tests/unit/src/unit/issues/Issue6801.hx create mode 100644 tests/unit/src/unit/issues/Issue6807.hx create mode 100644 tests/unit/src/unit/issues/Issue6822.hx create mode 100644 tests/unit/src/unit/issues/Issue6830.hx create mode 100644 tests/unit/src/unit/issues/Issue6833.hx create mode 100644 tests/unit/src/unit/issues/Issue6836.hx create mode 100644 tests/unit/src/unit/issues/Issue6838.hx create mode 100644 tests/unit/src/unit/issues/Issue6845.hx create mode 100644 tests/unit/src/unit/issues/Issue6848.hx create mode 100644 tests/unit/src/unit/issues/Issue6871.hx create mode 100644 tests/unit/src/unit/issues/Issue6873.hx create mode 100644 tests/unit/src/unit/issues/Issue6896.hx create mode 100644 tests/unit/src/unit/issues/Issue6942.hx create mode 100644 tests/unit/src/unit/issues/Issue6948.hx create mode 100644 tests/unit/src/unit/issues/Issue6952.hx create mode 100644 tests/unit/src/unit/issues/Issue6972.hx create mode 100644 tests/unit/src/unit/issues/Issue6979.hx create mode 100644 tests/unit/src/unit/issues/Issue7007.hx create mode 100644 tests/unit/src/unit/issues/Issue7032.hx create mode 100644 tests/unit/src/unit/issues/Issue7106.hx create mode 100644 tests/unit/src/unit/issues/Issue7115.hx create mode 100644 tests/unit/src/unit/issues/Issue7120.hx create mode 100644 tests/unit/src/unit/issues/Issue7132.hx create mode 100644 tests/unit/src/unit/issues/Issue7139.hx create mode 100644 tests/unit/src/unit/issues/Issue7142.hx create mode 100644 tests/unit/src/unit/issues/Issue7179.hx create mode 100644 tests/unit/src/unit/issues/Issue7182.hx create mode 100644 tests/unit/src/unit/issues/Issue7187.hx create mode 100644 tests/unit/src/unit/issues/Issue7207.hx create mode 100644 tests/unit/src/unit/issues/Issue7209.hx create mode 100644 tests/unit/src/unit/issues/Issue7220.hx create mode 100644 tests/unit/src/unit/issues/Issue7230.hx create mode 100644 tests/unit/src/unit/issues/Issue7233.hx create mode 100644 tests/unit/src/unit/issues/Issue7247.hx create mode 100644 tests/unit/src/unit/issues/Issue7286.hx create mode 100644 tests/unit/src/unit/issues/Issue7298.hx create mode 100644 tests/unit/src/unit/issues/Issue7332.hx create mode 100644 tests/unit/src/unit/issues/Issue7334.hx create mode 100644 tests/unit/src/unit/issues/Issue7335.hx create mode 100644 tests/unit/src/unit/issues/Issue7359.hx create mode 100644 tests/unit/src/unit/issues/Issue7367.hx create mode 100644 tests/unit/src/unit/issues/Issue7376.hx create mode 100644 tests/unit/src/unit/issues/Issue7388.hx create mode 100644 tests/unit/src/unit/issues/Issue7389.hx create mode 100644 tests/unit/src/unit/issues/Issue7391.hx create mode 100644 tests/unit/src/unit/issues/Issue7394.hx create mode 100644 tests/unit/src/unit/issues/Issue7443.hx create mode 100644 tests/unit/src/unit/issues/Issue7449.hx create mode 100644 tests/unit/src/unit/issues/Issue7466.hx create mode 100644 tests/unit/src/unit/issues/Issue7476.hx create mode 100644 tests/unit/src/unit/issues/Issue7492.hx create mode 100644 tests/unit/src/unit/issues/Issue7499.hx create mode 100644 tests/unit/src/unit/issues/Issue7531.hx create mode 100644 tests/unit/src/unit/issues/Issue7533.hx create mode 100644 tests/unit/src/unit/issues/Issue7536.hx create mode 100644 tests/unit/src/unit/issues/Issue7540.hx create mode 100644 tests/unit/src/unit/issues/Issue7546.hx create mode 100644 tests/unit/src/unit/issues/Issue7579.hx create mode 100644 tests/unit/src/unit/issues/Issue7590.hx create mode 100644 tests/unit/src/unit/issues/Issue7600.hx create mode 100644 tests/unit/src/unit/issues/Issue7603.hx create mode 100644 tests/unit/src/unit/issues/Issue7630.hx create mode 100644 tests/unit/src/unit/issues/Issue7642.hx create mode 100644 tests/unit/src/unit/issues/Issue7653.hx create mode 100644 tests/unit/src/unit/issues/Issue7659.hx create mode 100644 tests/unit/src/unit/issues/Issue7661.hx create mode 100644 tests/unit/src/unit/issues/Issue7671.hx create mode 100644 tests/unit/src/unit/issues/Issue7674.hx create mode 100644 tests/unit/src/unit/issues/Issue7688.hx create mode 100644 tests/unit/src/unit/issues/Issue7716.hx create mode 100644 tests/unit/src/unit/issues/Issue7727.hx create mode 100644 tests/unit/src/unit/issues/Issue7728.hx create mode 100644 tests/unit/src/unit/issues/Issue7743.hx create mode 100644 tests/unit/src/unit/issues/Issue7827.hx create mode 100644 tests/unit/src/unit/issues/Issue7844.hx create mode 100644 tests/unit/src/unit/issues/Issue7867.hx create mode 100644 tests/unit/src/unit/issues/Issue7869.hx create mode 100644 tests/unit/src/unit/issues/Issue7883.hx create mode 100644 tests/unit/src/unit/issues/Issue7890.hx create mode 100644 tests/unit/src/unit/issues/Issue7903.hx create mode 100644 tests/unit/src/unit/issues/Issue7922.hx create mode 100644 tests/unit/src/unit/issues/Issue7981.hx create mode 100644 tests/unit/src/unit/issues/Issue8032.hx create mode 100644 tests/unit/src/unit/issues/Issue8050.hx create mode 100644 tests/unit/src/unit/issues/Issue8053.hx create mode 100644 tests/unit/src/unit/issues/Issue8075.hx create mode 100644 tests/unit/src/unit/issues/Issue8079.hx create mode 100644 tests/unit/src/unit/issues/Issue8101.hx create mode 100644 tests/unit/src/unit/issues/Issue8118.hx create mode 100644 tests/unit/src/unit/issues/Issue8185.hx create mode 100644 tests/unit/src/unit/issues/Issue8187.hx create mode 100644 tests/unit/src/unit/issues/Issue8188.hx create mode 100644 tests/unit/src/unit/issues/Issue8200.hx create mode 100644 tests/unit/src/unit/issues/Issue8203.hx create mode 100644 tests/unit/src/unit/issues/Issue8211.hx create mode 100644 tests/unit/src/unit/issues/Issue8212.hx create mode 100644 tests/unit/src/unit/issues/Issue8213.hx create mode 100644 tests/unit/src/unit/issues/Issue8218.hx create mode 100644 tests/unit/src/unit/issues/Issue8220.hx create mode 100644 tests/unit/src/unit/issues/Issue8221.hx create mode 100644 tests/unit/src/unit/issues/Issue8227.hx create mode 100644 tests/unit/src/unit/issues/Issue8240.hx create mode 100644 tests/unit/src/unit/issues/Issue8241.hx create mode 100644 tests/unit/src/unit/issues/Issue8243.hx create mode 100644 tests/unit/src/unit/issues/Issue8248.hx create mode 100644 tests/unit/src/unit/issues/Issue8257.hx create mode 100644 tests/unit/src/unit/issues/Issue8261.hx create mode 100644 tests/unit/src/unit/issues/Issue8286.hx create mode 100644 tests/unit/src/unit/issues/Issue8296.hx create mode 100644 tests/unit/src/unit/issues/Issue8299.hx create mode 100644 tests/unit/src/unit/issues/Issue8337.hx create mode 100644 tests/unit/src/unit/issues/Issue8341.hx create mode 100644 tests/unit/src/unit/issues/Issue8343.hx create mode 100644 tests/unit/src/unit/issues/Issue8376.hx create mode 100644 tests/unit/src/unit/issues/Issue8425.hx create mode 100644 tests/unit/src/unit/issues/Issue8435.hx create mode 100644 tests/unit/src/unit/issues/Issue8489.hx create mode 100644 tests/unit/src/unit/issues/Issue8493.hx create mode 100644 tests/unit/src/unit/issues/Issue8502.hx create mode 100644 tests/unit/src/unit/issues/Issue8506.hx create mode 100644 tests/unit/src/unit/issues/Issue8513.hx create mode 100644 tests/unit/src/unit/issues/Issue8528.hx create mode 100644 tests/unit/src/unit/issues/Issue8537.hx create mode 100644 tests/unit/src/unit/issues/Issue8538.hx create mode 100644 tests/unit/src/unit/issues/Issue8549.hx create mode 100644 tests/unit/src/unit/issues/Issue8560.hx create mode 100644 tests/unit/src/unit/issues/misc/ISSUE7716.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue5009Assert.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue5255Class.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue6873Macro.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue7466Macro.hx rename tests/unit/src/unit/{ => spec}/TestSpecification.hx (76%) create mode 100644 tests/unit/src/unit/spec/import.hx rename tests/unit/src/unitstd/{Https.unit.hx => Https.unit.hx.no} (75%) create mode 100644 tests/unit/src/unitstd/InlineXml.unit.hx delete mode 100644 tests/unit/src/unitstd/Sys.unit.hx create mode 100644 tests/unit/src/unitstd/Unicode.unit.hx create mode 100644 tests/unit/src/unitstd/UnicodeString.unit.hx delete mode 100644 tests/unit/src/unitstd/haxe/crypto/Crc32.hx create mode 100644 tests/unit/src/unitstd/haxe/crypto/Crc32.unit.hx create mode 100644 tests/unit/src/unitstd/haxe/ds/IntMap.unit.hx create mode 100644 tests/unit/src/unitstd/haxe/ds/StringMap.unit.hx create mode 100644 tests/unit/src/unitstd/haxe/iterators/StringIteratorUnicode.unit.hx create mode 100644 tests/unit/src/unitstd/haxe/iterators/StringKeyValueIteratorUnicode.unit.hx create mode 100644 tests/unit/src/unitstd/haxe/zip/Uncompress.unit.hx create mode 100644 tests/unit/src/unitstd/sys/io/File.unit.hx create mode 100644 tests/unit/src/unitstd/sys/net/Socket.unit.hx diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000000..2481fa5c2f5 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +open_collective: haxe +custom: ['https://haxe.org/foundation/support-plans.html', 'https://haxe.org/foundation/donate.html'] diff --git a/.gitignore b/.gitignore index 7da676cce52..9d8e461a5bc 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.a *.exe .*.swp +.haxelib /out /installer @@ -19,12 +20,14 @@ /extra/deploy_key /extra/*_sec.gpg /extra/*_ssh +/extra/doc/ /src/version.ml /haxe /haxelib* /haxedoc* /lib +/prebuild /src/syntax/lexer.ml /libs/xml-light/xml_lexer.ml @@ -63,6 +66,9 @@ /tests/unit/unit.n /tests/unit/node_modules/ +/tests/nullsafety/bin +/tests/nullsafety/dump + /haxe.sublime* .idea build.bat @@ -77,6 +83,7 @@ tests/unit/unit.py.res1.txt tests/unit/unit.py.res2.bin tests/sys/bin/ /tests/sys/dump/ +/tests/sys/test-res/ tests/optimization/dump/ tests/misc/projects/*/*.n tests/misc/*/*/*.lua @@ -96,6 +103,7 @@ tests/misc/projects/Issue4070/cpp/ *.vscode/ /tests/sys/temp +/tests/sys/temp-unicode *.dll _build/ Makefile.dependencies @@ -105,10 +113,18 @@ Makefile.modules /tests/unit/compiler_loops/log.txt tests/benchs/mandelbrot/bin/ -tests/server/test/cases/ -tests/server/test.js tests/unit/pypy3-* tmp.tmp -dev-display.hxml \ No newline at end of file +dev-display.hxml + +.DS_Store +tests/sourcemaps/bin +/*_plugin.ml +tests/benchs/export/ +tests/benchs/dump/ +tests/display/.unittest/ +tests/unit/.unittest/ +tests/threads/export/ +tests/server/test.js.map diff --git a/.gitmodules b/.gitmodules index f5cee92fec7..6ce20925469 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "libs"] - path = libs - url = https://github.com/HaxeFoundation/ocamllibs.git [submodule "extra/haxelib_src"] path = extra/haxelib_src url = https://github.com/HaxeFoundation/haxelib.git diff --git a/.merlin b/.merlin index 6efccf7e736..7c9eaf64b74 100644 --- a/.merlin +++ b/.merlin @@ -3,10 +3,12 @@ B _build/src/** S libs/** B libs/** B +threads -PKG rope PKG ptmap PKG sedlex PKG extlib PKG camlzip PKG xml-light -FLG -safe-string \ No newline at end of file +PKG sha +FLG -safe-string +FLG -w -3 +FLG -w -40 \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index aef1648f4a1..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,259 +0,0 @@ -cache: - timeout: 1000 - directories: - - $HOME/.opam - - $HOME/neko - - $HOME/apt-cache - - $HOME/hxcache - - $HOME/lua_env - - $HOME/.luarocks - -before_cache: - - if [ $TRAVIS_OS_NAME = 'linux' ]; then - sudo apt-get autoclean; - sudo rm -f $HOME/apt-cache/lock || true; - fi - # somehow these files are recreated everytime - - rm -f $HOME/lua_env/lib/liblua51.a - - rm -f $HOME/lua_env/lib/liblua52.a - - rm -f $HOME/lua_env/lib/liblua53.a - - rm -f $HOME/lua_env/lib/libluajit-5.1.a - #- if [ $TRAVIS_OS_NAME = 'osx' ]; then brew cleanup; fi - -env: - global: - # make variables - - ADD_REVISION=1 - # nightly builds submit - - secure: "UoGjYvQqt66GWmeLC4Pih1iue5AufVgW8XQOd2Bx839NN/2mQQ9bD1HuONJe+taWBJ+PHInkAjYROYYaiCQUA7B1SXs3oQD7Og6arVcR7kY7XOdAQ2t8ZkxJHTnuYGWW/2gNFBESv+3H17bkXG4rzaSn2LV5PJLOxSjw0ziBUMY=" - - secure: "ugpxt+zeYiAiMYKLK96f5TLSxbQAtmDWiumdwaLHl88fIUeefxJJPIF1Xm0AHeYEJE7sD8dLE1dMbRSzOpXFfTmJoQZv19Wjv+2N5B+DaabKjGj1nZG7q3blGa3nUYzWVfFNFiIpM9c5fvW8yiUFzacZE5itEY8+lZQeGsNh+WQ=" - # SauceLabs - # - secure: SjyKefmjUEXi0IKHGGpcbLAajU0mLHONg8aA8LoY7Q9nAkSN6Aql+fzS38Boq7w1jWn+2FOpr+4jy0l6wVd/bftsF+huFfYpFJmdh8BlKmE0K71zZAral0H1c7YxkuQpPiJCIFGXqtkvev7SWTy0z31u7kuuQeEyW27boXe5cDA= - # - secure: sUvWUjCyPuWht4seNa4f2VG9DkvXkhZyLZfjJO9TUAHB2JndS16E2j/qrvKEjycyH6w8tU/B9vnjDRvvGrYXxEXcBEwsJVfkorFnRl9uwGCGIYrzjMhssEl3fMYZK7P304f+gAp5ULrDBX2gIaKeSa8lUNRtz2PsZOieE4kMdhk= - # Bintray - # - secure: "ETbwZaeRq8wIVZVyUk1IsNctYVuQa/U2biRkF9pQkz3MEXpaneynclVzNjm8rnm8JqfKcjUDUvQJBP1KYrJYq3tAJFhl31YUnS0FsF3sgLIcnHkhbRA24xJdIlCwHP6QUPoiyPbkec43NRwrF0071KOMD51vgUToXRtAe3o/15g=" - # - secure: "Fcrrge2f4jFYDOopig2rwkQvgJw6Ra8UK6OwTVk08wecytzVaOJK1TcB22PSvZ+h0ZLJs34T+pXHFjlNuSWm4+CwGSvnltRD1/svjS8zOqK7RzuUdzHz87yruz9PFqV63HTas6qtmgLqp8n/Q6AhtDLF39BTZPyDzEbi9qkwRuI=" - # - secure: "VBJDQNJ9uvdt0aszo7oU3txuRvjkuLmuHZGOkrd4wE/5B4sX5jzx/+dnrKcNTXJCmQ/rVLuMu9GyxqVjNHlzce678voxdQNOtNkNgpkr1qN9/A9rRnCp77hH27ErdthpWxbmcnE62hAJ83TIKSvn//5lAkx4sMCKS1NXEWQ5qec=" - # PPA configs - - PPA="ppa:haxe/snapshots" - - DEBFULLNAME="Haxe CI Bot" - - DEBEMAIL="haxe-ci@onthewings.net" - -sudo: required -dist: trusty -addons: &addons - ssh_known_hosts: - - haxe.org - - api.haxe.org - -install_linux: &install_linux - - if [ ! -d "$HOME/neko" ]; then - export CACHE_AVAILABLE=0; - elif [ ! -d "$HOME/neko/.git" ]; then - export CACHE_AVAILABLE=0; - else - export CACHE_AVAILABLE=1; - fi - # Install dependencies - - export APT_CACHE_DIR=~/apt-cache && mkdir -pv $APT_CACHE_DIR - - sudo apt-get install --reinstall ca-certificates # workaround for "Cannot add PPA: 'ppa:haxe/ocaml'. Please check that the PPA name or format is correct." - - sudo add-apt-repository ppa:haxe/ocaml -y - - sudo apt-get update -y - - sudo apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y - ocaml - ocaml-native-compilers - ocaml-findlib - camlp4 - libpcre3-dev - zlib1g-dev - libgtk2.0-dev - ninja-build - awscli - $JOB_DEPENDENCIES - - wget https://raw.github.com/ocaml/opam/master/shell/opam_installer.sh -O - | sh -s /usr/local/bin system - - export OPAMYES=1 - - opam install sedlex xml-light extlib rope ptmap - # check if we need to install neko - - export REF_CHANGED=1; - - if [ ! -d "$HOME/neko" ]; then - mkdir $HOME/neko; - pushd $HOME/neko; - git clone https://github.com/HaxeFoundation/neko.git .; - git submodule update --init --recursive; - else - pushd $HOME/neko; - if [ ! -d "$HOME/neko/.git" ]; then - git clone https://github.com/HaxeFoundation/neko.git .; - git submodule update --init --recursive; - else - git fetch --all; - export REF_CUR=`git rev-list master | head -n 1`; - export REF_REMOTE=`git rev-list origin/master | head -n 1`; - export REF_CHANGED=`(test $REF_CUR != $REF_REMOTE && echo 1) || echo 0`; - if [ $REF_CHANGED = 1 ]; then - git reset --hard origin/master; - git submodule update --init --recursive; - fi; - fi; - fi; - - env - - test $REF_CHANGED = 0 || cmake . -DSTATIC_DEPS=all -G Ninja || (git clean -dfx && export CACHE_AVAILABLE=0 && cmake . -DSTATIC_DEPS=all -G Ninja) - # download static dependencies before actual build, with 3 chances to deal with network issues - - test $REF_CHANGED = 0 || ninja download_static_deps || ninja download_static_deps || ninja download_static_deps - - test $REF_CHANGED = 0 || (ninja -j 4) - - sudo cmake -P cmake_install.cmake - - popd - # Setup JDK - - jdk_switcher use oraclejdk7 - - java -version - # Build haxe - - make package_src -s - - opam config exec -- make -s STATICLINK=1 libs - - opam config exec -- make -s -j STATICLINK=1 haxe - - opam config exec -- make -s haxelib - - make package_bin -s - - ls -l out - - ldd -v ./haxe - - ldd -v ./haxelib - - export PATH="$PATH:$TRAVIS_BUILD_DIR" - - export HAXE_STD_PATH="$TRAVIS_BUILD_DIR/std" - -install_osx: &install_osx - - if [ ! -d "$HOME/neko" ]; then - export CACHE_AVAILABLE=0; - elif [ ! -d "$HOME/neko/.git" ]; then - export CACHE_AVAILABLE=0; - else - export CACHE_AVAILABLE=1; - fi - # Install dependencies - - travis_retry brew update --merge - - brew uninstall --force brew-cask # https://github.com/caskroom/homebrew-cask/pull/15381 - - travis_retry brew tap Homebrew/bundle - - travis_retry brew bundle --file=tests/Brewfile - - export OPAMYES=1 - - opam init - - eval `opam config env` - - opam install camlp4 sedlex ocamlfind xml-light extlib rope ptmap - # check if we need to install neko - - export REF_CHANGED=1; - - if [ ! -d "$HOME/neko" ]; then - mkdir $HOME/neko; - pushd $HOME/neko; - git clone https://github.com/HaxeFoundation/neko.git .; - git submodule update --init --recursive; - else - pushd $HOME/neko; - if [ ! -d "$HOME/neko/.git" ]; then - git clone https://github.com/HaxeFoundation/neko.git .; - git submodule update --init --recursive; - else - git fetch --all; - export REF_CUR=`git rev-list master | head -n 1`; - export REF_REMOTE=`git rev-list origin/master | head -n 1`; - export REF_CHANGED=`(test $REF_CUR != $REF_REMOTE && echo 1) || echo 0`; - if [ $REF_CHANGED = 1 ]; then - git reset --hard origin/master; - git submodule update --init --recursive; - fi; - fi; - fi - - env - - test $REF_CHANGED = 0 || cmake . -DSTATIC_DEPS=all -G Ninja || (git clean -dfx && export CACHE_AVAILABLE=0 && cmake . -DSTATIC_DEPS=all -G Ninja) - # download static dependencies before actual build, with 3 chances to deal with network issues - - test $REF_CHANGED = 0 || ninja download_static_deps || ninja download_static_deps || ninja download_static_deps - - test $REF_CHANGED = 0 || (ninja -j 4) - - sudo cmake -P cmake_install.cmake - - popd - # Build haxe - - make -s STATICLINK=1 "LIB_PARAMS=/usr/local/opt/zlib/lib/libz.a /usr/local/lib/libpcre.a" libs - - make -s -j STATICLINK=1 "LIB_PARAMS=/usr/local/opt/zlib/lib/libz.a /usr/local/lib/libpcre.a" haxe - - make -s haxelib - - make package_bin -s - - ls -l out - - otool -L ./haxe - - otool -L ./haxelib - - export PATH="$PATH:$TRAVIS_BUILD_DIR" - - export HAXE_STD_PATH="$TRAVIS_BUILD_DIR/std" - -matrix: - include: - ######### - # linux # - ######### - - os: linux - env: - - TEST=macro,neko,js,php,flash9,as3,java,cs,python,hl,lua - - DEPLOY_API_DOCS=1 - - DEPLOY_NIGHTLIES=1 - # - SAUCE=1 - # haxeci_decrypt (Deploy source package to ppa:haxe/snapshots.) - - secure: "Mw3p6bDZuqVQ6u7GrwLQfje5hhIOA4+mdqqLXYHP79UKdhgqb91Dn6IbG9vQ1VXVe64W4YZbQAMBMMRX5kEPDl6JvTVGSBhg00Mi69oO5qrCMcBI6f9FntG72YaVvLf+PA7co+vKrnJzaP2M9pe4SH9Ztbhy0YNxULp7NQ8FLsM=" - # deploy_key_decrypt (Deploy doc to api.haxe.org.) - - secure: "A75uYqU0Xz6plIgSewEs0QQWe472dCMb9kf3j7Hx0DS7dApXgx8++189sw9Sv0wam5KPtbcIM292MucjGCb5zocVj9xCUVgajhEA0QpTuDMBjk/cg3ClWCGjfybaCl2E5LLdUs7Zy4b4oNWtVikOWLWJ4sC1kaarR9p6kv8yYZg=" - # addons: - # <<: *addons - # sauce_connect: true - before_install: - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" - - "export AUDIODEV=null" - install: *install_linux - - os: linux - env: - - TEST=cpp - - HXCPP_COMPILE_THREADS=4 - - HXCPP_COMPILE_CACHE=~/hxcache - before_install: - - export JOB_DEPENDENCIES="gcc-multilib g++-multilib" - install: *install_linux - - ####### - # osx # - ####### - - os: osx - osx_image: xcode7.3 # to compile binaries that support older versions of Mac, and 10.11 is the min version that brew provides bottles - env: - - TEST=macro,neko,js,php,flash9,python - - DEPLOY_NIGHTLIES=1 - install: *install_osx - - - os: osx - osx_image: xcode8.3 # to compile faster - env: - - TEST=java,cs,hl,lua - install: *install_osx - - - os: osx - osx_image: xcode8.3 # to compile faster - env: - - TEST=cpp - - HXCPP_COMPILE_CACHE=~/hxcache - - HXCPP_COMPILE_THREADS=4 - install: *install_osx - -script: - - eval `ssh-agent -s` # for deployment to haxe.org - - export CAN_BUILD=`(test $CACHE_AVAILABLE = 1 || test $TRAVIS_OS_NAME = 'linux') && echo 1` - - if [ ! $CAN_BUILD ]; then - echo "No cache available, but initial cache created, please try restarting this job"; - fi - - test $CAN_BUILD && pushd tests - - test $CAN_BUILD && mkdir ~/haxelib && haxelib setup ~/haxelib - - test $CAN_BUILD && haxe -version - - test $CAN_BUILD && haxe RunCi.hxml - - test $CAN_BUILD && popd - -branches: - except: - # A hack to prevent building for tags, assuming they all start with a number. - # https://github.com/travis-ci/travis-ci/issues/1532 - - /^[0-9]/ - -notifications: - webhooks: - urls: - - https://webhooks.gitter.im/e/95a5fa471c27beee8e7c - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false diff --git a/.vscode/settings.json b/.vscode/settings.json index 1d5dfd26a55..3b6ceacf28b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,8 @@ { "files.associations": { "*.mly": "ocaml", - "*.ml": "ocaml" + "*.ml": "ocaml", + "Makefile.*": "makefile" }, "[ocaml]": { "editor.tabSize": 4 @@ -9,5 +10,23 @@ "files.exclude": { "**/_build": true }, - "reason.server.languages": ["ocaml"] + "reason.server.languages": [ + "ocaml" + ], + "haxe.diagnosticsPathFilter": "${workspaceRoot}/std", + "npm.autoDetect": "off", + "json.schemas": [ + { + "fileMatch": [ + "src-json/define.json" + ], + "url": "./.vscode/schemas/define.schema.json" + }, + { + "fileMatch": [ + "src-json/meta.json" + ], + "url": "./.vscode/schemas/meta.schema.json" + } + ] } \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea1b2fc1941..48183c80866 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,9 +12,59 @@ This repository is about the Haxe compiler itself and the Haxe standard library. * The haxelib command line tool or lib.haxe.org: * Something on try.haxe.org: * Something under haxe.org/manual: -* Something on api.haxe.org: For content this is probably the right repository. If it's about the representation, try instead. +* Something on api.haxe.org: For content this is probably the right repository. If it's about the representation, try instead. * Something else on haxe.org: +## Submitting a Pull-Request + +Thank you for your interest in contributing to Haxe! Haxe is a +community-driven project and your help is vital and appreciated! + +When preparing to submit a pull-request, please make your PR as easy +as possible for core devs to evaluate and merge. To that end: + + * In your PR comments, include: + + * the reason for your proposed changes (What problem are you fixing?) + * some possible solutions, and rationale for the one you chose + * a summary of the code changes in your PR + * any pros and cons to note about the solution you implemented + * links to any relevant GitHub issues, PR's, and/or forum + discussions + + * If you've found and fixed a bug, have you also included a + corresponding test for it? + * Does your code formatting match that of the rest of the project? + * If your changes require updates to the documentation, does your PR + include those as well? + +Please also bear the following in mind: + + * Evaluating PR's takes time and effort. Even taking a look at a PR + in order to request more info or clarification is not zero-cost. + * Most members of the core team are volunteers too, and at any given time + are typically already busy working on other areas of Haxe. + * It's no fun providing negative feedback to a PR. The better you + can craft and champion your PR, the more likely it is to be + speedily evaluated. + + +## Debugging Hints + +### Using a debugger + +To debug the Haxe compiler, you can use either a system debugger (`gdb`/`lldb`), or [ocamldebug](http://caml.inria.fr/pub/docs/manual-ocaml/debugger.html). `ocamldebug` provides a better debugging experience. To use it, compile with `make BYTECODE=1`. + +### Using printf + +To print information about a type, you can add the following before most lines: + +```ocaml +Printf.printf "%s\n" (s_type_kind t); +``` + +There are lots of other stringifying functions, search for "Printing" in `src/core/type.ml` and scroll down to find them. + ## Other remarks: - Sometimes people try to be particularly helpful by not only including broken parts in their code, but also "similar" code which is working. More often than not this is more distracting than helpful. If you want to highlight something like this, consider adding the working code commented out. diff --git a/Makefile b/Makefile index ddd386f7fe1..45039960111 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ # .SUFFIXES : .ml .mli .cmo .cmi .cmx .mly -INSTALL_DIR=$(DESTDIR)/usr/local +INSTALL_DIR=/usr/local INSTALL_BIN_DIR=$(INSTALL_DIR)/bin INSTALL_LIB_DIR=$(INSTALL_DIR)/lib/haxe INSTALL_STD_DIR=$(INSTALL_DIR)/share/haxe/std @@ -21,17 +21,20 @@ PACKAGE_SRC_EXTENSION=.tar.gz MAKEFILENAME?=Makefile PLATFORM?=unix -OUTPUT=haxe +HAXE_OUTPUT=haxe +HAXELIB_OUTPUT=haxelib +PREBUILD_OUTPUT=prebuild EXTENSION= LFLAGS= STATICLINK?=0 # Configuration -HAXE_DIRECTORIES=core syntax context codegen codegen/gencommon generators optimization filters macro macro/eval typing compiler +# Modules in these directories should only depend on modules that are in directories to the left +HAXE_DIRECTORIES=core core/json core/display syntax context context/display codegen codegen/gencommon generators generators/jvm optimization filters macro macro/eval macro/eval/bytes typing compiler EXTLIB_LIBS=extlib-leftovers extc neko javalib swflib ttflib ilib objsize pcre ziplib OCAML_LIBS=unix str threads dynlink -OPAM_LIBS=sedlex xml-light extlib rope ptmap +OPAM_LIBS=sedlex xml-light extlib ptmap sha FINDLIB_LIBS=$(OCAML_LIBS) FINDLIB_LIBS+=$(OPAM_LIBS) @@ -43,7 +46,7 @@ EXTLIB_INCLUDES=$(EXTLIB_LIBS:%=-I libs/%) ALL_INCLUDES=$(EXTLIB_INCLUDES) $(HAXE_INCLUDES) FINDLIB_PACKAGES=$(FINDLIB_LIBS:%=-package %) CFLAGS= -ALL_CFLAGS=-bin-annot -safe-string -thread -g -w -3 $(CFLAGS) $(ALL_INCLUDES) $(FINDLIB_PACKAGES) +ALL_CFLAGS=-bin-annot -safe-string -thread -g -w -3 -w -40 $(CFLAGS) $(ALL_INCLUDES) $(FINDLIB_PACKAGES) MESSAGE_FILTER=sed -e 's/_build\/src\//src\//' tmp.tmp @@ -81,7 +84,8 @@ COMMIT_DATE=$(shell \ fi \ ) PACKAGE_FILE_NAME=haxe_$(COMMIT_DATE)_$(COMMIT_SHA) -HAXE_VERSION=$(shell $(OUTPUT) -version 2>&1 | awk '{print $$1;}') +HAXE_VERSION=$(shell $(CURDIR)/$(HAXE_OUTPUT) -version 2>&1 | awk '{print $$1;}') +HAXE_VERSION_SHORT=$(shell echo "$(HAXE_VERSION)" | grep -oE "^[0-9]+\.[0-9]+\.[0-9]+") # using $(CURDIR) on Windows will not work since it might be a Cygwin path ifdef SYSTEMROOT @@ -119,7 +123,7 @@ build_dirs: @mkdir -p $(BUILD_DIRECTORIES) _build/src/syntax/grammar.ml:src/syntax/grammar.mly - camlp4o -impl $< -o $@ + camlp5o -impl $< -o $@ _build/src/compiler/version.ml: FORCE ifneq ($(ADD_REVISION),0) @@ -128,7 +132,16 @@ else echo let version_extra = None > _build/src/compiler/version.ml endif -build_src: | $(BUILD_SRC) _build/src/syntax/grammar.ml _build/src/compiler/version.ml +_build/src/core/defineList.ml: src-json/define.json prebuild + ./$(PREBUILD_OUTPUT) define $< > $@ + +_build/src/core/metaList.ml: src-json/meta.json prebuild + ./$(PREBUILD_OUTPUT) meta $< > $@ + +build_src: | $(BUILD_SRC) _build/src/syntax/grammar.ml _build/src/compiler/version.ml _build/src/core/defineList.ml _build/src/core/metaList.ml + +prebuild: _build/src/core/json/json.ml _build/src/prebuild/main.ml + $(COMPILER) -safe-string -linkpkg -g -o $(PREBUILD_OUTPUT) -package sedlex -package extlib -I _build/src/core/json _build/src/core/json/json.ml _build/src/prebuild/main.ml haxe: build_src $(MAKE) -f $(MAKEFILENAME) build_pass_1 @@ -148,7 +161,12 @@ build_pass_3: ocamlfind ocamldep -slash $(OCAMLDEP_FLAGS) $(HAXE_INCLUDES) $(MODULES:%=%.ml) > Makefile.dependencies build_pass_4: $(MODULES:%=%.$(MODULE_EXT)) - $(COMPILER) -safe-string -linkpkg -o $(OUTPUT) $(NATIVE_LIBS) $(NATIVE_LIB_FLAG) $(LFLAGS) $(FINDLIB_PACKAGES) $(EXTLIB_INCLUDES) $(EXTLIB_LIBS:=.$(LIB_EXT)) $(MODULES:%=%.$(MODULE_EXT)) + $(COMPILER) -safe-string -linkpkg -g -o $(HAXE_OUTPUT) $(NATIVE_LIBS) $(NATIVE_LIB_FLAG) $(LFLAGS) $(FINDLIB_PACKAGES) $(EXTLIB_INCLUDES) $(EXTLIB_LIBS:=.$(LIB_EXT)) $(MODULES:%=%.$(MODULE_EXT)) + +kill_exe_win: +ifdef SYSTEMROOT + -@taskkill /F /IM haxe.exe 2>/dev/null +endif plugin: ifeq ($(BYTECODE),1) @@ -171,41 +189,29 @@ copy_haxetoolkit: /cygdrive/c/HaxeToolkit/haxe/haxe.exe endif haxelib: - (cd $(CURDIR)/extra/haxelib_src && $(CURDIR)/$(OUTPUT) client.hxml && nekotools boot run.n) - mv extra/haxelib_src/run$(EXTENSION) haxelib$(EXTENSION) + (cd $(CURDIR)/extra/haxelib_src && $(CURDIR)/$(HAXE_OUTPUT) client.hxml && nekotools boot run.n) + mv extra/haxelib_src/run$(EXTENSION) $(HAXELIB_OUTPUT) tools: haxelib install: uninstall - mkdir -p $(INSTALL_BIN_DIR) - mkdir -p $(INSTALL_LIB_DIR)/lib - mkdir -p $(INSTALL_STD_DIR) - cp -rf std/* $(INSTALL_STD_DIR) - cp -rf extra $(INSTALL_LIB_DIR) - cp haxe $(INSTALL_LIB_DIR) - ln -s $(INSTALL_LIB_DIR)/haxe $(INSTALL_BIN_DIR)/haxe - cp haxelib $(INSTALL_LIB_DIR) - ln -s $(INSTALL_LIB_DIR)/haxelib $(INSTALL_BIN_DIR)/haxelib - chmod -R a+rx $(INSTALL_LIB_DIR) - chmod 777 $(INSTALL_LIB_DIR)/lib - chmod a+rx $(INSTALL_BIN_DIR)/haxe $(INSTALL_BIN_DIR)/haxelib - -# will install native version of the tools instead of script ones -install_tools: tools - cp haxelib ${INSTALL_BIN_DIR}/haxelib - chmod a+rx $(INSTALL_BIN_DIR)/haxelib + mkdir -p "$(DESTDIR)$(INSTALL_BIN_DIR)" + cp $(HAXE_OUTPUT) $(HAXELIB_OUTPUT) "$(DESTDIR)$(INSTALL_BIN_DIR)" + mkdir -p "$(DESTDIR)$(INSTALL_STD_DIR)" + cp -r std/* "$(DESTDIR)$(INSTALL_STD_DIR)" uninstall: - rm -rf $(INSTALL_BIN_DIR)/haxe $(INSTALL_BIN_DIR)/haxelib - if [ -d "$(INSTALL_LIB_DIR)/lib" ] && find "$(INSTALL_LIB_DIR)/lib" -mindepth 1 -print -quit | grep -q .; then \ - echo "The local haxelib repo at $(INSTALL_LIB_DIR)/lib will not be removed. Remove it manually if you want."; \ - find $(INSTALL_LIB_DIR)/ ! -name 'lib' -mindepth 1 -maxdepth 1 -exec rm -rf {} +; \ + rm -rf $(DESTDIR)$(INSTALL_BIN_DIR)/$(HAXE_OUTPUT) $(DESTDIR)$(INSTALL_BIN_DIR)/$(HAXELIB_OUTPUT) + if [ -d "$(DESTDIR)$(INSTALL_LIB_DIR)/lib" ] && find "$(DESTDIR)$(INSTALL_LIB_DIR)/lib" -mindepth 1 -print -quit | grep -q .; then \ + echo "The local haxelib repo at $(DESTDIR)$(INSTALL_LIB_DIR)/lib will not be removed. Remove it manually if you want."; \ + find $(DESTDIR)$(INSTALL_LIB_DIR)/ ! -name 'lib' -mindepth 1 -maxdepth 1 -exec rm -rf {} +; \ else \ - rm -rf $(INSTALL_LIB_DIR); \ + rm -rf $(DESTDIR)$(INSTALL_LIB_DIR); \ fi + rm -rf $(DESTDIR)$(INSTALL_STD_DIR) opam_install: - opam install $(OPAM_LIBS) camlp4 ocamlfind --yes + opam install $(OPAM_LIBS) camlp5 ocamlfind --yes # Dependencies @@ -225,47 +231,33 @@ package_unix: rm -rf $(PACKAGE_FILE_NAME) $(PACKAGE_FILE_NAME).tar.gz # Copy the package contents to $(PACKAGE_FILE_NAME) mkdir -p $(PACKAGE_FILE_NAME) - cp -r $(OUTPUT) haxelib$(EXTENSION) std extra/LICENSE.txt extra/CONTRIB.txt extra/CHANGES.txt $(PACKAGE_FILE_NAME) + cp -r $(HAXE_OUTPUT) $(HAXELIB_OUTPUT) std extra/LICENSE.txt extra/CONTRIB.txt extra/CHANGES.txt $(PACKAGE_FILE_NAME) # archive tar -zcf $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_bin.tar.gz $(PACKAGE_FILE_NAME) rm -r $(PACKAGE_FILE_NAME) package_bin: package_$(PLATFORM) -install_dox: - haxelib git hxparse https://github.com/Simn/hxparse master src - haxelib git hxtemplo https://github.com/Simn/hxtemplo - haxelib git hxargs https://github.com/Simn/hxargs - haxelib git markdown https://github.com/dpeek/haxe-markdown master src - haxelib git hxcpp https://github.com/HaxeFoundation/hxcpp - haxelib git hxjava https://github.com/HaxeFoundation/hxjava - haxelib git hxcs https://github.com/HaxeFoundation/hxcs - haxelib git dox https://github.com/HaxeFoundation/dox - -package_doc: - mkdir -p $(PACKAGE_OUT_DIR) - $(eval OUTFILE := $(shell pwd)/$(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_doc.zip) - $(eval VERSION := $(shell haxe -version 2>&1)) - cd $$(haxelib path dox | head -n 1) && \ - haxe run.hxml && \ - haxe gen.hxml && \ - haxe -lib hxtemplo -lib hxparse -lib hxargs -lib markdown \ - -cp src -dce no --run dox.Dox -theme haxe_api -D website "http://haxe.org/" \ - --title "Haxe API" -o $(OUTFILE) \ - -D version "$(VERSION)" -i bin/xml -ex microsoft -ex javax -ex cs.internal \ - -D source-path https://github.com/HaxeFoundation/haxe/blob/$(BRANCH)/std/ - -deploy_doc: - scp $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_doc.zip www-haxe@api.haxe.org:/data/haxeapi/www/v/dev/api-latest.zip - ssh www-haxe@api.haxe.org "cd /data/haxeapi/www/v/dev && find . ! -name 'api-latest.zip' -maxdepth 1 -mindepth 1 -exec rm -rf {} + && unzip -q -o api-latest.zip" +xmldoc: + cd extra && \ + $(CURDIR)/$(HAXELIB_OUTPUT) newrepo && \ + $(CURDIR)/$(HAXELIB_OUTPUT) git hxcpp https://github.com/HaxeFoundation/hxcpp && \ + $(CURDIR)/$(HAXELIB_OUTPUT) git hxjava https://github.com/HaxeFoundation/hxjava && \ + $(CURDIR)/$(HAXELIB_OUTPUT) git hxcs https://github.com/HaxeFoundation/hxcs && \ + PATH="$(CURDIR):$(PATH)" $(CURDIR)/$(HAXE_OUTPUT) doc.hxml + +$(INSTALLER_TMP_DIR): + mkdir -p $(INSTALLER_TMP_DIR) + +$(INSTALLER_TMP_DIR)/neko-osx64.tar.gz: $(INSTALLER_TMP_DIR) + wget -nv http://nekovm.org/media/neko-2.1.0-osx64.tar.gz -O installer/neko-osx64.tar.gz # Installer -package_installer_mac: - $(eval DOCFILE := $(shell pwd)/$(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_doc.zip) +package_installer_mac: $(INSTALLER_TMP_DIR)/neko-osx64.tar.gz package_unix $(eval OUTFILE := $(shell pwd)/$(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_installer.tar.gz) $(eval PACKFILE := $(shell pwd)/$(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_bin.tar.gz) - $(eval VERSION := $(shell haxe -version 2>&1)) + $(eval VERSION := $(shell $(CURDIR)/$(HAXE_OUTPUT) -version 2>&1)) $(eval NEKOVER := $(shell neko -version 2>&1)) bash -c "rm -rf $(INSTALLER_TMP_DIR)/{resources,pkg,tgz,haxe.tar.gz}" mkdir $(INSTALLER_TMP_DIR)/resources @@ -314,10 +306,10 @@ clean_libs: $(foreach lib,$(EXTLIB_LIBS),$(MAKE) -C libs/$(lib) clean &&) true clean_haxe: - rm -f -r _build $(OUTPUT) + rm -f -r _build $(HAXE_OUTPUT) $(PREBUILD_OUTPUT) clean_tools: - rm -f $(OUTPUT) haxelib + rm -f $(HAXE_OUTPUT) $(PREBUILD_OUTPUT) $(HAXELIB_OUTPUT) clean_package: rm -rf $(PACKAGE_OUT_DIR) diff --git a/Makefile.version_extra b/Makefile.version_extra index 991233b6d56..f423bf99751 100644 --- a/Makefile.version_extra +++ b/Makefile.version_extra @@ -5,7 +5,7 @@ all: ; ifneq ($(ADD_REVISION),0) - $(info let version_extra = Some "(git build $(BRANCH) @ $(COMMIT_SHA))") + $(info let version_extra = Some ("git build $(BRANCH)","$(COMMIT_SHA)")) else $(info let version_extra = None) endif \ No newline at end of file diff --git a/Makefile.win b/Makefile.win index 55746bbf2c4..098d6f462f5 100644 --- a/Makefile.win +++ b/Makefile.win @@ -1,9 +1,16 @@ PLATFORM=win MAKEFILENAME=Makefile.win include Makefile -OUTPUT=haxe.exe +HAXE_OUTPUT=haxe.exe +HAXELIB_OUTPUT=haxelib.exe +PREBUILD_OUTPUT=prebuild.exe EXTENSION=.exe PACKAGE_SRC_EXTENSION=.zip +ARCH?=32 + +ifeq ($(ARCH),64) +NEKO_ARCH_STR=64 +endif kill: -@taskkill /F /IM haxe.exe @@ -32,10 +39,12 @@ endif ifdef FILTER CC_CMD=($(COMPILER) $(ALL_CFLAGS) -c $< 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1) -CC_PARSER_CMD=($(COMPILER) -pp camlp4o $(ALL_CFLAGS) -c src/syntax/parser.ml 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1) endif -PACKAGE_FILES=$(OUTPUT) haxelib$(EXTENSION) std "$$(cygpath -w "$$(which zlib1.dll)")" "$$(cygpath -w "$$(which libpcre-1.dll)")" +PACKAGE_FILES=$(HAXE_OUTPUT) $(HAXELIB_OUTPUT) std "$$(cygcheck $(CURDIR)/$(HAXE_OUTPUT) | grep zlib1.dll | sed -e 's/^\s*//')" "$$(cygcheck $(CURDIR)/$(HAXE_OUTPUT) | grep libpcre-1.dll | sed -e 's/^\s*//')" + +echo_package_files: + echo $(PACKAGE_FILES) package_win: mkdir -p out @@ -56,14 +65,16 @@ package_choco: mkdir -p OUTPUT 7z x -y out/$(PACKAGE_FILE_NAME)_bin.zip -oout > log.txt || type log.txt mv out/$(PACKAGE_FILE_NAME) out/choco - sed -e 's/@SNAPSHOT_VERSION@/$(HAXE_VERSION)-SNAP$(COMMIT_DATE)/g' extra/choco/haxe.nuspec > out/choco/haxe.nuspec + sed -e 's/@SNAPSHOT_VERSION@/$(HAXE_VERSION_SHORT)-SNAP$(COMMIT_DATE)/g' extra/choco/haxe.nuspec > out/choco/haxe.nuspec cd out/choco && choco pack mv out/choco/haxe.*.nupkg out rm -rf out/choco -package_installer_win: +$(INSTALLER_TMP_DIR)/neko-win.zip: $(INSTALLER_TMP_DIR) + wget -nv https://nekovm.org/media/neko-2.2.0-win$(NEKO_ARCH_STR).zip -O installer/neko-win.zip + +package_installer_win: $(INSTALLER_TMP_DIR)/neko-win.zip package_win $(eval OUTFILE := $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_installer.zip) - $(eval VERSION := $(shell haxe -version 2>&1 | cut -d ' ' -f1)) rm -rf $(INSTALLER_TMP_DIR)/resources # neko mkdir $(INSTALLER_TMP_DIR)/resources @@ -74,17 +85,19 @@ package_installer_win: 7z x -y $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_bin.zip -o$(INSTALLER_TMP_DIR)/resources mv $(INSTALLER_TMP_DIR)/resources/haxe* $(INSTALLER_TMP_DIR)/resources/haxe # haxesetup.exe - haxelib path hxcpp || haxelib install hxcpp - cd extra; haxelib run hxcpp build-haxesetup.xml + cd extra && \ + $(CURDIR)/$(HAXELIB_OUTPUT) newrepo && \ + $(CURDIR)/$(HAXELIB_OUTPUT) install hxcpp --quiet && \ + $(CURDIR)/$(HAXELIB_OUTPUT) run hxcpp build-haxesetup.xml cp extra/haxesetup.exe $(INSTALLER_TMP_DIR)/resources/haxe # extra cp extra/*.nsi $(INSTALLER_TMP_DIR) cp extra/*.nsh $(INSTALLER_TMP_DIR) cp -rf extra/images $(INSTALLER_TMP_DIR) # nsis - sed -i "s/%%VERSION%%/$(VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi - sed -i "s/%%VERSTRING%%/$(VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi - sed -i "s/%%VERLONG%%/$(VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi + sed -i "s/%%VERSION%%/$(HAXE_VERSION_SHORT)/g" $(INSTALLER_TMP_DIR)/installer.nsi + sed -i "s/%%VERSTRING%%/$(HAXE_VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi + sed -i "s/%%VERLONG%%/$(HAXE_VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi cd $(INSTALLER_TMP_DIR) && makensis installer.nsi 7z a -r -tzip $(OUTFILE) $(INSTALLER_TMP_DIR)/*.exe dir $(PACKAGE_OUT_DIR) diff --git a/README.md b/README.md index 84dba6d8645..21c57647dab 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,15 @@ +

+ +

-# [Haxe logo](https://haxe.org) - [The Cross-Platform Toolkit](https://haxe.org) -[![TravisCI Build Status](https://travis-ci.org/HaxeFoundation/haxe.svg?branch=development)](https://travis-ci.org/HaxeFoundation/haxe) -[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/HaxeFoundation/haxe?branch=development&svg=true)](https://ci.appveyor.com/project/HaxeFoundation/haxe) -[![SauceLabs Test Status](https://saucelabs.com/buildstatus/haxe)](https://saucelabs.com/u/haxe) -[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/HaxeFoundation/haxe?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +

+ Azure Pipelines Build Status + SauceLabs Test Status + Gitter + Discord +

+ +# Haxe is an open source toolkit that allows you to easily build cross-platform tools and applications that target many mainstream platforms. The Haxe toolkit includes: @@ -13,21 +19,22 @@ Haxe is an open source toolkit that allows you to easily build cross-platform to Haxe allows you to compile for the following targets: - * ActionScript 3 + * JavaScript * C++ * C# - * Flash - * [HashLink](http://hashlink.haxe.org/) * Java - * JavaScript * Lua - * [NekoVM](http://nekovm.org/) * PHP * Python 3 + * [HashLink](https://hashlink.haxe.org/) + * [NekoVM](https://nekovm.org/) + * Flash (SWF Bytecode) + * ActionScript 3 + * And its own [interpreter](https://haxe.org/blog/eval/) You can try Haxe directly from your browser at [try.haxe.org](https://try.haxe.org)! -For more information about Haxe, head to the [offical Haxe website](https://haxe.org). +For more information about Haxe, head to the [official Haxe website](https://haxe.org). ## License @@ -55,45 +62,45 @@ Automated development builds are available from [build.haxe.org](http://build.ha ## Building from source - 1. Clone the repository using git. Be sure to initialize and fetch the submodules. - - git clone --recursive git://github.com/HaxeFoundation/haxe.git - cd haxe - - 2. Follow the [documentation on building Haxe for your platform](https://haxe.org/documentation/introduction/building-haxe.html). +See [extra/BUILDING.md](extra/BUILDING.md). ## Using Haxe -For information on on using Haxe, consult the [Haxe documentation](https://haxe.org/documentation/): +For information on using Haxe, consult the [Haxe documentation](https://haxe.org/documentation/): * [Haxe Introduction](https://haxe.org/documentation/introduction/), an introduction to the Haxe toolkit * [The Haxe Manual](https://haxe.org/manual/), the reference manual for the Haxe language - * [Haxe Code Cookbook](http://code.haxe.org), code snippets / learning resource - * [Haxe API](http://api.haxe.org), documentation for the Haxe standard and native APIs - * [Haxelib](https://lib.haxe.org), a repository of Haxe libraries for a variety of needs + * [Haxe Code Cookbook](https://code.haxe.org), code snippets / learning resource + * [Haxe API](https://api.haxe.org), documentation for the Haxe standard and native APIs + * [Haxelib](https://lib.haxe.org), Haxelib is the package manager for the Haxe Toolkit. ## Community You can get help and talk with fellow Haxers from around the world via: + * [Haxe Community Forum](http://community.haxe.org) * [Haxe on Stack Overflow](https://stackoverflow.com/questions/tagged/haxe) - * the [official Haxe Google Group](https://groups.google.com/forum/#!forum/haxelang) - * [#Haxe on Twitter](https://twitter.com/hashtag/haxe?src=hash) - * the [Haxe IRC chatroom](https://unic0rn.github.io/tiramisu/haxe/), #haxe on chat.freenode.net + * [Haxe Gitter chatroom](https://gitter.im/HaxeFoundation/haxe/) + * [Haxe Discord server](https://discordapp.com/invite/0uEuWH3spjck73Lo) + * [#haxe on Twitter](https://twitter.com/hashtag/haxe?src=hash) -:+1: Get notified of the latest Haxe news, follow us on [Twitter](https://twitter.com/haxelang), [Facebook](https://www.facebook.com/haxe.org) or [Google+](https://plus.google.com/+HaxeOrg) +:+1: Get notified of the latest Haxe news, follow us on [Twitter](https://twitter.com/haxelang), [Facebook](https://www.facebook.com/haxe.org) and don't forget to read the [Haxe roundups](https://haxe.io/). ## Version compatibility -Haxe | neko ----- | ----- -2.* | 1.* -3.0.0 | 2.0.0 -3.1.3 | 2.0.0 -3.2.0 | 2.0.0 -3.3.0 | 2.1.0 -3.4.0 | 2.1.0 - +Haxe | Neko | SWF | Python | HL | PHP | Lua | +---- | ---- | ---- | ---- | ---- | ---- | ---- | +2.* | 1.* | 8-10 | - | - | - | - | +3.0.0 | 2.0.0 | | - | - | 5.1+ | - | +3.2.0 | | 12-14 | 3.2+ | - | | - | +3.3.0 | 2.1.0 | 21 | | - | | 5.1, 5.2, 5.3, LuaJIT 2.0, 2.1 | +3.4.0 | | | | 1.1 | 5.4+ and 7.0+ (with `-D php7`) | | +4.0.0-preview.1 | | | | 1.2 | 7.0+ | | +4.0.0-preview.3 | | | | 1.3 | | | +4.0.0-preview.4 | | | | 1.6 | | | +4.0.0-preview.5 | | | | 1.8 | | | +4.0.0-rc.1 | | | | 1.9 | | | +4.0.0-rc.3 | | | | 1.10 | | | ## Contributing diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 5d070f5a8ec..00000000000 --- a/appveyor.yml +++ /dev/null @@ -1,83 +0,0 @@ -version: "{build}" - -environment: - global: - HAXELIB_ROOT: C:/projects/haxelib - CYG_ROOT: C:/cygwin64 - ADD_REVISION: 1 - MYSQL_PATH: C:\Program Files\MySQL\MySQL Server 5.7 - MYSQL_USER: root - MYSQL_PASSWORD: Password12! - HXBUILDS_AWS_ACCESS_KEY_ID: - secure: fggQXlr5xGGl0znUi0UkqPWd6LviHnk0TR6YxJmuV3U= - HXBUILDS_AWS_SECRET_ACCESS_KEY: - secure: ewwkKcjnSKl/Vtrz1SXmI6XKk1ENmJDyzm5YaR2wi03foRhTke29TvymB21rDTSl - matrix: - - ARCH: 64 - TEST: "neko,python,cs,java,php,macro" - DEPLOY_NIGHTLIES: 1 - - ARCH: 64 - TEST: "cpp" - - ARCH: 32 - TEST: "macro" - DEPLOY_NIGHTLIES: 1 - -skip_tags: true - -cache: - - opam.tar.xz -> appveyor.yml - -install: - - 'git submodule update --init --recursive' - - '%CYG_ROOT%/bin/bash -lc "echo initialize"' - # http://help.appveyor.com/discussions/problems/5616-not-able-to-build-due-to-problem-in-chocolateyinstallps1 - - ps: Set-Service wuauserv -StartupType Manual - - choco install curl nsis.portable wget awscli -y - # Install ocaml - - curl -fsSL -o cygwin-setup.exe --retry 3 https://cygwin.com/setup-x86_64.exe - - 'cygwin-setup.exe -g -q -R "%CYG_ROOT%" -P make -P git -P mingw64-x86_64-zlib -P mingw64-i686-zlib -P rsync -P patch -P diffutils -P curl -P unzip -P m4 -P perl -P mingw64-x86_64-gcc-core -P mingw64-i686-gcc-core -P mingw64-x86_64-pcre -P mingw64-i686-pcre' - - if not exist "opam.tar.xz" ( - curl -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.1/opam%ARCH%.tar.xz - ) - - 7z x "opam.tar.xz" -so | 7z x -aoa -si -ttar - - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && bash opam${ARCH}/install.sh"' - - '%CYG_ROOT%/bin/bash -lc "opam init mingw \"https://github.com/fdopen/opam-repository-mingw.git\" --comp 4.02.3+mingw${ARCH}c --switch 4.02.3+mingw${ARCH}c --auto-setup --yes"' - - '%CYG_ROOT%/bin/bash -lc "opam install camlp4 sedlex ocamlfind xml-light extlib rope ptmap --yes"' - # Install neko - - choco install neko --prerelease --ignore-dependencies -s 'https://ci.appveyor.com/nuget/neko' -y - # Install php - - choco install php -y - - echo extension=php_openssl.dll >> C:\tools\php71\php.ini - - RefreshEnv - # setup python - - cmd: mklink C:\Python34-x64\python3.exe C:\Python34-x64\python.exe - - set PATH=%PATH%;C:\Python34-x64 - # expose the dll files - - if "%ARCH%" EQU "32" ( - set "PATH=%CYG_ROOT%/usr/i686-w64-mingw32/sys-root/mingw/bin;%PATH%" - ) else ( - set "PATH=%CYG_ROOT%/usr/x86_64-w64-mingw32/sys-root/mingw/bin;%PATH%" - ) - - neko -version - -build_script: - - 'cd %APPVEYOR_BUILD_FOLDER%' - - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win libs && make -j -s -f Makefile.win haxe && make -s -f Makefile.win haxelib"' - - 'set PATH=%PATH%;%APPVEYOR_BUILD_FOLDER%' - - 'set HAXEPATH=%APPVEYOR_BUILD_FOLDER%' - - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win package_bin"' - - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win package_choco"' - - move out\haxe.*.nupkg . - - dir %APPVEYOR_BUILD_FOLDER%\out - - cd %APPVEYOR_BUILD_FOLDER%/tests/ - - mkdir "%HAXELIB_ROOT%" - - haxelib setup "%HAXELIB_ROOT%" - -test_script: - - cd %APPVEYOR_BUILD_FOLDER%/tests/ - - haxe -version - - haxe RunCi.hxml - -artifacts: - - path: 'out/*.zip' - - path: '*.nupkg' diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 00000000000..4311d4542cf --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,300 @@ +variables: + - group: variables-haxe + - name: AZURE_PIPELINES_REPO_URL + value: $(Build.Repository.Uri) + - name: AZURE_PIPELINES_BRANCH + value: $(Build.SourceBranchName) + +stages: + - stage: StageTest + jobs: + - template: extra/azure-pipelines/build-linux.yml + parameters: + name: BuildLinux + + - template: extra/azure-pipelines/build-mac.yml + parameters: + name: BuildMac + + - template: extra/azure-pipelines/build-windows.yml + parameters: + name: BuildWin64 + arch: '64' + + - template: extra/azure-pipelines/build-windows.yml + parameters: + name: BuildWin32 + arch: '32' + + - job: TestLinux + dependsOn: BuildLinux + pool: + vmImage: 'ubuntu-16.04' + strategy: + matrix: + macro: + TEST: macro + neko: + TEST: neko + hl: + TEST: hl + APT_PACKAGES: cmake ninja-build + cpp: + TEST: cpp + HXCPP_COMPILE_CACHE: ~/hxcache + APT_PACKAGES: gcc-multilib g++-multilib + java: + TEST: java,jvm + cs: + TEST: cs + js: + TEST: js + SAUCE: 1 + SAUCE_TUNNEL_ID: $(Agent.JobName) + SAUCE_BUILD: $(Build.BuildNumber) + php: + TEST: php + flash: + TEST: flash9,as3 + APT_PACKAGES: libglib2.0 libfreetype6 xvfb + DISPLAY: ':99.0' + AUDIODEV: 'null' + python: + TEST: python + lua: + TEST: lua + steps: + - checkout: self + fetchDepth: 20 + - template: extra/azure-pipelines/install-neko-snapshot.yaml + parameters: + platform: linux64 + - task: DownloadPipelineArtifact@0 + inputs: + artifactName: 'linuxBinaries' + targetPath: linuxBinaries + - script: | + set -ex + tar -xf linuxBinaries/*_bin.tar.gz -C linuxBinaries --strip-components=1 + sudo mkdir -p /usr/local/bin/ + sudo mkdir -p /usr/local/share/haxe/ + sudo ln -s `pwd`/linuxBinaries/haxe /usr/local/bin/haxe + sudo ln -s `pwd`/linuxBinaries/haxelib /usr/local/bin/haxelib + sudo ln -s `pwd`/linuxBinaries/std /usr/local/share/haxe/std + displayName: Setup Haxe + - script: haxe -version + displayName: Print Haxe version + - script: | + set -ex + mkdir ~/haxelib + haxelib setup ~/haxelib + displayName: Setup haxelib + - script: | + set -ex + sudo apt update -qqy + sudo apt install -qqy $APT_PACKAGES + condition: and(succeeded(), variables['APT_PACKAGES']) + displayName: Install apt packages + - script: haxe RunCi.hxml + workingDirectory: $(Build.SourcesDirectory)/tests + env: + ${{ if variables['SAUCE_ACCESS_KEY'] }}: + SAUCE_ACCESS_KEY: $(SAUCE_ACCESS_KEY) + displayName: Test + + - job: TestMac + dependsOn: BuildMac + pool: + vmImage: 'macOS-10.13' + strategy: + matrix: + macro: + TEST: macro + neko: + TEST: neko + hl: + TEST: hl + BREW_PACKAGES: ninja + cpp: + TEST: cpp + HXCPP_COMPILE_CACHE: ~/hxcache + java: + TEST: java,jvm + cs: + TEST: cs + js: + TEST: js + php: + TEST: php + flash: + TEST: flash9,as3 + python: + TEST: python + lua: + TEST: lua + steps: + - checkout: self + fetchDepth: 20 + - template: extra/azure-pipelines/install-neko-snapshot.yaml + parameters: + platform: mac + - task: DownloadPipelineArtifact@0 + inputs: + artifactName: 'macBinaries' + targetPath: macBinaries + - script: | + set -ex + tar -xf macBinaries/*_bin.tar.gz -C macBinaries --strip-components=1 + sudo mkdir -p /usr/local/bin/ + sudo mkdir -p /usr/local/share/haxe/ + sudo ln -s `pwd`/macBinaries/haxe /usr/local/bin/haxe + sudo ln -s `pwd`/macBinaries/haxelib /usr/local/bin/haxelib + sudo ln -s `pwd`/macBinaries/std /usr/local/share/haxe/std + displayName: Setup Haxe + - script: haxe -version + displayName: Print Haxe version + - script: | + set -ex + mkdir ~/haxelib + haxelib setup ~/haxelib + displayName: Setup haxelib + - script: brew install $BREW_PACKAGES + condition: and(succeeded(), variables['BREW_PACKAGES']) + displayName: Install homebrew packages + - script: haxe RunCi.hxml + workingDirectory: $(Build.SourcesDirectory)/tests + displayName: Test + + - template: extra/azure-pipelines/test-windows.yml + parameters: + name: TestWin64 + arch: '64' + + - template: extra/azure-pipelines/test-windows.yml + parameters: + name: TestWin32 + arch: '32' + + - stage: StageDeploy + condition: and(succeeded(), not(variables['System.PullRequest.PullRequestId'])) + jobs: + - job: S3 + condition: and(succeeded(), variables['HXBUILDS_AWS_ACCESS_KEY_ID'], variables['HXBUILDS_S3ADDR']) + pool: + vmImage: 'ubuntu-16.04' + steps: + - checkout: self + fetchDepth: 20 + - task: DownloadPipelineArtifact@0 + inputs: + artifactName: 'linuxBinaries' + targetPath: linuxBinaries + displayName: Download linuxBinaries + - task: DownloadPipelineArtifact@0 + inputs: + artifactName: 'macBinaries' + targetPath: macBinaries + displayName: Download macBinaries + - task: DownloadPipelineArtifact@0 + inputs: + artifactName: 'win64Binaries' + targetPath: win64Binaries + displayName: Download win64Binaries + - task: DownloadPipelineArtifact@0 + inputs: + artifactName: 'win32Binaries' + targetPath: win32Binaries + displayName: Download win32Binaries + - template: extra/azure-pipelines/install-neko-snapshot.yaml + parameters: + platform: linux64 + - script: | + set -ex + tar -xf linuxBinaries/*_bin.tar.gz -C linuxBinaries --strip-components=1 + sudo mkdir -p /usr/local/bin/ + sudo mkdir -p /usr/local/share/haxe/ + sudo ln -s `pwd`/linuxBinaries/haxe /usr/local/bin/haxe + sudo ln -s `pwd`/linuxBinaries/haxelib /usr/local/bin/haxelib + sudo ln -s `pwd`/linuxBinaries/std /usr/local/share/haxe/std + displayName: Setup Haxe + - script: | + set -ex + sudo apt-get update -qqy + sudo apt-get install -qqy awscli + displayName: "Install awscli" + - script: | + set -ex + COMMIT_HASH=`git rev-parse HEAD` + COMMIT_HASH_SHORT=${COMMIT_HASH:0:7} + COMMIT_DATE=`TZ=UTC git show --quiet --date='format-local:%Y-%m-%d' --format="%cd"` + FILE_NAME=haxe_${COMMIT_DATE}_$(Build.SourceBranchName)_${COMMIT_HASH_SHORT} + aws s3 cp linuxBinaries/*_bin.tar.gz $(HXBUILDS_S3ADDR)/haxe/linux64/${FILE_NAME}.tar.gz + aws s3 cp macBinaries/*_bin.tar.gz $(HXBUILDS_S3ADDR)/haxe/mac/${FILE_NAME}.tar.gz + aws s3 cp win64Binaries/*_bin.zip $(HXBUILDS_S3ADDR)/haxe/windows64/${FILE_NAME}.zip + aws s3 cp win64Binaries/*_installer.zip $(HXBUILDS_S3ADDR)/haxe/windows64-installer/${FILE_NAME}.zip + aws s3 cp win64Binaries/*.nupkg $(HXBUILDS_S3ADDR)/haxe/windows64-choco/ + aws s3 cp win32Binaries/*_bin.zip $(HXBUILDS_S3ADDR)/haxe/windows/${FILE_NAME}.zip + aws s3 cp win32Binaries/*_installer.zip $(HXBUILDS_S3ADDR)/haxe/windows-installer/${FILE_NAME}.zip + aws s3 cp win32Binaries/*.nupkg $(HXBUILDS_S3ADDR)/haxe/windows-choco/ + env: + AWS_ACCESS_KEY_ID: $(HXBUILDS_AWS_ACCESS_KEY_ID) + AWS_SECRET_ACCESS_KEY: $(HXBUILDS_AWS_SECRET_ACCESS_KEY) + displayName: Upload binaries + - script: | + set -ex + aws s3 cp linuxBinaries/*_bin.tar.gz $(HXBUILDS_S3ADDR)/haxe/linux64/haxe_latest.tar.gz + aws s3 cp macBinaries/*_bin.tar.gz $(HXBUILDS_S3ADDR)/haxe/mac/haxe_latest.tar.gz + aws s3 cp win64Binaries/*_bin.zip $(HXBUILDS_S3ADDR)/haxe/windows64/haxe_latest.zip + aws s3 cp win64Binaries/*_installer.zip $(HXBUILDS_S3ADDR)/haxe/windows64-installer/haxe_latest.zip + aws s3 cp win32Binaries/*_bin.zip $(HXBUILDS_S3ADDR)/haxe/windows/haxe_latest.zip + aws s3 cp win32Binaries/*_installer.zip $(HXBUILDS_S3ADDR)/haxe/windows-installer/haxe_latest.zip + + # Chocolatey packages have to be named with version number, + # so let's use web redirection to keep the original file name. + [[ "$HXBUILDS_S3ADDR" =~ s3://([^/]+)(.*) ]] && HXBUILDS_S3BUCKET="${BASH_REMATCH[1]}" && HXBUILDS_S3PATH="${BASH_REMATCH[2]}" + [[ `echo win64Binaries/*.nupkg` =~ win64Binaries/(.+) ]] && FILE_NAME="${BASH_REMATCH[1]}" + aws s3 cp $(HXBUILDS_S3ADDR)/haxe/windows64-choco/${FILE_NAME} $(HXBUILDS_S3ADDR)/haxe/windows64-choco/haxe_latest.nupkg --acl public-read --website-redirect "${HXBUILDS_S3PATH}/haxe/windows64-choco/${FILE_NAME}" + [[ `echo win32Binaries/*.nupkg` =~ win32Binaries/(.+) ]] && FILE_NAME="${BASH_REMATCH[1]}" + aws s3 cp $(HXBUILDS_S3ADDR)/haxe/windows-choco/${FILE_NAME} $(HXBUILDS_S3ADDR)/haxe/windows-choco/haxe_latest.nupkg --acl public-read --website-redirect "${HXBUILDS_S3PATH}/haxe/windows-choco/${FILE_NAME}" + env: + AWS_ACCESS_KEY_ID: $(HXBUILDS_AWS_ACCESS_KEY_ID) + AWS_SECRET_ACCESS_KEY: $(HXBUILDS_AWS_SECRET_ACCESS_KEY) + condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'development')) + displayName: Update "latest" + + - job: ApiHaxeOrg + condition: and(succeeded(), variables['GHP_USERNAME'], variables['GHP_EMAIL']) + pool: + vmImage: 'ubuntu-16.04' + steps: + - checkout: none + - template: extra/azure-pipelines/install-neko-snapshot.yaml + parameters: + platform: linux64 + - task: DownloadPipelineArtifact@0 + inputs: + artifactName: 'linuxBinaries' + targetPath: linuxBinaries + displayName: Download linuxBinaries + - script: | + set -ex + tar -xf linuxBinaries/*_bin.tar.gz -C linuxBinaries --strip-components=1 + sudo mkdir -p /usr/local/bin/ + sudo mkdir -p /usr/local/share/haxe/ + sudo ln -s `pwd`/linuxBinaries/haxe /usr/local/bin/haxe + sudo ln -s `pwd`/linuxBinaries/haxelib /usr/local/bin/haxelib + sudo ln -s `pwd`/linuxBinaries/std /usr/local/share/haxe/std + displayName: Setup Haxe + - task: DownloadPipelineArtifact@0 + inputs: + artifactName: 'xmldoc' + targetPath: xmldoc + displayName: Download xmldoc + - script: | + set -ex + LOCAL="`pwd`/extra/api.haxe.org" + git clone "${GHP_REMOTE}" "${LOCAL}" + haxe --cwd "${LOCAL}" --run ImportXml "`pwd`/xmldoc" + env: + GHP_REMOTE: $(GHP_REMOTE) + displayName: Deploy to api.haxe.org \ No newline at end of file diff --git a/extra/BUILDING.md b/extra/BUILDING.md new file mode 100644 index 00000000000..18c80933b48 --- /dev/null +++ b/extra/BUILDING.md @@ -0,0 +1,79 @@ +# Building Haxe from source + +## Obtaining the source + +The Haxe compiler source files are hosted on GitHub under the [HaxeFoundation account](https://github.com/HaxeFoundation). The [Haxe repository](https://github.com/HaxeFoundation/haxe) has several submodules, so cloning it should be done with the `--recursive` flag like so: + +``` +git clone --recursive https://github.com/HaxeFoundation/haxe.git +``` + +Alternatively, source .zip archives or tarballs can be obtained from the [GitHub Haxe release overview](https://github.com/HaxeFoundation/haxe/releases). However, the git submodules are not included, so you will have to manually place the source code of [submodules](https://github.com/HaxeFoundation/haxe/blob/development/.gitmodules) into appropriate sub-folders. + +## Setting up OCaml + +The Haxe compiler is written in OCaml, so you have to set up an OCaml development environment. In addition, we make use of a number of OCaml libraries. We recommend using OPAM, which is an OCaml package manager that can also manage OCaml installations. + +The Haxe compiler requires OCaml version 4.02 or higher. Since some of the OCaml libraries Haxe depends on were uploaded in the OPAM 2 format, you should use OPAM 2.x instead of OPAM 1.x. + +To install OPAM on Unix (e.g. Mac, Linux) systems, follow the [instruction given by OPAM](https://opam.ocaml.org/doc/Install.html). On Windows, we recommend using the [Cygwin/MinGW-based OPAM environment provided by fdopen](https://fdopen.github.io/opam-repository-mingw/installation/), choose the 64-bit versions of everything, also make sure to [use the OPAM 2 version](https://github.com/fdopen/opam-repository-mingw/issues/48). + +In case you messed up the OPAM installation, you can uninstall OPAM and remove `~/.opam`, which contains the OCaml switches (OCaml compilers and libraries), and start over. + +Also note that since OPAM 2 on Linux will try to use bubblewrap, which uses Linux user namespaces, which might not be available on environments like Docker or Windows Subsystem for Linux (WSL). In case of encountering related errors, use `--disable-sandboxing` during `opam init`. + +## Installing dependencies + +You need to install some native libraries as well as some OCaml libraries. + + * Native libraries + * PCRE + * zlib + * Neko (for building haxelib) + * OCaml libraries + * listed in the `opam` file at the repository root + +To install the native libraries, use the appropriate system package manager. + + * Mac OS X + * Use [Homebrew](https://brew.sh/), `brew install zlib pcre`. + * Debian / Ubuntu + * `sudo apt install libpcre3-dev zlib1g-dev`. + * Windows (Cygwin) + * Run the Cygwin [setup-x86_64.exe](https://cygwin.com/install.html) against the Cygwin installation directory. Install `make`, `git`, `zlib-devel`, `libpcre-devel`, `mingw64-x86_64-gcc-core`, `mingw64-x86_64-zlib`, and `mingw64-x86_64-pcre`. You may need to select "Not Installed" in the dropdown list to see the packages. Copy `zlib1.dll` and `libpcre-1.dll` from `path/to/cygwin/usr/x86_64-w64-mingw32/sys-root/mingw/bin` to the checked out Haxe source directory. + * Install Neko by either + * Download the [Neko binaries](https://nekovm.org/download/), and add the extracted directory to the beginning of PATH. + * Install the [Chocolatey Neko package](https://chocolatey.org/packages/neko). + +To install the OCaml libraries, use OPAM as follows: + +```sh +# pin the haxe package to the checked out Haxe source directory +opam pin add haxe path/to/haxe --kind=path --no-action + +# install the haxe package dependencies (as listed in the `opam` file) +opam install haxe --deps-only +``` + +## Compile + +In the checked out Haxe source directory, +```sh +# On Unix +make + +# On Windows (Cygwin) +make -f Makefile.win +``` + +## Install + +Generally, you should remove any existing Haxe installation to avoid conflict. You should at least make sure that the `HAXE_STD_PATH` environment variable is not set. + +To install the freshly built Haxe, + + * On Unix (e.g. Mac and Linux), + ```sh + sudo make install + ``` + * On Windows, add the checked out Haxe source directory to the beginning of PATH. diff --git a/extra/CHANGES.txt b/extra/CHANGES.txt index 35873316bf3..303de5d9a9e 100644 --- a/extra/CHANGES.txt +++ b/extra/CHANGES.txt @@ -1,3 +1,343 @@ +2019-06-13: 4.0.0-rc.3 + + New features: + + all : added JVM target + + General improvements and optimizations: + + all : create temp vars in pattern matcher to avoid duplicate access (#8064) + all : support parsing dots in conditional compilation, e.g. `#if target.sys` + all : added `@:bypassAccessor` + all : improved various aspects of the display API + all : properly error on `@:op(a = b)` (#6903) + all : made `@:using` actually work + all : properly disallowed some modifier combinations related to `final` (#8335) + all : support `@:pure(false)` on variable fields (#8338) + flash : updated Flash externs to version 32.0 (now using `final`, `enum abstract` and `haxe.extern.Rest`) + flash : rework support for native Flash properties (#8241) + php : improved performance of various parser implementations (#8083) + cs : support .NET core target (#8391) + cs : generate native type parameter constraints (#8311, #7863) + + Standard Library: + + all : added StringTools.contains (#7608) + all : turned sys.thread.Thread into abstracts (#8130) + all : introduced `Std.downcast` as replacement for `Std.instance` (#8301) + all : introduced `UnicodeString`, deprecated `haxe.Utf8` (#8298) + java : added java.NativeString (#8163) + cs : added sys.thread implementations (#8166) + js : moved various classes to js.lib (#7390) + + Bugfixes + + all : fixed issue with `@:generic` type parameters not being bound to Dynamic (#8102) + all : fixed various issues related to `@:structInit` + all : fixed top-down inference on abstract setters (#7674) + all : fixed DCE issue related to closures (#8200) + all : fixed and restricted various Unicode-related issues in String literals + all : fixed various priority issues regarding loops and iterators + all : fixed cast handling in try-catch expressions (#8257) + all : fixed `inline new` handling (#8240) + all : fixed pattern matcher issue with wildcards in or-patterns (#8296) + all : fixed `@:allow(package)` allowing too much (#8306) + all : fixed various issues with startIndex handling on String.indexOf and String.lastIndexOf + all : fixed infinite recursion related to printing of objects with circular references (#8113) + sys : fixed various Unicode issues (#8135) + macro : fixed Array.pop handling (#8075) + macro : fixed assertion failure when throwing exception (#8039) + macro : fixed various uncatchable exceptions being thrown + php : error on case-insensitive name clashes (#8219) + lua : fixed issue where Process output occasionally is missing some data + hl : fixed various String Unicode issues + java : fixed null exception in CallStack.exceptionStack (#8322) + js : fixed code generation issue related to negative abstract values (#8318) + flash : fix various issues, including native `protected` handling and method overloading + + Removals: + + all : remove support for `@:fakeEnum` enums + all : disallowed `\x` with values > 0x7F (#8141) + all : consistently disallowed metadata in lambda function arguments (#7800) + all : removed `--gen-hx-classes` (#8237) + +2019-03-22: 4.0.0-rc.2 + + New features: + + all : added strictness settings for the null-safety checker, using loose checking by default (#7811) + js : added ES6 class generation with `-D js-es=6` (#7806) + + General improvements and optimizations: + + all : inherit `@:native` for overriden methods (#7844) + all : standardized identifiers allowed in markup literals (#7558) + all : show typo suggestions when declaring `override` field (#7847) + all : improved parser error messages (#7912) + all : improved diagnostics of syntax errors (#7940) + all : improved positions of `switch` and `case` expressions (#7947) + all : allow parsing `#if (a.b)` (#8005) + eval : improved performance of various string operations (#7982) + eval : fixed many error positions + eval : greatly improved debugger interaction (#7839) + eval : properly support threads when debugging (#7991) + eval : improved handling of capture variables (#8017) + js : generate dot-access for "keyword" field names (#7645) + js : optimized run-time type checking against interfaces (#7834) + js : skip generation of interfaces when no run-time type checking needed (#7843) + + Standard Library: + + all : unified various Thread APIs in sys.thread (#7999) + all : moved typed arrays from `js.html` to `js.lib` (#7894) + all : added `iterator()` to `haxe.DynamicAccess` (#7892) + all : added `keyValueIterator()` to `haxe.DynamicAccess` (#7769) + eval : completed Thread API + + Bugfixes: + + all : fixed argument default value checking for externs (#7752) + all : fixed optional status of overloaded arguments with default values (#7794) + all : fixed DCE compilation server state issue (#7805) + all : fixed compilation server module dependency issue related to macros (#7448) + all : fixed call-site inlining on abstracts (#7886) + all : fixed Constructible not checking constraints properly (#6714) + all : fixed @:structInit not being compatible with `final` fields (#7182) + all : fixed capture variables being allowed in `.match` (#7921) + all : fixed infinite recursion on `@:generic` field access (#6430) + all : fixed `-D no-deprecation-warnings` for typedefs and enums + js : fixed bad stack handling on `Map` constraint checks (#7781) + js : fixed DCE issues related to haxe.CallStack (#7908) + cpp : fixed Socket flags not being preserved (#7989) + lua : fixed broken output when compiling through the compilation server (#7851) + lua : fixed `StringTools.fastCodeAt` with `-D lua-vanilla` (#7589) + lua : fixed `@:expose` for classes inside packages (#7849) + +2019-02-01: 4.0.0-rc.1 + + New features: + + all : added experimental null-safety feature through `--macro nullSafety("package")` (#7717) + + General improvements and optimizations: + + all : improved unification error messages (#7547) + all : added `haxe4` define + all : do not require semicolon for markup literals (#7438) + all : made `@:expose` imply `@:keep` (#7695) + all : unified cast, catch and Std.is behavior of null-values (#7532) + macro : static variables are now always re-initialized when using the compilation server (#5746) + macro : support `@:persistent` to keep macro static values across compilations + js : improve js.Promise extern: now `then` callback argument types can be properly inferred (#7644) + + Bugfixes: + + all : fixed various pattern matching problems + all : fixed various wrong positions when encoding data to macros + all : specified String.indexOf with out-of-bounds indices (#7601) + all : fixed various problems related to DCE and feature-handling (#7694) + all : fixed bad unary operator optimization (#7704) + js : fixed syntax problem related to `instanceof` (#7653) + flash : fixed var field access on interfaces being uncast (#7727) + cpp : fixed various issues related to casts + cpp : fixed some leftover unicode issues + php : fixed class naming conflicts (#7716) + eval : fixed Socket.setTimeout (#7682) + eval : fixed int switch bug related to overflows + + Removals: + + macro : deprecated Context.registerModuleReuseCall and onMacroContextReused (#5746) + +2018-10-13: 4.0.0-preview.5 + New features: + + all : support Unicode strings properly on all targets + all : support `for (key => value in e)` syntax for key-value iterators + all : added keyValueIterator to Map and its implementations + all : support loop-unrolling on `for (i in 0...5)` (#7365) + all : added support for write-mode `@:op(a.b)` + all : support `inline call()` and `inline new` expressions (#7425) + all : support `@:using` on type declarations (#7462) + all : support markup literal strings but require them to be macro-processed (#7438) + all : allow enum values without arguments as default function argument values (#7439) + lua : add -D lua-vanilla, which emits code with reduced functionality but no additional lib dependencies + + General improvements and optimizations: + + all : [breaking] reserved `operator` and `overload` as keywords (#7413) + all : made `final` on structure fields invariant (#7039) + all : [breaking] disallowed static variables that have no type-hint and expression (#6440) + all : added display/typeDefinition to display protocol (#7266) + all : fixed various display-related problems + all : made parser in display mode much more tolerant + all : allowed assigning `[]` where `Map` is expected (#7426) + all : unified various parts of the String API across all targets + php : Optimized haxe.ds.Vector (VectorData is not Array anymore) + php : Optimized `Map.copy()` and `Array.copy()` + php : Optimized iterators of `Map` and native arrays. + php : Support native PHP generators. See `php.Syntax.yield()` and `php.Generator` + js : updated HTML externs + eval : improved object prototype field handling (#7393) + eval : optimized int switches (#7481) + eval : improved IntMap and StringMap performance + eval : improved performance of instance calls + + Removals : + + all : disallowed get_x/set_x property syntax, use get/set instead (#4699) + all : disallowed default values on interface variables (#4087) + all : disallowed `implements Dynamic` on non-extern classes (#6191) + all : warn about expressions in extern non-inline fields (#5898) + all : removed `-D use-rtti-doc`, always store documentation instead (#7493) + all : disallowed macro-in-macro calls (#7496) + js : removed jQuery and swfobject externs (#7494) + + Bugfixes: + + all : fix GC compacting too often in server mode + all : [breaking] `function () { }(e)` is no longer parsed as a call (#5854) + all : fixed various minor inlining issues + all : disallowed `return null` from Void-functions (#7198) + all : fixed various pattern matching problems + all : fixed compiler hang in display mode (#7236) + all : fixed the XML printer trimming CDATA content (#7454) + all : fixed invalid visibility unification with statics (#7527) + php : Escape `$` in field names of anonymous objects (#7230) + php : Generate `switch` as `if...else if...else...` to avoid loose comparison (#7257) + cs : fixed bad evaluation order in structures (#7531) + eval : fixed various problems with the debugger + eval : fixed Vector.fromArrayCopy (#7492) + eval : fixed bad string conversions on invalid + operations + + Standard Library: + + all : [breaking] made Lambda functions return Array instead of List (#7097) + all : added haxe.iterators package + all : improved StringTools.lpad/rpad/htmlEscape implementation + +2018-06-12: 4.0.0-preview.4 + + New features: + + all : added JSON-RPC-based display protocol + all : allow `enum abstract` syntax instead of `@:enum abstract` (#4282) + all : allow `extern` on fields instead of `@:extern` + all : support signature completion on incomplete structures (#5767) + all : support auto-numbering and auto-stringification in enum abstracts (#7139) + all : support `Type1 & Type2` intersection syntax for type parameter constraints and structures (#7127) + + General improvements and optimizations: + + all : reworked CLI usage/help output (#6862) + all : implemented `for` loop unrolling (#3784) + all : metadata can now use `.`, e.g. `@:a.b`. This is represented as a string (#3959) + all : [breaking] disallow static extensions through abstract field casts (#5924) + all : [breaking] disallow static extensions on implicit `this` (#6036) + all : allow true and false expressions as type parameters (#6958) + all : improved display support in many areas + all : support `override |` completion + all : make display/references and display/toplevel actually work sometimes + all : allow `var ?x` and `final ?x` parsing in structures (#6947) + all : improved overall robustness of the parser in display mode + all : allow `@:commutative` on non-static abstract functions (#5599) + js : added externs for js.Date (#6855) + js : respect `-D source-map` flag to generate source maps in release builds + js : enums are now generated as objects instead of arrays (#6350) + eval : improved debugger, support conditional breakpoints + + Removals: + + all : moved haxe.remoting to hx3compat + js : moved js.XMLSocket to hx3compat + neko : moved neko.net to hx3compat + all : removed support for `T:(A, B)` constraint syntax + + Bugfixes: + + all : fixed various issues with diagnostics + all : fixed fields with default values for `@:structInit` classes (#5449) + all : fixed `Null` inconsistency in if/ternary expressions (#6955) + all : fixed visibility check related to private constructors of sibling classes (#6957) + all : fixed @:generic naming (#6968) + all : fixed handling of type parameters in local functions (#6560) + all : fixed resolution order between `untyped` and type parameters (#7113) + all : fixed unification behavior in try/catch expressions (#7120) + all : fixed field type being lost for Int expressions on Float fields (#7132) + all : cleaned up `inline` handling (#7155) + display : fixed completion in packages starting with underscore (#5417) + php : fixed Reflect.callMethod with classes as first argument (#7106) + eval : fixed internal exception surfacing in some context calls (#7007) + eval : fixed Type.enumEq (#6710) + flash : fixed silently swallowing exceptions in getters/setters when invoked with Reflect methods (#5460, #6871) + + Standard Library: + + all : added `resize` to Array (#6869) + all : [breaking] removed `return this` from some haxe.Http methods (#6980) + +2018-02-23: 4.0.0-preview.3 + + See full commit history at https://github.com/HaxeFoundation/haxe/compare/4.0.0-preview.2...4.0.0-preview.3, notable changes below: + + New features: + + all : added new function type syntax (`(a:Int, b:String)->Void`) (#6645) + all : added column to StackItem.FilePos (#6665) + all : added `-D warn-var-shadowing` + all : added haxe.Log.formatOutput (#6738) + js : added js.Syntax class for generating unsupported JavaScript syntax in a type-safe analyzer-friendly way + js : added js.Map and js.Set and js.JsIterator extern definitions (ES6) + hl : added hl.Format.digest, use it for native Sha1/Md5 + + General improvements and optimizations: + + all : made all non-warning/non-error compiler messages output to stdout (#4480) + all : make DCE keep constructor if any instance field is kept (#6690) + all : make `final` in structures use class notation + display : added `this` and `super` to toplevel completion (#6051) + php : implemented direct method comparison. No need to use `Reflect.compareMethods()` + php : added `php.Syntax.code()` instead of deprecated `untyped __php__()` (#6708) + php : added methods to `php.Syntax` for each php operator: `??`, `?:`, `**` etc. (#6708) + python : add ssl support for http requests + python : improve Sys.print(ln) code generation (#6184) + js : generate faster code for `x.iterator()` calls (#6669) + js : rework exception handling, added js.Lib.getOriginalException (#6713) + js : generate `value instanceof MyClass` instead of `Std.is(value, MyClass)` (#6687) + js : use lazy getter for HaxeError.message instead of calling String(val) in the ctor (#6754) + + Removals: + + php : removed `php.Syntax.binop()` (#6708) + + Deprecations: + + php : deprecated support for `untyped __php__`, `untyped __call__` etc. Use `php.Syntax` instead. + + Bugfixes: + + all : delay interface accessor generation properly (#6225, #6672) + all : fixed unbound variable error in anonymous functions (#6674) + all : fixed abstract `@:to` used when `from` is available in a specific case (#6751) + all : sys.Http: fix chunked encoding handling (#6763) + all : fix some invalid Json being accepted by haxe.format.JsonParser (#6734) + all : fixed haxe.format.JsonPrinter for instances of classes to make it produce consistent result across targets (#6801) + all : fixed autogenerated constructor for extending @:structInit classes (#6822, #6078) + js : fixed saving setter to `tmp` var before invocation (#6672) + lua : fix toString behavior in the case of -0 (#6652) + lua : properly bind field functions when passed as arguments (#6722) + php : don't fail on generating import aliases for classes with the similar names (#6680) + php : fixed `Sys.environment()` to also return variables set by `Sys.putEnv()` + php : fixed `sys.net.Socket.bind()` (#6693) + php : fixed appending "sqlite:" prefix to the names of files created by `sys.db.Sqlite.open()` (#6692) + php : made php.Lib.objectOfAssociativeArray() recursive (#6698) + php : fixed php error on parsing expressions like `a == b == c` (#6720) + php : fixed multiple file uploads in php.Web.parseMultiPart() (#4173) + php : fixed an issue with "Object" used as a class name for PHP 7.2 (it's a new keyword in php) (#6838) + eval : don't lose dynamic function inits from parent classes (#6660) + cs : fix order-dependent enum type parameter issue (#6016) + 2017-10-08: 4.0.0-preview.2 New features: @@ -21,7 +361,7 @@ Bugfixes: all : fixed issue with various functions not being displayed in macro context (#6000) - all : fixed invalid static extension lookup on `super` (#3607) + all : fixed invalid static extension lookup on `super` (#3607) all : fixed typing error when constructing enums with abstracts over functions (#6609) all : fixed bug that skipped checking @:from typing in some cases (#6564) all : fixed Int64 parsing of negative numbers that end in a zero (#5493) @@ -83,6 +423,22 @@ all : added `EReg.escape` (#5098) all : `BalancedTree implements `haxe.Constraints.IMap` (#6231) +2018-01-31: 3.4.5 + + General improvements and optimizations: + + dce : optimized DCE performance (#6181) + + Bugfixes: + + dce : don't remove constructor if any instance field is kept (#6062) + js : fixed saving setter to `tmp` var before invocation (#6672) + php7 : don't fail on generating import aliases for classes with the similar names (#6680) + php7 : fixed appending "sqlite:" prefix to the names of files created by `sys.db.Sqlite.open()` (#6692) + php7 : made php.Lib.objectOfAssociativeArray() recursive (#6698) + php7 : fixed php error on parsing expressions like `a == b == c` (#6720) + php/php7 : fixed `sys.net.Socket.bind()` (#6693) + 2017-10-08: 3.4.4 Bugfixes: diff --git a/extra/ImportAll.hx b/extra/ImportAll.hx index 814709b65e4..22e3f49a506 100644 --- a/extra/ImportAll.hx +++ b/extra/ImportAll.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2016 Haxe Foundation + * Copyright (C)2005-2018 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,11 +23,20 @@ import haxe.macro.Context; class ImportAll { + static function isSysTarget() { + return Context.defined("neko") || Context.defined("php") || Context.defined("cpp") || + Context.defined("java") || Context.defined("python") || + Context.defined("lua") || Context.defined("hl") || Context.defined("eval"); // TODO: have to add cs here, SPOD gets in the way at the moment + } + public static function run( ?pack ) { if( pack == null ) { pack = ""; haxe.macro.Compiler.define("doc_gen"); } + if (Context.defined("interp")) { + haxe.macro.Compiler.define("macro"); + } switch( pack ) { case "php": if( !Context.defined("php") ) return; @@ -39,10 +48,16 @@ class ImportAll { if( !Context.defined("cpp") ) return; case "flash": if( !Context.defined("flash9") ) return; + case "mt","mtwin": + return; case "sys": - if( !Context.defined("neko") && !Context.defined("php") && !Context.defined("cpp") ) return; + if(!isSysTarget()) return; + case "sys.thread": + if ( !Context.defined("target.threaded") ) return; case "java": if( !Context.defined("java") ) return; + case "jvm": + if( !Context.defined("jvm") ) return; case "cs": if( !Context.defined("cs") ) return; case "python": @@ -53,10 +68,9 @@ class ImportAll { if( !Context.defined("lua") ) return; case "eval": if( !Context.defined("eval") ) return; - case "tools": - return; - case "build-tool": - return; + case "ssl": + if (!Context.defined("neko") && !Context.defined("cpp")) return; + case "tools", "build-tool", "jar-tool": return; } for( p in Context.getClassPath() ) { if( p == "/" ) @@ -78,12 +92,13 @@ class ImportAll { switch( cl ) { case "ImportAll", "neko.db.MacroManager": continue; case "haxe.TimerQueue": if( Context.defined("neko") || Context.defined("php") || Context.defined("cpp") ) continue; - case "Sys": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue; + case "Sys": if(!isSysTarget()) continue; case "haxe.web.Request": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("js")) ) continue; - case "haxe.macro.ExampleJSGenerator","haxe.macro.Context", "haxe.macro.Compiler": if( !Context.defined("neko") ) continue; + case "haxe.macro.ExampleJSGenerator","haxe.macro.Context", "haxe.macro.Compiler": if( !Context.defined("eval") ) continue; case "haxe.remoting.SocketWrapper": if( !Context.defined("flash") ) continue; case "haxe.remoting.SyncSocketConnection": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue; - case "sys.db.Sqlite" | "sys.db.Mysql" | "cs.db.AdoNet": continue; + case "neko.vm.Ui" | "sys.db.Sqlite" | "sys.db.Mysql" if ( Context.defined("interp") ): continue; + case "sys.db.Sqlite" | "sys.db.Mysql" | "cs.db.AdoNet" if ( Context.defined("cs") ): continue; } Context.getModule(cl); } else if( sys.FileSystem.isDirectory(p + "/" + file) ) diff --git a/extra/all.hxml b/extra/all.hxml index 4816ce3eb6e..1fbb6e39fea 100644 --- a/extra/all.hxml +++ b/extra/all.hxml @@ -15,7 +15,7 @@ -swf all9.swf -xml flash9.xml --swf-version 11.4 +--swf-version 11.4 --next @@ -26,19 +26,21 @@ -cpp all_cpp -xml cpp.xml --D xmldoc -D HXCPP_MULTI_THREADED --next -java all_java -xml java.xml --D xmldoc + +--next +-java all_jvm +-D jvm +-xml jvm.xml --next -cs all_cs -D unsafe -xml cs.xml --D xmldoc --next -python all_python diff --git a/extra/azure-pipelines/build-linux.yml b/extra/azure-pipelines/build-linux.yml new file mode 100644 index 00000000000..74993edf4cd --- /dev/null +++ b/extra/azure-pipelines/build-linux.yml @@ -0,0 +1,61 @@ +parameters: + name: 'BuildLinux' + vmImage: 'ubuntu-16.04' + +jobs: + - job: ${{ parameters.name }} + pool: + vmImage: ${{ parameters.vmImage }} + variables: + OPAMYES: 1 + ADD_REVISION: 1 + steps: + - checkout: self + submodules: recursive + - script: | + set -ex + sudo add-apt-repository ppa:avsm/ppa -y # provides newer version of OCaml and OPAM + sudo apt-get update -qqy + sudo apt-get install -qqy ocaml-nox camlp5 opam libpcre3-dev zlib1g-dev libgtk2.0-dev ninja-build + displayName: Install dependencies + - template: install-neko-snapshot.yaml + parameters: + platform: linux64 + - script: | + set -ex + opam init + opam update + opam pin add haxe . --no-action + opam install haxe --deps-only + opam list + ocamlopt -v + displayName: Install OCaml libraries + - script: | + set -ex + opam config exec -- make -s STATICLINK=1 libs + opam config exec -- make -s STATICLINK=1 prebuild + opam config exec -- make -s -j`nproc` STATICLINK=1 haxe + opam config exec -- make -s haxelib + make -s package_bin + ls -l out + ldd -v ./haxe + ldd -v ./haxelib + displayName: Build Haxe + - task: PublishPipelineArtifact@0 + inputs: + artifactName: 'linuxBinaries' + targetPath: out + - script: | + set -ex + make -s xmldoc + cat >extra/doc/info.json <&1') + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'opam update --yes 2>&1') + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam pin add haxe . --kind=path --no-action --yes 2>&1') + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'opam install haxe --deps-only --yes 2>&1') + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'opam list') + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'ocamlopt -v') + displayName: Install OCaml and OCaml libraries + - powershell: Write-Host "##vso[task.prependpath]${env:CYG_ROOT}/usr/$(MINGW_ARCH)-w64-mingw32/sys-root/mingw/bin" + displayName: Expose mingw dll files + - powershell: | + Set-PSDebug -Trace 1 + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam config exec -- make -s -f Makefile.win libs prebuild 2>&1') + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam config exec -- make -s -f Makefile.win -j`nproc` haxe 2>&1') + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam config exec -- make -s -f Makefile.win haxelib 2>&1') + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam config exec -- make -f Makefile.win echo_package_files package_bin package_installer_win package_choco 2>&1') + dir out + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && cygcheck ./haxe.exe') + & "$(CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && cygcheck ./haxelib.exe') + displayName: Build Haxe + - task: PublishPipelineArtifact@0 + inputs: + artifactName: 'win$(ARCH)Binaries' + targetPath: out \ No newline at end of file diff --git a/extra/azure-pipelines/install-neko-snapshot.yaml b/extra/azure-pipelines/install-neko-snapshot.yaml new file mode 100644 index 00000000000..7086a28f6b5 --- /dev/null +++ b/extra/azure-pipelines/install-neko-snapshot.yaml @@ -0,0 +1,33 @@ +parameters: + platform: '' # can be linux64, mac, windows, or windows64 + +steps: + - ${{ if startsWith(parameters.platform, 'windows') }}: + - powershell: | + Invoke-WebRequest https://build.haxe.org/builds/neko/${{parameters.platform}}/neko_latest.zip -OutFile $(Agent.TempDirectory)/neko_latest.zip + Expand-Archive $(Agent.TempDirectory)/neko_latest.zip -DestinationPath $(Agent.TempDirectory) + $NEKOPATH = Get-ChildItem $(Agent.TempDirectory)/neko-*-* + Write-Host "##vso[task.prependpath]$NEKOPATH" + Write-Host "##vso[task.setvariable variable=NEKOPATH]$NEKOPATH" + displayName: Install Neko using snapshot from S3 + - ${{ if not(startsWith(parameters.platform, 'windows')) }}: + - bash: | + set -ex + DOWNLOADDIR=$(Agent.TempDirectory) + curl -sSL https://build.haxe.org/builds/neko/${{parameters.platform}}/neko_latest.tar.gz -o $(Agent.TempDirectory)/neko_latest.tar.gz + tar -xf $(Agent.TempDirectory)/neko_latest.tar.gz -C $(Agent.TempDirectory) + NEKOPATH=`echo $(Agent.TempDirectory)/neko-*-*` + sudo mkdir -p /usr/local/bin + sudo mkdir -p /usr/local/lib/neko + sudo ln -s $NEKOPATH/{neko,nekoc,nekoml,nekotools} /usr/local/bin/ + sudo ln -s $NEKOPATH/libneko.* /usr/local/lib/ + sudo ln -s $NEKOPATH/*.ndll /usr/local/lib/neko/ + set +x + echo "##vso[task.prependpath]$NEKOPATH" + echo "##vso[task.setvariable variable=NEKOPATH]$NEKOPATH" + displayName: Install Neko using snapshot from S3 + - ${{ if eq(parameters.platform, 'linux64') }}: + - bash: sudo ldconfig + displayName: ldconfig + - script: neko -version 2>&1 + displayName: Print Neko version \ No newline at end of file diff --git a/extra/azure-pipelines/test-windows.yml b/extra/azure-pipelines/test-windows.yml new file mode 100644 index 00000000000..bbb84d66b1e --- /dev/null +++ b/extra/azure-pipelines/test-windows.yml @@ -0,0 +1,87 @@ +parameters: + name: 'TestWindows' + vmImage: 'windows-2019' + arch: '64' # or '32' + +jobs: + - job: ${{ parameters.name }} + dependsOn: BuildWin${{ parameters.arch }} + pool: + vmImage: ${{ parameters.vmImage }} + variables: + HAXELIB_ROOT: C:/haxelib + strategy: + matrix: + # https://github.com/HaxeFoundation/haxe/issues/8600 + ${{ if eq(parameters.arch, '64') }}: + macro: + TEST: macro + neko: + TEST: neko + hl: + TEST: hl + cpp: + TEST: cpp + HXCPP_COMPILE_CACHE: C:/hxcache + java: + # https://github.com/HaxeFoundation/haxe/issues/8601 + ${{ if eq(parameters.arch, '64') }}: + TEST: java,jvm + ${{ if eq(parameters.arch, '32') }}: + TEST: java + cs: + TEST: cs + js: + TEST: js + php: + TEST: php + # TODO. flash has never been enabled on our AppVeyor builds. + # flash: + # TEST: flash9,as3 + python: + TEST: python + # TODO. Lua has never been enabled on our AppVeyor builds. + # lua: + # TEST: lua + steps: + - checkout: self + fetchDepth: 20 + - template: install-neko-snapshot.yaml + parameters: + ${{ if eq(parameters.arch, '64') }}: + platform: windows64 + ${{ if eq(parameters.arch, '32') }}: + platform: windows + - task: DownloadPipelineArtifact@0 + inputs: + artifactName: 'win${{ parameters.arch }}Binaries' + targetPath: win${{ parameters.arch }}Binaries + - powershell: | + Set-PSDebug -Trace 1 + 7z x win${{ parameters.arch }}Binaries/*_bin.zip -owin${{ parameters.arch }}Binaries + $dir = Get-ChildItem win${{ parameters.arch }}Binaries/* -Name -Directory + Rename-Item win${{ parameters.arch }}Binaries/$dir haxe + $dir = '' + ( get-location ) + '\win${{ parameters.arch }}Binaries\haxe' + dir $dir + Set-PSDebug -Trace 0 + Write-Host "##vso[task.prependpath]$dir" + displayName: Setup Haxe + - script: haxe -version + displayName: Print Haxe version + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.7' + - powershell: | + Set-PSDebug -Trace 1 + $pypath = python -c "import sys; print(sys.executable)" + $py3path = $pypath.replace("python.exe","python3.exe") + cmd /c mklink $py3path $pypath + python3 -V + displayName: "Make Python 3 be available as python3 in the cmdline" + - script: | + mkdir "$(HAXELIB_ROOT)" + haxelib setup "$(HAXELIB_ROOT)" + displayName: Setup haxelib + - script: haxe RunCi.hxml + workingDirectory: $(Build.SourcesDirectory)/tests + displayName: Test diff --git a/extra/doc.hxml b/extra/doc.hxml new file mode 100644 index 00000000000..fa8b532121e --- /dev/null +++ b/extra/doc.hxml @@ -0,0 +1,56 @@ +--no-output +--macro ImportAll.run() +--dce no +-D doc-gen + +--each + +-neko all.n +-xml doc/neko.xml + +--next + +-js all.js +-xml doc/js.xml + +--next + +-swf all9.swf +-xml doc/flash.xml +--swf-version 11.4 + +--next + +-php all_php +-xml doc/php.xml + +--next + +-cpp all_cpp +-xml doc/cpp.xml +-D HXCPP_MULTI_THREADED + +--next +-java all_java +-xml doc/java.xml + +--next +-cs all_cs +-D unsafe +-xml doc/cs.xml + +--next +-python all_py +-xml doc/python.xml + +--next +--interp +-xml doc/macro.xml + +--next +-lua all_lua +-xml doc/lua.xml + +--next +-hl all_hl +-xml doc/hl.xml \ No newline at end of file diff --git a/extra/extract.hxml b/extra/extract.hxml index e0b3f0770b5..427a2d9026a 100644 --- a/extra/extract.hxml +++ b/extra/extract.hxml @@ -4,9 +4,9 @@ # - Run haxe extract.hxml # - Restore removed haxe/std/flash/DIR directories # - Copy directories from hxclasses/flash to haxe/std/flash, overwriting restored ones --debug --swf-lib library.swf +--debug +--swf-lib library.swf -swf test.swf --swf-version 15 +--swf-version 15 --macro patchTypes("../extra/extract.patch") ---gen-hx-classes +-D gen-hx-classes diff --git a/extra/haxelib_src b/extra/haxelib_src index 93f6a205bdf..8795d1120c3 160000 --- a/extra/haxelib_src +++ b/extra/haxelib_src @@ -1 +1 @@ -Subproject commit 93f6a205bdf4012a2615957b766e7a34efe9f0b6 +Subproject commit 8795d1120c3afb94dda229cab3a60bad42df506d diff --git a/extra/images/Readme.png b/extra/images/Readme.png new file mode 100644 index 0000000000000000000000000000000000000000..f101ccf0aeeecb651f6992fd6009e2073a173838 GIT binary patch literal 8453 zcmV+gA^P5lP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3#rmMbd`g#WXOUILR4EC-M{r+3iH?~k;r?o{u- zq1!&?Oyf*aC_)jUg8%2=C;W?7t|f;m+S_O?@~WebJUQv{^?Dsstk3838uC6%KaPhs z-Zy223di#L+Wd7)lX3ZWgVy)>`f)tye$Uh26TN@(nd2QPU*|4-p8k}) zn!nCnobM~jkEsZ;y)S4#<>)=0S6*e+C95r6eT_9Y^x1XG zZd-TXV^7OgjPkc;8m!x}>B*szR~K)t-hKEyaP5>+kDPY&^fS)5bY&tUlN2H`Ewb{g@(MIgyJQh~=6OH*&w?_62G-A4e$|`b!0Drsz%8pj%B7OUihT1Hul!M%GhgiuwcwOX{^-N%q zsB=Lb9+G^C!v!*xtChB`mDNvT{=ALA0HL`frl-LP4~FAP}SSIfHoFO;AJBB~I;JYKw>m&^6Oqtp*7$H&Zk=>UEsu!68=o*jNr3pe(79?M4 znh_F54C*|?7J{rDF`yA3`re#`9Pd}UddMef)`<48Itna0HwnOtgm6&{QE_)fMrLpO6trg{C0l2l)BqfZc$?xdihTQ)(Y@aK zRCIG8j>#GgG3zkre}LL60ar3P@T#rEW)>`%c=5?;IBD0j|JK z4uK50M#~XULK~6_TmySrHr01GPhkRfRC)wo%YGJh#}PTy{JA62RiZ z3+Gu|@UqmyDH(~1GH594buCGtZfbX9PJ@j^ zyd8e&nfCSRw955Mb`b05Y>7v9lv$C%Ck_I*+ z^>2zv_|pqf2RgSH{tNoS&pnc$4gUZD00v@9M??U90DS;`ikxYK00009a7bBm000id z000id0mpBsWB>pF2XskIMF-;q1`ibkw`*UZ000+&NkloWFY6E2E7}n-L&yMX{Lf8B!%p#T{?WcX&KaD z9!5OWh=&^X_204z%t~f1aDQ%n*Mq%ndaAak2EitxxjrRdH+|r^<694=Jen1 zfJ`n1&S^*{LD-$upC#Cy4I_~{Jv1y)iXaF{m&$<|on@)h38j*0A}4baa9?hH*ROz; zD(~Od{;^ZBGBa5kw}-&?CCqYnDh~7>O8=$T+F&mPkbqgrrLaLsBs(nG=C~ za_hT(4Xjjn_qNaJGbxjq=mh*ZRb>)*1UoZYBHOZhbXMNtr;-EqOXCy-Ar(^b?H{%N z(PbwB_jst^ulp^^QK@d_Sm8lu< z^^G;Mn`mj`Kck?%tYqE>+>OseVM70&I%RSQdY;KgfwnP`$Y7SBKNC$PGEsdDNy8Kb zAth45N6%Loi0`hd@*WHqb(dun-dM?;0NkBh-}Ml%5>MUJ_SPM$icDsq6YysP?V}Ru z3nj8OUWtsCibN`cAf!bqSjww3L*7G`m&^%Xn_7p@!(l>yU5QL)0?P=z#lb+fO^?pX zI46;@21N2Hf*_ue#1BOBDS{v*8NbqRz3IujC#xYJ z^;{cXyUO@eRU$tS$)^Z{kUpuP*8xkSPzuqNH(8N5u}D5e5QNl9#r3>O6`_n?L&C%& z`4mAAl1{dwRAQK~Vp1q$#Nt7)%l#X+gZY%hfNvWv^GCop4V5(&xXbYQ^#IpIT+c59 zZZllwO5i@r=Y2hJjK%W52Ykn1dDj8Q+4$-Lp8%e$@b{a5*QV4VPleY$u~b}`uhOhg zM#VBoX+JtH76nhzrB4TrZ}7e6 z07qCjrzg=XoeOnI1$XAFsNFtlQ=747>y%h>;Xk3(I2m|_*NR1HMH4 z{U%d^%PpMG2zuL$z0!mmk%|NJRZI)THL*xOrDa(h!7&yRT_^U1zy?cYzZLjEo$vXy zC26k$ekaX$VyWyad*dz4S4o*rToOx_e2T;`>7^4mHG<>34m)!*%CQ?b6MI|QtwQHm zYT@PB8JYGtaHTZg8l)1S9zsuK8TSfrT0C7~wuRz~SSsXG6mYXN(bRGVdW2RKEQ;{D z9s#bfRQ4=jNsX^viSGU~$=)!!l!v`qq|)BCF%Nvc>`ga@yh>C;iCrv}^C>^;?CE_> znrLcS9O1D(Nbydm_E`lyY^m%^fP-p?&d#xL>=nSDr0LcumGIg4N9CfGsPigO3nfmm zRLQ4Eh@D;zqw jqnm+euT#xK@XMQWufdDOq_hbhH9&YG{(cg7p3XeDV6L&z4>xC zvncZ_aS0_Zu~f*X+}YXF`=~U})Ut@^XMmj*@$q_r^DUKq9&mVtzny^jT-6YIEAqTF z-FhPxz(d^v{I&E|QRG$P7D^mqDU(l8VVEtX6OU+f90lfwPx(=DGjO|wa@&AwE7a{5 zEeQJ};Av^P4N4_bA-7^Xui}bOA{9&de99f2J-xq|rkPq!LMNP~W-|2;$u+^b!1ET$ zJrzByEv9%7Et3ruFEM@X3cgl#bRC54&$&t7? z9ym0H*2Bi?b<*(aOpgj(rL64q&$7a<4{rQLQjs?ppLFVJ@YSkO)TT{DQjiKSL!*-fpb_CKD>; z@J8*Ot1-43)wIG#D=Y}yO!A#6oNvcpxi=`x=az|%R?;oT& zrkaK5?T=kxQH;mF9=O-x&*=x~EsO;lQVAcSZyAkNn%rL{=|V9nmZE%$jQDB|7CUq< zAHZxER6PXfiG=+Qen!s&pOU6(St@NMBf%P#N?L?sL@Z=f(y-!H9ECN=?SSLRQ-i;fB7Xbbf_=PATBB`_=)LR${_QTPOu zX+|t+&*+b9I(vE_Z?QIaO8Bo;XahcEsH`>UkxnM0@*ebRzkM;*&8L79iD!j@Vm1Pw z5gkM*6@a`7Zq0c9GJKAxb!c(gh0>^4!hDM4Qd)!gz)KC4wHlq@+)4BEUE0vOm2bpY zH#@^f-n3LE9rR2v(%=1g;D@zHrB#Gdw^&}xr^tw} z*1*(At7p*NU!X@%z0c6OeIw@j`3-vim1Qv<|9aq832RfY45O>K_#S$&MOo@fka!+H z2A-TKuhMEl86%bnlJ`aV6p2#O&q2UH87gZ{(a(1pD)X(FpX1R8R{(KL{QXOeGD|IW zNhLF*HxFDdY_OQNP9_;-jAe|N6@S3n&1QIogrP|H0&-R z(}rGDQ*cQt0DimwWASq2dH19e45=mTRb75(-kk-#9VNfT*HVGY`sW=g8csJ;(K|evAP4-s%HP*9K7rpT z^J0E_zYus^gvUDr-R&p1AeE8+?&<7O7XXj}5zE9v0r0XM<>Q?uwUTO155;1F2dTbl zZa?s_p<}fH{~S}D9YH(;SiTlUErJ7)$`aKdbdCN`#4@2!fWo3U%LnHlCeccIF}dn) zEvpD8eH2(0z3fLE0|j0Jd{dfi%u>nqcTWdCt+tgcQ!HYsE|fxTXE{c&EPded4qiuZmhj^1A380!BFT~`^~byd%A)P)PSly zj5riaFpx2qLQIQL0Iyx4hP|Wq>+$$MX~8zv2W&O?Q1p6-uFYiE*V;N>`*Yx2gJN7x z%{wMF%p~+^uQmrhw;8~<(3^${QA$O@5}-@HFhP53QL#)Ul#&|1yno)IKke$-7_?ZM z`!;Zqp|Yj}1CCtR9N=(+<<+w*qe-dEL@(R&pym2n3Cwn=UCsy23EQXZi~yTrJpMK# zQW*(zDFEa0DI%8Igi?66&H^JG>EoS_-d0seJ|?4-r_h^m)ylo-36hfyUW-ks%mF^@ z;AeOpaCgi%>{@sphgSutCsJ7g%wWGl?Wl1IeT#^tW}y^l51%z)+0J>dy=_|0)3PQ( zvY8Bg&|rD{foto0&!9o6oCbUnJIlf!fbRBkG4nbtj8xu*tP^5aD!Jk)Wk;QLopQ0% zEfm0OQz$%u*#W`(f!n1iCYtx4`{hkBn|Qm1rUUN5LFQUKN0KnftGqrw^yN*R@3J~&@y*(aQ{^HTH@Cu!qdn4N7t4fu|JMs=R4;knAgo~20T{L#>UzoP8? zlok_9Q$i^)c9YrV1M|D30Vk7%)H#YWA!O0pA)De$=#gcndBoE7pOlcODp^tqqm&Cq zqm*j%Q(8nUMudXSs}yl03W-*d$s)P733)eqxULPMyd8U^wXVkP{7)hymC;-Zz=ZQt zQZ5!#LK%Gy9Luu7Q)bC5`(!a2I3~r{_a^jWkIm49o>*wQZ3n==p*JzR$kO$@JW|c+ z5Vxi%1)9jGR1r&3Muiy_NLgIOW&pp}Y5%Hc`e`frBla+joFR z!=GQYIGTLMhNbMk)Z8 z56nC4r=2|;T5XnnQXj}Z+yd9R2)#a6BW?0@OLa6*B07c6{r)$0lItshJAuDA@|jEm zPH?D=98~(eTq#Pqa7>i4!_r(J$GgI;359Wa6@Vi_oi6w5L~t_jiWa!eSE08@u9uf# zZ?4B>!1j{gJqrAnrQ=OTFVEj5&3xw zEp)Ao?6YEPANVJ#$Z9FD%TgU23tTMCz5%I}&Py4U$~MbAGLDJGx=;$WKVB@ek$Eew z(}}q)gOk8%=%jV6EV5KTg>J4&o#p=rTw}2wmH|gg^RGWr88hMwu#-=5SS*nUr9gYx z-!31RC-YVu=5*rOsW2`M1Wv8-wXXucV(C0?Vd8}@uLGX7_-*}e#c!=JUMdx%lpPVS ztroLbA{7c{^C~)8LFTPE%-Jn?&9%%~@qn8s={h&WF5us5c->y$a~A92jp&??P=V6U zm-8vJFrL+XN)@q0Jt{0}p_KguUgYwf^SW=J*3&B^!Q7%7vqM)E@U(^Ve3{{!`@7IX zS+`Vq%_o3UEYmjS>-pl}b-vM%MdsSSU{J9j5b&c{G!44UIy&6*d8v#&Mf}aNTqxn`GNyo`j*6! z-|Q0%I4~tdrc@;b(~C!L3ZJNLaaRO&@OpHKkq?Qc+tS z$rBqEi!(wg#E4mGjE>U*oM9nKu^Fb?kjjUP?i*Qjw^xUy^ZyUvnI_A)0oZ7T&iB(IVHOm}_t0S{O{=YYoZ5!G0Xp0Bao;<-av&ENu|%xDH4r{#nlL%9)rSf4DlLbN?mfW?rz z`g{z)NPqXq#SL9;4ah&7OU5PTDKC~J2?bz3sKGJkdSho#?|Bj^2!fClDt3Q4n@_0{ zv5e`UNSaVU@+yKLq*y9j6Sj_Fu~?EQltSDnc@;qrQYRJH=BLyl7Ox}d3;O*(1%nCQ zJW=MW2!fDc%03r6IX|WBiGteW5$yB{c6$A4(EG9)_P)|~xZ34+<`)Eez2$13ceEPP zuOk7$m)E9H$Zo=dAf!nuuI5vUB{Jv{^!t#bAGi*@uTKAdZ}H-BtM{y$xrQlf0bMLd zakSd&5e$1cEg8wH2!fD0sko9)DVE59N3g@!qu4c}O!(^b?{6%-66pb#Jg0!wd#-)W z8UnSz>rl%x9qMSh!m{^zs9}#_2-J`l?`q7Wp$e7uR}ln3NT5{W%%_w_B7J_jo9l!! z87G&Eo>ilfi=GX<9FL>D4u#jD@QWnlL?q+hd=)_ugvO*2X+EVi66yD=-AwD2NyW(J z>Oa7pY_U;;46*FWSm@< zZVG_a!`B?LMk()9;PO$qjNaL`WV{aWyVUsZGMkc-yow+Qsga7we2Ri#kB6#HBGzP5 zO2@^U6tE_YTo#OpT*ieD1<8!?;S5fiktom<^O?PuO5VGPXeT-thMG7$$Z zeO3W$hE~m7>p}T$u|_1*KqMo16+sY^FO`Y*qc4s`3PXIGf0~XwGMR`eI-$R2_^O#} zmCpj;vI!%XS|qd2L+uH>1Sg7QB(EX}LgJ;eEvPP$e&6IaH?c=16VY+09xXP!YUUbM zZ{$)=GLseF5Rz2N{9 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make -j4 FD_OUTPUT=1 -f Makefile.win kill haxe - - - - - - - - \ No newline at end of file diff --git a/opam b/opam new file mode 100644 index 00000000000..dbdaddb5f14 --- /dev/null +++ b/opam @@ -0,0 +1,34 @@ +opam-version: "2.0" +name: "haxe" +version: "4.0.0" +synopsis: "Multi-target universal programming language" +description: """ +Haxe is an open source toolkit based on a modern, +high level, static-typed programming language, a cross-compiler, +a complete cross-platform standard library and ways to access each +platform's native capabilities.""" +maintainer: ["Haxe Foundation " "Andy Li "] +authors: "Haxe Foundation " +homepage: "https://haxe.org/" +bug-reports: "https://github.com/HaxeFoundation/haxe/issues" +license: ["GPL2+" "MIT"] +dev-repo: "git+https://github.com/HaxeFoundation/haxe.git" +build: [ + [make] +] +install: [make "install" "INSTALL_DIR=%{prefix}%"] +remove: [make "uninstall" "INSTALL_DIR=%{prefix}%"] +depends: [ + "ocaml" {>= "4.02"} + "ocamlfind" {build} + "camlp5" {build} + "sedlex" {build & <= "1.99.4"} #https://github.com/HaxeFoundation/haxe/issues/7958 + "ppx_tools_versioned" {build & != "5.2.1"} #https://github.com/alainfrisch/sedlex/issues/64 + "xml-light" {build} + "extlib" {build & >= "1.7.6"} + "ptmap" {build} + "sha" {build} + "conf-libpcre" + "conf-zlib" + "conf-neko" +] \ No newline at end of file diff --git a/src-json/define.json b/src-json/define.json new file mode 100644 index 00000000000..37daedca77f --- /dev/null +++ b/src-json/define.json @@ -0,0 +1,639 @@ +[ + { + "name": "AbsolutePath", + "define": "absolute_path", + "doc": "Print absolute file path in trace output." + }, + { + "name": "AdvancedTelemetry", + "define": "advanced-telemetry", + "doc": "Allow the SWF to be measured with Monocle tool.", + "platforms": ["flash"] + }, + { + "name": "AnnotateSource", + "define": "annotate_source", + "doc": "Add additional comments to generated source code.", + "platforms": ["cpp"] + }, + { + "name": "As3", + "define": "as3", + "doc": "Defined when outputting flash9 as3 source code." + }, + { + "name": "CheckXmlProxy", + "define": "check_xml_proxy", + "doc": "Check the used fields of the XML proxy." + }, + { + "name": "CoreApi", + "define": "core_api", + "doc": "Defined in the core API context." + }, + { + "name": "CoreApiSerialize", + "define": "core_api_serialize", + "doc": "Mark some generated core API classes with the `Serializable` attribute on C#.", + "platforms": ["cs"] + }, + { + "name": "Cppia", + "define": "cppia", + "doc": "Generate cpp instruction assembly." + }, + { + "name": "CsVer", + "define": "cs_ver", + "doc": "The C# version to target.", + "platforms": ["cs"] + }, + { + "name": "NoCppiaAst", + "define": "nocppiaast", + "doc": "Use legacy cppia generation." + }, + { + "name": "Dce", + "define": "dce", + "doc": "Set the dead code elimination mode. (default: std)", + "params": ["mode: std | full | no"], + "links": ["https://haxe.org/manual/cr-dce.html"] + }, + { + "name": "DceDebug", + "define": "dce_debug", + "doc": "Show DCE log.", + "links": ["https://haxe.org/manual/cr-dce.html"] + }, + { + "name": "Debug", + "define": "debug", + "doc": "Activated when compiling with -debug." + }, + { + "name": "DisableUnicodeStrings", + "define": "disable_unicode_strings", + "doc": "Disable Unicode support in `String` type.", + "platforms": ["cpp"] + }, + { + "name": "Display", + "define": "display", + "doc": "Activated during completion.", + "links": ["https://haxe.org/manual/cr-completion.html"] + }, + { + "name": "DisplayStdin", + "define": "display_stdin", + "doc": "Read the contents of a file specified in `--display` from standard input." + }, + { + "name": "DllExport", + "define": "dll_export", + "doc": "GenCPP experimental linking.", + "platforms": ["cpp"] + }, + { + "name": "DllImport", + "define": "dll_import", + "doc": "Handle Haxe-generated .NET DLL imports.", + "platforms": ["cs"] + }, + { + "name": "DocGen", + "define": "doc_gen", + "doc": "Do not perform any removal/change in order to correctly generate documentation." + }, + { + "name": "Dump", + "define": "dump", + "doc": "Dump typed AST in dump subdirectory using specified mode or non-prettified default.", + "params": ["mode: pretty | record | position | legacy"] + }, + { + "name": "DumpDependencies", + "define": "dump_dependencies", + "doc": "Dump the classes dependencies in a dump subdirectory." + }, + { + "name": "DumpIgnoreVarIds", + "define": "dump_ignore_var_ids", + "doc": "Remove variable IDs from non-pretty dumps (helps with diff)." + }, + { + "name": "DynamicInterfaceClosures", + "define": "dynamic_interface_closures", + "doc": "Use slow path for interface closures to save space.", + "platforms": ["cpp"] + }, + { + "name": "EraseGenerics", + "define": "erase_generics", + "doc": "Erase generic classes on C#.", + "platforms": ["cs"] + }, + { + "name": "EvalCallStackDepth", + "define": "eval_call_stack_depth", + "doc": "Set maximum call stack depth for eval. (default: 1000)", + "platforms": ["eval"], + "params": ["depth"] + }, + { + "name": "EvalDebugger", + "define": "eval_debugger", + "doc": "Support debugger in macro/interp mode. Allows `host:port` value to open a socket. Implies eval_stack.", + "platforms": ["eval"] + }, + { + "name": "EvalStack", + "define": "eval_stack", + "doc": "Record stack information in macro/interp mode.", + "platforms": ["eval"] + }, + { + "name": "EvalTimes", + "define": "eval_times", + "doc": "Record per-method execution times in macro/interp mode. Implies eval_stack.", + "platforms": ["eval"] + }, + { + "name": "FastCast", + "define": "fast_cast", + "doc": "Enables an experimental casts cleanup on C# and Java.", + "platforms": ["cs", "java"] + }, + { + "name": "Fdb", + "define": "fdb", + "doc": "Enable full flash debug infos for FDB interactive debugging.", + "platforms": ["flash"] + }, + { + "name": "FileExtension", + "define": "file_extension", + "doc": "Output filename extension for cpp source code.", + "platforms": ["cpp"] + }, + { + "name": "FlashStrict", + "define": "flash_strict", + "doc": "More strict typing for flash target.", + "platforms": ["flash"] + }, + { + "name": "FlashUseStage", + "define": "flash_use_stage", + "doc": "Keep the SWF library initial stage.", + "platforms": ["flash"] + }, + { + "devcomment": "force_lib_check is only here as a debug facility - compiler checking allows errors to be found more easily", + "name": "ForceLibCheck", + "define": "force_lib_check", + "doc": "Force the compiler to check `--net-lib` and `–-java-lib` added classes (internal).", + "platforms": ["cs", "java"] + }, + { + "name": "ForceNativeProperty", + "define": "force_native_property", + "doc": "Tag all properties with `:nativeProperty` metadata for 3.1 compatibility.", + "platforms": ["cpp"] + }, + { + "name": "GencommonDebug", + "define": "gencommon_debug", + "doc": "GenCommon internal.", + "platforms": ["cs", "java"] + }, + { + "name": "Haxe3Compat", + "define": "haxe3compat", + "doc": "Gives warnings about transition from Haxe 3.x to Haxe 4.0." + }, + { + "name": "HaxeBoot", + "define": "haxe_boot", + "doc": "Give the name 'haxe' to the flash boot class instead of a generated name.", + "platforms": ["flash"] + }, + { + "name": "HaxeVer", + "define": "haxe_ver", + "doc": "The current Haxe version value as decimal number. E.g. 3.407 for 3.4.7." + }, + { + "name": "Haxe", + "define": "haxe", + "doc": "The current Haxe version value in SemVer format." + }, + { + "name": "HxcppApiLevel", + "define": "hxcpp_api_level", + "doc": "Provided to allow compatibility between hxcpp versions.", + "platforms": ["cpp"] + }, + { + "name": "HxcppGcGenerational", + "define": "HXCPP_GC_GENERATIONAL", + "doc": "Experimental Garbage Collector.", + "platforms": ["cpp"] + }, + { + "name": "HxcppDebugger", + "define": "HXCPP_DEBUGGER", + "doc": "Include additional information for hxcpp_debugger.", + "platforms": ["cpp"] + }, + { + "name": "HxcppSmartStings", + "define": "hxcpp_smart_strings", + "doc": "Use wide strings in hxcpp. (Turned on by default unless `-D disable_unicode_strings` is specified.)", + "platforms": ["cpp"] + }, + { + "name": "IncludePrefix", + "define": "include_prefix", + "doc": "Prepend path to generated include files.", + "platforms": ["cpp"] + }, + { + "name": "Interp", + "define": "interp", + "doc": "The code is compiled to be run with `--interp`." + }, + { + "name": "JavaVer", + "define": "java_ver", + "doc": "Sets the Java version to be targeted.", + "platforms": ["java"], + "params": ["version: 5-7"] + }, + { + "name": "JsClassic", + "define": "js_classic", + "doc": "Don't use a function wrapper and strict mode in JS output.", + "platforms": ["js"] + }, + { + "name": "JsEs", + "define": "js_es", + "doc": "Generate JS compliant with given ES standard version. (default: 5)", + "platforms": ["js"], + "params": ["version number"], + "links": ["https://haxe.org/manual/target-javascript-es6.html"] + }, + { + "name": "JsEnumsAsArrays", + "define": "js_enums_as_arrays", + "doc": "Generate enum representation as array instead of as object.", + "platforms": ["js"] + }, + { + "name": "JsUnflatten", + "define": "js_unflatten", + "doc": "Generate nested objects for packages and types.", + "platforms": ["js"] + }, + { + "name": "JsSourceMap", + "define": "js_source_map", + "doc": "Generate JavaScript source map even in non-debug mode.", + "platforms": ["js"] + }, + { + "name": "Jvm", + "define": "jvm", + "doc": "Generate jvm directly.", + "platforms": ["java"] + }, + { + "name": "SourceMap", + "define": "source_map", + "doc": "Generate source map for compiled files.", + "platforms": ["php"] + }, + { + "name": "KeepOldOutput", + "define": "keep_old_output", + "doc": "Keep old source files in the output directory.", + "platforms": ["cs", "java"] + }, + { + "name": "LoopUnrollMaxCost", + "define": "loop_unroll_max_cost", + "doc": "Maximum cost (number of expressions * iterations) before loop unrolling is canceled. (default: 250)", + "params": ["cost"] + }, + { + "name": "LuaJit", + "define": "lua_jit", + "doc": "Enable the jit compiler for lua (version 5.2 only).", + "platforms": ["lua"] + }, + { + "name": "LuaVanilla", + "define": "lua_vanilla", + "doc": "Generate code lacking compiled extern lib support (e.g. utf8).", + "platforms": ["lua"] + }, + { + "name": "LuaVer", + "define": "lua_ver", + "doc": "The lua version to target.", + "platforms": ["lua"], + "params": ["version"] + }, + { + "name": "Macro", + "define": "macro", + "doc": "Defined when code is compiled in the macro context.", + "links": ["https://haxe.org/manual/macro.html"] + }, + { + "name": "MacroTimes", + "define": "macro_times", + "doc": "Display per-macro timing when used with `--times`." + }, + { + "name": "NetVer", + "define": "net_ver", + "doc": "Sets the .NET version to be targeted.", + "platforms": ["cs"], + "params": ["version: 20-45"] + }, + { + "name": "NetcoreVer", + "define": "netcore_ver", + "doc": "Sets the .NET core version to be targeted", + "platforms": ["cs"], + "params": ["version: x.x.x"] + }, + { + "name": "NetTarget", + "define": "net_target", + "doc": "Sets the .NET target. `netcore` (.NET core), `xbox`, `micro` (Micro Framework), `compact` (Compact Framework) are some valid values. (default: `net`)", + "platforms": ["cs"], + "params": ["name"] + }, + { + "name": "NekoSource", + "define": "neko_source", + "doc": "Output neko source instead of bytecode.", + "platforms": ["neko"] + }, + { + "name": "NekoV1", + "define": "neko_v1", + "doc": "Keep Neko 1.x compatibility.", + "platforms": ["neko"] + }, + { + "name": "NetworkSandbox", + "define": "network-sandbox", + "doc": "Use local network sandbox instead of local file access one.", + "platforms": ["flash"] + }, + { + "name": "NoCompilation", + "define": "no-compilation", + "doc": "Disable final compilation.", + "platforms": ["cs", "java", "cpp", "hl"] + }, + { + "name": "NoCOpt", + "define": "no_copt", + "doc": "Disable completion optimization (for debug purposes)." + }, + { + "name": "NoDebug", + "define": "no_debug", + "doc": "Remove all debug macros from cpp output." + }, + { + "name": "NoDeprecationWarnings", + "define": "no-deprecation-warnings", + "doc": "Do not warn if fields annotated with `@:deprecated` are used." + }, + { + "name": "NoFlashOverride", + "define": "no-flash-override", + "doc": "Change overrides on some basic classes into HX suffixed methods", + "platforms": ["flash"] + }, + { + "name": "NoOpt", + "define": "no_opt", + "doc": "Disable optimizations." + }, + { + "name": "NoInline", + "define": "no_inline", + "doc": "Disable inlining.", + "links": ["https://haxe.org/manual/class-field-inline.html"] + }, + { + "name": "NoRoot", + "define": "no_root", + "doc": "Generate top-level types into the `haxe.root` namespace.", + "platforms": ["cs"] + }, + { + "name": "NoMacroCache", + "define": "no_macro_cache", + "doc": "Disable macro context caching." + }, + { + "name": "NoSwfCompress", + "define": "no_swf_compress", + "doc": "Disable SWF output compression.", + "platforms": ["flash"] + }, + { + "name": "NoTraces", + "define": "no_traces", + "doc": "Disable all trace calls." + }, + { + "name": "Objc", + "define": "objc", + "doc": "Sets the hxcpp output to Objective-C++ classes. Must be defined for interop.", + "platforms": ["cpp"] + }, + { + "name": "OldConstructorInline", + "define": "old-constructor-inline", + "doc": "Use old constructor inlining logic (from Haxe 3.4.2) instead of the reworked version." + }, + { + "name": "OldErrorFormat", + "define": "old-error-format", + "doc": "Use Haxe 3.x zero-based column error messages instead of new one-based format." + }, + { + "name": "PhpPrefix", + "define": "php_prefix", + "doc": "Root namespace for generated php classes. E.g. if compiled with`-D php-prefix=some.sub`, then all classes will be generated in `\\some\\sub` namespace.", + "platforms": ["php"], + "params": ["dot-separated namespace"] + }, + { + "name": "PhpLib", + "define": "php_lib", + "doc": "Select the name for the php lib folder.", + "platforms": ["php"], + "params": ["folder name"] + }, + { + "name": "PhpFront", + "define": "php_front", + "doc": "Select the name for the php front file. (default: `index.php`)", + "platforms": ["php"], + "params": ["filename"] + }, + { + "name": "PythonVersion", + "define": "python_version", + "doc": "The python version to target. (default: 3.3)", + "platforms": ["python"], + "params": ["version"] + }, + { + "name": "RealPosition", + "define": "real_position", + "doc": "Disables Haxe source mapping when targetting C#, removes position comments in Java and Php output.", + "platforms": ["cs", "java", "php"] + }, + { + "name": "ReplaceFiles", + "define": "replace_files", + "doc": "GenCommon internal.", + "platforms": ["cs", "java"] + }, + { + "name": "Scriptable", + "define": "scriptable", + "doc": "GenCPP internal.", + "platforms": ["cpp"] + }, + { + "name": "ShallowExpose", + "define": "shallow-expose", + "doc": "Expose types to surrounding scope of Haxe generated closure without writing to window object.", + "platforms": ["js"] + }, + { + "name": "SourceHeader", + "define": "source-header", + "doc": "Print value as comment on top of generated files, use '' value to disable." + }, + { + "name": "SourceMapContent", + "define": "source-map-content", + "doc": "Include the Haxe sources as part of the JS source map.", + "platforms": ["js"] + }, + { + "name": "Static", + "define": "static", + "doc": "Defined if the current target is static." + }, + { + "name": "Swc", + "define": "swc", + "doc": "Output a SWC instead of a SWF.", + "platforms": ["flash"] + }, + { + "name": "SwfCompressLevel", + "define": "swf_compress_level", + "doc": "Set the amount of compression for the SWF output.", + "platforms": ["flash"], + "params": ["level: 1-9"] + }, + { + "name": "SwfDebugPassword", + "define": "swf_debug_password", + "doc": "Set a password for debugging.", + "platforms": ["flash"], + "params": ["password"] + }, + { + "name": "SwfDirectBlit", + "define": "swf_direct_blit", + "doc": "Use hardware acceleration to blit graphics.", + "platforms": ["flash"] + }, + { + "name": "SwfGpu", + "define": "swf_gpu", + "doc": "Use GPU compositing features when drawing graphics.", + "platforms": ["flash"] + }, + { + "name": "SwfMetadata", + "define": "swf_metadata", + "doc": "Include contents of the given file as metadata in the SWF.", + "platforms": ["flash"], + "params": ["file"] + }, + { + "name": "SwfPreloaderFrame", + "define": "swf_preloader_frame", + "doc": "Insert empty first frame in SWF.", + "platforms": ["flash"] + }, + { + "name": "SwfProtected", + "define": "swf_protected", + "doc": "Compile Haxe `private` as `protected` in the SWF instead of `public`.", + "platforms": ["flash"] + }, + { + "name": "SwfScriptTimeout", + "define": "swf_script_timeout", + "doc": "Maximum ActionScript processing time before script stuck dialog box displays.", + "platforms": ["flash"], + "params": ["time in seconds"] + }, + { + "name": "SwfUseDoAbc", + "define": "swf_use_doabc", + "doc": "Use `DoAbc` SWF-tag instead of `DoAbcDefine`.", + "platforms": ["flash"] + }, + { + "name": "Sys", + "define": "sys", + "doc": "Defined for all system platforms." + }, + { + "name": "Unsafe", + "define": "unsafe", + "doc": "Allow unsafe code when targeting C#.", + "platforms": ["cs"] + }, + { + "name": "UseNekoc", + "define": "use_nekoc", + "doc": "Use `nekoc` compiler instead of the internal one.", + "platforms": ["neko"] + }, + { + "name": "Utf16", + "define": "utf16", + "doc": "Defined for all platforms that use UTF-16 string encoding with UCS-2 API." + }, + { + "name": "Vcproj", + "define": "vcproj", + "doc": "GenCPP internal.", + "platforms": ["cpp"] + }, + { + "name": "WarnVarShadowing", + "define": "warn_var_shadowing", + "doc": "Warn about shadowing variable declarations." + } +] diff --git a/src-json/meta.json b/src-json/meta.json new file mode 100644 index 00000000000..a8e91d2b02f --- /dev/null +++ b/src-json/meta.json @@ -0,0 +1,1196 @@ +[ + { + "name": "Abi", + "metadata": ":abi", + "doc": "Function ABI/calling convention.", + "platforms": ["cpp"] + }, + { + "name": "Abstract", + "metadata": ":abstract", + "doc": "Sets the underlying class implementation as `abstract`.", + "platforms": ["java", "cs"] + }, + { + "name": "Access", + "metadata": ":access", + "doc": "Forces private access to package, type or field.", + "params": ["Target path"], + "targets": ["TClass", "TClassField"], + "links": ["https://haxe.org/manual/lf-access-control.html"] + }, + { + "name": "Accessor", + "metadata": ":accessor", + "doc": "Used internally by DCE to mark property accessors.", + "targets": ["TClassField"], + "internal": true + }, + { + "name": "Allow", + "metadata": ":allow", + "doc": "Allows private access from package, type or field.", + "params": ["Target path"], + "links": ["https://haxe.org/manual/lf-access-control.html"] + }, + { + "name": "Analyzer", + "metadata": ":analyzer", + "doc": "Used to configure the static analyzer." + }, + { + "name": "Annotation", + "metadata": ":annotation", + "doc": "Annotation (`@interface`) definitions on `--java-lib` imports will be annotated with this metadata. Has no effect on types compiled by Haxe.", + "platforms": ["java"], + "targets": ["TClass"] + }, + { + "name": "ArrayAccess", + "metadata": ":arrayAccess", + "doc": "Allows array access on an abstract.", + "targets": ["TAbstract", "TAbstractField"], + "links": ["https://haxe.org/manual/types-abstract-array-access.html"] + }, + { + "name": "Ast", + "metadata": ":ast", + "doc": "Internally used to pass the AST source into the typed AST.", + "internal": true + }, + { + "name": "AstSource", + "metadata": ":astSource", + "doc": "Filled by the compiler with the parsed expression of the field.", + "targets": ["TClassField"] + }, + { + "name": "AutoBuild", + "metadata": ":autoBuild", + "doc": "Extends `@:build` metadata to all extending and implementing classes.", + "params": ["Build macro call"], + "targets": ["TClass"], + "links": ["https://haxe.org/manual/macro-auto-build.html"] + }, + { + "name": "Bind", + "metadata": ":bind", + "doc": "Override SWF class declaration.", + "platforms": ["flash"], + "targets": ["TClass"] + }, + { + "name": "Bitmap", + "metadata": ":bitmap", + "doc": "Embeds given bitmap data into the class (must extend `flash.display.BitmapData`).", + "platforms": ["flash"], + "params": ["Bitmap file path"], + "targets": ["TClass"], + "links": ["https://haxe.org/manual/target-flash-resources.html"] + }, + { + "name": "BridgeProperties", + "metadata": ":bridgeProperties", + "doc": "Creates native property bridges for all Haxe properties in this class.", + "platforms": ["cs"], + "targets": ["TClass"] + }, + { + "name": "Build", + "metadata": ":build", + "doc": "Builds a class or enum from a macro.", + "params": ["Build macro call"], + "targets": ["TClass", "TEnum"], + "links": ["https://haxe.org/manual/macro-type-building.html"] + }, + { + "name": "BuildXml", + "metadata": ":buildXml", + "doc": "Specify XML data to be injected into `Build.xml`.", + "platforms": ["cpp"] + }, + { + "name": "BypassAccessor", + "metadata": ":bypassAccessor", + "doc": "Do not call property accessor method and access the field directly.", + "targets": ["TExpr"], + "links": ["https://haxe.org/manual/class-field-property.html"] + }, + { + "name": "Callable", + "metadata": ":callable", + "doc": "Abstract forwards call to its underlying type.", + "targets": ["TAbstract"] + }, + { + "name": "Class", + "metadata": ":class", + "doc": "Used internally to annotate an enum that will be generated as a class.", + "platforms": ["java", "cs"], + "targets": ["TEnum"], + "internal": true + }, + { + "name": "ClassCode", + "metadata": ":classCode", + "doc": "Used to inject platform-native code into a class.", + "platforms": ["java", "cs"], + "targets": ["TClass"] + }, + { + "name": "Commutative", + "metadata": ":commutative", + "doc": "Declares an abstract operator as commutative.", + "targets": ["TAbstractField"], + "links": ["https://haxe.org/manual/types-abstract-operator-overloading.html"] + }, + { + "name": "CompilerGenerated", + "metadata": ":compilerGenerated", + "doc": "Marks a field as generated by the compiler. Should not be used by the end user.", + "platforms": ["java", "cs"] + }, + { + "name": "Const", + "metadata": ":const", + "doc": "Allows a type parameter to accept expression values.", + "targets": ["TTypeParameter"] + }, + { + "name": "CoreApi", + "metadata": ":coreApi", + "doc": "Identifies this class as a core API class (forces API check).", + "targets": ["TClass", "TEnum", "TTypedef", "TAbstract"] + }, + { + "name": "CoreType", + "metadata": ":coreType", + "doc": "Identifies an abstract as core type so that it requires no implementation.", + "targets": ["TAbstract"], + "links": ["https://haxe.org/manual/types-abstract-core-type.html"] + }, + { + "name": "CppFileCode", + "metadata": ":cppFileCode", + "doc": "Code to be injected into generated cpp file.", + "platforms": ["cpp"] + }, + { + "name": "CppInclude", + "metadata": ":cppInclude", + "doc": "File to be included in generated cpp file.", + "platforms": ["cpp"] + }, + { + "name": "CppNamespaceCode", + "metadata": ":cppNamespaceCode", + "doc": "", + "platforms": ["cpp"] + }, + { + "name": "CsNative", + "metadata": ":csNative", + "doc": "Automatically added by `--net-lib` on classes generated from .NET DLL files.", + "platforms": ["cs"], + "targets": ["TClass", "TEnum"], + "internal": true + }, + { + "name": "Dce", + "metadata": ":dce", + "doc": "Forces dead code elimination even when `--dce full` is not specified.", + "targets": ["TClass", "TEnum"], + "links": ["https://haxe.org/manual/cr-dce.html"] + }, + { + "name": "Debug", + "metadata": ":debug", + "doc": "Forces debug information to be generated into the SWF even without `--debug`.", + "platforms": ["flash"], + "targets": ["TClass", "TClassField"] + }, + { + "name": "Decl", + "metadata": ":decl", + "doc": "", + "platforms": ["cpp"] + }, + { + "name": "DefParam", + "metadata": ":defParam", + "doc": "Default function argument value loaded from the SWF and used for documentation in Genxml.", + "platforms": ["flash"], + "internal": true + }, + { + "name": "Delegate", + "metadata": ":delegate", + "doc": "Automatically added by `--net-lib` on delegates.", + "platforms": ["cs"], + "targets": ["TAbstract"] + }, + { + "name": "Depend", + "metadata": ":depend", + "doc": "", + "platforms": ["cpp"] + }, + { + "name": "Deprecated", + "metadata": ":deprecated", + "doc": "Mark a type or field as deprecated." + }, + { + "name": "DirectlyUsed", + "metadata": ":directlyUsed", + "doc": "Marks types that are directly referenced by non-extern code.", + "internal": true + }, + { + "name": "DynamicObject", + "metadata": ":dynamicObject", + "doc": "Used internally to identify the Dynamic Object implementation.", + "platforms": ["java", "cs"], + "targets": ["TClass"], + "internal": true + }, + { + "name": "Eager", + "metadata": ":eager", + "doc": "Forces typedefs to be followed early.", + "targets": ["TTypedef"] + }, + { + "name": "Enum", + "metadata": ":enum", + "doc": "Defines finite value sets to abstract definitions.", + "targets": ["TAbstract"], + "links": ["https://haxe.org/manual/types-abstract-enum.html"] + }, + { + "name": "EnumConstructorParam", + "metadata": ":enumConstructorParam", + "doc": "Used internally to annotate GADT type parameters.", + "targets": ["TClass"], + "internal": true + }, + { + "name": "Event", + "metadata": ":event", + "doc": "Automatically added by `--net-lib` on events. Has no effect on types compiled by Haxe.", + "platforms": ["cs"], + "targets": ["TClassField"] + }, + { + "name": "Exhaustive", + "metadata": ":exhaustive", + "doc": "Used internally to mark that a switch is exhaustive.", + "internal": true, + "links": ["https://haxe.org/manual/lf-pattern-matching-exhaustiveness.html"] + }, + { + "name": "Expose", + "metadata": ":expose", + "doc": "Includes the class or field in Haxe exports (default name is the classpath).", + "platforms": ["js", "lua"], + "params": ["name"], + "links": ["https://haxe.org/manual/target-javascript-expose.html"] + }, + { + "name": "Extern", + "metadata": ":extern", + "doc": "Marks the field as extern so it is not generated.", + "targets": ["TClassField"] + }, + { + "name": "File", + "metadata": ":file", + "doc": "Includes a given binary file into the target SWF and associates it with the class (must extend `flash.utils.ByteArray`).", + "platforms": ["flash"], + "params": ["File path"], + "targets": ["TClass"], + "links": ["https://haxe.org/manual/target-flash-resources.html"] + }, + { + "name": "FileXml", + "metadata": ":fileXml", + "doc": "Include a given XML attribute snippet in the `Build.xml` entry for the file.", + "platforms": ["cpp"], + "targets": ["TClass"] + }, + { + "name": "Final", + "metadata": ":final", + "doc": "Prevents a class or interface from being extended or a method from being overridden. Deprecated by the keyword `final`.", + "targets": ["TClass", "TClassField"], + "links": ["https://haxe.org/manual/class-field-final.html"] + }, + { + "devcomment": "this used to have UsedOn TObjectDecl(_)", + "name": "Fixed", + "metadata": ":fixed", + "doc": "Declares an anonymous object to have fixed fields." + }, + { + "name": "FlashProperty", + "metadata": ":flash.property", + "doc": "", + "platforms": ["flash"], + "targets": ["TClassField"] + }, + { + "name": "FlatEnum", + "metadata": ":flatEnum", + "doc": "Internally used to mark an enum as being flat, i.e. having no function constructors.", + "targets": ["TEnum"], + "internal": true + }, + { + "name": "Font", + "metadata": ":font", + "doc": "Embeds the given TrueType font into the class (must extend `flash.text.Font`).", + "params": ["TTF path", "Range String"], + "targets": ["TClass"], + "links": ["https://haxe.org/manual/target-flash-resources.html"] + }, + { + "name": "ForLoopVariable", + "metadata": ":forLoopVariable", + "doc": "Internally used to mark for-loop variables.", + "internal": true + }, + { + "name": "Forward", + "metadata": ":forward", + "doc": "Forwards field access to underlying type.", + "params": ["List of field names"], + "targets": ["TAbstract"], + "links": ["https://haxe.org/manual/types-abstract-forward.html"] + }, + { + "name": "ForwardStatics", + "metadata": ":forwardStatics", + "doc": "Forwards static field access to underlying type.", + "params": ["List of field names"], + "targets": ["TAbstract"], + "links": ["https://haxe.org/manual/types-abstract-forward.html"] + }, + { + "name": "From", + "metadata": ":from", + "doc": "Specifies that the field of the abstract is a cast operation from the type identified in the function.", + "targets": ["TAbstractField"], + "links": ["https://haxe.org/manual/types-abstract-implicit-casts.html"] + }, + { + "name": "FunctionCode", + "metadata": ":functionCode", + "doc": "Used to inject platform-native code into a function.", + "platforms": ["cpp", "java", "cs"] + }, + { + "name": "FunctionTailCode", + "metadata": ":functionTailCode", + "doc": "", + "platforms": ["cpp"] + }, + { + "name": "Generic", + "metadata": ":generic", + "doc": "Marks a class or class field as generic so each type parameter combination generates its own type/field.", + "links": ["https://haxe.org/manual/type-system-generic.html"] + }, + { + "name": "GenericBuild", + "metadata": ":genericBuild", + "doc": "Builds instances of a type using the specified macro.", + "targets": ["TClass"] + }, + { + "name": "GenericInstance", + "metadata": ":genericInstance", + "doc": "Internally used to mark instances of `@:generic` methods.", + "targets": ["TClassField"], + "internal": true + }, + { + "name": "Getter", + "metadata": ":getter", + "doc": "Generates a native getter function on the given field.", + "platforms": ["flash"], + "params": ["Class field name"], + "targets": ["TClassField"] + }, + { + "name": "Hack", + "metadata": ":hack", + "doc": "Allows extending classes marked as `@:final`. Not guaranteed to work on all targets.", + "targets": ["TClass"] + }, + { + "name": "HasUntyped", + "metadata": ":has_untyped", + "doc": "Used by the typer to mark fields that have untyped expressions.", + "internal": true + }, + { + "name": "HaxeGeneric", + "metadata": ":haxeGeneric", + "doc": "Used internally to annotate non-native generic classes.", + "platforms": ["cs"], + "targets": ["TClass", "TEnum"], + "internal": true + }, + { + "name": "HeaderClassCode", + "metadata": ":headerClassCode", + "doc": "Code to be injected into the generated class, in the header.", + "platforms": ["cpp"] + }, + { + "name": "HeaderCode", + "metadata": ":headerCode", + "doc": "Code to be injected into the generated header file.", + "platforms": ["cpp"] + }, + { + "name": "HeaderInclude", + "metadata": ":headerInclude", + "doc": "File to be included in generated header file.", + "platforms": ["cpp"] + }, + { + "name": "HeaderNamespaceCode", + "metadata": ":headerNamespaceCode", + "doc": "", + "platforms": ["cpp"] + }, + { + "name": "HlNative", + "metadata": ":hlNative", + "doc": "Specifies `hdll` name and function prefix for native functions.", + "platforms": ["hl"], + "targets": ["TClass", "TClassField"] + }, + { + "name": "HxGen", + "metadata": ":hxGen", + "doc": "Annotates that an extern class was generated by Haxe.", + "platforms": ["java", "cs"], + "targets": ["TClass", "TEnum"] + }, + { + "name": "IfFeature", + "metadata": ":ifFeature", + "doc": "Causes a field to be kept by DCE if the given feature is part of the compilation.", + "params": ["Feature name"], + "targets": ["TClassField"], + "links": ["https://haxe.org/manual/cr-dce.html"] + }, + { + "name": "Impl", + "metadata": ":impl", + "doc": "Used internally to mark abstract implementation fields.", + "targets": ["TAbstractField"], + "internal": true + }, + { + "name": "PythonImport", + "metadata": ":pythonImport", + "doc": "Generates python import statement for extern classes.", + "platforms": ["python"], + "targets": ["TClass"] + }, + { + "name": "ImplicitCast", + "metadata": ":implicitCast", + "doc": "Generated automatically on the AST when an implicit abstract cast happens.", + "targets": ["TExpr"], + "internal": true + }, + { + "name": "ImplicitReturn", + "metadata": ":implicitReturn", + "doc": "Generated automatically on the AST when an implicit return is inserted for arrow function.", + "targets": ["TExpr"], + "internal": true + }, + { + "name": "Include", + "metadata": ":include", + "doc": "", + "platforms": ["cpp"] + }, + { + "name": "InitPackage", + "metadata": ":initPackage", + "doc": "Some weird thing for Genjs we want to remove someday.", + "platforms": ["js"], + "internal": true + }, + { + "name": "Inline", + "metadata": ":inline", + "doc": "Inserted by the parser in case of `inline expr` and `inline function`.", + "targets": ["TExpr"] + }, + { + "name": "InlineConstructorArgument", + "metadata": ":inlineConstructorArgument", + "doc": "Internally used to mark expressions that were passed as arguments of an inlined constructor.", + "internal": true + }, + { + "name": "Internal", + "metadata": ":internal", + "doc": "Generates the annotated field/class with 'internal' access.", + "platforms": ["java", "cs"], + "targets": ["TClass", "TEnum", "TClassField"] + }, + { + "name": "IsVar", + "metadata": ":isVar", + "doc": "Forces a physical field to be generated for properties that otherwise would not require one.", + "targets": ["TClassField"], + "links": ["https://haxe.org/manual/class-field-property-rules.html"] + }, + { + "name": "JavaCanonical", + "metadata": ":javaCanonical", + "doc": "Used by the Java target to annotate the canonical path of the type.", + "platforms": ["java"], + "params": ["Output type package", "Output type name"], + "targets": ["TClass", "TEnum"] + }, + { + "name": "JavaNative", + "metadata": ":javaNative", + "doc": "Automatically added by `--java-lib` on classes generated from JAR/class files.", + "platforms": ["java"], + "targets": ["TClass", "TEnum"], + "internal": true + }, + { + "name": "JsRequire", + "metadata": ":jsRequire", + "doc": "Generate JavaScript module require expression for given extern.", + "platforms": ["js"], + "targets": ["TClass"], + "links": ["https://haxe.org/manual/target-javascript-require.html"] + }, + { + "name": "LuaRequire", + "metadata": ":luaRequire", + "doc": "Generate Lua module require expression for given extern.", + "platforms": ["lua"], + "targets": ["TClass"] + }, + { + "name": "LuaDotMethod", + "metadata": ":luaDotMethod", + "doc": "Indicates that the given extern type instance should have dot-style invocation for methods instead of colon.", + "platforms": ["lua"] + }, + { + "name": "Keep", + "metadata": ":keep", + "doc": "Causes a field or type to be kept by DCE.", + "links": ["https://haxe.org/manual/cr-dce.html"] + }, + { + "name": "KeepInit", + "metadata": ":keepInit", + "doc": "Causes a class to be kept by DCE even if all its field are removed.", + "targets": ["TClass"], + "links": ["https://haxe.org/manual/cr-dce.html"] + }, + { + "name": "KeepSub", + "metadata": ":keepSub", + "doc": "Extends `@:keep` metadata to all implementing and extending classes.", + "targets": ["TClass"], + "links": ["https://haxe.org/manual/cr-dce.html"] + }, + { + "name": "LibType", + "metadata": ":libType", + "doc": "Used by `--net-lib` and `--java-lib` to mark a class that should not be checked (overrides, interfaces, etc) by the type loader.", + "platforms": ["java", "cs"], + "targets": ["TClass"], + "internal": true + }, + { + "name": "LoopLabel", + "metadata": ":loopLabel", + "doc": "Mark loop and break expressions with a label to support breaking from within switch.", + "internal": true + }, + { + "name": "Markup", + "metadata": ":markup", + "doc": "Used as a result of inline XML parsing.", + "links": ["https://haxe.org/manual/lf-markup.html"] + }, + { + "name": "Meta", + "metadata": ":meta", + "doc": "Internally used to mark a class field as being the metadata field.", + "internal": true + }, + { + "name": "Macro", + "metadata": ":macro", + "doc": "(deprecated)" + }, + { + "name": "MaybeUsed", + "metadata": ":maybeUsed", + "doc": "Internally used by DCE to mark fields that might be kept.", + "internal": true + }, + { + "name": "MergeBlock", + "metadata": ":mergeBlock", + "doc": "Merge the annotated block into the current scope.", + "targets": ["TExpr"] + }, + { + "name": "MultiReturn", + "metadata": ":multiReturn", + "doc": "Annotates an extern class as the result of multi-return function.", + "platforms": ["lua"], + "targets": ["TClass"], + "links": ["https://haxe.org/manual/target-lua-multireturns.html"] + }, + { + "name": "MultiType", + "metadata": ":multiType", + "doc": "Specifies that an abstract chooses its this-type from its `@:to` functions.", + "params": ["Relevant type parameters"], + "targets": ["TAbstract"] + }, + { + "name": "Native", + "metadata": ":native", + "doc": "Rewrites the path of a class or enum during generation.", + "params": ["Output type path"], + "targets": ["TClass", "TEnum"], + "links": ["https://haxe.org/manual/lf-externs.html"] + }, + { + "name": "NativeChildren", + "metadata": ":nativeChildren", + "doc": "Annotates that all children from a type should be treated as if it were an extern definition - platform native.", + "platforms": ["java", "cs"], + "targets": ["TClass"] + }, + { + "name": "NativeGen", + "metadata": ":nativeGen", + "doc": "Annotates that a type should be treated as if it were an extern definition - platform native.", + "platforms": ["java", "cs", "python"], + "targets": ["TClass", "TEnum"] + }, + { + "name": "NativeGeneric", + "metadata": ":nativeGeneric", + "doc": "Used internally to annotate native generic classes.", + "platforms": ["cs"], + "targets": ["TClass", "TEnum"], + "internal": true + }, + { + "name": "NativeProperty", + "metadata": ":nativeProperty", + "doc": "Use native properties which will execute even with dynamic usage.", + "platforms": ["cpp"] + }, + { + "name": "NativeStaticExtension", + "metadata": ":nativeStaticExtension", + "doc": "Converts static function syntax into member call.", + "platforms": ["cpp"] + }, + { + "name": "NoCompletion", + "metadata": ":noCompletion", + "doc": "Prevents the compiler from suggesting completion on this field or type.", + "targets": ["TClassField"], + "links": ["https://haxe.org/manual/cr-completion.html"] + }, + { + "name": "NoClosure", + "metadata": ":noClosure", + "doc": "Prevents a method or all methods in a class from being used as a value.", + "targets": ["TClass", "TClassField"] + }, + { + "name": "NoDebug", + "metadata": ":noDebug", + "doc": "Does not generate debug information even if `--debug` is set.", + "platforms": ["flash", "cpp"], + "targets": ["TClass", "TClassField"] + }, + { + "name": "NoDoc", + "metadata": ":noDoc", + "doc": "Prevents a type from being included in documentation generation." + }, + { + "name": "NoExpr", + "metadata": ":noExpr", + "doc": "Internally used to mark abstract fields which have no expression by design.", + "internal": true + }, + { + "name": "NoImportGlobal", + "metadata": ":noImportGlobal", + "doc": "Prevents a static field from being imported with `import Class.*`.", + "targets": ["TAnyField"] + }, + { + "name": "NonVirtual", + "metadata": ":nonVirtual", + "doc": "Declares function to be non-virtual in cpp.", + "platforms": ["cpp"] + }, + { + "name": "NoPackageRestrict", + "metadata": ":noPackageRestrict", + "doc": "Allows a module to be accessed across all targets if found on its first type.", + "internal": true + }, + { + "name": "NoPrivateAccess", + "metadata": ":noPrivateAccess", + "doc": "Disallow private access to anything for the annotated expression.", + "targets": ["TExpr"] + }, + { + "name": "NoStack", + "metadata": ":noStack", + "doc": "", + "platforms": ["cpp"] + }, + { + "name": "NotNull", + "metadata": ":notNull", + "doc": "Declares an abstract type as not accepting null values.", + "targets": ["TAbstract"], + "links": ["https://haxe.org/manual/types-nullability.html"] + }, + { + "name": "NoUsing", + "metadata": ":noUsing", + "doc": "Prevents a field from being used with static extension.", + "targets": ["TClassField"], + "links": ["https://haxe.org/manual/lf-static-extension.html"] + }, + { + "name": "Ns", + "metadata": ":ns", + "doc": "Internally used by the SWF generator to handle namespaces.", + "platforms": ["flash"], + "internal": true + }, + { + "name": "NullSafety", + "metadata": ":nullSafety", + "doc": "Enables null safety for classes or fields. Disables null safety for classes, fields or expressions if provided with `Off` as an argument.", + "params": ["Off | Loose | Strict"], + "targets": ["TClass", "TClassField", "TExpr"], + "links": ["https://haxe.org/manual/cr-null-safety.html"] + }, + { + "name": "Objc", + "metadata": ":objc", + "doc": "Declares a class or interface that is used to interoperate with Objective-C code.", + "platforms": ["cpp"], + "targets": ["TClass"] + }, + { + "name": "ObjcProtocol", + "metadata": ":objcProtocol", + "doc": "Associates an interface with, or describes a function in, a native Objective-C protocol.", + "platforms": ["cpp"] + }, + { + "name": "Op", + "metadata": ":op", + "doc": "Declares an abstract field as being an operator overload.", + "params": ["The operation"], + "targets": ["TAbstractField"], + "links": ["https://haxe.org/manual/types-abstract-operator-overloading.html"] + }, + { + "name": "Optional", + "metadata": ":optional", + "doc": "Marks the field of a structure as optional.", + "targets": ["TClassField"], + "links": ["https://haxe.org/manual/types-nullability-optional-arguments.html"] + }, + { + "name": "Overload", + "metadata": ":overload", + "doc": "Allows the field to be called with different argument types.", + "params": ["Function specification (no expression)"], + "targets": ["TClassField"], + "links": ["https://haxe.org/manual/target-javascript-external-libraries.html"] + }, + { + "name": "Persistent", + "metadata": ":persistent", + "doc": "Keeps the value of static variables in macro context across compilations.", + "targets": ["TAnyField"], + "platforms": ["eval"] + }, + { + "name": "PhpGlobal", + "metadata": ":phpGlobal", + "doc": "Indicates that static fields of an extern class actually are located in the global PHP namespace.", + "platforms": ["php"], + "targets": ["TClass"] + }, + { + "name": "PhpClassConst", + "metadata": ":phpClassConst", + "doc": "Indicates that a static var of an extern class is a PHP class constant.", + "platforms": ["php"], + "targets": ["TClassField"] + }, + { + "name": "PhpMagic", + "metadata": ":phpMagic", + "doc": "Treat annotated field as special PHP magic field - this meta makes compiler avoid renaming such fields on generating PHP code.", + "platforms": ["php"], + "targets": ["TClassField"] + }, + { + "name": "PhpNoConstructor", + "metadata": ":phpNoConstructor", + "doc": "Special meta for extern classes which do not have native constructor in PHP, but need a constructor in Haxe extern.", + "platforms": ["php"], + "targets": ["TClass"] + }, + { + "name": "Pos", + "metadata": ":pos", + "doc": "Sets the position of a reified expression.", + "params": ["Position"], + "targets": ["TExpr"], + "links": ["https://haxe.org/manual/macro-reification.html"] + }, + { + "name": "Public", + "metadata": ":public", + "doc": "Marks a class field as being public.", + "targets": ["TClassField"], + "internal": true + }, + { + "name": "PublicFields", + "metadata": ":publicFields", + "doc": "Forces all class fields of inheriting classes to be public.", + "targets": ["TClass"] + }, + { + "name": "Private", + "metadata": ":private", + "doc": "Marks a class field as being private.", + "platforms": ["cs"], + "targets": ["TClassField"] + }, + { + "name": "PrivateAccess", + "metadata": ":privateAccess", + "doc": "Allow private access to anything for the annotated expression.", + "targets": ["TExpr"] + }, + { + "name": "Protected", + "metadata": ":protected", + "doc": "Marks a class field as being protected.", + "platforms": ["cs", "java", "flash"], + "targets": ["TClassField"] + }, + { + "name": "Property", + "metadata": ":property", + "doc": "Marks a property field to be compiled as a native C# property.", + "platforms": ["cs"], + "targets": ["TClassField"] + }, + { + "name": "Pure", + "metadata": ":pure", + "doc": "Marks a class field, class or expression as pure (side-effect free).", + "targets": ["TClass", "TClassField", "TExpr"] + }, + { + "name": "ReadOnly", + "metadata": ":readOnly", + "doc": "Generates a field with the `readonly` native keyword.", + "platforms": ["cs"], + "targets": ["TClassField"] + }, + { + "name": "RealPath", + "metadata": ":realPath", + "doc": "Internally used on `@:native` types to retain original path information.", + "internal": true + }, + { + "name": "Remove", + "metadata": ":remove", + "doc": "Causes an interface to be removed from all implementing classes before generation.", + "targets": ["TClass"] + }, + { + "name": "Require", + "metadata": ":require", + "doc": "Allows access to a field only if the specified compiler flag is set.", + "params": ["Compiler flag to check"], + "targets": ["TClassField"], + "links": ["https://haxe.org/manual/lf-condition-compilation.html"] + }, + { + "name": "RequiresAssign", + "metadata": ":requiresAssign", + "doc": "Used internally to mark certain abstract operator overloads.", + "internal": true + }, + { + "name": "Resolve", + "metadata": ":resolve", + "doc": "Abstract fields marked with this metadata can be used to resolve unknown fields.", + "targets": ["TClassField"] + }, + { + "name": "Rtti", + "metadata": ":rtti", + "doc": "Adds runtime type information.", + "targets": ["TClass"], + "links": ["https://haxe.org/manual/cr-rtti.html"] + }, + { + "name": "Runtime", + "metadata": ":runtime", + "doc": "", + "internal": true + }, + { + "name": "RuntimeValue", + "metadata": ":runtimeValue", + "doc": "Marks an abstract as being a runtime value.", + "targets": ["TAbstract"] + }, + { + "name": "Scalar", + "metadata": ":scalar", + "doc": "Used by hxcpp to mark a custom coreType abstract.", + "platforms": ["cpp"], + "targets": ["TAbstract"] + }, + { + "name": "SelfCall", + "metadata": ":selfCall", + "doc": "Translates method calls into calling object directly.", + "platforms": ["js", "lua"], + "targets": ["TClassField"], + "links": ["https://haxe.org/manual/target-javascript-external-libraries.html"] + }, + { + "name": "Semantics", + "metadata": ":semantics", + "doc": "The native semantics of the type.", + "params": ["value | reference | variable"], + "targets": ["TClass", "TTypedef", "TAbstract"] + }, + { + "name": "Setter", + "metadata": ":setter", + "doc": "Generates a native setter function on the given field.", + "platforms": ["flash"], + "params": ["Class field name"], + "targets": ["TClassField"] + }, + { + "name": "SkipCtor", + "metadata": ":skipCtor", + "doc": "Used internally to generate a constructor as if it were a native type (no `__hx_ctor`).", + "platforms": ["java", "cs"], + "internal": true + }, + { + "name": "SkipReflection", + "metadata": ":skipReflection", + "doc": "Used internally to annotate a field that shouldn't have its reflection data generated.", + "platforms": ["java", "cs"], + "targets": ["TClassField"], + "internal": true + }, + { + "name": "Sound", + "metadata": ":sound", + "doc": "Includes a given .wav or .mp3 file into the target SWF and associates it with the class (must extend `flash.media.Sound`).", + "platforms": ["flash"], + "params": ["File path"], + "targets": ["TClass"], + "links": ["https://haxe.org/manual/target-flash-resources.html"] + }, + { + "name": "SourceFile", + "metadata": ":sourceFile", + "doc": "Source code filename for external class.", + "platforms": ["cpp"] + }, + { + "name": "StackOnly", + "metadata": ":stackOnly", + "doc": "Instances of this type can only appear on the stack.", + "platforms": ["cpp"] + }, + { + "name": "StaticExtension", + "metadata": "haxe.internal.static_extension", + "doc": "Used internally to mark static extension fields.", + "internal": true + }, + { + "name": "StoredTypedExpr", + "metadata": ":storedTypedExpr", + "doc": "Used internally to reference a typed expression returned from a macro.", + "internal": true + }, + { + "name": "Strict", + "metadata": ":strict", + "doc": "Used to declare a native C# attribute or a native Java metadata; is type checked.", + "platforms": ["java", "cs"] + }, + { + "name": "Struct", + "metadata": ":struct", + "doc": "Marks a class definition as a struct.", + "platforms": ["cs", "hl"], + "targets": ["TClass"] + }, + { + "name": "StructAccess", + "metadata": ":structAccess", + "doc": "Marks an extern class as using struct access (`.`) not pointer (`->`).", + "platforms": ["cpp"], + "targets": ["TClass"] + }, + { + "name": "StructInit", + "metadata": ":structInit", + "doc": "Allows one to initialize the class with a structure that matches constructor parameters.", + "targets": ["TClass"] + }, + { + "name": "SuppressWarnings", + "metadata": ":suppressWarnings", + "doc": "Adds a `SuppressWarnings` annotation for the generated Java class.", + "platforms": ["java"], + "targets": ["TClass"] + }, + { + "name": "TemplatedCall", + "metadata": ":templatedCall", + "doc": "Indicates that the first parameter of static call should be treated as a template argument.", + "platforms": ["cpp"], + "targets": ["TClassField"] + }, + { + "name": "Throws", + "metadata": ":throws", + "doc": "Adds a `throws` declaration to the generated function.", + "platforms": ["java"], + "params": ["Type as String"], + "targets": ["TClassField"] + }, + { + "name": "This", + "metadata": ":this", + "doc": "Internally used to pass a `this` expression to macros.", + "targets": ["TExpr"], + "internal": true + }, + { + "name": "To", + "metadata": ":to", + "doc": "Specifies that the field of the abstract is a cast operation to the type identified in the function.", + "targets": ["TAbstractField"], + "links": ["https://haxe.org/manual/types-abstract-implicit-casts.html"] + }, + { + "name": "ToString", + "metadata": ":toString", + "doc": "Internally used.", + "internal": true + }, + { + "name": "Transient", + "metadata": ":transient", + "doc": "Adds the `transient` flag to the class field.", + "platforms": ["java"], + "targets": ["TClassField"] + }, + { + "name": "ValueUsed", + "metadata": ":valueUsed", + "doc": "Internally used by DCE to mark an abstract value as used.", + "internal": true + }, + { + "name": "Volatile", + "metadata": ":volatile", + "doc": "", + "platforms": ["java", "cs"] + }, + { + "name": "UnifyMinDynamic", + "metadata": ":unifyMinDynamic", + "doc": "Allows a collection of types to unify to `Dynamic`.", + "targets": ["TClassField"] + }, + { + "name": "Unreflective", + "metadata": ":unreflective", + "doc": "", + "platforms": ["cpp"] + }, + { + "name": "Unsafe", + "metadata": ":unsafe", + "doc": "Declares a class, or a method with the C#'s `unsafe` flag.", + "platforms": ["cs"], + "targets": ["TClass", "TClassField"] + }, + { + "name": "Used", + "metadata": ":used", + "doc": "Internally used by DCE to mark a class or field as used.", + "internal": true + }, + { + "name": "Using", + "metadata": ":using", + "doc": "Automatically uses the argument types as static extensions for the annotated type.", + "targets": ["TClass", "TEnum", "TAbstract"], + "links": ["https://haxe.org/manual/lf-static-extension-metadata.html"] + }, + { + "name": "Value", + "metadata": ":value", + "doc": "Used to store default values for fields and function arguments.", + "targets": ["TClassField"] + }, + { + "name": "Void", + "metadata": ":void", + "doc": "Use Cpp native `void` return type.", + "platforms": ["cpp"] + } +] \ No newline at end of file diff --git a/src/codegen/codegen.ml b/src/codegen/codegen.ml index 9be3814362e..8dee9ca9f06 100644 --- a/src/codegen/codegen.ml +++ b/src/codegen/codegen.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -26,110 +26,6 @@ open Globals (* -------------------------------------------------------------------------- *) (* TOOLS *) -(* Collection of functions that return expressions *) -module ExprBuilder = struct - let make_static_this c p = - let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in - mk (TTypeExpr (TClassDecl c)) ta p - - let make_typeexpr mt pos = - let t = - match mt with - | TClassDecl c -> TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } - | TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) } - | TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) } - | _ -> assert false - in - mk (TTypeExpr mt) t pos - - let make_static_field c cf p = - let e_this = make_static_this c p in - mk (TField(e_this,FStatic(c,cf))) cf.cf_type p - - let make_throw e p = - mk (TThrow e) t_dynamic p - - let make_int com i p = - mk (TConst (TInt (Int32.of_int i))) com.basic.tint p - - let make_float com f p = - mk (TConst (TFloat f)) com.basic.tfloat p - - let make_bool com b p = - mk (TConst(TBool b)) com.basic.tbool p - - let make_string com s p = - mk (TConst (TString s)) com.basic.tstring p - - let make_null t p = - mk (TConst TNull) t p - - let make_local v p = - mk (TLocal v) v.v_type p - - let make_const_texpr com ct p = match ct with - | TString s -> mk (TConst (TString s)) com.basic.tstring p - | TInt i -> mk (TConst (TInt i)) com.basic.tint p - | TFloat f -> mk (TConst (TFloat f)) com.basic.tfloat p - | TBool b -> mk (TConst (TBool b)) com.basic.tbool p - | TNull -> mk (TConst TNull) (com.basic.tnull (mk_mono())) p - | _ -> error "Unsupported constant" p -end - -let field e name t p = - mk (TField (e,try quick_field e.etype name with Not_found -> assert false)) t p - -let fcall e name el ret p = - let ft = tfun (List.map (fun e -> e.etype) el) ret in - mk (TCall (field e name ft p,el)) ret p - -let mk_parent e = - mk (TParenthesis e) e.etype e.epos - -let mk_return e = - mk (TReturn (Some e)) t_dynamic e.epos - -let binop op a b t p = - mk (TBinop (op,a,b)) t p - -let index com e index t p = - mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) com.basic.tint p)) t p - -let maybe_cast e t = - try - type_eq EqDoNotFollowNull e.etype t; - e - with - Unify_error _ -> mk (TCast(e,None)) t e.epos - -let type_constant com c p = - let t = com.basic in - match c with - | Int s -> - if String.length s > 10 && String.sub s 0 2 = "0x" then error "Invalid hexadecimal integer" p; - (try mk (TConst (TInt (Int32.of_string s))) t.tint p - with _ -> mk (TConst (TFloat s)) t.tfloat p) - | Float f -> mk (TConst (TFloat f)) t.tfloat p - | String s -> mk (TConst (TString s)) t.tstring p - | Ident "true" -> mk (TConst (TBool true)) t.tbool p - | Ident "false" -> mk (TConst (TBool false)) t.tbool p - | Ident "null" -> mk (TConst TNull) (t.tnull (mk_mono())) p - | Ident t -> error ("Invalid constant : " ^ t) p - | Regexp _ -> error "Invalid constant" p - -let rec type_constant_value com (e,p) = - match e with - | EConst c -> - type_constant com c p - | EParenthesis e -> - type_constant_value com e - | EObjectDecl el -> - mk (TObjectDecl (List.map (fun (k,e) -> k,type_constant_value com e) el)) (TAnon { a_fields = PMap.empty; a_status = ref Closed }) p - | EArrayDecl el -> - mk (TArrayDecl (List.map (type_constant_value com) el)) (com.basic.tarray t_dynamic) p - | _ -> - error "Constant value expected" p - let rec has_properties c = List.exists (fun f -> match f.cf_kind with @@ -160,7 +56,7 @@ let add_property_field com c = | _ -> let fields,values = List.fold_left (fun (fields,values) (n,v) -> let cf = mk_field n com.basic.tstring p null_pos in - PMap.add n cf fields,((n,null_pos,NoQuotes),ExprBuilder.make_string com v p) :: values + PMap.add n cf fields,((n,null_pos,NoQuotes),Texpr.Builder.make_string com.basic v p) :: values ) (PMap.empty,[]) props in let t = mk_anon fields in let e = mk (TObjectDecl values) t p in @@ -178,48 +74,6 @@ let escape_res_name name allow_dirs = else "-x" ^ (string_of_int (Char.code chr))) name -(* -------------------------------------------------------------------------- *) -(* BUILD META DATA OBJECT *) - -let build_metadata com t = - let api = com.basic in - let p, meta, fields, statics = (match t with - | TClassDecl c -> - let fields = List.map (fun f -> f.cf_name,f.cf_meta) (c.cl_ordered_fields @ (match c.cl_constructor with None -> [] | Some f -> [{ f with cf_name = "_" }])) in - let statics = List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in - (c.cl_pos, ["",c.cl_meta],fields,statics) - | TEnumDecl e -> - (e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, []) - | TTypeDecl t -> - (t.t_pos, ["",t.t_meta],(match follow t.t_type with TAnon a -> PMap.fold (fun f acc -> (f.cf_name,f.cf_meta) :: acc) a.a_fields [] | _ -> []),[]) - | TAbstractDecl a -> - (a.a_pos, ["",a.a_meta],[],[]) - ) in - let filter l = - let l = List.map (fun (n,ml) -> n, ExtList.List.filter_map (fun (m,el,p) -> match m with Meta.Custom s when String.length s > 0 && s.[0] <> ':' -> Some (s,el,p) | _ -> None) ml) l in - List.filter (fun (_,ml) -> ml <> []) l - in - let meta, fields, statics = filter meta, filter fields, filter statics in - let make_meta_field ml = - let h = Hashtbl.create 0 in - mk (TObjectDecl (List.map (fun (f,el,p) -> - if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p; - Hashtbl.add h f (); - (f,null_pos,NoQuotes), mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value com) el)) (api.tarray t_dynamic) p - ) ml)) t_dynamic p - in - let make_meta l = - mk (TObjectDecl (List.map (fun (f,ml) -> (f,null_pos,NoQuotes),make_meta_field ml) l)) t_dynamic p - in - if meta = [] && fields = [] && statics = [] then - None - else - let meta_obj = [] in - let meta_obj = (if fields = [] then meta_obj else (("fields",null_pos,NoQuotes),make_meta fields) :: meta_obj) in - let meta_obj = (if statics = [] then meta_obj else (("statics",null_pos,NoQuotes),make_meta statics) :: meta_obj) in - let meta_obj = (try (("obj",null_pos,NoQuotes), make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in - Some (mk (TObjectDecl meta_obj) t_dynamic p) - let update_cache_dependencies t = let rec check_t m t = match t with | TInst(c,tl) -> @@ -261,108 +115,6 @@ let update_cache_dependencies t = | _ -> () -(* -------------------------------------------------------------------------- *) -(* STACK MANAGEMENT EMULATION *) - -type stack_context = { - stack_var : string; - stack_exc_var : string; - stack_pos_var : string; - stack_pos : pos; - stack_expr : texpr; - stack_pop : texpr; - stack_save_pos : texpr; - stack_restore : texpr list; - stack_push : tclass -> string -> texpr; - stack_return : texpr -> texpr; -} - -let stack_context_init com stack_var exc_var pos_var tmp_var use_add p = - let t = com.basic in - let st = t.tarray t.tstring in - let stack_var = alloc_var stack_var st p in - let exc_var = alloc_var exc_var st p in - let pos_var = alloc_var pos_var t.tint p in - let stack_e = mk (TLocal stack_var) st p in - let exc_e = mk (TLocal exc_var) st p in - let stack_pop = fcall stack_e "pop" [] t.tstring p in - let stack_push c m = - fcall stack_e "push" [ - if use_add then - binop OpAdd (ExprBuilder.make_string com (s_type_path c.cl_path ^ "::") p) (ExprBuilder.make_string com m p) t.tstring p - else - ExprBuilder.make_string com (s_type_path c.cl_path ^ "::" ^ m) p - ] t.tvoid p - in - let stack_return e = - let tmp = alloc_var tmp_var e.etype e.epos in - mk (TBlock [ - mk (TVar (tmp, Some e)) t.tvoid e.epos; - stack_pop; - mk (TReturn (Some (mk (TLocal tmp) e.etype e.epos))) e.etype e.epos - ]) e.etype e.epos - in - { - stack_var = stack_var.v_name; - stack_exc_var = exc_var.v_name; - stack_pos_var = pos_var.v_name; - stack_pos = p; - stack_expr = stack_e; - stack_pop = stack_pop; - stack_save_pos = mk (TVar (pos_var, Some (field stack_e "length" t.tint p))) t.tvoid p; - stack_push = stack_push; - stack_return = stack_return; - stack_restore = [ - binop OpAssign exc_e (mk (TArrayDecl []) st p) st p; - mk (TWhile ( - mk_parent (binop OpGte (field stack_e "length" t.tint p) (mk (TLocal pos_var) t.tint p) t.tbool p), - fcall exc_e "unshift" [fcall stack_e "pop" [] t.tstring p] t.tvoid p, - NormalWhile - )) t.tvoid p; - fcall stack_e "push" [index com exc_e 0 t.tstring p] t.tvoid p - ]; - } - -let stack_init com use_add = - stack_context_init com "$s" "$e" "$spos" "$tmp" use_add null_pos - -let rec stack_block_loop ctx e = - match e.eexpr with - | TFunction _ -> - e - | TReturn None | TReturn (Some { eexpr = TConst _ }) | TReturn (Some { eexpr = TLocal _ }) -> - mk (TBlock [ - ctx.stack_pop; - e; - ]) e.etype e.epos - | TReturn (Some e) -> - ctx.stack_return (stack_block_loop ctx e) - | TTry (v,cases) -> - let v = stack_block_loop ctx v in - let cases = List.map (fun (v,e) -> - let e = stack_block_loop ctx e in - let e = (match (mk_block e).eexpr with - | TBlock l -> mk (TBlock (ctx.stack_restore @ l)) e.etype e.epos - | _ -> assert false - ) in - v , e - ) cases in - mk (TTry (v,cases)) e.etype e.epos - | _ -> - map_expr (stack_block_loop ctx) e - -let stack_block ctx c m e = - match (mk_block e).eexpr with - | TBlock l -> - mk (TBlock ( - ctx.stack_push c m :: - ctx.stack_save_pos :: - List.map (stack_block_loop ctx) l - @ [ctx.stack_pop] - )) e.etype e.epos - | _ -> - assert false - (* -------------------------------------------------------------------------- *) (* FIX OVERRIDES *) @@ -418,7 +170,7 @@ let fix_override com c f fd = end; cur with Unify_error _ -> - let v2 = alloc_var (prefix ^ v.v_name) t2 v.v_pos in + let v2 = alloc_var VGenerated (prefix ^ v.v_name) t2 v.v_pos in changed_args := (v,v2) :: !changed_args; v2,ct ) fd.tf_args targs in @@ -438,7 +190,7 @@ let fix_override com c f fd = ); } in (* as3 does not allow wider visibility, so the base method has to be made public *) - if Common.defined com Define.As3 && f.cf_public then f2.cf_public <- true; + if Common.defined com Define.As3 && has_class_field_flag f CfPublic then add_class_field_flag f2 CfPublic; let targs = List.map (fun(v,c) -> (v.v_name, Option.is_some c, v.v_type)) nargs in let fde = (match f.cf_expr with None -> assert false | Some e -> e) in f.cf_expr <- Some { fde with eexpr = TFunction fd2 }; @@ -506,38 +258,11 @@ let rec is_volatile t = | _ -> false -let set_default ctx a c p = - let t = a.v_type in - let ve = mk (TLocal a) t p in - let cond = TBinop (OpEq,ve,mk (TConst TNull) t p) in - mk (TIf (mk_parent (mk cond ctx.basic.tbool p), mk (TBinop (OpAssign,ve,mk (TConst c) t p)) t p,None)) ctx.basic.tvoid p - let bytes_serialize data = let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in let tbl = Array.init (String.length b64) (fun i -> String.get b64 i) in Bytes.unsafe_to_string (Base64.str_encode ~tbl data) -(* - Tells if the constructor might be called without any issue whatever its parameters -*) -let rec constructor_side_effects e = - match e.eexpr with - | TBinop (op,_,_) when op <> OpAssign -> - true - | TField (_,FEnum _) -> - false - | TUnop _ | TArray _ | TField _ | TEnumParameter _ | TEnumIndex _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ -> - true - | TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _ - | TFunction _ | TArrayDecl _ | TObjectDecl _ - | TParenthesis _ | TTypeExpr _ | TLocal _ | TMeta _ - | TConst _ | TContinue | TBreak | TCast _ | TIdent _ -> - try - Type.iter (fun e -> if constructor_side_effects e then raise Exit) e; - false; - with Exit -> - true - module Dump = struct (* Make a dump of the full typed AST of all types @@ -550,7 +275,7 @@ module Dump = struct close_out ch) let create_dumpfile_from_path com path = - let buf,close = create_dumpfile [] ("dump" :: (platform_name com.platform) :: fst path @ [snd path]) in + let buf,close = create_dumpfile [] ("dump" :: (platform_name_macro com) :: fst path @ [snd path]) in buf,close let dump_types com s_expr = @@ -564,7 +289,7 @@ module Dump = struct let args el = match el with | [] -> "" - | el -> Printf.sprintf "(%s)" (String.concat ", " (List.map (fun e -> Ast.s_expr e) el)) in + | el -> Printf.sprintf "(%s)" (String.concat ", " (List.map (fun e -> Ast.Printer.s_expr e) el)) in match ml with | [] -> "" | ml -> String.concat " " (List.map (fun me -> match me with (m,el,_) -> "@" ^ Meta.to_string m ^ args el) ml) ^ "\n" ^ tabs in @@ -578,7 +303,7 @@ module Dump = struct let rec print_field stat f = print "\n\t%s%s%s%s%s %s%s" (s_metas f.cf_meta "\t") - (if (f.cf_public && not (c.cl_extern || c.cl_interface)) then "public " else "") + (if (has_class_field_flag f CfPublic && not (c.cl_extern || c.cl_interface)) then "public " else "") (if stat then "static " else "") (match f.cf_kind with | Var v when (is_inline_var f.cf_kind) -> "inline " @@ -614,7 +339,6 @@ module Dump = struct print "%s%s%s%s %s%s" (s_metas c.cl_meta "") (if c.cl_private then "private " else "") (if c.cl_extern then "extern " else "") (if c.cl_interface then "interface" else "class") (s_type_path path) (params c.cl_params); (match c.cl_super with None -> () | Some (c,pl) -> print " extends %s" (s_type (TInst (c,pl)))); List.iter (fun (c,pl) -> print " implements %s" (s_type (TInst (c,pl)))) c.cl_implements; - (match c.cl_dynamic with None -> () | Some t -> print " implements Dynamic<%s>" (s_type t)); (match c.cl_array_access with None -> () | Some t -> print " implements ArrayAccess<%s>" (s_type t)); print " {\n"; (match c.cl_constructor with @@ -663,16 +387,39 @@ module Dump = struct close(); ) com.types + let dump_position com = + List.iter (fun mt -> + match mt with + | TClassDecl c -> + let buf,close = create_dumpfile_from_path com (t_path mt) in + Printf.bprintf buf "%s\n" (s_type_path c.cl_path); + let field cf = + Printf.bprintf buf "\t%s\n" cf.cf_name; + begin match cf.cf_expr with + | None -> () + | Some e -> + Printf.bprintf buf "%s\n" (Texpr.dump_with_pos "\t" e); + end + in + Option.may field c.cl_constructor; + List.iter field c.cl_ordered_statics; + List.iter field c.cl_ordered_fields; + close(); + | _ -> + () + ) com.types + let dump_types com = match Common.defined_value_safe com Define.Dump with | "pretty" -> dump_types com (Type.s_expr_pretty false "\t" true) | "legacy" -> dump_types com Type.s_expr | "record" -> dump_record com + | "position" -> dump_position com | _ -> dump_types com (Type.s_expr_ast (not (Common.defined com Define.DumpIgnoreVarIds)) "\t") let dump_dependencies ?(target_override=None) com = let target_name = match target_override with - | None -> platform_name com.platform + | None -> platform_name_macro com | Some s -> s in let buf,close = create_dumpfile [] ["dump";target_name;".dependencies"] in @@ -710,7 +457,7 @@ let default_cast ?(vtmp="$t") com e texpr t p = | TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) } | TTypeDecl _ -> assert false in - let vtmp = alloc_var vtmp e.etype e.epos in + let vtmp = alloc_var VGenerated vtmp e.etype e.epos in let var = mk (TVar (vtmp,Some e)) api.tvoid p in let vexpr = mk (TLocal vtmp) e.etype p in let texpr = mk (TTypeExpr texpr) (mk_texpr texpr) p in @@ -724,12 +471,15 @@ let default_cast ?(vtmp="$t") com e texpr t p = let std = mk (TTypeExpr std) (mk_texpr std) p in let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in + let enull = Texpr.Builder.make_null vexpr.etype p in + let eop = Texpr.Builder.binop OpEq vexpr enull api.tbool p in + let echeck = Texpr.Builder.binop OpBoolOr is eop api.tbool p in let exc = mk (TThrow (mk (TConst (TString "Class cast error")) api.tstring p)) t p in - let check = mk (TIf (mk_parent is,mk (TCast (vexpr,None)) t p,Some exc)) t p in + let check = mk (TIf (Texpr.Builder.mk_parent echeck,mk (TCast (vexpr,None)) t p,Some exc)) t p in mk (TBlock [var;check;vexpr]) t p module UnificationCallback = struct - let tf_stack = ref [] + let tf_stack = new_rec_stack() let check_call_params f el tl = let rec loop acc el tl = match el,tl with @@ -797,7 +547,7 @@ module UnificationCallback = struct | _ -> e end | TReturn (Some e1) -> - begin match !tf_stack with + begin match tf_stack.rec_stack with | tf :: _ -> { e with eexpr = TReturn (Some (f e1 tf.tf_type))} | _ -> e end @@ -806,10 +556,7 @@ module UnificationCallback = struct in match e.eexpr with | TFunction tf -> - tf_stack := tf :: !tf_stack; - let etf = {e with eexpr = TFunction({tf with tf_expr = run f tf.tf_expr})} in - tf_stack := List.tl !tf_stack; - etf + rec_stack_loop tf_stack tf (fun() -> {e with eexpr = TFunction({tf with tf_expr = run f tf.tf_expr})}) () | _ -> check (Type.map_expr (run ff) e) end;; @@ -866,23 +613,8 @@ module ExtClass = struct | Some e' -> c.cl_init <- Some (concat e' e) let add_static_init c cf e p = - let ethis = ExprBuilder.make_static_this c p in + let ethis = Texpr.Builder.make_static_this c p in let ef1 = mk (TField(ethis,FStatic(c,cf))) cf.cf_type p in let e_assign = mk (TBinop(OpAssign,ef1,e)) e.etype p in add_cl_init c e_assign -end - -let for_remap com v e1 e2 p = - let v' = alloc_var v.v_name e1.etype e1.epos in - let ev' = mk (TLocal v') e1.etype e1.epos in - let t1 = (Abstract.follow_with_abstracts e1.etype) in - let ehasnext = mk (TField(ev',quick_field t1 "hasNext")) (tfun [] com.basic.tbool) e1.epos in - let ehasnext = mk (TCall(ehasnext,[])) com.basic.tbool ehasnext.epos in - let enext = mk (TField(ev',quick_field t1 "next")) (tfun [] v.v_type) e1.epos in - let enext = mk (TCall(enext,[])) v.v_type e1.epos in - let eassign = mk (TVar(v,Some enext)) com.basic.tvoid p in - let ebody = Type.concat eassign e2 in - mk (TBlock [ - mk (TVar (v',Some e1)) com.basic.tvoid e1.epos; - mk (TWhile((mk (TParenthesis ehasnext) ehasnext.etype ehasnext.epos),ebody,NormalWhile)) com.basic.tvoid e1.epos; - ]) com.basic.tvoid p \ No newline at end of file +end \ No newline at end of file diff --git a/src/codegen/dotnet.ml b/src/codegen/dotnet.ml index 26f02f33516..14a5c3c195f 100644 --- a/src/codegen/dotnet.ml +++ b/src/codegen/dotnet.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -22,6 +22,7 @@ open Globals open Ast open IlData open IlMeta +open NativeLibraries (* see http://msdn.microsoft.com/en-us/library/2sk3x8a7(v=vs.71).aspx *) let cs_binops = @@ -126,11 +127,11 @@ let netpath_to_hx std = function let lookup_ilclass std com ilpath = let path = netpath_to_hx std ilpath in - List.fold_right (fun (_,_,_,get_raw_class) acc -> + List.fold_right (fun net_lib acc -> match acc with - | None -> get_raw_class path + | None -> net_lib#lookup path | Some p -> acc - ) com.net_libs None + ) com.native_libs.net_libs None let discard_nested = function | (ns,_),cl -> (ns,[]),cl @@ -309,17 +310,17 @@ let convert_ilfield ctx p field = | name -> name in let cff_access = match field.fflags.ff_access with - | FAFamily | FAFamOrAssem -> APrivate - | FAPublic -> APublic + | FAFamily | FAFamOrAssem -> (APrivate,null_pos) + | FAPublic -> (APublic,null_pos) | _ -> raise Exit (* private instances aren't useful on externs *) in let readonly, acc = List.fold_left (fun (readonly,acc) -> function - | CStatic -> readonly, AStatic :: acc + | CStatic -> readonly, (AStatic,null_pos) :: acc | CInitOnly | CLiteral -> true, acc | _ -> readonly,acc ) (false,[cff_access]) field.fflags.ff_contract in if PMap.mem "net_loader_debug" ctx.ncom.defines.Define.values then - Printf.printf "\t%sfield %s : %s\n" (if List.mem AStatic acc then "static " else "") cff_name (IlMetaDebug.ilsig_s field.fsig.ssig); + Printf.printf "\t%sfield %s : %s\n" (if List.mem_assoc AStatic acc then "static " else "") cff_name (IlMetaDebug.ilsig_s field.fsig.ssig); let kind = match readonly with | true -> cff_meta := (Meta.ReadOnly, [], cff_pos) :: !cff_meta; @@ -349,12 +350,12 @@ let convert_ilevent ctx p ev = let name = ev.ename in let kind = FVar (Some (convert_signature ctx p ev.esig.snorm,null_pos), None) in let meta = [Meta.Event, [], p; Meta.Keep,[],p; Meta.SkipReflection,[],p] in - let acc = [APrivate] in + let acc = [APrivate,null_pos] in let add_m acc m = match m with | None -> acc | Some (name,flags) -> if List.mem (CMStatic) flags.mf_contract then - AStatic :: acc + (AStatic,null_pos) :: acc else acc in @@ -392,11 +393,11 @@ let convert_ilmethod ctx p m is_explicit_impl = let meta = [Meta.Overload, [], p] in let acc, meta = match m.mflags.mf_access with | FAFamily | FAFamOrAssem -> - APrivate, ((Meta.Protected, [], p) :: meta) + (APrivate,null_pos), ((Meta.Protected, [], p) :: meta) (* | FAPrivate -> APrivate *) | FAPublic when List.mem SGetter m.msemantics || List.mem SSetter m.msemantics -> - APrivate, meta - | FAPublic -> APublic, meta + (APrivate,null_pos), meta + | FAPublic -> (APublic,null_pos), meta | _ -> if PMap.mem "net_loader_debug" ctx.ncom.defines.Define.values then Printf.printf "\tmethod %s (skipped) : %s\n" cff_name (IlMetaDebug.ilsig_s m.msig.ssig); @@ -404,7 +405,7 @@ let convert_ilmethod ctx p m is_explicit_impl = in let is_static = ref false in let acc, is_final = List.fold_left (fun (acc,is_final) -> function - | CMStatic when cff_name <> "new" -> is_static := true; AStatic :: acc, is_final + | CMStatic when cff_name <> "new" -> is_static := true; (AStatic,null_pos) :: acc, is_final | CMVirtual when is_final = None -> acc, Some false | CMFinal -> acc, Some true | _ -> acc, is_final @@ -412,11 +413,11 @@ let convert_ilmethod ctx p m is_explicit_impl = if PMap.mem "net_loader_debug" ctx.ncom.defines.Define.values then Printf.printf "\t%smethod %s : %s\n" (if !is_static then "static " else "") cff_name (IlMetaDebug.ilsig_s m.msig.ssig); - let meta = match is_final with + let acc = match is_final with | None | Some true when not force_check -> - (Meta.Final,[],p) :: meta + (AFinal,null_pos) :: acc | _ -> - meta + acc in let meta = if is_explicit_impl then (Meta.NoCompletion,[],p) :: (Meta.SkipReflection,[],p) :: meta @@ -469,7 +470,7 @@ let convert_ilmethod ctx p m is_explicit_impl = { tp_name = "M" ^ string_of_int t.tnumber,null_pos; tp_params = []; - tp_constraints = []; + tp_constraints = None; tp_meta = []; } ) m.mtypes in @@ -493,9 +494,9 @@ let convert_ilmethod ctx p m is_explicit_impl = | _ when cff_name = "new" -> acc | Some (path,s) -> match lookup_ilclass ctx.nstd ctx.ncom path with | Some ilcls when not (List.mem SInterface ilcls.cflags.tdf_semantics) -> - AOverride :: acc + (AOverride,null_pos) :: acc | None when ctx.ncom.verbose -> - prerr_endline ("(net-lib) A referenced assembly for path " ^ ilpath_s path ^ " was not found"); + print_endline ("(net-lib) A referenced assembly for path " ^ ilpath_s path ^ " was not found"); acc | _ -> acc in @@ -517,14 +518,14 @@ let convert_ilprop ctx p prop is_explicit_impl = | _ -> None in let cff_access = match pmflags with - | Some { mf_access = FAFamily | FAFamOrAssem } -> APrivate - | Some { mf_access = FAPublic } -> APublic + | Some { mf_access = FAFamily | FAFamOrAssem } -> (APrivate,null_pos) + | Some { mf_access = FAPublic } -> (APublic,null_pos) | _ -> raise Exit (* non-public / protected fields don't interest us *) in let access acc = acc.mf_access in let cff_access = match pmflags with | Some m when List.mem CMStatic m.mf_contract -> - [AStatic;cff_access] + [AStatic,null_pos;cff_access] | _ -> [cff_access] in let get = match prop.pget with @@ -638,7 +639,7 @@ let convert_delegate ctx p ilcls = { tp_name = ("T" ^ string_of_int t.tnumber),null_pos; tp_params = []; - tp_constraints = []; + tp_constraints = None; tp_meta = []; } ) ilcls.ctypes in @@ -661,8 +662,8 @@ let convert_delegate ctx p ilcls = cff_name = name,null_pos; cff_doc = None; cff_pos = p; - cff_meta = [ Meta.Extern,[],p ; Meta.Op, [ (EBinop(op, (EConst(Ident"A"),p), (EConst(Ident"B"),p)),p) ], p ]; - cff_access = [APublic;AInline;AStatic]; + cff_meta = [ Meta.Op, [ (EBinop(op, (EConst(Ident"A"),p), (EConst(Ident"B"),p)),p) ], p ]; + cff_access = [APublic,null_pos;AInline,null_pos;AStatic,null_pos;AExtern,null_pos]; cff_kind = mk_op_fn op name p; } in @@ -694,16 +695,16 @@ let convert_delegate ctx p ilcls = EReturn( Some ( EConst(Ident "this"), p ) ), p ); } in - let fn_new = mk_abstract_fun "new" p fn_new [Meta.Extern] [APublic;AInline] in - let fn_from_hx = mk_abstract_fun "FromHaxeFunction" p fn_from_hx [Meta.Extern;Meta.From] [APublic;AInline;AStatic] in - let fn_asdel = mk_abstract_fun "AsDelegate" p fn_asdel [Meta.Extern] [APublic;AInline] in + let fn_new = mk_abstract_fun "new" p fn_new [] [APublic,null_pos;AInline,null_pos;AExtern,null_pos] in + let fn_from_hx = mk_abstract_fun "FromHaxeFunction" p fn_from_hx [Meta.From] [APublic,null_pos;AInline,null_pos;AStatic,null_pos;AExtern,null_pos] in + let fn_asdel = mk_abstract_fun "AsDelegate" p fn_asdel [] [APublic,null_pos;AInline,null_pos;AExtern,null_pos] in let _, c = netpath_to_hx ctx.nstd ilcls.cpath in EAbstract { d_name = netname_to_hx c,null_pos; d_doc = None; d_params = types; d_meta = mk_metas [Meta.Delegate; Meta.Forward] p; - d_flags = [AIsType (underlying_type,null_pos)]; + d_flags = [AbOver (underlying_type,null_pos)]; d_data = [fn_new;fn_from_hx;fn_asdel;mk_op Ast.OpAdd "Add";mk_op Ast.OpSub "Remove"]; } @@ -725,7 +726,8 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with let is_interface = ref false in List.iter (fun f -> match f with - | SSealed -> meta := (Meta.Final, [], p) :: !meta + | SSealed -> + flags := HFinal :: !flags | SInterface -> is_interface := true; flags := HInterface :: !flags @@ -802,7 +804,7 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with { tp_name = "T" ^ string_of_int p.tnumber,null_pos; tp_params = []; - tp_constraints = []; + tp_constraints = None; tp_meta = []; }) ilcls.ctypes in @@ -817,7 +819,7 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with cff_doc = None; cff_pos = p; cff_meta = []; - cff_access = [APublic;AStatic]; + cff_access = [APublic,null_pos;AStatic,null_pos]; cff_kind = FFun { f_params = params; f_args = [("arg1",null_pos),false,[],Some (thist,null_pos),None;("arg2",null_pos),false,[],Some (thist,null_pos),None]; @@ -1108,52 +1110,57 @@ let normalize_ilcls ctx cls = let add_net_std com file = com.net_std <- file :: com.net_std -let add_net_lib com file std = - let ilctx = ref None in - let netpath_to_hx = netpath_to_hx std in - let real_file = ref file in - let get_ctx () = - match !ilctx with - | Some c -> - c - | None -> - let file = if Sys.file_exists file then - file - else try Common.find_file com file with - | Not_found -> try Common.find_file com (file ^ ".dll") with - | Not_found -> - failwith (".NET lib " ^ file ^ " not found") - in - real_file := file; - let r = PeReader.create_r (open_in_bin file) com.defines.Define.values in - let ctx = PeReader.read r in - let clr_header = PeReader.read_clr_header ctx in - let cache = IlMetaReader.create_cache () in - let meta = IlMetaReader.read_meta_tables ctx clr_header cache in - close_in (r.PeReader.ch); +class net_library com name file_path std = object(self) + inherit [net_lib_type,unit] native_library name file_path + + val mutable ilctx = None + val cache = Hashtbl.create 0 + + method private netpath_to_hx = + netpath_to_hx std + + method load = + let r = PeReader.create_r (open_in_bin file_path) com.defines.Define.values in + let ctx = PeReader.read r in + let clr_header = PeReader.read_clr_header ctx in + let cache = IlMetaReader.create_cache () in + let meta = IlMetaReader.read_meta_tables ctx clr_header cache in + close_in (r.PeReader.ch); + if PMap.mem "net_loader_debug" com.defines.Define.values then + print_endline ("for lib " ^ file_path); + let il_typedefs = Hashtbl.copy meta.il_typedefs in + Hashtbl.clear meta.il_typedefs; + + Hashtbl.iter (fun _ td -> + let path = IlMetaTools.get_path (TypeDef td) in if PMap.mem "net_loader_debug" com.defines.Define.values then - print_endline ("for lib " ^ file); - let il_typedefs = Hashtbl.copy meta.il_typedefs in - Hashtbl.clear meta.il_typedefs; - - Hashtbl.iter (fun _ td -> - let path = IlMetaTools.get_path (TypeDef td) in - if PMap.mem "net_loader_debug" com.defines.Define.values then - Printf.printf "found %s\n" (s_type_path (netpath_to_hx path)); - Hashtbl.replace com.net_path_map (netpath_to_hx path) path; - Hashtbl.replace meta.il_typedefs path td - ) il_typedefs; - let meta = { nstd = std; ncom = com; nil = meta } in - ilctx := Some meta; - meta - in + Printf.printf "found %s\n" (s_type_path (self#netpath_to_hx path)); + Hashtbl.replace com.net_path_map (self#netpath_to_hx path) path; + Hashtbl.replace meta.il_typedefs path td + ) il_typedefs; + let meta = { nstd = std; ncom = com; nil = meta } in + ilctx <- Some meta + + method get_ctx = match ilctx with + | None -> + self#load; + self#get_ctx + | Some ctx -> + ctx + + method close = + () - let cache = Hashtbl.create 0 in - let lookup path = + method list_modules = + Hashtbl.fold (fun path _ acc -> match path with + | _,_ :: _, _ -> acc + | _ -> self#netpath_to_hx path :: acc) (self#get_ctx).nil.il_typedefs [] + + method lookup path : net_lib_type = try Hashtbl.find cache path with | Not_found -> try - let ctx = get_ctx() in + let ctx = self#get_ctx in let ns, n, cl = hxpath_to_net ctx path in let cls = IlMetaTools.convert_class ctx.nil (ns,n,cl) in let cls = normalize_ilcls ctx cls in @@ -1162,38 +1169,31 @@ let add_net_lib com file std = with | Not_found -> Hashtbl.add cache path None; None - in - let all_files () = - Hashtbl.fold (fun path _ acc -> match path with - | _,_ :: _, _ -> acc - | _ -> netpath_to_hx path :: acc) (get_ctx()).nil.il_typedefs [] - in - - let build path = - let p = { pfile = !real_file ^ " @ " ^ s_type_path path; pmin = 0; pmax = 0; } in + method build (path : path) (p : pos) : Ast.package option = + let p = { pfile = file_path ^ " @ " ^ s_type_path path; pmin = 0; pmax = 0; } in let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in let cp = ref [] in let rec build path = try if PMap.mem "net_loader_debug" com.defines.Define.values then Printf.printf "looking up %s\n" (s_type_path path); - match lookup path with + match self#lookup path with | Some({csuper = Some{snorm = LClass( (["System"],[],("Delegate"|"MulticastDelegate")),_)}} as cls) when List.mem SSealed cls.cflags.tdf_semantics -> - let ctx = get_ctx() in + let ctx = self#get_ctx in let hxcls = convert_ilclass ctx p ~delegate:true cls in let delegate = convert_delegate ctx p cls in cp := (hxcls,p) :: (delegate,p) :: !cp; List.iter (fun ilpath -> - let path = netpath_to_hx ilpath in + let path = netpath_to_hx std ilpath in build path ) cls.cnested | Some cls -> - let ctx = get_ctx() in + let ctx = self#get_ctx in let hxcls = convert_ilclass ctx p cls in cp := (hxcls,p) :: !cp; List.iter (fun ilpath -> - let path = netpath_to_hx ilpath in + let path = netpath_to_hx std ilpath in build path ) cls.cnested | _ -> () @@ -1203,20 +1203,43 @@ let add_net_lib com file std = build path; match !cp with | [] -> None - | cp -> Some (!real_file, (pack,cp)) - in - let build path p = - build path - in - com.load_extern_type <- com.load_extern_type @ [build]; - com.net_libs <- (file, std, all_files, lookup) :: com.net_libs + | cp -> Some (pack,cp) + + method get_data = () + + initializer + if std then self#add_flag FlagIsStd +end +let add_net_lib com file std extern = + let real_file = if Sys.file_exists file then + file + else try Common.find_file com file with + | Not_found -> try Common.find_file com (file ^ ".dll") with + | Not_found -> + failwith (".NET lib " ^ file ^ " not found") + in + let net_lib = new net_library com file real_file std in + if extern then net_lib#add_flag FlagIsExtern; + com.native_libs.net_libs <- (net_lib :> (net_lib_type,unit) native_library) :: com.native_libs.net_libs; + CompilationServer.handle_native_lib com net_lib let before_generate com = + (* netcore version *) + let netcore_ver = try Some(PMap.find "netcore_ver" com.defines.Define.values) with Not_found -> None in + (* net version *) - let net_ver = try - int_of_string (PMap.find "net_ver" com.defines.Define.values) - with | Not_found -> + let net_ver = + try + let ver = PMap.find "net_ver" com.defines.Define.values in + try int_of_string ver with Failure _ -> raise (Arg.Bad "Invalid value for -D net-ver. Expected format: xx (e.g. 20, 35, 40, 45)") + with Not_found when netcore_ver != None -> + (* 4.7 was released around .NET core 2.1 *) + (* Note: better version mapping should be implemented some day, + * unless we just wait for .NET unification in october 2020 *) + Common.define_value com Define.NetVer "47"; + 47 + | Not_found -> Common.define_value com Define.NetVer "20"; 20 in @@ -1249,7 +1272,13 @@ let before_generate com = | s -> s in (* look for all dirs that have the digraph NET_TARGET-NET_VER *) - let digraph = net_target ^ "-" ^ string_of_int net_ver in + let digraph = match net_target with + | "netcore" -> + (match netcore_ver with + | None -> failwith (".NET target is defined as netcore but -D netcore-ver is missing"); + | Some(ver) -> net_target ^ "-" ^ ver); + | _ -> net_target ^ "-" ^ string_of_int net_ver in + let matched = ref [] in List.iter (fun f -> try let f = Common.find_file com (f ^ "/" ^ digraph) in @@ -1265,13 +1294,10 @@ let before_generate com = let f = Unix.readdir f in let finsens = String.lowercase f in if String.ends_with finsens ".dll" then - add_net_lib com (path ^ "/" ^ f) true; + add_net_lib com (path ^ "/" ^ f) true false (); loop() with | End_of_file -> Unix.closedir f in loop() - ) !matched; - - (* now force all libraries to initialize *) - List.iter (function (_,_,_,lookup) -> ignore (lookup ([],""))) com.net_libs + ) !matched diff --git a/src/codegen/gencommon/abstractImplementationFix.ml b/src/codegen/gencommon/abstractImplementationFix.ml index 786d87fbbd2..b27949f03ce 100644 --- a/src/codegen/gencommon/abstractImplementationFix.ml +++ b/src/codegen/gencommon/abstractImplementationFix.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/arrayDeclSynf.ml b/src/codegen/gencommon/arrayDeclSynf.ml index 0bc87ef1367..bcdc3f7de6d 100644 --- a/src/codegen/gencommon/arrayDeclSynf.ml +++ b/src/codegen/gencommon/arrayDeclSynf.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/arraySpliceOptimization.ml b/src/codegen/gencommon/arraySpliceOptimization.ml new file mode 100644 index 00000000000..0abeddb94c2 --- /dev/null +++ b/src/codegen/gencommon/arraySpliceOptimization.ml @@ -0,0 +1,40 @@ +open Common +open Type +open Gencommon + +(* + This filter finds lone array.splice(...) calls within blocks + and replaces them with array.spliceVoid(...) calls + that don't allocate additional array for removed items. +*) +let init com = + let rec run e = + match e.eexpr with + | TBlock el -> + let el = List.map (fun e -> + match e.eexpr with + | TCall ({ eexpr = TField (eobj, FInstance ({ cl_path = [],"Array" } as cl, params, { cf_name = "splice" })) } as e_splice, args) -> + let f_spliceVoid = PMap.find "spliceVoid" cl.cl_fields in + let e_spliceVoid = { e_splice with + eexpr = TField (eobj, FInstance (cl, params, f_spliceVoid)); + etype = f_spliceVoid.cf_type; + } in + { e with + eexpr = TCall (e_spliceVoid, args); + etype = com.basic.tvoid; + } + | _ -> + run e + ) el in + { e with eexpr = TBlock el } + | _ -> + Type.map_expr run e + in + run + +let name = "array_splice_synf" +let priority = solve_deps name [DAfter ExpressionUnwrap.priority] + +let configure gen = + let run = init gen.gcon in + gen.gsyntax_filters#add name (PCustom priority) run diff --git a/src/codegen/gencommon/castDetect.ml b/src/codegen/gencommon/castDetect.ml index 381ea646e6a..21a7a0b5d8c 100644 --- a/src/codegen/gencommon/castDetect.ml +++ b/src/codegen/gencommon/castDetect.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -81,10 +81,10 @@ struct let ret_type = match !current_ret_type with | Some(s) -> s | None -> gen.gcon.error "Invalid return outside function declaration." e.epos; assert false in (match eopt with | None when not (ExtType.is_void ret_type) -> - mk_return (null ret_type e.epos) + Texpr.Builder.mk_return (null ret_type e.epos) | None -> e | Some eret -> - mk_return (handle (run eret) ret_type eret.etype)) + Texpr.Builder.mk_return (handle (run eret) ret_type eret.etype)) | TFunction(tfunc) -> let last_ret = !current_ret_type in current_ret_type := Some(tfunc.tf_type); @@ -582,8 +582,19 @@ let select_overload gen applied_f overloads types params = | (t,cf) :: _ -> cf,t,false | _ -> assert false +let rec cur_ctor c tl = + match c.cl_constructor with + | Some ctor -> + ctor, c, tl + | None -> + match c.cl_super with + | None -> + raise Not_found + | Some (sup,stl) -> + cur_ctor sup (List.map (apply_params c.cl_params tl) stl) + let choose_ctor gen cl tparams etl maybe_empty_t p = - let ctor, sup, stl = OverloadingConstructor.cur_ctor cl tparams in + let ctor, sup, stl = cur_ctor cl tparams in (* get returned stl, with Dynamic as t_empty *) let rec get_changed_stl c tl = if c == sup then diff --git a/src/codegen/gencommon/classInstance.ml b/src/codegen/gencommon/classInstance.ml index 13588f5557a..f35e38f1ea9 100644 --- a/src/codegen/gencommon/classInstance.ml +++ b/src/codegen/gencommon/classInstance.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/closuresToClass.ml b/src/codegen/gencommon/closuresToClass.ml index 884e4f45270..d4a3e74020d 100644 --- a/src/codegen/gencommon/closuresToClass.ml +++ b/src/codegen/gencommon/closuresToClass.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -20,6 +20,7 @@ open Option open Common open Globals open Codegen +open Texpr.Builder open Ast open Type open Gencommon @@ -110,7 +111,12 @@ let funct gen t = match follow (run_follow gen t) with let mk_conversion_fun gen e = let args, ret = funct gen e.etype in - let tf_args = List.map (fun (n,o,t) -> alloc_var n t,None) args in + let i = ref 0 in + let tf_args = List.map (fun (n,o,t) -> + let n = if n = "" then ("arg" ^ string_of_int(!i)) else n in + incr i; + alloc_var n t,None) args + in let block, local = match e.eexpr with | TLocal v -> v.v_capture <- true; @@ -187,16 +193,30 @@ let traverse gen ?tparam_anon_decl ?tparam_anon_acc (handle_anon_func:texpr->tfu (match (vv, ve) with | ({ v_extra = Some( _ :: _, _) } as v), Some ({ eexpr = TFunction tf } as f) | ({ v_extra = Some( _ :: _, _) } as v), Some { eexpr = TArrayDecl([{ eexpr = TFunction tf } as f]) | TCall({ eexpr = TIdent "__array__" }, [{ eexpr = TFunction tf } as f]) } -> (* captured transformation *) - ignore(tparam_anon_decl v f { tf with tf_expr = run tf.tf_expr }); + tparam_anon_decl v f { tf with tf_expr = run tf.tf_expr }; { e with eexpr = TBlock([]) } | _ -> Type.map_expr run { e with eexpr = TVar(vv, ve) }) ) - | TLocal ({ v_extra = Some( _ :: _, _) } as v) - | TArray ({ eexpr = TLocal ({ v_extra = Some( _ :: _, _) } as v) }, _) -> (* captured transformation *) + | TBinop(OpAssign, { eexpr = TLocal({ v_extra = Some(_ :: _, _) } as v)}, ({ eexpr= TFunction tf } as f)) when is_some tparam_anon_decl -> + (match tparam_anon_decl with + | None -> assert false + | Some tparam_anon_decl -> + tparam_anon_decl v f { tf with tf_expr = run tf.tf_expr }; + { e with eexpr = TBlock([]) } + ) + | TLocal ({ v_extra = Some( _ :: _, _) } as v) -> + (match tparam_anon_acc with + | None -> Type.map_expr run e + | Some tparam_anon_acc -> tparam_anon_acc v e false) + | TArray ( ({ eexpr = TLocal ({ v_extra = Some( _ :: _, _) } as v) } as expr), _) -> (* captured transformation *) + (match tparam_anon_acc with + | None -> Type.map_expr run e + | Some tparam_anon_acc -> tparam_anon_acc v { expr with etype = e.etype } false) + | TMeta((Meta.Custom ":tparamcall",_,_),({ eexpr=TLocal ({ v_extra = Some( _ :: _, _) } as v) } as expr)) -> (match tparam_anon_acc with | None -> Type.map_expr run e - | Some tparam_anon_acc -> tparam_anon_acc v e) + | Some tparam_anon_acc -> tparam_anon_acc v expr true) | TCall( { eexpr = TField(_, FEnum _) }, _ ) -> Type.map_expr run e (* if a TClosure is being call immediately, there's no need to convert it to a TClosure *) @@ -258,8 +278,9 @@ let traverse gen ?tparam_anon_decl ?tparam_anon_acc (handle_anon_func:texpr->tfu let rec get_type_params acc t = match t with - | TInst(( { cl_kind = KTypeParameter _ } as cl), []) -> - if List.memq cl acc then acc else cl :: acc + | TInst(( { cl_kind = KTypeParameter constraints } as cl), []) -> + let params = List.fold_left get_type_params acc constraints in + List.filter (fun t -> not (List.memq t acc)) (cl :: params) @ acc; | TFun (params,tret) -> List.fold_left get_type_params acc ( tret :: List.map (fun (_,_,t) -> t) params ) | TDynamic t -> @@ -350,7 +371,9 @@ let get_captured expr = *) let configure gen ft = - let handle_anon_func fexpr tfunc mapinfo delegate_type : texpr * (tclass * texpr list) = + let tvar_to_cdecl = Hashtbl.create 0 in + + let handle_anon_func fexpr ?tvar tfunc mapinfo delegate_type : texpr * (tclass * texpr list) = let fexpr = match fexpr.eexpr with | TFunction(_) -> { fexpr with eexpr = TFunction(tfunc) } @@ -381,10 +404,20 @@ let configure gen ft = | Some cf -> cf.cf_name in let cur_line = Lexer.get_error_line fexpr.epos in - let path = (fst gen.gcurrent_path, Printf.sprintf "%s_%s_%d__Fun" (snd gen.gcurrent_path) cfield cur_line) in + let name = match tvar with + | None -> + Printf.sprintf "%s_%s_%d__Fun" (snd gen.gcurrent_path) cfield cur_line + | Some (v) -> + Printf.sprintf "%s_%s_%d__Fun" (snd gen.gcurrent_path) v.v_name cur_line + in + let path = (fst gen.gcurrent_path, name) in let cls = mk_class (get gen.gcurrent_class).cl_module path tfunc.tf_expr.epos in if in_unsafe then cls.cl_meta <- (Meta.Unsafe,[],null_pos) :: cls.cl_meta; + (* forward NativeGen meta for Cs target *) + if (Common.platform gen.gcon Cs) && not(is_hxgen (TClassDecl (get gen.gcurrent_class))) && Meta.has(Meta.NativeGen) (get gen.gcurrent_class).cl_meta then + cls.cl_meta <- (Meta.NativeGen,[],null_pos) :: cls.cl_meta; + if Common.defined gen.gcon Define.EraseGenerics then begin cls.cl_meta <- (Meta.HaxeGeneric,[],null_pos) :: cls.cl_meta end; @@ -435,7 +468,7 @@ let configure gen ft = let pos = cls.cl_pos in let cf = mk_class_field "Delegate" (TFun(fun_args tfunc.tf_args, tfunc.tf_type)) true pos (Method MethNormal) [] in cf.cf_expr <- Some { fexpr with eexpr = TFunction { tfunc with tf_expr = func_expr }; }; - cf.cf_meta <- (Meta.Final,[],pos) :: cf.cf_meta; + add_class_field_flag cf CfFinal; cls.cl_ordered_fields <- cf :: cls.cl_ordered_fields; cls.cl_fields <- PMap.add cf.cf_name cf cls.cl_fields; (* invoke function body: call Delegate function *) @@ -493,7 +526,14 @@ let configure gen ft = cls.cl_fields <- PMap.add invoke_field.cf_name invoke_field cls.cl_fields; cls.cl_overrides <- invoke_field :: cls.cl_overrides; - gen.gadd_to_module (TClassDecl cls) priority; + (match tvar with + | None -> () + | Some ({ v_extra = Some(_ :: _, _) } as v) -> + Hashtbl.add tvar_to_cdecl v.v_id (cls,captured) + | _ -> ()); + + (* set priority as priority + 0.00001 so that this filter runs again *) + gen.gadd_to_module (TClassDecl cls) (priority +. 0.000001); (* if there are no captured variables, we can create a cache so subsequent calls don't need to create a new function *) let expr, clscapt = @@ -541,15 +581,14 @@ let configure gen ft = }, clscapt in - let tvar_to_cdecl = Hashtbl.create 0 in let run = traverse gen ~tparam_anon_decl:(fun v e fn -> - let _, info = handle_anon_func e fn null_map_info None in - Hashtbl.add tvar_to_cdecl v.v_id info + let _, (cls,captured) = handle_anon_func e ~tvar:v fn null_map_info None in + Hashtbl.add tvar_to_cdecl v.v_id (cls,captured) ) - ~tparam_anon_acc:(fun v e -> try + ~tparam_anon_acc:(fun v e in_tparam -> try let cls, captured = Hashtbl.find tvar_to_cdecl v.v_id in let captured = List.sort (fun e1 e2 -> match e1, e2 with | { eexpr = TLocal v1 }, { eexpr = TLocal v2 } -> @@ -587,12 +626,25 @@ let configure gen ft = { e with eexpr = TNew(cls, cltparams, List.rev captured) } with | Not_found -> - gen.gcon.warning "This expression may be invalid" e.epos; - e + if in_tparam then begin + gen.gcon.warning "This expression may be invalid" e.epos; + e + end else + (* It is possible that we are recursively calling a function + that has type parameters. In this case, we must leave it be + because as soon as the new class is added to the module, + this filter will run again. By this time, the tvar-to-cdecl + hashtable will be already filled with all functions, so + it should run correctly. In this case, if it keeps failing. + we will add the "Expression may be invalid warning" like we did + before (see Issue #7118) *) + { e with eexpr = TMeta( + (Meta.Custom(":tparamcall"), [], e.epos), e + ) } | Unify_error el -> List.iter (fun el -> gen.gcon.warning (Error.unify_error_msg (print_context()) el) e.epos) el; - gen.gcon.warning "This expression may be invalid" e.epos; - e + gen.gcon.warning "This expression may be invalid" e.epos; + e ) (* (handle_anon_func:texpr->tfunc->texpr) (dynamic_func_call:texpr->texpr->texpr list->texpr) *) (fun e f info delegate_type -> fst (handle_anon_func e f info delegate_type)) @@ -683,7 +735,7 @@ struct | Some const -> { eexpr = TIf( { elocal with eexpr = TBinop(Ast.OpEq, elocal, null elocal.etype elocal.epos); etype = basic.tbool }, - { elocal with eexpr = TConst(const); etype = const_type basic const t }, + const, Some ( mk_cast t elocal ) ); etype = t; epos = elocal.epos } in @@ -691,7 +743,7 @@ struct if arity >= max_arity then begin let varray = match changed_args with | [v,_] -> v | _ -> assert false in let varray_local = mk_local varray pos in - let mk_varray i = { eexpr = TArray(varray_local, ExprBuilder.make_int gen.gcon i pos); etype = t_dynamic; epos = pos } in + let mk_varray i = { eexpr = TArray(varray_local, make_int gen.gcon.basic i pos); etype = t_dynamic; epos = pos } in let el = snd (List.fold_left (fun (count,acc) (v,const) -> (count + 1, (mk (TVar(v, Some(mk_const const (mk_varray count) v.v_type))) basic.tvoid pos) :: acc) @@ -794,8 +846,8 @@ struct invoke_field.cf_expr <- Some invoke_fun; invoke_field, [ - ExprBuilder.make_int gen.gcon arity pos; - ExprBuilder.make_int gen.gcon type_number pos; + make_int gen.gcon.basic arity pos; + make_int gen.gcon.basic type_number pos; ] in @@ -1028,7 +1080,7 @@ struct let pos = cl.cl_pos in let rec mk_dyn_call arity api = - let zero = ExprBuilder.make_float gen.gcon "0.0" pos in + let zero = make_float gen.gcon.basic "0.0" pos in let rec loop i acc = if i = 0 then acc @@ -1046,7 +1098,7 @@ struct let mk_invoke_switch i api = let t = TFun (func_sig_i i, t_dynamic) in (* case i: return this.invokeX_o(0, 0, 0, 0, 0, ... arg[0], args[1]....); *) - [ExprBuilder.make_int gen.gcon i pos], mk_return (mk (TCall(mk_this (iname i false) t, mk_dyn_call i api)) t_dynamic pos) + [make_int gen.gcon.basic i pos], mk_return (mk (TCall(mk_this (iname i false) t, mk_dyn_call i api)) t_dynamic pos) in let rec loop_cases api arity acc = if arity < 0 then @@ -1067,8 +1119,8 @@ struct in { eexpr = TIf( - mk (TBinop (Ast.OpNotEq, mk_this type_name basic.tint, (ExprBuilder.make_int gen.gcon (if is_float then 0 else 1) pos))) basic.tbool pos, - ExprBuilder.make_throw (mk_arg_exception "Wrong number of arguments" pos) pos, + mk (TBinop (Ast.OpNotEq, mk_this type_name basic.tint, (make_int gen.gcon.basic (if is_float then 0 else 1) pos))) basic.tbool pos, + make_throw (mk_arg_exception "Wrong number of arguments" pos) pos, Some (mk_return call_expr) ); etype = t_dynamic; @@ -1099,7 +1151,7 @@ struct eexpr = TSwitch( switch_cond, loop_cases api !max_arity [], - Some(ExprBuilder.make_throw (mk_arg_exception "Too many arguments" pos) pos)); + Some(make_throw (mk_arg_exception "Too many arguments" pos) pos)); etype = basic.tvoid; epos = pos; } diff --git a/src/codegen/gencommon/dynamicFieldAccess.ml b/src/codegen/gencommon/dynamicFieldAccess.ml index 3d191fc35c6..2ecbc07260d 100644 --- a/src/codegen/gencommon/dynamicFieldAccess.ml +++ b/src/codegen/gencommon/dynamicFieldAccess.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -68,8 +68,8 @@ let configure gen (is_dynamic:texpr->Type.tfield_access->bool) (change_expr:texp (* class types *) | TField(fexpr, f) when is_nondynamic_tparam fexpr f -> (match follow fexpr.etype with - | TInst({ cl_kind = KTypeParameter(tl) }, _) -> - let t = List.find (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl in + | TInst( ({ cl_kind = KTypeParameter(tl) } as tp_cl), tp_tl) -> + let t = apply_params tp_cl.cl_params tp_tl (List.find (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl) in { e with eexpr = TField(mk_cast t (run fexpr), f) } | _ -> assert false) @@ -89,7 +89,7 @@ let configure gen (is_dynamic:texpr->Type.tfield_access->bool) (change_expr:texp assert false with Not_found -> match f with - | FStatic (cl, cf) when Meta.has Meta.Extern cf.cf_meta -> + | FStatic (cl, cf) when has_class_field_flag cf CfExtern -> { e with eexpr = TField ({ fexpr with eexpr = TTypeExpr decl }, FStatic (cl, cf)) } | _ -> change_expr e { fexpr with eexpr = TTypeExpr decl } (field_name f) None true) diff --git a/src/codegen/gencommon/dynamicOperators.ml b/src/codegen/gencommon/dynamicOperators.ml index 64b6925e51b..538a9a06818 100644 --- a/src/codegen/gencommon/dynamicOperators.ml +++ b/src/codegen/gencommon/dynamicOperators.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -20,6 +20,7 @@ open Common open Ast open Type open Codegen +open Texpr.Builder open Gencommon (* ******************************************* *) @@ -65,9 +66,9 @@ open Gencommon let init com handle_strings (should_change:texpr->bool) (equals_handler:texpr->texpr->texpr) (dyn_plus_handler:texpr->texpr->texpr->texpr) (compare_handler:Ast.binop->texpr->texpr->texpr->texpr) = let get_etype_one e = if like_int e.etype then - ExprBuilder.make_int com 1 e.epos + make_int com.basic 1 e.epos else - ExprBuilder.make_float com "1.0" e.epos + make_float com.basic "1.0" e.epos in let rec run e = match e.eexpr with @@ -144,28 +145,36 @@ let init com handle_strings (should_change:texpr->bool) (equals_handler:texpr->t | TField (fexpr, field) -> let tmp = mk_temp "getvar" fexpr.etype in let var = mk (TVar (tmp, Some (run fexpr))) com.basic.tvoid e.epos in - ([var], mk (TField (ExprBuilder.make_local tmp fexpr.epos, field)) etype e1.epos) + ([var], mk (TField (make_local tmp fexpr.epos, field)) etype e1.epos) | _ -> ([], e1) in match flag with | Prefix -> vars @ [ - mk_cast etype { e with eexpr = TBinop(OpAssign, getvar, Codegen.binop op (mk_cast etype getvar) one etype e.epos); etype = getvar.etype } + mk_cast etype { e with eexpr = TBinop(OpAssign, getvar, binop op (mk_cast etype getvar) one etype e.epos); etype = getvar.etype } ] | Postfix -> let ret = mk_temp "ret" etype in - let retlocal = ExprBuilder.make_local ret e.epos in + let retlocal = make_local ret e.epos in vars @ [ mk (TVar (ret, Some (mk_cast etype getvar))) com.basic.tvoid e.epos; - { e with eexpr = TBinop (OpAssign, getvar, Codegen.binop op retlocal one getvar.etype e.epos) }; + { e with eexpr = TBinop (OpAssign, getvar, binop op retlocal one getvar.etype e.epos) }; retlocal ] in mk (TBlock block) etype e.epos | TUnop (op, flag, e1) when should_change e -> - let etype = match op with Not -> com.basic.tbool | _ -> com.basic.tint in + let etype = match op with + | Not -> com.basic.tbool + | Neg -> + if like_float e.etype || like_i64 e.etype then + e.etype + else + com.basic.tfloat + | _ -> com.basic.tint + in mk_parent (mk (TUnop (op, flag, mk_cast etype (run e1))) etype e.epos) | _ -> diff --git a/src/codegen/gencommon/enumToClass.ml b/src/codegen/gencommon/enumToClass.ml index 635dabc10ad..b4331cd6de7 100644 --- a/src/codegen/gencommon/enumToClass.ml +++ b/src/codegen/gencommon/enumToClass.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,6 +21,7 @@ open Globals open Ast open Type open Codegen +open Texpr.Builder open Gencommon (* ******************************************* *) @@ -79,7 +80,7 @@ struct let cl = mk_class en.e_module en.e_path pos in Hashtbl.add t.ec_tbl en.e_path cl; - (match Codegen.build_metadata gen.gcon (TEnumDecl en) with + (match Texpr.build_metadata gen.gcon.basic (TEnumDecl en) with | Some expr -> let cf = mk_class_field "__meta__" expr.etype false expr.epos (Var { v_read = AccNormal; v_write = AccNormal }) [] in cf.cf_expr <- Some expr; @@ -137,13 +138,13 @@ struct let cf = mk_class_field name ef_type true pos (Method MethNormal) cf_params in cf.cf_meta <- []; - let tf_args = List.map (fun (name,opt,t) -> (alloc_var name t, if opt then Some TNull else None) ) params in + let tf_args = List.map (fun (name,opt,t) -> (alloc_var name t, if opt then Some (Texpr.Builder.make_null t null_pos) else None) ) params in let arr_decl = mk_nativearray_decl gen t_dynamic (List.map (fun (v,_) -> mk_local v pos) tf_args) pos in let expr = { eexpr = TFunction({ tf_args = tf_args; tf_type = ret; - tf_expr = mk_block ( mk_return { eexpr = TNew(cl,List.map snd dup_types, [ExprBuilder.make_int gen.gcon old_i pos; arr_decl] ); etype = TInst(cl, List.map snd dup_types); epos = pos } ); + tf_expr = mk_block ( mk_return { eexpr = TNew(cl,List.map snd dup_types, [make_int gen.gcon.basic old_i pos; arr_decl] ); etype = TInst(cl, List.map snd dup_types); epos = pos } ); }); etype = ef_type; epos = pos @@ -157,9 +158,9 @@ struct in let cf = mk_class_field name actual_t true pos (Var { v_read = AccNormal; v_write = AccNever }) [] in let args = if has_params then - [ExprBuilder.make_int gen.gcon old_i pos; null (gen.gclasses.nativearray t_dynamic) pos] + [make_int gen.gcon.basic old_i pos; null (gen.gclasses.nativearray t_dynamic) pos] else - [ExprBuilder.make_int gen.gcon old_i pos] + [make_int gen.gcon.basic old_i pos] in cf.cf_meta <- [Meta.ReadOnly,[],pos]; cf.cf_expr <- Some { @@ -181,7 +182,7 @@ struct let getTag_cf_type = tfun [] basic.tstring in let getTag_cf = mk_class_field "getTag" getTag_cf_type true pos (Method MethNormal) [] in - getTag_cf.cf_meta <- [(Meta.Final, [], pos)]; + add_class_field_flag getTag_cf CfFinal; getTag_cf.cf_expr <- Some { eexpr = TFunction { tf_args = []; @@ -287,7 +288,7 @@ struct f in let cond_array = { (mk_field_access gen f "params" f.epos) with etype = gen.gclasses.nativearray t_dynamic } in - Codegen.index gen.gcon cond_array i e.etype e.epos + index gen.gcon.basic cond_array i e.etype e.epos | _ -> Type.map_expr run e in diff --git a/src/codegen/gencommon/enumToClass2.ml b/src/codegen/gencommon/enumToClass2.ml index d39771c6c9c..1c4ebef2a43 100644 --- a/src/codegen/gencommon/enumToClass2.ml +++ b/src/codegen/gencommon/enumToClass2.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -19,7 +19,7 @@ open Common open Ast open Codegen -open Codegen.ExprBuilder +open Texpr.Builder open Type open Gencommon @@ -37,7 +37,7 @@ let add_meta com en cl_enum = let cf_meta = mk_field "__meta__" expr.etype expr.epos expr.epos in cf_meta.cf_expr <- Some expr; add_static cl_enum cf_meta; - ) (Codegen.build_metadata com (TEnumDecl en)); + ) (Texpr.build_metadata com.basic (TEnumDecl en)); type enclasses = { base : tclass; @@ -68,7 +68,7 @@ module EnumToClass2Modf = struct (* add constructs field (for reflection) *) if has_feature gen.gcon "Type.getEnumConstructs" then begin - let e_constructs = mk_array_decl basic.tstring (List.map (fun s -> make_string gen.gcon s pos) en.e_names) pos in + let e_constructs = mk_array_decl basic.tstring (List.map (fun s -> make_string gen.gcon.basic s pos) en.e_names) pos in let cf_constructs = mk_field "__hx_constructs" e_constructs.etype pos pos in cf_constructs.cf_kind <- Var { v_read = AccNormal; v_write = AccNever }; cf_constructs.cf_meta <- (Meta.ReadOnly,[],pos) :: (Meta.Protected,[],pos) :: cf_constructs.cf_meta; @@ -85,7 +85,7 @@ module EnumToClass2Modf = struct let e_pack, e_name = en.e_path in let cl_enum_t = TInst (cl_enum, []) in let cf_getTag_t = tfun [] basic.tstring in - let cf_getParams_ret = basic.tarray basic.tstring in + let cf_getParams_ret = basic.tarray (mk_anon PMap.empty) in let cf_getParams_t = tfun [] cf_getParams_ret in let static_ctors = ref [] in let ctors_map = ref PMap.empty in @@ -94,18 +94,18 @@ module EnumToClass2Modf = struct let pos = ef.ef_pos in let cl_ctor = mk_class en.e_module (e_pack, e_name ^ "_" ^ name) pos in + cl_ctor.cl_final <- true; cl_ctor.cl_super <- Some (cl_enum, []); cl_ctor.cl_meta <- [ (Meta.Enum,[],pos); (Meta.NativeGen,[],pos); - (Meta.Final,[],pos); ] @ cl_ctor.cl_meta; ctors_map := PMap.add name cl_ctor !ctors_map; gen.gadd_to_module (TClassDecl cl_ctor) max_dep; let esuper = mk (TConst TSuper) cl_enum_t pos in - let etag = make_string gen.gcon name pos in + let etag = make_string gen.gcon.basic name pos in let efields = ref [] in (match follow ef.ef_type with | TFun(_, _) -> @@ -146,7 +146,7 @@ module EnumToClass2Modf = struct ctor_args := (ctor_arg_v, None) :: !ctor_args; (* generate assignment for the constructor *) - let assign = Codegen.binop OpAssign efield (mk_local ctor_arg_v pos) t pos in + let assign = binop OpAssign efield (mk_local ctor_arg_v pos) t pos in ctor_block := assign :: !ctor_block; (* generate an enumEq check for the Equals method (TODO: extract this) *) @@ -154,13 +154,13 @@ module EnumToClass2Modf = struct let e_enumeq_check = mk (TCall (enumeq, [efield; eotherfield])) basic.tbool pos in let e_param_check = mk (TIf (mk (TUnop (Not, Prefix, e_enumeq_check)) basic.tbool pos, - mk_return (make_bool gen.gcon false pos), + mk_return (make_bool gen.gcon.basic false pos), None) ) basic.tvoid pos in param_equal_checks := e_param_check :: !param_equal_checks; ) (List.rev params); - ctor_block := (mk (TCall(esuper,[make_int gen.gcon index pos])) basic.tvoid pos) :: !ctor_block; + ctor_block := (mk (TCall(esuper,[make_int gen.gcon.basic index pos])) basic.tvoid pos) :: !ctor_block; let cf_ctor_t = TFun (params, basic.tvoid) in let cf_ctor = mk_class_field "new" cf_ctor_t true pos (Method MethNormal) [] in @@ -214,18 +214,18 @@ module EnumToClass2Modf = struct let equals_exprs = ref (List.rev [ mk (TIf ( mk (TCall(refeq,[ethis;eother_local])) basic.tbool pos, - mk_return (make_bool gen.gcon true pos), + mk_return (make_bool gen.gcon.basic true pos), None )) basic.tvoid pos; mk (TVar(other_en_v, Some ecast)) basic.tvoid pos; mk (TIf( mk (TBinop(OpEq,other_en_local,make_null cl_ctor_t pos)) basic.tbool pos, - mk_return (make_bool gen.gcon false pos), + mk_return (make_bool gen.gcon.basic false pos), None )) basic.tvoid pos; ]) in equals_exprs := (List.rev !param_equal_checks) @ !equals_exprs; - equals_exprs := mk_return (make_bool gen.gcon true pos) :: !equals_exprs; + equals_exprs := mk_return (make_bool gen.gcon.basic true pos) :: !equals_exprs; let cf_Equals_t = TFun([("other",false,t_dynamic)],basic.tbool) in let cf_Equals = mk_class_field "Equals" cf_Equals_t true pos (Method MethNormal) [] in @@ -250,7 +250,7 @@ module EnumToClass2Modf = struct tf_args = []; tf_type = basic.tint; tf_expr = mk_block (mk_return ( - mk (TCall(eparamsGetHashCode, [make_int gen.gcon index pos;etoString_args])) basic.tint pos + mk (TCall(eparamsGetHashCode, [make_int gen.gcon.basic index pos;etoString_args])) basic.tint pos )); }; etype = cf_GetHashCode_t; @@ -266,7 +266,7 @@ module EnumToClass2Modf = struct eexpr = TFunction { tf_args = []; tf_type = basic.tvoid; - tf_expr = mk (TBlock [mk (TCall(esuper,[make_int gen.gcon index pos])) basic.tvoid pos]) basic.tvoid pos; + tf_expr = mk (TBlock [mk (TCall(esuper,[make_int gen.gcon.basic index pos])) basic.tvoid pos]) basic.tvoid pos; }; etype = cf_ctor_t; epos = pos; @@ -349,7 +349,7 @@ module EnumToClass2Exprf = struct let mk_converted_enum_index_access f = let cl = (get_converted_enum_classes f.etype).base in let e_enum = { f with etype = TInst (cl, []) } in - Codegen.field e_enum "_hx_index" com.basic.tint e.epos + field e_enum "_hx_index" com.basic.tint e.epos in match e.eexpr with | TEnumIndex f -> @@ -378,7 +378,7 @@ module EnumToClass2Exprf = struct (match ef.ef_type with | TFun (params, _) -> let fname, _, _ = List.nth params i in - Codegen.field ecast fname e.etype e.epos + field ecast fname e.etype e.epos | _ -> assert false) | _ -> Type.map_expr run e diff --git a/src/codegen/gencommon/expressionUnwrap.ml b/src/codegen/gencommon/expressionUnwrap.ml index e2d3142b32e..1a4d2be9f26 100644 --- a/src/codegen/gencommon/expressionUnwrap.ml +++ b/src/codegen/gencommon/expressionUnwrap.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -292,7 +292,7 @@ and expr_kind expr = | TObjectDecl (sel) -> aggregate true (List.map snd sel) | TCast (e,_) -> - aggregate true [e] + aggregate false [e] | _ -> trace (debug_expr expr); assert false (* should have been read as Statement by shallow_expr_type *) let get_kinds (statement:texpr) = @@ -494,7 +494,7 @@ let try_call_unwrap_statement com handle_cast problematic_expression_unwrap (add | _ when ExtType.is_void e.etype -> { e with eexpr = TBlock([e; { e with eexpr = TReturn None }]) } | _ -> - Codegen.mk_return e + Texpr.Builder.mk_return e ) e ) in diff --git a/src/codegen/gencommon/filterClosures.ml b/src/codegen/gencommon/filterClosures.ml index c28b5fed9da..1f2308a2d2a 100644 --- a/src/codegen/gencommon/filterClosures.ml +++ b/src/codegen/gencommon/filterClosures.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/fixOverrides.ml b/src/codegen/gencommon/fixOverrides.ml index 007c24eebb7..002702543b6 100644 --- a/src/codegen/gencommon/fixOverrides.ml +++ b/src/codegen/gencommon/fixOverrides.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -101,7 +101,7 @@ let run ~explicit_fn_name ~get_vmtype gen = | _, TDynamic _ -> false | r1, r2 -> try unify r1 r2; - true + if like_int r1 then like_int r2 else true with | Unify_error _ -> false in (* we only have to worry about non-covariant issues *) @@ -126,6 +126,10 @@ let run ~explicit_fn_name ~get_vmtype gen = in let p = f2.cf_pos in let newf = mk_class_field name real_ftype true f.cf_pos (Method MethNormal) f.cf_params in + (* make sure that there isn't already an overload with the same exact type *) + if List.exists (fun (t,f2) -> + type_iseq (get_real_fun gen t) real_ftype + ) overloads then raise Not_found; let vars = List.map (fun (n,_,t) -> alloc_var n t) a2 in let args = List.map2 (fun v (_,_,t) -> mk_cast t (mk_local v f2.cf_pos)) vars a1 in @@ -138,7 +142,7 @@ let run ~explicit_fn_name ~get_vmtype gen = eexpr = TFunction({ tf_args = List.map (fun v -> v,None) vars; tf_type = r2; - tf_expr = if is_void then call else (mk_return (mk_cast r2 call)); + tf_expr = if is_void then call else (Texpr.Builder.mk_return (mk_cast r2 call)); }); etype = real_ftype; epos = p; @@ -203,12 +207,12 @@ let run ~explicit_fn_name ~get_vmtype gen = f.cf_meta <- (Meta.Overload, [], f.cf_pos) :: f.cf_meta; if Meta.has Meta.Overload f.cf_meta then begin (* if it is overload, create another field with the requested type *) - let f3 = mk_class_field f.cf_name t f.cf_public f.cf_pos f.cf_kind f.cf_params in + let f3 = mk_class_field f.cf_name t (has_class_field_flag f CfPublic) f.cf_pos f.cf_kind f.cf_params in let p = f.cf_pos in let old_args, old_ret = get_fun f.cf_type in let args, ret = get_fun t in let tf_args = List.rev new_args in - let f3_mk_return = if ExtType.is_void ret then (fun e -> e) else (fun e -> mk_return (mk_cast ret e)) in + let f3_mk_return = if ExtType.is_void ret then (fun e -> e) else (fun e -> Texpr.Builder.mk_return (mk_cast ret e)) in f3.cf_expr <- Some { eexpr = TFunction({ tf_args = tf_args; diff --git a/src/codegen/gencommon/gencommon.ml b/src/codegen/gencommon/gencommon.ml index 4111a72b520..c05245c3720 100644 --- a/src/codegen/gencommon/gencommon.ml +++ b/src/codegen/gencommon/gencommon.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -118,9 +118,9 @@ let follow_once t = let t_empty = TAnon({ a_fields = PMap.empty; a_status = ref Closed }) -let alloc_var n t = Type.alloc_var n t null_pos +let alloc_var n t = Type.alloc_var VGenerated n t null_pos -let mk_local = ExprBuilder.make_local +let mk_local = Texpr.Builder.make_local (* the undefined is a special var that works like null, but can have special meaning *) let undefined = @@ -136,7 +136,7 @@ let debug_expr = s_expr debug_type let debug_mode = ref false let trace s = if !debug_mode then print_endline s else () -let timer name = if !debug_mode then Common.timer name else fun () -> () +let timer name = if !debug_mode then Timer.timer name else fun () -> () let is_string t = match follow t with @@ -186,7 +186,7 @@ let mk_castfast t e = { e with eexpr = TCast(e, Some (TClassDecl null_class)); e let mk_static_field_access_infer cl field pos params = try - let e_type = ExprBuilder.make_static_this cl pos in + let e_type = Texpr.Builder.make_static_this cl pos in let cf = PMap.find field cl.cl_statics in let t = if params = [] then cf.cf_type else apply_params cf.cf_params params cf.cf_type in mk (TField(e_type, FStatic(cl, cf))) t pos @@ -302,7 +302,7 @@ class ['tp, 'ret] rule_dispatcher name = if key < priority then begin let q = Hashtbl.find tbl key in Stack.iter (fun (n, rule) -> - let t = if !debug_mode then Common.timer [("rule dispatcher rule: " ^ n)] else fun () -> () in + let t = if !debug_mode then Timer.timer [("rule dispatcher rule: " ^ n)] else fun () -> () in let r = rule(tp) in t(); if is_some r then begin ret := r; raise Exit end @@ -362,7 +362,7 @@ class ['tp] rule_map_dispatcher name = object(self) let q = Hashtbl.find tbl key in Stack.iter (fun (n, rule) -> trace ("running rule " ^ n); - let t = if !debug_mode then Common.timer [("rule map dispatcher rule: " ^ n)] else fun () -> () in + let t = if !debug_mode then Timer.timer [("rule map dispatcher rule: " ^ n)] else fun () -> () in cur := rule !cur; t(); ) q @@ -550,7 +550,12 @@ let new_ctx con = | TClassDecl cl -> Hashtbl.add types cl.cl_path mt | TEnumDecl e -> Hashtbl.add types e.e_path mt | TTypeDecl t -> Hashtbl.add types t.t_path mt - | TAbstractDecl a -> Hashtbl.add types a.a_path mt + | TAbstractDecl a -> + (* There are some cases where both an abstract and a class + have the same name (e.g. java.lang.Double/Integer/etc) + in this case we generally want the class to have priority *) + if not (Hashtbl.mem types a.a_path) then + Hashtbl.add types a.a_path mt ) con.types; let get_type path = @@ -719,7 +724,7 @@ let run_filters gen = let has_errors = ref false in gen.gcon.error <- (fun msg pos -> has_errors := true; last_error msg pos); (* first of all, we have to make sure that the filters won't trigger a major Gc collection *) - let t = Common.timer ["gencommon_filters"] in + let t = Timer.timer ["gencommon_filters"] in (if Common.defined gen.gcon Define.GencommonDebug then debug_mode := true else debug_mode := false); let run_filters (filter : texpr rule_map_dispatcher) = let rec loop acc mds = @@ -815,7 +820,7 @@ let write_file gen w source_dir path extension out_files = let t = timer ["write";"file"] in let s_path = source_dir ^ "/" ^ (snd path) ^ "." ^ (extension) in (* create the folders if they don't exist *) - mkdir_from_path s_path; + Path.mkdir_from_path s_path; let contents = SourceWriter.contents w in let should_write = if not (Common.defined gen.gcon Define.ReplaceFiles) && Sys.file_exists s_path then begin @@ -942,19 +947,19 @@ let dump_descriptor gen name path_s module_s = file in if Common.platform gen.gcon Java then - List.iter (fun (s,std,_,_,_) -> - if not std then begin - SourceWriter.write w (path s ".jar"); + List.iter (fun java_lib -> + if not (java_lib#has_flag NativeLibraries.FlagIsStd) && not (java_lib#has_flag NativeLibraries.FlagIsExtern) then begin + SourceWriter.write w (path java_lib#get_file_path ".jar"); SourceWriter.newline w; end - ) gen.gcon.java_libs + ) gen.gcon.native_libs.java_libs else if Common.platform gen.gcon Cs then - List.iter (fun (s,std,_,_) -> - if not std then begin - SourceWriter.write w (path s ".dll"); + List.iter (fun net_lib -> + if not (net_lib#has_flag NativeLibraries.FlagIsStd) && not (net_lib#has_flag NativeLibraries.FlagIsExtern) then begin + SourceWriter.write w (path net_lib#get_name ".dll"); SourceWriter.newline w; end - ) gen.gcon.net_libs; + ) gen.gcon.native_libs.net_libs; SourceWriter.write w "end libs"; SourceWriter.newline w; let args = gen.gcon.c_args in @@ -1078,8 +1083,7 @@ let rec replace_mono t = (* helper *) let mk_class_field name t public pos kind params = - let f = mk_field name t pos null_pos in - f.cf_public <- public; + let f = mk_field name ~public t pos null_pos in f.cf_meta <- [ Meta.CompilerGenerated, [], null_pos ]; (* annotate that this class field was generated by the compiler *) f.cf_kind <- kind; f.cf_params <- params; @@ -1246,7 +1250,7 @@ let rec field_access gen (t:t) (field:string) : (tfield_access) = | _ -> FNotFound let field_access_esp gen t field = match field with - | FStatic(cl,cf) | FInstance(cl,_,cf) when Meta.has Meta.Extern cf.cf_meta -> + | FStatic(cl,cf) | FInstance(cl,_,cf) when has_class_field_flag cf CfExtern -> let static = match field with | FStatic _ -> true | _ -> false @@ -1310,6 +1314,6 @@ let get_type gen path = try Hashtbl.find gen.gtypes path with | Not_found -> raise (TypeNotFound path) -let fun_args (l : (tvar * tconstant option) list)= +let fun_args l = List.map (fun (v,s) -> (v.v_name, (s <> None), v.v_type)) l diff --git a/src/codegen/gencommon/hardNullableSynf.ml b/src/codegen/gencommon/hardNullableSynf.ml index b9765f32ea4..9dc0070cfb3 100644 --- a/src/codegen/gencommon/hardNullableSynf.ml +++ b/src/codegen/gencommon/hardNullableSynf.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/initFunction.ml b/src/codegen/gencommon/initFunction.ml index a420d01d9da..4f10bd83711 100644 --- a/src/codegen/gencommon/initFunction.ml +++ b/src/codegen/gencommon/initFunction.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -19,6 +19,7 @@ open Common open Type open Codegen +open Texpr.Builder open Gencommon (* @@ -88,14 +89,14 @@ let handle_class com cl = | Some e -> (match cf.cf_params with | [] -> - let var = mk (TField (ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf))) cf.cf_type cf.cf_pos in + let var = mk (TField (make_static_this cl cf.cf_pos, FStatic(cl,cf))) cf.cf_type cf.cf_pos in let ret = binop Ast.OpAssign var e cf.cf_type cf.cf_pos in cf.cf_expr <- None; ret :: acc | _ -> let params = List.map (fun _ -> t_dynamic) cf.cf_params in let fn = apply_params cf.cf_params params in - let var = mk (TField (ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf))) (fn cf.cf_type) cf.cf_pos in + let var = mk (TField (make_static_this cl cf.cf_pos, FStatic(cl,cf))) (fn cf.cf_type) cf.cf_pos in let rec change_expr e = Type.map_expr_type change_expr fn (fun v -> v.v_type <- fn v.v_type; v) e in @@ -200,16 +201,18 @@ let handle_class com cl = | TBlock(hd :: tl) -> (match hd.eexpr with | TCall ({ eexpr = TConst TSuper }, _) -> + let tl_block = { e with eexpr = TBlock(tl) } in if not (OverloadingConstructor.descends_from_native_or_skipctor cl) then - { e with eexpr = TBlock (vars @ (hd :: (funs @ tl))) } + { e with eexpr = TBlock (vars @ (hd :: (funs @ [tl_block]))) } else - { e with eexpr = TBlock (hd :: (vars @ funs @ tl)) } + { e with eexpr = TBlock (hd :: (vars @ funs @ [tl_block])) } | TBlock _ -> - { e with eexpr = TBlock ((add_fn hd) :: tl) } + let tl_block = { e with eexpr = TBlock(tl) } in + { e with eexpr = TBlock ((add_fn hd) :: [tl_block]) } | _ -> - { e with eexpr = TBlock (vars @ funs @ (hd :: tl)) }) + { e with eexpr = TBlock (vars @ funs @ [{ e with eexpr = TBlock(hd :: tl) }]) }) | _ -> - Type.concat { e with eexpr = TBlock (vars @ funs) } e + Type.concat { e with eexpr = TBlock (vars @ funs) } { e with eexpr = TBlock([e]) } in let tf_expr = add_fn (mk_block tf.tf_expr) in { e with eexpr = TFunction { tf with tf_expr = tf_expr } } diff --git a/src/codegen/gencommon/intDivisionSynf.ml b/src/codegen/gencommon/intDivisionSynf.ml index 87bbc2d34f4..71d51618976 100644 --- a/src/codegen/gencommon/intDivisionSynf.ml +++ b/src/codegen/gencommon/intDivisionSynf.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -30,41 +30,51 @@ open Gencommon it will be one of the last modules to run *) let init com = - let rec is_int t = - match follow t with - | TInst ({ cl_path = (["haxe";"lang"],"Null") }, [t]) -> - is_int t - | t -> - like_int t && not (like_i64 t) + let rec is_int e = + let rec is_int_type t = + match follow t with + | TInst ({ cl_path = (["haxe";"lang"],"Null") }, [t]) -> + is_int_type t + | t -> + like_int t && not (like_i64 t) + in + is_int_type e.etype || begin + match e.eexpr with + | TUnop (_, _, e) -> is_int e + | _ -> false + end in - let is_exactly_int t = - match follow t with + let rec is_exactly_int e = + match follow e.etype with | TAbstract ({ a_path = ([],"Int") }, []) -> true - | _ -> false + | _ -> + match e.eexpr with + | TUnop (_, _, e) -> is_exactly_int e + | _ -> false in let rec run e = match e.eexpr with - | TBinop ((OpDiv as op), e1, e2) when is_int e1.etype && is_int e2.etype -> + | TBinop ((OpDiv as op), e1, e2) when is_int e1 && is_int e2 -> { e with eexpr = TBinop (op, mk_cast com.basic.tfloat (run e1), run e2) } | TCall ( { eexpr = TField (_, FStatic ({ cl_path = ([], "Std") }, { cf_name = "int" })) }, [ { eexpr = TBinop ((OpDiv as op), e1, e2) } as ebinop ] - ) when is_int e1.etype && is_int e2.etype -> + ) when is_int e1 && is_int e2 -> let e = { ebinop with eexpr = TBinop (op, run e1, run e2); etype = com.basic.tint } in - if not (is_exactly_int e1.etype && is_exactly_int e2.etype) then + if not (is_exactly_int e1 && is_exactly_int e2) then mk_cast com.basic.tint e else - e + Type.map_expr run e | TCast ({ eexpr = TBinop((OpDiv as op), e1, e2) } as ebinop, _ ) - | TCast ({ eexpr = TBinop(((OpAssignOp OpDiv) as op), e1, e2) } as ebinop, _ ) when is_int e1.etype && is_int e2.etype && is_int e.etype -> + | TCast ({ eexpr = TBinop(((OpAssignOp OpDiv) as op), e1, e2) } as ebinop, _ ) when is_int e1 && is_int e2 && is_int e -> let ret = { ebinop with eexpr = TBinop (op, run e1, run e2); etype = e.etype } in - if not (is_exactly_int e1.etype && is_exactly_int e2.etype) then + if not (is_exactly_int e1 && is_exactly_int e2) then mk_cast e.etype ret else - e + Type.map_expr run e | _ -> Type.map_expr run e diff --git a/src/codegen/gencommon/interfaceProps.ml b/src/codegen/gencommon/interfaceProps.ml index 5e295bac5c2..7d92d74594f 100644 --- a/src/codegen/gencommon/interfaceProps.ml +++ b/src/codegen/gencommon/interfaceProps.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/interfaceVarsDeleteModf.ml b/src/codegen/gencommon/interfaceVarsDeleteModf.ml index 14af1bf925e..ea067f75ecd 100644 --- a/src/codegen/gencommon/interfaceVarsDeleteModf.ml +++ b/src/codegen/gencommon/interfaceVarsDeleteModf.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/normalize.ml b/src/codegen/gencommon/normalize.ml index 106a431fed9..fd2f4528ca1 100644 --- a/src/codegen/gencommon/normalize.ml +++ b/src/codegen/gencommon/normalize.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -49,7 +49,7 @@ let rec filter_param t = TAbstract(a, List.map filter_param tl) | TAbstract({a_path = [],"Null"} as a,[t]) -> TAbstract(a,[filter_param t]) - | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> + | TAbstract(a,tl) when (Meta.has Meta.MultiType a.a_meta) -> filter_param (Abstract.get_underlying_type a tl) | TAbstract(a,tl) -> TAbstract(a, List.map filter_param tl) diff --git a/src/codegen/gencommon/objectDeclMap.ml b/src/codegen/gencommon/objectDeclMap.ml index 93054e0cc6a..7d657ac83d5 100644 --- a/src/codegen/gencommon/objectDeclMap.ml +++ b/src/codegen/gencommon/objectDeclMap.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/overloadingConstructor.ml b/src/codegen/gencommon/overloadingConstructor.ml index 586425ce57b..f1f2b9f3a70 100644 --- a/src/codegen/gencommon/overloadingConstructor.ml +++ b/src/codegen/gencommon/overloadingConstructor.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -41,16 +41,6 @@ open Gencommon empty construction without the need of incompatibility with the platform's native construction method the ability to call super() constructor in any place in the constructor *) -let rec cur_ctor c tl = - match c.cl_constructor with - | Some ctor -> - ctor, c, tl - | None -> - match c.cl_super with - | None -> - raise Not_found - | Some (sup,stl) -> - cur_ctor sup (List.map (apply_params c.cl_params tl) stl) let rec prev_ctor c tl = match c.cl_super with @@ -106,7 +96,7 @@ let replace_super_call com c tl with_params me p follow_type = { eexpr = TCall( { - eexpr = TField(ExprBuilder.make_static_this sup p, FStatic(sup,cf)); + eexpr = TField(Texpr.Builder.make_static_this sup p, FStatic(sup,cf)); etype = apply_params cf.cf_params stl cf.cf_type; epos = p }, @@ -125,6 +115,15 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type = let static_ctor_name = make_static_ctor_name cl in (* create the static constructor *) let ctor_types = List.map (fun (s,t) -> (s, TInst(map_param (get_cl_t t), []))) cl.cl_params in + let ctor_type_params = List.map snd ctor_types in + List.iter (function (_,TInst(c,[])) -> ( + match c.cl_kind with + | KTypeParameter (hd :: tail) -> + let before = hd :: tail in + let after = List.map (apply_params cl.cl_params ctor_type_params) (before) in + c.cl_kind <- KTypeParameter(after) + | _ -> ()) + | _ -> ()) ctor_types; let me = alloc_var "__hx_this" (TInst(cl, List.map snd ctor_types)) in me.v_capture <- true; @@ -147,7 +146,8 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type = ) cur_tf_args in let static_ctor = mk_class_field static_ctor_name fn_type false ctor.cf_pos (Method MethNormal) ctor_types in - static_ctor.cf_meta <- (Meta.Protected,[],ctor.cf_pos) :: static_ctor.cf_meta; + let static_ctor_meta = if cl.cl_final then Meta.Private else Meta.Protected in + static_ctor.cf_meta <- (static_ctor_meta,[],ctor.cf_pos) :: static_ctor.cf_meta; (* change ctor contents to reference the 'me' var instead of 'this' *) let actual_super_call = ref None in @@ -205,7 +205,7 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type = eexpr = TCall( { eexpr = TField( - ExprBuilder.make_static_this cl p, + Texpr.Builder.make_static_this cl p, FStatic(cl, static_ctor)); etype = apply_params static_ctor.cf_params (List.map snd cl.cl_params) static_ctor.cf_type; epos = p @@ -222,7 +222,7 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type = (* makes constructors that only call super() for the 'ctor' argument *) let clone_ctors com ctor sup stl cl = let rec clone cf = - let ncf = mk_class_field "new" (apply_params sup.cl_params stl cf.cf_type) cf.cf_public cf.cf_pos cf.cf_kind cf.cf_params in + let ncf = mk_class_field "new" (apply_params sup.cl_params stl cf.cf_type) (has_class_field_flag cf CfPublic) cf.cf_pos cf.cf_kind cf.cf_params in if Meta.has Meta.Protected cf.cf_meta then ncf.cf_meta <- (Meta.Protected,[],ncf.cf_pos) :: ncf.cf_meta; let args, ret = get_fun ncf.cf_type in @@ -331,15 +331,22 @@ let init com (empty_ctor_type : t) (empty_ctor_expr : texpr) (follow_type : t -> cl.cl_constructor <- Some ctor; ctor in + + let has_super_constructor = + match cl.cl_super with + | None -> false + | Some (csup,_) -> has_constructor csup + in + (* now that we made sure we have a constructor, exit if native gen *) if not (is_hxgen (TClassDecl cl)) || Meta.has Meta.SkipCtor cl.cl_meta then begin - if descends_from_native_or_skipctor cl && is_some cl.cl_super then + if descends_from_native_or_skipctor cl && has_super_constructor then List.iter (fun cf -> ensure_super_is_first com cf) (ctor :: ctor.cf_overloads); raise Exit end; (* if cl descends from a native class, we cannot use the static constructor strategy *) - if descends_from_native_or_skipctor cl && is_some cl.cl_super then + if descends_from_native_or_skipctor cl && has_super_constructor then List.iter (fun cf -> ensure_super_is_first com cf) (ctor :: ctor.cf_overloads) else (* now that we have a current ctor, create the static counterparts *) diff --git a/src/codegen/gencommon/realTypeParams.ml b/src/codegen/gencommon/realTypeParams.ml index d341c080f26..4d8b3b0e3e6 100644 --- a/src/codegen/gencommon/realTypeParams.ml +++ b/src/codegen/gencommon/realTypeParams.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,6 +21,7 @@ open Common open Ast open Type open Codegen +open Texpr.Builder open Gencommon (* ******************************************* *) @@ -121,7 +122,21 @@ let rec is_hxgeneric md = | TAbstract(a,_) -> not (Meta.has Meta.NativeGeneric a.a_meta) | _ -> true +type nativegeneric_reason = + | ReasonField of string * Type.t + | ReasonSuper of Globals.path + | ReasonExplicit + +exception Cannot_be_native of Globals.path * pos * Globals.path * nativegeneric_reason + let rec set_hxgeneric gen mds isfirst md = + let iface_path, raise_pos, raise_if_native = match md with + | TClassDecl(cl) -> (try + (fst (List.find (fun (cl,_) -> (set_hxgeneric gen mds isfirst (TClassDecl cl) ) = Some(true) ) cl.cl_implements)).cl_path, cl.cl_pos, true + with Not_found -> + ([],""), Globals.null_pos, false) + | _ -> ([],""), Globals.null_pos, false + in let path = t_path md in if List.exists (fun m -> path = t_path m) mds then begin if isfirst then @@ -136,14 +151,14 @@ let rec set_hxgeneric gen mds isfirst md = | None -> has_unresolved := true; false | Some true -> false in - let mds = md :: mds in match md with | TClassDecl(cl) -> (* first see if any meta is present (already processed) *) - if Meta.has Meta.NativeGeneric cl.cl_meta then + if Meta.has Meta.NativeGeneric cl.cl_meta then begin + if raise_if_native then raise (Cannot_be_native(path, raise_pos, iface_path, ReasonExplicit)); Some false - else if Meta.has Meta.HaxeGeneric cl.cl_meta then + end else if Meta.has Meta.HaxeGeneric cl.cl_meta then Some true else if cl.cl_params = [] && is_hxgen md then (cl.cl_meta <- (Meta.HaxeGeneric,[],cl.cl_pos) :: cl.cl_meta; @@ -162,6 +177,7 @@ let rec set_hxgeneric gen mds isfirst md = (* on the first pass, our job is to find any evidence that makes it not be hxgeneric. Otherwise it will be hxgeneric *) match cl.cl_super with | Some (c,_) when is_false (set_hxgeneric gen mds isfirst (TClassDecl c)) -> + if raise_if_native then raise (Cannot_be_native(path, raise_pos, iface_path, ReasonSuper(c.cl_path))); cl.cl_meta <- (Meta.NativeGeneric, [], cl.cl_pos) :: cl.cl_meta; Some false | _ -> @@ -177,20 +193,28 @@ let rec set_hxgeneric gen mds isfirst md = | _ -> (* if it is, loop through all fields + statics and look for non-hxgeneric generic classes that have KTypeParameter as params *) - let rec loop cfs = + let raise_or_return_true = if raise_if_native then + (fun cf -> raise (Cannot_be_native(path, raise_pos, iface_path, ReasonField(cf.cf_name, cf.cf_type)))) + else + (fun cf -> true) + in + let rec cfs_must_be_native cfs = match cfs with | [] -> false - | cf :: cfs -> + | cf :: cfs when Type.is_physical_field cf -> let t = follow (gen.greal_type cf.cf_type) in - match t with - | TInst( { cl_kind = KTypeParameter _ }, _ ) -> loop cfs + (match t with + | TInst( { cl_kind = KTypeParameter _ }, _ ) -> cfs_must_be_native cfs | TInst(cl,p) when has_type_params t && is_false (set_hxgeneric gen mds isfirst (TClassDecl cl)) -> - if not (Hashtbl.mem gen.gtparam_cast cl.cl_path) then true else loop cfs + if not (Hashtbl.mem gen.gtparam_cast cl.cl_path) then raise_or_return_true cf else cfs_must_be_native cfs | TEnum(e,p) when has_type_params t && is_false (set_hxgeneric gen mds isfirst (TEnumDecl e)) -> - if not (Hashtbl.mem gen.gtparam_cast e.e_path) then true else loop cfs - | _ -> loop cfs (* TAbstracts / Dynamics can't be generic *) + if not (Hashtbl.mem gen.gtparam_cast e.e_path) then raise_or_return_true cf else cfs_must_be_native cfs + | _ -> cfs_must_be_native cfs (* TAbstracts / Dynamics can't be generic *) + ) + | _ :: cfs -> + cfs_must_be_native cfs in - if loop cl.cl_ordered_fields then begin + if cfs_must_be_native cl.cl_ordered_fields then begin cl.cl_meta <- (Meta.NativeGeneric, [], cl.cl_pos) :: cl.cl_meta; Some false end else if isfirst && !has_unresolved then @@ -201,9 +225,10 @@ let rec set_hxgeneric gen mds isfirst md = end end | TEnumDecl e -> - if Meta.has Meta.NativeGeneric e.e_meta then + if Meta.has Meta.NativeGeneric e.e_meta then begin + if raise_if_native then raise (Cannot_be_native(path, raise_pos, iface_path, ReasonExplicit)); Some false - else if Meta.has Meta.HaxeGeneric e.e_meta then + end else if Meta.has Meta.HaxeGeneric e.e_meta then Some true else if not (is_hxgen (TEnumDecl e)) then begin e.e_meta <- (Meta.NativeGeneric, [], e.e_pos) :: e.e_meta; @@ -215,7 +240,12 @@ let rec set_hxgeneric gen mds isfirst md = e.e_meta <- (Meta.HaxeGeneric, [], e.e_pos) :: e.e_meta; Some true | _ -> - let rec loop efs = + let raise_or_return_true = if raise_if_native then + (fun name t -> raise (Cannot_be_native(path, raise_pos, iface_path, ReasonField(name, t)))) + else + (fun _ _ -> true) + in + let rec efs_must_be_native efs = match efs with | [] -> false | ef :: efs -> @@ -228,18 +258,18 @@ let rec set_hxgeneric gen mds isfirst md = | TInst( { cl_kind = KTypeParameter _ }, _ ) -> false | TInst(cl,p) when has_type_params t && is_false (set_hxgeneric gen mds isfirst (TClassDecl cl)) -> - not (Hashtbl.mem gen.gtparam_cast cl.cl_path) + if not (Hashtbl.mem gen.gtparam_cast cl.cl_path) then raise_or_return_true ef.ef_name t else false | TEnum(e,p) when has_type_params t && is_false (set_hxgeneric gen mds isfirst (TEnumDecl e)) -> - not (Hashtbl.mem gen.gtparam_cast e.e_path) + if not (Hashtbl.mem gen.gtparam_cast e.e_path) then raise_or_return_true ef.ef_name t else false | _ -> false ) args then true else - loop efs - | _ -> loop efs + efs_must_be_native efs + | _ -> efs_must_be_native efs in let efs = PMap.fold (fun ef acc -> ef :: acc) e.e_constrs [] in - if loop efs then begin + if efs_must_be_native efs then begin e.e_meta <- (Meta.NativeGeneric, [], e.e_pos) :: e.e_meta; Some false end else if isfirst && !has_unresolved then @@ -252,47 +282,66 @@ let rec set_hxgeneric gen mds isfirst md = | _ -> assert false end +let path_s = function + | [],name -> name + | pack,name -> String.concat "." pack ^ "." ^ name + let set_hxgeneric gen md = - let ret = match md with - | TClassDecl { cl_kind = KAbstractImpl a } -> (match follow_all_md md with - | (TInst _ | TEnum _ as t) -> ( - let md = match t with - | TInst(cl,_) -> TClassDecl cl - | TEnum(e,_) -> TEnumDecl e - | _ -> assert false + try + let ret = match md with + | TClassDecl { cl_kind = KAbstractImpl a } -> (match follow_all_md md with + | (TInst _ | TEnum _ as t) -> ( + let md = match t with + | TInst(cl,_) -> TClassDecl cl + | TEnum(e,_) -> TEnumDecl e + | _ -> assert false + in + let ret = set_hxgeneric gen [] true md in + if ret = None then get (set_hxgeneric gen [] false md) else get ret) + | TAbstract(a,_) -> true + | _ -> true) + | _ -> match set_hxgeneric gen [] true md with + | None -> + get (set_hxgeneric gen [] false md) + | Some v -> + v + in + if not ret then begin + match md with + | TClassDecl c -> + let set_hxgeneric (_,param) = match follow param with + | TInst(c,_) -> + c.cl_meta <- (Meta.NativeGeneric, [], c.cl_pos) :: c.cl_meta + | _ -> () in - let ret = set_hxgeneric gen [] true md in - if ret = None then get (set_hxgeneric gen [] false md) else get ret) - | TAbstract(a,_) -> true - | _ -> true) - | _ -> match set_hxgeneric gen [] true md with - | None -> - get (set_hxgeneric gen [] false md) - | Some v -> - v - in - if not ret then begin - match md with - | TClassDecl c -> - let set_hxgeneric (_,param) = match follow param with - | TInst(c,_) -> - c.cl_meta <- (Meta.NativeGeneric, [], c.cl_pos) :: c.cl_meta - | _ -> () - in - List.iter set_hxgeneric c.cl_params; - let rec handle_field cf = - List.iter set_hxgeneric cf.cf_params; - List.iter handle_field cf.cf_overloads - in - (match c.cl_kind with - | KAbstractImpl a -> - List.iter set_hxgeneric a.a_params; - | _ -> ()); - List.iter handle_field c.cl_ordered_fields; - List.iter handle_field c.cl_ordered_statics - | _ -> () - end; - ret + List.iter set_hxgeneric c.cl_params; + let rec handle_field cf = + List.iter set_hxgeneric cf.cf_params; + List.iter handle_field cf.cf_overloads + in + (match c.cl_kind with + | KAbstractImpl a -> + List.iter set_hxgeneric a.a_params; + | _ -> ()); + List.iter handle_field c.cl_ordered_fields; + List.iter handle_field c.cl_ordered_statics + | _ -> () + end; + ret + with Cannot_be_native(path, pos, iface_path, reason) -> + let reason_start = "The class at path " ^ path_s path ^ " implements a haxe generic interface " ^ path_s iface_path + ^ ". It however cannot be a haxe generic class " + in + let reason = reason_start ^ match reason with + | ReasonField (field_name, t) -> + "because its field " ^ field_name ^ " is of type " ^ debug_type t + | ReasonSuper (path) -> + "because it extends the type " ^ path_s path ^ " that was determined to be a native generic type" + | ReasonExplicit -> + "because it explicitly has the metadata @:nativeGeneric set" + in + gen.gcon.error (reason) pos; + assert false let params_has_tparams params = List.fold_left (fun acc t -> acc || has_type_params t) false params @@ -416,6 +465,7 @@ struct let params = List.map snd cparams in let fields = get_fields gen cl (List.map snd cl.cl_params) params [] in + let fields = List.filter (fun (cf,_,_) -> Type.is_physical_field cf) fields in (* now create the contents of the function *) (* @@ -459,21 +509,25 @@ struct | _ -> assert false in List.map (fun (cf, t_cl, t_cf) -> + let t_cf = follow (gen.greal_type t_cf) in let this_field = mk (TField (this, FInstance (cl, List.map snd cl.cl_params, cf))) t_cl pos in let expr = binop OpAssign (mk (TField (local_new_me, FInstance(cl, List.map snd cl.cl_params, cf))) t_cf pos) - (try (Hashtbl.find gen.gtparam_cast (get_path t_cf)) this_field t_cf with Not_found -> (* if not found tparam cast, it shouldn't be a valid hxgeneric *) assert false) + (try (Hashtbl.find gen.gtparam_cast (get_path t_cf)) this_field t_cf with Not_found -> + (* if not found tparam cast, it shouldn't be a valid hxgeneric *) + print_endline ("Could not find a gtparam_cast for " ^ (String.concat "." (fst (get_path t_cf)) ^ "." ^ (snd (get_path t_cf)))); + assert false) t_cf pos in - [ExprBuilder.make_string gen.gcon cf.cf_name pos], expr + [make_string gen.gcon.basic cf.cf_name pos], expr ) fields in let mk_typehandle = - (fun cl -> mk (TCall (mk (TIdent "__typeof__") t_dynamic pos, [ExprBuilder.make_static_this cl pos])) t_dynamic pos) + (fun cl -> mk (TCall (mk (TIdent "__typeof__") t_dynamic pos, [make_static_this cl pos])) t_dynamic pos) in let mk_eq cl1 cl2 = binop OpEq (mk_typehandle cl1) (mk_typehandle cl2) basic.tbool pos @@ -503,7 +557,7 @@ struct (* var fields = Reflect.fields(this); *) mk (TVar (fields_var, Some (gen.gtools.r_fields true this))) basic.tvoid pos; (* var i = 0; *) - mk (TVar (i_var, Some (ExprBuilder.make_int gen.gcon 0 pos))) basic.tvoid pos; + mk (TVar (i_var, Some (make_int gen.gcon.basic 0 pos))) basic.tvoid pos; (* while (i < fields.length) *) mk (TWhile ( binop OpLt local_i (mk_field_access gen local_fields "length" pos) basic.tbool pos, @@ -666,7 +720,7 @@ struct not (has_type_params cf_type) ) cl.cl_ordered_fields in - let fields = List.map (fun f -> mk_class_field f.cf_name f.cf_type f.cf_public f.cf_pos f.cf_kind f.cf_params) fields in + let fields = List.map (fun f -> mk_class_field f.cf_name f.cf_type (has_class_field_flag f CfPublic) f.cf_pos f.cf_kind f.cf_params) fields in let fields = iface_cf :: fields in iface.cl_ordered_fields <- fields; List.iter (fun f -> iface.cl_fields <- PMap.add f.cf_name f iface.cl_fields) fields; diff --git a/src/codegen/gencommon/reflectionCFs.ml b/src/codegen/gencommon/reflectionCFs.ml index 071d3e42cb5..a283d537663 100644 --- a/src/codegen/gencommon/reflectionCFs.ml +++ b/src/codegen/gencommon/reflectionCFs.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,6 +21,7 @@ open Common open Ast open Type open Codegen +open Texpr.Builder open Gencommon open ClosuresToClass @@ -103,6 +104,7 @@ type rcf_ctx = rcf_optimize : bool; rcf_object_iface : tclass; + rcf_dynamic_data_class : tclass option; rcf_max_func_arity : int; @@ -125,7 +127,7 @@ type rcf_ctx = rcf_hash_fields : (int, string) Hashtbl.t; - rcf_hash_paths : (path * int, string) Hashtbl.t; + rcf_hash_paths : (Globals.path * int, string) Hashtbl.t; rcf_hash_conflict_ctx : rcf_hash_conflict_ctx option; @@ -141,12 +143,13 @@ type rcf_ctx = rcf_on_call_field : texpr->texpr->string->int32 option->texpr list->texpr; } -let new_ctx gen ft object_iface optimize dynamic_getset_field dynamic_call_field hash_function lookup_function insert_function remove_function hash_conflict_ctx rcf_mk_exception = +let new_ctx gen ft object_iface ?dynamic_data_class optimize dynamic_getset_field dynamic_call_field hash_function lookup_function insert_function remove_function hash_conflict_ctx rcf_mk_exception = { rcf_gen = gen; rcf_ft = ft; rcf_optimize = optimize; + rcf_dynamic_data_class = dynamic_data_class; rcf_object_iface = object_iface; @@ -238,7 +241,7 @@ let switch_case ctx pos field_name = let i = hash_field_i32 ctx pos field_name in mk (TConst (TInt i)) ctx.rcf_gen.gcon.basic.tint pos | false -> - ExprBuilder.make_string ctx.rcf_gen.gcon field_name pos + make_string ctx.rcf_gen.gcon.basic field_name pos let call_super ctx fn_args ret_t cf cl this_t pos = { @@ -264,7 +267,7 @@ let enumerate_dynamic_fields ctx cl when_found base_arr = let convert_str e = if ctx.rcf_optimize then ctx.rcf_lookup_function e else e in let tmpinc = { eexpr = TUnop(Ast.Increment, Ast.Postfix, mk_local vtmp pos); etype = basic.tint; epos = pos } in [ - { eexpr = TBinop(OpAssign, mk_local vtmp pos, ExprBuilder.make_int ctx.rcf_gen.gcon 0 pos); etype = basic.tint; epos = pos }; + { eexpr = TBinop(OpAssign, mk_local vtmp pos, make_int ctx.rcf_gen.gcon.basic 0 pos); etype = basic.tint; epos = pos }; { eexpr = TWhile ( { eexpr = TBinop(Ast.OpLt, mk_local vtmp pos, len); etype = basic.tbool; epos = pos }, @@ -378,12 +381,12 @@ let abstract_dyn_lookup_implementation ctx this field_local hash_local may_value let vconflict = alloc_var "conflict" conflict_ctx.t in let local_conflict = mk_local vconflict pos in [mk (TIf ( - mk (TBinop (OpLt, hash_local, ExprBuilder.make_int gen.gcon 0 pos)) basic.tbool pos, + mk (TBinop (OpLt, hash_local, make_int gen.gcon.basic 0 pos)) basic.tbool pos, mk (TBlock [ mk (TVar (vconflict, Some (conflict_ctx.get_conflict ehead hash_local field_local))) basic.tvoid pos; mk (TIf ( mk (TBinop (OpNotEq, local_conflict, mk (TConst TNull) local_conflict.etype pos)) basic.tbool pos, - mk_return (Codegen.field local_conflict "value" t_dynamic pos), + mk_return (field local_conflict "value" t_dynamic pos), None )) basic.tvoid pos; ]) basic.tvoid pos, @@ -453,7 +456,7 @@ let abstract_dyn_lookup_implementation ctx this field_local hash_local may_value let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in [mk (TIf ( - mk (TBinop (OpLt, hash_local, ExprBuilder.make_int gen.gcon 0 pos)) basic.tbool pos, + mk (TBinop (OpLt, hash_local, make_int gen.gcon.basic 0 pos)) basic.tbool pos, conflict_ctx.set ehead hash_local field_local value_local, Some (mk (TBlock block) basic.tvoid pos) )) basic.tvoid pos] @@ -538,7 +541,7 @@ let get_delete_field ctx cl is_dynamic = let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in (mk (TIf ( - binop OpLt local_switch_var (ExprBuilder.make_int gen.gcon 0 pos) basic.tbool pos, + binop OpLt local_switch_var (make_int gen.gcon.basic 0 pos) basic.tbool pos, mk_return (conflict_ctx.delete ehead local_switch_var local_name), None )) basic.tvoid pos) :: common @@ -559,12 +562,6 @@ let get_delete_field ctx cl is_dynamic = cf.cf_expr <- Some({ eexpr = TFunction(fn); etype = fun_type; epos = pos }); cf -let rec is_first_dynamic cl = - match cl.cl_super with - | Some(cl,_) -> - if is_some cl.cl_dynamic then false else is_first_dynamic cl - | None -> true - let is_override cl = match cl.cl_super with | Some (cl, _) when is_hxgen (TClassDecl cl) -> true | _ -> false @@ -604,75 +601,6 @@ let implement_dynamic_object_ctor ctx cl = let basic = gen.gcon.basic in let hasht = if ctx.rcf_optimize then basic.tint else basic.tstring in - let hashes_field = mk_internal_name "hx" "hashes", gen.gclasses.nativearray hasht in - let hashes_f_field = mk_internal_name "hx" "hashes_f", gen.gclasses.nativearray hasht in - let dynamics_field = mk_internal_name "hx" "dynamics", gen.gclasses.nativearray t_empty in - let dynamics_f_field = mk_internal_name "hx" "dynamics_f", gen.gclasses.nativearray basic.tfloat in - let fields = - [ - hashes_field; - dynamics_field; - hashes_f_field; - dynamics_f_field; - ] in - - let hashes_var = alloc_var (fst hashes_field) (snd hashes_field) in - let hashes_f_var = alloc_var (fst hashes_f_field) (snd hashes_f_field) in - let tf_args = [ - hashes_var, None; - alloc_var (fst dynamics_field) (snd dynamics_field), None; - hashes_f_var, None; - alloc_var (fst dynamics_f_field) (snd dynamics_f_field), None; - ] in - - let this = { eexpr = TConst TThis; etype = TInst(cl, List.map snd cl.cl_params); epos = pos } in - let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in - let fun_t = TFun(fun_args tf_args,basic.tvoid) in - let ctor = mk_class_field "new" fun_t true pos (Method MethNormal) [] in - ctor.cf_expr <- Some( - { - eexpr = TFunction({ - tf_args = tf_args; - tf_type = basic.tvoid; - tf_expr = - { - eexpr = TBlock( - List.map (fun (v,_) -> - { eexpr = TBinop(Ast.OpAssign, mk_this v.v_name v.v_type, mk_local v pos); etype = v.v_type; epos = pos } - ) tf_args - @ - [ - mk (TBinop(OpAssign, mk_this (mk_internal_name "hx" "length") basic.tint, gen.gclasses.nativearray_len (mk_local hashes_var pos) pos)) basic.tint pos; - mk (TBinop(OpAssign, mk_this (mk_internal_name "hx" "length_f") basic.tint, gen.gclasses.nativearray_len (mk_local hashes_f_var pos) pos)) basic.tint pos; - ] - ); - etype = basic.tvoid; - epos = pos - } - }); - etype = fun_t; - epos = pos - }); - - add_constructor cl ctor; - (* default ctor also *) - let ctor = mk_class_field "new" (TFun([],basic.tvoid)) false pos (Method MethNormal) [] in - ctor.cf_expr <- Some { - eexpr = TFunction { - tf_type = basic.tvoid; - tf_args = []; - tf_expr = { - eexpr = TBlock(List.map (fun (f,t) -> - { eexpr = TBinop(Ast.OpAssign, mk_this f t,{ eexpr = TCall(mk (TIdent "__array__") t_dynamic pos, []); etype = t; epos = pos; }); etype = t; epos = pos } - ) fields); - etype = basic.tvoid; - epos = pos; - } - }; - etype = ctor.cf_type; - epos = pos; - }; - add_constructor cl ctor; (* and finally we will return a function that transforms a TObjectDecl into a new DynamicObject() call *) let rec loop objdecl acc acc_f = match objdecl with @@ -693,7 +621,7 @@ let implement_dynamic_object_ctor ctx cl = if ctx.rcf_optimize then begin mk (TConst (TInt (hash_field_i32 ctx pos s))) basic.tint pos end else begin - ExprBuilder.make_string gen.gcon s pos + make_string gen.gcon.basic s pos end in @@ -723,7 +651,6 @@ let implement_dynamic_object_ctor ctx cl = in let odecl, odecl_f = List.sort sort_fn odecl, List.sort sort_fn odecl_f in - let ret = { e with eexpr = TNew(cl,[], [ @@ -744,79 +671,6 @@ let implement_dynamic_object_ctor ctx cl = in do_objdecl -let implement_dynamics ctx cl = - let pos = cl.cl_pos in - let is_override = is_override cl in - if is_some cl.cl_dynamic then begin - if is_first_dynamic cl then begin - (* - * add hx_hashes, hx_hashes_f, hx_dynamics, hx_dynamics_f to class - * implement hx_deleteField - *) - let gen = ctx.rcf_gen in - let basic = gen.gcon.basic in - let hasht = if ctx.rcf_optimize then basic.tint else basic.tstring in - - let new_fields = - [ - mk_class_field (mk_internal_name "hx" "hashes") (gen.gclasses.nativearray hasht) false pos (Var { v_read = AccNormal; v_write = AccNormal }) []; - mk_class_field (mk_internal_name "hx" "dynamics") (gen.gclasses.nativearray t_empty) false pos (Var { v_read = AccNormal; v_write = AccNormal }) []; - mk_class_field (mk_internal_name "hx" "hashes_f") (gen.gclasses.nativearray hasht) false pos (Var { v_read = AccNormal; v_write = AccNormal }) []; - mk_class_field (mk_internal_name "hx" "dynamics_f") (gen.gclasses.nativearray basic.tfloat) false pos (Var { v_read = AccNormal; v_write = AccNormal }) []; - ] in - - (if cl.cl_path <> (["haxe"; "lang"], "DynamicObject") then - List.iter (fun cf -> cf.cf_expr <- Some { eexpr = TCall(mk (TIdent "__array__") t_dynamic pos, []); etype = cf.cf_type; epos = cf.cf_pos }) new_fields - ); - - let new_fields = - if ctx.rcf_optimize then - let f = mk_class_field (mk_internal_name "hx" "conflicts") (Option.get ctx.rcf_hash_conflict_ctx).t false pos (Var { v_read = AccNormal; v_write = AccNormal }) [] in - f :: new_fields - else - new_fields - in - - let delete = get_delete_field ctx cl true in - - let new_fields = new_fields @ [ - mk_class_field (mk_internal_name "hx" "length") (basic.tint) false pos (Var { v_read = AccNormal; v_write = AccNormal }) []; - mk_class_field (mk_internal_name "hx" "length_f") (basic.tint) false pos (Var { v_read = AccNormal; v_write = AccNormal }) []; - delete; - ] in - - List.iter (fun cf -> - cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields - ) new_fields; - - (* - let rec last_ctor cl = - match cl.cl_constructor with - | None -> (match cl.cl_super with | None -> None | Some (cl,_) -> last_ctor cl) - | Some c -> Some c - in - *) - (* - in order for the next to work, we need to execute our script before InitFunction, so the expressions inside the variables are initialized by the constructor - *) - (* - Now we need to add their initialization. - This will consist of different parts: - Check if there are constructors. If not, create one and add initialization to it (calling super, ok) - If there are, add as first statement (or second if there is a super() call in the first) - If class has @:dynamicObject meta, also create another new() class with its parameters as constructor arguments - *) - - cl.cl_ordered_fields <- cl.cl_ordered_fields @ new_fields; - if is_override then cl.cl_overrides <- delete :: cl.cl_overrides - end - end else if not is_override then begin - let delete = get_delete_field ctx cl false in - cl.cl_ordered_fields <- cl.cl_ordered_fields @ [delete]; - cl.cl_fields <- PMap.add delete.cf_name delete cl.cl_fields - end - - (* Implements: __hx_lookupField(field:String, throwErrors:Bool, isCheck:Bool, handleProperties:Bool, isFirst:Bool):Dynamic @@ -833,11 +687,11 @@ let implement_final_lookup ctx cl = let pos = cl.cl_pos in let is_override = is_override cl in - let this = { eexpr = TConst(TThis); etype = TInst(cl, List.map snd cl.cl_params); epos = pos } in + (* let this = { eexpr = TConst(TThis); etype = TInst(cl, List.map snd cl.cl_params); epos = pos } in *) let mk_throw str pos = let e = ctx.rcf_mk_exception str pos in - ExprBuilder.make_throw e pos + make_throw e pos in (* @@ -926,25 +780,16 @@ let implement_final_lookup ctx cl = if is_override then cl.cl_overrides <- cf :: cl.cl_overrides ) cfs in - - if is_some cl.cl_dynamic then begin - (* let abstract_dyn_lookup_implementation ctx this hash_local may_value is_float pos = *) - (* callback : is_float fields_args switch_var throw_errors_option is_check_option value_option : texpr list *) - if is_first_dynamic cl then - create_cfs true (fun is_float fields_args switch_var _ _ value_opt -> - let v_name = match fields_args with (v,_) :: _ -> v | _ -> assert false in - abstract_dyn_lookup_implementation ctx this (mk_local v_name pos) (mk_local switch_var pos) (Option.map (fun v -> mk_local v pos) value_opt) is_float pos - ) - end else if not is_override then begin + if not is_override then begin create_cfs false (fun is_float fields_args switch_var _ _ value_opt -> match value_opt with - | None -> (* is not set *) - [] - | Some _ -> (* is set *) - if is_float then - [ mk_throw "Cannot access field for writing or incompatible type." pos ] - else - [ mk_throw "Cannot access field for writing." pos ] + | None -> (* is not set *) + [] + | Some _ -> (* is set *) + if is_float then + [ mk_throw "Cannot access field for writing or incompatible type." pos ] + else + [ mk_throw "Cannot access field for writing." pos ] ) end @@ -1144,10 +989,13 @@ let implement_get_set ctx cl = let content = let fields = get_fields() in - let fields = List.filter (fun (_, cf) -> match is_set, cf.cf_kind with - | true, Var { v_write = AccCall } -> true - | false, Var { v_read = AccCall } -> true - | _ -> Type.is_physical_field cf) fields + let fields = List.filter + (fun (_, cf) -> match is_set, cf.cf_kind with + | true, Var { v_write = AccCall } -> true + | false, Var { v_read = AccCall } -> true + | _ -> Type.is_physical_field cf && not (has_meta Meta.ReadOnly cf.cf_meta) + ) + fields in (if fields <> [] then has_fields := true); let cases = List.map (fun (names, cf) -> @@ -1219,7 +1067,7 @@ let implement_getFields ctx cl = | Var _ | Method MethDynamic when not (List.memq cf cl.cl_overrides) -> has_value := true; - mk_push (ExprBuilder.make_string gen.gcon cf.cf_name pos) + mk_push (make_string gen.gcon.basic cf.cf_name pos) | _ -> null basic.tvoid pos ) in @@ -1227,22 +1075,14 @@ let implement_getFields ctx cl = (* if it is first_dynamic, then we need to enumerate the dynamic fields *) - let exprs = - if is_some cl.cl_dynamic && is_first_dynamic cl then begin - has_value := true; - enumerate_dynamic_fields ctx cl mk_push base_arr - end else - [] - in - let exprs = if is_override cl then let tparams = List.map snd cl.cl_params in let esuper = mk (TConst TSuper) (TInst(cl, tparams)) pos in let efield = mk (TField (esuper, FInstance (cl, tparams, cf))) t pos in - exprs @ [mk (TCall (efield, [base_arr])) basic.tvoid pos] + [mk (TCall (efield, [base_arr])) basic.tvoid pos] else - exprs + [] in let exprs = map_fields (collect_fields cl (Some false)) @ exprs in @@ -1338,7 +1178,7 @@ let implement_invokeField ctx slow_invoke cl = (cases, mk_return ( mk_this_call cf (List.map (fun (name,_,t) -> - let ret = { eexpr = TArray(dyn_arg_local, ExprBuilder.make_int ctx.rcf_gen.gcon !i pos); etype = t_dynamic; epos = pos } in + let ret = { eexpr = TArray(dyn_arg_local, make_int ctx.rcf_gen.gcon.basic !i pos); etype = t_dynamic; epos = pos } in incr i; ret ) (fst (get_fun (cf.cf_type)))) @@ -1367,9 +1207,9 @@ let implement_invokeField ctx slow_invoke cl = let tf_args, _ = field_type_args ctx pos in let tf_args, args = fun_args tf_args, field_args_exprs in - let tf_args, args = tf_args @ ["throwErrors",false, basic.tbool], args @ [ExprBuilder.make_bool gen.gcon true pos] in - let tf_args, args = tf_args @ ["isCheck", false, basic.tbool], args @ [ExprBuilder.make_bool gen.gcon false pos] in - let tf_args, args = tf_args @ ["handleProperties", false, basic.tbool], args @ [ExprBuilder.make_bool gen.gcon false pos] in + let tf_args, args = tf_args @ ["throwErrors",false, basic.tbool], args @ [make_bool gen.gcon.basic true pos] in + let tf_args, args = tf_args @ ["isCheck", false, basic.tbool], args @ [make_bool gen.gcon.basic false pos] in + let tf_args, args = tf_args @ ["handleProperties", false, basic.tbool], args @ [make_bool gen.gcon.basic false pos] in mk (TCall ({ (mk_field_access gen this fun_name pos) with etype = TFun(tf_args, t_dynamic) }, args)) t_dynamic pos end in @@ -1549,7 +1389,7 @@ let implement_closure_cl ctx cl = tf_args = tf_args; tf_type = basic.tvoid; tf_expr = { eexpr = TBlock({ - eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(cl,[]); epos = pos }, [ExprBuilder.make_int ctx.rcf_gen.gcon (-1) pos; ExprBuilder.make_int ctx.rcf_gen.gcon (-1) pos]); + eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(cl,[]); epos = pos }, [make_int ctx.rcf_gen.gcon.basic (-1) pos; make_int ctx.rcf_gen.gcon.basic (-1) pos]); etype = basic.tvoid; epos = pos } :: ctor_body); etype = basic.tvoid; epos = pos } @@ -1561,7 +1401,7 @@ let implement_closure_cl ctx cl = cl.cl_constructor <- Some ctor_cf; let closure_fun eclosure e field is_static = - let f = ExprBuilder.make_string gen.gcon field eclosure.epos in + let f = make_string gen.gcon.basic field eclosure.epos in let args = if ctx.rcf_optimize then [ f; { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else [ f ] in let args = args @ [ mk_cast (TInst(ctx.rcf_object_iface, [])) e ] in @@ -1576,7 +1416,7 @@ let get_closure_func ctx closure_cl = mk_cast eclosure.etype { eclosure with eexpr = TNew(closure_cl, [], [ e; - ExprBuilder.make_string gen.gcon field eclosure.epos + make_string gen.gcon.basic field eclosure.epos ] @ ( if ctx.rcf_optimize then [ { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else [] )); @@ -1639,10 +1479,7 @@ struct (* don't add any base classes to abstract implementations *) () | TClassDecl ({ cl_super = None } as cl) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && cl.cl_path <> basedynamic.cl_path -> - if is_some cl.cl_dynamic then - cl.cl_super <- Some (basedynamic,[]) - else - cl.cl_super <- Some (baseclass,[]) + cl.cl_super <- Some (baseclass,[]) | TClassDecl ({ cl_super = Some(super,_) } as cl) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && not (is_hxgen (TClassDecl super)) -> cl.cl_implements <- (baseinterface, []) :: cl.cl_implements | _ -> @@ -1658,15 +1495,33 @@ end;; *) let priority = solve_deps name [DAfter UniversalBaseClass.priority] +let add_override cl cf = + if List.memq cf cl.cl_overrides then + cl.cl_overrides + else + cf :: cl.cl_overrides + +let has_field_override cl name = + try + cl.cl_overrides <- add_override cl (PMap.find name cl.cl_fields); + true + with | Not_found -> + false + let configure ctx baseinterface ~slow_invoke = let run md = (match md with | TClassDecl ({ cl_extern = false } as cl) when is_hxgen md && ( not cl.cl_interface || cl.cl_path = baseinterface.cl_path ) && (match cl.cl_kind with KAbstractImpl _ -> false | _ -> true) -> - implement_dynamics ctx cl; - if not (PMap.mem (mk_internal_name "hx" "lookupField") cl.cl_fields) then implement_final_lookup ctx cl; - if not (PMap.mem (mk_internal_name "hx" "getField") cl.cl_fields) then implement_get_set ctx cl; - if not (PMap.mem (mk_internal_name "hx" "invokeField") cl.cl_fields) then implement_invokeField ctx slow_invoke cl; - if not (PMap.mem (mk_internal_name "hx" "getFields") cl.cl_fields) then implement_getFields ctx cl; + if is_some cl.cl_super then begin + ignore (has_field_override cl (mk_internal_name "hx" "setField")); + ignore (has_field_override cl (mk_internal_name "hx" "setField_f")); + ignore (has_field_override cl (mk_internal_name "hx" "getField_f")); + end; + + if not (has_field_override cl (mk_internal_name "hx" "lookupField")) then implement_final_lookup ctx cl; + if not (has_field_override cl (mk_internal_name "hx" "getField")) then implement_get_set ctx cl; + if not (has_field_override cl (mk_internal_name "hx" "invokeField")) then implement_invokeField ctx slow_invoke cl; + if not (has_field_override cl (mk_internal_name "hx" "getFields")) then implement_getFields ctx cl; | _ -> ()); md in diff --git a/src/codegen/gencommon/renameTypeParameters.ml b/src/codegen/gencommon/renameTypeParameters.ml index 20dc31f789d..716aae029e4 100644 --- a/src/codegen/gencommon/renameTypeParameters.ml +++ b/src/codegen/gencommon/renameTypeParameters.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/setHXGen.ml b/src/codegen/gencommon/setHXGen.ml index a5525da48ac..dd9be5f5285 100644 --- a/src/codegen/gencommon/setHXGen.ml +++ b/src/codegen/gencommon/setHXGen.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/switchToIf.ml b/src/codegen/gencommon/switchToIf.ml index a6cf60914fb..01803c44e00 100644 --- a/src/codegen/gencommon/switchToIf.ml +++ b/src/codegen/gencommon/switchToIf.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -137,7 +137,7 @@ let configure gen (should_convert:texpr->bool) = let fields = Hashtbl.create (List.length real_enum.e_names) in PMap.iter (fun _ ef -> Hashtbl.add fields ef.ef_index ef) real_enum.e_constrs; - let enum_expr = ExprBuilder.make_typeexpr (TEnumDecl real_enum) e.epos in + let enum_expr = Texpr.Builder.make_typeexpr (TEnumDecl real_enum) e.epos in let cases = List.map (fun (patterns, body) -> let patterns = List.map (fun e -> match e.eexpr with diff --git a/src/codegen/gencommon/tArrayTransform.ml b/src/codegen/gencommon/tArrayTransform.ml index 9cf18a8b404..60e36304e58 100644 --- a/src/codegen/gencommon/tArrayTransform.ml +++ b/src/codegen/gencommon/tArrayTransform.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/unnecessaryCastsRemoval.ml b/src/codegen/gencommon/unnecessaryCastsRemoval.ml index d607d451b5b..8fced4edb0c 100644 --- a/src/codegen/gencommon/unnecessaryCastsRemoval.ml +++ b/src/codegen/gencommon/unnecessaryCastsRemoval.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/codegen/gencommon/unreachableCodeEliminationSynf.ml b/src/codegen/gencommon/unreachableCodeEliminationSynf.ml index 26b0588a4a4..718599481ae 100644 --- a/src/codegen/gencommon/unreachableCodeEliminationSynf.ml +++ b/src/codegen/gencommon/unreachableCodeEliminationSynf.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -129,7 +129,7 @@ let init com java_mode = | TFunction tf -> let changed, kind = process_expr tf.tf_expr in let changed = if not (ExtType.is_void tf.tf_type) && kind <> BreaksFunction then - Type.concat changed (Codegen.mk_return (null tf.tf_type expr.epos)) + Type.concat changed (Texpr.Builder.mk_return (null tf.tf_type expr.epos)) else changed in diff --git a/src/codegen/genxml.ml b/src/codegen/genxml.ml index 387182c434b..0ed807813aa 100644 --- a/src/codegen/genxml.ml +++ b/src/codegen/genxml.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -86,7 +86,7 @@ let gen_meta meta = | [] -> [] | _ -> let nodes = List.map (fun (m,el,_) -> - node "m" ["n",Meta.to_string m] (List.map (fun e -> node "e" [] [gen_string (Ast.s_expr e)]) el) + node "m" ["n",Meta.to_string m] (List.map (fun e -> node "e" [] [gen_string (Ast.Printer.s_expr e)]) el) ) meta in [node "meta" [] nodes] @@ -107,7 +107,7 @@ let rec gen_type ?(values=None) t = try let e = PMap.find n values in has_value := true; - let s = Ast.s_expr e in + let s = Ast.Printer.s_expr e in s with Not_found -> "" @@ -121,7 +121,7 @@ let rec gen_type ?(values=None) t = if opt then follow_param t else t ) args in node "f" (("a",names) :: values) (List.map gen_type (args @ [r])) - | TAnon a -> node "a" [] (pmap (fun f -> gen_field [] { f with cf_public = false }) a.a_fields) + | TAnon a -> node "a" [] (pmap (fun f -> gen_field [] { f with cf_flags = unset_flag f.cf_flags (int_of_class_field_flag CfPublic) }) a.a_fields) | TDynamic t2 -> node "d" [] (if t == t2 then [] else [gen_type t2]) | TLazy f -> gen_type (lazy_type f) @@ -142,7 +142,7 @@ and gen_field att f = | Var v -> let att = try begin match Meta.get Meta.Value f.cf_meta with - | (_,[e],_) -> ("expr",Ast.s_expr e) :: att + | (_,[e],_) -> ("expr",Ast.Printer.s_expr e) :: att | _ -> att end with Not_found -> @@ -171,8 +171,8 @@ and gen_field att f = with Not_found -> cf.cf_name in - let att = if f.cf_public then ("public","1") :: att else att in - let att = if (Meta.has Meta.Final) f.cf_meta then ("final","1") :: att else att in + let att = if has_class_field_flag f CfPublic then ("public","1") :: att else att in + let att = if has_class_field_flag f CfFinal then ("final","1") :: att else att in node (field_name f) att (gen_type ~values:(Some values) f.cf_type :: gen_meta f.cf_meta @ gen_doc_opt f.cf_doc @ overloads) let gen_constr e = @@ -236,11 +236,7 @@ let rec gen_type_decl com pos t = let meta = gen_meta c.cl_meta in let ext = (if c.cl_extern then [("extern","1")] else []) in let interf = (if c.cl_interface then [("interface","1")] else []) in - let dynamic = (match c.cl_dynamic with - | None -> [] - | Some t -> [node "haxe_dynamic" [] [gen_type t]] - ) in - node "class" (gen_type_params pos c.cl_private (tpath t) c.cl_params c.cl_pos m @ ext @ interf) (tree @ stats @ fields @ constr @ doc @ meta @ dynamic) + node "class" (gen_type_params pos c.cl_private (tpath t) c.cl_params c.cl_pos m @ ext @ interf) (tree @ stats @ fields @ constr @ doc @ meta) | TEnumDecl e -> let doc = gen_doc_opt e.e_doc in let meta = gen_meta e.e_meta in @@ -288,10 +284,10 @@ let rec write_xml ch tabs x = IO.printf ch "" s let generate com file = - let t = Common.timer ["generate";"xml"] in + let t = Timer.timer ["generate";"xml"] in let x = node "haxe" [] (List.map (gen_type_decl com true) (List.filter (fun t -> not (Meta.has Meta.NoDoc (t_infos t).mt_meta)) com.types)) in t(); - let t = Common.timer ["write";"xml"] in + let t = Timer.timer ["write";"xml"] in let ch = IO.output_channel (open_out_bin file) in IO.printf ch "\n"; write_xml ch "" x; @@ -303,256 +299,3 @@ let gen_type_string ctx t = let ch = IO.output_string() in write_xml ch "" x; IO.close_out ch - - -(* -------------------------------------------------------------------------- *) -(* PRINT HX FROM TYPE *) - -let rec create_dir acc = function - | [] -> () - | d :: l -> - let path = acc ^ "/" ^ d in - (try Unix.mkdir path 0o777 with _ -> ()); - create_dir path l - -let conv_path p = - match List.rev (fst p) with - | x :: l when x.[0] = '_' -> List.rev (("priv" ^ x) :: l), snd p - | _ -> p - -let get_real_path meta path = - try - let real_path = match Meta.get Meta.RealPath meta with - | (_,[(EConst(String s),_)],_) -> - s - | _ -> raise Not_found - in - match List.rev (String.nsplit real_path ".") with - | name :: pack -> - (List.rev pack), name - | _ -> raise Not_found - with | Not_found -> - path - - -let generate_type com t = - let base_path = "hxclasses" in - let pack, name = - let info = t_infos t in - get_real_path info.mt_meta info.mt_path - in - create_dir "." (base_path :: pack); - match pack, name with - | ["flash";"net"], "NetStreamPlayTransitions" - | ["flash";"filters"], "BitmapFilterQuality" - | ["flash";"display"], ("BitmapDataChannel" | "GraphicsPathCommand") -> () - | _ -> - let f = open_out_bin (base_path ^ "/" ^ (match pack with [] -> "" | l -> String.concat "/" l ^ "/") ^ name ^ ".hx") in - let ch = IO.output_channel f in - let p fmt = IO.printf ch fmt in - if pack <> [] then IO.printf ch "package %s;\n\n" (String.concat "." pack); - let rec notnull t = - match t with - | TMono r -> - (match !r with - | None -> t - | Some t -> notnull t) - | TLazy f -> - notnull (lazy_type f) - | TAbstract ({ a_path = [],"Null" },[t]) -> - t - | _ -> - t - in - let rec path meta p tl = - let p = conv_path (get_real_path meta p) in - (if fst p = pack then snd p else s_type_path p) ^ (match tl with [] -> "" | _ -> "<" ^ String.concat "," (List.map stype tl) ^ ">") - and stype t = - match t with - | TMono r -> - (match !r with - | None -> "Unknown" - | Some t -> stype t) - | TInst ({ cl_kind = KTypeParameter _ } as c,tl) -> - path [] ([],snd c.cl_path) tl - | TInst (c,tl) -> - path c.cl_meta c.cl_path tl - | TEnum (e,tl) -> - path e.e_meta e.e_path tl - | TType (t,tl) -> - path t.t_meta t.t_path tl - | TAbstract (a,tl) -> - path a.a_meta a.a_path tl - | TAnon a -> - let fields = PMap.fold (fun f acc -> (f.cf_name ^ " : " ^ stype f.cf_type) :: acc) a.a_fields [] in - "{" ^ String.concat ", " fields ^ "}" - | TLazy f -> - stype (lazy_type f) - | TDynamic t2 -> - if t == t2 then "Dynamic" else "Dynamic<" ^ stype t2 ^ ">" - | TFun ([],ret) -> - "Void -> " ^ ftype ret - | TFun (args,ret) -> - String.concat " -> " (List.map (fun (_,_,t) -> ftype t) args) ^ " -> " ^ ftype ret - and ftype t = - match t with - | TMono r -> - (match !r with - | None -> stype t - | Some t -> ftype t) - | TLazy f -> - ftype (lazy_type f) - | TFun _ -> - "(" ^ stype t ^ ")" - | _ -> - stype t - in - let sparam (n,v,t) = - match v with - | None -> - n ^ " : " ^ stype t - | Some (Ident "null") -> - if is_nullable (notnull t) then - "?" ^ n ^ " : " ^ stype (notnull t) - else - (* we have not found a default value stored in metadata, let's generate it *) - n ^ " : " ^ stype t ^ " = " ^ (match follow t with - | TAbstract ({ a_path = [],("Int"|"Float"|"UInt") },_) -> "0" - | TAbstract ({ a_path = [],"Bool" },_) -> "false" - | _ -> "null") - | Some v -> - n ^ " : " ^ stype t ^ " = " ^ (match s_constant v with "nan" -> "0./*NaN*/" | v -> v) - in - let print_meta ml = - List.iter (fun (m,pl,_) -> - match m with - | Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed | Meta.FlatEnum | Meta.Value | Meta.DirectlyUsed -> () - | _ -> - match pl with - | [] -> p "@%s " (Meta.to_string m) - | l -> p "@%s(%s) " (Meta.to_string m) (String.concat "," (List.map Ast.s_expr pl)) - ) ml - in - let access is_read a = s_access is_read a in - let rec print_field stat f = - p "\t"; - print_meta f.cf_meta; - if stat then p "static "; - let name = try (match Meta.get Meta.RealPath f.cf_meta with - | (Meta.RealPath, [EConst( String s ), _], _) -> - s - | _ -> - raise Not_found) - with Not_found -> - f.cf_name - in - (match f.cf_kind with - | Var v -> - p "var %s" name; - if v.v_read <> AccNormal || v.v_write <> AccNormal then p "(%s,%s)" (access true v.v_read) (access false v.v_write); - p " : %s" (stype f.cf_type); - | Method m -> - let params, ret = (match follow f.cf_type with - | TFun (args,ret) -> - List.map (fun (a,o,t) -> - let rec loop = function - | [] -> Ident "null" - | (Meta.DefParam,[(EConst (String p),_);(EConst v,_)],_) :: _ when p = a -> - (match v with - | Float "1.#QNAN" -> Float "0./*NaN*/" - | Float "4294967295." -> Int "0xFFFFFFFF" - | Int "16777215" -> Int "0xFFFFFF" - | Float x -> - (try - let f = float_of_string x in - let s = string_of_int (int_of_float f) in - if s ^ "." = x then Int s else v - with _ -> - v) - | _ -> v) - | _ :: l -> loop l - in - a,(if o then Some (loop f.cf_meta) else None ),t - ) args, ret - | _ -> - assert false - ) in - let tparams = (match f.cf_params with [] -> "" | l -> "<" ^ String.concat "," (List.map fst l) ^ ">") in - p "function %s%s(%s) : %s" name tparams (String.concat ", " (List.map sparam params)) (stype ret); - ); - p ";\n"; - if Meta.has Meta.Overload f.cf_meta then List.iter (fun f -> print_field stat f) f.cf_overloads - in - (match t with - | TClassDecl c -> - print_meta c.cl_meta; - p "extern %s %s" (if c.cl_interface then "interface" else "class") (stype (TInst (c,List.map snd c.cl_params))); - let ext = (match c.cl_super with - | None -> [] - | Some (c,pl) -> [" extends " ^ stype (TInst (c,pl))] - ) in - let ext = List.fold_left (fun acc (i,pl) -> ((if c.cl_interface then " extends " else " implements ") ^ stype (TInst (i,pl))) :: acc) ext c.cl_implements in - let ext = (match c.cl_dynamic with - | None -> ext - | Some t -> - (match c.cl_path with - | ["flash";"errors"], _ -> ext - | _ when t == t_dynamic -> " implements Dynamic" :: ext - | _ -> (" implements Dynamic<" ^ stype t ^ ">") :: ext) - ) in - let ext = (match c.cl_path with - | ["flash";"utils"], "ByteArray" -> " implements ArrayAccess" :: ext - | ["flash";"utils"], "Dictionary" -> [" implements ArrayAccess"] - | ["flash";"xml"], "XML" -> [" implements Dynamic"] - | ["flash";"xml"], "XMLList" -> [" implements ArrayAccess"] - | ["flash";"display"],"MovieClip" -> [" extends Sprite #if !flash_strict implements Dynamic #end"] - | ["flash";"errors"], "Error" -> [" #if !flash_strict implements Dynamic #end"] - | _ -> ext - ) in - p "%s" (String.concat "" (List.rev ext)); - p " {\n"; - let sort l = - let a = Array.of_list (List.filter (fun f -> f.cf_public && not (List.memq f c.cl_overrides)) l) in - let name = function "new" -> "" | n -> n in - Array.sort (fun f1 f2 -> - match f1.cf_kind, f2.cf_kind with - | Var _, Var _ | Method _ , Method _ -> compare (name f1.cf_name) (name f2.cf_name) - | Var _, _ -> -1 - | _ -> 1 - ) a; - Array.to_list a - in - List.iter (print_field false) (sort (match c.cl_constructor with None -> c.cl_ordered_fields | Some f -> f :: c.cl_ordered_fields)); - List.iter (print_field true) (sort c.cl_ordered_statics); - p "}\n"; - | TEnumDecl e -> - print_meta e.e_meta; - p "extern enum %s {\n" (stype (TEnum(e,List.map snd e.e_params))); - let sort l = - let a = Array.of_list l in - Array.sort compare a; - Array.to_list a - in - List.iter (fun n -> - let c = PMap.find n e.e_constrs in - p "\t%s" c.ef_name; - (match follow c.ef_type with - | TFun (args,_) -> p "(%s)" (String.concat ", " (List.map sparam (List.map (fun (a,o,t) -> a,(if o then Some (Ident "null") else None),t) args))) - | _ -> ()); - p ";\n"; - ) (if Meta.has Meta.FakeEnum e.e_meta then sort e.e_names else e.e_names); - p "}\n" - | TTypeDecl t -> - print_meta t.t_meta; - p "typedef %s = " (stype (TType (t,List.map snd t.t_params))); - p "%s" (stype t.t_type); - p "\n"; - | TAbstractDecl a -> - print_meta a.a_meta; - p "abstract %s {}" (stype (TAbstract (a,List.map snd a.a_params))); - ); - IO.close_out ch - -let generate_hx com = - List.iter (generate_type com) com.types - diff --git a/src/codegen/java.ml b/src/codegen/java.ml index 9e15085595f..35c35fefc48 100644 --- a/src/codegen/java.ml +++ b/src/codegen/java.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,6 +18,7 @@ *) open Unix open ExtString +open NativeLibraries open Common open Globals open Ast @@ -31,6 +32,7 @@ type java_lib_ctx = { jcom : Common.context; (* current tparams context *) mutable jtparams : jtypes list; + is_std : bool; } exception ConversionError of string * pos @@ -73,11 +75,11 @@ let real_java_path ctx (pack,name) = let lookup_jclass com path = let path = jpath_to_hx path in - List.fold_right (fun (_,_,_,_,get_raw_class) acc -> + List.fold_right (fun java_lib acc -> match acc with - | None -> get_raw_class path + | None -> java_lib#lookup path | Some p -> Some p - ) com.java_libs None + ) com.native_libs.java_libs None let mk_type_path ctx path params = let name, sub = try @@ -183,6 +185,11 @@ let rec same_sig parent jsig = | TArray(s,_) -> same_sig parent s | _ -> false +let convert_constraints ctx p tl = match tl with + | [] -> None + | [t] -> Some (convert_signature ctx p t,null_pos) + | tl -> Some (CTIntersection(List.map (fun t -> convert_signature ctx p t,null_pos) tl),null_pos) + let convert_param ctx p parent param = let name, constraints = match param with | (name, Some extends_sig, implem_sig) -> @@ -194,7 +201,7 @@ let convert_param ctx p parent param = { tp_name = jname_to_hx name,null_pos; tp_params = []; - tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) constraints; + tp_constraints = convert_constraints ctx p constraints; tp_meta = []; } @@ -212,6 +219,12 @@ let del_override field = let get_canonical ctx p pack name = (Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst (String name), p], p) +let show_in_completion ctx jc = + if not ctx.is_std then true + else match fst jc.cpath with + | ("java" | "javax" | "org") :: _ -> true + | _ -> false + let convert_java_enum ctx p pe = let meta = ref (get_canonical ctx p (fst pe.cpath) (snd pe.cpath) :: [Meta.Native, [EConst (String (real_java_path ctx pe.cpath) ), p], p ]) in let data = ref [] in @@ -223,6 +236,8 @@ let convert_java_enum ctx p pe = | _ -> () ) pe.cfields; + if not (show_in_completion ctx pe) then meta := (Meta.NoCompletion,[],null_pos) :: !meta; + EEnum { d_name = jname_to_hx (snd pe.cpath),null_pos; d_doc = None; @@ -251,14 +266,14 @@ let convert_java_enum ctx p pe = let readonly = ref false in List.iter (function - | JPublic -> cff_access := APublic :: !cff_access + | JPublic -> cff_access := (APublic,null_pos) :: !cff_access | JPrivate -> raise Exit (* private instances aren't useful on externs *) | JProtected -> cff_meta := (Meta.Protected, [], p) :: !cff_meta; - cff_access := APrivate :: !cff_access - | JStatic -> cff_access := AStatic :: !cff_access + cff_access := (APrivate,null_pos) :: !cff_access + | JStatic -> cff_access := (AStatic,null_pos) :: !cff_access | JFinal -> - cff_meta := (Meta.Final, [], p) :: !cff_meta; + cff_access := (AFinal, p) :: !cff_access; (match field.jf_kind, field.jf_vmsignature, field.jf_constant with | JKField, TObject _, _ -> jf_constant := None @@ -279,7 +294,7 @@ let convert_java_enum ctx p pe = | AttrVisibleAnnotations ann -> List.iter (function | { ann_type = TObject( (["java";"lang"], "Override"), [] ) } -> - cff_access := AOverride :: !cff_access + cff_access := (AOverride,null_pos) :: !cff_access | _ -> () ) ann | _ -> () @@ -311,20 +326,19 @@ let convert_java_enum ctx p pe = ) args in let t = Option.map_default (convert_signature ctx p) (mk_type_path ctx ([], "Void") []) ret in cff_meta := (Meta.Overload, [], p) :: !cff_meta; - let types = List.map (function | (name, Some ext, impl) -> { tp_name = name,null_pos; tp_params = []; - tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) (ext :: impl); + tp_constraints = convert_constraints ctx p (ext :: impl); tp_meta = []; } | (name, None, impl) -> { tp_name = name,null_pos; tp_params = []; - tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) (impl); + tp_constraints = convert_constraints ctx p impl; tp_meta = []; } ) field.jf_types in @@ -357,7 +371,7 @@ let convert_java_enum ctx p pe = (Meta.Native, [EConst (String (cff_name) ), cff_pos], cff_pos) :: !cff_meta in if PMap.mem "java_loader_debug" ctx.jcom.defines.Define.values then - Printf.printf "\t%s%sfield %s : %s\n" (if List.mem AStatic !cff_access then "static " else "") (if List.mem AOverride !cff_access then "override " else "") cff_name (s_sig field.jf_signature); + Printf.printf "\t%s%sfield %s : %s\n" (if List.mem_assoc AStatic !cff_access then "static " else "") (if List.mem_assoc AOverride !cff_access then "override " else "") cff_name (s_sig field.jf_signature); { cff_name = cff_name,null_pos; @@ -410,7 +424,7 @@ let convert_java_enum ctx p pe = let is_interface = ref false in List.iter (fun f -> match f with - | JFinal -> meta := (Meta.Final, [], p) :: !meta + | JFinal -> flags := HFinal :: !flags | JInterface -> is_interface := true; flags := HInterface :: !flags @@ -462,6 +476,8 @@ let convert_java_enum ctx p pe = ) f.jf_throws ) jc.cmethods) in + if not (show_in_completion ctx jc) then meta := (Meta.NoCompletion,[],null_pos) :: !meta; + (EClass { d_name = jname_to_hx (snd jc.cpath),null_pos; d_doc = None; @@ -471,10 +487,11 @@ let convert_java_enum ctx p pe = d_data = !fields; }) :: imports - let create_ctx com = + let create_ctx com is_std = { jcom = com; jtparams = []; + is_std = is_std; } let rec has_type_param = function @@ -589,7 +606,7 @@ let jclass_with_params com cls params = try cinterfaces = List.map (japply_params jparams) cls.cinterfaces; } with Invalid_argument _ -> - if com.verbose then prerr_endline ("Differing parameters for class: " ^ s_type_path cls.cpath); + if com.verbose then print_endline ("Differing parameters for class: " ^ s_type_path cls.cpath); cls let is_object = function | TObject( (["java";"lang"], "Object"), [] ) -> true | _ -> false @@ -643,8 +660,8 @@ let compare_type com s1 s2 = let implements = List.map (japply_params jparams) c.cinterfaces in loop ~first_error:first_error super s2 || List.exists (fun super -> loop ~first_error:first_error super s2) implements with | Not_found -> - prerr_endline ("-java-lib: The type " ^ (s_sig s1) ^ " is referred but was not found. Compilation may not occur correctly."); - prerr_endline "Did you forget to include a needed lib?"; + print_endline ("-java-lib: The type " ^ (s_sig s1) ^ " is referred but was not found. Compilation may not occur correctly."); + print_endline "Did you forget to include a needed lib?"; if first_error then not (loop ~first_error:false s2 s1) else @@ -677,13 +694,13 @@ let select_best com flist = | -1 -> loop cur_best flist | -2 -> (* error - no type is compatible *) - if com.verbose then prerr_endline (f.jf_name ^ ": The types " ^ (s_sig r) ^ " and " ^ (s_sig r2) ^ " are incompatible"); + if com.verbose then print_endline (f.jf_name ^ ": The types " ^ (s_sig r) ^ " and " ^ (s_sig r2) ^ " are incompatible"); (* bet that the current best has "beaten" other types *) loop cur_best flist | _ -> assert false with | Exit -> (* incompatible type parameters *) (* error mode *) - if com.verbose then prerr_endline (f.jf_name ^ ": Incompatible argument return signatures: " ^ (s_sig r) ^ " and " ^ (s_sig r2)); + if com.verbose then print_endline (f.jf_name ^ ": Incompatible argument return signatures: " ^ (s_sig r) ^ " and " ^ (s_sig r2)); None) | TMethod _, _ -> (* select the method *) loop f flist @@ -774,7 +791,7 @@ let normalize_jclass com cls = List.iter (fun jf -> if not(List.mem JStatic jf.jf_flags) && not (List.exists (fun jf2 -> jf.jf_name = jf2.jf_name && not (List.mem JStatic jf2.jf_flags) && jf.jf_signature = jf2.jf_signature) all_methods) then begin let jf = if abstract && force_check then del_override jf else jf in - let jf = { jf with jf_flags = JPublic :: jf.jf_flags } in (* interfaces implementations are always public *) + let jf = if not (List.mem JPublic jf.jf_flags) then { jf with jf_flags = JPublic :: jf.jf_flags } else jf in (* interfaces implementations are always public *) added_interface_fields := jf :: !added_interface_fields; end @@ -886,101 +903,15 @@ let get_classes_zip zip = ) (Zip.entries zip); !ret -let add_java_lib com file std = - let file = if Sys.file_exists file then - file - else try Common.find_file com file with - | Not_found -> try Common.find_file com (file ^ ".jar") with - | Not_found -> - failwith ("Java lib " ^ file ^ " not found") - in - let hxpack_to_jpack = Hashtbl.create 16 in - let get_raw_class, close, list_all_files = - (* check if it is a directory or jar file *) - match (Unix.stat file).st_kind with - | S_DIR -> (* open classes directly from directory *) - let all = ref [] in - let rec iter_files pack dir path = try - let file = Unix.readdir dir in - let filepath = path ^ "/" ^ file in - (if String.ends_with file ".class" then - let name = String.sub file 0 (String.length file - 6) in - let path = jpath_to_hx (pack,name) in - if not (String.exists file "$") then all := path :: !all; - Hashtbl.add hxpack_to_jpack path (pack,name) - else if (Unix.stat filepath).st_kind = S_DIR && file <> "." && file <> ".." then - let pack = pack @ [file] in - iter_files (pack) (Unix.opendir filepath) filepath); - iter_files pack dir path - with | End_of_file | Unix.Unix_error _ -> - Unix.closedir dir - in - iter_files [] (Unix.opendir file) file; - let all = !all in - - (fun (pack, name) -> - let real_path = file ^ "/" ^ (String.concat "/" pack) ^ "/" ^ (name ^ ".class") in - try - let data = Std.input_file ~bin:true real_path in - Some(JReader.parse_class (IO.input_string data), real_path, real_path) - with - | _ -> None), (fun () -> ()), (fun () -> all) - | _ -> (* open zip file *) - let closed = ref false in - let zip = ref (Zip.open_in file) in - let check_open () = - if !closed then begin - prerr_endline ("JAR file " ^ file ^ " already closed"); (* if this happens, find when *) - zip := Zip.open_in file; - closed := false - end - in - List.iter (function - | { Zip.is_directory = false; Zip.filename = filename } when String.ends_with filename ".class" -> - let pack = String.nsplit filename "/" in - (match List.rev pack with - | [] -> () - | name :: pack -> - let name = String.sub name 0 (String.length name - 6) in - let pack = List.rev pack in - Hashtbl.add hxpack_to_jpack (jpath_to_hx (pack,name)) (pack,name)) - | _ -> () - ) (Zip.entries !zip); - (fun (pack, name) -> - check_open(); - try - let location = (String.concat "/" (pack @ [name]) ^ ".class") in - let entry = Zip.find_entry !zip location in - let data = Zip.read_entry !zip entry in - Some(JReader.parse_class (IO.input_string data), file, file ^ "@" ^ location) - with - | Not_found -> - None), - (fun () -> if not !closed then begin closed := true; Zip.close_in !zip end), - (fun () -> check_open(); get_classes_zip !zip) - in - let cached_types = Hashtbl.create 12 in - let get_raw_class path = - try - Hashtbl.find cached_types path - with | Not_found -> try - let pack, name = Hashtbl.find hxpack_to_jpack path in - let try_file (pack,name) = - match get_raw_class (pack,name) with - | None -> - Hashtbl.add cached_types path None; - None - | Some (i, p1, p2) -> - Hashtbl.add cached_types path (Some(i,p1,p2)); (* type loop normalization *) - let ret = Some (normalize_jclass com i, p1, p2) in - Hashtbl.replace cached_types path ret; - ret - in - try_file (pack,name) - with Not_found -> - None - in - let replace_canonical_name p pack name_original name_replace decl = +class virtual java_library com name file_path = object(self) + inherit [java_lib_type,unit] native_library name file_path as super + + val hxpack_to_jpack = Hashtbl.create 16 + + method convert_path (path : path) : path = + Hashtbl.find hxpack_to_jpack path + + method private replace_canonical_name p pack name_original name_replace decl = let mk_meta name = (Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst(String name), p], p) in let add_meta name metas = if Meta.has Meta.JavaCanonical metas then @@ -1002,145 +933,279 @@ let add_java_lib com file std = | EAbstract a -> EAbstract { a with d_meta = add_meta (fst a.d_name) a.d_meta } | d -> d - in - let rec build ctx path p types = + + method build path (p : pos) : Ast.package option = + let rec build ctx path p types = + try + if List.mem path !types then + None + else begin + let first = match !types with + | [ ["java";"lang"], "String" ] | [] -> true + | p :: _ -> + false + in + types := path :: !types; + match self#lookup path, path with + | None, ([], c) -> build ctx (["haxe";"root"], c) p types + | None, _ -> None + | Some (cls, real_path, pos_path), _ -> + let is_disallowed_inner = first && String.exists (snd cls.cpath) "$" in + let is_disallowed_inner = if is_disallowed_inner then begin + let outer, inner = String.split (snd cls.cpath) "$" in + match self#lookup (fst path, outer) with + | None -> false + | _ -> true + end else + false + in + if is_disallowed_inner then + None + else begin + if ctx.jcom.verbose then print_endline ("Parsed Java class " ^ (s_type_path cls.cpath)); + let old_types = ctx.jtparams in + ctx.jtparams <- cls.ctypes :: ctx.jtparams; + + let pos = { pfile = pos_path; pmin = 0; pmax = 0; } in + + let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in + + let ppath = self#convert_path path in + let inner = List.fold_left (fun acc (path,out,_,_) -> + let path = jpath_to_hx path in + (if out <> Some ppath then + acc + else match build ctx path p types with + | Some(_, classes) -> + let base = snd ppath ^ "$" in + (List.map (fun (def,p) -> + self#replace_canonical_name p (fst ppath) base (snd ppath ^ ".") def, p) classes) @ acc + | _ -> acc); + ) [] cls.cinner_types in + + (* add _Statics class *) + let inner = try + if not (List.mem JInterface cls.cflags) then raise Not_found; + let smethods = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cmethods in + let sfields = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cfields in + if not (smethods <> [] || sfields <> []) then raise Not_found; + let obj = TObject( (["java";"lang"],"Object"), []) in + let ncls = convert_java_class ctx pos { cls with cmethods = smethods; cfields = sfields; cflags = []; csuper = obj; cinterfaces = []; cinner_types = []; ctypes = [] } in + match ncls with + | EClass c :: imports -> + (EClass { c with d_name = (fst c.d_name ^ "_Statics"),snd c.d_name }, pos) :: inner @ List.map (fun i -> i,pos) imports + | _ -> assert false + with | Not_found -> + inner + in + let inner_alias = ref SS.empty in + List.iter (fun x -> + match fst x with + | EClass c -> + inner_alias := SS.add (fst c.d_name) !inner_alias; + | _ -> () + ) inner; + let alias_list = ref [] in + List.iter (fun x -> + match x with + | (EClass c, pos) -> begin + let parts = String.nsplit (fst c.d_name) "_24" in + match parts with + | _ :: _ -> + let alias_name = String.concat "_" parts in + if (not (SS.mem alias_name !inner_alias)) && (not (String.exists (snd path) "_24")) then begin + let alias_def = ETypedef { + d_name = alias_name,null_pos; + d_doc = None; + d_params = c.d_params; + d_meta = []; + d_flags = []; + d_data = CTPath { + tpackage = pack; + tname = snd path; + tparams = List.map (fun tp -> + TPType (CTPath { + tpackage = []; + tname = fst tp.tp_name; + tparams = []; + tsub = None; + },null_pos) + ) c.d_params; + tsub = Some(fst c.d_name); + },null_pos; + } in + inner_alias := SS.add alias_name !inner_alias; + alias_list := (alias_def, pos) :: !alias_list; + end + | _ -> () + end + | _ -> () + ) inner; + let inner = List.concat [!alias_list ; inner] in + let classes = List.map (fun t -> t,pos) (convert_java_class ctx pos cls) in + let imports, defs = List.partition (function | (EImport(_),_) -> true | _ -> false) (classes @ inner) in + let ret = Some (pack, imports @ defs) in + ctx.jtparams <- old_types; + ret + end + end + with + | JReader.Error_message msg -> + print_endline ("Class reader failed: " ^ msg); + None + | e -> + if ctx.jcom.verbose then begin + (* print_endline (Printexc.get_backtrace ()); requires ocaml 3.11 *) + print_endline (Printexc.to_string e) + end; + None + in + build (create_ctx com (self#has_flag FlagIsStd)) path p (ref [["java";"lang"], "String"]) + + method get_data = () +end + +class java_library_jar com name file_path = object(self) + inherit java_library com name file_path + + val zip = lazy (Zip.open_in file_path) + val mutable cached_files = None + val cached_types = Hashtbl.create 12 + val mutable closed = false + + method load = + List.iter (function + | { Zip.is_directory = false; Zip.filename = filename } when String.ends_with filename ".class" -> + let pack = String.nsplit filename "/" in + (match List.rev pack with + | [] -> () + | name :: pack -> + let name = String.sub name 0 (String.length name - 6) in + let pack = List.rev pack in + Hashtbl.add hxpack_to_jpack (jpath_to_hx (pack,name)) (pack,name)) + | _ -> () + ) (Zip.entries (Lazy.force zip)) + + method private lookup' ((pack,name) : path) : java_lib_type = try - if List.mem path !types then + let zip = Lazy.force zip in + let location = (String.concat "/" (pack @ [name]) ^ ".class") in + let entry = Zip.find_entry zip location in + let data = Zip.read_entry zip entry in + Some(JReader.parse_class (IO.input_string data), file_path, file_path ^ "@" ^ location) + with + | Not_found -> None - else begin - let first = match !types with - | [ ["java";"lang"], "String" ] | [] -> true - | p :: _ -> - false - in - types := path :: !types; - match get_raw_class path, path with - | None, ([], c) -> build ctx (["haxe";"root"], c) p types - | None, _ -> None - | Some (cls, real_path, pos_path), _ -> - let is_disallowed_inner = first && String.exists (snd cls.cpath) "$" in - let is_disallowed_inner = if is_disallowed_inner then begin - let outer, inner = String.split (snd cls.cpath) "$" in - match get_raw_class (fst path, outer) with - | None -> false - | _ -> true - end else - false - in - if is_disallowed_inner then - None - else begin - if com.verbose then print_endline ("Parsed Java class " ^ (s_type_path cls.cpath)); - let old_types = ctx.jtparams in - ctx.jtparams <- cls.ctypes :: ctx.jtparams; - - let pos = { pfile = pos_path; pmin = 0; pmax = 0; } in - - let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in - - let ppath = Hashtbl.find hxpack_to_jpack path in - let inner = List.fold_left (fun acc (path,out,_,_) -> - let path = jpath_to_hx path in - (if out <> Some ppath then - acc - else match build ctx path p types with - | Some(_,(_, classes)) -> - let base = snd ppath ^ "$" in - (List.map (fun (def,p) -> - replace_canonical_name p (fst ppath) base (snd ppath ^ ".") def, p) classes) @ acc - | _ -> acc); - ) [] cls.cinner_types in - - (* add _Statics class *) - let inner = try - if not (List.mem JInterface cls.cflags) then raise Not_found; - let smethods = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cmethods in - let sfields = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cfields in - if not (smethods <> [] || sfields <> []) then raise Not_found; - let obj = TObject( (["java";"lang"],"Object"), []) in - let ncls = convert_java_class ctx pos { cls with cmethods = smethods; cfields = sfields; cflags = []; csuper = obj; cinterfaces = []; cinner_types = []; ctypes = [] } in - match ncls with - | EClass c :: imports -> - (EClass { c with d_name = (fst c.d_name ^ "_Statics"),snd c.d_name }, pos) :: inner @ List.map (fun i -> i,pos) imports - | _ -> assert false - with | Not_found -> - inner - in - let inner_alias = ref SS.empty in - List.iter (fun x -> - match fst x with - | EClass c -> - inner_alias := SS.add (fst c.d_name) !inner_alias; - | _ -> () - ) inner; - let alias_list = ref [] in - List.iter (fun x -> - match x with - | (EClass c, pos) -> begin - let parts = String.nsplit (fst c.d_name) "_24" in - match parts with - | _ :: _ -> - let alias_name = String.concat "_" parts in - if (not (SS.mem alias_name !inner_alias)) && (not (String.exists (snd path) "_24")) then begin - let alias_def = ETypedef { - d_name = alias_name,null_pos; - d_doc = None; - d_params = c.d_params; - d_meta = []; - d_flags = []; - d_data = CTPath { - tpackage = pack; - tname = snd path; - tparams = List.map (fun tp -> - TPType (CTPath { - tpackage = []; - tname = fst tp.tp_name; - tparams = []; - tsub = None; - },null_pos) - ) c.d_params; - tsub = Some(fst c.d_name); - },null_pos; - } in - inner_alias := SS.add alias_name !inner_alias; - alias_list := (alias_def, pos) :: !alias_list; - end - | _ -> () - end - | _ -> () - ) inner; - let inner = List.concat [!alias_list ; inner] in - let classes = List.map (fun t -> t,pos) (convert_java_class ctx pos cls) in - let imports, defs = List.partition (function | (EImport(_),_) -> true | _ -> false) (classes @ inner) in - let ret = Some ( real_path, (pack, imports @ defs) ) in - ctx.jtparams <- old_types; - ret + + method lookup (path : path) : java_lib_type = + try + Hashtbl.find cached_types path + with | Not_found -> try + let pack, name = self#convert_path path in + let try_file (pack,name) = + match self#lookup' (pack,name) with + | None -> + Hashtbl.add cached_types path None; + None + | Some (i, p1, p2) -> + Hashtbl.add cached_types path (Some(i,p1,p2)); (* type loop normalization *) + let ret = Some (normalize_jclass com i, p1, p2) in + Hashtbl.replace cached_types path ret; + ret + in + try_file (pack,name) + with Not_found -> + None + + method close = + if not closed then begin + closed <- true; + Zip.close_in (Lazy.force zip) + end + + method private list_modules' : path list = + let ret = ref [] in + List.iter (function + | { Zip.is_directory = false; Zip.filename = f } when (String.sub (String.uncapitalize f) (String.length f - 6) 6) = ".class" && not (String.exists f "$") -> + (match List.rev (String.nsplit f "/") with + | clsname :: pack -> + if not (String.contains clsname '$') then begin + let path = jpath_to_hx (List.rev pack, String.sub clsname 0 (String.length clsname - 6)) in + ret := path :: !ret end - end + | _ -> + ret := ([], jname_to_hx f) :: !ret) + | _ -> () + ) (Zip.entries (Lazy.force zip)); + !ret + + method list_modules : path list = match cached_files with + | None -> + let ret = self#list_modules' in + cached_files <- Some ret; + ret + | Some r -> + r +end + +class java_library_dir com name file_path = object(self) + inherit java_library com name file_path + + val mutable files = [] + + method load = + let all = ref [] in + let rec iter_files pack dir path = try + let file = Unix.readdir dir in + let filepath = path ^ "/" ^ file in + (if String.ends_with file ".class" then + let name = String.sub file 0 (String.length file - 6) in + let path = jpath_to_hx (pack,name) in + if not (String.exists file "$") then all := path :: !all; + Hashtbl.add hxpack_to_jpack path (pack,name) + else if (Unix.stat filepath).st_kind = S_DIR && file <> "." && file <> ".." then + let pack = pack @ [file] in + iter_files (pack) (Unix.opendir filepath) filepath); + iter_files pack dir path + with | End_of_file | Unix.Unix_error _ -> + Unix.closedir dir + in + iter_files [] (Unix.opendir file_path) file_path; + files <- !all + + method close = + () + + method list_modules = + files + + method lookup (pack,name) : java_lib_type = + let real_path = file_path ^ "/" ^ (String.concat "/" pack) ^ "/" ^ (name ^ ".class") in + try + let data = Std.input_file ~bin:true real_path in + Some(JReader.parse_class (IO.input_string data), real_path, real_path) with - | JReader.Error_message msg -> - prerr_endline ("Class reader failed: " ^ msg); - None - | e -> - if com.verbose then begin - (* prerr_endline (Printexc.get_backtrace ()); requires ocaml 3.11 *) - prerr_endline (Printexc.to_string e) - end; - None + | _ -> None +end + +let add_java_lib com name std extern = + let file = if Sys.file_exists name then + name + else try Common.find_file com name with + | Not_found -> try Common.find_file com (name ^ ".jar") with + | Not_found -> + failwith ("Java lib " ^ name ^ " not found") in - let build path p = build (create_ctx com) path p (ref [["java";"lang"], "String"]) in - let cached_files = ref None in - let list_all_files () = match !cached_files with - | None -> - let ret = list_all_files () in - cached_files := Some ret; - ret - | Some r -> r + let java_lib = match (Unix.stat file).st_kind with + | S_DIR -> + (new java_library_dir com name file :> java_library) + | _ -> + (new java_library_jar com name file :> java_library) in - - (* TODO: add_dependency m mdep *) - com.load_extern_type <- com.load_extern_type @ [build]; - com.java_libs <- (file, std, close, list_all_files, get_raw_class) :: com.java_libs + if std then java_lib#add_flag FlagIsStd; + if extern then java_lib#add_flag FlagIsExtern; + com.native_libs.java_libs <- (java_lib :> (java_lib_type,unit) native_library) :: com.native_libs.java_libs; + CompilationServer.handle_native_lib com java_lib let before_generate con = let java_ver = try diff --git a/src/codegen/swfLoader.ml b/src/codegen/swfLoader.ml index 50964fa37c1..d38ad6a32af 100644 --- a/src/codegen/swfLoader.ml +++ b/src/codegen/swfLoader.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -22,6 +22,35 @@ open As3hl open Common open Globals open Ast +open NativeLibraries + +let lowercase_pack pack = + let rec loop acc pack = + match pack with + | [] -> List.rev acc + | name :: rest -> + let name = + let fchar = String.get name 0 in + if fchar >= 'A' && fchar <= 'Z' then + (String.make 1 (Char.lowercase fchar)) ^ String.sub name 1 (String.length name - 1) + else + name + in + loop (name :: acc) rest + in + loop [] pack + + +let tp_dyn = { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; } + +let ct_dyn = CTPath tp_dyn + +let ct_rest = CTPath { + tpackage = ["haxe"; "extern"]; + tname = "Rest"; + tparams = [TPType (ct_dyn,null_pos)]; + tsub = None; +} let rec make_tpath = function | HMPath (pack,name) -> @@ -42,12 +71,12 @@ let rec make_tpath = function | [] , "Namespace" -> ["flash";"utils"], "Namespace" | [] , "RegExp" -> ["flash";"utils"], "RegExp" | ["__AS3__";"vec"] , "Vector" -> ["flash"], "Vector" - | _ -> pack, name + | _ -> lowercase_pack pack, name in { tpackage = pack; tname = name; - tparams = if !pdyn then [TPType (CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; },null_pos)] else[]; + tparams = if !pdyn then [TPType (ct_dyn,null_pos)] else[]; tsub = None; } | HMName (id,ns) -> @@ -89,7 +118,7 @@ let rec make_tpath = function { (make_tpath t) with tparams = params } let make_topt = function - | None -> { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None } + | None -> tp_dyn | Some t -> make_tpath t let make_type t = CTPath (make_topt t) @@ -103,10 +132,10 @@ let is_valid_path com pack name = let rec loop = function | [] -> false - | load :: l -> + | (file,load) :: l -> match load (pack,name) null_pos with | None -> loop l - | Some (file,(_,a)) -> true + | Some (_,a) -> true in let file = Printf.sprintf "%s/%s.hx" (String.concat "/" pack) name in loop com.load_extern_type || (try ignore(Common.find_file com file); true with Not_found -> false) @@ -122,7 +151,7 @@ let build_class com c file = d_params = []; d_meta = []; d_flags = []; - d_data = CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; },null_pos; + d_data = ct_dyn,null_pos; } in (path.tpackage, [(ETypedef inf,pos)]) | _ -> @@ -148,7 +177,7 @@ let build_class com c file = ) in if c.hlc_interface then HExtends (make_tpath i,null_pos) else HImplements (make_tpath i,null_pos) ) (Array.to_list c.hlc_implements) @ flags in - let flags = if c.hlc_sealed || Common.defined com Define.FlashStrict then flags else HImplements (make_tpath (HMPath ([],"Dynamic")),null_pos) :: flags in + let flags = if c.hlc_sealed || Common.defined com Define.FlashStrict then flags else HImplements (tp_dyn,null_pos) :: flags in (* make fields *) let getters = Hashtbl.create 0 in let setters = Hashtbl.create 0 in @@ -160,22 +189,25 @@ let build_class com c file = let make_field stat acc f = let meta = ref [] in let flags = (match f.hlf_name with - | HMPath _ -> [APublic] + | HMPath _ -> [APublic,null_pos] | HMName (_,ns) -> (match ns with | HNPrivate _ | HNNamespace "http://www.adobe.com/2006/flex/mx/internal" -> [] | HNNamespace ns -> if not (c.hlc_interface || is_xml) then meta := (Meta.Ns,[String ns]) :: !meta; - [APublic] + [APublic,null_pos] + | HNInternal (Some ns) -> + if not (c.hlc_interface || is_xml) then meta := (Meta.Ns,[String ns; Ident "internal"]) :: !meta; + [APublic,null_pos] | HNExplicit _ | HNInternal _ | HNPublic _ -> - [APublic] + [APublic,null_pos] | HNStaticProtected _ | HNProtected _ -> meta := (Meta.Protected,[]) :: !meta; - [APrivate]) + [APrivate,null_pos]) | _ -> [] ) in if flags = [] then acc else - let flags = if stat then AStatic :: flags else flags in + let flags = if stat then (AStatic,null_pos) :: flags else flags in let name = (make_tpath f.hlf_name).tname in let mk_meta() = List.map (fun (s,cl) -> s, List.map (fun c -> EConst c,pos) cl, pos) (!meta) @@ -184,16 +216,17 @@ let build_class com c file = cff_name = name,null_pos; cff_doc = None; cff_pos = pos; - cff_meta = mk_meta(); + cff_meta = []; cff_access = flags; cff_kind = FVar (None,None); } in match f.hlf_kind with | HFVar v -> - if v.hlv_const then - cf.cff_kind <- FProp (("default",null_pos),("never",null_pos),Some (make_type v.hlv_type,null_pos),None) - else - cf.cff_kind <- FVar (Some (make_dyn_type v.hlv_type,null_pos),None); + cf.cff_meta <- mk_meta(); + cf.cff_kind <- FVar (Some (make_dyn_type v.hlv_type,null_pos),None); + if v.hlv_const then begin + cf.cff_access <- (AFinal,null_pos) :: cf.cff_access; + end; cf :: acc | HFMethod m when m.hlm_override -> Hashtbl.add override (name,stat) (); @@ -235,19 +268,19 @@ let build_class com c file = | HVInt i | HVUInt i -> Some (Int (Int32.to_string i)) | HVFloat f -> - Some (Float (float_repres f)) + Some (Float (Numeric.float_repres f)) ) in match v with | None -> None | Some v -> - (* add for --gen-hx-classes generation *) + (* add for -D gen-hx-classes generation *) meta := (Meta.DefParam,[String aname;v]) :: !meta; Some (EConst v,pos) in ((aname,null_pos),!is_opt,[],Some (t,null_pos),def_val) ) t.hlmt_args in let args = if t.hlmt_var_args then - args @ List.map (fun _ -> incr pn; (("p" ^ string_of_int !pn,null_pos),true,[],Some (make_type None,null_pos),None)) [1;2;3;4;5] + args @ [("restArgs",null_pos),false,[],Some (ct_rest,null_pos),None] else args in let f = { f_params = []; @@ -259,10 +292,10 @@ let build_class com c file = cf.cff_kind <- FFun f; cf :: acc | MK3Getter -> - Hashtbl.add getters (name,stat) m.hlm_type.hlmt_ret; + Hashtbl.add getters (name,stat) (m.hlm_type.hlmt_ret,mk_meta()); acc | MK3Setter -> - Hashtbl.add setters (name,stat) (match m.hlm_type.hlmt_args with [t] -> t | _ -> assert false); + Hashtbl.add setters (name,stat) ((match m.hlm_type.hlmt_args with [t] -> t | _ -> assert false),mk_meta()); acc ) | _ -> acc @@ -281,84 +314,141 @@ let build_class com c file = let fields = Array.fold_left (make_field false) fields c.hlc_fields in let fields = Array.fold_left (make_field true) fields c.hlc_static_fields in let make_get_set name stat tget tset = - let get, set, t = (match tget, tset with + let get, set, t, meta = (match tget, tset with | None, None -> assert false - | Some t, None -> true, false, t - | None, Some t -> false, true, t - | Some t1, Some t2 -> true, true, (if t1 <> t2 then None else t1) + | Some (t,meta), None -> true, false, t, meta + | None, Some (t,meta) -> false, true, t, meta + | Some (t1,meta1), Some (t2,meta2) -> true, true, (if t1 <> t2 then None else t1), meta1 @ (List.filter (fun m -> not (List.mem m meta1)) meta2) ) in let t = if name = "endian" then Some (HMPath (["flash";"utils"],"Endian")) else t in - let flags = [APublic] in - let flags = if stat then AStatic :: flags else flags in + let flags, accessor_flags = [APublic,null_pos], [APrivate,null_pos] in + let flags, accessor_flags = if stat then (AStatic,null_pos) :: flags, (AStatic,null_pos) :: accessor_flags else flags, accessor_flags in + let property_typehint = Some (make_dyn_type t,null_pos) in + let fields = [] in + let read_access, fields = + if get then + let getter = { + cff_name = "get_" ^ name,null_pos; + cff_pos = pos; + cff_doc = None; + cff_access = accessor_flags; + cff_meta = []; + cff_kind = FFun { + f_params = []; + f_args = []; + f_type = property_typehint; + f_expr = None; + }; + } in + ("get",null_pos), getter :: fields + else + ("never",null_pos), fields + in + let write_access, fields = + if set then + let setter = { + cff_name = "set_" ^ name,null_pos; + cff_pos = pos; + cff_doc = None; + cff_access = accessor_flags; + cff_meta = []; + cff_kind = FFun { + f_params = []; + f_args = [(("value",null_pos),false,[],property_typehint,None)]; + f_type = property_typehint; + f_expr = None; + }; + } in + ("set",null_pos), setter :: fields + else + ("never",null_pos), fields + in { cff_name = name,null_pos; cff_pos = pos; cff_doc = None; cff_access = flags; - cff_meta = []; - cff_kind = if get && set then FVar (Some (make_dyn_type t,null_pos), None) else FProp (((if get then "default" else "never"),null_pos),((if set then "default" else "never"),null_pos),Some (make_dyn_type t,null_pos),None); - } + cff_meta = (Meta.FlashProperty,[],pos) :: meta; + cff_kind = FProp (read_access,write_access,property_typehint,None); + } :: fields in let fields = Hashtbl.fold (fun (name,stat) t acc -> if Hashtbl.mem override (name,stat) then acc else - make_get_set name stat (Some t) (try Some (Hashtbl.find setters (name,stat)) with Not_found -> None) :: acc + make_get_set name stat (Some t) (try Some (Hashtbl.find setters (name,stat)) with Not_found -> None) @ acc ) getters fields in let fields = Hashtbl.fold (fun (name,stat) t acc -> if Hashtbl.mem getters (name,stat) || Hashtbl.mem override (name,stat) then acc else - make_get_set name stat None (Some t) :: acc + make_get_set name stat None (Some t) @ acc ) setters fields in try (* If the class only contains static String constants, make it an enum *) - let real_type = ref "" in + let real_type = ref None in let rec loop = function | [] -> [] | f :: l -> match f.cff_kind with - | FVar (Some (CTPath { tpackage = []; tname = ("String" | "Int" | "UInt") as tname },null_pos),None) - | FProp (("default",_),("never",_),Some (CTPath { tpackage = []; tname = ("String" | "Int" | "UInt") as tname },null_pos),None) when List.mem AStatic f.cff_access -> - if !real_type = "" then real_type := tname else if !real_type <> tname then raise Exit; + | FVar (Some ((CTPath { tpackage = []; tname = ("String" | "Int" | "UInt")} as real_t),_),None) + | FProp (("default",_),("never",_),Some ((CTPath { tpackage = []; tname = ("String" | "Int" | "UInt")}) as real_t,_),None) when List.mem_assoc AStatic f.cff_access -> + (match !real_type with + | None -> + real_type := Some real_t + | Some t -> + if t <> real_t then raise Exit); { - ec_name = f.cff_name; - ec_pos = pos; - ec_args = []; - ec_params = []; - ec_meta = []; - ec_doc = None; - ec_type = None; + cff_name = f.cff_name; + cff_doc = None; + cff_pos = pos; + cff_meta = []; + cff_access = []; + cff_kind = FVar (Some (real_t,null_pos), None); } :: loop l | FFun { f_args = [] } when fst f.cff_name = "new" -> loop l | _ -> raise Exit in List.iter (function HExtends _ | HImplements _ -> raise Exit | _ -> ()) flags; let constr = loop fields in - let name = "fakeEnum:" ^ String.concat "." (path.tpackage @ [path.tname]) in + let name = "enumAbstract:" ^ String.concat "." (path.tpackage @ [path.tname]) in if not (Common.raw_defined com name) then raise Exit; - let enum_data = { + let native_path = s_type_path (path.tpackage, path.tname) in + let real_type = Option.get !real_type in + let abstract_data = { d_name = path.tname,null_pos; d_doc = None; d_params = []; - d_meta = [(Meta.FakeEnum,[EConst (Ident !real_type),pos],pos)]; - d_flags = [EExtern]; + d_meta = [(Meta.Enum,[],null_pos);(Meta.Native,[(EConst (String native_path),null_pos)],null_pos)]; + d_flags = [AbExtern; AbOver (real_type,pos); AbFrom (real_type,pos)]; d_data = constr; } in - (path.tpackage, [(EEnum enum_data,pos)]) + (path.tpackage, [(EAbstract abstract_data,pos)]) with Exit -> + let flags = if c.hlc_final && List.exists (fun f -> fst f.cff_name <> "new" && not (List.mem_assoc AStatic f.cff_access)) fields then HFinal :: flags else flags in + + let meta = + (* if the package was lowercased, add @:native("Original.Path") meta *) + match c.hlc_name with + | HMPath (pack,name) when (pack <> [] && pack <> path.tpackage) -> + let native_path = (String.concat "." pack) ^ "." ^ name in + [(Meta.Native,[(EConst (String native_path), pos)],pos)] + | _ -> + [] + in + let class_data = { d_name = path.tname,null_pos; d_doc = None; d_params = []; - d_meta = if c.hlc_final && List.exists (fun f -> fst f.cff_name <> "new" && not (List.mem AStatic f.cff_access)) fields then [Meta.Final,[],pos] else []; + d_meta = meta; d_flags = flags; d_data = fields; } in (path.tpackage, [(EClass class_data,pos)]) let extract_data (_,tags) = - let t = Common.timer ["read";"swf"] in + let t = Timer.timer ["read";"swf"] in let h = Hashtbl.create 0 in let rec loop_field f = match f.hlf_kind with @@ -450,9 +540,8 @@ let remove_debug_infos as3 = As3hlparse.flatten (List.map loop_static hl) let parse_swf com file = - let t = Common.timer ["read";"swf"] in + let t = Timer.timer ["read";"swf"] in let is_swc = file_extension file = "swc" || file_extension file = "ane" in - let file = (try Common.find_file com file with Not_found -> failwith ((if is_swc then "SWC" else "SWF") ^ " Library not found : " ^ file)) in let ch = if is_swc then begin let zip = Zip.open_in file in try @@ -476,46 +565,75 @@ let parse_swf com file = IO.close_in ch; List.iter (fun t -> match t.tdata with - | TActionScript3 (id,as3) when not com.debug && not com.display.DisplayMode.dms_display -> + | TActionScript3 (id,as3) when not com.debug && not com.display.DisplayTypes.DisplayMode.dms_display -> t.tdata <- TActionScript3 (id,remove_debug_infos as3) | _ -> () ) tags; t(); (h,tags) -let add_swf_lib com file extern = - let swf_data = ref None in - let swf_classes = ref None in - let getSWF = (fun() -> - match !swf_data with +class swf_library com name file_path = object(self) + inherit [swf_lib_type,Swf.swf] native_library name file_path + + val mutable swf_data = None + val mutable swf_classes = None + val haxe_classes = Hashtbl.create 0 + + method load = + ignore(self#get_swf) + + method get_swf = match swf_data with | None -> - let d = parse_swf com file in - swf_data := Some d; + let d = parse_swf com file_path in + swf_data <- Some d; d - | Some d -> d - ) in - let extract = (fun() -> - match !swf_classes with + | Some d -> + d + + method extract = match swf_classes with | None -> - let d = extract_data (getSWF()) in - swf_classes := Some d; + let d = extract_data self#get_swf in + swf_classes <- Some d; d - | Some d -> d - ) in - let build cl p = - match (try Some (Hashtbl.find (extract()) cl) with Not_found -> None) with - | None -> None - | Some c -> Some (file, build_class com c file) - in - com.load_extern_type <- com.load_extern_type @ [build]; - if not extern then com.swf_libs <- (file,getSWF,extract) :: com.swf_libs + | Some d -> + d + + method lookup path = + try Some (Hashtbl.find (self#extract) path) + with Not_found -> None + + method list_modules = + Hashtbl.fold (fun path _ acc -> path :: acc) (self#extract) [] + + method close = + () + + method build (path : path) (p : pos) : Ast.package option = + try + Some (Hashtbl.find haxe_classes path) + with Not_found -> try + let c = Hashtbl.find (self#extract) path in + let c = build_class com c file_path in + Hashtbl.add haxe_classes path c; + Some c + with Not_found -> + None + + method get_data = self#get_swf +end + +let add_swf_lib com file extern = + let real_file = (try Common.find_file com file with Not_found -> failwith (" Library not found : " ^ file)) in + let swf_lib = new swf_library com file real_file in + if not extern then com.native_libs.swf_libs <- (swf_lib :> (swf_lib_type,Swf.swf) native_library) :: com.native_libs.swf_libs; + CompilationServer.handle_native_lib com swf_lib -let remove_classes toremove lib hcl = - let lib = lib() in +let remove_classes toremove lib l = match !toremove with | [] -> lib | _ -> - let hcl = hcl() in + let hcl = Hashtbl.create 0 in + List.iter (fun path -> Hashtbl.add hcl path ()) l; match List.filter (fun c -> Hashtbl.mem hcl c) (!toremove) with | [] -> lib | classes -> diff --git a/src/compiler/displayOutput.ml b/src/compiler/displayOutput.ml index 0151c9b5daf..4ca71e51b5c 100644 --- a/src/compiler/displayOutput.ml +++ b/src/compiler/displayOutput.ml @@ -1,9 +1,22 @@ open Globals +open Ast open Common -open Common.DisplayMode +open Filename +open CompilationServer +open Timer +open DisplayTypes.DisplayMode +open DisplayTypes.CompletionResultKind +open CompletionItem +open CompletionClassField +open CompletionEnumField +open ClassFieldOrigin +open DisplayException open Type open Display +open DisplayTypes +open CompletionModuleType open Typecore +open Genjson (* Old XML stuff *) @@ -16,12 +29,12 @@ let htmlescape s = let get_timer_fields start_time = let tot = ref 0. in - Hashtbl.iter (fun _ t -> tot := !tot +. t.total) Common.htimers; + Hashtbl.iter (fun _ t -> tot := !tot +. t.total) Timer.htimers; let fields = [("@TOTAL", Printf.sprintf "%.3fs" (get_time() -. start_time))] in if !tot > 0. then Hashtbl.fold (fun _ t acc -> ((String.concat "." t.id),(Printf.sprintf "%.3fs (%.0f%%)" t.total (t.total *. 100. /. !tot))) :: acc - ) Common.htimers fields + ) Timer.htimers fields else fields @@ -37,18 +50,42 @@ let print_keywords () = let print_fields fields = let b = Buffer.create 0 in Buffer.add_string b "\n"; - List.iter (fun (n,k,d) -> - let s_kind, t = match k with - | FKVar t -> "var", s_type (print_context()) t - | FKMethod t -> "method", s_type (print_context()) t - | FKType t -> "type", s_type (print_context()) t - | FKPackage -> "package", "" - | FKModule -> "type", "" - | FKMetadata -> "metadata", "" - | FKTimer s -> "timer", s - in - Buffer.add_string b (Printf.sprintf "%s%s\n" n s_kind (htmlescape t) (htmlescape d)) - ) (List.sort (fun (a,ak,_) (b,bk,_) -> compare (display_field_kind_index ak,a) (display_field_kind_index bk,b)) fields); + let convert k = match k.ci_kind with + | ITClassField({field = cf}) | ITEnumAbstractField(_,{field = cf}) -> + let kind = match cf.cf_kind with + | Method _ -> "method" + | Var _ -> "var" + in + kind,cf.cf_name,s_type (print_context()) cf.cf_type,cf.cf_doc + | ITEnumField ef -> + let ef = ef.efield in + let kind = match follow ef.ef_type with + | TFun _ -> "method" + | _ -> "var" + in + kind,ef.ef_name,s_type (print_context()) ef.ef_type,ef.ef_doc + | ITType(cm,_) -> + let path = CompletionItem.CompletionModuleType.get_path cm in + "type",snd path,s_type_path path,None + | ITPackage(path,_) -> "package",snd path,"",None + | ITModule path -> "type",snd path,"",None + | ITMetadata meta -> + let s,(doc,_) = Meta.get_info meta in + "metadata","@" ^ s,"",Some doc + | ITTimer(name,value) -> "timer",name,"",Some value + | ITLiteral s -> + let t = match k.ci_type with None -> t_dynamic | Some (t,_) -> t in + "literal",s,s_type (print_context()) t,None + | ITLocal v -> "local",v.v_name,s_type (print_context()) v.v_type,None + | ITKeyword kwd -> "keyword",Ast.s_keyword kwd,"",None + | ITExpression _ | ITAnonymous _ | ITTypeParameter _ -> assert false + in + let fields = List.sort (fun k1 k2 -> compare (legacy_sort k1) (legacy_sort k2)) fields in + let fields = List.map convert fields in + List.iter (fun(k,n,t,d) -> + let d = match d with None -> "" | Some d -> d in + Buffer.add_string b (Printf.sprintf "%s%s\n" n k (htmlescape t) (htmlescape d)) + ) fields; Buffer.add_string b "\n"; Buffer.contents b @@ -68,28 +105,33 @@ let print_toplevel il = true end in - List.iter (fun id -> match id with - | IdentifierType.ITLocal v -> + List.iter (fun id -> match id.ci_kind with + | ITLocal v -> if check_ident v.v_name then Buffer.add_string b (Printf.sprintf "%s\n" (s_type v.v_type) v.v_name); - | IdentifierType.ITMember(c,cf) -> + | ITClassField({field = cf;scope = CFSMember}) -> if check_ident cf.cf_name then Buffer.add_string b (Printf.sprintf "%s\n" (s_type cf.cf_type) (s_doc cf.cf_doc) cf.cf_name); - | IdentifierType.ITStatic(c,cf) -> + | ITClassField({field = cf;scope = (CFSStatic | CFSConstructor)}) -> if check_ident cf.cf_name then Buffer.add_string b (Printf.sprintf "%s\n" (s_type cf.cf_type) (s_doc cf.cf_doc) cf.cf_name); - | IdentifierType.ITEnum(en,ef) -> + | ITEnumField ef -> + let ef = ef.efield in if check_ident ef.ef_name then Buffer.add_string b (Printf.sprintf "%s\n" (s_type ef.ef_type) (s_doc ef.ef_doc) ef.ef_name); - | IdentifierType.ITEnumAbstract(a,cf) -> + | ITEnumAbstractField(a,cf) -> + let cf = cf.field in if check_ident cf.cf_name then Buffer.add_string b (Printf.sprintf "%s\n" (s_type cf.cf_type) (s_doc cf.cf_doc) cf.cf_name); - | IdentifierType.ITGlobal(mt,s,t) -> - if check_ident s then Buffer.add_string b (Printf.sprintf "%s\n" (s_type_path (t_infos mt).mt_path) (s_type t) s); - | IdentifierType.ITType(mt) -> - let infos = t_infos mt in - if check_ident (snd infos.mt_path) then Buffer.add_string b (Printf.sprintf "%s\n" (s_type_path infos.mt_path) (s_doc infos.mt_doc) (snd infos.mt_path)); - | IdentifierType.ITPackage s -> - Buffer.add_string b (Printf.sprintf "%s\n" s) - | IdentifierType.ITLiteral s -> + | ITType(cm,_) -> + let path = CompletionItem.CompletionModuleType.get_path cm in + Buffer.add_string b (Printf.sprintf "%s\n" (s_type_path path) ("") cm.name); + | ITPackage(path,_) -> + Buffer.add_string b (Printf.sprintf "%s\n" (snd path)) + | ITLiteral s -> Buffer.add_string b (Printf.sprintf "%s\n" s) - | IdentifierType.ITTimer s -> + | ITTimer(s,_) -> Buffer.add_string b (Printf.sprintf "%s\n" s) + | ITTypeParameter c -> + Buffer.add_string b (Printf.sprintf "%s\n" (s_type_path c.cl_path) ("") (snd c.cl_path)); + | ITMetadata _ | ITModule _ | ITKeyword _ | ITAnonymous _ | ITExpression _ -> + (* compat: don't add *) + () ) il; Buffer.add_string b ""; Buffer.contents b @@ -111,7 +153,7 @@ let print_type t p doc = let print_signatures tl = let b = Buffer.create 0 in - List.iter (fun ((args,ret),doc) -> + List.iter (fun (((args,ret),_),doc) -> Buffer.add_string b " Buffer.add_string b (Printf.sprintf " d=\"%s\"" (htmlescape s))) doc; Buffer.add_string b ">\n"; @@ -133,9 +175,56 @@ let print_positions pl = Buffer.add_string b ""; Buffer.contents b -let display_memory com = - let verbose = com.verbose in - let print = print_endline in +module Memory = struct + open CompilationServer + + let update_module_type_deps deps md = + deps := Obj.repr md :: !deps; + List.iter (fun t -> + match t with + | TClassDecl c -> + deps := Obj.repr c :: !deps; + c.cl_descendants <- []; (* prevent false positive *) + List.iter (fun f -> deps := Obj.repr f :: !deps) c.cl_ordered_statics; + List.iter (fun f -> deps := Obj.repr f :: !deps) c.cl_ordered_fields; + | TEnumDecl e -> + deps := Obj.repr e :: !deps; + List.iter (fun n -> deps := Obj.repr (PMap.find n e.e_constrs) :: !deps) e.e_names; + | TTypeDecl t -> deps := Obj.repr t :: !deps; + | TAbstractDecl a -> deps := Obj.repr a :: !deps; + ) md.m_types + + let rec scan_module_deps m h = + if Hashtbl.mem h m.m_id then + () + else begin + Hashtbl.add h m.m_id m; + PMap.iter (fun _ m -> scan_module_deps m h) m.m_extra.m_deps + end + + let get_out out = + Obj.repr Common.memory_marker :: PMap.fold (fun m acc -> Obj.repr m :: acc) out [] + + let collect_memory_stats cs = + let all_modules = Hashtbl.fold (fun _ m acc -> PMap.add m.m_id m acc) cs.c_modules PMap.empty in + let modules = Hashtbl.fold (fun (path,key) m acc -> + let mdeps = Hashtbl.create 0 in + scan_module_deps m mdeps; + let deps = ref [Obj.repr null_module] in + let out = ref all_modules in + Hashtbl.iter (fun _ md -> + out := PMap.remove md.m_id !out; + if m == md then + () + else + update_module_type_deps deps md; + ) mdeps; + let chk = get_out !out in + let inf = Objsize.objsize m !deps chk in + (m,Objsize.size_with_headers inf, (inf.Objsize.reached,!deps,!out)) :: acc + ) cs.c_modules [] in + modules + let fmt_size sz = if sz < 1024 then string_of_int sz ^ " B" @@ -143,102 +232,166 @@ let display_memory com = string_of_int (sz asr 10) ^ " KB" else Printf.sprintf "%.1f MB" ((float_of_int sz) /. (1024.*.1024.)) - in + let size v = fmt_size (mem_size v) - in - Gc.full_major(); - Gc.compact(); - let mem = Gc.stat() in - print ("Total Allocated Memory " ^ fmt_size (mem.Gc.heap_words * (Sys.word_size asr 8))); - print ("Free Memory " ^ fmt_size (mem.Gc.free_words * (Sys.word_size asr 8))); - (match CompilationServer.get() with - | None -> - print "No cache found"; - | Some {CompilationServer.cache = c} -> - print ("Total cache size " ^ size c); - print (" haxelib " ^ size c.CompilationServer.c_haxelib); - print (" parsed ast " ^ size c.CompilationServer.c_files ^ " (" ^ string_of_int (Hashtbl.length c.CompilationServer.c_files) ^ " files stored)"); - print (" typed modules " ^ size c.CompilationServer.c_modules ^ " (" ^ string_of_int (Hashtbl.length c.CompilationServer.c_modules) ^ " modules stored)"); - let rec scan_module_deps m h = - if Hashtbl.mem h m.m_id then - () - else begin - Hashtbl.add h m.m_id m; - PMap.iter (fun _ m -> scan_module_deps m h) m.m_extra.m_deps - end + + let get_memory_json cs = + Gc.full_major(); + Gc.compact(); + let contexts = Hashtbl.create 0 in + let add_context sign = + let ctx = (sign,ref [],ref 0) in + Hashtbl.add contexts sign ctx; + ctx in - let all_modules = Hashtbl.fold (fun _ m acc -> PMap.add m.m_id m acc) c.CompilationServer.c_modules PMap.empty in - let modules = Hashtbl.fold (fun (path,key) m acc -> - let mdeps = Hashtbl.create 0 in - scan_module_deps m mdeps; - let deps = ref [Obj.repr null_module] in - let out = ref all_modules in - Hashtbl.iter (fun _ md -> - out := PMap.remove md.m_id !out; - if m == md then () else begin - deps := Obj.repr md :: !deps; - List.iter (fun t -> - match t with + let get_context sign = + try + Hashtbl.find contexts sign + with Not_found -> + add_context sign + in + let modules = collect_memory_stats cs.cache in + List.iter (fun (m,size,(reached,deps,_)) -> + let (_,l,mem) = get_context m.m_extra.m_sign in + let deps = ref deps in + update_module_type_deps deps m; + let deps = !deps in + let types = List.map (fun md -> + let fields,inf = match md with | TClassDecl c -> - deps := Obj.repr c :: !deps; - c.cl_descendants <- []; (* prevent false positive *) - List.iter (fun f -> deps := Obj.repr f :: !deps) c.cl_ordered_statics; - List.iter (fun f -> deps := Obj.repr f :: !deps) c.cl_ordered_fields; - | TEnumDecl e -> - deps := Obj.repr e :: !deps; - List.iter (fun n -> deps := Obj.repr (PMap.find n e.e_constrs) :: !deps) e.e_names; - | TTypeDecl t -> deps := Obj.repr t :: !deps; - | TAbstractDecl a -> deps := Obj.repr a :: !deps; - ) md.m_types; - end - ) mdeps; - let chk = Obj.repr Common.memory_marker :: PMap.fold (fun m acc -> Obj.repr m :: acc) !out [] in - let inf = Objsize.objsize m !deps chk in - (m,Objsize.size_with_headers inf, (inf.Objsize.reached,!deps,!out)) :: acc - ) c.CompilationServer.c_modules [] in - let cur_key = ref "" and tcount = ref 0 and mcount = ref 0 in - List.iter (fun (m,size,(reached,deps,out)) -> - let key = m.m_extra.m_sign in - if key <> !cur_key then begin - print (Printf.sprintf (" --- CONFIG %s ----------------------------") (Digest.to_hex key)); - cur_key := key; - end; - let sign md = - if md.m_extra.m_sign = key then "" else "(" ^ (try Digest.to_hex md.m_extra.m_sign with _ -> "???" ^ md.m_extra.m_sign) ^ ")" - in - print (Printf.sprintf " %s : %s" (s_type_path m.m_path) (fmt_size size)); - (if reached then try - incr mcount; - let lcount = ref 0 in - let leak l = - incr lcount; - incr tcount; - print (Printf.sprintf " LEAK %s" l); - if !lcount >= 3 && !tcount >= 100 && not verbose then begin - print (Printf.sprintf " ..."); - raise Exit; - end; + let field acc cf = + let repr = Obj.repr cf in + let deps = List.filter (fun repr' -> repr' != repr) deps in + let size = Objsize.size_with_headers (Objsize.objsize cf deps []) in + (cf.cf_name,size) :: acc + in + let fields = List.fold_left field [] c.cl_ordered_fields in + let fields = List.fold_left field fields c.cl_ordered_statics in + let fields = List.sort (fun (_,size1) (_,size2) -> compare size2 size1) fields in + let fields = List.map (fun (name,size) -> + jobject [ + "path",jstring name; + "size",jint size; + ] + ) fields in + let repr = Obj.repr c in + let deps = List.filter (fun repr' -> repr' != repr) deps in + fields,Objsize.objsize c deps [] + | TEnumDecl en -> + let repr = Obj.repr en in + let deps = List.filter (fun repr' -> repr' != repr) deps in + [],Objsize.objsize en deps [] + | TTypeDecl td -> + let repr = Obj.repr td in + let deps = List.filter (fun repr' -> repr' != repr) deps in + [],Objsize.objsize td deps [] + | TAbstractDecl a -> + let repr = Obj.repr a in + let deps = List.filter (fun repr' -> repr' != repr) deps in + [],Objsize.objsize a deps [] in - if (Objsize.objsize m deps [Obj.repr Common.memory_marker]).Objsize.reached then leak "common"; - PMap.iter (fun _ md -> - if (Objsize.objsize m deps [Obj.repr md]).Objsize.reached then leak (s_type_path md.m_path ^ sign md); - ) out; - with Exit -> - ()); - if verbose then begin - print (Printf.sprintf " %d total deps" (List.length deps)); - PMap.iter (fun _ md -> - print (Printf.sprintf " dep %s%s" (s_type_path md.m_path) (sign md)); - ) m.m_extra.m_deps; - end; - flush stdout - ) (List.sort (fun (m1,s1,_) (m2,s2,_) -> - let k1 = m1.m_extra.m_sign and k2 = m2.m_extra.m_sign in - if k1 = k2 then s1 - s2 else if k1 > k2 then 1 else -1 - ) modules); - if !mcount > 0 then print ("*** " ^ string_of_int !mcount ^ " modules have leaks !"); - print "Cache dump complete") + md,Objsize.size_with_headers inf,fields + ) m.m_types in + let types = List.sort (fun (_,size1,_) (_,size2,_) -> compare size2 size1) types in + let ja = List.map (fun (md,size,fields) -> + jobject [ + "path",jstring (s_type_path (t_infos md).mt_path); + "size",jint size; + "fields",jarray fields; + ] + ) types in + l := (m,size,jarray ja) :: !l; + mem := !mem + size; + ) modules; + let ja = Hashtbl.fold (fun key (sign,modules,size) l -> + let modules = List.sort (fun (_,size1,_) (_,size2,_) -> compare size2 size1) !modules in + let modules = List.map (fun (m,size,jmt) -> + jobject [ + "path",jstring (s_type_path m.m_path); + "size",jint size; + "types",jmt; + ] + ) modules in + let j = try (List.assoc sign cs.signs).cs_json with Not_found -> jnull in + let jo = jobject [ + "context",j; + "size",jint !size; + "modules",jarray modules; + ] in + jo :: l + ) contexts [] in + jobject [ + "contexts",jarray ja; + "memory",jobject [ + "totalCache",jint (mem_size cs.cache); + "haxelibCache",jint (mem_size cs.cache.c_haxelib); + "parserCache",jint (mem_size cs.cache.c_files); + "moduleCache",jint (mem_size cs.cache.c_modules); + "nativeLibCache",jint (mem_size cs.cache.c_native_libs); + ] + ] + + let display_memory com = + let verbose = com.verbose in + let print = print_endline in + Gc.full_major(); + Gc.compact(); + let mem = Gc.stat() in + print ("Total Allocated Memory " ^ fmt_size (mem.Gc.heap_words * (Sys.word_size asr 8))); + print ("Free Memory " ^ fmt_size (mem.Gc.free_words * (Sys.word_size asr 8))); + (match get() with + | None -> + print "No cache found"; + | Some {cache = c} -> + print ("Total cache size " ^ size c); + print (" haxelib " ^ size c.c_haxelib); + print (" parsed ast " ^ size c.c_files ^ " (" ^ string_of_int (Hashtbl.length c.c_files) ^ " files stored)"); + print (" typed modules " ^ size c.c_modules ^ " (" ^ string_of_int (Hashtbl.length c.c_modules) ^ " modules stored)"); + let modules = collect_memory_stats c in + let cur_key = ref "" and tcount = ref 0 and mcount = ref 0 in + List.iter (fun (m,size,(reached,deps,out)) -> + let key = m.m_extra.m_sign in + if key <> !cur_key then begin + print (Printf.sprintf (" --- CONFIG %s ----------------------------") (Digest.to_hex key)); + cur_key := key; + end; + let sign md = + if md.m_extra.m_sign = key then "" else "(" ^ (try Digest.to_hex md.m_extra.m_sign with _ -> "???" ^ md.m_extra.m_sign) ^ ")" + in + print (Printf.sprintf " %s : %s" (s_type_path m.m_path) (fmt_size size)); + (if reached then try + incr mcount; + let lcount = ref 0 in + let leak l = + incr lcount; + incr tcount; + print (Printf.sprintf " LEAK %s" l); + if !lcount >= 3 && !tcount >= 100 && not verbose then begin + print (Printf.sprintf " ..."); + raise Exit; + end; + in + if (Objsize.objsize m deps [Obj.repr Common.memory_marker]).Objsize.reached then leak "common"; + PMap.iter (fun _ md -> + if (Objsize.objsize m deps [Obj.repr md]).Objsize.reached then leak (s_type_path md.m_path ^ sign md); + ) out; + with Exit -> + ()); + if verbose then begin + print (Printf.sprintf " %d total deps" (List.length deps)); + PMap.iter (fun _ md -> + print (Printf.sprintf " dep %s%s" (s_type_path md.m_path) (sign md)); + ) m.m_extra.m_deps; + end; + flush stdout + ) (List.sort (fun (m1,s1,_) (m2,s2,_) -> + let k1 = m1.m_extra.m_sign and k2 = m2.m_extra.m_sign in + if k1 = k2 then s1 - s2 else if k1 > k2 then 1 else -1 + ) modules); + if !mcount > 0 then print ("*** " ^ string_of_int !mcount ^ " modules have leaks !"); + print "Cache dump complete") +end module TypePathHandler = struct let unique l = @@ -283,7 +436,7 @@ module TypePathHandler = struct else packages := f :: !packages end; - end else if file_extension f = "hx" then begin + end else if file_extension f = "hx" && f <> "import.hx" then begin let c = Filename.chop_extension f in try ignore(String.index c '.') @@ -292,8 +445,8 @@ module TypePathHandler = struct end; ) r; ) com.class_path; - List.iter (fun (_,_,extract) -> - Hashtbl.iter (fun (path,name) _ -> + let process_lib lib = + List.iter (fun (path,name) -> if path = p then classes := name :: !classes else let rec loop p1 p2 = match p1, p2 with @@ -302,42 +455,21 @@ module TypePathHandler = struct | a :: p1, b :: p2 -> if a = b then loop p1 p2 in loop path p - ) (extract()); - ) com.swf_libs; - List.iter (fun (path,std,close,all_files,lookup) -> - List.iter (fun (path, name) -> - if path = p then classes := name :: !classes else - let rec loop p1 p2 = - match p1, p2 with - | [], _ -> () - | x :: _, [] -> packages := x :: !packages - | a :: p1, b :: p2 -> if a = b then loop p1 p2 - in - loop path p - ) (all_files()) - ) com.java_libs; - List.iter (fun (path,std,all_files,lookup) -> - List.iter (fun (path, name) -> - if path = p then classes := name :: !classes else - let rec loop p1 p2 = - match p1, p2 with - | [], _ -> () - | x :: _, [] -> packages := x :: !packages - | a :: p1, b :: p2 -> if a = b then loop p1 p2 - in - loop path p - ) (all_files()) - ) com.net_libs; + ) lib#list_modules; + in + List.iter process_lib com.native_libs.swf_libs; + List.iter process_lib com.native_libs.net_libs; + List.iter process_lib com.native_libs.java_libs; unique !packages, unique !classes (** raise field completion listing packages and modules in a given package *) let complete_type_path com p = let packs, modules = read_type_path com p in if packs = [] && modules = [] then - (abort ("No classes found in " ^ String.concat "." p) null_pos) + (abort ("No modules found in " ^ String.concat "." p) null_pos) else - let packs = List.map (fun n -> n,Display.FKPackage,"") packs in - let modules = List.map (fun n -> n,Display.FKModule,"") modules in + let packs = List.map (fun n -> make_ci_package (p,n) []) packs in + let modules = List.map (fun n -> make_ci_module (p,n)) modules in Some (packs @ modules) (** raise field completion listing module sub-types and static fields *) @@ -348,9 +480,13 @@ module TypePathHandler = struct | _ -> p,c in let ctx = Typer.create com in + (* This is a bit wacky: We want to reset the display position so that revisiting the display file + does not raise another TypePath exception. However, we still want to have it treated like the + display file, so we just set the position to 0 (#6558). *) + DisplayPosition.display_position#set {DisplayPosition.display_position#get with pmin = 0; pmax = 0}; let rec lookup p = try - Typeload.load_module ctx (p,s_module) null_pos + TypeloadModule.load_module ctx (p,s_module) null_pos with e -> if cur_package then match List.rev p with @@ -361,13 +497,16 @@ module TypePathHandler = struct in let m = lookup sl_pack in let statics = ref None in + let enum_statics = ref None in let public_types = List.filter (fun t -> let tinfos = t_infos t in let is_module_type = snd tinfos.mt_path = c in if is_import && is_module_type then begin match t with - | TClassDecl c -> + | TClassDecl c | TAbstractDecl {a_impl = Some c} -> ignore(c.cl_build()); - statics := Some c.cl_ordered_statics + statics := Some c + | TEnumDecl en -> + enum_statics := Some en | _ -> () end; not tinfos.mt_private @@ -376,19 +515,29 @@ module TypePathHandler = struct if c <> s_module then [] else - List.map (fun t -> - let infos = t_infos t in - (snd infos.mt_path), Display.FKModule, (Option.default "" infos.mt_doc) + List.map (fun mt -> + make_ci_type (CompletionItem.CompletionModuleType.of_module_type mt) ImportStatus.Imported None ) public_types in - let make_field_doc cf = - cf.cf_name, - (match cf.cf_kind with Method _ -> Display.FKMethod cf.cf_type | Var _ -> Display.FKVar cf.cf_type), - (match cf.cf_doc with Some s -> s | None -> "") + let class_origin c = match c.cl_kind with + | KAbstractImpl a -> Self (TAbstractDecl a) + | _ -> Self (TClassDecl c) + in + let tpair t = + (t,DisplayEmitter.completion_type_of_type ctx t) + in + let make_field_doc c cf = + make_ci_class_field (CompletionClassField.make cf CFSStatic (class_origin c) true) (tpair cf.cf_type) in let fields = match !statics with | None -> types - | Some cfl -> types @ (List.map make_field_doc (List.filter (fun cf -> cf.cf_public) cfl)) + | Some c -> types @ (List.map (make_field_doc c) (List.filter (fun cf -> has_class_field_flag cf CfPublic) c.cl_ordered_statics)) + in + let fields = match !enum_statics with + | None -> fields + | Some en -> PMap.fold (fun ef acc -> + make_ci_enum_field (CompletionEnumField.make ef (Self (TEnumDecl en)) true) (tpair ef.ef_type) :: acc + ) en.e_constrs fields in Some fields with _ -> @@ -399,29 +548,11 @@ end open Json -(** return a range JSON structure for given position - positions are 0-based and the result object looks like this: - { - start: {line: 0, character: 0}, - end: {line: 3, character: 42}, - } -*) -let pos_to_json_range p = - if p.pmin = -1 then - JNull - else - let l1, p1, l2, p2 = Lexer.get_pos_coords p in - let to_json l c = JObject [("line", JInt (l - 1)); ("character", JInt (c - 1))] in - JObject [ - ("start", to_json l1 p1); - ("end", to_json l2 p2); - ] - let print_signature tl display_arg = let st = s_type (print_context()) in let s_arg (n,o,t) = Printf.sprintf "%s%s:%s" (if o then "?" else "") n (st t) in let s_fun args ret = Printf.sprintf "(%s):%s" (String.concat ", " (List.map s_arg args)) (st ret) in - let siginf = List.map (fun ((args,ret),doc) -> + let siginf = List.map (fun (((args,ret),_),doc) -> let label = s_fun args ret in let parameters = List.map (fun arg -> @@ -442,195 +573,7 @@ let print_signature tl display_arg = "activeParameter",JInt display_arg; "activeSignature",JInt 0; ] in - let b = Buffer.create 0 in - write_json (Buffer.add_string b) jo; - Buffer.contents b - -module StatisticsPrinter = struct - open Statistics - - let relation_to_string = function - | Implemented -> "implementers" - | Extended -> "subclasses" - | Overridden -> "overrides" - | Referenced -> "references" - - let symbol_to_string = function - | SKClass _ -> "class type" - | SKInterface _ -> "interface type" - | SKEnum _ -> "enum type" - | SKField _ -> "class field" - | SKEnumField _ -> "enum field" - | SKVariable _ -> "variable" - - let print_statistics (kinds,relations) = - let files = Hashtbl.create 0 in - Hashtbl.iter (fun p rl -> - let file = Path.get_real_path p.pfile in - try - Hashtbl.replace files file ((p,rl) :: Hashtbl.find files file) - with Not_found -> - Hashtbl.add files file [p,rl] - ) relations; - let ja = Hashtbl.fold (fun file relations acc -> - let l = List.map (fun (p,rl) -> - let h = Hashtbl.create 0 in - List.iter (fun (r,p) -> - let s = relation_to_string r in - let jo = JObject [ - "range",pos_to_json_range p; - "file",JString (Path.get_real_path p.pfile); - ] in - try Hashtbl.replace h s (jo :: Hashtbl.find h s) - with Not_found -> Hashtbl.add h s [jo] - ) rl; - let l = Hashtbl.fold (fun s js acc -> (s,JArray js) :: acc) h [] in - let l = ("range",pos_to_json_range p) :: l in - let l = try ("kind",JString (symbol_to_string (Hashtbl.find kinds p))) :: l with Not_found -> l in - JObject l - ) relations in - (JObject [ - "file",JString file; - "statistics",JArray l - ]) :: acc - ) files [] in - let b = Buffer.create 0 in - write_json (Buffer.add_string b) (JArray ja); - Buffer.contents b -end - -module DiagnosticsPrinter = struct - open Diagnostics - open Diagnostics.DiagnosticsKind - open DisplayTypes - - type t = DiagnosticsKind.t * pos - - module UnresolvedIdentifierSuggestion = struct - type t = - | UISImport - | UISTypo - - let to_int = function - | UISImport -> 0 - | UISTypo -> 1 - end - - let print_diagnostics ctx global = - let com = ctx.com in - let diag = Hashtbl.create 0 in - let add dk p sev args = - let file = Path.get_real_path p.pfile in - let diag = try - Hashtbl.find diag file - with Not_found -> - let d = DynArray.create() in - Hashtbl.add diag file d; - d - in - DynArray.add diag (dk,p,sev,args) - in - let add dk p sev args = - if global || is_display_file p.pfile then add dk p sev args - in - let find_type i = - let types = ref [] in - Hashtbl.iter (fun _ m -> - List.iter (fun mt -> - let s_full_type_path (p,s) n = s_type_path (p,s) ^ if (s <> n) then "." ^ n else "" in - let tinfos = t_infos mt in - if snd tinfos.mt_path = i then - types := JObject [ - "kind",JInt (UnresolvedIdentifierSuggestion.to_int UnresolvedIdentifierSuggestion.UISImport); - "name",JString (s_full_type_path m.m_path i) - ] :: !types - ) m.m_types; - ) ctx.g.modules; - !types - in - List.iter (fun (s,p,suggestions) -> - let suggestions = List.map (fun (s,_) -> - JObject [ - "kind",JInt (UnresolvedIdentifierSuggestion.to_int UnresolvedIdentifierSuggestion.UISTypo); - "name",JString s - ] - ) suggestions in - add DKUnresolvedIdentifier p DiagnosticsSeverity.Error (JArray (suggestions @ (find_type s))); - ) com.display_information.unresolved_identifiers; - PMap.iter (fun p (r,_) -> - if not !r then add DKUnusedImport p DiagnosticsSeverity.Warning (JArray []) - ) com.shared.shared_display_information.import_positions; - List.iter (fun (s,p,sev) -> - add DKCompilerError p sev (JString s) - ) com.shared.shared_display_information.diagnostics_messages; - List.iter (fun (s,p,prange) -> - add DKRemovableCode p DiagnosticsSeverity.Warning (JObject ["description",JString s;"range",if prange = null_pos then JNull else pos_to_json_range prange]) - ) com.shared.shared_display_information.removable_code; - let jl = Hashtbl.fold (fun file diag acc -> - let jl = DynArray.fold_left (fun acc (dk,p,sev,jargs) -> - (JObject [ - "kind",JInt (to_int dk); - "severity",JInt (DiagnosticsSeverity.to_int sev); - "range",pos_to_json_range p; - "args",jargs - ]) :: acc - ) [] diag in - (JObject [ - "file",JString file; - "diagnostics",JArray jl - ]) :: acc - ) diag [] in - let js = JArray jl in - let b = Buffer.create 0 in - write_json (Buffer.add_string b) js; - Buffer.contents b -end - -module ModuleSymbolsPrinter = struct - open DisplayTypes.SymbolKind - open DisplayTypes.SymbolInformation - - let print_module_symbols com symbols filter = - let regex = Option.map Str.regexp_case_fold filter in - let reported = Hashtbl.create 0 in - let add si = - if Hashtbl.mem reported si.pos then false - else begin - let b = match regex with - | None -> true - | Some regex -> (try ignore(Str.search_forward regex si.name 0); true with Not_found -> false) - in - Hashtbl.replace reported si.pos true; - b - end - in - let ja = List.fold_left (fun acc (file,l) -> - let jl = ExtList.List.filter_map (fun si -> - if not (add si) then - None - else begin - let l = - ("name",JString si.name) :: - ("kind",JInt (to_int si.kind)) :: - ("range", pos_to_json_range si.pos) :: - (match si.container_name with None -> [] | Some s -> ["containerName",JString s]) - in - Some (JObject l) - end - ) (DynArray.to_list l) in - if jl = [] then - acc - else - (JObject [ - "file",JString file; - "symbols",JArray jl - ]) :: acc - ) [] symbols in - let js = JArray ja in - let b = Buffer.create 0 in - write_json (Buffer.add_string b) js; - Buffer.contents b -end + string_of_json jo (* Mode processing *) @@ -638,21 +581,26 @@ exception Completion of string let unquote v = let len = String.length v in - if len > 0 && v.[0] = '"' && v.[len - 1] = '"' then String.sub v 1 (len - 2) else v + if len > 0 then + match v.[0], v.[len - 1] with + | '"', '"' + | '\'', '\'' -> String.sub v 1 (len - 2) + | _ -> v + else v let handle_display_argument com file_pos pre_compilation did_something = match file_pos with | "classes" -> - pre_compilation := (fun() -> raise (Parser.TypePath (["."],None,true))) :: !pre_compilation; + pre_compilation := (fun() -> raise (Parser.TypePath (["."],None,true,null_pos))) :: !pre_compilation; | "keywords" -> raise (Completion (print_keywords ())) | "memory" -> did_something := true; - (try display_memory com with e -> prerr_endline (Printexc.get_backtrace ())); + (try Memory.display_memory com with e -> prerr_endline (Printexc.get_backtrace ())); | "diagnostics" -> Common.define com Define.NoCOpt; com.display <- DisplayMode.create (DMDiagnostics true); - Common.display_default := DMDiagnostics true; + Parser.display_mode := DMDiagnostics true; | _ -> let file, pos = try ExtString.String.split file_pos "@" with _ -> failwith ("Invalid format: " ^ file_pos) in let file = unquote file in @@ -660,7 +608,7 @@ let handle_display_argument com file_pos pre_compilation did_something = let mode = match smode with | "position" -> Common.define com Define.NoCOpt; - DMPosition + DMDefinition | "usage" -> Common.define com Define.NoCOpt; DMUsage false @@ -671,10 +619,9 @@ let handle_display_argument com file_pos pre_compilation did_something = DMPackage | "type" -> Common.define com Define.NoCOpt; - DMType + DMHover | "toplevel" -> - Common.define com Define.NoCOpt; - DMToplevel + DMDefault | "module-symbols" -> Common.define com Define.NoCOpt; DMModuleSymbols None; @@ -685,9 +632,10 @@ let handle_display_argument com file_pos pre_compilation did_something = Common.define com Define.NoCOpt; DMStatistics | "signature" -> + Common.define com Define.NoCOpt; DMSignature | "" -> - DMField + DMDefault | _ -> let smode,arg = try ExtString.String.split smode "@" with _ -> pos,"" in match smode with @@ -697,14 +645,13 @@ let handle_display_argument com file_pos pre_compilation did_something = Common.define com Define.NoCOpt; DMModuleSymbols (Some arg) | _ -> - DMField + DMDefault in let pos = try int_of_string pos with _ -> failwith ("Invalid format: " ^ pos) in com.display <- DisplayMode.create mode; - Common.display_default := mode; - Common.define_value com Define.Display (if smode <> "" then smode else "1"); - Parser.use_doc := true; - Parser.resume_display := { + Parser.display_mode := mode; + if not com.display.dms_full_typing then Common.define_value com Define.Display (if smode <> "" then smode else "1"); + DisplayPosition.display_position#set { pfile = Path.unique_full_path file; pmin = pos; pmax = pos; @@ -733,69 +680,51 @@ let process_display_file com classes = in match com.display.dms_display_file_policy with | DFPNo -> - () + None | dfp -> if dfp = DFPOnly then begin classes := []; com.main_class <- None; end; - let real = Path.get_real_path (!Parser.resume_display).pfile in - (match get_module_path_from_file_path com real with + let real = Path.get_real_path (DisplayPosition.display_position#get).pfile in + let path = match get_module_path_from_file_path com real with | Some path -> - if com.display.dms_kind = DMPackage then raise (DisplayPackage (fst path)); - classes := path :: !classes + if com.display.dms_kind = DMPackage then raise_package (fst path); + classes := path :: !classes; + Some path | None -> if not (Sys.file_exists real) then failwith "Display file does not exist"; (match List.rev (ExtString.String.nsplit real Path.path_sep) with | file :: _ when file.[0] >= 'a' && file.[0] <= 'z' -> failwith ("Display file '" ^ file ^ "' should not start with a lowercase letter") | _ -> ()); failwith "Display file was not found in class path" - ); + in Common.log com ("Display file : " ^ real); - Common.log com ("Classes found : [" ^ (String.concat "," (List.map s_type_path !classes)) ^ "]") + Common.log com ("Classes found : [" ^ (String.concat "," (List.map s_type_path !classes)) ^ "]"); + path let process_global_display_mode com tctx = match com.display.dms_kind with | DMUsage with_definition -> - let symbols,relations = Statistics.collect_statistics tctx in - let rec loop acc relations = match relations with - | (Statistics.Referenced,p) :: relations -> loop (p :: acc) relations - | _ :: relations -> loop acc relations - | [] -> acc - in - let usages = Hashtbl.fold (fun p sym acc -> - if Statistics.is_usage_symbol sym then begin - let acc = if with_definition then p :: acc else acc in - (try loop acc (Hashtbl.find relations p) - with Not_found -> acc) - end else - acc - ) symbols [] in - let usages = List.sort (fun p1 p2 -> - let c = compare p1.pfile p2.pfile in - if c <> 0 then c else compare p1.pmin p2.pmin - ) usages in - raise (DisplayPosition usages) + FindReferences.find_references tctx com with_definition | DMDiagnostics global -> - Diagnostics.prepare com global; - raise (Diagnostics (DiagnosticsPrinter.print_diagnostics tctx global)) + Diagnostics.run com global | DMStatistics -> - let stats = Statistics.collect_statistics tctx in - raise (Statistics (StatisticsPrinter.print_statistics stats)) + let stats = Statistics.collect_statistics tctx (SFFile (DisplayPosition.display_position#get).pfile) in + raise_statistics (Statistics.Printer.print_statistics stats) + | DMModuleSymbols (Some "") -> () | DMModuleSymbols filter -> - let symbols = com.shared.shared_display_information.document_symbols in let symbols = match CompilationServer.get() with - | None -> symbols + | None -> [] | Some cs -> let l = CompilationServer.get_context_files cs ((Define.get_signature com.defines) :: (match com.get_macros() with None -> [] | Some com -> [Define.get_signature com.defines])) in - List.fold_left (fun acc (file,data) -> - print_endline (Printf.sprintf "%s %b" file (is_display_file file)); - if (filter <> None || is_display_file file) then - (file,DocumentSymbols.collect_module_symbols data) :: acc + List.fold_left (fun acc (file,cfile) -> + if (filter <> None || DisplayPosition.display_position#is_in_file file) then + (file,DocumentSymbols.collect_module_symbols (filter = None) (cfile.c_package,cfile.c_decls)) :: acc else acc - ) symbols l + ) [] l in - raise (ModuleSymbols(ModuleSymbolsPrinter.print_module_symbols com symbols filter)) + raise_module_symbols (DocumentSymbols.Printer.print_module_symbols com symbols filter) | _ -> () let find_doc t = @@ -810,4 +739,51 @@ let find_doc t = | _ -> None in - doc \ No newline at end of file + doc + +let handle_syntax_completion com kind p = + let open Parser in + let l,kind = match kind with + | SCClassRelation -> + [Extends;Implements],CRTypeRelation + | SCInterfaceRelation -> + [Extends],CRTypeRelation + | SCComment -> + [],CRTypeRelation + | SCTypeDecl mode -> + let in_import_hx = Filename.basename p.pfile = "import.hx" in + let l = if in_import_hx then [] else [Private;Extern;Class;Interface;Enum;Abstract;Typedef;Final] in + let l = match mode with + | TCBeforePackage -> Package :: Import :: Using :: l + | TCAfterImport -> Import :: Using :: l + | TCAfterType -> l + in + l,CRTypeDecl + | SCAfterTypeFlag flags -> + let l = [Class;Interface] in + let l = if List.mem DPrivate flags then l else Private :: l in + let l = if List.mem DExtern flags then l else Extern :: l in + let l = if List.mem DFinal flags then l else + Final :: Enum :: Abstract :: Typedef :: l + in + l,CRTypeDecl + in + match l with + | [] -> + () + | _ -> + let l = List.map make_ci_keyword l in + match com.json_out with + | None -> + let b = Buffer.create 0 in + Buffer.add_string b "\n"; + List.iter (fun item -> match item.ci_kind with + | ITKeyword kwd -> Buffer.add_string b (Printf.sprintf "%s" (s_keyword kwd)); + | _ -> assert false + ) l; + Buffer.add_string b ""; + let s = Buffer.contents b in + raise (Completion s) + | Some(f,_,jsonrpc) -> + let ctx = Genjson.create_context ~jsonrpc:jsonrpc GMFull in + f(fields_to_json ctx l kind None None) \ No newline at end of file diff --git a/src/compiler/main.ml b/src/compiler/main.ml index 3ecf9ecc0d5..23f85ba44a0 100644 --- a/src/compiler/main.ml +++ b/src/compiler/main.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -44,28 +44,22 @@ open Printf open Common -open Common.DisplayMode +open DisplayTypes.DisplayMode +open DisplayTypes.CompletionResultKind +open DisplayException open Type open Server open Globals +open Filename exception Abort +exception HelpMessage of string let executable_path() = Extc.executable_path() -let format msg p = - if p = null_pos then - msg - else begin - let error_printer file line = sprintf "%s:%d:" file line in - let epos = Lexer.get_error_pos error_printer p in - let msg = String.concat ("\n" ^ epos ^ " : ") (ExtString.String.nsplit msg "\n") in - sprintf "%s : %s" epos msg - end - -let message ctx msg p = - ctx.messages <- format msg p :: ctx.messages +let message ctx msg = + ctx.messages <- msg :: ctx.messages let deprecated = [] @@ -83,14 +77,16 @@ let limit_string s offset = let error ctx msg p = let msg = try List.assoc msg deprecated with Not_found -> msg in - message ctx msg p; + message ctx (CMError(msg,p)); ctx.has_error <- true let reserved_flags = [ "cross";"js";"lua";"neko";"flash";"php";"cpp";"cs";"java";"python"; - "as3";"swc";"macro";"sys" + "as3";"swc";"macro";"sys";"static";"utf16";"haxe";"haxe_ver" ] +let reserved_flag_namespaces = ["target"] + let delete_file f = try Sys.remove f with _ -> () let expand_env ?(h=None) path = @@ -109,7 +105,7 @@ let expand_env ?(h=None) path = let add_libs com libs = let call_haxelib() = - let t = Common.timer ["haxelib"] in + let t = Timer.timer ["haxelib"] in let cmd = "haxelib path " ^ String.concat " " libs in let pin, pout, perr = Unix.open_process_full cmd (Unix.environment()) in let lines = Std.input_list pin in @@ -117,7 +113,7 @@ let add_libs com libs = let ret = Unix.close_process_full (pin,pout,perr) in if ret <> Unix.WEXITED 0 then failwith (match lines, err with | [], [] -> "Failed to call haxelib (command not found ?)" - | [], [s] when ExtString.String.ends_with (ExtString.String.strip s) "Module not found : path" -> "The haxelib command has been strip'ed, please install it again" + | [], [s] when ExtString.String.ends_with (ExtString.String.strip s) "Module not found: path" -> "The haxelib command has been strip'ed, please install it again" | _ -> String.concat "\n" (lines@err)); t(); lines @@ -158,7 +154,7 @@ let run_command ctx cmd = let h = Hashtbl.create 0 in Hashtbl.add h "__file__" ctx.com.file; Hashtbl.add h "__platform__" (platform_name ctx.com.platform); - let t = Common.timer ["command"] in + let t = Timer.timer ["command"] in let cmd = expand_env ~h:(Some h) cmd in let len = String.length cmd in if len > 3 && String.sub cmd 0 3 = "cd " then begin @@ -180,7 +176,7 @@ let run_command ctx cmd = let result = (match Unix.close_process_full (pout,pin,perr) with Unix.WEXITED c | Unix.WSIGNALED c | Unix.WSTOPPED c -> c) in let serr = binary_string (Buffer.contents berr) in let sout = binary_string (Buffer.contents bout) in - if serr <> "" then ctx.messages <- (if serr.[String.length serr - 1] = '\n' then String.sub serr 0 (String.length serr - 1) else serr) :: ctx.messages; + if serr <> "" then ctx.messages <- CMError((if serr.[String.length serr - 1] = '\n' then String.sub serr 0 (String.length serr - 1) else serr),null_pos) :: ctx.messages; if sout <> "" then ctx.com.print (sout ^ "\n"); t(); result @@ -218,9 +214,6 @@ module Initialize = struct add_std "neko"; "n" | Js -> - if not (PMap.exists (fst (Define.infos Define.JqueryVer)) com.defines.Define.values) then - Common.define_value com Define.JqueryVer "11204"; - let es_version = try int_of_string (Common.defined_value com Define.JsEs) @@ -245,7 +238,7 @@ module Initialize = struct add_std "php"; "php" | Cpp -> - Common.define_value com Define.HxcppApiLevel "332"; + Common.define_value com Define.HxcppApiLevel "400"; add_std "cpp"; if Common.defined com Define.Cppia then classes := (Path.parse_path "cpp.cppia.HostClasses" ) :: !classes; @@ -253,7 +246,7 @@ module Initialize = struct | Cs -> let old_flush = ctx.flush in ctx.flush <- (fun () -> - com.net_libs <- []; + com.native_libs.net_libs <- []; old_flush() ); Dotnet.before_generate com; @@ -261,30 +254,41 @@ module Initialize = struct | Java -> let old_flush = ctx.flush in ctx.flush <- (fun () -> - List.iter (fun (_,_,close,_,_) -> close()) com.java_libs; - com.java_libs <- []; + List.iter (fun java_lib -> java_lib#close) com.native_libs.java_libs; + com.native_libs.java_libs <- []; old_flush() ); Java.before_generate com; - add_std "java"; "java" + if defined com Define.Jvm then begin + add_std "jvm"; + com.package_rules <- PMap.remove "jvm" com.package_rules; + end; + add_std "java"; + "java" | Python -> add_std "python"; + if not (Common.defined com Define.PythonVersion) then + Common.define_value com Define.PythonVersion "3.3"; "python" | Hl -> add_std "hl"; + if not (Common.raw_defined com "hl_ver") then Define.raw_define_value com.defines "hl_ver" (try Std.input_file (Common.find_file com "hl/hl_version") with Not_found -> assert false); "hl" | Eval -> add_std "eval"; "eval" end -let generate tctx ext xml_out interp swf_header = +let generate tctx ext interp swf_header = let com = tctx.Typecore.com in (* check file extension. In case of wrong commandline, we don't want to accidentaly delete a source file. *) if file_extension com.file = ext then delete_file com.file; if com.platform = Flash || com.platform = Cpp || com.platform = Hl then List.iter (Codegen.fix_overrides com) com.types; - if Common.defined com Define.Dump then Codegen.Dump.dump_types com; + if Common.defined com Define.Dump then begin + Codegen.Dump.dump_types com; + Option.may Codegen.Dump.dump_types (com.get_macros()) + end; if Common.defined com Define.DumpDependencies then begin Codegen.Dump.dump_dependencies com; if not tctx.Typecore.in_macro then match tctx.Typecore.g.Typecore.macros with @@ -294,11 +298,11 @@ let generate tctx ext xml_out interp swf_header = begin match com.platform with | Neko | Hl | Eval when interp -> () | Cpp when Common.defined com Define.Cppia -> () - | Cpp | Cs | Java | Php -> Common.mkdir_from_path (com.file ^ "/.") - | _ -> Common.mkdir_from_path com.file + | Cpp | Cs | Java | Php -> Path.mkdir_from_path (com.file ^ "/.") + | _ -> Path.mkdir_from_path com.file end; if interp then - Std.finally (Common.timer ["interp"]) MacroContext.interpret tctx + Std.finally (Timer.timer ["interp"]) MacroContext.interpret tctx else if com.platform = Cross then () else begin @@ -320,7 +324,10 @@ let generate tctx ext xml_out interp swf_header = | Cs -> Gencs.generate,"cs" | Java -> - Genjava.generate,"java" + if Common.defined com Jvm then + Genjvm.generate,"java" + else + Genjava.generate,"java" | Python -> Genpy.generate,"python" | Hl -> @@ -331,7 +338,7 @@ let generate tctx ext xml_out interp swf_header = assert false in Common.log com ("Generating " ^ name ^ ": " ^ com.file); - let t = Common.timer ["generate";name] in + let t = Timer.timer ["generate";name] in generate com; t() end @@ -351,24 +358,258 @@ let get_std_class_paths () = let parts = Str.split_delim (Str.regexp "[;:]") p in "" :: List.map Path.add_trailing_slash (loop parts) with Not_found -> + let base_path = Path.get_real_path (try executable_path() with _ -> "./") in if Sys.os_type = "Unix" then + let prefix_path = Filename.dirname base_path in + let lib_path = Filename.concat prefix_path "lib" in + let share_path = Filename.concat prefix_path "share" in [ - "/usr/local/share/haxe/std/"; - "/usr/local/lib/haxe/std/"; - "/usr/local/lib/haxe/extraLibs/"; - "/usr/share/haxe/std/"; - "/usr/lib/haxe/std/"; - "/usr/lib/haxe/extraLibs/"; - "" + ""; + Path.add_trailing_slash (Filename.concat lib_path "haxe/std"); + Path.add_trailing_slash (Filename.concat lib_path "haxe/extraLibs"); + Path.add_trailing_slash (Filename.concat share_path "haxe/std"); + Path.add_trailing_slash (Filename.concat share_path "haxe/extraLibs"); + Path.add_trailing_slash (Filename.concat base_path "std"); + Path.add_trailing_slash (Filename.concat base_path "extraLibs") ] else - let base_path = Path.add_trailing_slash (Path.get_real_path (try executable_path() with _ -> "./")) in [ - base_path ^ "std/"; - base_path ^ "extraLibs/"; - "" + ""; + Path.add_trailing_slash (Filename.concat base_path "std"); + Path.add_trailing_slash (Filename.concat base_path "extraLibs") ] +let setup_common_context ctx com = + Common.define_value com Define.HaxeVer (Printf.sprintf "%.3f" (float_of_int Globals.version /. 1000.)); + Common.raw_define com "haxe3"; + Common.raw_define com "haxe4"; + Common.define_value com Define.Haxe (s_version false); + Common.define_value com Define.Dce "std"; + com.info <- (fun msg p -> message ctx (CMInfo(msg,p))); + com.warning <- (fun msg p -> message ctx (CMWarning(msg,p))); + com.error <- error ctx; + let filter_messages = (fun keep_errors predicate -> (List.filter (fun msg -> + (match msg with + | CMError(_,_) -> keep_errors; + | CMInfo(_,_) | CMWarning(_,_) -> predicate msg;) + ) (List.rev ctx.messages))) in + com.get_messages <- (fun () -> (List.map (fun msg -> + (match msg with + | CMError(_,_) -> assert false; + | CMInfo(_,_) | CMWarning(_,_) -> msg;) + ) (filter_messages false (fun _ -> true)))); + com.filter_messages <- (fun predicate -> (ctx.messages <- (List.rev (filter_messages true predicate)))); + if CompilationServer.runs() then com.run_command <- run_command ctx; + com.class_path <- get_std_class_paths (); + com.std_path <- List.filter (fun p -> ExtString.String.ends_with p "std/" || ExtString.String.ends_with p "std\\") com.class_path + +let process_args arg_spec = + (* Takes a list of arg specs including some custom info, and generates a + list in the format Arg.parse_argv wants. Handles multiple official or + deprecated names for the same arg; deprecated versions will display a + warning. *) + List.flatten(List.map (fun (cat, ok, dep, spec, hint, doc) -> + (* official argument names *) + (List.map (fun (arg) -> (arg, spec, doc)) ok) @ + (* deprecated argument names *) + (* let dep_msg arg = (Printf.sprintf "WARNING: %s is deprecated" arg) ^ (if List.length ok > 0 then (Printf.sprintf ". Use %s instead" (String.concat "/" ok)) else "") in *) + (* For now, these warnings are a noop. Can replace this function to + enable error output: *) + (* let dep_fun = prerr_endline (dep_msg arg) in *) + let dep_fun arg spec = () in + let dep_spec arg spec = match spec with + | Arg.String f -> Arg.String (fun x -> dep_fun arg spec; f x) + | Arg.Unit f -> Arg.Unit (fun x -> dep_fun arg spec; f x) + | Arg.Bool f -> Arg.Bool (fun x -> dep_fun arg spec; f x) + | _ -> spec in + (List.map (fun (arg) -> (arg, dep_spec arg spec, doc)) dep) + ) arg_spec) + +let usage_string ?(print_cat=true) arg_spec usage = + let make_label = fun names hint -> Printf.sprintf "%s %s" (String.concat ", " names) hint in + let args = (List.filter (fun (cat, ok, dep, spec, hint, doc) -> (List.length ok) > 0) arg_spec) in + let cat_order = ["Target";"Compilation";"Optimization";"Debug";"Batch";"Services";"Compilation Server";"Target-specific";"Miscellaneous"] in + let cats = List.filter (fun x -> List.mem x (List.map (fun (cat, _, _, _, _, _) -> cat) args)) cat_order in + let max_length = List.fold_left max 0 (List.map String.length (List.map (fun (_, ok, _, _, hint, _) -> make_label ok hint) args)) in + usage ^ (String.concat "\n" (List.flatten (List.map (fun cat -> (if print_cat then ["\n"^cat^":"] else []) @ (List.map (fun (cat, ok, dep, spec, hint, doc) -> + let label = make_label ok hint in + Printf.sprintf " %s%s %s" label (String.make (max_length - (String.length label)) ' ') doc + ) (List.filter (fun (cat', _, _, _, _, _) -> (if List.mem cat' cat_order then cat' else "Miscellaneous") = cat) args))) cats))) + +let process_display_configuration ctx = + let com = ctx.com in + if com.display.dms_kind <> DMNone then begin + com.warning <- + if com.display.dms_error_policy = EPCollect then + (fun s p -> add_diagnostics_message com s p DKCompilerError DisplayTypes.DiagnosticsSeverity.Warning) + else + (fun msg p -> message ctx (CMWarning(msg,p))); + com.error <- error ctx; + end; + Lexer.old_format := Common.defined com Define.OldErrorFormat; + if !Lexer.old_format && !Parser.in_display then begin + let p = DisplayPosition.display_position#get in + (* convert byte position to utf8 position *) + try + let content = Std.input_file ~bin:true (Path.get_real_path p.pfile) in + let pos = UTF8.length (String.sub content 0 p.pmin) in + DisplayPosition.display_position#set { p with pmin = pos; pmax = pos } + with _ -> + () (* ignore *) + end + +let run_or_diagnose com f arg = + let handle_diagnostics global msg p kind = + add_diagnostics_message com msg p kind DisplayTypes.DiagnosticsSeverity.Error; + Diagnostics.run com global; + in + match com.display.dms_kind with + | DMDiagnostics global -> + begin try + f arg + with + | Error.Error(msg,p) -> + handle_diagnostics global (Error.error_msg msg) p DisplayTypes.DiagnosticsKind.DKCompilerError + | Parser.Error(msg,p) -> + handle_diagnostics global (Parser.error_msg msg) p DisplayTypes.DiagnosticsKind.DKParserError + | Lexer.Error(msg,p) -> + handle_diagnostics global (Lexer.error_msg msg) p DisplayTypes.DiagnosticsKind.DKParserError + end + | _ -> + f arg + +(** Creates the typer context and types [classes] into it. *) +let do_type ctx native_libs config_macros classes = + let com = ctx.com in + ctx.setup(); + Common.log com ("Classpath: " ^ (String.concat ";" com.class_path)); + Common.log com ("Defines: " ^ (String.concat ";" (PMap.foldi (fun k v acc -> (match v with "1" -> k | _ -> k ^ "=" ^ v) :: acc) com.defines.Define.values []))); + let t = Timer.timer ["typing"] in + Typecore.type_expr_ref := (fun ?(mode=MGet) ctx e with_type -> Typer.type_expr ~mode ctx e with_type); + List.iter (fun f -> f ()) (List.rev com.callbacks#get_before_typer_create); + (* Native lib pass 1: Register *) + let fl = List.map (fun (file,extern) -> NativeLibraryHandler.add_native_lib com file extern) native_libs in + (* Native lib pass 2: Initialize *) + List.iter (fun f -> f()) fl; + let tctx = Typer.create com in + let add_signature desc = + Option.may (fun cs -> CompilationServer.maybe_add_context_sign cs com desc) (CompilationServer.get ()); + in + add_signature "before_init_macros"; + List.iter (MacroContext.call_init_macro tctx) (List.rev config_macros); + add_signature "after_init_macros"; + List.iter (fun f -> f ()) (List.rev com.callbacks#get_after_init_macros); + run_or_diagnose com (fun () -> + List.iter (fun cpath -> ignore(tctx.Typecore.g.Typecore.do_load_module tctx cpath null_pos)) (List.rev classes); + Finalization.finalize tctx; + ) (); + (* If we are trying to find references, let's syntax-explore everything we know to check for the + identifier we are interested in. We then type only those modules that contain the identifier. *) + begin match !CompilationServer.instance,com.display.dms_kind with + | Some cs,DMUsage _ -> FindReferences.find_possible_references tctx cs; + | _ -> () + end; + t(); + tctx + +let load_display_module_in_macro tctx display_file_dot_path clear = match display_file_dot_path with + | Some cpath -> + let p = null_pos in + begin try + let open Typecore in + let _, mctx = MacroContext.get_macro_context tctx p in + (* Tricky stuff: We want to remove the module from our lookups and load it again in + display mode. This covers some cases like --macro typing it in non-display mode (issue #7017). *) + if clear then begin + begin try + let m = Hashtbl.find mctx.g.modules cpath in + Hashtbl.remove mctx.g.modules cpath; + Hashtbl.remove mctx.g.types_module cpath; + List.iter (fun mt -> + let ti = t_infos mt in + Hashtbl.remove mctx.g.modules ti.mt_path; + Hashtbl.remove mctx.g.types_module ti.mt_path; + ) m.m_types + with Not_found -> + () + end; + end; + let _ = MacroContext.load_macro_module tctx cpath true p in + Finalization.finalize mctx; + Some mctx + with DisplayException _ | Parser.TypePath _ as exc -> + raise exc + | _ -> + None + end + | None -> + None + +let handle_display ctx tctx display_file_dot_path = + let com = ctx.com in + if not ctx.com.display.dms_display && ctx.has_error then raise Abort; + begin match ctx.com.display.dms_kind,!Parser.delayed_syntax_completion with + | DMDefault,Some(kind,p) -> DisplayOutput.handle_syntax_completion com kind p + | _ -> () + end; + if ctx.com.display.dms_exit_during_typing then begin + if ctx.has_next || ctx.has_error then raise Abort; + (* If we didn't find a completion point, load the display file in macro mode. *) + ignore(load_display_module_in_macro tctx display_file_dot_path true); + let no_completion_point_found = "No completion point was found" in + match com.json_out with + | Some _ -> (match ctx.com.display.dms_kind with + | DMDefault -> raise (DisplayException(DisplayFields None)) + | DMSignature -> raise (DisplayException(DisplaySignatures None)) + | DMHover -> raise (DisplayException(DisplayHover None)) + | DMDefinition | DMTypeDefinition -> raise_positions [] + | _ -> failwith no_completion_point_found) + | None -> + failwith no_completion_point_found; + end + +let filter ctx tctx display_file_dot_path = + let com = ctx.com in + let t = Timer.timer ["filters"] in + let main, types, modules = run_or_diagnose com Finalization.generate tctx in + com.main <- main; + com.types <- types; + com.modules <- modules; + (* Special case for diagnostics: We don't want to load the display file in macro mode because there's a chance it might not be + macro-compatible. This means that we might some macro-specific diagnostics, but I don't see what we could do about that. *) + if ctx.com.display.dms_force_macro_typing && (match ctx.com.display.dms_kind with DMDiagnostics _ -> false | _ -> true) then begin + match load_display_module_in_macro tctx display_file_dot_path false with + | None -> () + | Some mctx -> + (* We don't need a full macro flush here because we're not going to run any macros. *) + let _, types, modules = Finalization.generate mctx in + mctx.Typecore.com.types <- types; + mctx.Typecore.com.Common.modules <- modules + end; + DisplayOutput.process_global_display_mode com tctx; + if not (Common.defined com Define.NoDeprecationWarnings) then + DeprecationCheck.run com; + Filters.run com tctx main; + t() + +let check_auxiliary_output com xml_out json_out = + begin match xml_out with + | None -> () + | Some "hx" -> + Genhxold.generate com + | Some file -> + Common.log com ("Generating xml: " ^ file); + Path.mkdir_from_path file; + Genxml.generate com file + end; + begin match json_out with + | None -> () + | Some file -> + Common.log com ("Generating json : " ^ file); + Path.mkdir_from_path file; + Genjson.generate com.types file + end + let rec process_params create pl = let each_params = ref [] in let rec loop acc = function @@ -387,7 +628,7 @@ let rec process_params create pl = | "--each" :: l -> each_params := List.rev acc; loop [] l - | "--cwd" :: dir :: l -> + | "--cwd" :: dir :: l | "-C" :: dir :: l -> (* we need to change it immediately since it will affect hxml loading *) (try Unix.chdir dir with _ -> raise (Arg.Bad ("Invalid directory: " ^ dir))); loop acc l @@ -400,14 +641,14 @@ let rec process_params create pl = (* already connected : skip *) loop acc l) | "--run" :: cl :: args -> - let acc = cl :: "-main" :: "--interp" :: acc in + let acc = cl :: "-x" :: acc in let ctx = create (!each_params @ (List.rev acc)) in ctx.com.sys_args <- args; init ctx; ctx.flush() | arg :: l -> match List.rev (ExtString.String.nsplit arg ".") with - | "hxml" :: _ when (match acc with "-cmd" :: _ -> false | _ -> true) -> + | "hxml" :: _ when (match acc with "-cmd" :: _ | "--cmd" :: _ -> false | _ -> true) -> let acc, l = (try acc, parse_hxml arg @ l with Not_found -> (arg ^ " (file not found)") :: acc, l) in loop acc l | _ -> loop (arg :: acc) l @@ -415,20 +656,22 @@ let rec process_params create pl = (* put --display in front if it was last parameter *) let pl = (match List.rev pl with | file :: "--display" :: pl when file <> "memory" -> "--display" :: file :: List.rev pl - | "use_rtti_doc" :: "-D" :: file :: "--display" :: pl -> "--display" :: file :: List.rev pl | _ -> pl ) in loop [] pl and init ctx = let usage = Printf.sprintf - "Haxe Compiler %s - (C)2005-2017 Haxe Foundation\n Usage : haxe%s -main [-swf|-js|-neko|-php|-cpp|-cppia|-as3|-cs|-java|-python|-hl|-lua] [options]\n Options :" - s_version (if Sys.os_type = "Win32" then ".exe" else "") + "Haxe Compiler %s - (C)2005-2019 Haxe Foundation\nUsage: haxe%s [options] [hxml files...]\n" + (s_version true) (if Sys.os_type = "Win32" then ".exe" else "") in let com = ctx.com in let classes = ref [([],"Std")] in try + set_binary_mode_out stdout true; + set_binary_mode_out stderr true; let xml_out = ref None in + let json_out = ref None in let swf_header = ref None in let cmds = ref [] in let config_macros = ref [] in @@ -440,16 +683,9 @@ try let pre_compilation = ref [] in let interp = ref false in let swf_version = ref false in - Common.define_value com Define.HaxeVer (Printf.sprintf "%.3f" (float_of_int Globals.version /. 1000.)); - Common.raw_define com "haxe3"; - Common.define_value com Define.Dce "std"; - com.warning <- (fun msg p -> message ctx ("Warning : " ^ msg) p); - com.error <- error ctx; - if CompilationServer.runs() then com.run_command <- run_command ctx; - Parser.display_error := (fun e p -> com.error (Parser.error_msg e) p); - Parser.use_doc := !Common.display_default <> DMNone || (CompilationServer.runs()); - com.class_path <- get_std_class_paths (); - com.std_path <- List.filter (fun p -> ExtString.String.ends_with p "std/" || ExtString.String.ends_with p "std\\") com.class_path; + let native_libs = ref [] in + let add_native_lib file extern = native_libs := (file,extern) :: !native_libs in + setup_common_context ctx com; let define f = Arg.Unit (fun () -> Common.define com f) in let process_ref = ref (fun args -> ()) in let process_libs() = @@ -461,88 +697,123 @@ try | [] -> () | args -> (!process_ref) args in - let arg_delays = ref [] in + (* category, official names, deprecated names, arg spec, usage hint, doc *) let basic_args_spec = [ - ("-cp",Arg.String (fun path -> - process_libs(); - com.class_path <- Path.add_trailing_slash path :: com.class_path - )," : add a directory to find source files"); - ("-js",Arg.String (Initialize.set_platform com Js)," : compile code to JavaScript file"); - ("-lua",Arg.String (Initialize.set_platform com Lua)," : compile code to Lua file"); - ("-swf",Arg.String (Initialize.set_platform com Flash)," : compile code to Flash SWF file"); - ("-as3",Arg.String (fun dir -> + ("Target",["--js"],["-js"],Arg.String (Initialize.set_platform com Js),"","compile code to JavaScript file"); + ("Target",["--lua"],["-lua"],Arg.String (Initialize.set_platform com Lua),"","compile code to Lua file"); + ("Target",["--swf"],["-swf"],Arg.String (Initialize.set_platform com Flash),"","compile code to Flash SWF file"); + ("Target",["--as3"],["-as3"],Arg.String (fun dir -> Initialize.set_platform com Flash dir; Common.define com Define.As3; Common.define com Define.NoInline; - )," : generate AS3 code into target directory"); - ("-neko",Arg.String (Initialize.set_platform com Neko)," : compile code to Neko Binary"); - ("-php",Arg.String (fun dir -> + ),"","generate AS3 code into target directory"); + ("Target",["--neko"],["-neko"],Arg.String (Initialize.set_platform com Neko),"","compile code to Neko Binary"); + ("Target",["--php"],["-php"],Arg.String (fun dir -> classes := (["php"],"Boot") :: !classes; Initialize.set_platform com Php dir; - )," : generate PHP code into target directory"); - ("-cpp",Arg.String (fun dir -> + ),"","generate PHP code into target directory"); + ("Target",["--cpp"],["-cpp"],Arg.String (fun dir -> Initialize.set_platform com Cpp dir; - )," : generate C++ code into target directory"); - ("-cppia",Arg.String (fun file -> - Initialize.set_platform com Cpp file; + ),"","generate C++ code into target directory"); + ("Target",["--cppia"],["-cppia"],Arg.String (fun file -> Common.define com Define.Cppia; - )," : generate Cppia code into target file"); - ("-cs",Arg.String (fun dir -> + Initialize.set_platform com Cpp file; + ),"","generate Cppia code into target file"); + ("Target",["--cs"],["-cs"],Arg.String (fun dir -> cp_libs := "hxcs" :: !cp_libs; Initialize.set_platform com Cs dir; - )," : generate C# code into target directory"); - ("-java",Arg.String (fun dir -> + ),"","generate C# code into target directory"); + ("Target",["--java"],["-java"],Arg.String (fun dir -> cp_libs := "hxjava" :: !cp_libs; Initialize.set_platform com Java dir; - )," : generate Java code into target directory"); - ("-python",Arg.String (fun dir -> + ),"","generate Java code into target directory"); + ("Target",["--python"],["-python"],Arg.String (fun dir -> Initialize.set_platform com Python dir; - )," : generate Python code as target file"); - ("-hl",Arg.String (fun file -> + ),"","generate Python code as target file"); + ("Target",["--hl"],["-hl"],Arg.String (fun file -> Initialize.set_platform com Hl file; - )," : compile HL code as target file"); - ("-xml",Arg.String (fun file -> - Parser.use_doc := true; - xml_out := Some file - )," : generate XML types description"); - ("-main",Arg.String (fun cl -> - if com.main_class <> None then raise (Arg.Bad "Multiple -main"); + ),"","compile HL code as target file"); + ("Target",[],["-x"], Arg.String (fun cl -> + let cpath = Path.parse_type_path cl in + (match com.main_class with + | Some c -> if cpath <> c then raise (Arg.Bad "Multiple --main classes specified") + | None -> com.main_class <- Some cpath); + classes := cpath :: !classes; + Common.define com Define.Interp; + Initialize.set_platform com (!Globals.macro_platform) ""; + interp := true; + ),"","interpret the program using internal macro system"); + ("Target",["--interp"],[], Arg.Unit (fun() -> + Common.define com Define.Interp; + Initialize.set_platform com (!Globals.macro_platform) ""; + interp := true; + ),"","interpret the program using internal macro system"); + + ("Compilation",["-p";"--class-path"],["-cp"],Arg.String (fun path -> + process_libs(); + com.class_path <- Path.add_trailing_slash path :: com.class_path + ),"","add a directory to find source files"); + ("Compilation",["-m";"--main"],["-main"],Arg.String (fun cl -> + if com.main_class <> None then raise (Arg.Bad "Multiple --main classes specified"); let cpath = Path.parse_type_path cl in com.main_class <- Some cpath; classes := cpath :: !classes - )," : select startup class"); - ("-lib",Arg.String (fun l -> + ),"","select startup class"); + ("Compilation",["-L";"--library"],["-lib"],Arg.String (fun l -> cp_libs := l :: !cp_libs; Common.raw_define com l; - )," : use a haxelib library"); - ("-D",Arg.String (fun var -> - begin match var with - | "no_copt" | "no-copt" -> com.foptimize <- false; - | "use_rtti_doc" | "use-rtti-doc" -> Parser.use_doc := true; - | _ -> if List.mem var reserved_flags then raise (Arg.Bad (var ^ " is a reserved compiler flag and cannot be defined from command line")); - end; + ),"","use a haxelib library"); + ("Compilation",["-D";"--define"],[],Arg.String (fun var -> + let raise_reserved description = + raise (Arg.Bad (description ^ " and cannot be defined from the command line")) + in + if List.mem var reserved_flags then raise_reserved (Printf.sprintf "`%s` is a reserved compiler flag" var); + List.iter (fun ns -> + if ExtString.String.starts_with var (ns ^ ".") then raise_reserved (Printf.sprintf "`%s` uses the reserved compiler flag namespace `%s.*`" var ns) + ) reserved_flag_namespaces; Common.raw_define com var; - )," : define a conditional compilation flag"); - ("-v",Arg.Unit (fun () -> + ),"","define a conditional compilation flag"); + ("Debug",["-v";"--verbose"],[],Arg.Unit (fun () -> com.verbose <- true - ),": turn on verbose mode"); - ("-debug", Arg.Unit (fun() -> + ),"","turn on verbose mode"); + ("Debug",["--debug"],["-debug"], Arg.Unit (fun() -> Common.define com Define.Debug; com.debug <- true; - ), ": add debug information to the compiled code"); + ),"","add debug information to the compiled code"); + ("Miscellaneous",["--version"],["-version"],Arg.Unit (fun() -> + com.info (s_version true) null_pos; + did_something := true; + ),"","print version and exit"); + ("Miscellaneous", ["-h";"--help"], ["-help"], Arg.Unit (fun () -> + raise (Arg.Help "") + ),"","show extended help information"); + ("Miscellaneous",["--help-defines"],[], Arg.Unit (fun() -> + let all,max_length = Define.get_documentation_list() in + let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" max_length n (limit_string doc (max_length + 3))) all in + List.iter (fun msg -> ctx.com.print (msg ^ "\n")) all; + did_something := true + ),"","print help for all compiler specific defines"); + ("Miscellaneous",["--help-metas"],[], Arg.Unit (fun() -> + let all,max_length = Meta.get_documentation_list() in + let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" max_length n (limit_string doc (max_length + 3))) all in + List.iter (fun msg -> ctx.com.print (msg ^ "\n")) all; + did_something := true + ),"","print help for all compiler metadatas"); + ("Misc",["--run"],[], Arg.Unit (fun() -> assert false), " [args...]","compile and execute a Haxe module with command line arguments"); ] in let adv_args_spec = [ - ("-dce", Arg.String (fun mode -> + ("Optimization",["--dce"],["-dce"],Arg.String (fun mode -> (match mode with | "std" | "full" | "no" -> () | _ -> raise (Arg.Bad "Invalid DCE mode, expected std | full | no")); Common.define_value com Define.Dce mode - ),"[std|full|no] : set the dead code elimination mode (default std)"); - ("-swf-version",Arg.Float (fun v -> + ),"[std|full|no]","set the dead code elimination mode (default std)"); + ("Target-specific",["--swf-version"],["-swf-version"],Arg.Float (fun v -> if not !swf_version || com.flash_version < v then com.flash_version <- v; swf_version := true; - )," : change the SWF version"); - ("-swf-header",Arg.String (fun h -> + ),"","change the SWF version"); + (* FIXME: replace with -D define *) + ("Target-specific",["--swf-header"],["-swf-header"],Arg.String (fun h -> try swf_header := Some (match ExtString.String.nsplit h ":" with | [width; height; fps] -> @@ -553,45 +824,30 @@ try | _ -> raise Exit) with _ -> raise (Arg.Bad "Invalid SWF header format, expected width:height:fps[:color]") - ),"
: define SWF header (width:height:fps:color)"); - ("-swf-lib",Arg.String (fun file -> + ),"
","define SWF header (width:height:fps:color)"); + ("Target-specific",["--flash-strict"],[], define Define.FlashStrict, "","more type strict flash API"); + ("Target-specific",[],["--swf-lib";"-swf-lib"],Arg.String (fun file -> process_libs(); (* linked swf order matters, and lib might reference swf as well *) - SwfLoader.add_swf_lib com file false - )," : add the SWF library to the compiled SWF"); - ("-swf-lib-extern",Arg.String (fun file -> - SwfLoader.add_swf_lib com file true - )," : use the SWF library for type checking"); - ("-java-lib",Arg.String (fun file -> - let std = file = "lib/hxjava-std.jar" in - arg_delays := (fun () -> Java.add_java_lib com file std) :: !arg_delays; - )," : add an external JAR or class directory library"); - ("-net-lib",Arg.String (fun file -> - let file, is_std = match ExtString.String.nsplit file "@" with - | [file] -> - file,false - | [file;"std"] -> - file,true - | _ -> raise Exit - in - arg_delays := (fun () -> Dotnet.add_net_lib com file is_std) :: !arg_delays; - ),"[@std] : add an external .NET DLL file"); - ("-net-std",Arg.String (fun file -> + add_native_lib file false; + ),"","add the SWF library to the compiled SWF"); + (* FIXME: replace with -D define *) + ("Target-specific",[],["--swf-lib-extern";"-swf-lib-extern"],Arg.String (fun file -> + add_native_lib file true; + ),"","use the SWF library for type checking"); + ("Target-specific",[],["--java-lib";"-java-lib"],Arg.String (fun file -> + add_native_lib file false; + ),"","add an external JAR or class directory library"); + ("Target-specific",[],["--net-lib";"-net-lib"],Arg.String (fun file -> + add_native_lib file false; + ),"[@std]","add an external .NET DLL file"); + ("Target-specific",["--net-std"],["-net-std"],Arg.String (fun file -> Dotnet.add_net_std com file - )," : add a root std .NET DLL search path"); - ("-c-arg",Arg.String (fun arg -> + ),"","add a root std .NET DLL search path"); + (* FIXME: replace with -D define *) + ("Target-specific",["--c-arg"],["-c-arg"],Arg.String (fun arg -> com.c_args <- arg :: com.c_args - )," : pass option to the native Java/C# compiler"); - ("-x", Arg.String (fun file -> - let neko_file = file ^ ".n" in - Initialize.set_platform com Neko neko_file; - if com.main_class = None then begin - let cpath = Path.parse_type_path file in - com.main_class <- Some cpath; - classes := cpath :: !classes - end; - cmds := ("neko " ^ neko_file) :: !cmds; - )," : shortcut for compiling and executing a neko file"); - ("-resource",Arg.String (fun res -> + ),"","pass option to the native Java/C# compiler"); + ("Compilation",["-r";"--resource"],["-resource"],Arg.String (fun res -> let file, name = (match ExtString.String.nsplit res "@" with | [file; name] -> file, name | [file] -> file, file @@ -603,195 +859,169 @@ try if String.length s > 12000000 then raise Exit; s; with - | Sys_error _ -> failwith ("Resource file not found : " ^ file) + | Sys_error _ -> failwith ("Resource file not found: " ^ file) | _ -> failwith ("Resource '" ^ file ^ "' excess the maximum size of 12MB") ) in if Hashtbl.mem com.resources name then failwith ("Duplicate resource name " ^ name); Hashtbl.add com.resources name data - ),"[@name] : add a named resource file"); - ("-prompt", Arg.Unit (fun() -> prompt := true),": prompt on error"); - ("-cmd", Arg.String (fun cmd -> + ),"[@name]","add a named resource file"); + ("Debug",["--prompt"],["-prompt"], Arg.Unit (fun() -> prompt := true),"","prompt on error"); + ("Compilation",["--cmd"],["-cmd"], Arg.String (fun cmd -> cmds := DisplayOutput.unquote cmd :: !cmds - ),": run the specified command after successful compilation"); - ("--flash-strict", define Define.FlashStrict, ": more type strict flash API"); - ("--no-traces", define Define.NoTraces, ": don't compile trace calls in the program"); - ("--gen-hx-classes", Arg.Unit (fun() -> - force_typing := true; - pre_compilation := (fun() -> - List.iter (fun (_,_,extract) -> - Hashtbl.iter (fun n _ -> classes := n :: !classes) (extract()) - ) com.swf_libs; - List.iter (fun (_,std,_,all_files,_) -> - if not std then - List.iter (fun path -> if path <> (["java";"lang"],"String") then classes := path :: !classes) (all_files()) - ) com.java_libs; - List.iter (fun (_,std,all_files,_) -> - if not std then - List.iter (fun path -> classes := path :: !classes) (all_files()) - ) com.net_libs; - ) :: !pre_compilation; - xml_out := Some "hx" - ),": generate hx headers for all input classes"); - ("--next", Arg.Unit (fun() -> assert false), ": separate several haxe compilations"); - ("--each", Arg.Unit (fun() -> assert false), ": append preceding parameters to all haxe compilations separated by --next"); - ("--display", Arg.String (fun file_pos -> - DisplayOutput.handle_display_argument com file_pos pre_compilation did_something; - ),": display code tips"); - ("--no-output", Arg.Unit (fun() -> no_output := true),": compiles but does not generate any file"); - ("--times", Arg.Unit (fun() -> measure_times := true),": measure compilation times"); - ("--no-inline", define Define.NoInline, ": disable inlining"); - ("--no-opt", Arg.Unit (fun() -> + ),"","run the specified command after successful compilation"); + (* FIXME: replace with -D define *) + ("Optimization",["--no-traces"],[], define Define.NoTraces, "","don't compile trace calls in the program"); + ("Batch",["--next"],[], Arg.Unit (fun() -> assert false), "","separate several haxe compilations"); + ("Batch",["--each"],[], Arg.Unit (fun() -> assert false), "","append preceding parameters to all Haxe compilations separated by --next"); + ("Services",["--display"],[], Arg.String (fun input -> + let input = String.trim input in + if String.length input > 0 && (input.[0] = '[' || input.[0] = '{') then begin + did_something := true; + force_typing := true; + DisplayJson.parse_input com input measure_times + end else + DisplayOutput.handle_display_argument com input pre_compilation did_something; + ),"","display code tips"); + ("Services",["--xml"],["-xml"],Arg.String (fun file -> + xml_out := Some file + ),"","generate XML types description"); + ("Services",["--json"],[],Arg.String (fun file -> + json_out := Some file + ),"","generate JSON types description"); + ("Optimization",["--no-output"],[], Arg.Unit (fun() -> no_output := true),"","compiles but does not generate any file"); + ("Debug",["--times"],[], Arg.Unit (fun() -> measure_times := true),"","measure compilation times"); + ("Optimization",["--no-inline"],[], define Define.NoInline, "","disable inlining"); + ("Optimization",["--no-opt"],[], Arg.Unit (fun() -> com.foptimize <- false; Common.define com Define.NoOpt; - ), ": disable code optimizations"); - ("--remap", Arg.String (fun s -> + ), "","disable code optimizations"); + ("Compilation",["--remap"],[], Arg.String (fun s -> let pack, target = (try ExtString.String.split s ":" with _ -> raise (Arg.Bad "Invalid remap format, expected source:target")) in com.package_rules <- PMap.add pack (Remap target) com.package_rules; - )," : remap a package to another one"); - ("--interp", Arg.Unit (fun() -> - Common.define com Define.Interp; - Initialize.set_platform com (!Globals.macro_platform) ""; - interp := true; - ),": interpret the program using internal macro system"); - ("--macro", Arg.String (fun e -> + ),"","remap a package to another one"); + ("Compilation",["--macro"],[], Arg.String (fun e -> force_typing := true; config_macros := e :: !config_macros - )," : call the given macro before typing anything else"); - ("--wait", Arg.String (fun hp -> + ),"","call the given macro before typing anything else"); + ("Compilation Server",["--wait"],[], Arg.String (fun hp -> let accept = match hp with | "stdio" -> Server.init_wait_stdio() | _ -> let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in let port = try int_of_string port with _ -> raise (Arg.Bad "Invalid port") in - init_wait_socket com.verbose host port + init_wait_socket host port in wait_loop process_params com.verbose accept - ),"<[host:]port> : wait on the given port for commands to run)"); - ("--connect",Arg.String (fun _ -> + ),"[[host:]port]|stdio]","wait on the given port (or use standard i/o) for commands to run)"); + ("Compilation Server",["--connect"],[],Arg.String (fun _ -> assert false - ),"<[host:]port> : connect on the given port and run commands there)"); - ("--cwd", Arg.String (fun dir -> + ),"<[host:]port>","connect on the given port and run commands there)"); + ("Compilation",["-C";"--cwd"],[], Arg.String (fun dir -> assert false - )," : set current working directory"); - ("-version",Arg.Unit (fun() -> - message ctx s_version null_pos; - did_something := true; - ),": print version and exit"); - ("--help-defines", Arg.Unit (fun() -> - let all,max_length = Define.get_documentation_list() in - let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" max_length n (limit_string doc (max_length + 3))) all in - List.iter (fun msg -> ctx.com.print (msg ^ "\n")) all; - did_something := true - ),": print help for all compiler specific defines"); - ("--help-metas", Arg.Unit (fun() -> - let all,max_length = Meta.get_documentation_list() in - let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" max_length n (limit_string doc (max_length + 3))) all in - List.iter (fun msg -> ctx.com.print (msg ^ "\n")) all; - did_something := true - ),": print help for all compiler metadatas"); + ),"","set current working directory"); ] in let args_callback cl = - let path,name = Path.parse_path cl in - if Path.starts_uppercase name then - classes := (path,name) :: !classes - else begin - force_typing := true; - config_macros := (Printf.sprintf "include('%s', true, null, null, true)" cl) :: !config_macros; + begin try + let path,name = Path.parse_path cl in + if StringHelper.starts_uppercase name then + classes := (path,name) :: !classes + else begin + force_typing := true; + config_macros := (Printf.sprintf "include('%s', true, null, null, true)" cl) :: !config_macros; + end + with Failure _ when ctx.com.display.dms_display -> + () end in - let all_args_spec = basic_args_spec @ adv_args_spec in + let all_args = (basic_args_spec @ adv_args_spec) in + let all_args_spec = process_args all_args in let process args = let current = ref 0 in (try - Arg.parse_argv ~current (Array.of_list ("" :: List.map expand_env args)) all_args_spec args_callback usage; - List.iter (fun fn -> fn()) !arg_delays - with (Arg.Bad msg) as exc -> - let r = Str.regexp "unknown option `\\([-A-Za-z]+\\)'" in + let rec loop acc args = match args with + | "--display" :: arg :: args -> + loop (arg :: "--display" :: acc) args + | arg :: args -> + loop (expand_env arg :: acc) args + | [] -> + List.rev acc + in + let args = loop [] args in + Arg.parse_argv ~current (Array.of_list ("" :: args)) all_args_spec args_callback ""; + with + | Arg.Help _ -> + raise (HelpMessage (usage_string all_args usage)) + | Arg.Bad msg -> + let first_line = List.nth (Str.split (Str.regexp "\n") msg) 0 in + let new_msg = (Printf.sprintf "%s" first_line) in + let r = Str.regexp "unknown option [`']?\\([-A-Za-z]+\\)[`']?" in try ignore(Str.search_forward r msg 0); let s = Str.matched_group 1 msg in let sl = List.map (fun (s,_,_) -> s) all_args_spec in - let msg = StringError.string_error_raise s sl (Printf.sprintf "Invalid command: %s" s) in - raise (Arg.Bad msg) + let sl = StringError.get_similar s sl in + begin match sl with + | [] -> raise Not_found + | _ -> + let spec = List.filter (fun (_,sl',sl'',_,_,_) -> + List.exists (fun s -> List.mem s sl) (sl' @ sl'') + ) all_args in + let new_msg = (Printf.sprintf "%s\nDid you mean:\n%s" first_line (usage_string ~print_cat:false spec "")) in + raise (Arg.Bad new_msg) + end; with Not_found -> - raise exc); - arg_delays := [] + raise (Arg.Bad new_msg)); + if com.platform = Globals.Cpp && not (Define.defined com.defines DisableUnicodeStrings) && not (Define.defined com.defines HxcppSmartStings) then begin + Define.define com.defines HxcppSmartStings; + end; + if Define.raw_defined com.defines "gen_hx_classes" then begin + (* TODO: this is something we're gonna remove once we have something nicer for generating flash externs *) + force_typing := true; + pre_compilation := (fun() -> + let process_lib lib = + if not (lib#has_flag NativeLibraries.FlagIsStd) then + List.iter (fun path -> if path <> (["java";"lang"],"String") then classes := path :: !classes) lib#list_modules + in + List.iter process_lib com.native_libs.net_libs; + List.iter process_lib com.native_libs.swf_libs; + List.iter process_lib com.native_libs.java_libs; + ) :: !pre_compilation; + xml_out := Some "hx" + end; in process_ref := process; + (* Handle CLI arguments *) process ctx.com.args; + (* Process haxelibs *) process_libs(); - if com.display.dms_display then begin - com.warning <- if com.display.dms_error_policy = EPCollect then (fun s p -> add_diagnostics_message com s p DisplayTypes.DiagnosticsSeverity.Warning) else message ctx; - com.error <- error ctx; - end; - Lexer.old_format := Common.defined com Define.OldErrorFormat; - if !Lexer.old_format && Parser.do_resume () then begin - let p = !Parser.resume_display in - (* convert byte position to utf8 position *) - try - let content = Std.input_file ~bin:true (Path.get_real_path p.pfile) in - let pos = UTF8.length (String.sub content 0 p.pmin) in - Parser.resume_display := { p with pmin = pos; pmax = pos } - with _ -> - () (* ignore *) - end; - DisplayOutput.process_display_file com classes; + (* Set up display configuration *) + process_display_configuration ctx; + let display_file_dot_path = DisplayOutput.process_display_file com classes in + (* Initialize target: This allows access to the appropriate std packages and sets the -D defines. *) let ext = Initialize.initialize_target ctx com classes in (* if we are at the last compilation step, allow all packages accesses - in case of macros or opening another project file *) - if com.display.dms_display then begin - if not ctx.has_next then com.package_rules <- PMap.foldi (fun p r acc -> match r with Forbidden -> acc | _ -> PMap.add p r acc) com.package_rules PMap.empty; + if com.display.dms_display then begin match com.display.dms_kind with + | DMDefault -> () + | _ -> if not ctx.has_next then com.package_rules <- PMap.foldi (fun p r acc -> match r with Forbidden -> acc | _ -> PMap.add p r acc) com.package_rules PMap.empty; end; com.config <- get_config com; (* make sure to adapt all flags changes defined after platform *) + let t = Timer.timer ["init"] in List.iter (fun f -> f()) (List.rev (!pre_compilation)); + t(); if !classes = [([],"Std")] && not !force_typing then begin - let help_spec = basic_args_spec @ [ - ("-help", Arg.Unit (fun () -> ()),": show extended help information"); - ("--help", Arg.Unit (fun () -> ()),": show extended help information"); - ("--help-defines", Arg.Unit (fun () -> ()),": print help for all compiler specific defines"); - ("--help-metas", Arg.Unit (fun () -> ()),": print help for all compiler metadatas"); - ("", Arg.Unit (fun () -> ()),": compile the module specified by dot-path"); - ] in - if !cmds = [] && not !did_something then print_endline (Arg.usage_string help_spec usage); + if !cmds = [] && not !did_something then raise (HelpMessage (usage_string basic_args_spec usage)); end else begin - ctx.setup(); - Common.log com ("Classpath : " ^ (String.concat ";" com.class_path)); - Common.log com ("Defines : " ^ (String.concat ";" (PMap.foldi (fun k v acc -> (match v with "1" -> k | _ -> k ^ "=" ^ v) :: acc) com.defines.Define.values []))); - let t = Common.timer ["typing"] in - Typecore.type_expr_ref := (fun ctx e with_type -> Typer.type_expr ctx e with_type); - let tctx = Typer.create com in - List.iter (MacroContext.call_init_macro tctx) (List.rev !config_macros); - List.iter (fun cpath -> ignore(tctx.Typecore.g.Typecore.do_load_module tctx cpath null_pos)) (List.rev !classes); - Typer.finalize tctx; - t(); - if not ctx.com.display.dms_display && ctx.has_error then raise Abort; - if ctx.com.display.dms_exit_during_typing then begin - if ctx.has_next || ctx.has_error then raise Abort; - failwith "No completion point was found"; - end; - let t = Common.timer ["filters"] in - let main, types, modules = Typer.generate tctx in - com.main <- main; - com.types <- types; - com.modules <- modules; - DisplayOutput.process_global_display_mode com tctx; - if not (Common.defined com Define.NoDeprecationWarnings) then - Display.DeprecationCheck.run com; - Filters.run com tctx main; - t(); + (* Actual compilation starts here *) + let tctx = do_type ctx !native_libs !config_macros !classes in + handle_display ctx tctx display_file_dot_path; + filter ctx tctx display_file_dot_path; if ctx.has_error then raise Abort; - (match !xml_out with - | None -> () - | Some "hx" -> - Genxml.generate_hx com - | Some file -> - Common.log com ("Generating xml : " ^ file); - Common.mkdir_from_path file; - Genxml.generate com file); - if not !no_output then generate tctx ext !xml_out !interp !swf_header; + check_auxiliary_output com !xml_out !json_out; + if not !no_output then generate tctx ext !interp !swf_header; end; Sys.catch_break false; - List.iter (fun f -> f()) (List.rev com.callbacks.after_generation); + List.iter (fun f -> f()) (List.rev com.callbacks#get_after_generation); if not !no_output then begin List.iter (fun c -> let r = run_command ctx c in @@ -810,7 +1040,7 @@ with | Parser.Error (m,p) -> error ctx (Parser.error_msg m) p | Typecore.Forbid_package ((pack,m,p),pl,pf) -> - if !Common.display_default <> DMNone && ctx.has_next then begin + if !Parser.display_mode <> DMNone && ctx.has_next then begin ctx.has_error <- false; ctx.messages <- []; end else begin @@ -819,52 +1049,79 @@ with end | Error.Error (m,p) -> error ctx (Error.error_msg m) p - | Hlmacro.Error (msg,p :: l) -> - message ctx msg p; - List.iter (message ctx "Called from") l; - error ctx "Aborted" null_pos; - | Typeload.Generic_Exception(m,p) -> + | Generic.Generic_Exception(m,p) -> error ctx m p | Arg.Bad msg -> error ctx ("Error: " ^ msg) null_pos | Failure msg when not (is_debug_run()) -> error ctx ("Error: " ^ msg) null_pos - | Arg.Help msg -> - message ctx msg null_pos - | Display.DisplayPackage pack -> + | HelpMessage msg -> + com.info msg null_pos + | DisplayException(DisplayHover _ | DisplayPositions _ | DisplayFields _ | DisplayPackage _ | DisplaySignatures _ as de) when ctx.com.json_out <> None -> + begin + DisplayPosition.display_position#reset; + match ctx.com.json_out with + | Some (f,_,jsonrpc) -> + let ctx = DisplayJson.create_json_context jsonrpc (match de with DisplayFields _ -> true | _ -> false) in + f (DisplayException.to_json ctx de) + | _ -> assert false + end + (* | Parser.TypePath (_,_,_,p) when ctx.com.json_out <> None -> + begin match com.json_out with + | Some (f,_) -> + let tctx = Typer.create ctx.com in + let fields = DisplayToplevel.collect tctx true Typecore.NoValue in + let jctx = Genjson.create_context Genjson.GMMinimum in + f (DisplayException.fields_to_json jctx fields CRImport (Some (Parser.cut_pos_at_display p)) false) + | _ -> assert false + end *) + | DisplayException(DisplayPackage pack) -> + DisplayPosition.display_position#reset; raise (DisplayOutput.Completion (String.concat "." pack)) - | Display.DisplayFields fields -> - let fields = List.map ( - fun (name,kind,doc) -> name, kind, (Option.default "" doc) - ) fields in - let fields = - if !measure_times then begin - close_times(); - (List.map (fun (name,value) -> ("@TIME " ^ name, Display.FKTimer value, "")) (DisplayOutput.get_timer_fields !start_time)) @ fields - end else - fields + | DisplayException(DisplayFields Some r) -> + DisplayPosition.display_position#reset; + let fields = if !measure_times then begin + Timer.close_times(); + (List.map (fun (name,value) -> + CompletionItem.make_ci_timer ("@TIME " ^ name) value + ) (DisplayOutput.get_timer_fields !start_time)) @ r.fitems + end else + r.fitems + in + let s = match r.fkind with + | CRToplevel _ + | CRTypeHint + | CRExtends + | CRImplements + | CRStructExtension _ + | CRImport + | CRUsing + | CRNew + | CRPattern _ + | CRTypeRelation + | CRTypeDecl -> + DisplayOutput.print_toplevel fields + | CRField _ + | CRStructureField + | CRMetadata + | CROverride -> + DisplayOutput.print_fields fields in - raise (DisplayOutput.Completion (DisplayOutput.print_fields fields)) - | Display.DisplayType (t,p,doc) -> - let doc = match doc with Some _ -> doc | None -> DisplayOutput.find_doc t in - raise (DisplayOutput.Completion (DisplayOutput.print_type t p doc)) - | Display.DisplaySignatures(signatures,display_arg) -> + raise (DisplayOutput.Completion s) + | DisplayException(DisplayHover Some ({hitem = {CompletionItem.ci_type = Some (t,_)}} as hover)) -> + DisplayPosition.display_position#reset; + let doc = CompletionItem.get_documentation hover.hitem in + raise (DisplayOutput.Completion (DisplayOutput.print_type t hover.hpos doc)) + | DisplayException(DisplaySignatures Some (signatures,_,display_arg,_)) -> + DisplayPosition.display_position#reset; if ctx.com.display.dms_kind = DMSignature then raise (DisplayOutput.Completion (DisplayOutput.print_signature signatures display_arg)) else raise (DisplayOutput.Completion (DisplayOutput.print_signatures signatures)) - | Display.DisplayPosition pl -> + | DisplayException(DisplayPositions pl) -> + DisplayPosition.display_position#reset; raise (DisplayOutput.Completion (DisplayOutput.print_positions pl)) - | Display.DisplayToplevel il -> - let il = - if !measure_times then begin - close_times(); - (List.map (fun (name,value) -> IdentifierType.ITTimer ("@TIME " ^ name ^ ": " ^ value)) (DisplayOutput.get_timer_fields !start_time)) @ il - end else - il - in - raise (DisplayOutput.Completion (DisplayOutput.print_toplevel il)) - | Parser.TypePath (p,c,is_import) -> + | Parser.TypePath (p,c,is_import,pos) -> let fields = try begin match c with | None -> @@ -875,20 +1132,43 @@ with error ctx msg p; None in - Option.may (fun fields -> raise (DisplayOutput.Completion (DisplayOutput.print_fields fields))) fields - | Display.ModuleSymbols s | Display.Diagnostics s | Display.Statistics s | Display.Metadata s -> + begin match fields with + | None -> () + | Some fields -> + begin match ctx.com.json_out with + | Some (f,_,jsonrpc) -> + let ctx = DisplayJson.create_json_context jsonrpc false in + let path = match List.rev p with + | name :: pack -> List.rev pack,name + | [] -> [],"" + in + let kind = CRField ((CompletionItem.make_ci_module path,pos,None,None)) in + f (DisplayException.fields_to_json ctx fields kind None None); + | _ -> raise (DisplayOutput.Completion (DisplayOutput.print_fields fields)) + end + end + | Parser.SyntaxCompletion(kind,pos) -> + DisplayOutput.handle_syntax_completion com kind pos; + error ctx ("Error: No completion point was found") null_pos + | DisplayException(ModuleSymbols s | Diagnostics s | Statistics s | Metadata s) -> + DisplayPosition.display_position#reset; raise (DisplayOutput.Completion s) | EvalExceptions.Sys_exit i | Hlinterp.Sys_exit i -> ctx.flush(); - if !measure_times then report_times prerr_endline; + if !measure_times then Timer.report_times prerr_endline; exit i + | DisplayOutput.Completion _ as exc -> + raise exc + | Out_of_memory as exc -> + raise exc | e when (try Sys.getenv "OCAMLRUNPARAM" <> "b" || CompilationServer.runs() with _ -> true) && not (is_debug_run()) -> error ctx (Printexc.to_string e) null_pos ;; -let other = Common.timer ["other"] in +let other = Timer.timer ["other"] in Sys.catch_break true; MacroContext.setup(); + let args = List.tl (Array.to_list Sys.argv) in (try let server = Sys.getenv "HAXE_COMPILATION_SERVER" in @@ -904,4 +1184,4 @@ with DisplayOutput.Completion c -> exit 1 ); other(); -if !measure_times then report_times prerr_endline +if !measure_times then Timer.report_times prerr_endline diff --git a/src/compiler/server.ml b/src/compiler/server.ml index f222b68f0b4..5bc47b31ce3 100644 --- a/src/compiler/server.ml +++ b/src/compiler/server.ml @@ -2,16 +2,19 @@ open Printf open Globals open Ast open Common -open Common.DisplayMode +open CompilationServer +open DisplayTypes.DisplayMode +open Timer open Type open DisplayOutput open Json exception Dirty of module_def +exception ServerError of string let measure_times = ref false let prompt = ref false -let start_time = ref (get_time()) +let start_time = ref (Timer.get_time()) let is_debug_run() = try Sys.getenv "HAXEDEBUG" = "1" with _ -> false @@ -20,132 +23,71 @@ type context = { com : Common.context; mutable flush : unit -> unit; mutable setup : unit -> unit; - mutable messages : string list; + mutable messages : compiler_message list; mutable has_next : bool; mutable has_error : bool; } -type server_message = - | AddedDirectory of string - | FoundDirectories of (string * float ref) list - | ChangedDirectories of (string * float) list - | ModulePathChanged of (module_def * float * string) - | NotCached of module_def - | Parsed of (string * string) - | RemovedDirectory of string - | Reusing of module_def - | SkippingDep of (module_def * module_def) - -let s_version = - Printf.sprintf "%d.%d.%d%s" version_major version_minor version_revision (match Version.version_extra with None -> "" | Some v -> " " ^ v) - -type timer_node = { - name : string; - path : string; - parent : timer_node; - info : string; - mutable time : float; - mutable num_calls : int; - mutable children : timer_node list; -} +let s_version with_build = + let pre = Option.map_default (fun pre -> "-" ^ pre) "" version_pre in + let build = + match with_build, Version.version_extra with + | true, Some (_,build) -> "+" ^ build + | _, _ -> "" + in + Printf.sprintf "%d.%d.%d%s%s" version_major version_minor version_revision pre build -let report_times print = - let nodes = Hashtbl.create 0 in - let rec root = { - name = ""; - path = ""; - parent = root; - info = ""; - time = 0.; - num_calls = 0; - children = []; - } in - Hashtbl.iter (fun _ timer -> - let rec loop parent sl = match sl with - | [] -> assert false - | s :: sl -> - let path = (match parent.path with "" -> "" | _ -> parent.path ^ ".") ^ s in - let node = try - let node = Hashtbl.find nodes path in - node.num_calls <- node.num_calls + timer.calls; - node.time <- node.time +. timer.total; - node - with Not_found -> - let name,info = try - let i = String.rindex s '.' in - String.sub s (i + 1) (String.length s - i - 1),String.sub s 0 i - with Not_found -> - s,"" - in - let node = { - name = name; - path = path; - parent = parent; - info = info; - time = timer.total; - num_calls = timer.calls; - children = []; - } in - Hashtbl.add nodes path node; - node +let check_display_flush ctx f_otherwise = match ctx.com.json_out with + | None -> + begin match ctx.com.display.dms_kind with + | DMDiagnostics global-> + List.iter (fun msg -> + let msg,p,kind = match msg with + | CMInfo(msg,p) -> msg,p,DisplayTypes.DiagnosticsSeverity.Information + | CMWarning(msg,p) -> msg,p,DisplayTypes.DiagnosticsSeverity.Warning + | CMError(msg,p) -> msg,p,DisplayTypes.DiagnosticsSeverity.Error in - begin match sl with - | [] -> () - | _ -> - let child = loop node sl in - if not (List.memq child node.children) then - node.children <- child :: node.children; - end; - node - in - let node = loop root timer.id in - if not (List.memq node root.children) then - root.children <- node :: root.children - ) Common.htimers; - let max_name = ref 0 in - let max_calls = ref 0 in - let rec loop depth node = - let l = (String.length node.name) + 2 * depth in - List.iter (fun child -> - if depth = 0 then begin - node.num_calls <- node.num_calls + child.num_calls; - node.time <- node.time +. child.time; - end; - loop (depth + 1) child; - ) node.children; - node.children <- List.sort (fun node1 node2 -> compare node2.time node1.time) node.children; - if node.num_calls > !max_calls then max_calls := node.num_calls; - if node.time > 0.0009 && l > !max_name then max_name := l; - in - loop 0 root; - let max_calls = String.length (string_of_int !max_calls) in - print (Printf.sprintf "%-*s | %7s | %% | p%% | %*s | info" !max_name "name" "time(s)" max_calls "#"); - let sep = String.make (!max_name + max_calls + 27) '-' in - print sep; - let print_time name node = - if node.time > 0.0009 then - print (Printf.sprintf "%-*s | %7.3f | %3.0f | %3.0f | %*i | %s" !max_name name node.time (node.time *. 100. /. root.time) (node.time *. 100. /. node.parent.time) max_calls node.num_calls node.info) - in - let rec loop depth node = - let name = (String.make (depth * 2) ' ') ^ node.name in - print_time name node; - List.iter (loop (depth + 1)) node.children - in - List.iter (loop 0) root.children; - print sep; - print_time "total" root + add_diagnostics_message ctx.com msg p DisplayTypes.DiagnosticsKind.DKCompilerError kind + ) (List.rev ctx.messages); + raise (Completion (Diagnostics.print ctx.com global)) + | _ -> + f_otherwise () + end + | Some(_,f,_) -> + if ctx.has_error then begin + let errors = List.map (fun msg -> + let msg,p,i = match msg with + | CMInfo(msg,p) -> msg,p,3 + | CMWarning(msg,p) -> msg,p,2 + | CMError(msg,p) -> msg,p,1 + in + JObject [ + "severity",JInt i; + "location",Genjson.generate_pos_as_location p; + "message",JString msg; + ] + ) (List.rev ctx.messages) in + f errors + end let default_flush ctx = - List.iter prerr_endline (List.rev ctx.messages); - if ctx.has_error && !prompt then begin - print_endline "Press enter to exit..."; - ignore(read_line()); - end; - if ctx.has_error then exit 1 + check_display_flush ctx (fun () -> + List.iter + (fun msg -> match msg with + | CMInfo _ -> print_endline (compiler_message_string msg) + | CMWarning _ | CMError _ -> prerr_endline (compiler_message_string msg) + ) + (List.rev ctx.messages); + if ctx.has_error && !prompt then begin + print_endline "Press enter to exit..."; + ignore(read_line()); + end; + if ctx.has_error then exit 1 + ) let create_context params = let ctx = { - com = Common.create version s_version params; + com = Common.create version (s_version true) params; flush = (fun()->()); setup = (fun()->()); messages = []; @@ -188,95 +130,56 @@ let ssend sock str = loop 0 (Bytes.length str) let rec wait_loop process_params verbose accept = - Sys.catch_break false; - let has_parse_error = ref false in - let test_server_messages = DynArray.create () in + if verbose then ServerMessage.enable_all (); + Sys.catch_break false; (* Sys can never catch a break *) let cs = CompilationServer.create () in - let sign_string com = - let sign = Define.get_signature com.defines in - let sign_id = - try - CompilationServer.get_sign cs sign; - with Not_found -> - let i = CompilationServer.add_sign cs sign in - print_endline (Printf.sprintf "Found context %s:\n%s" i (dump_context com)); - i - in - Printf.sprintf "%2s,%3s: " sign_id (short_platform_name com.platform) - in - let process_server_message com tabs = - if Common.raw_defined com "compilation-server-test" then (fun message -> - let module_path m = JString (s_type_path m.m_path) in - let kind,data = match message with - | AddedDirectory dir -> "addedDirectory",JString dir - | FoundDirectories dirs -> "foundDirectories",JInt (List.length dirs) - | ChangedDirectories dirs -> "changedDirectories",JArray (List.map (fun (s,_) -> JString s) dirs) - | ModulePathChanged(m,time,file) -> "modulePathChanged",module_path m - | NotCached m -> "notCached",module_path m - | Parsed(ffile,_) -> "parsed",JString ffile - | RemovedDirectory dir -> "removedDirectory",JString dir - | Reusing m -> "reusing",module_path m - | SkippingDep(m,m') -> "skipping",JObject ["skipped",module_path m;"dependency",module_path m'] - in - let js = JObject [("kind",JString kind);("data",data)] in - DynArray.add test_server_messages js; - ) else (fun message -> match message with - | AddedDirectory dir -> print_endline (Printf.sprintf "%sadded directory %s" (sign_string com) dir) - | FoundDirectories dirs -> print_endline (Printf.sprintf "%sfound %i directories" (sign_string com) (List.length dirs)); - | ChangedDirectories dirs -> - print_endline (Printf.sprintf "%schanged directories: [%s]" (sign_string com) (String.concat ", " (List.map (fun (s,_) -> "\"" ^ s ^ "\"") dirs))) - | ModulePathChanged(m,time,file) -> - print_endline (Printf.sprintf "%smodule path might have changed: %s\n\twas: %2.0f %s\n\tnow: %2.0f %s" - (sign_string com) (s_type_path m.m_path) m.m_extra.m_time m.m_extra.m_file time file); - | NotCached m -> print_endline (Printf.sprintf "%s%s not cached (%s)" (sign_string com) (s_type_path m.m_path) (if m.m_extra.m_time = -1. then "macro-in-macro" else "modified")); - | Parsed(ffile,info) -> print_endline (Printf.sprintf "%sparsed %s (%s)" (sign_string com) ffile info) - | RemovedDirectory dir -> print_endline (Printf.sprintf "%sremoved directory %s" (sign_string com) dir); - | Reusing m -> print_endline (Printf.sprintf "%s%sreusing %s" (sign_string com) tabs (s_type_path m.m_path)); - | SkippingDep(m,m') -> print_endline (Printf.sprintf "%sskipping %s%s" (sign_string com) (s_type_path m.m_path) (if m == m' then "" else Printf.sprintf "(%s)" (s_type_path m'.m_path))); - ) - in MacroContext.macro_enable_cache := true; let current_stdin = ref None in - Typeload.parse_hook := (fun com2 file p -> + TypeloadParse.parse_hook := (fun com2 file p -> let ffile = Path.unique_full_path file in - let is_display_file = ffile = (!Parser.resume_display).pfile in + let is_display_file = ffile = (DisplayPosition.display_position#get).pfile in match is_display_file, !current_stdin with | true, Some stdin when Common.defined com2 Define.DisplayStdin -> - Typeload.parse_file_from_string com2 file p stdin + TypeloadParse.parse_file_from_string com2 file p stdin | _ -> let sign = Define.get_signature com2.defines in let ftime = file_time ffile in let fkey = (ffile,sign) in - try - let time, data = CompilationServer.find_file cs fkey in - if time <> ftime then raise Not_found; - data - with Not_found -> - has_parse_error := false; - let data = Typeload.parse_file com2 file p in - let info,is_unusual = if !has_parse_error then "not cached, has parse error",true - else if is_display_file then "not cached, is display file",true - else begin try - (* We assume that when not in display mode it's okay to cache stuff that has #if display - checks. The reasoning is that non-display mode has more information than display mode. *) - if not com2.display.dms_display then raise Not_found; - let ident = Hashtbl.find Parser.special_identifier_files ffile in - Printf.sprintf "not cached, using \"%s\" define" ident,true - with Not_found -> - CompilationServer.cache_file cs fkey (ftime,data); - "cached",false - end in - if verbose && is_unusual then process_server_message com2 "" (Parsed(ffile,info)); - data + let data = Std.finally (Timer.timer ["server";"parser cache"]) (fun () -> + try + let cfile = CompilationServer.find_file cs fkey in + if cfile.c_time <> ftime then raise Not_found; + Parser.ParseSuccess(cfile.c_package,cfile.c_decls) + with Not_found -> + let parse_result = TypeloadParse.parse_file com2 file p in + let info,is_unusual = match parse_result with + | ParseError(_,_,_) -> "not cached, has parse error",true + | ParseDisplayFile _ -> "not cached, is display file",true + | ParseSuccess data -> + begin try + (* We assume that when not in display mode it's okay to cache stuff that has #if display + checks. The reasoning is that non-display mode has more information than display mode. *) + if not com2.display.dms_display then raise Not_found; + let ident = Hashtbl.find Parser.special_identifier_files ffile in + Printf.sprintf "not cached, using \"%s\" define" ident,true + with Not_found -> + CompilationServer.cache_file cs fkey ftime data; + "cached",false + end + in + if is_unusual then ServerMessage.parsed com2 "" (ffile,info); + parse_result + ) () in + data ); let check_module_shadowing com paths m = - List.iter (fun (path,_) -> - let file = (path ^ (snd m.m_path)) ^ ".hx" in + List.iter (fun dir -> + let file = (dir.c_path ^ (snd m.m_path)) ^ ".hx" in if Sys.file_exists file then begin let time = file_time file in if time > m.m_extra.m_time then begin - if verbose then process_server_message com "" (ModulePathChanged(m,time,file)); + ServerMessage.module_path_changed com "" (m,time,file); raise Not_found end end @@ -289,7 +192,7 @@ let rec wait_loop process_params verbose accept = (Unix.stat (Path.remove_trailing_slash dir)).Unix.st_mtime in let get_changed_directories (ctx : Typecore.typer) = - let t = Common.timer ["server";"module cache";"changed dirs"] in + let t = Timer.timer ["server";"module cache";"changed dirs"] in let com = ctx.Typecore.com in let sign = Define.get_signature com.defines in let dirs = try @@ -299,28 +202,28 @@ let rec wait_loop process_params verbose accept = let dirs = try (* Next, get all directories from the cache and filter the ones that haven't changed. *) let all_dirs = CompilationServer.find_directories cs sign in - let dirs = List.fold_left (fun acc (dir,time) -> + let dirs = List.fold_left (fun acc dir -> try - let time' = stat dir in - if !time < time' then begin - time := time'; - let sub_dirs = Path.find_directories (platform_name com.platform) false [dir] in + let time' = stat dir.c_path in + if dir.c_mtime < time' then begin + dir.c_mtime <- time'; + let sub_dirs = Path.find_directories (platform_name com.platform) false [dir.c_path] in List.iter (fun dir -> if not (CompilationServer.has_directory cs sign dir) then begin let time = stat dir in - if verbose then process_server_message com "" (AddedDirectory dir); - CompilationServer.add_directory cs sign (dir,ref time) + ServerMessage.added_directory com "" dir; + CompilationServer.add_directory cs sign (CompilationServer.create_directory dir time) end; ) sub_dirs; - (dir,time') :: acc + (CompilationServer.create_directory dir.c_path time') :: acc end else acc with Unix.Unix_error _ -> - CompilationServer.remove_directory cs sign dir; - if verbose then process_server_message com "" (RemovedDirectory dir); + CompilationServer.remove_directory cs sign dir.c_path; + ServerMessage.removed_directory com "" dir.c_path; acc ) [] all_dirs in - if verbose then process_server_message com "" (ChangedDirectories dirs); + ServerMessage.changed_directories com "" dirs; dirs with Not_found -> (* There were no directories in the cache, so this must be a new context. Let's add @@ -332,13 +235,13 @@ let rec wait_loop process_params verbose accept = let add_dir path = try let time = stat path in - dirs := (path,ref time) :: !dirs + dirs := CompilationServer.create_directory path time :: !dirs with Unix.Unix_error _ -> () in List.iter add_dir com.class_path; List.iter add_dir (Path.find_directories (platform_name com.platform) true com.class_path); - if verbose then process_server_message com "" (FoundDirectories !dirs); + ServerMessage.found_directories com "" !dirs; CompilationServer.add_directories cs sign !dirs ) :: !delays; (* Returning [] should be fine here because it's a new context, so we won't do any @@ -354,19 +257,21 @@ let rec wait_loop process_params verbose accept = let compilation_step = ref 0 in let compilation_mark = ref 0 in let mark_loop = ref 0 in - Typeload.type_module_hook := (fun (ctx:Typecore.typer) mpath p -> - let t = Common.timer ["server";"module cache"] in + let removed_modules = ref [] in + let is_removed_module m = List.exists (fun (_,m') -> m == m') !removed_modules in + TypeloadModule.type_module_hook := (fun (ctx:Typecore.typer) mpath p -> + let t = Timer.timer ["server";"module cache"] in let com2 = ctx.Typecore.com in let sign = Define.get_signature com2.defines in let content_changed m file = let ffile = Path.unique_full_path file in let fkey = (ffile,sign) in try - let _, old_data = CompilationServer.find_file cs fkey in + let cfile = CompilationServer.find_file cs fkey in (* We must use the module path here because the file path is absolute and would cause positions in the parsed declarations to differ. *) - let new_data = Typeload.parse_module ctx m.m_path p in - snd old_data <> snd new_data + let new_data = TypeloadParse.parse_module ctx m.m_path p in + cfile.c_decls <> snd new_data with Not_found -> true in @@ -380,21 +285,21 @@ let rec wait_loop process_params verbose accept = | MFake | MImport -> () (* don't get classpath *) | MExtern -> (* if we have a file then this will override our extern type *) - let has_file = (try check_module_shadowing com2 directories m; true with Not_found -> false) in + let has_file = (try check_module_shadowing com2 directories m; false with Not_found -> true) in if has_file then begin - if verbose then print_endline ("A file is masking the library file " ^ s_type_path m.m_path); + if verbose then print_endline ("A file is masking the library file " ^ s_type_path m.m_path); (* TODO *) raise Not_found; end; let rec loop = function | [] -> - if verbose then print_endline ("No library file was found for " ^ s_type_path m.m_path); + if verbose then print_endline ("No library file was found for " ^ s_type_path m.m_path); (* TODO *) raise Not_found (* no extern registration *) - | load :: l -> + | (file,load) :: l -> match load m.m_path p with | None -> loop l - | Some (file,_) -> + | Some _ -> if Path.unique_full_path file <> m.m_extra.m_file then begin - if verbose then print_endline ("Library file was changed for " ^ s_type_path m.m_path); + if verbose then print_endline ("Library file was changed for " ^ s_type_path m.m_path); (* TODO *) raise Not_found; end in @@ -402,16 +307,29 @@ let rec wait_loop process_params verbose accept = | MCode -> check_module_shadowing com2 directories m | MMacro when ctx.Typecore.in_macro -> check_module_shadowing com2 directories m | MMacro -> + (* + Creating another context while the previous one is incomplete means we have an infinite loop in the compiler. + Most likely because of circular dependencies in base modules (e.g. `StdTypes` or `String`) + Prevents spending another 5 hours for debugging. + @see https://github.com/HaxeFoundation/haxe/issues/8174 + *) + if not ctx.g.complete && ctx.in_macro then + raise (ServerError ("Infinite loop in Haxe server detected. " + ^ "Probably caused by shadowing a module of the standard library. " + ^ "Make sure shadowed module does not pull macro context.")); let _, mctx = MacroContext.get_macro_context ctx p in check_module_shadowing mctx.Typecore.com (get_changed_directories mctx) m in - let has_policy policy = List.mem policy m.m_extra.m_check_policy in + let has_policy policy = List.mem policy m.m_extra.m_check_policy || match policy with + | NoCheckShadowing | NoCheckFileTimeModification when !ServerConfig.do_not_check_modules && !Parser.display_mode <> DMNone -> true + | _ -> false + in let check_file () = if file_time m.m_extra.m_file <> m.m_extra.m_time then begin if has_policy CheckFileContentModification && not (content_changed m m.m_extra.m_file) then begin - if verbose then print_endline (Printf.sprintf "%s%s changed time not but content, reusing" (sign_string com2) m.m_extra.m_file) + ServerMessage.unchanged_content com2 "" m.m_extra.m_file; end else begin - if verbose then process_server_message com2 "" (NotCached m); + ServerMessage.not_cached com2 "" m; if m.m_extra.m_kind = MFake then Hashtbl.remove Typecore.fake_modules m.m_extra.m_file; raise Not_found; end @@ -430,11 +348,16 @@ let rec wait_loop process_params verbose accept = if m.m_extra.m_mark = mark then None else try - if m.m_extra.m_mark <= start_mark then begin - if not (has_policy NoCheckShadowing) then check_module_path(); + let old_mark = m.m_extra.m_mark in + m.m_extra.m_mark <- mark; + if old_mark <= start_mark then begin + (* Workaround for preview.4 Java issue *) + begin match m.m_extra.m_kind with + | MExtern -> check_module_path() + | _ -> if not (has_policy NoCheckShadowing) then check_module_path(); + end; if not (has_policy NoCheckFileTimeModification) then check_file(); end; - m.m_extra.m_mark <- mark; if not (has_policy NoCheckDependencies) then check_dependencies(); None with @@ -452,8 +375,10 @@ let rec wait_loop process_params verbose accept = | MCode, MMacro | MMacro, MCode -> (* this was just a dependency to check : do not add to the context *) PMap.iter (Hashtbl.replace com2.resources) m.m_extra.m_binded_res; + | _ when is_removed_module m -> + () | _ -> - if verbose then process_server_message com2 tabs (Reusing m); + ServerMessage.reusing com2 tabs m; m.m_extra.m_added <- !compilation_step; List.iter (fun t -> match t with @@ -471,26 +396,24 @@ let rec wait_loop process_params verbose accept = a.a_meta <- List.filter (fun (m,_,_) -> m <> Meta.ValueUsed) a.a_meta | _ -> () ) m.m_types; - Typeload.add_module ctx m p; + TypeloadModule.add_module ctx m p; PMap.iter (Hashtbl.replace com2.resources) m.m_extra.m_binded_res; - if ctx.Typecore.in_macro || com2.display.dms_full_typing then - PMap.iter (fun _ m2 -> add_modules (tabs ^ " ") m0 m2) m.m_extra.m_deps; - List.iter (MacroContext.call_init_macro ctx) m.m_extra.m_macro_calls + PMap.iter (fun _ m2 -> add_modules (tabs ^ " ") m0 m2) m.m_extra.m_deps ) end in try let m = CompilationServer.find_module cs (mpath,sign) in - let tcheck = Common.timer ["server";"module cache";"check"] in + let tcheck = Timer.timer ["server";"module cache";"check"] in begin match check m with | None -> () | Some m' -> - if verbose then process_server_message com2 "" (SkippingDep(m,m')); + ServerMessage.skipping_dep com2 "" (m,m'); tcheck(); raise Not_found; end; tcheck(); - let tadd = Common.timer ["server";"module cache";"add modules"] in + let tadd = Timer.timer ["server";"module cache";"add modules"] in add_modules "" m m; tadd(); t(); @@ -502,49 +425,62 @@ let rec wait_loop process_params verbose accept = let run_count = ref 0 in while true do let read, write, close = accept() in - let rec cache_context com = - let cache_module m = - CompilationServer.cache_module cs (m.m_path,m.m_extra.m_sign) m; - (*if verbose then print_endline (Printf.sprintf "%scached %s" (sign_string com) (s_type_path m.m_path));*) - in + let was_compilation = ref false in + let recache_removed_modules () = + List.iter (fun (k,m) -> + try + ignore(CompilationServer.find_module cs k); + with Not_found -> + CompilationServer.cache_module cs k m + ) !removed_modules; + removed_modules := []; + in + let maybe_cache_context com = if com.display.dms_full_typing then begin - List.iter cache_module com.modules; - if verbose then print_endline ("Cached " ^ string_of_int (List.length com.modules) ^ " modules"); - end; - match com.get_macros() with - | None -> () - | Some com -> cache_context com + CompilationServer.cache_context cs com; + ServerMessage.cached_modules com "" (List.length com.modules); + removed_modules := []; + end else + recache_removed_modules(); in let create params = let ctx = create_context params in ctx.flush <- (fun() -> incr compilation_step; compilation_mark := !mark_loop; - List.iter (fun s -> write (s ^ "\n"); if verbose then print_endline ("> " ^ s)) (List.rev ctx.messages); - if ctx.has_error then begin - measure_times := false; - write "\x02\n" - end else cache_context ctx.com; + check_display_flush ctx (fun () -> + List.iter + (fun msg -> + let s = compiler_message_string msg in + write (s ^ "\n"); + ServerMessage.message s; + ) + (List.rev ctx.messages); + was_compilation := ctx.com.display.dms_full_typing; + if ctx.has_error then begin + measure_times := false; + write "\x02\n" + end else maybe_cache_context ctx.com; + ) ); ctx.setup <- (fun() -> let sign = Define.get_signature ctx.com.defines in - if verbose then begin - let defines = PMap.foldi (fun k v acc -> (k ^ "=" ^ v) :: acc) ctx.com.defines.Define.values [] in - print_endline ("Defines " ^ (String.concat "," (List.sort compare defines))); - print_endline ("Using signature " ^ Digest.to_hex sign); - print_endline ("Display position: " ^ (Printer.s_pos !Parser.resume_display)); - end; - Parser.display_error := (fun e p -> has_parse_error := true; ctx.com.error (Parser.error_msg e) p); - if ctx.com.display.dms_display then begin - let file = (!Parser.resume_display).pfile in + ServerMessage.defines ctx.com ""; + ServerMessage.signature ctx.com "" sign; + ServerMessage.display_position ctx.com "" (DisplayPosition.display_position#get); + (* Special case for diagnostics: It's not treated as a display mode, but we still want to invalidate the + current file in order to run diagnostics on it again. *) + if ctx.com.display.dms_display || (match ctx.com.display.dms_kind with DMDiagnostics _ -> true | _ -> false) then begin + let file = (DisplayPosition.display_position#get).pfile in let fkey = (file,sign) in (* force parsing again : if the completion point have been changed *) CompilationServer.remove_file cs fkey; - CompilationServer.taint_modules cs file; + removed_modules := CompilationServer.filter_modules cs file; + delays := recache_removed_modules :: !delays; end; try if (Hashtbl.find arguments sign) <> ctx.com.class_path then begin - if verbose then print_endline (Printf.sprintf "%sclass paths changed, resetting directories" (sign_string ctx.com)); + ServerMessage.class_paths_changed ctx.com ""; Hashtbl.replace arguments sign ctx.com.class_path; CompilationServer.clear_directories cs sign; end; @@ -567,21 +503,20 @@ let rec wait_loop process_params verbose accept = s in let data = parse_hxml_data hxml in - if verbose then print_endline ("Processing Arguments [" ^ String.concat "," data ^ "]"); + ServerMessage.arguments data; (try - DynArray.clear test_server_messages; Hashtbl.clear changed_directories; - Common.display_default := DMNone; - Parser.resume_display := null_pos; - Typeload.return_partial_type := false; + Parser.reset_state(); + return_partial_type := false; measure_times := false; + Hashtbl.clear DeprecationCheck.warned_positions; close_times(); stats.s_files_parsed := 0; stats.s_classes_built := 0; stats.s_methods_typed := 0; stats.s_macros_called := 0; - Hashtbl.clear Common.htimers; - let _ = Common.timer ["other"] in + Hashtbl.clear Timer.htimers; + let _ = Timer.timer ["other"] in incr compilation_step; compilation_mark := !mark_loop; start_time := get_time(); @@ -590,43 +525,36 @@ let rec wait_loop process_params verbose accept = if !measure_times then report_times (fun s -> write (s ^ "\n")) with | Completion str -> - if verbose then print_endline ("Completion Response =\n" ^ str); + ServerMessage.completion str; write str | Arg.Bad msg -> print_endline ("Error: " ^ msg); ); - if DynArray.length test_server_messages > 0 then begin - let b = Buffer.create 0 in - write_json (Buffer.add_string b) (JArray (DynArray.to_list test_server_messages)); - write (Buffer.contents b) - end; let fl = !delays in delays := []; List.iter (fun f -> f()) fl; - if verbose then begin - print_endline (Printf.sprintf "Stats = %d files, %d classes, %d methods, %d macros" !(stats.s_files_parsed) !(stats.s_classes_built) !(stats.s_methods_typed) !(stats.s_macros_called)); - print_endline (Printf.sprintf "Time spent : %.3fs" (get_time() -. t0)); - end; + ServerMessage.stats stats (get_time() -. t0); with Unix.Unix_error _ -> - if verbose then print_endline "Connection Aborted" + ServerMessage.socket_message "Connection Aborted" | e -> let estr = Printexc.to_string e in - if verbose then print_endline ("Uncaught Error : " ^ estr); - (try write estr with _ -> ()); - if is_debug_run() then print_endline (Printexc.get_backtrace()); + ServerMessage.uncaught_error estr; + (try write ("\x02\n" ^ estr); with _ -> ()); + if is_debug_run() then print_endline (estr ^ "\n" ^ Printexc.get_backtrace()); + if e = Out_of_memory then begin + close(); + exit (-1); + end; ); close(); current_stdin := None; (* prevent too much fragmentation by doing some compactions every X run *) - incr run_count; + if !was_compilation then incr run_count; if !run_count mod 10 = 0 then begin + run_count := 1; let t0 = get_time() in Gc.compact(); - if verbose then begin - let stat = Gc.quick_stat() in - let size = (float_of_int stat.Gc.heap_words) *. 4. in - print_endline (Printf.sprintf "Compacted memory %.3fs %.1fMB" (get_time() -. t0) (size /. (1024. *. 1024.))); - end + ServerMessage.gc_stats (get_time() -. t0); end else Gc.minor(); done @@ -652,18 +580,18 @@ and init_wait_stdio() = Buffer.clear berr; read, write, close -and init_wait_socket verbose host port = +and init_wait_socket host port = let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in (try Unix.setsockopt sock Unix.SO_REUSEADDR true with _ -> ()); (try Unix.bind sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't wait on " ^ host ^ ":" ^ string_of_int port)); - if verbose then print_endline ("Waiting on " ^ host ^ ":" ^ string_of_int port); + ServerMessage.socket_message ("Waiting on " ^ host ^ ":" ^ string_of_int port); Unix.listen sock 10; let bufsize = 1024 in let tmp = Bytes.create bufsize in let accept() = ( let sin, _ = Unix.accept sock in Unix.set_nonblock sin; - if verbose then print_endline "Client connected"; + ServerMessage.socket_message "Client connected"; let b = Buffer.create 0 in let rec read_loop count = try @@ -671,7 +599,7 @@ and init_wait_socket verbose host port = if r = 0 then failwith "Incomplete request" else begin - if verbose then Printf.printf "Reading %d bytes\n" r; + ServerMessage.socket_message (Printf.sprintf "Reading %d bytes\n" r); Buffer.add_subbytes b tmp 0 r; if Bytes.get tmp (r-1) = '\000' then Buffer.sub b 0 (Buffer.length b - 1) @@ -682,7 +610,7 @@ and init_wait_socket verbose host port = if count = 100 then failwith "Aborting inactive connection" else begin - if verbose then print_endline "Waiting for data..."; + ServerMessage.socket_message "Waiting for data..."; ignore(Unix.select [] [] [] 0.05); (* wait a bit *) read_loop (count + 1); end diff --git a/src/compiler/serverConfig.ml b/src/compiler/serverConfig.ml new file mode 100644 index 00000000000..0bca3c59354 --- /dev/null +++ b/src/compiler/serverConfig.ml @@ -0,0 +1 @@ +let do_not_check_modules = ref false \ No newline at end of file diff --git a/src/compiler/serverMessage.ml b/src/compiler/serverMessage.ml new file mode 100644 index 00000000000..df9367d4d53 --- /dev/null +++ b/src/compiler/serverMessage.ml @@ -0,0 +1,192 @@ +open Globals +open Common +open CompilationServer +open Type +open Json + +type server_message_options = { + mutable print_added_directory : bool; + mutable print_found_directories : bool; + mutable print_changed_directories : bool; + mutable print_module_path_changed : bool; + mutable print_not_cached : bool; + mutable print_parsed : bool; + mutable print_removed_directory : bool; + mutable print_reusing : bool; + mutable print_skipping_dep : bool; + mutable print_unchanged_content : bool; + mutable print_cached_modules : bool; + mutable print_class_paths_changed : bool; + mutable print_arguments : bool; + mutable print_completion : bool; + mutable print_defines : bool; + mutable print_signature : bool; + mutable print_display_position : bool; + mutable print_stats : bool; + mutable print_message : bool; + mutable print_socket_message : bool; + mutable print_uncaught_error : bool; + mutable print_new_context : bool; +} + +let config = { + print_added_directory = false; + print_found_directories = false; + print_changed_directories = false; + print_module_path_changed = false; + print_not_cached = false; + print_parsed = false; + print_removed_directory = false; + print_reusing = false; + print_skipping_dep = false; + print_unchanged_content = false; + print_cached_modules = false; + print_class_paths_changed = false; + print_arguments = false; + print_completion = false; + print_defines = false; + print_signature = false; + print_display_position = false; + print_stats = false; + print_message = false; + print_socket_message = false; + print_uncaught_error = false; + print_new_context = false; +} + +let sign_string com = + let sign = Define.get_signature com.defines in + let cs = CompilationServer.force () in + let sign_id = + try + (CompilationServer.get_sign cs sign).cs_index + with Not_found -> + let i = CompilationServer.add_sign cs sign "message" com in + if config.print_new_context then print_endline (Printf.sprintf "Found context %i:\n%s" i (dump_context com)); + i + in + Printf.sprintf "%2i,%3s: " sign_id (short_platform_name com.platform) + +let added_directory com tabs dir = + if config.print_added_directory then print_endline (Printf.sprintf "%sadded directory %s" (sign_string com) dir) + +let found_directories com tabs dirs = + if config.print_found_directories then print_endline (Printf.sprintf "%sfound %i directories" (sign_string com) (List.length dirs)) + +let changed_directories com tabs dirs = + if config.print_changed_directories then print_endline (Printf.sprintf "%schanged directories: [%s]" (sign_string com) (String.concat ", " (List.map (fun dir -> "\"" ^ dir.c_path ^ "\"") dirs))) + +let module_path_changed com tabs (m,time,file) = + if config.print_module_path_changed then print_endline (Printf.sprintf "%smodule path might have changed: %s\n\twas: %2.0f %s\n\tnow: %2.0f %s" + (sign_string com) (s_type_path m.m_path) m.m_extra.m_time m.m_extra.m_file time file) + +let not_cached com tabs m = + if config.print_not_cached then print_endline (Printf.sprintf "%s%s not cached (%s)" (sign_string com) (s_type_path m.m_path) "modified") + +let parsed com tabs (ffile,info) = + if config.print_parsed then print_endline (Printf.sprintf "%sparsed %s (%s)" (sign_string com) ffile info) + +let removed_directory com tabs dir = + if config.print_removed_directory then print_endline (Printf.sprintf "%sremoved directory %s" (sign_string com) dir) + +let reusing com tabs m = + if config.print_reusing then print_endline (Printf.sprintf "%s%sreusing %s" (sign_string com) tabs (s_type_path m.m_path)) + +let skipping_dep com tabs (m,m') = + if config.print_skipping_dep then print_endline (Printf.sprintf "%sskipping %s%s" (sign_string com) (s_type_path m.m_path) (if m == m' then "" else Printf.sprintf "(%s)" (s_type_path m'.m_path))) + +let unchanged_content com tabs file = + if config.print_unchanged_content then print_endline (Printf.sprintf "%s%s changed time not but content, reusing" (sign_string com) file) + +let cached_modules com tabs i = + if config.print_cached_modules then print_endline (Printf.sprintf "%sCached %i modules" (sign_string com) i) + +let class_paths_changed com tabs = + if config.print_class_paths_changed then print_endline (Printf.sprintf "%sclass paths changed, resetting directories" (sign_string com)) + +let arguments data = + if config.print_arguments then print_endline (("Processing Arguments [" ^ String.concat "," data ^ "]")) + +let completion str = + if config.print_completion then print_endline ("Completion Response =\n" ^ str) + +let defines com tabs = + if config.print_defines then begin + let defines = PMap.foldi (fun k v acc -> (k ^ "=" ^ v) :: acc) com.defines.Define.values [] in + print_endline ("Defines " ^ (String.concat "," (List.sort compare defines))) + end + +let signature com tabs sign = + if config.print_signature then print_endline ("Using signature " ^ Digest.to_hex sign) + +let display_position com tabs p = + if config.print_display_position then print_endline ("Display position: " ^ (Printer.s_pos p)) + +let stats stats time = + if config.print_stats then begin + print_endline (Printf.sprintf "Stats = %d files, %d classes, %d methods, %d macros" !(stats.s_files_parsed) !(stats.s_classes_built) !(stats.s_methods_typed) !(stats.s_macros_called)); + print_endline (Printf.sprintf "Time spent : %.3fs" time) + end + +let message s = + if config.print_message then print_endline ("> " ^ s) + +let gc_stats time = + if config.print_stats then begin + let stat = Gc.quick_stat() in + let size = (float_of_int stat.Gc.heap_words) *. 4. in + print_endline (Printf.sprintf "Compacted memory %.3fs %.1fMB" time (size /. (1024. *. 1024.))); + end + +let socket_message s = + if config.print_socket_message then print_endline s + +let uncaught_error s = + if config.print_uncaught_error then print_endline ("Uncaught Error : " ^ s) + +let enable_all () = + config.print_added_directory <- true; + config.print_found_directories <- true; + config.print_changed_directories <- true; + config.print_module_path_changed <- true; + config.print_not_cached <- true; + config.print_parsed <- true; + config.print_removed_directory <- true; + config.print_reusing <- true; + config.print_skipping_dep <- true; + config.print_unchanged_content <- true; + config.print_cached_modules <- true; + config.print_arguments <- true; + config.print_completion <- true; + config.print_defines <- true; + config.print_signature <- true; + config.print_display_position <- true; + config.print_stats <- true; + config.print_message <- true; + config.print_socket_message <- true; + config.print_uncaught_error <- true; + config.print_new_context <- true + +let set_by_name name value = match name with + | "addedDirectory" -> config.print_added_directory <- value + | "foundDirectories" -> config.print_found_directories <- value; + | "changedDirectories" -> config.print_changed_directories <- value; + | "modulePathChanged" -> config.print_module_path_changed <- value; + | "notCached" -> config.print_not_cached <- value; + | "parsed" -> config.print_parsed <- value; + | "removedDirectory" -> config.print_removed_directory <- value; + | "reusing" -> config.print_reusing <- value; + | "skippingDep" -> config.print_skipping_dep <- value; + | "unchangedContent" -> config.print_unchanged_content <- value; + | "cachedModules" -> config.print_cached_modules <- value; + | "arguments" -> config.print_arguments <- value; + | "completion" -> config.print_completion <- value; + | "defines" -> config.print_defines <- value; + | "signature" -> config.print_signature <- value; + | "displayPosition" -> config.print_display_position <- value; + | "stats" -> config.print_stats <- value; + | "message" -> config.print_message <- value; + | "socketMessage" -> config.print_socket_message <- value; + | "uncaughtError" -> config.print_uncaught_error <- value; + | "newContext" -> config.print_new_context <- value; + | _ -> raise Not_found \ No newline at end of file diff --git a/src/context/abstractCast.ml b/src/context/abstractCast.ml new file mode 100644 index 00000000000..060692aa325 --- /dev/null +++ b/src/context/abstractCast.ml @@ -0,0 +1,290 @@ +open Globals +open Common +open Ast +open Type +open Typecore +open Error + +let cast_stack = new_rec_stack() + +let make_static_call ctx c cf a pl args t p = + if cf.cf_kind = Method MethMacro then begin + match args with + | [e] -> + let e,f = push_this ctx e in + ctx.with_type_stack <- (WithType.with_type t) :: ctx.with_type_stack; + let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name [e] p with + | Some e -> type_expr ctx e WithType.value + | None -> type_expr ctx (EConst (Ident "null"),p) WithType.value + in + ctx.with_type_stack <- List.tl ctx.with_type_stack; + f(); + e + | _ -> assert false + end else + make_static_call ctx c cf (apply_params a.a_params pl) args t p + +let do_check_cast ctx tleft eright p = + let recurse cf f = + if cf == ctx.curfield || rec_stack_memq cf cast_stack then error "Recursive implicit cast" p; + rec_stack_loop cast_stack cf f () + in + let find a tl f = + let tcf,cf = f() in + if (Meta.has Meta.MultiType a.a_meta) then + mk_cast eright tleft p + else match a.a_impl with + | Some c -> recurse cf (fun () -> + let ret = make_static_call ctx c cf a tl [eright] tleft p in + { ret with eexpr = TMeta( (Meta.ImplicitCast,[],ret.epos), ret) } + ) + | None -> assert false + in + if type_iseq tleft eright.etype then + eright + else begin + let rec loop stack tleft tright = + if List.exists (fun (tleft',tright') -> fast_eq tleft tleft' && fast_eq tright tright') stack then + raise Not_found + else begin + let stack = (tleft,tright) :: stack in + match follow tleft,follow tright with + | TAbstract(a1,tl1),TAbstract(a2,tl2) -> + Abstract.find_to_from find a1 tl1 a2 tl2 tleft eright.etype + | TAbstract(a,tl),_ -> + begin try find a tl (fun () -> Abstract.find_from a tl eright.etype tleft) + with Not_found -> + let rec loop2 tcl = match tcl with + | tc :: tcl -> + if not (type_iseq tc tleft) then loop stack (apply_params a.a_params tl tc) tright + else loop2 tcl + | [] -> raise Not_found + in + loop2 a.a_from + end + | _,TAbstract(a,tl) -> + begin try find a tl (fun () -> Abstract.find_to a tl tleft) + with Not_found -> + let rec loop2 tcl = match tcl with + | tc :: tcl -> + if not (type_iseq tc tright) then loop stack tleft (apply_params a.a_params tl tc) + else loop2 tcl + | [] -> raise Not_found + in + loop2 a.a_to + end + | _ -> + raise Not_found + end + in + loop [] tleft eright.etype + end + +let cast_or_unify_raise ctx tleft eright p = + try + (* can't do that anymore because this might miss macro calls (#4315) *) + (* if ctx.com.display <> DMNone then raise Not_found; *) + do_check_cast ctx tleft eright p + with Not_found -> + unify_raise ctx eright.etype tleft p; + eright + +let cast_or_unify ctx tleft eright p = + try + cast_or_unify_raise ctx tleft eright p + with Error (Unify l,p) -> + raise_or_display ctx l p; + eright + +let find_array_access_raise ctx a pl e1 e2o p = + let is_set = e2o <> None in + let ta = apply_params a.a_params pl a.a_this in + let rec loop cfl = match cfl with + | [] -> raise Not_found + | cf :: cfl -> + let monos = List.map (fun _ -> mk_mono()) cf.cf_params in + let map t = apply_params a.a_params pl (apply_params cf.cf_params monos t) in + let check_constraints () = + List.iter2 (fun m (name,t) -> match follow t with + | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> + List.iter (fun tc -> match follow m with TMono _ -> raise (Unify_error []) | _ -> Type.unify m (map tc) ) constr + | _ -> () + ) monos cf.cf_params; + in + match follow (map cf.cf_type) with + | TFun([(_,_,tab);(_,_,ta1);(_,_,ta2)],r) as tf when is_set -> + begin try + Type.unify tab ta; + let e1 = cast_or_unify_raise ctx ta1 e1 p in + let e2o = match e2o with None -> None | Some e2 -> Some (cast_or_unify_raise ctx ta2 e2 p) in + check_constraints(); + cf,tf,r,e1,e2o + with Unify_error _ | Error (Unify _,_) -> + loop cfl + end + | TFun([(_,_,tab);(_,_,ta1)],r) as tf when not is_set -> + begin try + Type.unify tab ta; + let e1 = cast_or_unify_raise ctx ta1 e1 p in + check_constraints(); + cf,tf,r,e1,None + with Unify_error _ | Error (Unify _,_) -> + loop cfl + end + | _ -> loop cfl + in + loop a.a_array + +let find_array_access ctx a tl e1 e2o p = + try find_array_access_raise ctx a tl e1 e2o p + with Not_found -> match e2o with + | None -> + error (Printf.sprintf "No @:arrayAccess function accepts argument of %s" (s_type (print_context()) e1.etype)) p + | Some e2 -> + error (Printf.sprintf "No @:arrayAccess function accepts arguments of %s and %s" (s_type (print_context()) e1.etype) (s_type (print_context()) e2.etype)) p + +let find_multitype_specialization com a pl p = + let m = mk_mono() in + let tl = match Meta.get Meta.MultiType a.a_meta with + | _,[],_ -> pl + | _,el,_ -> + let relevant = Hashtbl.create 0 in + List.iter (fun e -> + let rec loop f e = match fst e with + | EConst(Ident s) -> + Hashtbl.replace relevant s f + | EMeta((Meta.Custom ":followWithAbstracts",_,_),e1) -> + loop Abstract.follow_with_abstracts e1; + | _ -> + error "Type parameter expected" (pos e) + in + loop (fun t -> t) e + ) el; + let tl = List.map2 (fun (n,_) t -> + try + (Hashtbl.find relevant n) t + with Not_found -> + if not (has_mono t) then t + else t_dynamic + ) a.a_params pl in + if com.platform = Globals.Js && a.a_path = (["haxe";"ds"],"Map") then begin match tl with + | t1 :: _ -> + let stack = ref [] in + let rec loop t = + if List.exists (fun t2 -> fast_eq t t2) !stack then + t + else begin + stack := t :: !stack; + match follow t with + | TAbstract ({ a_path = [],"Class" },_) -> + error (Printf.sprintf "Cannot use %s as key type to Map because Class is not comparable" (s_type (print_context()) t1)) p; + | TEnum(en,tl) -> + PMap.iter (fun _ ef -> ignore(loop ef.ef_type)) en.e_constrs; + Type.map loop t + | t -> + Type.map loop t + end + in + ignore(loop t1) + | _ -> assert false + end; + tl + in + let _,cf = + try + Abstract.find_to a tl m + with Not_found -> + let at = apply_params a.a_params pl a.a_this in + let st = s_type (print_context()) at in + if has_mono at then + error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p + else + error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p; + in + cf, follow m + +let handle_abstract_casts ctx e = + let rec loop ctx e = match e.eexpr with + | TNew({cl_kind = KAbstractImpl a} as c,pl,el) -> + if not (Meta.has Meta.MultiType a.a_meta) then begin + (* This must have been a @:generic expansion with a { new } constraint (issue #4364). In this case + let's construct the underlying type. *) + match Abstract.get_underlying_type a pl with + | TInst(c,tl) as t -> {e with eexpr = TNew(c,tl,el); etype = t} + | _ -> error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos + end else begin + (* a TNew of an abstract implementation is only generated if it is a multi type abstract *) + let cf,m = find_multitype_specialization ctx.com a pl e.epos in + let e = make_static_call ctx c cf a pl ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el) m e.epos in + {e with etype = m} + end + | TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) -> + begin match follow e1.etype with + | TAbstract({a_impl = Some c} as a,tl) -> + begin try + let cf = PMap.find "toString" c.cl_statics in + make_static_call ctx c cf a tl [e1] ctx.t.tstring e.epos + with Not_found -> + e + end + | _ -> + assert false + end + | TCall(e1, el) -> + begin try + let rec find_abstract e t = match follow t,e.eexpr with + | TAbstract(a,pl),_ when Meta.has Meta.MultiType a.a_meta -> a,pl,e + | _,TCast(e1,None) -> find_abstract e1 e1.etype + | _,TLocal {v_extra = Some(_,Some e')} -> + begin match follow e'.etype with + | TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta -> a,pl,mk (TCast(e,None)) e'.etype e.epos + | _ -> raise Not_found + end + | _ -> raise Not_found + in + let rec find_field e1 = + match e1.eexpr with + | TCast(e2,None) -> + {e1 with eexpr = TCast(find_field e2,None)} + | TField(e2,fa) -> + let a,pl,e2 = find_abstract e2 e2.etype in + let m = Abstract.get_underlying_type a pl in + let fname = field_name fa in + let el = List.map (loop ctx) el in + begin try + let fa = quick_field m fname in + let get_fun_type t = match follow t with + | TFun(_,tr) as tf -> tf,tr + | _ -> raise Not_found + in + let tf,tr = match fa with + | FStatic(_,cf) -> get_fun_type cf.cf_type + | FInstance(c,tl,cf) -> get_fun_type (apply_params c.cl_params tl cf.cf_type) + | FAnon cf -> get_fun_type cf.cf_type + | _ -> raise Not_found + in + let ef = mk (TField({e2 with etype = m},fa)) tf e2.epos in + let ecall = make_call ctx ef el tr e.epos in + if not (type_iseq ecall.etype e.etype) then + mk (TCast(ecall,None)) e.etype e.epos + else + ecall + with Not_found -> + (* quick_field raises Not_found if m is an abstract, we have to replicate the 'using' call here *) + match follow m with + | TAbstract({a_impl = Some c} as a,pl) -> + let cf = PMap.find fname c.cl_statics in + make_static_call ctx c cf a pl (e2 :: el) e.etype e.epos + | _ -> raise Not_found + end + | _ -> + raise Not_found + in + find_field e1 + with Not_found -> + Type.map_expr (loop ctx) e + end + | _ -> + Type.map_expr (loop ctx) e + in + loop ctx e \ No newline at end of file diff --git a/src/context/common.ml b/src/context/common.ml index 41f608dcfda..6bf9cfacd8a 100644 --- a/src/context/common.ml +++ b/src/context/common.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,6 +21,7 @@ open Ast open Type open Globals open Define +open NativeLibraries type package_rule = | Forbidden @@ -29,16 +30,6 @@ type package_rule = type pos = Globals.pos -type basic_types = { - mutable tvoid : t; - mutable tint : t; - mutable tfloat : t; - mutable tbool : t; - mutable tnull : t -> t; - mutable tstring : t; - mutable tarray : t -> t; -} - let const_type basic const default = match const with | TString _ -> basic.tstring @@ -54,6 +45,25 @@ type stats = { s_macros_called : int ref; } +type compiler_message = + | CMInfo of string * pos + | CMWarning of string * pos + | CMError of string * pos + +let compiler_message_string msg = + let (str,p) = match msg with + | CMInfo(str,p) | CMError(str,p) -> (str,p) + | CMWarning(str,p) -> ("Warning : " ^ str, p) + in + if p = null_pos then + str + else begin + let error_printer file line = Printf.sprintf "%s:%d:" file line in + let epos = Lexer.get_error_pos error_printer p in + let str = String.concat ("\n" ^ epos ^ " : ") (ExtString.String.nsplit str "\n") in + Printf.sprintf "%s : %s" epos str + end + (** The capture policy tells which handling we make of captured locals (the locals which are referenced in local functions) @@ -85,162 +95,69 @@ type platform_config = { pf_can_skip_non_nullable_argument : bool; (** type paths that are reserved on the platform *) pf_reserved_type_paths : path list; + (** supports function == function **) + pf_supports_function_equality : bool; + (** uses utf16 encoding with ucs2 api **) + pf_uses_utf16 : bool; + (** target supports accessing `this` before calling `super(...)` **) + pf_this_before_super : bool; + (** target supports threads **) + pf_supports_threads : bool; + (** target supports Unicode **) + pf_supports_unicode : bool; } -module DisplayMode = struct - type t = - | DMNone - | DMField - | DMUsage of bool (* true = also report definition *) - | DMPosition - | DMToplevel - | DMResolve of string - | DMPackage - | DMType - | DMModuleSymbols of string option - | DMDiagnostics of bool (* true = global, false = only in display file *) - | DMStatistics - | DMSignature - - type error_policy = - | EPIgnore - | EPCollect - | EPShow - - type display_file_policy = - | DFPOnly - | DFPAlso - | DFPNo - - type settings = { - dms_kind : t; - dms_display : bool; - dms_full_typing : bool; - dms_force_macro_typing : bool; - dms_error_policy : error_policy; - dms_collect_data : bool; - dms_check_core_api : bool; - dms_inline : bool; - dms_display_file_policy : display_file_policy; - dms_exit_during_typing : bool; - } +class compiler_callbacks = object(self) + val mutable before_typer_create = []; + val mutable after_init_macros = []; + val mutable after_typing = []; + val mutable before_save = []; + val mutable after_save = []; + val mutable after_filters = []; + val mutable after_generation = []; + val mutable null_safety_report = []; - let default_display_settings = { - dms_kind = DMField; - dms_display = true; - dms_full_typing = false; - dms_force_macro_typing = false; - dms_error_policy = EPIgnore; - dms_collect_data = false; - dms_check_core_api = false; - dms_inline = false; - dms_display_file_policy = DFPOnly; - dms_exit_during_typing = true; - } + method add_before_typer_create (f : unit -> unit) : unit = + before_typer_create <- f :: before_typer_create - let default_compilation_settings = { - dms_kind = DMNone; - dms_display = false; - dms_full_typing = true; - dms_force_macro_typing = true; - dms_error_policy = EPShow; - dms_collect_data = false; - dms_check_core_api = true; - dms_inline = true; - dms_display_file_policy = DFPNo; - dms_exit_during_typing = false; - } + method add_after_init_macros (f : unit -> unit) : unit = + after_init_macros <- f :: after_init_macros - let create dm = - let settings = { default_display_settings with dms_kind = dm } in - match dm with - | DMNone -> default_compilation_settings - | DMField | DMPosition | DMResolve _ | DMPackage | DMType | DMSignature -> settings - | DMUsage _ -> { settings with - dms_full_typing = true; - dms_collect_data = true; - dms_display_file_policy = DFPAlso; - dms_exit_during_typing = false - } - | DMToplevel -> { settings with dms_full_typing = true; } - | DMModuleSymbols filter -> { settings with - dms_display_file_policy = if filter = None then DFPOnly else DFPNo; - dms_exit_during_typing = false; - dms_force_macro_typing = false; - } - | DMDiagnostics global -> { settings with - dms_full_typing = true; - dms_error_policy = EPCollect; - dms_collect_data = true; - dms_inline = true; - dms_display_file_policy = if global then DFPNo else DFPAlso; - dms_exit_during_typing = false; - } - | DMStatistics -> { settings with - dms_full_typing = true; - dms_collect_data = true; - dms_inline = false; - dms_display_file_policy = DFPAlso; - dms_exit_during_typing = false - } + method add_after_typing (f : module_type list -> unit) : unit = + after_typing <- f :: after_typing - let to_string = function - | DMNone -> "none" - | DMField -> "field" - | DMPosition -> "position" - | DMResolve s -> "resolve " ^ s - | DMPackage -> "package" - | DMType -> "type" - | DMUsage true -> "rename" - | DMUsage false -> "references" - | DMToplevel -> "toplevel" - | DMModuleSymbols None -> "module-symbols" - | DMModuleSymbols (Some s) -> "workspace-symbols " ^ s - | DMDiagnostics b -> (if b then "global " else "") ^ "diagnostics" - | DMStatistics -> "statistics" - | DMSignature -> "signature" -end + method add_before_save (f : unit -> unit) : unit = + before_save <- f :: before_save -type compiler_callback = { - mutable after_typing : (module_type list -> unit) list; - mutable before_dce : (unit -> unit) list; - mutable after_generation : (unit -> unit) list; -} + method add_after_save (f : unit -> unit) : unit = + after_save <- f :: after_save + + method add_after_filters (f : unit -> unit) : unit = + after_filters <- f :: after_filters -module IdentifierType = struct - type t = - | ITLocal of tvar - | ITMember of tclass * tclass_field - | ITStatic of tclass * tclass_field - | ITEnum of tenum * tenum_field - | ITEnumAbstract of tabstract * tclass_field - | ITGlobal of module_type * string * Type.t - | ITType of module_type - | ITPackage of string - | ITLiteral of string - | ITTimer of string - - let get_name = function - | ITLocal v -> v.v_name - | ITMember(_,cf) | ITStatic(_,cf) | ITEnumAbstract(_,cf) -> cf.cf_name - | ITEnum(_,ef) -> ef.ef_name - | ITGlobal(_,s,_) -> s - | ITType mt -> snd (t_infos mt).mt_path - | ITPackage s -> s - | ITLiteral s -> s - | ITTimer s -> s + method add_after_generation (f : unit -> unit) : unit = + after_generation <- f :: after_generation + + method add_null_safety_report (f : (string*pos) list -> unit) : unit = + null_safety_report <- f :: null_safety_report + + method get_before_typer_create = before_typer_create + method get_after_init_macros = after_init_macros + method get_after_typing = after_typing + method get_before_save = before_save + method get_after_save = after_save + method get_after_filters = after_filters + method get_after_generation = after_generation + method get_null_safety_report = null_safety_report end type shared_display_information = { mutable import_positions : (pos,bool ref * placed_name list) PMap.t; - mutable diagnostics_messages : (string * pos * DisplayTypes.DiagnosticsSeverity.t) list; - mutable type_hints : (pos,Type.t) Hashtbl.t; - mutable document_symbols : (string * DisplayTypes.SymbolInformation.t DynArray.t) list; - mutable removable_code : (string * pos * pos) list; + mutable diagnostics_messages : (string * pos * DisplayTypes.DiagnosticsKind.t * DisplayTypes.DiagnosticsSeverity.t) list; } type display_information = { - mutable unresolved_identifiers : (string * pos * (string * IdentifierType.t) list) list; + mutable unresolved_identifiers : (string * pos * (string * CompletionItem.t * int) list) list; mutable interface_field_implementations : (tclass * tclass_field * tclass * tclass_field option) list; } @@ -256,7 +173,7 @@ type context = { shared : shared_context; display_information : display_information; mutable sys_args : string list; - mutable display : DisplayMode.settings; + mutable display : DisplayTypes.DisplayMode.settings; mutable debug : bool; mutable verbose : bool; mutable foptimize : bool; @@ -264,20 +181,26 @@ type context = { mutable config : platform_config; mutable std_path : string list; mutable class_path : string list; - mutable main_class : Type.path option; + mutable main_class : path option; mutable package_rules : (string,package_rule) PMap.t; mutable error : string -> pos -> unit; + mutable info : string -> pos -> unit; mutable warning : string -> pos -> unit; - mutable load_extern_type : (path -> pos -> (string * Ast.package) option) list; (* allow finding types which are not in sources *) - callbacks : compiler_callback; + mutable get_messages : unit -> compiler_message list; + mutable filter_messages : (compiler_message -> bool) -> unit; + mutable load_extern_type : (string * (path -> pos -> Ast.package option)) list; (* allow finding types which are not in sources *) + callbacks : compiler_callbacks; defines : Define.define; mutable print : string -> unit; mutable get_macros : unit -> context option; mutable run_command : string -> int; file_lookup_cache : (string,string option) Hashtbl.t; + readdir_cache : (string * string,(string array) option) Hashtbl.t; parser_cache : (string,(type_def * pos) list) Hashtbl.t; - cached_macros : (path * string,((string * bool * t) list * t * tclass * Type.tclass_field)) Hashtbl.t; + module_to_file : (path,string) Hashtbl.t; + cached_macros : (path * string,(((string * bool * t) list * t * tclass * Type.tclass_field) * module_def)) Hashtbl.t; mutable stored_typed_exprs : (int, texpr) PMap.t; + pass_debug_messages : string DynArray.t; (* output *) mutable file : string; mutable flash_version : float; @@ -288,13 +211,12 @@ type context = { mutable resources : (string,string) Hashtbl.t; mutable neko_libs : string list; mutable include_files : (string * string) list; - mutable swf_libs : (string * (unit -> Swf.swf) * (unit -> ((string list * string),As3hl.hl_class) Hashtbl.t)) list; - mutable java_libs : (string * bool * (unit -> unit) * (unit -> (path list)) * (path -> ((JData.jclass * string * string) option))) list; (* (path,std,close,all_files,lookup) *) - mutable net_libs : (string * bool * (unit -> path list) * (path -> IlData.ilclass option)) list; (* (path,std,all_files,lookup) *) + mutable native_libs : native_libraries; mutable net_std : string list; net_path_map : (path,string list * string list * string) Hashtbl.t; mutable c_args : string list; mutable js_gen : (unit -> unit) option; + mutable json_out : ((Json.t -> unit) * (Json.t list -> unit) * Jsonrpc_handler.jsonrpc_handler) option; (* typing *) mutable basic : basic_types; memory_marker : float array; @@ -302,130 +224,6 @@ type context = { exception Abort of string * pos -let display_default = ref DisplayMode.DMNone - -module CompilationServer = struct - type cache = { - c_haxelib : (string list, string list) Hashtbl.t; - c_files : ((string * string), float * Ast.package) Hashtbl.t; - c_modules : (path * string, module_def) Hashtbl.t; - c_directories : (string, (string * float ref) list) Hashtbl.t; - } - - type t = { - cache : cache; - mutable signs : (string * string) list; - } - - type context_options = - | NormalContext - | MacroContext - | NormalAndMacroContext - - let instance : t option ref = ref None - - let create_cache () = { - c_haxelib = Hashtbl.create 0; - c_files = Hashtbl.create 0; - c_modules = Hashtbl.create 0; - c_directories = Hashtbl.create 0; - } - - let create () = - let cs = { - cache = create_cache(); - signs = []; - } in - instance := Some cs; - cs - - let get () = - !instance - - let runs () = - !instance <> None - - let get_context_files cs signs = - Hashtbl.fold (fun (file,sign) (_,data) acc -> - if (List.mem sign signs) then (file,data) :: acc - else acc - ) cs.cache.c_files [] - - (* signatures *) - - let get_sign cs sign = - List.assoc sign cs.signs - - let add_sign cs sign = - let i = string_of_int (List.length cs.signs) in - cs.signs <- (sign,i) :: cs.signs; - i - - (* modules *) - - let find_module cs key = - Hashtbl.find cs.cache.c_modules key - - let cache_module cs key value = - Hashtbl.replace cs.cache.c_modules key value - - let taint_modules cs file = - Hashtbl.iter (fun _ m -> if m.m_extra.m_file = file then m.m_extra.m_dirty <- Some m) cs.cache.c_modules - - (* files *) - - let find_file cs key = - Hashtbl.find cs.cache.c_files key - - let cache_file cs key value = - Hashtbl.replace cs.cache.c_files key value - - let remove_file cs key = - Hashtbl.remove cs.cache.c_files key - - let remove_files cs file = - List.iter (fun (sign,_) -> remove_file cs (sign,file)) cs.signs - - (* haxelibs *) - - let find_haxelib cs key = - Hashtbl.find cs.cache.c_haxelib key - - let cache_haxelib cs key value = - Hashtbl.replace cs.cache.c_haxelib key value - - (* directories *) - - let find_directories cs key = - Hashtbl.find cs.cache.c_directories key - - let add_directories cs key value = - Hashtbl.replace cs.cache.c_directories key value - - let remove_directory cs key value = - try - let current = find_directories cs key in - Hashtbl.replace cs.cache.c_directories key (List.filter (fun (s,_) -> s <> value) current); - with Not_found -> - () - - let has_directory cs key value = - try - List.mem_assoc value (find_directories cs key) - with Not_found -> - false - - let add_directory cs key value = - try - let current = find_directories cs key in - add_directories cs key (value :: current) - with Not_found -> - add_directories cs key [value] - - let clear_directories cs key = - Hashtbl.remove cs.cache.c_directories key -end - (* Defines *) module Define = Define @@ -456,6 +254,9 @@ let define_value com k v = let raw_defined_value com k = Define.raw_defined_value com.defines k +let get_es_version com = + try int_of_string (defined_value com Define.JsEs) with _ -> 0 + let short_platform_name = function | Cross -> "x" | Js -> "js" @@ -488,6 +289,11 @@ let default_config = pf_overload = false; pf_can_skip_non_nullable_argument = true; pf_reserved_type_paths = []; + pf_supports_function_equality = true; + pf_uses_utf16 = true; + pf_this_before_super = true; + pf_supports_threads = false; + pf_supports_unicode = true; } let get_config com = @@ -502,18 +308,23 @@ let get_config com = pf_sys = false; pf_capture_policy = CPLoopVars; pf_reserved_type_paths = [([],"Object");([],"Error")]; + pf_this_before_super = (get_es_version com) < 6; (* cannot access `this` before `super()` when generating ES6 classes *) } | Lua -> { default_config with pf_static = false; pf_capture_policy = CPLoopVars; + pf_uses_utf16 = false; } | Neko -> { default_config with pf_static = false; pf_pad_nulls = true; + pf_uses_utf16 = false; + pf_supports_threads = true; + pf_supports_unicode = false; } | Flash when defined Define.As3 -> { @@ -535,6 +346,7 @@ let get_config com = { default_config with pf_static = false; + pf_uses_utf16 = false; } | Cpp -> { @@ -542,6 +354,8 @@ let get_config com = pf_capture_policy = CPWrapRef; pf_pad_nulls = true; pf_add_final_return = true; + pf_supports_threads = true; + pf_supports_unicode = (defined Define.Cppia) || not (defined Define.DisableUnicodeStrings); } | Cs -> { @@ -549,6 +363,7 @@ let get_config com = pf_capture_policy = CPWrapRef; pf_pad_nulls = true; pf_overload = true; + pf_supports_threads = true; } | Java -> { @@ -556,42 +371,41 @@ let get_config com = pf_capture_policy = CPWrapRef; pf_pad_nulls = true; pf_overload = true; + pf_supports_threads = true; + pf_this_before_super = false; } | Python -> { default_config with pf_static = false; pf_capture_policy = CPLoopVars; + pf_uses_utf16 = false; } | Hl -> { default_config with pf_capture_policy = CPWrapRef; pf_pad_nulls = true; - pf_can_skip_non_nullable_argument = false; + pf_supports_threads = true; } | Eval -> { default_config with pf_static = false; pf_pad_nulls = true; + pf_uses_utf16 = false; + pf_supports_threads = true; + pf_capture_policy = CPWrapRef; } let memory_marker = [|Unix.time()|] -let create_callbacks () = - { - after_typing = []; - before_dce = []; - after_generation = []; - } - let create version s_version args = let m = Type.mk_mono() in let defines = PMap.add "true" "1" ( - PMap.add "source-header" ("Generated by Haxe " ^ s_version) ( - if !display_default <> DisplayMode.DMNone then PMap.add "display" "1" PMap.empty else PMap.empty)) + PMap.add "source-header" ("Generated by Haxe " ^ s_version) PMap.empty + ) in { version = version; @@ -600,9 +414,6 @@ let create version s_version args = shared_display_information = { import_positions = PMap.empty; diagnostics_messages = []; - type_hints = Hashtbl.create 0; - document_symbols = []; - removable_code = []; } }; display_information = { @@ -611,7 +422,7 @@ let create version s_version args = }; sys_args = args; debug = false; - display = DisplayMode.create !display_default; + display = DisplayTypes.DisplayMode.create !Parser.display_mode; verbose = false; foptimize = true; features = Hashtbl.create 0; @@ -625,15 +436,13 @@ let create version s_version args = package_rules = PMap.empty; file = ""; types = []; - callbacks = create_callbacks(); + callbacks = new compiler_callbacks; modules = []; main = None; flash_version = 10.; resources = Hashtbl.create 0; - swf_libs = []; - java_libs = []; - net_libs = []; net_std = []; + native_libs = create_native_libs(); net_path_map = Hashtbl.create 0; c_args = []; neko_libs = []; @@ -645,8 +454,12 @@ let create version s_version args = values = defines; }; get_macros = (fun() -> None); + info = (fun _ _ -> assert false); warning = (fun _ _ -> assert false); error = (fun _ _ -> assert false); + get_messages = (fun() -> []); + filter_messages = (fun _ -> ()); + pass_debug_messages = DynArray.create(); basic = { tvoid = m; tint = m; @@ -657,10 +470,13 @@ let create version s_version args = tarray = (fun _ -> assert false); }; file_lookup_cache = Hashtbl.create 0; + readdir_cache = Hashtbl.create 0; + module_to_file = Hashtbl.create 0; stored_typed_exprs = PMap.empty; cached_macros = Hashtbl.create 0; memory_marker = memory_marker; parser_cache = Hashtbl.create 0; + json_out = None; } let log com str = @@ -673,8 +489,10 @@ let clone com = main_class = None; features = Hashtbl.create 0; file_lookup_cache = Hashtbl.create 0; - parser_cache = Hashtbl.create 0 ; - callbacks = create_callbacks(); + readdir_cache = Hashtbl.create 0; + parser_cache = Hashtbl.create 0; + module_to_file = Hashtbl.create 0; + callbacks = new compiler_callbacks; display_information = { unresolved_identifiers = []; interface_field_implementations = []; @@ -682,7 +500,8 @@ let clone com = defines = { values = com.defines.values; defines_signature = com.defines.defines_signature; - } + }; + native_libs = create_native_libs(); } let file_time file = Extc.filetime file @@ -696,7 +515,7 @@ let flash_versions = List.map (fun v -> let maj = int_of_float v in let min = int_of_float (mod_float (v *. 10.) 10.) in v, string_of_int maj ^ (if min = 0 then "" else "_" ^ string_of_int min) -) [9.;10.;10.1;10.2;10.3;11.;11.1;11.2;11.3;11.4;11.5;11.6;11.7;11.8;11.9;12.0;13.0;14.0;15.0;16.0;17.0] +) [9.;10.;10.1;10.2;10.3;11.;11.1;11.2;11.3;11.4;11.5;11.6;11.7;11.8;11.9;12.0;13.0;14.0;15.0;16.0;17.0;18.0;19.0;20.0;21.0;22.0;23.0;24.0;25.0;26.0;27.0;28.0;29.0;31.0;32.0] let flash_version_tag = function | 6. -> 6 @@ -723,10 +542,28 @@ let init_platform com pf = com.platform <- pf; let name = platform_name pf in let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in - com.package_rules <- List.fold_left forbid com.package_rules (List.map platform_name platforms); + com.package_rules <- List.fold_left forbid com.package_rules ("jvm" :: (List.map platform_name platforms)); com.config <- get_config com; -(* if com.config.pf_static then define com "static"; *) - if com.config.pf_sys then define com Define.Sys else com.package_rules <- PMap.add "sys" Forbidden com.package_rules; + if com.config.pf_static then begin + raw_define_value com.defines "target.static" "true"; + define com Define.Static; + end; + if com.config.pf_sys then begin + raw_define_value com.defines "target.sys" "true"; + define com Define.Sys + end else + com.package_rules <- PMap.add "sys" Forbidden com.package_rules; + if com.config.pf_uses_utf16 then begin + raw_define_value com.defines "target.utf16" "true"; + define com Define.Utf16; + end; + if com.config.pf_supports_threads then begin + raw_define_value com.defines "target.threaded" "true"; + end; + if com.config.pf_supports_unicode then begin + raw_define_value com.defines "target.unicode" "true"; + end; + raw_define_value com.defines "target.name" name; raw_define com name let add_feature com f = @@ -754,22 +591,22 @@ let rec has_feature com f = match List.rev (ExtString.String.nsplit f ".") with | [] -> assert false | [cl] -> has_feature com (cl ^ ".*") - | meth :: cl :: pack -> + | field :: cl :: pack -> let r = (try let path = List.rev pack, cl in (match List.find (fun t -> t_path t = path && not (Meta.has Meta.RealPath (t_infos t).mt_meta)) com.types with - | t when meth = "*" -> (match t with TAbstractDecl a -> Meta.has Meta.ValueUsed a.a_meta | _ -> - Meta.has Meta.Used (t_infos t).mt_meta) + | t when field = "*" -> + not (has_dce com) || + (match t with TAbstractDecl a -> Meta.has Meta.ValueUsed a.a_meta | _ -> Meta.has Meta.Used (t_infos t).mt_meta) | TClassDecl ({cl_extern = true} as c) when com.platform <> Js || cl <> "Array" && cl <> "Math" -> - Meta.has Meta.Used (try PMap.find meth c.cl_statics with Not_found -> PMap.find meth c.cl_fields).cf_meta + not (has_dce com) || Meta.has Meta.Used (try PMap.find field c.cl_statics with Not_found -> PMap.find field c.cl_fields).cf_meta | TClassDecl c -> - PMap.exists meth c.cl_statics || PMap.exists meth c.cl_fields + PMap.exists field c.cl_statics || PMap.exists field c.cl_fields | _ -> false) with Not_found -> false ) in - let r = r || not (has_dce com) in Hashtbl.add com.features f r; r @@ -783,159 +620,92 @@ let abort msg p = raise (Abort (msg,p)) let platform ctx p = ctx.platform = p -let add_typing_filter ctx f = - ctx.callbacks.after_typing <- f :: ctx.callbacks.after_typing - -let add_filter ctx f = - ctx.callbacks.before_dce <- f :: ctx.callbacks.before_dce +let platform_name_macro com = + if defined com Define.Macro then "macro" else platform_name com.platform -let add_final_filter ctx f = - ctx.callbacks.after_generation <- f :: ctx.callbacks.after_generation +let normalize_dir_separator path = + if is_windows then String.map (fun c -> if c = '/' then '\\' else c) path + else path let find_file ctx f = try - (match Hashtbl.find ctx.file_lookup_cache f with + match Hashtbl.find ctx.file_lookup_cache f with | None -> raise Exit - | Some f -> f) + | Some f -> f with Exit -> raise Not_found | Not_found -> + let remove_extension file = + try String.sub file 0 (String.rindex file '.') + with Not_found -> file + in + let extension file = + try + let dot_pos = String.rindex file '.' in + String.sub file dot_pos (String.length file - dot_pos) + with Not_found -> file + in + let f_dir = Filename.dirname f + and platform_ext = "." ^ (platform_name_macro ctx) + and is_core_api = defined ctx Define.CoreApi in let rec loop had_empty = function | [] when had_empty -> raise Not_found | [] -> loop true [""] | p :: l -> let file = p ^ f in - if Sys.file_exists file then begin - (try - let ext = String.rindex file '.' in - let file_pf = String.sub file 0 (ext + 1) ^ platform_name ctx.platform ^ String.sub file ext (String.length file - ext) in - if not (defined ctx Define.CoreApi) && Sys.file_exists file_pf then file_pf else file - with Not_found -> - file) - end else + let dir = Filename.dirname file in + if Hashtbl.mem ctx.readdir_cache (p,dir) then loop (had_empty || p = "") l + else begin + let found = ref "" in + let dir_listing = + try Some (Sys.readdir dir); + with Sys_error _ -> None + in + Hashtbl.add ctx.readdir_cache (p,dir) dir_listing; + let normalized_f = normalize_dir_separator f in + Option.may + (Array.iter (fun file_name -> + let current_f = if f_dir = "." then file_name else f_dir ^ "/" ^ file_name in + let pf,current_f = + if is_core_api then false,current_f + else begin + let ext = extension current_f in + let pf_ext = extension (remove_extension current_f) in + if platform_ext = pf_ext then + true,(remove_extension (remove_extension current_f)) ^ ext + else + false,current_f + end + in + let is_cached = Hashtbl.mem ctx.file_lookup_cache current_f in + if is_core_api || pf || not is_cached then begin + let full_path = if dir = "." then file_name else dir ^ "/" ^ file_name in + if is_cached then + Hashtbl.remove ctx.file_lookup_cache current_f; + Hashtbl.add ctx.file_lookup_cache current_f (Some full_path); + if normalize_dir_separator current_f = normalized_f then + found := full_path; + end + )) + dir_listing; + if !found <> "" then !found + else loop (had_empty || p = "") l + end in let r = (try Some (loop false ctx.class_path) with Not_found -> None) in Hashtbl.add ctx.file_lookup_cache f r; - (match r with + match r with | None -> raise Not_found - | Some f -> f) - -let rec mkdir_recursive base dir_list = - match dir_list with - | [] -> () - | dir :: remaining -> - let path = match base with - | "" -> dir - | "/" -> "/" ^ dir - | _ -> base ^ "/" ^ dir - in - let path_len = String.length path in - let path = - if path_len > 0 && (path.[path_len - 1] = '/' || path.[path_len - 1] == '\\') then - String.sub path 0 (path_len - 1) - else - path - in - if not ( (path = "") || ( (path_len = 2) && ((String.sub path 1 1) = ":") ) ) then - if not (Sys.file_exists path) then - Unix.mkdir path 0o755; - mkdir_recursive (if (path = "") then "/" else path) remaining - -let mkdir_from_path path = - let parts = Str.split_delim (Str.regexp "[\\/]+") path in - match parts with - | [] -> (* path was "" *) () - | _ -> - let dir_list = List.rev (List.tl (List.rev parts)) in - mkdir_recursive "" dir_list + | Some f -> f + +(* let find_file ctx f = + let timer = Timer.timer ["find_file"] in + Std.finally timer (find_file ctx) f *) let mem_size v = Objsize.size_with_headers (Objsize.objsize v [] []) -(* ------------------------- TIMERS ----------------------------- *) - -type timer_infos = { - id : string list; - mutable start : float list; - mutable total : float; - mutable calls : int; -} - -let get_time = Extc.time -let htimers = Hashtbl.create 0 - -let new_timer id = - let key = String.concat "." id in - try - let t = Hashtbl.find htimers key in - t.start <- get_time() :: t.start; - t.calls <- t.calls + 1; - t - with Not_found -> - let t = { id = id; start = [get_time()]; total = 0.; calls = 1; } in - Hashtbl.add htimers key t; - t - -let curtime = ref [] - -let close t = - let start = (match t.start with - | [] -> assert false - | s :: l -> t.start <- l; s - ) in - let now = get_time() in - let dt = now -. start in - t.total <- t.total +. dt; - let rec loop() = - match !curtime with - | [] -> failwith ("Timer " ^ (String.concat "." t.id) ^ " closed while not active") - | tt :: l -> curtime := l; if t != tt then loop() - in - loop(); - (* because of rounding errors while adding small times, we need to make sure that we don't have start > now *) - List.iter (fun ct -> ct.start <- List.map (fun t -> let s = t +. dt in if s > now then now else s) ct.start) !curtime - -let timer id = - let t = new_timer id in - curtime := t :: !curtime; - (function() -> close t) - -let rec close_times() = - match !curtime with - | [] -> () - | t :: _ -> close t; close_times() - -;; - -(* Taken from OCaml source typing/oprint.ml - - This is a better version of string_of_float which prints without loss of precision - so that float_of_string (float_repres x) = x for all floats x -*) -let valid_float_lexeme s = - let l = String.length s in - let rec loop i = - if i >= l then s ^ "." else - match s.[i] with - | '0' .. '9' | '-' -> loop (i+1) - | _ -> s - in loop 0 - -let float_repres f = - match classify_float f with - | FP_nan -> "nan" - | FP_infinite -> - if f < 0.0 then "neg_infinity" else "infinity" - | _ -> - let float_val = - let s1 = Printf.sprintf "%.12g" f in - if f = float_of_string s1 then s1 else - let s2 = Printf.sprintf "%.15g" f in - if f = float_of_string s2 then s2 else - Printf.sprintf "%.18g" f - in valid_float_lexeme float_val - let hash f = let h = ref 0 in for i = 0 to String.length f - 1 do @@ -943,9 +713,93 @@ let hash f = done; if Sys.word_size = 64 then Int32.to_int (Int32.shift_right (Int32.shift_left (Int32.of_int !h) 1) 1) else !h -let add_diagnostics_message com s p sev = +let url_encode s add_char = + let hex = "0123456789ABCDEF" in + for i = 0 to String.length s - 1 do + let c = String.unsafe_get s i in + match c with + | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' | '-' | '.' -> + add_char c + | _ -> + add_char '%'; + add_char (String.unsafe_get hex (int_of_char c lsr 4)); + add_char (String.unsafe_get hex (int_of_char c land 0xF)); + done + +let url_encode_s s = + let b = Buffer.create 0 in + url_encode s (Buffer.add_char b); + Buffer.contents b + +(* UTF8 *) + +let to_utf8 str p = + let u8 = try + UTF8.validate str; + str; + with + UTF8.Malformed_code -> + (* ISO to utf8 *) + let b = UTF8.Buf.create 0 in + String.iter (fun c -> UTF8.Buf.add_char b (UChar.of_char c)) str; + UTF8.Buf.contents b + in + let ccount = ref 0 in + UTF8.iter (fun c -> + let c = UChar.code c in + if (c >= 0xD800 && c <= 0xDFFF) || c >= 0x110000 then abort "Invalid unicode char" p; + incr ccount; + if c > 0x10000 then incr ccount; + ) u8; + u8, !ccount + +let utf16_add buf c = + let add c = + Buffer.add_char buf (char_of_int (c land 0xFF)); + Buffer.add_char buf (char_of_int (c lsr 8)); + in + if c >= 0 && c < 0x10000 then begin + if c >= 0xD800 && c <= 0xDFFF then failwith ("Invalid unicode char " ^ string_of_int c); + add c; + end else if c < 0x110000 then begin + let c = c - 0x10000 in + add ((c asr 10) + 0xD800); + add ((c land 1023) + 0xDC00); + end else + failwith ("Invalid unicode char " ^ string_of_int c) + +let utf8_to_utf16 str zt = + let b = Buffer.create (String.length str * 2) in + (try UTF8.iter (fun c -> utf16_add b (UChar.code c)) str with Invalid_argument _ | UChar.Out_of_range -> ()); (* if malformed *) + if zt then utf16_add b 0; + Buffer.contents b + +let utf16_to_utf8 str = + let b = Buffer.create 0 in + let add c = Buffer.add_char b (char_of_int (c land 0xFF)) in + let get i = int_of_char (String.unsafe_get str i) in + let rec loop i = + if i >= String.length str then () + else begin + let c = get i in + if c < 0x80 then begin + add c; + loop (i + 2); + end else if c < 0x800 then begin + let c = c lor ((get (i + 1)) lsl 8) in + add c; + add (c lsr 8); + loop (i + 2); + end else + assert false; + end + in + loop 0; + Buffer.contents b + +let add_diagnostics_message com s p kind sev = let di = com.shared.shared_display_information in - di.diagnostics_messages <- (s,p,sev) :: di.diagnostics_messages + di.diagnostics_messages <- (s,p,kind,sev) :: di.diagnostics_messages open Printer @@ -958,32 +812,4 @@ let dump_context com = s_record_fields "" [ "class_path",s_list ", " (fun s -> s) com.class_path; "defines",s_pmap (fun s -> s) (fun s -> s) com.defines.values; "defines_signature",s_opt (fun s -> Digest.to_hex s) com.defines.defines_signature; -] - -let parse_float s = - let rec loop sp i = - if i = String.length s then (if sp = 0 then s else String.sub s sp (i - sp)) else - match String.unsafe_get s i with - | ' ' when sp = i -> loop (sp + 1) (i + 1) - | '0'..'9' | '-' | '+' | 'e' | 'E' | '.' -> loop sp (i + 1) - | _ -> String.sub s sp (i - sp) - in - float_of_string (loop 0 0) - -let parse_int s = - let rec loop_hex i = - if i = String.length s then s else - match String.unsafe_get s i with - | '0'..'9' | 'a'..'f' | 'A'..'F' -> loop_hex (i + 1) - | _ -> String.sub s 0 i - in - let rec loop sp i = - if i = String.length s then (if sp = 0 then s else String.sub s sp (i - sp)) else - match String.unsafe_get s i with - | '0'..'9' -> loop sp (i + 1) - | ' ' when sp = i -> loop (sp + 1) (i + 1) - | '-' when i = 0 -> loop sp (i + 1) - | ('x' | 'X') when i = 1 && String.get s 0 = '0' -> loop_hex (i + 1) - | _ -> String.sub s sp (i - sp) - in - Int32.of_string (loop 0 0) \ No newline at end of file +] \ No newline at end of file diff --git a/src/context/compilationServer.ml b/src/context/compilationServer.ml new file mode 100644 index 00000000000..012c26a5eb0 --- /dev/null +++ b/src/context/compilationServer.ml @@ -0,0 +1,297 @@ +open Globals +open Ast +open Json +open Type +open Common + +type cached_file = { + c_time : float; + c_package : string list; + c_decls : type_decl list; + mutable c_module_name : string option; +} + +type cached_directory = { + c_path : string; + mutable c_mtime : float; +} + +type cached_native_lib = { + c_nl_mtime : float; + c_nl_files : (path,Ast.package) Hashtbl.t; +} + +type cache = { + c_haxelib : (string list, string list) Hashtbl.t; + c_files : ((string * string), cached_file) Hashtbl.t; + c_modules : (path * string, module_def) Hashtbl.t; + c_directories : (string, cached_directory list) Hashtbl.t; + c_removed_files : (string * string,unit) Hashtbl.t; + c_native_libs : (string,cached_native_lib) Hashtbl.t; +} + +type context_sign = { + cs_json : Json.t; + cs_index : int; +} + +type t = { + cache : cache; + mutable signs : (string * context_sign) list; + mutable initialized : bool; +} + +type context_options = + | NormalContext + | MacroContext + | NormalAndMacroContext + +let instance : t option ref = ref None + +let create_cache () = { + c_haxelib = Hashtbl.create 0; + c_files = Hashtbl.create 0; + c_modules = Hashtbl.create 0; + c_directories = Hashtbl.create 0; + c_removed_files = Hashtbl.create 0; + c_native_libs = Hashtbl.create 0; +} + +let create () = + let cs = { + cache = create_cache(); + signs = []; + initialized = false; + } in + instance := Some cs; + cs + +let get () = + !instance + +let runs () = + !instance <> None + +let force () = match !instance with None -> assert false | Some i -> i + +let is_initialized cs = + cs.initialized = true + +let set_initialized cs = + cs.initialized <- true + +let get_context_files cs signs = + Hashtbl.fold (fun (file,sign) cfile acc -> + if (List.mem sign signs) then (file,cfile) :: acc + else acc + ) cs.cache.c_files [] + +(* signatures *) + +let get_sign cs sign = + List.assoc sign cs.signs + +let has_sign cs sign = + List.mem_assoc sign cs.signs + +let add_sign cs sign desc com = + let i = List.length cs.signs in + let jo = JObject [ + "index",JInt i; + "desc",JString desc; + "platform",JString (platform_name com.platform); + "classPaths",JArray (List.map (fun s -> JString s) com.class_path); + "signature",JString (Digest.to_hex sign); + "defines",JArray (PMap.foldi (fun k v acc -> JObject [ + "key",JString k; + "value",JString v; + ] :: acc) com.defines.values []); + ] in + cs.signs <- (sign,{cs_json = jo;cs_index = i}) :: cs.signs; + i + +let maybe_add_context_sign cs com desc = + let sign = Define.get_signature com.defines in + if not (has_sign cs sign) then ignore (add_sign cs sign desc com) + +let get_signs cs = + cs.signs + +(* modules *) + +let find_module cs key = + Hashtbl.find cs.cache.c_modules key + +let cache_module cs key value = + Hashtbl.replace cs.cache.c_modules key value + +let taint_modules cs file = + Hashtbl.iter (fun _ m -> if m.m_extra.m_file = file then m.m_extra.m_dirty <- Some m) cs.cache.c_modules + +let filter_modules cs file = + let removed = DynArray.create () in + (* TODO: Using filter_map_inplace would be better, but we can't move to OCaml 4.03 yet *) + Hashtbl.iter (fun k m -> + if m.m_extra.m_file = file then DynArray.add removed (k,m); + ) cs.cache.c_modules; + DynArray.iter (fun (k,_) -> Hashtbl.remove cs.cache.c_modules k) removed; + DynArray.to_list removed + +let iter_modules cs com f = + let sign = Define.get_signature com.defines in + Hashtbl.iter (fun (_,sign') m -> if sign = sign' then f m) cs.cache.c_modules + +let is_cached_module cs com path = + let sign = Define.get_signature com.defines in + Hashtbl.mem cs.cache.c_modules (path,sign) + +(* files *) + +let find_file cs key = + Hashtbl.find cs.cache.c_files key + +let cache_file cs key time data = + Hashtbl.replace cs.cache.c_files key { c_time = time; c_package = fst data; c_decls = snd data; c_module_name = None } + +let remove_file cs key = + if Hashtbl.mem cs.cache.c_files key then begin + Hashtbl.remove cs.cache.c_files key; + Hashtbl.replace cs.cache.c_removed_files key () + end + +(* Like remove_file, but doesn't keep track of the file *) +let remove_file_for_real cs key = + Hashtbl.remove cs.cache.c_files key + +let remove_files cs file = + List.iter (fun (sign,_) -> remove_file cs (file,sign)) cs.signs + +let iter_files cs com f = + let sign = Define.get_signature com.defines in + Hashtbl.iter (fun (file,sign') decls -> if sign = sign' then f file decls) cs.cache.c_files + +let get_file_list cs com = + let sign = Define.get_signature com.defines in + Hashtbl.fold (fun (file,sign') decls acc -> if sign = sign' then (file,decls) :: acc else acc) cs.cache.c_files [] + +let get_module_name_of_cfile file cfile = match cfile.c_module_name with + | None -> + let name = Path.module_name_of_file file in + cfile.c_module_name <- Some name; + name + | Some name -> + name + +let get_files cs = + cs.cache.c_files + +(* haxelibs *) + +let find_haxelib cs key = + Hashtbl.find cs.cache.c_haxelib key + +let cache_haxelib cs key value = + Hashtbl.replace cs.cache.c_haxelib key value + +(* directories *) + +let create_directory path mtime = { + c_path = path; + c_mtime = mtime; +} + +let find_directories cs key = + Hashtbl.find cs.cache.c_directories key + +let add_directories cs key value = + Hashtbl.replace cs.cache.c_directories key value + +let remove_directory cs key value = + try + let current = find_directories cs key in + Hashtbl.replace cs.cache.c_directories key (List.filter (fun dir -> dir.c_path <> value) current); + with Not_found -> + () + +let has_directory cs key value = + try + List.exists (fun dir -> dir.c_path = value) (find_directories cs key) + with Not_found -> + false + +let add_directory cs key value = + try + let current = find_directories cs key in + add_directories cs key (value :: current) + with Not_found -> + add_directories cs key [value] + +let clear_directories cs key = + Hashtbl.remove cs.cache.c_directories key + +(* native lib *) + +let add_native_lib cs key files timestamp = + Hashtbl.replace cs.cache.c_native_libs key { c_nl_files = files; c_nl_mtime = timestamp } + +let get_native_lib cs key = + try Some (Hashtbl.find cs.cache.c_native_libs key) + with Not_found -> None + +let handle_native_lib com lib = + com.native_libs.all_libs <- lib#get_file_path :: com.native_libs.all_libs; + com.load_extern_type <- com.load_extern_type @ [lib#get_file_path,lib#build]; + match get() with + | Some cs when Define.raw_defined com.defines "haxe.cacheNativeLibs" -> + let init () = + let file = lib#get_file_path in + let key = file in + let ftime = file_time file in + begin match get_native_lib cs key with + | Some lib when ftime <= lib.c_nl_mtime -> + (* Cached lib is good, set up lookup into cached files. *) + lib.c_nl_files; + | _ -> + (* Cached lib is outdated or doesn't exist yet, read library. *) + lib#load; + (* Created lookup and eagerly read each known type. *) + let h = Hashtbl.create 0 in + List.iter (fun path -> + if not (Hashtbl.mem h path) then begin + let p = { pfile = file ^ " @ " ^ Globals.s_type_path path; pmin = 0; pmax = 0; } in + try begin match lib#build path p with + | Some r -> Hashtbl.add h path r + | None -> () + end with _ -> + () + end + ) lib#list_modules; + (* Save and set up lookup. *) + add_native_lib cs key h ftime; + h; + end; + in + (fun () -> + let lut = init() in + let build path p = + try Some (Hashtbl.find lut path) + with Not_found -> None + in + com.load_extern_type <- List.map (fun (name,f) -> + name,if name = lib#get_file_path then build else f + ) com.load_extern_type + ) + | _ -> + (* Offline mode, just read library as usual. *) + (fun () -> lib#load) + +(* context *) + +let rec cache_context cs com = + let cache_module m = + cache_module cs (m.m_path,m.m_extra.m_sign) m; + in + List.iter cache_module com.modules; + match com.get_macros() with + | None -> () + | Some com -> cache_context cs com \ No newline at end of file diff --git a/src/context/display.ml b/src/context/display.ml deleted file mode 100644 index f61d0bcd2fe..00000000000 --- a/src/context/display.ml +++ /dev/null @@ -1,935 +0,0 @@ -open Ast -open Common -open Common.DisplayMode -open Type -open Typecore -open Globals - -type display_field_kind = - | FKVar of t - | FKMethod of t - | FKType of t - | FKModule - | FKPackage - | FKMetadata - | FKTimer of string - -let display_field_kind_index = function - | FKVar _ -> 0 - | FKMethod _ -> 1 - | FKType _ -> 2 - | FKModule -> 3 - | FKPackage -> 4 - | FKMetadata -> 5 - | FKTimer _ -> 6 - -exception Diagnostics of string -exception Statistics of string -exception ModuleSymbols of string -exception Metadata of string -exception DisplaySignatures of (tsignature * documentation) list * int -exception DisplayType of t * pos * string option -exception DisplayPosition of pos list -exception DisplayFields of (string * display_field_kind * documentation) list -exception DisplayToplevel of IdentifierType.t list -exception DisplayPackage of string list - -let is_display_file file = - file <> "?" && Path.unique_full_path file = (!Parser.resume_display).pfile - -let encloses_position p_target p = - p.pmin <= p_target.pmin && p.pmax >= p_target.pmax - -let is_display_position p = - encloses_position !Parser.resume_display p - -module ExprPreprocessing = struct - let find_enclosing com e = - let display_pos = ref (!Parser.resume_display) in - let mk_null p = (EDisplay(((EConst(Ident "null")),p),false),p) in - let encloses_display_pos p = - if encloses_position !display_pos p then begin - let p = !display_pos in - display_pos := { pfile = ""; pmin = -2; pmax = -2 }; - Some p - end else - None - in - let rec loop e = match fst e with - | EBlock el -> - let p = pos e in - (* We want to find the innermost block which contains the display position. *) - let el = List.map loop el in - let el = match encloses_display_pos p with - | None -> - el - | Some p2 -> - let b,el = List.fold_left (fun (b,el) e -> - let p = pos e in - if b || p.pmax <= p2.pmin then begin - (b,e :: el) - end else begin - let e_d = (EDisplay(mk_null p,false)),p in - (true,e :: e_d :: el) - end - ) (false,[]) el in - let el = if b then - el - else begin - mk_null p :: el - end in - List.rev el - in - (EBlock el),(pos e) - | _ -> - Ast.map_expr loop e - in - loop e - - let find_before_pos com e = - let display_pos = ref (!Parser.resume_display) in - let is_annotated p = - if p.pmin <= !display_pos.pmin && p.pmax >= !display_pos.pmax then begin - display_pos := { pfile = ""; pmin = -2; pmax = -2 }; - true - end else - false - in - let loop e = - if is_annotated (pos e) then - (EDisplay(e,false),(pos e)) - else - e - in - let rec map e = - loop (Ast.map_expr map e) - in - map e - - let find_display_call e = - let found = ref false in - let loop e = if !found then e else match fst e with - | ECall _ | ENew _ when is_display_position (pos e) -> - found := true; - (EDisplay(e,true),(pos e)) - | _ -> - e - in - let rec map e = match fst e with - | EDisplay(_,true) -> - found := true; - e - | EDisplay(e1,false) -> map e1 - | _ -> loop (Ast.map_expr map e) - in - map e - - - let process_expr com e = match com.display.dms_kind with - | DMToplevel -> find_enclosing com e - | DMPosition | DMUsage _ | DMType -> find_before_pos com e - | DMSignature -> find_display_call e - | _ -> e -end - -module DisplayEmitter = struct - let display_module_type dm mt p = match dm.dms_kind with - | DMPosition -> raise (DisplayPosition [(t_infos mt).mt_pos]); - | DMUsage _ -> - let ti = t_infos mt in - ti.mt_meta <- (Meta.Usage,[],ti.mt_pos) :: ti.mt_meta - | DMType -> raise (DisplayType (type_of_module_type mt,p,None)) - | _ -> () - - let rec display_type dm t p = match dm.dms_kind with - | DMType -> raise (DisplayType (t,p,None)) - | _ -> - try display_module_type dm (module_type_of_type t) p - with Exit -> match follow t,follow !t_dynamic_def with - | _,TDynamic _ -> () (* sanity check in case it's still t_dynamic *) - | TDynamic _,_ -> display_type dm !t_dynamic_def p - | _ -> () - - let check_display_type ctx t p = - let add_type_hint () = - Hashtbl.replace ctx.com.shared.shared_display_information.type_hints p t; - in - let maybe_display_type () = - if ctx.is_display_file && is_display_position p then - display_type ctx.com.display t p - in - match ctx.com.display.dms_kind with - | DMStatistics -> add_type_hint() - | DMUsage _ -> add_type_hint(); maybe_display_type() - | _ -> maybe_display_type() - - let display_variable dm v p = match dm.dms_kind with - | DMPosition -> raise (DisplayPosition [v.v_pos]) - | DMUsage _ -> v.v_meta <- (Meta.Usage,[],v.v_pos) :: v.v_meta; - | DMType -> raise (DisplayType (v.v_type,p,None)) - | _ -> () - - let display_field dm cf p = match dm.dms_kind with - | DMPosition -> raise (DisplayPosition [cf.cf_pos]); - | DMUsage _ -> cf.cf_meta <- (Meta.Usage,[],cf.cf_pos) :: cf.cf_meta; - | DMType -> raise (DisplayType (cf.cf_type,p,cf.cf_doc)) - | _ -> () - - let maybe_display_field ctx p cf = - if is_display_position p then display_field ctx.com.display cf p - - let display_enum_field dm ef p = match dm.dms_kind with - | DMPosition -> raise (DisplayPosition [p]); - | DMUsage _ -> ef.ef_meta <- (Meta.Usage,[],p) :: ef.ef_meta; - | DMType -> raise (DisplayType (ef.ef_type,p,ef.ef_doc)) - | _ -> () - - let display_meta dm meta = match dm.dms_kind with - | DMType -> - begin match meta with - | Meta.Custom _ | Meta.Dollar _ -> () - | _ -> match Meta.get_documentation meta with - | None -> () - | Some (_,s) -> - (* TODO: hack until we support proper output for hover display mode *) - raise (Metadata ("" ^ s ^ "")); - end - | DMField -> - let all,_ = Meta.get_documentation_list() in - let all = List.map (fun (s,doc) -> (s,FKMetadata,Some doc)) all in - raise (DisplayFields all) - | _ -> - () - - let check_display_metadata ctx meta = - List.iter (fun (meta,args,p) -> - if is_display_position p then display_meta ctx.com.display meta; - List.iter (fun e -> - if is_display_position (pos e) then begin - let e = ExprPreprocessing.process_expr ctx.com e in - delay ctx PTypeField (fun _ -> ignore(type_expr ctx e Value)); - end - ) args - ) meta -end - -module DocumentSymbols = struct - open DisplayTypes.SymbolKind - - let collect_module_symbols (pack,decls) = - let l = DynArray.create() in - let add name kind location parent = - let si = DisplayTypes.SymbolInformation.make name kind location (if parent = "" then None else Some parent) in - DynArray.add l si; - in - let rec expr parent (e,p) = - let add name kind location = add name kind location parent in - begin match e with - | EVars vl -> - List.iter (fun ((s,p),_,eo) -> - add s Variable p; - expr_opt parent eo - ) vl - | ETry(e1,catches) -> - expr parent e1; - List.iter (fun ((s,p),_,e,_) -> - add s Variable p; - expr parent e - ) catches; - | EFunction(Some s,f) -> - add s Function p; - func parent f - | EBinop(OpIn,(EConst(Ident s),p),e2) -> - add s Variable p; - expr parent e2; - | _ -> - iter_expr (expr parent) (e,p) - end - and expr_opt parent eo = match eo with - | None -> () - | Some e -> expr parent e - and func parent f = - List.iter (fun ((s,p),_,_,_,eo) -> - add s Variable p parent; - expr_opt parent eo - ) f.f_args; - expr_opt parent f.f_expr - in - let field parent cff = - let field_parent = parent ^ "." ^ (fst cff.cff_name) in - match cff.cff_kind with - | FVar(_,eo) -> - add (fst cff.cff_name) Field cff.cff_pos parent; - expr_opt field_parent eo - | FFun f -> - add (fst cff.cff_name) (if fst cff.cff_name = "new" then Constructor else Method) cff.cff_pos parent; - func field_parent f - | FProp(_,_,_,eo) -> - add (fst cff.cff_name) Property cff.cff_pos parent; - expr_opt field_parent eo - in - List.iter (fun (td,p) -> match td with - | EImport _ | EUsing _ -> - () (* TODO: Can we do anything with these? *) - | EClass d -> - add (fst d.d_name) (if List.mem HInterface d.d_flags then Interface else Class) p ""; - List.iter (field (fst d.d_name)) d.d_data - | EEnum d -> - add (fst d.d_name) Enum p ""; - List.iter (fun ef -> - add (fst ef.ec_name) Method ef.ec_pos (fst d.d_name) - ) d.d_data - | ETypedef d -> - add (fst d.d_name) Typedef p ""; - (match d.d_data with - | CTAnonymous fields,_ -> - List.iter (field (fst d.d_name)) fields - | _ -> ()) - | EAbstract d -> - add (fst d.d_name) Abstract p ""; - List.iter (field (fst d.d_name)) d.d_data - ) decls; - l -end - -module DeprecationCheck = struct - - let curclass = ref null_class - - let warned_positions = Hashtbl.create 0 - - let print_deprecation_message com meta s p_usage = - let s = match meta with - | _,[EConst(String s),_],_ -> s - | _ -> Printf.sprintf "Usage of this %s is deprecated" s - in - if not (Hashtbl.mem warned_positions p_usage) then begin - Hashtbl.replace warned_positions p_usage true; - com.warning s p_usage; - end - - let check_meta com meta s p_usage = - try - print_deprecation_message com (Meta.get Meta.Deprecated meta) s p_usage; - with Not_found -> - () - - let check_cf com cf p = check_meta com cf.cf_meta "field" p - - let check_class com c p = if c != !curclass then check_meta com c.cl_meta "class" p - - let check_enum com en p = check_meta com en.e_meta "enum" p - - let check_ef com ef p = check_meta com ef.ef_meta "enum field" p - - let check_typedef com t p = check_meta com t.t_meta "typedef" p - - let check_module_type com mt p = match mt with - | TClassDecl c -> check_class com c p - | TEnumDecl en -> check_enum com en p - | _ -> () - - let run_on_expr com e = - let rec expr e = match e.eexpr with - | TField(e1,fa) -> - expr e1; - begin match fa with - | FStatic(c,cf) | FInstance(c,_,cf) -> - check_class com c e.epos; - check_cf com cf e.epos - | FAnon cf -> - check_cf com cf e.epos - | FClosure(co,cf) -> - (match co with None -> () | Some (c,_) -> check_class com c e.epos); - check_cf com cf e.epos - | FEnum(en,ef) -> - check_enum com en e.epos; - check_ef com ef e.epos; - | _ -> - () - end - | TNew(c,_,el) -> - List.iter expr el; - check_class com c e.epos; - (match c.cl_constructor with None -> () | Some cf -> check_cf com cf e.epos) - | TTypeExpr(mt) | TCast(_,Some mt) -> - check_module_type com mt e.epos - | TMeta((Meta.Deprecated,_,_) as meta,e1) -> - print_deprecation_message com meta "field" e1.epos; - expr e1; - | _ -> - Type.iter expr e - in - expr e - - let run_on_field com cf = match cf.cf_expr with None -> () | Some e -> run_on_expr com e - - let run com = - List.iter (fun t -> match t with - | TClassDecl c -> - curclass := c; - (match c.cl_constructor with None -> () | Some cf -> run_on_field com cf); - (match c.cl_init with None -> () | Some e -> run_on_expr com e); - List.iter (run_on_field com) c.cl_ordered_statics; - List.iter (run_on_field com) c.cl_ordered_fields; - | _ -> - () - ) com.types -end - -module Diagnostics = struct - module DiagnosticsKind = struct - type t = - | DKUnusedImport - | DKUnresolvedIdentifier - | DKCompilerError - | DKRemovableCode - - let to_int = function - | DKUnusedImport -> 0 - | DKUnresolvedIdentifier -> 1 - | DKCompilerError -> 2 - | DKRemovableCode -> 3 - end - - open DiagnosticsKind - open DisplayTypes - - let add_removable_code com s p prange = - let di = com.shared.shared_display_information in - di.removable_code <- (s,p,prange) :: di.removable_code - - let find_unused_variables com e = - let vars = Hashtbl.create 0 in - let pmin_map = Hashtbl.create 0 in - let rec loop e = match e.eexpr with - | TVar(v,eo) when Meta.has Meta.UserVariable v.v_meta -> - Hashtbl.add pmin_map e.epos.pmin v; - let p = match eo with - | None -> e.epos - | Some e1 -> - loop e1; - { e.epos with pmax = e1.epos.pmin } - in - Hashtbl.replace vars v.v_id (v,p); - | TLocal v when Meta.has Meta.UserVariable v.v_meta -> - Hashtbl.remove vars v.v_id; - | _ -> - Type.iter loop e - in - loop e; - Hashtbl.iter (fun _ (v,p) -> - let p = match (Hashtbl.find_all pmin_map p.pmin) with [_] -> p | _ -> null_pos in - add_removable_code com "Unused variable" v.v_pos p - ) vars - - let check_other_things com e = - let had_effect = ref false in - let no_effect p = - add_diagnostics_message com "This code has no effect" p DiagnosticsSeverity.Warning; - in - let pointless_compound s p = - add_diagnostics_message com (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p DiagnosticsSeverity.Warning; - in - let rec compound s el p = - let old = !had_effect in - had_effect := false; - List.iter (loop true) el; - if not !had_effect then no_effect p else pointless_compound s p; - had_effect := old; - and loop in_value e = match e.eexpr with - | TBlock el -> - let rec loop2 el = match el with - | [] -> () - | [e] -> loop in_value e - | e :: el -> loop false e; loop2 el - in - loop2 el - | TMeta((Meta.Extern,_,_),_) -> - (* This is so something like `[inlineFunc()]` is not reported. *) - had_effect := true; - | TLocal v when not (Meta.has Meta.UserVariable v.v_meta) -> - () - | TConst _ | TLocal _ | TTypeExpr _ | TFunction _ | TIdent _ when not in_value -> - no_effect e.epos; - | TConst _ | TLocal _ | TTypeExpr _ | TEnumParameter _ | TEnumIndex _ | TVar _ | TIdent _ -> - () - | TFunction tf -> - loop false tf.tf_expr - | TNew _ | TCall _ | TBinop ((Ast.OpAssignOp _ | Ast.OpAssign),_,_) | TUnop ((Ast.Increment | Ast.Decrement),_,_) - | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) - | TIf _ | TTry _ | TSwitch _ | TWhile _ | TFor _ -> - had_effect := true; - Type.iter (loop true) e - | TParenthesis e1 | TMeta(_,e1) -> - loop in_value e1 - | TArray _ | TCast (_,None) | TBinop _ | TUnop _ - | TField _ | TArrayDecl _ | TObjectDecl _ when in_value -> - Type.iter (loop true) e; - | TArray(e1,e2) -> compound "array access" [e1;e2] e.epos - | TCast(e1,None) -> compound "cast" [e1] e.epos - | TBinop(op,e1,e2) -> compound (Printf.sprintf "'%s' operator" (s_binop op)) [e1;e2] e.epos - | TUnop(op,_,e1) -> compound (Printf.sprintf "'%s' operator" (s_unop op)) [e1] e.epos - | TField(e1,_) -> compound "field access" [e1] e.epos - | TArrayDecl el -> compound "array declaration" el e.epos - | TObjectDecl fl -> compound "object declaration" (List.map snd fl) e.epos - in - loop true e - - let prepare_field com cf = match cf.cf_expr with - | None -> () - | Some e -> - find_unused_variables com e; - check_other_things com e; - DeprecationCheck.run_on_expr com e - - let prepare com global = - List.iter (function - | TClassDecl c when global || is_display_file c.cl_pos.pfile -> - List.iter (prepare_field com) c.cl_ordered_fields; - List.iter (prepare_field com) c.cl_ordered_statics; - (match c.cl_constructor with None -> () | Some cf -> prepare_field com cf); - | _ -> - () - ) com.types - - let is_diagnostics_run ctx = match ctx.com.display.dms_kind with - | DMDiagnostics true -> true - | DMDiagnostics false -> ctx.is_display_file - | _ -> false - - let secure_generated_code ctx e = - if is_diagnostics_run ctx then mk (TMeta((Meta.Extern,[],e.epos),e)) e.etype e.epos else e -end - -module ImportHandling = struct - type import_display_kind = - | IDKPackage of string list - | IDKModule of string list * string - | IDKSubType of string list * string * string - | IDKModuleField of string list * string * string - | IDKSubTypeField of string list * string * string * string - | IDK - - type import_display = import_display_kind * pos - - let convert_import_to_something_usable pt path = - let rec loop pack m t = function - | (s,p) :: l -> - let is_lower = is_lower_ident s in - let is_display_pos = encloses_position pt p in - begin match is_lower,m,t with - | _,None,Some _ -> - assert false (* impossible, I think *) - | true,Some m,None -> - if is_display_pos then (IDKModuleField(List.rev pack,m,s),p) - else (IDK,p) (* assume that we're done *) - | _,Some m,Some t -> - if is_display_pos then (IDKSubTypeField(List.rev pack,m,t,s),p) - else (IDK,p) - | true,None,None -> - if is_display_pos then (IDKPackage (List.rev (s :: pack)),p) - else loop (s :: pack) m t l - | false,Some sm,None -> - if is_display_pos then (IDKSubType (List.rev pack,sm,s),p) - else loop pack m (Some s) l - | false,None,None -> - if is_display_pos then (IDKModule (List.rev pack,s),p) - else loop pack (Some s) None l - end - | [] -> - (IDK,null_pos) - in - loop [] None None path - - let add_import_position com p path = - com.shared.shared_display_information.import_positions <- PMap.add p (ref false,path) com.shared.shared_display_information.import_positions - - let mark_import_position com p = - try - let r = fst (PMap.find p com.shared.shared_display_information.import_positions) in - r := true - with Not_found -> - () - - let maybe_mark_import_position ctx p = - if Diagnostics.is_diagnostics_run ctx then mark_import_position ctx.com p -end - -module Statistics = struct - open ImportHandling - - type relation = - | Implemented - | Extended - | Overridden - | Referenced - - type symbol = - | SKClass of tclass - | SKInterface of tclass - | SKEnum of tenum - | SKField of tclass_field - | SKEnumField of tenum_field - | SKVariable of tvar - - let is_usage_symbol symbol = - let meta = match symbol with - | SKClass c | SKInterface c -> c.cl_meta - | SKEnum en -> en.e_meta - | SKField cf -> cf.cf_meta - | SKEnumField ef -> ef.ef_meta - | SKVariable v -> v.v_meta - in - Meta.has Meta.Usage meta - - let collect_statistics ctx = - let relations = Hashtbl.create 0 in - let symbols = Hashtbl.create 0 in - let add_relation pos r = - if is_display_file pos.pfile then try - Hashtbl.replace relations pos (r :: Hashtbl.find relations pos) - with Not_found -> - Hashtbl.add relations pos [r] - in - let declare kind p = - if is_display_file p.pfile then begin - if not (Hashtbl.mem relations p) then Hashtbl.add relations p []; - Hashtbl.replace symbols p kind; - end - in - let collect_overrides c = - List.iter (fun cf -> - let rec loop c = match c.cl_super with - | Some (c,_) -> - begin try - let cf' = PMap.find cf.cf_name c.cl_fields in - add_relation cf'.cf_name_pos (Overridden,cf.cf_pos) - with Not_found -> - loop c - end - | _ -> - () - in - loop c - ) c.cl_overrides - in - let rec find_real_constructor c = match c.cl_constructor,c.cl_super with - (* The pos comparison might be a bit weak, not sure... *) - | Some cf,_ when not (Meta.has Meta.CompilerGenerated cf.cf_meta) && c.cl_pos <> cf.cf_pos -> cf - | _,Some(c,_) -> find_real_constructor c - | _,None -> raise Not_found - in - let var_decl v = declare (SKVariable v) v.v_pos in - let patch_string_pos p s = { p with pmin = p.pmax - String.length s } in - let patch_string_pos_front p s = { p with pmax = p.pmin + String.length s } in - let field_reference cf p = - add_relation cf.cf_name_pos (Referenced,patch_string_pos p cf.cf_name) - in - let collect_references c e = - let rec loop e = match e.eexpr with - | TField(e1,fa) -> - (* Check if the sub-expression is actually shorter than the whole one. This should - detect cases where it was automatically generated. *) - if e1.epos.pmin = e.epos.pmin && e1.epos.pmax <> e.epos.pmax then - loop e1; - begin match fa with - | FStatic(_,cf) | FInstance(_,_,cf) | FClosure(_,cf) -> - field_reference cf e.epos - | FAnon cf -> - declare (SKField cf) cf.cf_name_pos; - field_reference cf e.epos - | FEnum(_,ef) -> - add_relation ef.ef_name_pos (Referenced,patch_string_pos e.epos ef.ef_name) - | FDynamic _ -> - () - end - | TTypeExpr mt -> - let tinfos = t_infos mt in - add_relation tinfos.mt_name_pos (Referenced,patch_string_pos e.epos (snd tinfos.mt_path)) - | TNew(c,_,el) -> - List.iter loop el; - (try add_relation (find_real_constructor c).cf_name_pos (Referenced,e.epos) with Not_found -> ()); - | TCall({eexpr = TConst TSuper},el) -> - List.iter loop el; - begin match c.cl_super with - | Some(c,_) -> (try add_relation (find_real_constructor c).cf_name_pos (Referenced,e.epos) with Not_found -> ()) - | None -> () - end - | TVar(v,eo) -> - Option.may loop eo; - var_decl v; - | TFor(v,e1,e2) -> - var_decl v; - loop e1; - loop e2; - | TFunction tf -> - List.iter (fun (v,_) -> var_decl v) tf.tf_args; - loop tf.tf_expr; - | TLocal v when e.epos.pmax - e.epos.pmin = String.length v.v_name -> - add_relation v.v_pos (Referenced,e.epos) - | _ -> - Type.iter loop e - in - loop e - in - List.iter (function - | TClassDecl c -> - declare (if c.cl_interface then (SKInterface c) else (SKClass c)) c.cl_name_pos; - List.iter (fun (c',_) -> add_relation c'.cl_name_pos ((if c.cl_interface then Extended else Implemented),c.cl_name_pos)) c.cl_implements; - begin match c.cl_super with - | None -> () - | Some (c',_) -> add_relation c'.cl_name_pos (Extended,c.cl_name_pos); - end; - collect_overrides c; - let field cf = - if cf.cf_pos.pmin > c.cl_name_pos.pmin then declare (SKField cf) cf.cf_name_pos; - let _ = follow cf.cf_type in - match cf.cf_expr with None -> () | Some e -> collect_references c e - in - Option.may field c.cl_constructor; - List.iter field c.cl_ordered_fields; - List.iter field c.cl_ordered_statics; - | TEnumDecl en -> - declare (SKEnum en) en.e_name_pos; - PMap.iter (fun _ ef -> declare (SKEnumField ef) ef.ef_name_pos) en.e_constrs - | _ -> - () - ) ctx.com.types; - let explore_type_hint p t = match follow t with - | TInst(c,_) -> add_relation c.cl_name_pos (Referenced,(patch_string_pos_front p (snd c.cl_path))) - | _ -> () - in - Hashtbl.iter (fun p t -> - explore_type_hint p t - ) ctx.com.shared.shared_display_information.type_hints; - let l = List.fold_left (fun acc (_,cfi,_,cfo) -> match cfo with - | Some cf -> if List.mem_assoc cf.cf_name_pos acc then acc else (cf.cf_name_pos,cfi.cf_name_pos) :: acc - | None -> acc - ) [] ctx.com.display_information.interface_field_implementations in - List.iter (fun (p,p') -> add_relation p' (Implemented,p)) l; - let deal_with_imports paths = - let check_subtype m s p = - try - let mt = List.find (fun mt -> snd (t_infos mt).mt_path = s) m.m_types in - add_relation (t_infos mt).mt_name_pos (Referenced,p); - Some mt - with Not_found -> - None - in - let check_module path p = - let m = ctx.g.do_load_module ctx path p in - m - in - let check_field c s p = - let cf = PMap.find s c.cl_statics in - add_relation cf.cf_name_pos (Referenced,p) - in - let check_subtype_field m ssub psub sfield pfield = match check_subtype m ssub psub with - | Some (TClassDecl c) -> check_field c sfield pfield - | _ -> () - in - PMap.iter (fun p (_,path) -> - match ImportHandling.convert_import_to_something_usable { p with pmin = p.pmax - 1; pmax = p.pmax - 1 } path,List.rev path with - | (IDKSubType(sl,s1,s2),_),(_,psubtype) :: (_,pmodule) :: _ -> - let m = check_module (sl,s1) pmodule in - (*ignore(check_subtype m s1 pmodule);*) - ignore(check_subtype m s2 psubtype) - | (IDKModuleField(sl,s1,s2),_),(_,pfield) :: (_,pmodule) :: _ -> - let m = check_module (sl,s1) pmodule in - check_subtype_field m s1 pmodule s2 pfield - | (IDKSubTypeField(sl,s1,s2,s3),_),(_,pfield) :: (_,psubtype) :: (_,pmodule) :: _ -> - let m = check_module (sl,s1) pmodule in - check_subtype_field m s2 psubtype s3 pfield - | (IDKModule(sl,s),_),(_,pmodule) :: _ -> - let m = check_module (sl,s) pmodule in - ignore(check_subtype m s pmodule); - | _ -> - () - ) paths - in - if false then deal_with_imports ctx.com.shared.shared_display_information.import_positions; - symbols,relations -end - -let explore_class_paths ctx class_paths recusive f_pack f_module f_type = - let rec loop dir pack = - try - let entries = Sys.readdir dir in - Array.iter (fun file -> - match file with - | "." | ".." -> - () - | _ when Sys.is_directory (dir ^ file) && file.[0] >= 'a' && file.[0] <= 'z' -> - f_pack file; - if recusive then loop (dir ^ file ^ "/") (file :: pack) - | _ -> - let l = String.length file in - if l > 3 && String.sub file (l - 3) 3 = ".hx" then begin - try - let name = String.sub file 0 (l - 3) in - let path = (List.rev pack,name) in - let md = ctx.g.do_load_module ctx path null_pos in - f_module md; - List.iter (fun mt -> f_type mt) md.m_types - with _ -> - () - end - ) entries; - with Sys_error _ -> - () - in - List.iter (fun dir -> loop dir []) class_paths - -module ToplevelCollector = struct - open IdentifierType - - let run ctx only_types = - let acc = DynArray.create () in - let add x = DynArray.add acc x in - - if not only_types then begin - (* locals *) - PMap.iter (fun _ v -> - if not (is_gen_local v) then - add (ITLocal v) - ) ctx.locals; - - (* member vars *) - if ctx.curfun <> FunStatic then begin - let rec loop c = - List.iter (fun cf -> - if not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITMember(ctx.curclass,cf)) - ) c.cl_ordered_fields; - match c.cl_super with - | None -> - () - | Some (csup,tl) -> - loop csup; (* TODO: type parameters *) - in - loop ctx.curclass; - (* TODO: local using? *) - end; - - (* statics *) - List.iter (fun cf -> - if not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITStatic(ctx.curclass,cf)) - ) ctx.curclass.cl_ordered_statics; - - (* enum constructors *) - let rec enum_ctors t = - match t with - | TAbstractDecl ({a_impl = Some c} as a) when Meta.has Meta.Enum a.a_meta -> - List.iter (fun cf -> - if (Meta.has Meta.Enum cf.cf_meta) && not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITEnumAbstract(a,cf)); - ) c.cl_ordered_statics - | TClassDecl _ | TAbstractDecl _ -> - () - | TTypeDecl t -> - begin match follow t.t_type with - | TEnum (e,_) -> enum_ctors (TEnumDecl e) - | _ -> () - end - | TEnumDecl e -> - PMap.iter (fun _ ef -> - add (ITEnum(e,ef)) - ) e.e_constrs; - in - List.iter enum_ctors ctx.m.curmod.m_types; - List.iter enum_ctors (List.map fst ctx.m.module_types); - - (* imported globals *) - PMap.iter (fun _ (mt,s,_) -> - try - let t = match resolve_typedef mt with - | TClassDecl c -> (PMap.find s c.cl_statics).cf_type - | TEnumDecl en -> (PMap.find s en.e_constrs).ef_type - | TAbstractDecl {a_impl = Some c} -> (PMap.find s c.cl_statics).cf_type - | _ -> raise Not_found - in - add (ITGlobal(mt,s,t)) - with Not_found -> - () - ) ctx.m.module_globals; - - (* literals *) - add (ITLiteral "null"); - add (ITLiteral "true"); - add (ITLiteral "false"); - end; - - let module_types = ref [] in - - let add_type mt = - match mt with - | TClassDecl {cl_kind = KAbstractImpl _} -> () - | _ -> - let path = (t_infos mt).mt_path in - if not (List.exists (fun mt2 -> (t_infos mt2).mt_path = path) !module_types) then begin - (match mt with - | TClassDecl c | TAbstractDecl { a_impl = Some c } when Meta.has Meta.CoreApi c.cl_meta -> - !merge_core_doc_ref ctx c - | _ -> ()); - module_types := mt :: !module_types - end - in - - (* module types *) - List.iter add_type ctx.m.curmod.m_types; - - (* module imports *) - List.iter add_type (List.map fst ctx.m.module_types); - - (* module using *) - List.iter (fun (c,_) -> - add_type (TClassDecl c) - ) ctx.m.module_using; - - (* TODO: wildcard packages. How? *) - - (* packages and toplevel types *) - let class_paths = ctx.com.class_path in - let class_paths = List.filter (fun s -> s <> "") class_paths in - - let packages = ref [] in - let add_package pack = - try - begin match PMap.find pack ctx.com.package_rules with - | Forbidden -> - () - | _ -> - raise Not_found - end - with Not_found -> - if not (List.mem pack !packages) then packages := pack :: !packages - in - - let maybe_add_type mt = if not (t_infos mt).mt_private then add_type mt in - - explore_class_paths ctx class_paths false add_package (fun _ -> ()) maybe_add_type; - - List.iter (fun pack -> - add (ITPackage pack) - ) !packages; - - List.iter (fun mt -> - add (ITType mt) - ) !module_types; - - (* type params *) - List.iter (fun (_,t) -> - add (ITType (module_type_of_type t)) - ) ctx.type_params; - - DynArray.to_list acc - - let handle_unresolved_identifier ctx i p only_types = - let l = run ctx only_types in - let cl = List.map (fun it -> - let s = IdentifierType.get_name it in - (s,it),StringError.levenshtein i s - ) l in - let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in - let cl = StringError.filter_similar (fun (s,_) r -> r > 0 && r <= (min (String.length s) (String.length i)) / 3) cl in - ctx.com.display_information.unresolved_identifiers <- (i,p,cl) :: ctx.com.display_information.unresolved_identifiers -end \ No newline at end of file diff --git a/src/context/display/deprecationCheck.ml b/src/context/display/deprecationCheck.ml new file mode 100644 index 00000000000..7934314eb75 --- /dev/null +++ b/src/context/display/deprecationCheck.ml @@ -0,0 +1,95 @@ +open Globals +open Type +open Common +open Ast + +let curclass = ref null_class + +let warned_positions = Hashtbl.create 0 + +let warn_deprecation com s p_usage = + if not (Hashtbl.mem warned_positions p_usage) then begin + Hashtbl.replace warned_positions p_usage s; + match com.display.dms_kind with + | DMDiagnostics _ -> () + | _ -> com.warning s p_usage; + end + +let print_deprecation_message com meta s p_usage = + let s = match meta with + | _,[EConst(String s),_],_ -> s + | _ -> Printf.sprintf "Usage of this %s is deprecated" s + in + warn_deprecation com s p_usage + +let check_meta com meta s p_usage = + try + print_deprecation_message com (Meta.get Meta.Deprecated meta) s p_usage; + with Not_found -> + () + +let check_cf com cf p = check_meta com cf.cf_meta "field" p + +let check_class com c p = if c != !curclass then check_meta com c.cl_meta "class" p + +let check_enum com en p = check_meta com en.e_meta "enum" p + +let check_ef com ef p = check_meta com ef.ef_meta "enum field" p + +let check_typedef com t p = check_meta com t.t_meta "typedef" p + +let check_module_type com mt p = match mt with + | TClassDecl c -> check_class com c p + | TEnumDecl en -> check_enum com en p + | _ -> () + +let run_on_expr com e = + let rec expr e = match e.eexpr with + | TField(e1,fa) -> + expr e1; + begin match fa with + | FStatic(c,cf) | FInstance(c,_,cf) -> + check_class com c e.epos; + check_cf com cf e.epos + | FAnon cf -> + check_cf com cf e.epos + | FClosure(co,cf) -> + (match co with None -> () | Some (c,_) -> check_class com c e.epos); + check_cf com cf e.epos + | FEnum(en,ef) -> + check_enum com en e.epos; + check_ef com ef e.epos; + | _ -> + () + end + | TNew(c,_,el) -> + List.iter expr el; + check_class com c e.epos; + begin match c.cl_constructor with + (* The AST doesn't carry the correct overload for TNew, so let's ignore this case... (#8557). *) + | Some cf when cf.cf_overloads = [] -> check_cf com cf e.epos + | _ -> () + end + | TTypeExpr(mt) | TCast(_,Some mt) -> + check_module_type com mt e.epos + | TMeta((Meta.Deprecated,_,_) as meta,e1) -> + print_deprecation_message com meta "field" e1.epos; + expr e1; + | _ -> + Type.iter expr e + in + expr e + +let run_on_field com cf = match cf.cf_expr with None -> () | Some e -> run_on_expr com e + +let run com = + List.iter (fun t -> match t with + | TClassDecl c -> + curclass := c; + (match c.cl_constructor with None -> () | Some cf -> run_on_field com cf); + (match c.cl_init with None -> () | Some e -> run_on_expr com e); + List.iter (run_on_field com) c.cl_ordered_statics; + List.iter (run_on_field com) c.cl_ordered_fields; + | _ -> + () + ) com.types \ No newline at end of file diff --git a/src/context/display/diagnostics.ml b/src/context/display/diagnostics.ml new file mode 100644 index 00000000000..0b571271aff --- /dev/null +++ b/src/context/display/diagnostics.ml @@ -0,0 +1,219 @@ +open Globals +open Ast +open Type +open Typecore +open Common +open Display +open DisplayTypes.DisplayMode + +type diagnostics_context = { + com : Common.context; + mutable removable_code : (string * pos * pos) list; +} + +open DisplayTypes + +let add_removable_code ctx s p prange = + ctx.removable_code <- (s,p,prange) :: ctx.removable_code + +let find_unused_variables com e = + let vars = Hashtbl.create 0 in + let pmin_map = Hashtbl.create 0 in + let rec loop e = match e.eexpr with + | TVar({v_kind = VUser _} as v,eo) when v.v_name <> "_" -> + Hashtbl.add pmin_map e.epos.pmin v; + let p = match eo with + | None -> e.epos + | Some e1 -> + loop e1; + { e.epos with pmax = e1.epos.pmin } + in + Hashtbl.replace vars v.v_id (v,p); + | TLocal ({v_kind = VUser _} as v) -> + Hashtbl.remove vars v.v_id; + | _ -> + Type.iter loop e + in + loop e; + Hashtbl.iter (fun _ (v,p) -> + let p = match (Hashtbl.find_all pmin_map p.pmin) with [_] -> p | _ -> null_pos in + add_removable_code com "Unused variable" v.v_pos p + ) vars + +let check_other_things com e = + let had_effect = ref false in + let no_effect p = + add_diagnostics_message com "This code has no effect" p DKCompilerError DiagnosticsSeverity.Warning; + in + let pointless_compound s p = + add_diagnostics_message com (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p DKCompilerError DiagnosticsSeverity.Warning; + in + let rec compound s el p = + let old = !had_effect in + had_effect := false; + List.iter (loop true) el; + if not !had_effect then no_effect p else pointless_compound s p; + had_effect := old; + and loop in_value e = match e.eexpr with + | TBlock el -> + let rec loop2 el = match el with + | [] -> () + | [e] -> loop in_value e + | e :: el -> loop false e; loop2 el + in + loop2 el + | TMeta((Meta.Extern,_,_),_) -> + (* This is so something like `[inlineFunc()]` is not reported. *) + had_effect := true; + | TConst _ | TLocal {v_kind = VUser _} | TTypeExpr _ | TFunction _ | TIdent _ when not in_value -> + no_effect e.epos; + | TConst _ | TLocal _ | TTypeExpr _ | TEnumParameter _ | TEnumIndex _ | TVar _ | TIdent _ -> + () + | TField (_, fa) when PurityState.is_explicitly_impure fa -> () + | TFunction tf -> + loop false tf.tf_expr + | TCall({eexpr = TField(e1,fa)},el) when not in_value && PurityState.is_pure_field_access fa -> compound "call" el e.epos + | TNew _ | TCall _ | TBinop ((Ast.OpAssignOp _ | Ast.OpAssign),_,_) | TUnop ((Ast.Increment | Ast.Decrement),_,_) + | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) + | TIf _ | TTry _ | TSwitch _ | TWhile _ | TFor _ -> + had_effect := true; + Type.iter (loop true) e + | TParenthesis e1 | TMeta(_,e1) -> + loop in_value e1 + | TArray _ | TCast (_,None) | TBinop _ | TUnop _ + | TField _ | TArrayDecl _ | TObjectDecl _ when in_value -> + Type.iter (loop true) e; + | TArray(e1,e2) -> compound "array access" [e1;e2] e.epos + | TCast(e1,None) -> compound "cast" [e1] e.epos + | TBinop(op,e1,e2) -> compound (Printf.sprintf "'%s' operator" (s_binop op)) [e1;e2] e.epos + | TUnop(op,_,e1) -> compound (Printf.sprintf "'%s' operator" (s_unop op)) [e1] e.epos + | TField(e1,_) -> compound "field access" [e1] e.epos + | TArrayDecl el -> compound "array declaration" el e.epos + | TObjectDecl fl -> compound "object declaration" (List.map snd fl) e.epos + in + loop true e + +let prepare_field dctx cf = match cf.cf_expr with + | None -> () + | Some e -> + find_unused_variables dctx e; + check_other_things dctx.com e; + DeprecationCheck.run_on_expr dctx.com e + +let prepare com global = + let dctx = { + removable_code = []; + com = com; + } in + List.iter (function + | TClassDecl c when global || DisplayPosition.display_position#is_in_file c.cl_pos.pfile -> + List.iter (prepare_field dctx) c.cl_ordered_fields; + List.iter (prepare_field dctx) c.cl_ordered_statics; + (match c.cl_constructor with None -> () | Some cf -> prepare_field dctx cf); + | _ -> + () + ) com.types; + dctx + +let is_diagnostics_run p = match (!Parser.display_mode) with + | DMDiagnostics true -> true + | DMDiagnostics false -> DisplayPosition.display_position#is_in_file p.pfile + | _ -> false + +let secure_generated_code ctx e = + if is_diagnostics_run e.epos then mk (TMeta((Meta.Extern,[],e.epos),e)) e.etype e.epos else e + +module Printer = struct + open Json + open DiagnosticsKind + open DisplayTypes + + type t = DiagnosticsKind.t * pos + + module UnresolvedIdentifierSuggestion = struct + type t = + | UISImport + | UISTypo + + let to_int = function + | UISImport -> 0 + | UISTypo -> 1 + end + + open UnresolvedIdentifierSuggestion + open CompletionItem + open CompletionModuleType + + let print_diagnostics dctx com global = + let diag = Hashtbl.create 0 in + let add dk p sev args = + let file = if p = null_pos then p.pfile else Path.get_real_path p.pfile in + let diag = try + Hashtbl.find diag file + with Not_found -> + let d = Hashtbl.create 0 in + Hashtbl.add diag file d; + d + in + if not (Hashtbl.mem diag p) then + Hashtbl.add diag p (dk,p,sev,args) + in + let add dk p sev args = + if global || p = null_pos || DisplayPosition.display_position#is_in_file p.pfile then add dk p sev args + in + List.iter (fun (s,p,suggestions) -> + let suggestions = ExtList.List.filter_map (fun (s,item,r) -> + match item.ci_kind with + | ITType(t,_) when r = 0 -> + let path = if t.module_name = t.name then (t.pack,t.name) else (t.pack @ [t.module_name],t.name) in + Some (JObject [ + "kind",JInt (to_int UISImport); + "name",JString (s_type_path path); + ]) + | _ when r = 0 -> + (* TODO !!! *) + None + | _ -> + Some (JObject [ + "kind",JInt (to_int UISTypo); + "name",JString s; + ]) + ) suggestions in + add DKUnresolvedIdentifier p DiagnosticsSeverity.Error (JArray suggestions); + ) com.display_information.unresolved_identifiers; + PMap.iter (fun p (r,_) -> + if not !r then add DKUnusedImport p DiagnosticsSeverity.Warning (JArray []) + ) com.shared.shared_display_information.import_positions; + List.iter (fun (s,p,kind,sev) -> + add kind p sev (JString s) + ) (List.rev com.shared.shared_display_information.diagnostics_messages); + List.iter (fun (s,p,prange) -> + add DKRemovableCode p DiagnosticsSeverity.Warning (JObject ["description",JString s;"range",if prange = null_pos then JNull else Genjson.generate_pos_as_range prange]) + ) dctx.removable_code; + Hashtbl.iter (fun p s -> + add DKDeprecationWarning p DiagnosticsSeverity.Warning (JString s); + ) DeprecationCheck.warned_positions; + let jl = Hashtbl.fold (fun file diag acc -> + let jl = Hashtbl.fold (fun _ (dk,p,sev,jargs) acc -> + (JObject [ + "kind",JInt (DiagnosticsKind.to_int dk); + "severity",JInt (DiagnosticsSeverity.to_int sev); + "range",Genjson.generate_pos_as_range p; + "args",jargs + ]) :: acc + ) diag [] in + (JObject [ + "file",if file = "?" then JNull else JString file; + "diagnostics",JArray jl + ]) :: acc + ) diag [] in + let js = JArray jl in + string_of_json js +end + +let print com global = + let dctx = prepare com global in + Printer.print_diagnostics dctx com global + +let run com global = + DisplayException.raise_diagnostics (print com global) \ No newline at end of file diff --git a/src/context/display/display.ml b/src/context/display/display.ml new file mode 100644 index 00000000000..423bdb55561 --- /dev/null +++ b/src/context/display/display.ml @@ -0,0 +1,254 @@ +open Ast +open Common +open DisplayTypes +open DisplayMode +open DisplayPosition +open CompletionItem +open CompletionResultKind +open Type +open Typecore +open Globals +open Genjson +open DisplayPosition + + +let merge_core_doc ctx mtype = + display_position#run_outside (fun () -> Typecore.merge_core_doc ctx mtype) + +let parse_module' com m p = + display_position#run_outside (fun () -> TypeloadParse.parse_module' com m p) + +let parse_module ctx m p = + display_position#run_outside (fun () -> TypeloadParse.parse_module ctx m p) + +module ReferencePosition = struct + let reference_position = ref ("",null_pos,KVar) + let set (s,p,k) = reference_position := (s,{p with pfile = Path.unique_full_path p.pfile},k) + let get () = !reference_position +end + +module ExprPreprocessing = struct + let find_before_pos dm e = + let display_pos = ref (DisplayPosition.display_position#get) in + let was_annotated = ref false in + let is_annotated,is_completion = match dm with + | DMDefault -> (fun p -> not !was_annotated && encloses_position !display_pos p),true + | DMHover -> (fun p -> not !was_annotated && encloses_position_gt !display_pos p),false + | _ -> (fun p -> not !was_annotated && encloses_position !display_pos p),false + in + let annotate e dk = + was_annotated := true; + (EDisplay(e,dk),pos e) + in + let annotate_marked e = annotate e DKMarked in + let mk_null p = annotate_marked ((EConst(Ident "null")),p) in + let loop_el el = + let pr = DisplayPosition.display_position#get in + let rec loop el = match el with + | [] -> [mk_null pr] + | e :: el -> + if (pos e).pmin >= pr.pmax then (mk_null pr) :: e :: el + else e :: loop el + in + (* print_endline (Printf.sprintf "%i-%i: PR" pr.pmin pr.pmax); + List.iter (fun e -> + print_endline (Printf.sprintf "%i-%i: %s" (pos e).pmin (pos e).pmax (Ast.s_expr e)); + ) el; *) + match el with + | [] -> [mk_null pr] + | e :: el -> + if (pos e).pmin >= pr.pmax then (mk_null pr) :: e :: el + else loop (e :: el) + in + let in_pattern = ref false in + let loop e = + (* print_endline (Printf.sprintf "%i-%i: %s" (pos e).pmin (pos e).pmax (Ast.s_expr e)); *) + match fst e with + | EVars vl when is_annotated (pos e) && is_completion -> + let rec loop2 acc mark vl = match vl with + | ((s,pn),final,tho,eo) as v :: vl -> + if mark then + loop2 (v :: acc) mark vl + else if is_annotated pn then + (* If the name is the display position, mark the expression *) + loop2 (v :: acc) true vl + else begin match eo with + | None -> + (* If there is no expression, we don't have to do anything. + Should the display position be on the type-hint, it will + be picked up while loading the type. *) + loop2 (v :: acc) mark vl + | Some e -> + (* Determine the area between the `|` in `var x| = | e`. This is not really + correct because we don't want completion on the left side of the `=`, but + we cannot determine that correctly without knowing its position. + Note: We know `e` itself isn't the display position because this entire + algorithm is bottom-up and it would be marked already if it was. *) + let p0 = match tho with + | Some (_,pt) -> pt + | None -> pn + in + let p = {p0 with pmax = (pos e).pmin} in + let e = if is_annotated p then annotate_marked e else e in + loop2 (((s,pn),final,tho,(Some e)) :: acc) mark vl + end + | [] -> + List.rev acc,mark + in + let vl,mark = loop2 [] false vl in + let e = EVars (List.rev vl),pos e in + if !was_annotated then e else raise Exit + | EBinop((OpAssign | OpAssignOp _) as op,e1,e2) when is_annotated (pos e) && is_completion -> + (* Special case for assign ops: If the expression is marked, but none of its operands are, + we are "probably" interested in the rhs. Like with EVars, this isn't accurate because we + could be on the left side of the `=`. I don't think there's a reason for requesting + completion there though. *) + (EBinop(op,e1,annotate_marked e2)),(pos e) + | EBinop(OpOr,e1,(EIf(_,(EConst(Ident "null"),_),None),p1)) when is_annotated (pos e) && is_completion && !in_pattern -> + (* This HAS TO come from an attempted `case pattern | guard:` completion (issue #7068). *) + let p = { p1 with pmin = (pos e1).pmax; pmax = p1.pmin } in + EBinop(OpOr,e1,mk_null p),(pos e) + | EIf(_,(EConst(Ident "null"),_),None) when is_completion && !in_pattern -> + (* This is fine. *) + mk_null (pos e) + | EBlock [] when is_annotated (pos e) -> + annotate e DKStructure + | EBlock [EDisplay((EConst(Ident s),pn),DKMarked),_] when is_completion -> + let e = EObjectDecl [(s,pn,NoQuotes),(EConst (Ident "null"),null_pos)],(pos e) in + annotate e DKStructure + | EBlock el when is_annotated (pos e) && is_completion -> + let el = loop_el el in + EBlock el,(pos e) + | ECall(e1,el) when is_annotated (pos e) && is_completion -> + let el = loop_el el in + ECall(e1,el),(pos e) + | ENew((tp,pp),el) when is_annotated (pos e) && is_completion -> + if is_annotated pp || pp.pmax >= (DisplayPosition.display_position#get).pmax then + annotate_marked e + else begin + let el = loop_el el in + ENew((tp,pp),el),(pos e) + end + | EArrayDecl el when is_annotated (pos e) && is_completion -> + let el = loop_el el in + EArrayDecl el,(pos e) + | EObjectDecl fl when is_annotated (pos e) && is_completion -> + annotate e DKStructure + | ESwitch(e1,cases,def) when is_annotated (pos e) -> + (* We must be "between" two cases, or at the end of the last case. + Let's find the last case which has a position that is < the display + position and mark it. *) + let did_mark = ref false in + let mark_case ec p = + did_mark := true; + let ep = mk_null p in + match ec with + | Some ec -> + let ec = match fst ec with + | EBlock el -> (EBlock (el @ [ep]),p) + | _ -> (EBlock [ec;ep],p) + in + Some ec + | None -> + Some (mk_null p) + in + let rec loop cases = match cases with + | [el,eg,ec,p1] -> + let ec = match def with + | None when (pos e).pmax > !display_pos.pmin -> (* this is so we don't trigger if we're on the } *) + mark_case ec p1 (* no default, must be the last case *) + | Some (_,p2) when p1.pmax <= !display_pos.pmin && p2.pmin >= !display_pos.pmax -> + mark_case ec p1 (* default is beyond display position, mark *) + | _ -> + ec (* default contains display position, don't mark *) + in + [el,eg,ec,p1] + | (el1,eg1,ec1,p1) :: (el2,eg2,ec2,p2) :: cases -> + if p1.pmax <= !display_pos.pmin && p2.pmin >= !display_pos.pmax then + (el1,eg1,mark_case ec1 p1,p1) :: (el2,eg2,ec2,p2) :: cases + else + (el1,eg1,ec1,p1) :: loop ((el2,eg2,ec2,p2) :: cases) + | [] -> + [] + in + let cases = loop cases in + let def = if !did_mark then + def + else match def with + | Some(eo,p) when (pos e).pmax > !display_pos.pmin -> Some (mark_case eo p,p) + | _ -> def + in + ESwitch(e1,cases,def),pos e + | EDisplay _ -> + raise Exit + | EMeta((Meta.Markup,_,_),(EConst(String _),p)) when is_annotated p -> + annotate_marked e + | EConst (String _) when (not (Lexer.is_fmt_string (pos e)) || !Parser.was_auto_triggered) && is_annotated (pos e) && is_completion -> + (* TODO: check if this makes any sense *) + raise Exit + | EConst(Regexp _) when is_annotated (pos e) && is_completion -> + raise Exit + | EVars vl when is_annotated (pos e) -> + (* We only want to mark EVars if we're on a var name. *) + if List.exists (fun ((_,pn),_,_,_) -> is_annotated pn) vl then + annotate_marked e + else + raise Exit + | _ -> + if is_annotated (pos e) then + annotate_marked e + else + e + in + let opt f o = + match o with None -> None | Some v -> Some (f v) + in + let rec map e = match fst e with + | ESwitch(e1,cases,def) when is_annotated (pos e) -> + let e1 = map e1 in + let cases = List.map (fun (el,eg,e,p) -> + let old = !in_pattern in + in_pattern := true; + let el = List.map map el in + in_pattern := old; + let eg = opt map eg in + let e = opt map e in + el,eg,e,p + ) cases in + let def = opt (fun (eo,p) -> opt map eo,p) def in + loop (ESwitch (e1, cases, def),(pos e)) + | _ -> + loop (Ast.map_expr map e) + in + try map e with Exit -> e + + let find_display_call e = + let found = ref false in + let handle_el e el = + let call_arg_is_marked () = + el = [] || List.exists (fun (e,_) -> match e with EDisplay(_,DKMarked) -> true | _ -> false) el + in + if not !Parser.was_auto_triggered || call_arg_is_marked () then begin + found := true; + Parser.mk_display_expr e DKCall + end else + e + in + let loop e = match fst e with + | ECall(_,el) | ENew(_,el) when not !found && display_position#enclosed_in (pos e) -> + handle_el e el + | EArray(e1,e2) when not !found && display_position#enclosed_in (pos e2) -> + handle_el e [e2] + | EDisplay(_,DKCall) -> + raise Exit + | _ -> e + in + let rec map e = loop (Ast.map_expr map e) in + try map e with Exit -> e + + + let process_expr com e = match com.display.dms_kind with + | DMDefinition | DMTypeDefinition | DMUsage _ | DMHover | DMDefault -> find_before_pos com.display.dms_kind e + | DMSignature -> find_display_call e + | _ -> e +end \ No newline at end of file diff --git a/src/context/display/displayEmitter.ml b/src/context/display/displayEmitter.ml new file mode 100644 index 00000000000..83b46e1204c --- /dev/null +++ b/src/context/display/displayEmitter.ml @@ -0,0 +1,309 @@ +open Globals +open Ast +open Type +open Typecore +open DisplayException +open DisplayTypes +open DisplayMode +open CompletionItem +open CompletionType +open ImportStatus +open ClassFieldOrigin +open DisplayTypes.CompletionResultKind +open Common +open Display +open DisplayPosition + +let get_expected_name with_type = match with_type with + | WithType.Value (Some src) | WithType.WithType(_,Some src) -> + (match src with + | WithType.FunctionArgument name -> Some name + | WithType.StructureField name -> Some name + | WithType.ImplicitReturn -> None + ) + | _ -> None + +let sort_fields l with_type tk = + let p = match tk with + | TKExpr p | TKField p -> Some p + | _ -> None + in + let expected_name = get_expected_name with_type in + let l = List.map (fun ci -> + let i = get_sort_index tk ci (Option.default Globals.null_pos p) expected_name in + ci,i + ) l in + let sort l = + List.map fst (List.sort (fun (_,i1) (_,i2) -> compare i1 i2) l) + in + (* This isn't technically accurate, but I don't think it matters. *) + let rec dynamify_type_params t = match follow t with + | TInst({cl_kind = KTypeParameter _},_) -> mk_mono() + | _ -> Type.map dynamify_type_params t + in + let l = match with_type with + | WithType.WithType(t,_) when (match follow t with TMono _ -> false | _ -> true) -> + let rec comp item = match item.ci_type with + | None -> 9 + | Some (t',_) -> + (* For enum constructors, we consider the return type of the constructor function + so it has the same priority as argument-less constructors. *) + let t' = match item.ci_kind,follow t' with + | ITEnumField _,TFun(_,r) -> r + | _ -> t' + in + let t' = dynamify_type_params t' in + if type_iseq t' t then 0 (* equal types - perfect *) + else if t' == t_dynamic then 5 (* dynamic isn't good, but better than incompatible *) + else try Type.unify t' t; 1 (* assignable - great *) + with Unify_error _ -> match follow t' with + | TFun(_,tr) -> + if type_iseq tr t then 2 (* function returns our exact type - alright *) + else (try Type.unify tr t; 3 (* function returns compatible type - okay *) + with Unify_error _ -> 7) (* incompatible function - useless *) + | _ -> + 6 (* incompatible type - probably useless *) + in + let l = List.map (fun (item,i1) -> + let i2 = comp item in + item,(i2,i1) + ) l in + sort l + | _ -> + sort l + in + l + +let completion_type_of_type ctx ?(values=PMap.empty) t = + let get_import_status path = + try + let mt' = ctx.g.do_load_type_def ctx null_pos {tpackage = []; tname = snd path; tparams = []; tsub = None} in + if path <> (t_infos mt').mt_path then Shadowed else Imported + with _ -> + Unimported + in + let rec ppath mpath tpath tl = { + ct_pack = fst tpath; + ct_module_name = snd mpath; + ct_type_name = snd tpath; + ct_import_status = get_import_status tpath; + ct_params = List.map (from_type PMap.empty) tl; + } + and funarg value (name,opt,t) = { + ct_name = name; + ct_optional = opt; + ct_type = from_type PMap.empty t; + ct_value = value + } + and from_type values t = match t with + | TMono r -> + begin match !r with + | None -> CTMono + | Some t -> from_type values t + end + | TLazy r -> + from_type values (lazy_type r) + | TInst({cl_kind = KTypeParameter _} as c,_) -> + CTInst ({ + ct_pack = fst c.cl_path; + ct_module_name = snd c.cl_module.m_path; + ct_type_name = snd c.cl_path; + ct_import_status = Imported; + ct_params = []; + }) + | TInst(c,tl) -> + CTInst (ppath c.cl_module.m_path c.cl_path tl) + | TEnum(en,tl) -> + CTEnum (ppath en.e_module.m_path en.e_path tl) + | TType(td,tl) -> + CTTypedef (ppath td.t_module.m_path td.t_path tl) + | TAbstract(a,tl) -> + CTAbstract (ppath a.a_module.m_path a.a_path tl) + | TFun(tl,t) when not (PMap.is_empty values) -> + let get_arg n = try Some (PMap.find n values) with Not_found -> None in + CTFunction { + ct_args = List.map (fun (n,o,t) -> funarg (get_arg n) (n,o,t)) tl; + ct_return = from_type PMap.empty t; + } + | TFun(tl,t) -> + CTFunction { + ct_args = List.map (funarg None) tl; + ct_return = from_type PMap.empty t; + } + | TAnon an -> + let afield af = { + ctf_field = af; + ctf_type = from_type PMap.empty af.cf_type; + } in + CTAnonymous { + ct_fields = PMap.fold (fun cf acc -> afield cf :: acc) an.a_fields []; + ct_status = !(an.a_status); + } + | TDynamic t -> + CTDynamic (if t == t_dynamic then None else Some (from_type PMap.empty t)) + in + from_type values t + +let display_module_type ctx mt p = match ctx.com.display.dms_kind with + | DMDefinition | DMTypeDefinition -> + begin match mt with + | TClassDecl c when Meta.has Meta.CoreApi c.cl_meta -> + let c' = ctx.g.do_load_core_class ctx c in + raise_positions [c.cl_name_pos;c'.cl_name_pos] + | _ -> + raise_positions [(t_infos mt).mt_name_pos]; + end + | DMUsage _ -> + let infos = t_infos mt in + ReferencePosition.set (snd infos.mt_path,infos.mt_name_pos,KModuleType) + | DMHover -> + let t = type_of_module_type mt in + let ct = completion_type_of_type ctx t in + raise_hover (make_ci_type (CompletionModuleType.of_module_type mt) ImportStatus.Imported (Some (t,ct))) None p + | _ -> () + +let rec display_type ctx t p = + let dm = ctx.com.display in + try + display_module_type ctx (module_type_of_type t) p + with Exit -> + match follow t,follow !t_dynamic_def with + | _,TDynamic _ -> () (* sanity check in case it's still t_dynamic *) + | TDynamic _,_ -> display_type ctx !t_dynamic_def p + | _ -> + match dm.dms_kind with + | DMHover -> + let ct = completion_type_of_type ctx t in + let ci = make_ci_expr (mk (TConst TNull) t p) (t,ct) in + raise_hover ci None p + | _ -> + () + +let check_display_type ctx t p = + let add_type_hint () = + let md = ctx.m.curmod.m_extra.m_display in + md.m_type_hints <- (p,t) :: md.m_type_hints; + in + let maybe_display_type () = + if ctx.is_display_file && display_position#enclosed_in p then + display_type ctx t p + in + add_type_hint(); + maybe_display_type() + +let raise_position_of_type t = + let mt = + let rec follow_null t = + match t with + | TMono r -> (match !r with None -> raise_positions [null_pos] | Some t -> follow_null t) + | TLazy f -> follow_null (lazy_type f) + | TAbstract({a_path = [],"Null"},[t]) -> follow_null t + | TDynamic _ -> !t_dynamic_def + | _ -> t + in + try + Type.module_type_of_type (follow_null t) + with + Exit -> raise_positions [null_pos] + in + raise_positions [(t_infos mt).mt_name_pos] + +let display_variable ctx v p = match ctx.com.display.dms_kind with + | DMDefinition -> raise_positions [v.v_pos] + | DMTypeDefinition -> raise_position_of_type v.v_type + | DMUsage _ -> ReferencePosition.set (v.v_name,v.v_pos,KVar) + | DMHover -> + let ct = completion_type_of_type ctx ~values:(get_value_meta v.v_meta) v.v_type in + raise_hover (make_ci_local v (v.v_type,ct)) None p + | _ -> () + +let display_field ctx origin scope cf p = match ctx.com.display.dms_kind with + | DMDefinition -> raise_positions [cf.cf_name_pos] + | DMTypeDefinition -> raise_position_of_type cf.cf_type + | DMUsage _ -> + let name,kind = match cf.cf_name,origin with + | "new",(Self (TClassDecl c) | Parent(TClassDecl c)) -> + (* For constructors, we care about the class name so we don't end up looking for "new". *) + snd c.cl_path,KConstructor + | _ -> + cf.cf_name,KClassField + in + ReferencePosition.set (name,cf.cf_name_pos,kind) + | DMHover -> + let cf = if Meta.has Meta.Impl cf.cf_meta then + prepare_using_field cf + else + cf + in + let cf = match origin,scope,follow cf.cf_type with + | Self (TClassDecl c),CFSConstructor,TFun(tl,_) -> {cf with cf_type = TFun(tl,TInst(c,List.map snd c.cl_params))} + | _ -> cf + in + let ct = completion_type_of_type ctx ~values:(get_value_meta cf.cf_meta) cf.cf_type in + raise_hover (make_ci_class_field (CompletionClassField.make cf scope origin true) (cf.cf_type,ct)) None p + | _ -> () + +let maybe_display_field ctx origin scope cf p = + if display_position#enclosed_in p then display_field ctx origin scope cf p + +let display_enum_field ctx en ef p = match ctx.com.display.dms_kind with + | DMDefinition -> raise_positions [ef.ef_name_pos] + | DMTypeDefinition -> raise_position_of_type ef.ef_type + | DMUsage _ -> ReferencePosition.set (ef.ef_name,ef.ef_name_pos,KEnumField) + | DMHover -> + let ct = completion_type_of_type ctx ef.ef_type in + raise_hover (make_ci_enum_field (CompletionEnumField.make ef (Self (TEnumDecl en)) true) (ef.ef_type,ct)) None p + | _ -> () + +let display_meta com meta p = match com.display.dms_kind with + | DMHover -> + begin match meta with + | Meta.Custom _ | Meta.Dollar _ -> () + | _ -> + if com.json_out = None then begin match Meta.get_documentation meta with + | None -> () + | Some (_,s) -> + raise_metadata ("" ^ s ^ "") + end else + raise_hover (make_ci_metadata meta) None p + end + | DMDefault -> + let all = Meta.get_all() in + let all = List.map make_ci_metadata all in + raise_fields all CRMetadata (Some p) + | _ -> + () + +let check_display_metadata ctx meta = + List.iter (fun (meta,args,p) -> + if display_position#enclosed_in p then display_meta ctx.com meta p; + List.iter (fun e -> + if display_position#enclosed_in (pos e) then begin + let e = ExprPreprocessing.process_expr ctx.com e in + delay ctx PTypeField (fun _ -> ignore(type_expr ctx e WithType.value)); + end + ) args + ) meta + +let check_field_modifiers ctx c cf override display_modifier = + match override,display_modifier with + | Some p,_ when display_position#enclosed_in p && ctx.com.display.dms_kind = DMDefinition -> + begin match c.cl_super with + | Some(c,tl) -> + let _,_,cf = raw_class_field (fun cf -> cf.cf_type) c tl cf.cf_name in + display_field ctx (Parent(TClassDecl c)) CFSMember cf p + | _ -> + () + end + | _,Some (AOverride,p) when ctx.com.display.dms_kind = DMDefault -> + let all_fields = TClass.get_all_super_fields c in + let missing_fields = List.fold_left (fun fields cf -> PMap.remove cf.cf_name fields) all_fields c.cl_ordered_fields in + let l = PMap.fold (fun (c,cf) fields -> + let origin = Parent (TClassDecl c) in + ignore(follow cf.cf_type); + let ct = completion_type_of_type ctx ~values:(get_value_meta cf.cf_meta) cf.cf_type in + make_ci_class_field (CompletionClassField.make cf CFSMember origin true) (cf.cf_type,ct) :: fields + ) missing_fields [] in + let l = sort_fields l NoValue TKOverride in + raise_fields l CROverride None + | _ -> () \ No newline at end of file diff --git a/src/context/display/displayException.ml b/src/context/display/displayException.ml new file mode 100644 index 00000000000..dbb2c1f846c --- /dev/null +++ b/src/context/display/displayException.ml @@ -0,0 +1,188 @@ +open Globals +open Ast +open DisplayTypes +open CompletionItem +open Type +open Genjson + +type hover_result = { + hitem : CompletionItem.t; + hpos : pos; + hexpected : WithType.t option; +} + +type fields_result = { + fitems : CompletionItem.t list; + fkind : CompletionResultKind.t; + finsert_pos : pos option; + fsubject : placed_name option; +} + +type signature_kind = + | SKCall + | SKArrayAccess + +type kind = + | Diagnostics of string + | Statistics of string + | ModuleSymbols of string + | Metadata of string + | DisplaySignatures of (((tsignature * CompletionType.ct_function) * documentation) list * int * int * signature_kind) option + | DisplayHover of hover_result option + | DisplayPositions of pos list + | DisplayFields of fields_result option + | DisplayPackage of string list + +exception DisplayException of kind + +let raise_diagnostics s = raise (DisplayException(Diagnostics s)) +let raise_statistics s = raise (DisplayException(Statistics s)) +let raise_module_symbols s = raise (DisplayException(ModuleSymbols s)) +let raise_metadata s = raise (DisplayException(Metadata s)) +let raise_signatures l isig iarg kind = raise (DisplayException(DisplaySignatures(Some(l,isig,iarg,kind)))) +let raise_hover item expected p = raise (DisplayException(DisplayHover(Some {hitem = item;hpos = p;hexpected = expected}))) +let raise_positions pl = raise (DisplayException(DisplayPositions pl)) +let raise_fields ckl cr po = raise (DisplayException(DisplayFields(Some({fitems = ckl;fkind = cr;finsert_pos = po;fsubject = None})))) +let raise_fields2 ckl cr po subject = raise (DisplayException(DisplayFields(Some({fitems = ckl;fkind = cr;finsert_pos = po;fsubject = Some subject})))) +let raise_package sl = raise (DisplayException(DisplayPackage sl)) + +(* global state *) +let last_completion_result = ref (Array.make 0 (CompletionItem.make (ITModule ([],"")) None)) +let last_completion_pos = ref None +let max_completion_items = ref 0 + +let filter_somehow ctx items subject kind po = + let ret = DynArray.create () in + let acc_types = DynArray.create () in + let subject = match subject with + | None -> "" + | Some(subject,_) -> String.lowercase subject + in + let subject_matches s = + let rec loop i o = + if i < String.length subject then begin + let o = String.index_from s o subject.[i] in + loop (i + 1) o + end + in + try + loop 0 0; + true + with Not_found -> + false + in + let rec loop items index = + match items with + | _ when DynArray.length ret > !max_completion_items -> + () + | item :: items -> + let name = String.lowercase (get_filter_name item) in + if subject_matches name then begin + (* Treat types with lowest priority. The assumption is that they are the only kind + which actually causes the limit to be hit, so we show everything else and then + fill in types. *) + match item.ci_kind with + | ITType _ -> + if DynArray.length ret + DynArray.length acc_types < !max_completion_items then + DynArray.add acc_types (item,index); + | _ -> + DynArray.add ret (CompletionItem.to_json ctx (Some index) item); + end; + loop items (index + 1) + | [] -> + () + in + loop items 0; + DynArray.iter (fun (item,index) -> + if DynArray.length ret < !max_completion_items then + DynArray.add ret (CompletionItem.to_json ctx (Some index) item); + ) acc_types; + DynArray.to_list ret,DynArray.length ret = !max_completion_items + +let fields_to_json ctx fields kind po subject = + last_completion_result := Array.of_list fields; + let needs_filtering = !max_completion_items > 0 && Array.length !last_completion_result > !max_completion_items in + let ja,did_filter = if needs_filtering then + filter_somehow ctx fields subject kind po + else + List.mapi (fun i item -> CompletionItem.to_json ctx (Some i) item) fields,false + in + if did_filter then begin match subject with + | Some(_,p) -> last_completion_pos := Some p; + | None -> last_completion_pos := None + end; + let fl = + ("items",jarray ja) :: + ("isIncomplete",jbool did_filter) :: + ("mode",CompletionResultKind.to_json ctx kind) :: + (match po with None -> [] | Some p -> ["replaceRange",generate_pos_as_range (Parser.cut_pos_at_display p)]) in + jobject fl + +let to_json ctx de = + match de with + | Diagnostics _ + | Statistics _ + | ModuleSymbols _ + | Metadata _ -> assert false + | DisplaySignatures None -> + jnull + | DisplaySignatures Some(sigs,isig,iarg,kind) -> + (* We always want full info for signatures *) + let ctx = Genjson.create_context GMFull in + let fsig ((_,signature),doc) = + let fl = CompletionType.generate_function' ctx signature in + let fl = (match doc with None -> fl | Some s -> ("documentation",jstring s) :: fl) in + jobject fl + in + let sigkind = match kind with + | SKCall -> 0 + | SKArrayAccess -> 1 + in + jobject [ + "activeSignature",jint isig; + "activeParameter",jint iarg; + "signatures",jlist fsig sigs; + "kind",jint sigkind; + ] + | DisplayHover None -> + jnull + | DisplayHover (Some hover) -> + let named_source_kind = function + | WithType.FunctionArgument name -> (0, name) + | WithType.StructureField name -> (1, name) + | _ -> assert false + in + let ctx = Genjson.create_context GMFull in + let generate_name kind = + let i, name = named_source_kind kind in + jobject [ + "name",jstring name; + "kind",jint i; + ] + in + let expected = match hover.hexpected with + | Some(WithType.WithType(t,src)) -> + jobject (("type",generate_type ctx t) + :: (match src with + | None -> [] + | Some ImplicitReturn -> [] + | Some src -> ["name",generate_name src]) + ) + | Some(Value(Some ((FunctionArgument name | StructureField name) as src))) -> + jobject ["name",generate_name src] + | _ -> jnull + in + jobject [ + "documentation",jopt jstring (CompletionItem.get_documentation hover.hitem); + "range",generate_pos_as_range hover.hpos; + "item",CompletionItem.to_json ctx None hover.hitem; + "expected",expected; + ] + | DisplayPositions pl -> + jarray (List.map generate_pos_as_location pl) + | DisplayFields None -> + jnull + | DisplayFields Some r -> + fields_to_json ctx r.fitems r.fkind r.finsert_pos r.fsubject + | DisplayPackage pack -> + jarray (List.map jstring pack) \ No newline at end of file diff --git a/src/context/display/displayFields.ml b/src/context/display/displayFields.ml new file mode 100644 index 00000000000..501e5bcbf24 --- /dev/null +++ b/src/context/display/displayFields.ml @@ -0,0 +1,287 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*) +open Ast +open Globals +open Error +open Typecore +open Type +open CompletionItem +open ClassFieldOrigin +open DisplayEmitter + +let get_submodule_fields ctx path = + let m = Hashtbl.find ctx.g.modules path in + let tl = List.filter (fun t -> path <> (t_infos t).mt_path && not (t_infos t).mt_private) m.m_types in + let tl = List.map (fun mt -> + make_ci_type (CompletionItem.CompletionModuleType.of_module_type mt) ImportStatus.Imported None + ) tl in + tl + +let collect_static_extensions ctx items e p = + let opt_type t = + match t with + | TLazy f -> + return_partial_type := true; + let t = lazy_type f in + return_partial_type := false; + t + | _ -> + t + in + let rec loop acc = function + | [] -> + acc + | (c,_) :: l -> + let rec dup t = Type.map dup t in + let acc = List.fold_left (fun acc f -> + if Meta.has Meta.NoUsing f.cf_meta || Meta.has Meta.NoCompletion f.cf_meta || Meta.has Meta.Impl f.cf_meta || PMap.mem f.cf_name acc then + acc + else begin + let f = { f with cf_type = opt_type f.cf_type } in + let monos = List.map (fun _ -> mk_mono()) f.cf_params in + let map = apply_params f.cf_params monos in + match follow (map f.cf_type) with + | TFun((_,_,TType({t_path=["haxe";"macro"], "ExprOf"}, [t])) :: args, ret) + | TFun((_,_,t) :: args, ret) -> + begin try + let e = TyperBase.unify_static_extension ctx {e with etype = dup e.etype} t p in + List.iter2 (fun m (name,t) -> match follow t with + | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> + List.iter (fun tc -> unify_raise ctx m (map tc) e.epos) constr + | _ -> () + ) monos f.cf_params; + if not (can_access ctx c f true) || follow e.etype == t_dynamic && follow t != t_dynamic then + acc + else begin + let f = prepare_using_field f in + let f = { f with cf_params = []; cf_flags = set_flag f.cf_flags (int_of_class_field_flag CfPublic); cf_type = TFun(args,ret) } in + let decl = match c.cl_kind with + | KAbstractImpl a -> TAbstractDecl a + | _ -> TClassDecl c + in + let origin = StaticExtension(decl) in + let ct = DisplayEmitter.completion_type_of_type ctx ~values:(get_value_meta f.cf_meta) f.cf_type in + let item = make_ci_class_field (CompletionClassField.make f CFSMember origin true) (f.cf_type,ct) in + PMap.add f.cf_name item acc + end + with Error (Unify _,_) | Unify_error _ -> + acc + end + | _ -> + acc + end + ) acc c.cl_ordered_statics in + loop acc l + in + match follow e.etype with + | TMono _ -> + items + | _ -> + let items = loop items ctx.m.module_using in + let items = loop items ctx.g.global_using in + let items = try + let mt = module_type_of_type e.etype in + loop items (t_infos mt).mt_using + with Exit -> + items + in + items + +let collect ctx e_ast e dk with_type p = + let opt_args args ret = TFun(List.map(fun (n,o,t) -> n,true,t) args,ret) in + let should_access c cf stat = + if Meta.has Meta.NoCompletion cf.cf_meta then false + else if c != ctx.curclass && not (has_class_field_flag cf CfPublic) && String.length cf.cf_name > 4 then begin match String.sub cf.cf_name 0 4 with + | "get_" | "set_" -> false + | _ -> can_access ctx c cf stat + end else + (not stat || not (Meta.has Meta.Impl cf.cf_meta)) && + can_access ctx c cf stat + in + let make_class_field origin cf = + let ct = DisplayEmitter.completion_type_of_type ctx ~values:(get_value_meta cf.cf_meta) cf.cf_type in + make_ci_class_field (CompletionClassField.make cf CFSMember origin true) (cf.cf_type,ct) + in + let rec loop items t = + let is_new_item items name = not (PMap.mem name items) in + match follow t with + | TInst ({cl_kind = KTypeParameter tl},_) -> + (* Type parameters can access the fields of their constraints *) + List.fold_left (fun acc t -> loop acc t) items tl + | TInst(c0,tl) -> + (* For classes, browse the hierarchy *) + let fields = TClass.get_all_fields c0 tl in + Display.merge_core_doc ctx (TClassDecl c0); + PMap.foldi (fun k (c,cf) acc -> + if should_access c cf false && is_new_item acc cf.cf_name then begin + let origin = if c == c0 then Self(TClassDecl c) else Parent(TClassDecl c) in + let item = make_class_field origin cf in + PMap.add k item acc + end else + acc + ) fields items + | TEnum _ -> + let t = ctx.g.do_load_type_def ctx p {tpackage=[];tname="EnumValue";tsub=None;tparams=[]} in + begin match t with + | TAbstractDecl ({a_impl = Some c} as a) -> + begin try + let cf = PMap.find "match" c.cl_statics in + let item = make_class_field (Self(TAbstractDecl a)) cf in + PMap.add "match" item items + with Not_found -> + items + end + | _ -> + items + end; + | TAbstract({a_impl = Some c} as a,tl) -> + Display.merge_core_doc ctx (TAbstractDecl a); + (* Abstracts should show all their @:impl fields minus the constructor. *) + let items = List.fold_left (fun acc cf -> + if Meta.has Meta.Impl cf.cf_meta && not (Meta.has Meta.Enum cf.cf_meta) && should_access c cf false && is_new_item acc cf.cf_name then begin + let origin = Self(TAbstractDecl a) in + let cf = prepare_using_field cf in + let cf = if tl = [] then cf else {cf with cf_type = apply_params a.a_params tl cf.cf_type} in + let item = make_class_field origin cf in + PMap.add cf.cf_name item acc + end else + acc + ) items c.cl_ordered_statics in + begin try + (* If there's a @:forward, get the fields of the underlying type and filter them. *) + let _,el,_ = Meta.get Meta.Forward a.a_meta in + let sl = ExtList.List.filter_map (fun e -> match fst e with + | EConst(Ident s) -> Some s + | _ -> None + ) el in + let forwarded_fields = loop PMap.empty (apply_params a.a_params tl a.a_this) in + let abstract_has_own_field field_name = + PMap.mem field_name c.cl_fields || PMap.mem field_name c.cl_statics + in + PMap.foldi (fun name item acc -> + if (sl = [] || List.mem name sl && is_new_item acc name) && not (abstract_has_own_field name) then + PMap.add name item acc + else + acc + ) forwarded_fields items + with Not_found -> + items + end + | TAnon an -> + (* @:forwardStatics *) + let items = match !(an.a_status) with + | Statics { cl_kind = KAbstractImpl { a_meta = meta; a_this = TInst (c,_) }} when Meta.has Meta.ForwardStatics meta -> + let items = List.fold_left (fun acc cf -> + if should_access c cf true && is_new_item acc cf.cf_name then begin + let origin = Self(TClassDecl c) in + let item = make_class_field origin cf in + PMap.add cf.cf_name item acc + end else + acc + ) items c.cl_ordered_statics in + PMap.foldi (fun name item acc -> + if is_new_item acc name then + PMap.add name item acc + else + acc + ) PMap.empty items + | _ -> items + in + (* Anon own fields *) + PMap.foldi (fun name cf acc -> + if is_new_item acc name then begin + let allow_static_abstract_access c cf = + should_access c cf false && + (not (Meta.has Meta.Impl cf.cf_meta) || Meta.has Meta.Enum cf.cf_meta) + in + let ct = DisplayEmitter.completion_type_of_type ctx ~values:(get_value_meta cf.cf_meta) cf.cf_type in + let add origin make_field = + PMap.add name (make_field (CompletionClassField.make cf CFSMember origin true) (cf.cf_type,ct)) acc + in + match !(an.a_status) with + | Statics ({cl_kind = KAbstractImpl a} as c) -> + if allow_static_abstract_access c cf then + let make = if Meta.has Meta.Enum cf.cf_meta then + (make_ci_enum_abstract_field a) + else + make_ci_class_field + in + add (Self (TAbstractDecl a)) make + else + acc; + | Statics c -> + Display.merge_core_doc ctx (TClassDecl c); + if should_access c cf true then add (Self (TClassDecl c)) make_ci_class_field else acc; + | EnumStatics en -> + let ef = PMap.find name en.e_constrs in + PMap.add name (make_ci_enum_field (CompletionEnumField.make ef (Self (TEnumDecl en)) true) (cf.cf_type,ct)) acc + | AbstractStatics a -> + Display.merge_core_doc ctx (TAbstractDecl a); + let check = match a.a_impl with + | None -> true + | Some c -> allow_static_abstract_access c cf + in + if check then add (Self (TAbstractDecl a)) make_ci_class_field else acc; + | _ -> + let origin = match t with + | TType(td,_) -> Self (TTypeDecl td) + | _ -> AnonymousStructure an + in + add origin make_ci_class_field; + end else + acc + ) an.a_fields items + | TFun (args,ret) -> + (* A function has no field except the magic .bind one. *) + if is_new_item items "bind" then begin + let t = opt_args args ret in + let cf = mk_field "bind" (tfun [t] t) p null_pos in + cf.cf_kind <- Method MethNormal; + let ct = DisplayEmitter.completion_type_of_type ctx ~values:(get_value_meta cf.cf_meta) t in + let item = make_ci_class_field (CompletionClassField.make cf CFSStatic BuiltIn true) (t,ct) in + PMap.add "bind" item items + end else + items + | _ -> + items + in + (* Add special `.code` field if we have a string of length 1 *) + let items = match fst e_ast with + | EConst(String s) when String.length s = 1 -> + let cf = mk_field "code" ctx.t.tint e.epos null_pos in + cf.cf_doc <- Some "The character code of this character (inlined at compile-time)."; + cf.cf_kind <- Var { v_read = AccNormal; v_write = AccNever }; + let ct = DisplayEmitter.completion_type_of_type ctx ~values:(get_value_meta cf.cf_meta) cf.cf_type in + let item = make_ci_class_field (CompletionClassField.make cf CFSMember BuiltIn true) (cf.cf_type,ct) in + PMap.add cf.cf_name item PMap.empty + | _ -> + PMap.empty + in + (* Collect fields of the type *) + let items = loop items e.etype in + (* Add static extensions *) + let items = collect_static_extensions ctx items e p in + let items = PMap.fold (fun item acc -> item :: acc) items [] in + let items = sort_fields items WithType.value (TKField p) in + try + let sl = string_list_of_expr_path_raise e_ast in + (* Add submodule fields *) + items @ get_submodule_fields ctx (List.tl sl,List.hd sl) + with Exit | Not_found -> + items diff --git a/src/context/display/displayJson.ml b/src/context/display/displayJson.ml new file mode 100644 index 00000000000..b1d8d18b32e --- /dev/null +++ b/src/context/display/displayJson.ml @@ -0,0 +1,305 @@ +open Globals +open Json.Reader +open JsonRpc +open Jsonrpc_handler +open Json +open Common +open DisplayTypes.DisplayMode +open Timer +open Genjson +open Type + +(* Generate the JSON of our times. *) +let json_of_times root = + let rec loop node = + if node == root || node.time > 0.0009 then begin + let children = ExtList.List.filter_map loop node.children in + let fl = [ + "name",jstring node.name; + "path",jstring node.path; + "info",jstring node.info; + "time",jfloat node.time; + "calls",jint node.num_calls; + "percentTotal",jfloat (node.time *. 100. /. root.time); + "percentParent",jfloat (if node == root then 0. else node.time *. 100. /. node.parent.time); + ] in + let fl = match children with + | [] -> fl + | _ -> ("children",jarray children) :: fl + in + Some (jobject fl) + end else + None + in + loop root + +let supports_resolve = ref false + +let create_json_context jsonrpc may_resolve = + Genjson.create_context ~jsonrpc:jsonrpc (if may_resolve && !supports_resolve then GMMinimum else GMFull) + +let send_string j = + raise (DisplayOutput.Completion j) + +let send_json json = + send_string (string_of_json json) + +class display_handler (jsonrpc : jsonrpc_handler) com cs = object(self) + val cs = cs; + + method get_cs = cs + + method enable_display mode = + com.display <- create mode; + Parser.display_mode := mode; + Common.define_value com Define.Display "1" + + method set_display_file was_auto_triggered requires_offset = + let file = jsonrpc#get_string_param "file" in + let file = Path.unique_full_path file in + let pos = if requires_offset then jsonrpc#get_int_param "offset" else (-1) in + TypeloadParse.current_stdin := jsonrpc#get_opt_param (fun () -> + let s = jsonrpc#get_string_param "contents" in + Common.define com Define.DisplayStdin; (* TODO: awkward *) + (* Remove our current display file from the cache so the server doesn't pick it up *) + CompilationServer.remove_files cs file; + Some s + ) None; + Parser.was_auto_triggered := was_auto_triggered; + DisplayPosition.display_position#set { + pfile = file; + pmin = pos; + pmax = pos; + } +end + +type handler_context = { + com : Common.context; + jsonrpc : jsonrpc_handler; + display : display_handler; + send_result : Json.t -> unit; + send_error : 'a . Json.t list -> 'a; +} + +let handler = + let open CompilationServer in + let h = Hashtbl.create 0 in + let l = [ + "initialize", (fun hctx -> + supports_resolve := hctx.jsonrpc#get_opt_param (fun () -> hctx.jsonrpc#get_bool_param "supportsResolve") false; + DisplayException.max_completion_items := hctx.jsonrpc#get_opt_param (fun () -> hctx.jsonrpc#get_int_param "maxCompletionItems") 0; + let exclude = hctx.jsonrpc#get_opt_param (fun () -> hctx.jsonrpc#get_array_param "exclude") [] in + DisplayToplevel.exclude := List.map (fun e -> match e with JString s -> s | _ -> assert false) exclude; + let methods = Hashtbl.fold (fun k _ acc -> (jstring k) :: acc) h [] in + hctx.send_result (JObject [ + "methods",jarray methods; + "haxeVersion",jobject [ + "major",jint version_major; + "minor",jint version_minor; + "patch",jint version_revision; + "pre",(match version_pre with None -> jnull | Some pre -> jstring pre); + "build",(match Version.version_extra with None -> jnull | Some(_,build) -> jstring build); + ]; + "protocolVersion",jobject [ + "major",jint 0; + "minor",jint 2; + "patch",jint 0; + ] + ]) + ); + "display/completionItem/resolve", (fun hctx -> + let i = hctx.jsonrpc#get_int_param "index" in + begin try + let item = (!DisplayException.last_completion_result).(i) in + let ctx = Genjson.create_context GMFull in + hctx.send_result (jobject ["item",CompletionItem.to_json ctx None item]) + with Invalid_argument _ -> + hctx.send_error [jstring (Printf.sprintf "Invalid index: %i" i)] + end + ); + "display/completion", (fun hctx -> + hctx.display#set_display_file (hctx.jsonrpc#get_bool_param "wasAutoTriggered") true; + hctx.display#enable_display DMDefault; + ); + "display/definition", (fun hctx -> + Common.define hctx.com Define.NoCOpt; + hctx.display#set_display_file false true; + hctx.display#enable_display DMDefinition; + ); + "display/typeDefinition", (fun hctx -> + Common.define hctx.com Define.NoCOpt; + hctx.display#set_display_file false true; + hctx.display#enable_display DMTypeDefinition; + ); + "display/references", (fun hctx -> + Common.define hctx.com Define.NoCOpt; + hctx.display#set_display_file false true; + hctx.display#enable_display (DMUsage false); + ); + "display/hover", (fun hctx -> + Common.define hctx.com Define.NoCOpt; + hctx.display#set_display_file false true; + hctx.display#enable_display DMHover; + ); + "display/package", (fun hctx -> + hctx.display#set_display_file false false; + hctx.display#enable_display DMPackage; + ); + "display/signatureHelp", (fun hctx -> + hctx.display#set_display_file (hctx.jsonrpc#get_bool_param "wasAutoTriggered") true; + hctx.display#enable_display DMSignature + ); + "server/readClassPaths", (fun hctx -> + hctx.com.callbacks#add_after_init_macros (fun () -> + CompilationServer.set_initialized hctx.display#get_cs; + DisplayToplevel.read_class_paths hctx.com ["init"]; + let files = CompilationServer.get_files hctx.display#get_cs in + hctx.send_result (jobject [ + "files", jint (Hashtbl.length files) + ]); + ) + ); + "server/contexts", (fun hctx -> + let l = List.map (fun (sign,csign) -> csign.cs_json) (CompilationServer.get_signs hctx.display#get_cs) in + hctx.send_result (jarray l) + ); + "server/modules", (fun hctx -> + let sign = Digest.from_hex (hctx.jsonrpc#get_string_param "signature") in + let l = Hashtbl.fold (fun (_,sign') m acc -> + if sign = sign' && m.m_extra.m_kind <> MFake then jstring (s_type_path m.m_path) :: acc else acc + ) hctx.display#get_cs.cache.c_modules [] in + hctx.send_result (jarray l) + ); + "server/module", (fun hctx -> + let sign = Digest.from_hex (hctx.jsonrpc#get_string_param "signature") in + let path = Path.parse_path (hctx.jsonrpc#get_string_param "path") in + let m = try + CompilationServer.find_module hctx.display#get_cs (path,sign) + with Not_found -> + hctx.send_error [jstring "No such module"] + in + hctx.send_result (generate_module () m) + ); + "server/moduleCreated", (fun hctx -> + let file = hctx.jsonrpc#get_string_param "file" in + let file = Path.unique_full_path file in + let cs = hctx.display#get_cs in + List.iter (fun (sign,_) -> + Hashtbl.replace cs.cache.c_removed_files (file,sign) () + ) (CompilationServer.get_signs cs); + hctx.send_result (jstring file); + ); + "server/files", (fun hctx -> + let sign = Digest.from_hex (hctx.jsonrpc#get_string_param "signature") in + let files = CompilationServer.get_files hctx.display#get_cs in + let files = Hashtbl.fold (fun (file,sign') decls acc -> if sign = sign' then (file,decls) :: acc else acc) files [] in + let files = List.sort (fun (file1,_) (file2,_) -> compare file1 file2) files in + let files = List.map (fun (file,cfile) -> + jobject [ + "file",jstring file; + "time",jfloat cfile.c_time; + "pack",jstring (String.concat "." cfile.c_package); + "moduleName",jopt jstring cfile.c_module_name; + ] + ) files in + hctx.send_result (jarray files) + ); + "server/invalidate", (fun hctx -> + let file = hctx.jsonrpc#get_string_param "file" in + let file = Path.unique_full_path file in + let cs = hctx.display#get_cs in + CompilationServer.taint_modules cs file; + CompilationServer.remove_files cs file; + hctx.send_result jnull + ); + "server/configure", (fun hctx -> + let l = ref (List.map (fun (name,value) -> + let value = hctx.jsonrpc#get_bool "value" value in + try + ServerMessage.set_by_name name value; + jstring (Printf.sprintf "Printing %s %s" name (if value then "enabled" else "disabled")) + with Not_found -> + hctx.send_error [jstring ("Invalid print parame name: " ^ name)] + ) (hctx.jsonrpc#get_opt_param (fun () -> (hctx.jsonrpc#get_object_param "print")) [])) in + hctx.jsonrpc#get_opt_param (fun () -> + let b = hctx.jsonrpc#get_bool_param "noModuleChecks" in + ServerConfig.do_not_check_modules := b; + l := jstring ("Module checks " ^ (if b then "disabled" else "enabled")) :: !l; + () + ) (); + hctx.send_result (jarray !l) + ); + "server/memory",(fun hctx -> + let j = DisplayOutput.Memory.get_memory_json hctx.display#get_cs in + hctx.send_result j + ); + (* TODO: wait till gama complains about the naming, then change it to something else *) + "typer/compiledTypes", (fun hctx -> + hctx.com.callbacks#add_after_filters (fun () -> + let ctx = create_context GMFull in + let l = List.map (generate_module_type ctx) hctx.com.types in + hctx.send_result (jarray l) + ); + ); + ] in + List.iter (fun (s,f) -> Hashtbl.add h s f) l; + h + +let parse_input com input report_times = + let input = + JsonRpc.handle_jsonrpc_error (fun () -> JsonRpc.parse_request input) send_json + in + let jsonrpc = new jsonrpc_handler input in + + let send_result json = + let fl = [ + "result",json; + "timestamp",jfloat (Unix.gettimeofday ()); + ] in + let fl = if !report_times then begin + close_times(); + let _,_,root = Timer.build_times_tree () in + begin match json_of_times root with + | None -> fl + | Some jo -> ("timers",jo) :: fl + end + end else fl in + let fl = if DynArray.length com.pass_debug_messages > 0 then + ("passMessages",jarray (List.map jstring (DynArray.to_list com.pass_debug_messages))) :: fl + else + fl + in + let jo = jobject fl in + send_json (JsonRpc.result jsonrpc#get_id jo) + in + + let send_error jl = + send_json (JsonRpc.error jsonrpc#get_id 0 ~data:(Some (JArray jl)) "Compiler error") + in + + com.json_out <- Some(send_result,send_error,jsonrpc); + + let cs = match CompilationServer.get() with + | Some cs -> cs + | None -> send_error [jstring "compilation server not running for some reason"]; + in + + let display = new display_handler jsonrpc com cs in + + let hctx = { + com = com; + jsonrpc = jsonrpc; + display = display; + send_result = send_result; + send_error = send_error; + } in + + JsonRpc.handle_jsonrpc_error (fun () -> + let method_name = jsonrpc#get_method_name in + let f = try + Hashtbl.find handler method_name + with Not_found -> + raise_method_not_found jsonrpc#get_id method_name + in + f hctx + ) send_json diff --git a/src/context/display/displayToplevel.ml b/src/context/display/displayToplevel.ml new file mode 100644 index 00000000000..5045678dc9f --- /dev/null +++ b/src/context/display/displayToplevel.ml @@ -0,0 +1,460 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*) +open Ast +open Common +open CompilationServer +open Type +open Typecore +open CompletionItem +open ClassFieldOrigin +open DisplayTypes +open DisplayEmitter +open Genjson +open Globals + +let exclude : string list ref = ref [] + +let explore_class_paths com timer class_paths recusive f_pack f_module = + let rec loop dir pack = + let dot_path = (String.concat "." (List.rev pack)) in + begin + if (List.mem dot_path !exclude) then + () + else try + let entries = Sys.readdir dir in + Array.iter (fun file -> + match file with + | "." | ".." -> + () + | _ when Sys.is_directory (dir ^ file) && file.[0] >= 'a' && file.[0] <= 'z' -> + begin try + begin match PMap.find file com.package_rules with + | Forbidden | Remap _ -> () + | _ -> raise Not_found + end + with Not_found -> + f_pack (List.rev pack,file); + if recusive then loop (dir ^ file ^ "/") (file :: pack) + end + | _ -> + let l = String.length file in + if l > 3 && String.sub file (l - 3) 3 = ".hx" then begin + try + let name = String.sub file 0 (l - 3) in + let path = (List.rev pack,name) in + let dot_path = if dot_path = "" then name else dot_path ^ "." ^ name in + if (List.mem dot_path !exclude) then () else f_module path; + with _ -> + () + end + ) entries; + with Sys_error _ -> + () + end + in + let t = Timer.timer (timer @ ["class path exploration"]) in + List.iter (fun dir -> loop dir []) class_paths; + t() + +let read_class_paths com timer = + let sign = Define.get_signature com.defines in + explore_class_paths com timer (List.filter ((<>) "") com.class_path) true (fun _ -> ()) (fun path -> + let file,_,pack,_ = Display.parse_module' com path Globals.null_pos in + match CompilationServer.get() with + | Some cs when pack <> fst path -> + let file = Path.unique_full_path file in + CompilationServer.remove_file_for_real cs (file,sign) + | _ -> + () + ) + +let init_or_update_server cs com timer_name = + if not (CompilationServer.is_initialized cs) then begin + CompilationServer.set_initialized cs; + read_class_paths com timer_name + end else begin + (* Iterate all removed files of the current context. If they aren't part of the context again, + re-parse them and remove them from c_removed_files. *) + let sign = Define.get_signature com.defines in + let removed_removed_files = DynArray.create () in + Hashtbl.iter (fun (file,sign') () -> + if sign = sign' then begin + DynArray.add removed_removed_files (file,sign'); + try + ignore(find_file cs (file,sign)); + with Not_found -> + try ignore(TypeloadParse.parse_module_file com file null_pos) with _ -> () + end; + ) cs.cache.c_removed_files; + DynArray.iter (Hashtbl.remove cs.cache.c_removed_files) removed_removed_files; + end + +module CollectionContext = struct + open ImportStatus + + type t = { + ctx : typer; + items : CompletionItem.t DynArray.t; + names : (string,CompletionItem.t) Hashtbl.t; + paths : (Globals.path,bool) Hashtbl.t; + } + + let create ctx = { + ctx = ctx; + items = DynArray.create (); + names = Hashtbl.create 0; + paths = Hashtbl.create 0; + } + + let add_item ctx item name = + DynArray.add ctx.items item; + match name with + | None -> () + | Some name -> Hashtbl.replace ctx.names name item + + let get_import_status ctx is_import path = + try + let _ = Hashtbl.find ctx.names (snd path) in + (* TODO: do we have to check if we get the same thing? *) + Shadowed + with Not_found -> + let check_wildcard () = + List.exists (fun (sl,_) -> (sl,snd path) = path) ctx.ctx.m.wildcard_packages + in + if is_import || (fst path = []) || check_wildcard () then Imported else Unimported + + let is_qualified ctx name = + not (Hashtbl.mem ctx.names name) + + let path_exists ctx path = Hashtbl.mem ctx.paths path + let add_path ctx path = Hashtbl.add ctx.paths path true +end + +open CollectionContext + +(* +1 for each matching package part. 0 = no common part *) +let pack_similarity pack1 pack2 = + let rec loop count pack1 pack2 = match pack1,pack2 with + | [],[] -> count + | (s1 :: pack1),(s2 :: pack2) when s1 = s2 -> loop (count + 1) pack1 pack2 + | _ -> count + in + loop 0 pack1 pack2 + +(* Returns `true` if `pack1` contains or is `pack2` *) +let pack_contains pack1 pack2 = + let rec loop pack1 pack2 = match pack1,pack2 with + | [],_ -> true + | (s1 :: pack1),(s2 :: pack2) when s1 = s2 -> loop pack1 pack2 + | _ -> false + in + loop pack1 pack2 + +let is_pack_visible pack = + not (List.exists (fun s -> String.length s > 0 && s.[0] = '_') pack) + +let collect ctx tk with_type = + let t = Timer.timer ["display";"toplevel"] in + let cctx = CollectionContext.create ctx in + let curpack = fst ctx.curclass.cl_path in + let packages = Hashtbl.create 0 in + let add_package path = Hashtbl.replace packages path true in + + let add item name = add_item cctx item name in + + let add_type mt = + match mt with + | TClassDecl {cl_kind = KAbstractImpl _} -> () + | _ -> + let path = (t_infos mt).mt_path in + let mname = snd (t_infos mt).mt_module.m_path in + let path = if snd path = mname then path else (fst path @ [mname],snd path) in + if not (path_exists cctx path) then begin + Display.merge_core_doc ctx mt; + let is = get_import_status cctx true path in + if not (Meta.has Meta.NoCompletion (t_infos mt).mt_meta) then begin + add (make_ci_type (CompletionModuleType.of_module_type mt) is None) (Some (snd path)); + add_path cctx path; + end + end + in + + let process_decls pack name decls = + let added_something = ref false in + let add item name = + added_something := true; + add item name + in + let run () = List.iter (fun (d,p) -> + begin try + let tname,is_private,meta = match d with + | EClass d -> fst d.d_name,List.mem HPrivate d.d_flags,d.d_meta + | EEnum d -> fst d.d_name,List.mem EPrivate d.d_flags,d.d_meta + | ETypedef d -> fst d.d_name,List.mem EPrivate d.d_flags,d.d_meta + | EAbstract d -> fst d.d_name,List.mem AbPrivate d.d_flags,d.d_meta + | _ -> raise Exit + in + let path = Path.full_dot_path pack name tname in + if not (path_exists cctx path) && not is_private && not (Meta.has Meta.NoCompletion meta) then begin + add_path cctx path; + (* If we share a package, the module's main type shadows everything with the same name. *) + let shadowing_name = if pack_contains pack curpack && tname = name then (Some name) else None in + (* Also, this means we can access it as if it was imported (assuming it's not shadowed by something else. *) + let is = get_import_status cctx (shadowing_name <> None) path in + add (make_ci_type (CompletionModuleType.of_type_decl pack name (d,p)) is None) shadowing_name + end + with Exit -> + () + end + ) decls in + if is_pack_visible pack then run(); + !added_something + in + + (* Collection starts here *) + + let tpair ?(values=PMap.empty) t = + let ct = DisplayEmitter.completion_type_of_type ctx ~values t in + (t,ct) + in + begin match tk with + | TKType | TKOverride -> () + | TKExpr p | TKPattern p | TKField p -> + (* locals *) + PMap.iter (fun _ v -> + if not (is_gen_local v) then + add (make_ci_local v (tpair ~values:(get_value_meta v.v_meta) v.v_type)) (Some v.v_name) + ) ctx.locals; + + let add_field scope origin cf = + let is_qualified = is_qualified cctx cf.cf_name in + add (make_ci_class_field (CompletionClassField.make cf scope origin is_qualified) (tpair ~values:(get_value_meta cf.cf_meta) cf.cf_type)) (Some cf.cf_name) + in + let maybe_add_field scope origin cf = + if not (Meta.has Meta.NoCompletion cf.cf_meta) then add_field scope origin cf + in + (* member fields *) + if ctx.curfun <> FunStatic then begin + let all_fields = Type.TClass.get_all_fields ctx.curclass (List.map snd ctx.curclass.cl_params) in + PMap.iter (fun _ (c,cf) -> + let origin = if c == ctx.curclass then Self (TClassDecl c) else Parent (TClassDecl c) in + maybe_add_field CFSMember origin cf + ) all_fields; + (* TODO: local using? *) + end; + + (* statics *) + begin match ctx.curclass.cl_kind with + | KAbstractImpl ({a_impl = Some c} as a) -> + let origin = Self (TAbstractDecl a) in + List.iter (fun cf -> + if Meta.has Meta.Impl cf.cf_meta then begin + if ctx.curfun = FunStatic then () + else begin + let cf = prepare_using_field cf in + maybe_add_field CFSMember origin cf + end + end else + maybe_add_field CFSStatic origin cf + ) c.cl_ordered_statics + | _ -> + List.iter (maybe_add_field CFSStatic (Self (TClassDecl ctx.curclass))) ctx.curclass.cl_ordered_statics + end; + + (* enum constructors *) + let rec enum_ctors t = + match t with + | TAbstractDecl ({a_impl = Some c} as a) when Meta.has Meta.Enum a.a_meta && not (path_exists cctx a.a_path) && ctx.curclass != c -> + add_path cctx a.a_path; + List.iter (fun cf -> + let ccf = CompletionClassField.make cf CFSMember (Self (decl_of_class c)) true in + if (Meta.has Meta.Enum cf.cf_meta) && not (Meta.has Meta.NoCompletion cf.cf_meta) then + add (make_ci_enum_abstract_field a ccf (tpair cf.cf_type)) (Some cf.cf_name); + ) c.cl_ordered_statics + | TTypeDecl t -> + begin match follow t.t_type with + | TEnum (e,_) -> enum_ctors (TEnumDecl e) + | _ -> () + end + | TEnumDecl e when not (path_exists cctx e.e_path) -> + add_path cctx e.e_path; + let origin = Self (TEnumDecl e) in + PMap.iter (fun _ ef -> + let is_qualified = is_qualified cctx ef.ef_name in + add (make_ci_enum_field (CompletionEnumField.make ef origin is_qualified) (tpair ef.ef_type)) (Some ef.ef_name) + ) e.e_constrs; + | _ -> + () + in + List.iter enum_ctors ctx.m.curmod.m_types; + List.iter enum_ctors (List.map fst ctx.m.module_types); + + (* enum constructors of expected type *) + begin match with_type with + | WithType.WithType(t,_) -> + (try enum_ctors (module_type_of_type t) with Exit -> ()) + | _ -> () + end; + + (* imported globals *) + PMap.iter (fun name (mt,s,_) -> + try + let is_qualified = is_qualified cctx name in + let class_import c = + let cf = PMap.find s c.cl_statics in + let cf = if name = cf.cf_name then cf else {cf with cf_name = name} in + let decl,make = match c.cl_kind with + | KAbstractImpl a -> TAbstractDecl a, + if Meta.has Meta.Enum cf.cf_meta then make_ci_enum_abstract_field a else make_ci_class_field + | _ -> TClassDecl c,make_ci_class_field + in + let origin = StaticImport decl in + add (make (CompletionClassField.make cf CFSStatic origin is_qualified) (tpair ~values:(get_value_meta cf.cf_meta) cf.cf_type)) (Some name) + in + match resolve_typedef mt with + | TClassDecl c -> class_import c; + | TEnumDecl en -> + let ef = PMap.find s en.e_constrs in + let ef = if name = ef.ef_name then ef else {ef with ef_name = name} in + let origin = StaticImport (TEnumDecl en) in + add (make_ci_enum_field (CompletionEnumField.make ef origin is_qualified) (tpair ef.ef_type)) (Some s) + | TAbstractDecl {a_impl = Some c} -> class_import c; + | _ -> raise Not_found + with Not_found -> + () + ) ctx.m.module_globals; + + (* literals *) + add (make_ci_literal "null" (tpair t_dynamic)) (Some "null"); + add (make_ci_literal "true" (tpair ctx.com.basic.tbool)) (Some "true"); + add (make_ci_literal "false" (tpair ctx.com.basic.tbool)) (Some "false"); + begin match ctx.curfun with + | FunMember | FunConstructor | FunMemberClassLocal -> + let t = TInst(ctx.curclass,List.map snd ctx.curclass.cl_params) in + add (make_ci_literal "this" (tpair t)) (Some "this"); + begin match ctx.curclass.cl_super with + | Some(c,tl) -> add (make_ci_literal "super" (tpair (TInst(c,tl)))) (Some "super") + | None -> () + end + | _ -> + () + end; + + (* keywords *) + let kwds = [ + Function; Var; Final; If; Else; While; Do; For; Break; Return; Continue; Switch; + Try; New; Throw; Untyped; Cast; Inline; + ] in + List.iter (fun kwd -> add(make_ci_keyword kwd) (Some (s_keyword kwd))) kwds; + + (* builtins *) + add (make_ci_literal "trace" (tpair (TFun(["value",false,t_dynamic],ctx.com.basic.tvoid)))) (Some "trace") + end; + + (* type params *) + List.iter (fun (s,t) -> match follow t with + | TInst(c,_) -> + add (make_ci_type_param c (tpair t)) (Some (snd c.cl_path)) + | _ -> assert false + ) ctx.type_params; + + (* module types *) + List.iter add_type ctx.m.curmod.m_types; + + (* module imports *) + List.iter add_type (List.rev_map fst ctx.m.module_types); (* reverse! *) + + (* types from files *) + begin match !CompilationServer.instance with + | None -> + (* offline: explore class paths *) + let class_paths = ctx.com.class_path in + let class_paths = List.filter (fun s -> s <> "") class_paths in + explore_class_paths ctx.com ["display";"toplevel"] class_paths true add_package (fun path -> + if not (path_exists cctx path) then begin + let _,decls = Display.parse_module ctx path Globals.null_pos in + ignore(process_decls (fst path) (snd path) decls) + end + ) + | Some cs -> + (* online: iter context files *) + init_or_update_server cs ctx.com ["display";"toplevel"]; + let files = CompilationServer.get_file_list cs ctx.com in + (* Sort files by reverse distance of their package to our current package. *) + let files = List.map (fun (file,cfile) -> + let i = pack_similarity curpack cfile.c_package in + (file,cfile),i + ) files in + let files = List.sort (fun (_,i1) (_,i2) -> -compare i1 i2) files in + let check_package pack = match List.rev pack with + | [] -> () + | s :: sl -> add_package (List.rev sl,s) + in + List.iter (fun ((file,cfile),_) -> + let module_name = CompilationServer.get_module_name_of_cfile file cfile in + let dot_path = s_type_path (cfile.c_package,module_name) in + if (List.exists (fun e -> ExtString.String.starts_with dot_path (e ^ ".")) !exclude) then + () + else begin + Hashtbl.replace ctx.com.module_to_file (cfile.c_package,module_name) file; + if process_decls cfile.c_package module_name cfile.c_decls then check_package cfile.c_package; + end + ) files; + List.iter (fun file -> + try + let lib = Hashtbl.find cs.cache.c_native_libs file in + Hashtbl.iter (fun path (pack,decls) -> + if process_decls pack (snd path) decls then check_package pack; + ) lib.c_nl_files + with Not_found -> + () + ) ctx.com.native_libs.all_libs + end; + + (* packages *) + Hashtbl.iter (fun path _ -> + let full_pack = fst path @ [snd path] in + if is_pack_visible full_pack then add (make_ci_package path []) (Some (snd path)) + ) packages; + + (* sorting *) + let l = DynArray.to_list cctx.items in + let l = sort_fields l with_type tk in + t(); + l + +let collect_and_raise ctx tk with_type cr subject pinsert = + let fields = match !DisplayException.last_completion_pos with + | Some p' when (pos subject).pmin = p'.pmin -> + Array.to_list (!DisplayException.last_completion_result) + | _ -> + collect ctx tk with_type + in + DisplayException.raise_fields2 fields cr pinsert subject + +let handle_unresolved_identifier ctx i p only_types = + let l = collect ctx (if only_types then TKType else TKExpr p) NoValue in + let cl = List.map (fun it -> + let s = CompletionItem.get_name it in + let i = StringError.levenshtein i s in + (s,it,i),i + ) l in + let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in + let cl = StringError.filter_similar (fun (s,_,_) r -> r <= (min (String.length s) (String.length i)) / 3) cl in + ctx.com.display_information.unresolved_identifiers <- (i,p,cl) :: ctx.com.display_information.unresolved_identifiers diff --git a/src/context/display/documentSymbols.ml b/src/context/display/documentSymbols.ml new file mode 100644 index 00000000000..9efc32c0476 --- /dev/null +++ b/src/context/display/documentSymbols.ml @@ -0,0 +1,123 @@ +open Ast + +open DisplayTypes.SymbolKind + +let collect_module_symbols with_locals (pack,decls) = + let l = DynArray.create() in + let add name kind location parent = + let si = DisplayTypes.SymbolInformation.make name kind location (if parent = "" then None else Some parent) in + DynArray.add l si; + in + let rec expr parent (e,p) = + let add name kind location = add name kind location parent in + begin match e with + | EVars vl -> + List.iter (fun ((s,p),_,_,eo) -> + add s Variable p; + expr_opt parent eo + ) vl + | ETry(e1,catches) -> + expr parent e1; + List.iter (fun ((s,p),_,e,_) -> + add s Variable p; + expr parent e + ) catches; + | EFunction(Some (s,_),f) -> + add s Function p; + func parent f + | EBinop(OpIn,(EConst(Ident s),p),e2) -> + add s Variable p; + expr parent e2; + | _ -> + iter_expr (expr parent) (e,p) + end + and expr_opt parent eo = match eo with + | None -> () + | Some e -> expr parent e + and func parent f = + List.iter (fun ((s,p),_,_,_,eo) -> + add s Variable p parent; + expr_opt parent eo + ) f.f_args; + expr_opt parent f.f_expr + in + let field parent cff = + let field_parent = parent ^ "." ^ (fst cff.cff_name) in + match cff.cff_kind with + | FVar(_,eo) -> + add (fst cff.cff_name) Field cff.cff_pos parent; + if with_locals then expr_opt field_parent eo + | FFun f -> + add (fst cff.cff_name) (if fst cff.cff_name = "new" then Constructor else Method) cff.cff_pos parent; + if with_locals then func field_parent f + | FProp(_,_,_,eo) -> + add (fst cff.cff_name) Property cff.cff_pos parent; + if with_locals then expr_opt field_parent eo + in + List.iter (fun (td,p) -> match td with + | EImport _ | EUsing _ -> + () (* TODO: Can we do anything with these? *) + | EClass d -> + add (fst d.d_name) (if List.mem HInterface d.d_flags then Interface else Class) p ""; + List.iter (field (fst d.d_name)) d.d_data + | EEnum d -> + add (fst d.d_name) Enum p ""; + List.iter (fun ef -> + add (fst ef.ec_name) Method ef.ec_pos (fst d.d_name) + ) d.d_data + | ETypedef d -> + add (fst d.d_name) Typedef p ""; + (match d.d_data with + | CTAnonymous fields,_ -> + List.iter (field (fst d.d_name)) fields + | _ -> ()) + | EAbstract d -> + add (fst d.d_name) Abstract p ""; + List.iter (field (fst d.d_name)) d.d_data + ) decls; + l + +module Printer = struct + open Json + open DisplayTypes.SymbolKind + open DisplayTypes.SymbolInformation + + let print_module_symbols com symbols filter = + let regex = Option.map Str.regexp_case_fold filter in + let reported = Hashtbl.create 0 in + let add si = + if Hashtbl.mem reported si.pos then false + else begin + let b = match regex with + | None -> true + | Some regex -> (try ignore(Str.search_forward regex si.name 0); true with Not_found -> false) + in + Hashtbl.replace reported si.pos true; + b + end + in + let ja = List.fold_left (fun acc (file,l) -> + let jl = ExtList.List.filter_map (fun si -> + if not (add si) then + None + else begin + let l = + ("name",JString si.name) :: + ("kind",JInt (to_int si.kind)) :: + ("range", Genjson.generate_pos_as_range si.pos) :: + (match si.container_name with None -> [] | Some s -> ["containerName",JString s]) + in + Some (JObject l) + end + ) (DynArray.to_list l) in + if jl = [] then + acc + else + (JObject [ + "file",JString file; + "symbols",JArray jl + ]) :: acc + ) [] symbols in + let js = JArray ja in + string_of_json js +end \ No newline at end of file diff --git a/src/context/display/findReferences.ml b/src/context/display/findReferences.ml new file mode 100644 index 00000000000..e4f3d099768 --- /dev/null +++ b/src/context/display/findReferences.ml @@ -0,0 +1,192 @@ +open Globals +open Ast +open DisplayTypes +open Common +open Typecore +open CompilationServer +open ImportHandling + +let find_possible_references kind name (pack,decls) = + (* Employ some heuristics: We know what kind of symbol we are looking for, so let's + filter where we can. *) + let check kind' name' = + if name = name' then match kind',kind with + | KIdent,_ + | KAnyField,(KAnyField | KClassField | KEnumField) + | KClassField,KClassField + | KEnumField,KEnumField + | KModuleType,KModuleType + | KConstructor,(KConstructor | KModuleType) -> + raise Exit + | _ -> + () + in + let rec type_path kind path = + check KModuleType path.tname; + Option.may (check KModuleType) path.tsub; + List.iter (function + | TPType th -> type_hint th + | TPExpr e -> expr e + ) path.tparams + and type_hint th = match fst th with + | CTPath path -> type_path KModuleType path + | CTParent th | CTOptional th | CTNamed(_,th) -> type_hint th + | CTFunction(thl,th) -> + List.iter type_hint thl; + type_hint th; + | CTAnonymous cffl -> + List.iter field cffl + | CTExtend(tl,cffl) -> + List.iter (fun (path,_) -> type_path KModuleType path) tl; + List.iter field cffl; + | CTIntersection tl -> + List.iter type_hint tl + and type_param tp = + List.iter type_param tp.tp_params; + Option.may type_hint tp.tp_constraints + and expr (e,p) = + begin match e with + | EConst(Ident s) -> + check KIdent s + | EField(e1,s) -> + expr e1; + check KAnyField s; + | EVars vl -> + List.iter (fun (_,_,tho,eo) -> + Option.may type_hint tho; + expr_opt eo + ) vl; + | ECast(e1,tho) -> + expr e1; + Option.may type_hint tho; + | ENew((path,_),el) -> + type_path KConstructor path; + List.iter expr el; + | EFunction(_,f) -> + func f + | ETry(e1,catches) -> + expr e1; + List.iter (fun (_,th,e,_) -> + type_hint th; + expr e + ) catches; + | ECheckType(e1,th) -> + expr e1; + type_hint th; + | _ -> + iter_expr expr (e,p) + end + and expr_opt eo = match eo with + | None -> () + | Some e -> expr e + and func f = + List.iter (fun ((s,p),_,_,tho,eo) -> + Option.may type_hint tho; + expr_opt eo + ) f.f_args; + List.iter type_param f.f_params; + Option.may type_hint f.f_type; + expr_opt f.f_expr + and field cff = + check KClassField (fst cff.cff_name); + match cff.cff_kind with + | FVar(tho,eo) -> + Option.may type_hint tho; + expr_opt eo + | FFun f -> + func f + | FProp(_,_,tho,eo) -> + Option.may type_hint tho; + expr_opt eo + in + List.iter (fun (td,p) -> match td with + | EImport(path,_) | EUsing path -> + begin match fst (ImportHandling.convert_import_to_something_usable null_pos path) with + | IDKModule(_,s) -> check KModuleType s + | IDKSubType(_,s1,s2) -> + check KModuleType s1; + check KModuleType s2; + | IDKSubTypeField(_,s1,s2,s3) -> + check KModuleType s1; + check KModuleType s2; + check KAnyField s3; + | IDKModuleField(_,s1,s2) -> + check KModuleType s1; + check KAnyField s2; + | IDKPackage _ | IDK -> + () + end; + | EClass d -> + check KModuleType (fst d.d_name); + List.iter (function + | HExtends(path,_) | HImplements(path,_) -> type_path KModuleType path + | _ -> () + ) d.d_flags; + List.iter type_param d.d_params; + List.iter field d.d_data + | EEnum d -> + check KModuleType (fst d.d_name); + List.iter (fun ef -> + Option.may type_hint ef.ec_type; + check KEnumField (fst ef.ec_name); + List.iter type_param ef.ec_params; + ) d.d_data; + List.iter type_param d.d_params; + | ETypedef d -> + check KModuleType (fst d.d_name); + List.iter type_param d.d_params; + type_hint d.d_data; + | EAbstract d -> + check KModuleType (fst d.d_name); + List.iter field d.d_data; + List.iter type_param d.d_params; + List.iter (function + | AbFrom th | AbTo th | AbOver th -> type_hint th + | _ -> () + ) d.d_flags; + ) decls + +let find_possible_references tctx cs = + let name,pos,kind = Display.ReferencePosition.get () in + DisplayToplevel.init_or_update_server cs tctx.com ["display";"references"]; + let files = CompilationServer.get_file_list cs tctx.com in + let t = Timer.timer ["display";"references";"candidates"] in + List.iter (fun (file,cfile) -> + let module_name = CompilationServer.get_module_name_of_cfile file cfile in + if not (CompilationServer.is_cached_module cs tctx.com (cfile.c_package,module_name)) then try + find_possible_references kind name (cfile.c_package,cfile.c_decls); + with Exit -> + begin try + ignore(tctx.g.do_load_module tctx (cfile.c_package,module_name) null_pos); + (* We have to flush immediately so we catch exceptions from weird modules *) + Typecore.flush_pass tctx Typecore.PFinal "final"; + with _ -> + () + end + ) files; + t(); + () + +let find_references tctx com with_definition = + let name,pos,kind = Display.ReferencePosition.get () in + let t = Timer.timer ["display";"references";"collect"] in + let symbols,relations = Statistics.collect_statistics tctx (SFPos pos) in + t(); + let rec loop acc relations = match relations with + | (Statistics.Referenced,p) :: relations -> loop (p :: acc) relations + | _ :: relations -> loop acc relations + | [] -> acc + in + let t = Timer.timer ["display";"references";"filter"] in + let usages = Hashtbl.fold (fun p sym acc -> + let acc = if with_definition then p :: acc else acc in + (try loop acc (Hashtbl.find relations p) + with Not_found -> acc) + ) symbols [] in + let usages = List.sort (fun p1 p2 -> + let c = compare p1.pfile p2.pfile in + if c <> 0 then c else compare p1.pmin p2.pmin + ) usages in + t(); + Display.ReferencePosition.set ("",null_pos,KVar); + DisplayException.raise_positions usages \ No newline at end of file diff --git a/src/context/display/importHandling.ml b/src/context/display/importHandling.ml new file mode 100644 index 00000000000..14ea6e1021d --- /dev/null +++ b/src/context/display/importHandling.ml @@ -0,0 +1,59 @@ +open Globals +open Ast +open DisplayPosition +open Common +open Typecore + +type import_display_kind = + | IDKPackage of string list + | IDKModule of string list * string + | IDKSubType of string list * string * string + | IDKModuleField of string list * string * string + | IDKSubTypeField of string list * string * string * string + | IDK + +type import_display = import_display_kind * pos + +let convert_import_to_something_usable pt path = + let rec loop pack m t = function + | (s,p) :: l -> + let is_lower = is_lower_ident s in + let is_display_pos = encloses_position pt p in + begin match is_lower,m,t with + | _,None,Some _ -> + assert false (* impossible, I think *) + | true,Some m,None -> + if is_display_pos then (IDKModuleField(List.rev pack,m,s),p) + else (IDK,p) (* assume that we're done *) + | _,Some m,Some t -> + if is_display_pos then (IDKSubTypeField(List.rev pack,m,t,s),p) + else (IDK,p) + | true,None,None -> + if is_display_pos then (IDKPackage (List.rev (s :: pack)),p) + else loop (s :: pack) m t l + | false,Some sm,None -> + if is_display_pos then (IDKSubType (List.rev pack,sm,s),p) + else loop pack m (Some s) l + | false,None,None -> + if is_display_pos then (IDKModule (List.rev pack,s),p) + else loop pack (Some s) None l + end + | [] -> + (IDK,null_pos) + in + loop [] None None path + +let add_import_position com p path = + let infos = com.shared.shared_display_information in + if not (PMap.mem p infos.import_positions) then + infos.import_positions <- PMap.add p (ref false,path) infos.import_positions + +let mark_import_position com p = + try + let r = fst (PMap.find p com.shared.shared_display_information.import_positions) in + r := true + with Not_found -> + () + +let maybe_mark_import_position ctx p = + if Diagnostics.is_diagnostics_run p then mark_import_position ctx.com p \ No newline at end of file diff --git a/src/context/display/statistics.ml b/src/context/display/statistics.ml new file mode 100644 index 00000000000..ae2d743e352 --- /dev/null +++ b/src/context/display/statistics.ml @@ -0,0 +1,292 @@ +open Globals +open Ast +open Type +open Common +open Typecore + +open ImportHandling + +type relation = + | Implemented + | Extended + | Overridden + | Referenced + +type symbol = + | SKClass of tclass + | SKInterface of tclass + | SKEnum of tenum + | SKTypedef of tdef + | SKAbstract of tabstract + | SKField of tclass_field + | SKEnumField of tenum_field + | SKVariable of tvar + +type statistics_filter = + | SFNone + | SFPos of pos + | SFFile of string + +let collect_statistics ctx pfilter = + let relations = Hashtbl.create 0 in + let symbols = Hashtbl.create 0 in + let handled_modules = Hashtbl.create 0 in + let full_path = + let paths = Hashtbl.create 0 in + (fun path -> + try + Hashtbl.find paths path + with Not_found -> + let unique = Path.unique_full_path path in + Hashtbl.add paths path unique; + unique + ) + in + let check_pos = match pfilter with + | SFNone -> (fun p -> p <> null_pos) + | SFPos p -> (fun p' -> p.pmin = p'.pmin && p.pmax = p'.pmax && p.pfile = full_path p'.pfile) + | SFFile s -> (fun p -> full_path p.pfile = s) + in + let add_relation p r = + if check_pos p then try + let l = Hashtbl.find relations p in + if not (List.mem r l) then + Hashtbl.replace relations p (r :: l) + with Not_found -> + Hashtbl.add relations p [r] + in + let declare kind p = + if check_pos p then begin + if not (Hashtbl.mem relations p) then Hashtbl.add relations p []; + Hashtbl.replace symbols p kind; + end + in + let collect_overrides c = + List.iter (fun cf -> + let rec loop c = match c.cl_super with + | Some (c,_) -> + begin try + let cf' = PMap.find cf.cf_name c.cl_fields in + add_relation cf'.cf_name_pos (Overridden,cf.cf_pos) + with Not_found -> + loop c + end + | _ -> + () + in + loop c + ) c.cl_overrides + in + let rec find_real_constructor c = match c.cl_constructor,c.cl_super with + (* The pos comparison might be a bit weak, not sure... *) + | Some cf,_ when not (Meta.has Meta.CompilerGenerated cf.cf_meta) && c.cl_pos <> cf.cf_pos -> cf + | _,Some(c,_) -> find_real_constructor c + | _,None -> raise Not_found + in + let var_decl v = declare (SKVariable v) v.v_pos in + let patch_string_pos p s = { p with pmin = p.pmax - String.length s } in + let field_reference cf p = + add_relation cf.cf_name_pos (Referenced,patch_string_pos p cf.cf_name) + in + let collect_references c e = + let rec loop e = match e.eexpr with + | TField(e1,fa) -> + (* Check if the sub-expression is actually shorter than the whole one. This should + detect cases where it was automatically generated. *) + if e1.epos.pmin = e.epos.pmin && e1.epos.pmax <> e.epos.pmax then + loop e1; + begin match fa with + | FStatic(_,cf) | FInstance(_,_,cf) | FClosure(_,cf) -> + field_reference cf e.epos + | FAnon cf -> + declare (SKField cf) cf.cf_name_pos; + field_reference cf e.epos + | FEnum(_,ef) -> + add_relation ef.ef_name_pos (Referenced,patch_string_pos e.epos ef.ef_name) + | FDynamic _ -> + () + end + | TTypeExpr mt -> + let tinfos = t_infos mt in + add_relation tinfos.mt_name_pos (Referenced,patch_string_pos e.epos (snd tinfos.mt_path)) + | TNew(c,_,el) -> + List.iter loop el; + (try add_relation (find_real_constructor c).cf_name_pos (Referenced,e.epos) with Not_found -> ()); + | TCall({eexpr = TConst TSuper},el) -> + List.iter loop el; + begin match c.cl_super with + | Some(c,_) -> (try add_relation (find_real_constructor c).cf_name_pos (Referenced,e.epos) with Not_found -> ()) + | None -> () + end + | TVar(v,eo) -> + Option.may loop eo; + var_decl v; + | TFor(v,e1,e2) -> + var_decl v; + loop e1; + loop e2; + | TFunction tf -> + List.iter (fun (v,_) -> var_decl v) tf.tf_args; + loop tf.tf_expr; + | TLocal v when e.epos.pmax - e.epos.pmin = String.length v.v_name -> + add_relation v.v_pos (Referenced,e.epos) + | _ -> + Type.iter loop e + in + loop e + in + let rec explore_type_hint (p,t) = + match t with + | TMono r -> (match !r with None -> () | Some t -> explore_type_hint (p,t)) + | TLazy f -> explore_type_hint (p,lazy_type f) + | TInst(({cl_name_pos = pn;cl_path = (_,name)}),_) + | TEnum(({e_name_pos = pn;e_path = (_,name)}),_) + | TType(({t_name_pos = pn;t_path = (_,name)}),_) + | TAbstract(({a_name_pos = pn;a_path = (_,name)}),_) -> + add_relation pn (Referenced,p) + | TDynamic _ -> () + | TFun _ | TAnon _ -> () + in + let check_module m = + if not (Hashtbl.mem handled_modules m.m_path) then begin + Hashtbl.add handled_modules m.m_path true; + List.iter (fun (p1,p2) -> + add_relation p1 (Referenced,p2) + ) m.m_extra.m_display.m_inline_calls; + List.iter explore_type_hint m.m_extra.m_display.m_type_hints + end + in + let f = function + | TClassDecl c -> + check_module c.cl_module; + declare (if c.cl_interface then (SKInterface c) else (SKClass c)) c.cl_name_pos; + List.iter (fun (c',_) -> add_relation c'.cl_name_pos ((if c.cl_interface then Extended else Implemented),c.cl_name_pos)) c.cl_implements; + begin match c.cl_super with + | None -> () + | Some (c',_) -> add_relation c'.cl_name_pos (Extended,c.cl_name_pos); + end; + collect_overrides c; + let field cf = + if cf.cf_pos.pmin > c.cl_name_pos.pmin then declare (SKField cf) cf.cf_name_pos; + let _ = follow cf.cf_type in + match cf.cf_expr with None -> () | Some e -> collect_references c e + in + Option.may field c.cl_constructor; + List.iter field c.cl_ordered_fields; + List.iter field c.cl_ordered_statics; + | TEnumDecl en -> + check_module en.e_module; + declare (SKEnum en) en.e_name_pos; + PMap.iter (fun _ ef -> declare (SKEnumField ef) ef.ef_name_pos) en.e_constrs + | TTypeDecl td -> + check_module td.t_module; + declare (SKTypedef td) td.t_name_pos + | TAbstractDecl a -> + check_module a.a_module; + declare (SKAbstract a) a.a_name_pos + in + let rec loop com = + List.iter f com.types; + Option.may loop (com.get_macros()) + in + loop ctx.com; + let l = List.fold_left (fun acc (_,cfi,_,cfo) -> match cfo with + | Some cf -> if List.mem_assoc cf.cf_name_pos acc then acc else (cf.cf_name_pos,cfi.cf_name_pos) :: acc + | None -> acc + ) [] ctx.com.display_information.interface_field_implementations in + List.iter (fun (p,p') -> add_relation p' (Implemented,p)) l; + (* let deal_with_imports paths = + let check_subtype m s p = + try + let mt = List.find (fun mt -> snd (t_infos mt).mt_path = s) m.m_types in + add_relation (t_infos mt).mt_name_pos (Referenced,p); + Some mt + with Not_found -> + None + in + let check_module path p = + let m = ctx.g.do_load_module ctx path p in + m + in + let check_field c s p = + let cf = PMap.find s c.cl_statics in + add_relation cf.cf_name_pos (Referenced,p) + in + let check_subtype_field m ssub psub sfield pfield = match check_subtype m ssub psub with + | Some (TClassDecl c) -> check_field c sfield pfield + | _ -> () + in + PMap.iter (fun p (_,path) -> + match ImportHandling.convert_import_to_something_usable { p with pmin = p.pmax - 1; pmax = p.pmax - 1 } path,List.rev path with + | (IDKSubType(sl,s1,s2),_),(_,psubtype) :: (_,pmodule) :: _ -> + let m = check_module (sl,s1) pmodule in + (*ignore(check_subtype m s1 pmodule);*) + ignore(check_subtype m s2 psubtype) + | (IDKModuleField(sl,s1,s2),_),(_,pfield) :: (_,pmodule) :: _ -> + let m = check_module (sl,s1) pmodule in + check_subtype_field m s1 pmodule s2 pfield + | (IDKSubTypeField(sl,s1,s2,s3),_),(_,pfield) :: (_,psubtype) :: (_,pmodule) :: _ -> + let m = check_module (sl,s1) pmodule in + check_subtype_field m s2 psubtype s3 pfield + | (IDKModule(sl,s),_),(_,pmodule) :: _ -> + let m = check_module (sl,s) pmodule in + ignore(check_subtype m s pmodule); + | _ -> + () + ) paths + in + if false then deal_with_imports ctx.com.shared.shared_display_information.import_positions; *) + symbols,relations + +module Printer = struct + open Json + + let relation_to_string = function + | Implemented -> "implementers" + | Extended -> "subclasses" + | Overridden -> "overrides" + | Referenced -> "references" + + let symbol_to_string = function + | SKClass _ -> "class type" + | SKInterface _ -> "interface type" + | SKEnum _ -> "enum type" + | SKTypedef _ -> "typedef" + | SKAbstract _ -> "abstract" + | SKField _ -> "class field" + | SKEnumField _ -> "enum field" + | SKVariable _ -> "variable" + + let print_statistics (kinds,relations) = + let files = Hashtbl.create 0 in + Hashtbl.iter (fun p rl -> + let file = Path.get_real_path p.pfile in + try + Hashtbl.replace files file ((p,rl) :: Hashtbl.find files file) + with Not_found -> + Hashtbl.add files file [p,rl] + ) relations; + let ja = Hashtbl.fold (fun file relations acc -> + let l = List.map (fun (p,rl) -> + let h = Hashtbl.create 0 in + List.iter (fun (r,p) -> + let s = relation_to_string r in + let jo = JObject [ + "range",Genjson.generate_pos_as_range p; + "file",JString (Path.get_real_path p.pfile); + ] in + try Hashtbl.replace h s (jo :: Hashtbl.find h s) + with Not_found -> Hashtbl.add h s [jo] + ) rl; + let l = Hashtbl.fold (fun s js acc -> (s,JArray js) :: acc) h [] in + let l = ("range",Genjson.generate_pos_as_range p) :: l in + let l = try ("kind",JString (symbol_to_string (Hashtbl.find kinds p))) :: l with Not_found -> l in + JObject l + ) relations in + (JObject [ + "file",JString file; + "statistics",JArray l + ]) :: acc + ) files [] in + string_of_json (JArray ja) +end \ No newline at end of file diff --git a/src/context/displayTypes.ml b/src/context/displayTypes.ml deleted file mode 100644 index 83c13cf4f8f..00000000000 --- a/src/context/displayTypes.ml +++ /dev/null @@ -1,59 +0,0 @@ -open Ast - -module SymbolKind = struct - type t = - | Class - | Interface - | Enum - | Typedef - | Abstract - | Field - | Property - | Method - | Constructor - | Function - | Variable - - let to_int = function - | Class -> 1 - | Interface -> 2 - | Enum -> 3 - | Typedef -> 4 - | Abstract -> 5 - | Field -> 6 - | Property -> 7 - | Method -> 8 - | Constructor -> 9 - | Function -> 10 - | Variable -> 11 -end - -module SymbolInformation = struct - type t = { - name : string; - kind : SymbolKind.t; - pos : Globals.pos; - container_name : string option; - } - - let make name kind pos container_name = { - name = name; - kind = kind; - pos = pos; - container_name = container_name; - } -end - -module DiagnosticsSeverity = struct - type t = - | Error - | Warning - | Information - | Hint - - let to_int = function - | Error -> 1 - | Warning -> 2 - | Information -> 3 - | Hint -> 4 -end \ No newline at end of file diff --git a/src/context/nativeLibraries.ml b/src/context/nativeLibraries.ml new file mode 100644 index 00000000000..2d874dfaa16 --- /dev/null +++ b/src/context/nativeLibraries.ml @@ -0,0 +1,60 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals +open ExtString + +type native_lib_flags = + | FlagIsStd + | FlagIsExtern + +class virtual ['a,'data] native_library (name : string) (file_path : string) = object(self) + val mutable flags : native_lib_flags list = [] + + method add_flag flag = flags <- flag :: flags + method has_flag flag = List.mem flag flags + + method get_name = name + method get_file_path = file_path + + method virtual build : path -> pos -> Ast.package option + method virtual close : unit + method virtual list_modules : path list + method virtual load : unit + method virtual lookup : path -> 'a + method virtual get_data : 'data +end + +type java_lib_type = (JData.jclass * string * string) option +type net_lib_type = IlData.ilclass option +type swf_lib_type = As3hl.hl_class option + +type native_libraries = { + mutable java_libs : (java_lib_type,unit) native_library list; + mutable net_libs : (net_lib_type,unit) native_library list; + mutable swf_libs : (swf_lib_type,Swf.swf) native_library list; + mutable all_libs : string list; +} + +let create_native_libs () = { + java_libs = []; + net_libs = []; + swf_libs = []; + all_libs = []; +} \ No newline at end of file diff --git a/src/context/nativeLibraryHandler.ml b/src/context/nativeLibraryHandler.ml new file mode 100644 index 00000000000..810413eb8ee --- /dev/null +++ b/src/context/nativeLibraryHandler.ml @@ -0,0 +1,39 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals +open Common + +let add_native_lib com file is_extern = match com.platform with + | Globals.Flash -> + SwfLoader.add_swf_lib com file is_extern + | Globals.Java -> + let std = file = "lib/hxjava-std.jar" in + Java.add_java_lib com file std is_extern + | Globals.Cs -> + let file, is_std = match ExtString.String.nsplit file "@" with + | [file] -> + file,false + | [file;"std"] -> + file,true + | _ -> failwith ("unsupported file@`std` format: " ^ file) + in + Dotnet.add_net_lib com file is_std is_extern + | pf -> + failwith (Printf.sprintf "Target %s does not support native libraries (trying to load %s)" (platform_name pf) file); \ No newline at end of file diff --git a/src/context/purityState.ml b/src/context/purityState.ml new file mode 100644 index 00000000000..034787def3b --- /dev/null +++ b/src/context/purityState.ml @@ -0,0 +1,67 @@ +open Globals +open Ast +open Type +open Error + +(* + PurityState represents whether or not something has a side-effect. Unless otherwise stated + by using `@:pure` (equivalent to `@:pure(true)`) or `@:pure(false)`, fields are originally + supposed to be "maybe pure". Once all types and fields are known, this is refined by + AnalyzerTexpr.Purity. + + There's a special case for fields that override a parent class field or implement an + interface field: If the overridden/implemented field is explicitly marked as pure, + the type loader marks the overriding/implementing as "expected pure". If during purity + inference this assumption does not hold, an error is shown. +*) +type t = + | Pure + | Impure + | MaybePure + | ExpectPure of pos + +let get_purity_from_meta meta = + try + begin match Meta.get Meta.Pure meta with + | (_,[EConst(Ident s),p],_) -> + begin match s with + | "true" -> Pure + | "false" -> Impure + | "expect" -> ExpectPure p + | _ -> error ("Unsupported purity value " ^ s ^ ", expected true or false") p + end + | (_,[],_) -> + Pure + | (_,_,p) -> + error "Unsupported purity value" p + end + with Not_found -> + MaybePure + +let get_purity c cf = match get_purity_from_meta cf.cf_meta with + | Pure -> Pure + | Impure -> Impure + | ExpectPure p -> ExpectPure p + | _ -> get_purity_from_meta c.cl_meta + +let is_pure c cf = get_purity c cf = Pure + +let is_pure_field_access fa = match fa with + | FInstance(c,_,cf) | FClosure(Some(c,_),cf) | FStatic(c,cf) -> is_pure c cf + | FAnon cf | FClosure(None,cf) -> (get_purity_from_meta cf.cf_meta = Pure) + | FEnum _ -> true + | FDynamic _ -> false + +let is_explicitly_impure fa = match fa with + | FInstance(c,_,cf) | FClosure(Some(c,_),cf) | FStatic(c,cf) -> + get_purity_from_meta cf.cf_meta = Impure + || get_purity_from_meta c.cl_meta = Impure + | FAnon cf | FClosure(None,cf) -> + get_purity_from_meta cf.cf_meta = Impure + | _ -> false + +let to_string = function + | Pure -> "pure" + | Impure -> "impure" + | MaybePure -> "maybe" + | ExpectPure _ -> "expect" diff --git a/src/context/sourcemaps.ml b/src/context/sourcemaps.ml index b49a2c40a1f..4f48b3b2f91 100644 --- a/src/context/sourcemaps.ml +++ b/src/context/sourcemaps.ml @@ -131,7 +131,7 @@ class sourcemap_writer (generated_file:string) = "],\n"); if Common.defined com Define.SourceMapContent then begin output_string channel ("\"sourcesContent\":[" ^ - (String.concat "," (List.map (fun s -> try "\"" ^ Ast.s_escape (Std.input_file ~bin:true s) ^ "\"" with _ -> "null") sources)) ^ + (String.concat "," (List.map (fun s -> try "\"" ^ StringHelper.s_escape (Std.input_file ~bin:true s) ^ "\"" with _ -> "null") sources)) ^ "],\n"); end; output_string channel "\"names\":[],\n"; diff --git a/src/context/typecore.ml b/src/context/typecore.ml index d428e649fdb..ab89e9dac02 100644 --- a/src/context/typecore.ml +++ b/src/context/typecore.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -22,11 +22,7 @@ open Ast open Common open Type open Error - -type with_type = - | NoValue - | Value - | WithType of t +open DisplayTypes type type_patch = { mutable tp_type : complex_type option; @@ -48,9 +44,15 @@ type macro_mode = | MMacroType | MDisplay +type access_mode = + | MGet + | MSet + | MCall + type typer_pass = | PBuildModule (* build the module structure and setup module type parameters *) | PBuildClass (* build the class structure *) + | PConnectField (* handle associated fields, which may affect each other. E.g. a property and its getter *) | PTypeField (* type the class field, allow access to types structures *) | PCheckConstraint (* perform late constraint checks with inferred types *) | PForce (* usually ensure that lazy have been evaluated *) @@ -78,19 +80,21 @@ type typer_globals = { type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t; mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list; mutable module_check_policies : (string list * module_check_policy list * bool) list; - mutable get_build_infos : unit -> (module_type * t list * class_field list) option; - delayed_macros : (unit -> unit) DynArray.t; mutable global_using : (tclass * pos) list; + (* Indicates that Typer.create() finished building this instance *) + mutable complete : bool; (* api *) do_inherit : typer -> Type.tclass -> pos -> (bool * placed_type_path) -> bool; do_create : Common.context -> typer; do_macro : typer -> macro_mode -> path -> string -> expr list -> pos -> expr option; do_load_module : typer -> path -> pos -> module_def; + do_load_type_def : typer -> pos -> type_path -> module_type; do_optimize : typer -> texpr -> texpr; do_build_instance : typer -> module_type -> pos -> ((string * t) list * path * (t list -> t)); do_format_string : typer -> string -> pos -> Ast.expr; do_finalize : typer -> unit; do_generate : typer -> (texpr option * module_type list * module_def list); + do_load_core_class : typer -> tclass -> tclass; } and typer = { @@ -98,9 +102,10 @@ and typer = { com : context; t : basic_types; g : typer_globals; + mutable bypass_accessor : int; mutable meta : metadata; mutable this_stack : texpr list; - mutable with_type_stack : with_type list; + mutable with_type_stack : WithType.t list; mutable call_argument_stack : expr list list; (* variable *) mutable pass : typer_pass; @@ -111,6 +116,7 @@ and typer = { mutable curclass : tclass; mutable tthis : t; mutable type_params : (string * t) list; + mutable get_build_infos : unit -> (module_type * t list * class_field list) option; (* per-function *) mutable curfield : tclass_field; mutable untyped : bool; @@ -131,21 +137,17 @@ exception Forbid_package of (string * path * pos) * pos list * string exception WithTypeError of error_msg * pos -let make_call_ref : (typer -> texpr -> texpr list -> t -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false) -let type_expr_ref : (typer -> expr -> with_type -> texpr) ref = ref (fun _ _ _ -> assert false) -let type_module_type_ref : (typer -> module_type -> t list option -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false) +let make_call_ref : (typer -> texpr -> texpr list -> t -> ?force_inline:bool -> pos -> texpr) ref = ref (fun _ _ _ _ ?force_inline:bool _ -> assert false) +let type_expr_ref : (?mode:access_mode -> typer -> expr -> WithType.t -> texpr) ref = ref (fun ?(mode=MGet) _ _ _ -> assert false) +let type_block_ref : (typer -> expr list -> WithType.t -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false) let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> assert false) -let match_expr_ref : (typer -> expr -> (expr list * expr option * expr option * pos) list -> (expr option * pos) option -> with_type -> pos -> texpr) ref = ref (fun _ _ _ _ _ _ -> assert false) -let get_pattern_locals_ref : (typer -> expr -> Type.t -> (string, tvar * pos) PMap.t) ref = ref (fun _ _ _ -> assert false) -let get_constructor_ref : (typer -> tclass -> t list -> pos -> (t * tclass_field)) ref = ref (fun _ _ _ _ -> assert false) -let cast_or_unify_ref : (typer -> t -> texpr -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false) -let find_array_access_raise_ref : (typer -> tabstract -> tparams -> texpr -> texpr option -> pos -> (tclass_field * t * t * texpr * texpr option)) ref = ref (fun _ _ _ _ _ _ -> assert false) +let unify_min_for_type_source_ref : (typer -> texpr list -> WithType.with_type_source option -> t) ref = ref (fun _ _ _ -> assert false) let analyzer_run_on_expr_ref : (Common.context -> texpr -> texpr) ref = ref (fun _ _ -> assert false) -let merge_core_doc_ref : (typer -> tclass -> unit) ref = ref (fun _ _ -> assert false) let pass_name = function | PBuildModule -> "build-module" | PBuildClass -> "build-class" + | PConnectField -> "connect-field" | PTypeField -> "type-field" | PCheckConstraint -> "check-constraint" | PForce -> "force" @@ -153,15 +155,14 @@ let pass_name = function let display_error ctx msg p = match ctx.com.display.DisplayMode.dms_error_policy with | DisplayMode.EPShow | DisplayMode.EPIgnore -> ctx.on_error ctx msg p - | DisplayMode.EPCollect -> add_diagnostics_message ctx.com msg p DisplayTypes.DiagnosticsSeverity.Error + | DisplayMode.EPCollect -> add_diagnostics_message ctx.com msg p DisplayTypes.DiagnosticsKind.DKCompilerError DisplayTypes.DiagnosticsSeverity.Error let make_call ctx e el t p = (!make_call_ref) ctx e el t p -let type_expr ctx e with_type = (!type_expr_ref) ctx e with_type +let type_expr ?(mode=MGet) ctx e with_type = (!type_expr_ref) ~mode ctx e with_type let unify_min ctx el = (!unify_min_ref) ctx el - -let match_expr ctx e cases def with_type p = !match_expr_ref ctx e cases def with_type p +let unify_min_for_type_source ctx el src = (!unify_min_for_type_source_ref) ctx el src let make_static_this c p = let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in @@ -205,11 +206,25 @@ let save_locals ctx = let locals = ctx.locals in (fun() -> ctx.locals <- locals) -let add_local ctx n t p = - let v = alloc_var n t p in +let add_local ctx k n t p = + let v = alloc_var k n t p in + if Define.defined ctx.com.defines Define.WarnVarShadowing && n <> "_" then begin + try + let v' = PMap.find n ctx.locals in + (* ignore std lib *) + if not (List.exists (ExtLib.String.starts_with p.pfile) ctx.com.std_path) then begin + ctx.com.warning "This variable shadows a previously declared variable" p; + ctx.com.warning "Previous variable was here" v'.v_pos + end + with Not_found -> + () + end; ctx.locals <- PMap.add n v ctx.locals; v +let add_local_with_origin ctx origin n t p = + add_local ctx (VUser origin) n t p + let gen_local_prefix = "`" let gen_local ctx t p = @@ -221,7 +236,7 @@ let gen_local ctx t p = else nv in - add_local ctx (loop 0) t p + add_local ctx VGenerated (loop 0) t p let is_gen_local v = String.unsafe_get v.v_name 0 = String.unsafe_get gen_local_prefix 0 @@ -307,300 +322,141 @@ let push_this ctx e = match e.eexpr with er,fun () -> ctx.this_stack <- List.tl ctx.this_stack let is_removable_field ctx f = - Meta.has Meta.Extern f.cf_meta || Meta.has Meta.Generic f.cf_meta + has_class_field_flag f CfExtern || Meta.has Meta.Generic f.cf_meta || (match f.cf_kind with | Var {v_read = AccRequire (s,_)} -> true | Method MethMacro -> not ctx.in_macro | _ -> false) -(* -------------------------------------------------------------------------- *) -(* ABSTRACT CASTS *) - -module AbstractCast = struct - - let cast_stack = ref [] - - let make_static_call ctx c cf a pl args t p = - if cf.cf_kind = Method MethMacro then begin - match args with - | [e] -> - let e,f = push_this ctx e in - ctx.with_type_stack <- (WithType t) :: ctx.with_type_stack; - let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name [e] p with - | Some e -> type_expr ctx e Value - | None -> type_expr ctx (EConst (Ident "null"),p) Value - in - ctx.with_type_stack <- List.tl ctx.with_type_stack; - f(); - e - | _ -> assert false - end else - make_static_call ctx c cf (apply_params a.a_params pl) args t p - - let do_check_cast ctx tleft eright p = - let recurse cf f = - if cf == ctx.curfield || List.mem cf !cast_stack then error "Recursive implicit cast" p; - cast_stack := cf :: !cast_stack; - let r = f() in - cast_stack := List.tl !cast_stack; - r - in - let find a tl f = - let tcf,cf = f() in - if (Meta.has Meta.MultiType a.a_meta) then - mk_cast eright tleft p - else match a.a_impl with - | Some c -> recurse cf (fun () -> - let ret = make_static_call ctx c cf a tl [eright] tleft p in - { ret with eexpr = TMeta( (Meta.ImplicitCast,[],ret.epos), ret) } - ) - | None -> assert false +(** checks if we can access to a given class field using current context *) +let rec can_access ctx ?(in_overload=false) c cf stat = + if (has_class_field_flag cf CfPublic) then + true + else if not in_overload && ctx.com.config.pf_overload && Meta.has Meta.Overload cf.cf_meta then + true + else + (* TODO: should we add a c == ctx.curclass short check here? *) + (* has metadata path *) + let rec make_path c f = match c.cl_kind with + | KAbstractImpl a -> fst a.a_path @ [snd a.a_path; f.cf_name] + | KGenericInstance(c,_) -> make_path c f + | _ when c.cl_private -> List.rev (f.cf_name :: snd c.cl_path :: (List.tl (List.rev (fst c.cl_path)))) + | _ -> fst c.cl_path @ [snd c.cl_path; f.cf_name] + in + let rec expr_path acc e = + match fst e with + | EField (e,f) -> expr_path (f :: acc) e + | EConst (Ident n) -> n :: acc + | _ -> [] + in + let rec chk_path psub pfull is_current_path = + match psub, pfull with + | [], _ -> true + | a :: l1, b :: l2 when a = b -> + if + (* means it's a path of a superclass or implemented interface *) + not is_current_path && + (* it's the last part of path in a meta && it denotes a package *) + l1 = [] && not (StringHelper.starts_uppercase a) + then + false + else + chk_path l1 l2 is_current_path + | _ -> false + in + let has m c f (path,is_current_path) = + let rec loop = function + | (m2,el,_) :: l when m = m2 -> + List.exists (fun e -> + match fst e with + | EConst (Ident "std") -> + (* If we have `@:allow(std)`, check if our path has exactly two elements + (type name + field name) *) + (match path with [_;_] -> true | _ -> false) + | _ -> + let p = expr_path [] e in + (p <> [] && chk_path p path is_current_path) + ) el + || loop l + | _ :: l -> loop l + | [] -> false in - if type_iseq tleft eright.etype then - eright - else begin - let rec loop tleft tright = match follow tleft,follow tright with - | TAbstract(a1,tl1),TAbstract(a2,tl2) -> - begin try find a2 tl2 (fun () -> Abstract.find_to a2 tl2 tleft) - with Not_found -> try find a1 tl1 (fun () -> Abstract.find_from a1 tl1 eright.etype tleft) - with Not_found -> raise Not_found - end - | TAbstract(a,tl),_ -> - begin try find a tl (fun () -> Abstract.find_from a tl eright.etype tleft) - with Not_found -> - let rec loop2 tcl = match tcl with - | tc :: tcl -> - if not (type_iseq tc tleft) then loop (apply_params a.a_params tl tc) tright - else loop2 tcl - | [] -> raise Not_found - in - loop2 a.a_from - end - | _,TAbstract(a,tl) -> - begin try find a tl (fun () -> Abstract.find_to a tl tleft) - with Not_found -> - let rec loop2 tcl = match tcl with - | tc :: tcl -> - if not (type_iseq tc tright) then loop tleft (apply_params a.a_params tl tc) - else loop2 tcl - | [] -> raise Not_found - in - loop2 a.a_to - end - | _ -> - raise Not_found - in - loop tleft eright.etype - end - - let cast_or_unify_raise ctx tleft eright p = - try - (* can't do that anymore because this might miss macro calls (#4315) *) - (* if ctx.com.display <> DMNone then raise Not_found; *) - do_check_cast ctx tleft eright p - with Not_found -> - unify_raise ctx eright.etype tleft p; - eright - - let cast_or_unify ctx tleft eright p = + loop c.cl_meta || loop f.cf_meta + in + let cur_paths = ref [] in + let rec loop c is_current_path = + cur_paths := (make_path c ctx.curfield, is_current_path) :: !cur_paths; + begin match c.cl_super with + | Some (csup,_) -> loop csup false + | None -> () + end; + List.iter (fun (c,_) -> loop c false) c.cl_implements; + in + loop ctx.curclass true; + let is_constr = cf.cf_name = "new" in + let rec loop c = try - cast_or_unify_raise ctx tleft eright p - with Error (Unify l,p) -> - raise_or_display ctx l p; - eright - - let find_array_access_raise ctx a pl e1 e2o p = - let is_set = e2o <> None in - let ta = apply_params a.a_params pl a.a_this in - let rec loop cfl = match cfl with - | [] -> raise Not_found - | cf :: cfl -> - let monos = List.map (fun _ -> mk_mono()) cf.cf_params in - let map t = apply_params a.a_params pl (apply_params cf.cf_params monos t) in - let check_constraints () = - List.iter2 (fun m (name,t) -> match follow t with - | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> - List.iter (fun tc -> match follow m with TMono _ -> raise (Unify_error []) | _ -> Type.unify m (map tc) ) constr - | _ -> () - ) monos cf.cf_params; - in - match follow (map cf.cf_type) with - | TFun([(_,_,tab);(_,_,ta1);(_,_,ta2)],r) as tf when is_set -> - begin try - Type.unify tab ta; - let e1 = cast_or_unify_raise ctx ta1 e1 p in - let e2o = match e2o with None -> None | Some e2 -> Some (cast_or_unify_raise ctx ta2 e2 p) in - check_constraints(); - cf,tf,r,e1,e2o - with Unify_error _ | Error (Unify _,_) -> - loop cfl - end - | TFun([(_,_,tab);(_,_,ta1)],r) as tf when not is_set -> - begin try - Type.unify tab ta; - let e1 = cast_or_unify_raise ctx ta1 e1 p in - check_constraints(); - cf,tf,r,e1,None - with Unify_error _ | Error (Unify _,_) -> - loop cfl - end - | _ -> loop cfl - in - loop a.a_array - - let find_array_access ctx a tl e1 e2o p = - try find_array_access_raise ctx a tl e1 e2o p - with Not_found -> match e2o with - | None -> - error (Printf.sprintf "No @:arrayAccess function accepts argument of %s" (s_type (print_context()) e1.etype)) p - | Some e2 -> - error (Printf.sprintf "No @:arrayAccess function accepts arguments of %s and %s" (s_type (print_context()) e1.etype) (s_type (print_context()) e2.etype)) p - - let find_multitype_specialization com a pl p = - let m = mk_mono() in - let tl = match Meta.get Meta.MultiType a.a_meta with - | _,[],_ -> pl - | _,el,_ -> - let relevant = Hashtbl.create 0 in - List.iter (fun e -> - let rec loop f e = match fst e with - | EConst(Ident s) -> - Hashtbl.replace relevant s f - | EMeta((Meta.Custom ":followWithAbstracts",_,_),e1) -> - loop Abstract.follow_with_abstracts e1; - | _ -> - error "Type parameter expected" (pos e) - in - loop (fun t -> t) e - ) el; - let tl = List.map2 (fun (n,_) t -> - try - (Hashtbl.find relevant n) t - with Not_found -> - if not (has_mono t) then t - else t_dynamic - ) a.a_params pl in - if com.platform = Globals.Js && a.a_path = (["haxe";"ds"],"Map") then begin match tl with - | t1 :: _ -> - let rec loop stack t = - if List.exists (fun t2 -> fast_eq t t2) stack then - t - else begin - let stack = t :: stack in - match follow t with - | TAbstract ({ a_path = [],"Class" },_) -> - error (Printf.sprintf "Cannot use %s as key type to Map because Class is not comparable" (s_type (print_context()) t1)) p; - | TEnum(en,tl) -> - PMap.iter (fun _ ef -> ignore(loop stack ef.ef_type)) en.e_constrs; - Type.map (loop stack) t - | t -> - Type.map (loop stack) t - end - in - ignore(loop [] t1) - | _ -> assert false - end; - tl - in - let _,cf = - try - Abstract.find_to a tl m - with Not_found -> - let at = apply_params a.a_params pl a.a_this in - let st = s_type (print_context()) at in - if has_mono at then - error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p - else - error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p; + has Meta.Access ctx.curclass ctx.curfield ((make_path c cf), true) + || ( + (* if our common ancestor declare/override the field, then we can access it *) + let allowed f = is_parent c ctx.curclass || (List.exists (has Meta.Allow c f) !cur_paths) in + if is_constr + then (match c.cl_constructor with + | Some cf -> + if allowed cf then true + else if cf.cf_expr = None then false (* maybe it's an inherited auto-generated constructor *) + else raise Not_found + | _ -> false + ) + else try allowed (PMap.find cf.cf_name (if stat then c.cl_statics else c.cl_fields)) with Not_found -> false + ) + || (match c.cl_super with + | Some (csup,_) -> loop csup + | None -> false) + with Not_found -> false + in + let b = loop c + (* access is also allowed of we access a type parameter which is constrained to our (base) class *) + || (match c.cl_kind with + | KTypeParameter tl -> + List.exists (fun t -> match follow t with TInst(c,_) -> loop c | _ -> false) tl + | _ -> false) + || (Meta.has Meta.PrivateAccess ctx.meta) in + (* TODO: find out what this does and move it to genas3 *) + if b && Common.defined ctx.com Common.Define.As3 && not (Meta.has Meta.Public cf.cf_meta) then cf.cf_meta <- (Meta.Public,[],cf.cf_pos) :: cf.cf_meta; + b + +(** removes the first argument of the class field's function type and all its overloads *) +let prepare_using_field cf = match follow cf.cf_type with + | TFun((_,_,tf) :: args,ret) -> + let rec loop acc overloads = match overloads with + | ({cf_type = TFun((_,_,tfo) :: args,ret)} as cfo) :: l -> + let tfo = apply_params cfo.cf_params (List.map snd cfo.cf_params) tfo in + (* ignore overloads which have a different first argument *) + if type_iseq tf tfo then loop ({cfo with cf_type = TFun(args,ret)} :: acc) l else loop acc l + | _ :: l -> + loop acc l + | [] -> + acc in - cf, follow m - - let handle_abstract_casts ctx e = - let rec loop ctx e = match e.eexpr with - | TNew({cl_kind = KAbstractImpl a} as c,pl,el) -> - if not (Meta.has Meta.MultiType a.a_meta) then begin - (* This must have been a @:generic expansion with a { new } constraint (issue #4364). In this case - let's construct the underlying type. *) - match Abstract.get_underlying_type a pl with - | TInst(c,tl) as t -> {e with eexpr = TNew(c,tl,el); etype = t} - | _ -> error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos - end else begin - (* a TNew of an abstract implementation is only generated if it is a multi type abstract *) - let cf,m = find_multitype_specialization ctx.com a pl e.epos in - let e = make_static_call ctx c cf a pl ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el) m e.epos in - {e with etype = m} - end - | TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) -> - begin match follow e1.etype with - | TAbstract({a_impl = Some c} as a,tl) -> - begin try - let cf = PMap.find "toString" c.cl_statics in - make_static_call ctx c cf a tl [e1] ctx.t.tstring e.epos - with Not_found -> - e - end - | _ -> - assert false - end - | TCall(e1, el) -> - begin try - let rec find_abstract e t = match follow t,e.eexpr with - | TAbstract(a,pl),_ when Meta.has Meta.MultiType a.a_meta -> a,pl,e - | _,TCast(e1,None) -> find_abstract e1 e1.etype - | _,TLocal {v_extra = Some(_,Some e')} -> - begin match follow e'.etype with - | TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta -> a,pl,mk (TCast(e,None)) e'.etype e.epos - | _ -> raise Not_found - end - | _ -> raise Not_found - in - let rec find_field e1 = - match e1.eexpr with - | TCast(e2,None) -> - {e1 with eexpr = TCast(find_field e2,None)} - | TField(e2,fa) -> - let a,pl,e2 = find_abstract e2 e2.etype in - let m = Abstract.get_underlying_type a pl in - let fname = field_name fa in - let el = List.map (loop ctx) el in - begin try - let fa = quick_field m fname in - let get_fun_type t = match follow t with - | TFun(_,tr) as tf -> tf,tr - | _ -> raise Not_found - in - let tf,tr = match fa with - | FStatic(_,cf) -> get_fun_type cf.cf_type - | FInstance(c,tl,cf) -> get_fun_type (apply_params c.cl_params tl cf.cf_type) - | FAnon cf -> get_fun_type cf.cf_type - | _ -> raise Not_found - in - let ef = mk (TField({e2 with etype = m},fa)) tf e2.epos in - let ecall = make_call ctx ef el tr e.epos in - if not (type_iseq ecall.etype e.etype) then - mk (TCast(ecall,None)) e.etype e.epos - else - ecall - with Not_found -> - (* quick_field raises Not_found if m is an abstract, we have to replicate the 'using' call here *) - match follow m with - | TAbstract({a_impl = Some c} as a,pl) -> - let cf = PMap.find fname c.cl_statics in - make_static_call ctx c cf a pl (e2 :: el) e.etype e.epos - | _ -> raise Not_found - end - | _ -> - raise Not_found - in - find_field e1 - with Not_found -> - Type.map_expr (loop ctx) e - end - | _ -> - Type.map_expr (loop ctx) e + {cf with cf_overloads = loop [] cf.cf_overloads; cf_type = TFun(args,ret)} + | _ -> cf + +let merge_core_doc ctx mt = + (match mt with + | TClassDecl c | TAbstractDecl { a_impl = Some c } when Meta.has Meta.CoreApi c.cl_meta -> + let c_core = ctx.g.do_load_core_class ctx c in + if c.cl_doc = None then c.cl_doc <- c_core.cl_doc; + let maybe_merge cf_map cf = + if cf.cf_doc = None then try cf.cf_doc <- (PMap.find cf.cf_name cf_map).cf_doc with Not_found -> () in - loop ctx e -end + List.iter (maybe_merge c_core.cl_fields) c.cl_ordered_fields; + List.iter (maybe_merge c_core.cl_statics) c.cl_ordered_statics; + begin match c.cl_constructor,c_core.cl_constructor with + | Some ({cf_doc = None} as cf),Some cf2 -> cf.cf_doc <- cf2.cf_doc + | _ -> () + end + | _ -> ()) (* -------------- debug functions to activate when debugging typer passes ------------------------------- *) (*/* @@ -616,7 +472,12 @@ let context_ident ctx = " out " let debug ctx str = - if Common.raw_defined ctx.com "cdebug" then print_endline (context_ident ctx ^ string_of_int (String.length !delay_tabs) ^ " " ^ !delay_tabs ^ str) + if Common.raw_defined ctx.com "cdebug" then begin + let s = (context_ident ctx ^ string_of_int (String.length !delay_tabs) ^ " " ^ !delay_tabs ^ str) in + match ctx.com.json_out with + | None -> print_endline s + | Some _ -> DynArray.add ctx.com.pass_debug_messages s + end let init_class_done ctx = debug ctx ("init_class_done " ^ s_type_path ctx.curclass.cl_path); diff --git a/src/core/abstract.ml b/src/core/abstract.ml index 711381fe70b..812ff16a9d1 100644 --- a/src/core/abstract.ml +++ b/src/core/abstract.ml @@ -2,27 +2,55 @@ open Meta open Type open Error +let build_abstract a = match a.a_impl with + | Some c -> ignore(c.cl_build()) + | None -> () + +let has_direct_to ab pl b = + List.exists (unify_to ab pl ~allow_transitive_cast:false b) ab.a_to + +let has_direct_from ab pl a b = + List.exists (unify_from ab pl a ~allow_transitive_cast:false b) ab.a_from + +let find_field_to ab pl b = + build_abstract ab; + List.find (unify_to_field ab pl b) ab.a_to_field + +let find_field_from ab pl a b = + build_abstract ab; + List.find (unify_from_field ab pl a b) ab.a_from_field + +let find_to_from f ab_left tl_left ab_right tl_right tleft tright = + build_abstract ab_left; + build_abstract ab_right; + if has_direct_to ab_right tl_right tleft || has_direct_from ab_left tl_left tright tleft then + raise Not_found + else + try f ab_right tl_right (fun () -> find_field_to ab_right tl_right tleft) + with Not_found -> f ab_left tl_left (fun () -> find_field_from ab_left tl_left tright tleft) + let find_to ab pl b = + build_abstract ab; if follow b == t_dynamic then List.find (fun (t,_) -> follow t == t_dynamic) ab.a_to_field - else if List.exists (unify_to ab pl ~allow_transitive_cast:false b) ab.a_to then + else if has_direct_to ab pl b then raise Not_found (* legacy compatibility *) else - List.find (unify_to_field ab pl b) ab.a_to_field + find_field_to ab pl b let find_from ab pl a b = + build_abstract ab; if follow a == t_dynamic then List.find (fun (t,_) -> follow t == t_dynamic) ab.a_from_field - else if List.exists (unify_from ab pl a ~allow_transitive_cast:false b) ab.a_from then + else if has_direct_from ab pl a b then raise Not_found (* legacy compatibility *) else - List.find (unify_from_field ab pl a b) ab.a_from_field + find_field_from ab pl a b -let underlying_type_stack = ref [] +let underlying_type_stack = new_rec_stack() -let rec get_underlying_type a pl = +let rec get_underlying_type ?(return_first=false) a pl = let maybe_recurse t = - underlying_type_stack := (TAbstract(a,pl)) :: !underlying_type_stack; let rec loop t = match t with | TMono r -> (match !r with @@ -35,22 +63,29 @@ let rec get_underlying_type a pl = | TType (t,tl) -> loop (apply_params t.t_params tl t.t_type) | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> - if List.exists (fast_eq t) !underlying_type_stack then begin + if rec_stack_exists (fast_eq t) underlying_type_stack then begin let pctx = print_context() in - let s = String.concat " -> " (List.map (fun t -> s_type pctx t) (List.rev (t :: !underlying_type_stack))) in - underlying_type_stack := []; + let s = String.concat " -> " (List.map (fun t -> s_type pctx t) (List.rev (t :: underlying_type_stack.rec_stack))) in error ("Abstract chain detected: " ^ s) a.a_pos end; - get_underlying_type a tl + (* + Even if only the first underlying type was requested + keep traversing to detect mutually recursive abstracts + *) + let result = get_underlying_type a tl in + if return_first then t + else result | _ -> t in - let t = loop t in - underlying_type_stack := List.tl !underlying_type_stack; - t + rec_stack_loop underlying_type_stack (TAbstract(a,pl)) loop t in try if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found; + (* TODO: + Look into replacing `mk_mono` & `find_to` with `build_abstract a` & `TAbstract(a, pl)`. + `find_to` is probably needed for `@:multiType` + *) let m = mk_mono() in let _ = find_to a pl m in maybe_recurse (follow m) diff --git a/src/core/ast.ml b/src/core/ast.ml index 745320c981c..c59fd27c36a 100644 --- a/src/core/ast.ml +++ b/src/core/ast.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -63,6 +63,8 @@ type keyword = | Abstract | Macro | Final + | Operator + | Overload type binop = | OpAdd @@ -161,6 +163,8 @@ and complex_type = | CTParent of type_hint | CTExtend of placed_type_path list * class_field list | CTOptional of type_hint + | CTNamed of placed_name * type_hint + | CTIntersection of type_hint list and type_hint = complex_type * pos @@ -173,6 +177,13 @@ and func = { and placed_name = string * pos +and display_kind = + | DKCall + | DKDot + | DKStructure + | DKMarked + | DKPattern of bool + and expr_def = | EConst of constant | EArray of expr * expr @@ -184,8 +195,8 @@ and expr_def = | ECall of expr * expr list | ENew of placed_type_path * expr list | EUnop of unop * unop_flag * expr - | EVars of (placed_name * type_hint option * expr option) list - | EFunction of string option * func + | EVars of (placed_name * bool * type_hint option * expr option) list + | EFunction of placed_name option * func | EBlock of expr list | EFor of expr * expr | EIf of expr * expr * expr option @@ -198,7 +209,7 @@ and expr_def = | EUntyped of expr | EThrow of expr | ECast of expr * type_hint option - | EDisplay of expr * bool + | EDisplay of expr * display_kind | EDisplayNew of placed_type_path | ETernary of expr * expr * expr | ECheckType of expr * type_hint @@ -209,7 +220,7 @@ and expr = expr_def * pos and type_param = { tp_name : placed_name; tp_params : type_param list; - tp_constraints : type_hint list; + tp_constraints : type_hint option; tp_meta : metadata; } @@ -227,6 +238,9 @@ and access = | AInline | AMacro | AFinal + | AExtern + +and placed_access = access * pos and class_field_kind = | FVar of type_hint option * expr option @@ -238,7 +252,7 @@ and class_field = { cff_doc : documentation; cff_pos : pos; mutable cff_meta : metadata; - mutable cff_access : access list; + mutable cff_access : placed_access list; mutable cff_kind : class_field_kind; } @@ -252,13 +266,14 @@ type class_flag = | HPrivate | HExtends of placed_type_path | HImplements of placed_type_path + | HFinal type abstract_flag = - | APrivAbstract - | AFromType of type_hint - | AToType of type_hint - | AIsType of type_hint - | AExtern + | AbPrivate + | AbFrom of type_hint + | AbTo of type_hint + | AbOver of type_hint + | AbExtern type enum_constructor = { ec_name : placed_name; @@ -281,7 +296,7 @@ type ('a,'b) definition = { type import_mode = | INormal - | IAsName of string + | IAsName of placed_name | IAll type import = placed_name list * import_mode @@ -339,24 +354,10 @@ let parse_path s = | [] -> [],"" (* This is how old extlib behaved. *) | x :: l -> List.rev l, x -let s_escape ?(hex=true) s = - let b = Buffer.create (String.length s) in - for i = 0 to (String.length s) - 1 do - match s.[i] with - | '\n' -> Buffer.add_string b "\\n" - | '\t' -> Buffer.add_string b "\\t" - | '\r' -> Buffer.add_string b "\\r" - | '"' -> Buffer.add_string b "\\\"" - | '\\' -> Buffer.add_string b "\\\\" - | c when int_of_char c < 32 && hex -> Buffer.add_string b (Printf.sprintf "\\x%.2X" (int_of_char c)) - | c -> Buffer.add_char b c - done; - Buffer.contents b - let s_constant = function | Int s -> s | Float s -> s - | String s -> "\"" ^ s_escape s ^ "\"" + | String s -> "\"" ^ StringHelper.s_escape s ^ "\"" | Ident s -> s | Regexp (r,o) -> "~/" ^ r ^ "/" @@ -369,6 +370,9 @@ let s_access = function | AInline -> "inline" | AMacro -> "macro" | AFinal -> "final" + | AExtern -> "extern" + +let s_placed_access (a,_) = s_access a let s_keyword = function | Function -> "function" @@ -414,6 +418,8 @@ let s_keyword = function | Abstract -> "abstract" | Macro -> "macro" | Final -> "final" + | Operator -> "operator" + | Overload -> "overload" let rec s_binop = function | OpAdd -> "+" @@ -473,7 +479,7 @@ let s_token = function | At -> "@" | Dollar v -> "$" ^ v -exception Invalid_escape_sequence of char * int +exception Invalid_escape_sequence of char * int * (string option) let unescape s = let b = Buffer.create 0 in @@ -482,7 +488,7 @@ let unescape s = () else let c = s.[i] in - let fail () = raise (Invalid_escape_sequence(c,i)) in + let fail msg = raise (Invalid_escape_sequence(c,i,msg)) in if esc then begin let inext = ref (i + 1) in (match c with @@ -491,14 +497,21 @@ let unescape s = | 't' -> Buffer.add_char b '\t' | '"' | '\'' | '\\' -> Buffer.add_char b c | '0'..'3' -> - let c = (try char_of_int (int_of_string ("0o" ^ String.sub s i 3)) with _ -> fail()) in - Buffer.add_char b c; + let u = (try (int_of_string ("0o" ^ String.sub s i 3)) with _ -> fail None) in + if u > 127 then + fail (Some ("Values greater than \\177 are not allowed. Use \\u00" ^ (Printf.sprintf "%02x" u) ^ " instead.")); + Buffer.add_char b (char_of_int u); inext := !inext + 2; | 'x' -> - let c = (try char_of_int (int_of_string ("0x" ^ String.sub s (i+1) 2)) with _ -> fail()) in - Buffer.add_char b c; + let fail_no_hex () = fail (Some "Must be followed by a hexadecimal sequence.") in + let hex = try String.sub s (i+1) 2 with _ -> fail_no_hex () in + let u = (try (int_of_string ("0x" ^ hex)) with _ -> fail_no_hex ()) in + if u > 127 then + fail (Some ("Values greater than \\x7f are not allowed. Use \\u00" ^ hex ^ " instead.")); + Buffer.add_char b (char_of_int u); inext := !inext + 2; | 'u' -> + let fail_no_hex () = fail (Some "Must be followed by a hexadecimal sequence enclosed in curly brackets.") in let (u, a) = try (int_of_string ("0x" ^ String.sub s (i+1) 4), 4) @@ -506,17 +519,19 @@ let unescape s = assert (s.[i+1] = '{'); let l = String.index_from s (i+3) '}' - (i+2) in let u = int_of_string ("0x" ^ String.sub s (i+2) l) in - assert (u <= 0x10FFFF); + if u > 0x10FFFF then + fail (Some "Maximum allowed value for unicode escape sequence is \\u{10FFFF}"); (u, l+2) - with _ -> - fail() + with + | Invalid_escape_sequence (c,i,msg) as e -> raise e + | _ -> fail_no_hex () in - let ub = UTF8.Buf.create 0 in - UTF8.Buf.add_char ub (UChar.uchar_of_int u); - Buffer.add_string b (UTF8.Buf.contents ub); + if u >= 0xD800 && u < 0xE000 then + fail (Some "UTF-16 surrogates are not allowed in strings."); + UTF8.add_uchar b (UChar.uchar_of_int u); inext := !inext + a; | _ -> - fail()); + fail None); loop false !inext; end else match c with @@ -559,9 +574,12 @@ let map_expr loop (e,p) = let tl = List.map tpath tl in let fl = List.map cfield fl in CTExtend (tl,fl) - | CTOptional t -> CTOptional (type_hint t)),p + | CTOptional t -> CTOptional (type_hint t) + | CTNamed (n,t) -> CTNamed (n,type_hint t) + | CTIntersection tl -> CTIntersection(List.map type_hint tl) + ),p and tparamdecl t = - let constraints = List.map type_hint t.tp_constraints in + let constraints = opt type_hint t.tp_constraints in let params = List.map tparamdecl t.tp_params in { tp_name = t.tp_name; tp_constraints = constraints; tp_params = params; tp_meta = t.tp_meta } and func f = @@ -605,10 +623,10 @@ let map_expr loop (e,p) = ENew (t,el) | EUnop (op,f,e) -> EUnop (op,f,loop e) | EVars vl -> - EVars (List.map (fun (n,t,eo) -> + EVars (List.map (fun (n,b,t,eo) -> let t = opt type_hint t in let eo = opt loop eo in - n,t,eo + n,b,t,eo ) vl) | EFunction (n,f) -> EFunction (n,func f) | EBlock el -> EBlock (List.map loop el) @@ -689,13 +707,20 @@ let iter_expr loop (e,p) = | EFunction(_,f) -> List.iter (fun (_,_,_,_,eo) -> opt eo) f.f_args; opt f.f_expr - | EVars vl -> List.iter (fun (_,_,eo) -> opt eo) vl + | EVars vl -> List.iter (fun (_,_,_,eo) -> opt eo) vl let s_object_key_name name = function - | DoubleQuotes -> "\"" ^ s_escape name ^ "\"" + | DoubleQuotes -> "\"" ^ StringHelper.s_escape name ^ "\"" | NoQuotes -> name -let s_expr e = +let s_display_kind = function + | DKCall -> "DKCall" + | DKDot -> "DKDot" + | DKStructure -> "DKStructure" + | DKMarked -> "DKMarked" + | DKPattern _ -> "DKPattern" + +module Printer = struct let rec s_expr_inner tabs (e,_) = match e with | EConst c -> s_constant c @@ -709,7 +734,7 @@ let s_expr e = | ENew (t,el) -> "new " ^ s_complex_type_path tabs t ^ "(" ^ s_expr_list tabs el ", " ^ ")" | EUnop (op,Postfix,e) -> s_expr_inner tabs e ^ s_unop op | EUnop (op,Prefix,e) -> s_unop op ^ s_expr_inner tabs e - | EFunction (Some n,f) -> "function " ^ n ^ s_func tabs f + | EFunction (Some (n,_),f) -> "function " ^ n ^ s_func tabs f | EFunction (None,f) -> "function" ^ s_func tabs f | EVars vl -> "var " ^ String.concat ", " (List.map (s_var tabs) vl) | EBlock [] -> "{ }" @@ -733,7 +758,7 @@ let s_expr e = | ETernary (e1,e2,e3) -> s_expr_inner tabs e1 ^ " ? " ^ s_expr_inner tabs e2 ^ " : " ^ s_expr_inner tabs e3 | ECheckType (e,(t,_)) -> "(" ^ s_expr_inner tabs e ^ " : " ^ s_complex_type tabs t ^ ")" | EMeta (m,e) -> s_metadata tabs m ^ " " ^ s_expr_inner tabs e - | EDisplay (e1,iscall) -> Printf.sprintf "#DISPLAY(%s, %b)" (s_expr_inner tabs e1) iscall + | EDisplay (e1,dk) -> Printf.sprintf "#DISPLAY(%s, %s)" (s_expr_inner tabs e1) (s_display_kind dk) | EDisplayNew tp -> Printf.sprintf "#DISPLAY_NEW(%s)" (s_complex_type_path tabs tp) and s_expr_list tabs el sep = (String.concat sep (List.map (s_expr_inner tabs) el)) @@ -757,13 +782,15 @@ let s_expr e = | CTAnonymous fl -> "{ " ^ String.concat "; " (List.map (s_class_field tabs) fl) ^ "}"; | CTParent(t,_) -> "(" ^ s_complex_type tabs t ^ ")" | CTOptional(t,_) -> "?" ^ s_complex_type tabs t + | CTNamed((n,_),(t,_)) -> n ^ ":" ^ s_complex_type tabs t | CTExtend (tl, fl) -> "{> " ^ String.concat " >, " (List.map (s_complex_type_path tabs) tl) ^ ", " ^ String.concat ", " (List.map (s_class_field tabs) fl) ^ " }" + | CTIntersection tl -> String.concat "&" (List.map (fun (t,_) -> s_complex_type tabs t) tl) and s_class_field tabs f = match f.cff_doc with | Some s -> "/**\n\t" ^ tabs ^ s ^ "\n**/\n" | None -> "" ^ if List.length f.cff_meta > 0 then String.concat ("\n" ^ tabs) (List.map (s_metadata tabs) f.cff_meta) else "" ^ - if List.length f.cff_access > 0 then String.concat " " (List.map s_access f.cff_access) else "" ^ + if List.length f.cff_access > 0 then String.concat " " (List.map s_placed_access f.cff_access) else "" ^ match f.cff_kind with | FVar (t,e) -> "var " ^ (fst f.cff_name) ^ s_opt_type_hint tabs t " : " ^ s_opt_expr tabs e " = " | FProp ((get,_),(set,_),t,e) -> "var " ^ (fst f.cff_name) ^ "(" ^ get ^ "," ^ set ^ ")" ^ s_opt_type_hint tabs t " : " ^ s_opt_expr tabs e " = " @@ -785,12 +812,15 @@ let s_expr e = s_opt_expr tabs f.f_expr " " and s_type_param tabs t = fst (t.tp_name) ^ s_type_param_list tabs t.tp_params ^ - if List.length t.tp_constraints > 0 then ":(" ^ String.concat ", " (List.map ((fun (t,_) -> s_complex_type tabs t)) t.tp_constraints) ^ ")" else "" + begin match t.tp_constraints with + | None -> "" + | Some(th,_) -> ":(" ^ s_complex_type tabs th ^ ")" + end and s_type_param_list tabs tl = if List.length tl > 0 then "<" ^ String.concat ", " (List.map (s_type_param tabs) tl) ^ ">" else "" and s_func_arg tabs ((n,_),o,_,t,e) = if o then "?" else "" ^ n ^ s_opt_type_hint tabs t ":" ^ s_opt_expr tabs e " = " - and s_var tabs ((n,_),t,e) = + and s_var tabs ((n,_),_,t,e) = n ^ (s_opt_type_hint tabs t ":") ^ s_opt_expr tabs e " = " and s_case tabs (el,e1,e2,_) = "case " ^ s_expr_list tabs el ", " ^ @@ -805,7 +835,9 @@ let s_expr e = | (EBlock [],_) -> "" | (EBlock el,_) -> s_block (tabs ^ "\t") el "" "" "" | _ -> s_expr_inner (tabs ^ "\t") e ^ ";" - in s_expr_inner "" e + + let s_expr e = s_expr_inner "" e +end let get_value_meta meta = try @@ -824,6 +856,12 @@ let rec string_list_of_expr_path_raise (e,p) = | EField (e,f) -> f :: string_list_of_expr_path_raise e | _ -> raise Exit +let rec string_pos_list_of_expr_path_raise (e,p) = + match e with + | EConst (Ident i) -> [i,p] + | EField (e,f) -> (f,p) :: string_pos_list_of_expr_path_raise e (* wrong p? *) + | _ -> raise Exit + let expr_of_type_path (sl,s) p = match sl with | [] -> (EConst(Ident s),p) @@ -850,7 +888,7 @@ let match_path recursive sl sl_pattern = in loop sl sl_pattern -let full_dot_path mpath tpath = +let full_dot_path2 mpath tpath = if mpath = tpath then (fst tpath) @ [snd tpath] else @@ -884,4 +922,156 @@ module Expr = struct loop fl with Exit -> true + + let dump_with_pos e = + let buf = Buffer.create 0 in + let add = Buffer.add_string buf in + let rec loop' tabs (e,p) = + let add s = add (Printf.sprintf "%4i-%4i %s%s\n" p.pmin p.pmax tabs s) in + let loop e = loop' (tabs ^ " ") e in + match e with + | EConst ct -> add (s_constant ct) + | EArray(e1,e2) -> + add "EArray"; + loop e1; + loop e2; + | EBinop(op,e1,e2) -> + add ("EBinop " ^ (s_binop op)); + loop e1; + loop e2; + | EField(e1,s) -> + add ("EField " ^ s); + loop e1 + | EParenthesis e1 -> + add "EParenthesis"; + loop e1 + | EObjectDecl fl -> + add "EObjectDecl"; + List.iter (fun ((n,p,_),e1) -> + Buffer.add_string buf (Printf.sprintf "%4i-%4i %s%s\n" p.pmin p.pmax tabs n); + loop e1 + ) fl; + | EArrayDecl el -> + add "EArrayDecl"; + List.iter loop el + | ECall(e1,el) -> + add "ECall"; + loop e1; + List.iter loop el + | ENew((tp,_),el) -> + add ("ENew " ^ s_type_path(tp.tpackage,tp.tname)); + List.iter loop el + | EUnop(op,_,e1) -> + add ("EUnop " ^ (s_unop op)); + loop e1 + | EVars vl -> + add "EVars"; + List.iter (fun ((n,p),_,cto,eo) -> + add (Printf.sprintf "%s %s%s" tabs n (match cto with None -> "" | Some (ct,_) -> ":" ^ Printer.s_complex_type "" ct)); + match eo with + | None -> () + | Some e -> + loop' (Printf.sprintf "%s " tabs) e + ) vl + | EFunction(so,f) -> + add "EFunction"; + Option.may loop f.f_expr; + | EBlock el -> + add "EBlock"; + List.iter loop el + | EFor(e1,e2) -> + add "EFor"; + loop e1; + loop e2; + | EIf(e1,e2,eo) -> + add "EIf"; + loop e1; + loop e2; + Option.may loop eo; + | EWhile(e1,e2,_) -> + add "EWhile"; + loop e1; + loop e2; + | ESwitch(e1,cases,def) -> + add "ESwitch"; + loop e1; + List.iter (fun (el,eg,eo,p) -> + List.iter (loop' (tabs ^ " ")) el; + Option.may (loop' (tabs ^ " ")) eo; + ) cases; + Option.may (fun (eo,_) -> Option.may (loop' (tabs ^ " ")) eo) def + | ETry(e1,catches) -> + add "ETry"; + loop e1; + List.iter (fun (_,_,e,_) -> + loop' (tabs ^ " ") e + ) catches + | EReturn eo -> + add "EReturn"; + Option.may loop eo; + | EBreak -> + add "EBreak"; + | EContinue -> + add "EContinue" + | EUntyped e1 -> + add "EUntyped"; + loop e1; + | EThrow e1 -> + add "EThrow"; + loop e1 + | ECast(e1,_) -> + add "ECast"; + loop e1; + | EDisplay(e1,dk) -> + add ("EDisplay " ^ (s_display_kind dk)); + loop e1 + | ETernary(e1,e2,e3) -> + add "ETernary"; + loop e1; + loop e2; + loop e3; + | ECheckType(e1,_) -> + add "ECheckType"; + loop e1; + | EMeta((m,_,_),e1) -> + add ("EMeta " ^ fst (Meta.get_info m)); + loop e1 + | EDisplayNew _ -> + assert false + in + loop' "" e; + Buffer.contents buf end + +let has_meta_option metas meta s = + let rec loop ml = match ml with + | (meta',el,_) :: ml when meta = meta' -> + if List.exists (fun (e,p) -> + match e with + | EConst(Ident s2) when s = s2 -> true + | _ -> false + ) el then + true + else + loop ml + | _ :: ml -> + loop ml + | [] -> + false + in + loop metas + +let get_meta_options metas meta = + let rec loop ml = match ml with + | (meta',el,_) :: ml when meta = meta' -> + ExtList.List.filter_map (fun (e,p) -> + match e with + | EConst(Ident s2) -> Some s2 + | _ -> None + ) el + | _ :: ml -> + loop ml + | [] -> + [] + in + loop metas \ No newline at end of file diff --git a/src/core/define.ml b/src/core/define.ml index 5a046e71136..ed4176e3f23 100644 --- a/src/core/define.ml +++ b/src/core/define.ml @@ -1,239 +1,30 @@ open Globals +include DefineList type define = { mutable values : (string,string) PMap.t; mutable defines_signature : string option; } -type strict_defined = - | AbsolutePath - | AdvancedTelemetry - | AnnotateSource - (* | Analyzer *) - | As3 - | CheckXmlProxy - | CoreApi - | CoreApiSerialize - | Cppia - | NoCppiaAst - | Dce - | DceDebug - | Debug - | Display - | DisplayStdin - | DllExport - | DllImport - | DocGen - | Dump - | DumpDependencies - | DumpIgnoreVarIds - | DynamicInterfaceClosures - | EraseGenerics - | EvalDebugger - | EvalStack - | EvalTimes - | FastCast - | Fdb - | FileExtension - | FlashStrict - | FlashUseStage - | ForceLibCheck - | ForceNativeProperty - | FormatWarning - | GencommonDebug - | Haxe3Compat - | HaxeBoot - | HaxeVer - | HxcppApiLevel - | HxcppGcGenerational - | HxcppDebugger - | IncludePrefix - | Interp - | JavaVer - | JqueryVer - | JsClassic - | JsEs - | JsUnflatten - | JsSourceMap - | JsEnumsAsObjects - | SourceMap - | KeepOldOutput - | LoopUnrollMaxCost - | LuaVer - | LuaJit - | Macro - | MacroDebug - | MacroTimes - | NekoSource - | NekoV1 - | NetworkSandbox - | NetVer - | NetTarget - | NoCompilation - | NoCOpt - | NoDeprecationWarnings - | NoFlashOverride - | NoDebug - | NoInline - | NoOpt - | NoRoot - | NoSwfCompress - | NoTraces - | Objc - | OldConstructorInline - | OldErrorFormat - | PhpLib - | PhpFront - | PhpPrefix - | RealPosition - | ReplaceFiles - | Scriptable - | ShallowExpose - | SourceHeader - | SourceMapContent - | Swc - | SwfCompressLevel - | SwfDebugPassword - | SwfDirectBlit - | SwfGpu - | SwfMetadata - | SwfPreloaderFrame - | SwfProtected - | SwfScriptTimeout - | SwfUseDoAbc - | Sys - | Unsafe - | UseNekoc - | UseRttiDoc - | Vcproj - | NoMacroCache - | Last (* must be last *) - -type define_parameter = - | HasParam of string - | Platform of platform - | Platforms of platform list - -let infos = function - | AbsolutePath -> "absolute_path",("Print absolute file path in trace output",[]) - | AdvancedTelemetry -> "advanced-telemetry",("Allow the SWF to be measured with Monocle tool",[Platform Flash]) - | AnnotateSource -> "annotate_source",("Add additional comments to generated source code",[Platform Cpp]) - (* | Analyzer -> "analyzer",("Use static analyzer for optimization (experimental)") *) - | As3 -> "as3",("Defined when outputting flash9 as3 source code",[]) - | CheckXmlProxy -> "check_xml_proxy",("Check the used fields of the xml proxy",[]) - | CoreApi -> "core_api",("Defined in the core api context",[]) - | CoreApiSerialize -> "core_api_serialize",("Mark some generated core api classes with the Serializable attribute on C#",[Platform Cs]) - | Cppia -> "cppia",("Generate cpp instruction assembly",[]) - | NoCppiaAst -> "nocppiaast",("Use legacy cppia generation",[]) - | Dce -> "dce",(" Set the dead code elimination mode (default std)",[]) - | DceDebug -> "dce_debug",("Show DCE log",[]) - | Debug -> "debug",("Activated when compiling with -debug",[]) - | Display -> "display",("Activated during completion",[]) - | DisplayStdin -> "display_stdin",("Read the contents of a file specified in --display from standard input",[]) - | DllExport -> "dll_export",("GenCPP experimental linking",[Platform Cpp]) - | DllImport -> "dll_import",("Handle Haxe-generated .NET dll imports",[Platform Cs]) - | DocGen -> "doc_gen",("Do not perform any removal/change in order to correctly generate documentation",[]) - | Dump -> "dump",(" Dump typed AST in dump subdirectory using specified mode or non-prettified default",[]) - | DumpDependencies -> "dump_dependencies",("Dump the classes dependencies in a dump subdirectory",[]) - | DumpIgnoreVarIds -> "dump_ignore_var_ids",("Remove variable IDs from non-pretty dumps (helps with diff)",[]) - | DynamicInterfaceClosures -> "dynamic_interface_closures",("Use slow path for interface closures to save space",[Platform Cpp]) - | EraseGenerics -> "erase_generics",("Erase generic classes on C#",[Platform Cs]) - | EvalDebugger -> "eval_debugger",("Support debugger in macro/interp mode. Allows host:port value to open a socket. Implies eval_stack.",[]) - | EvalStack -> "eval_stack",("Record stack information in macro/interp mode",[]) - | EvalTimes -> "eval_times",("Record per-method execution times in macro/interp mode. Implies eval_stack.",[]) - | FastCast -> "fast_cast",("Enables an experimental casts cleanup on C# and Java",[Platforms [Cs;Java]]) - | Fdb -> "fdb",("Enable full flash debug infos for FDB interactive debugging",[Platform Flash]) - | FileExtension -> "file_extension",("Output filename extension for cpp source code",[Platform Cpp]) - | FlashStrict -> "flash_strict",("More strict typing for flash target",[Platform Flash]) - | FlashUseStage -> "flash_use_stage",("Keep the SWF library initial stage",[Platform Flash]) - (* force_lib_check is only here as a debug facility - compiler checking allows errors to be found more easily *) - | ForceLibCheck -> "force_lib_check",("Force the compiler to check -net-lib and -java-lib added classes (internal)",[Platforms [Cs;Java]]) - | ForceNativeProperty -> "force_native_property",("Tag all properties with :nativeProperty metadata for 3.1 compatibility",[Platform Cpp]) - | FormatWarning -> "format_warning",("Print a warning for each formatted string, for 2.x compatibility",[]) - | GencommonDebug -> "gencommon_debug",("GenCommon internal",[Platforms [Cs;Java]]) - | Haxe3Compat -> "haxe3compat", ("Gives warnings about transition from Haxe 3.x to Haxe 4.0",[]) - | HaxeBoot -> "haxe_boot",("Given the name 'haxe' to the flash boot class instead of a generated name",[Platform Flash]) - | HaxeVer -> "haxe_ver",("The current Haxe version value",[]) - | HxcppApiLevel -> "hxcpp_api_level",("Provided to allow compatibility between hxcpp versions",[Platform Cpp]) - | HxcppGcGenerational -> "HXCPP_GC_GENERATIONAL",("Experimental Garbage Collector",[Platform Cpp]) - | HxcppDebugger -> "HXCPP_DEBUGGER",("Include additional information for HXCPP_DEBUGGER",[Platform Cpp]) - | IncludePrefix -> "include_prefix",("prepend path to generated include files",[Platform Cpp]) - | Interp -> "interp",("The code is compiled to be run with --interp",[]) - | JavaVer -> "java_ver",(" Sets the Java version to be targeted",[Platform Java]) - | JqueryVer -> "jquery_ver",("The jQuery version supported by js.jquery.*. The version is encoded as an integer. e.g. 1.11.3 is encoded as 11103",[Platform Js]) - | JsClassic -> "js_classic",("Don't use a function wrapper and strict mode in JS output",[Platform Js]) - | JsEs -> "js_es",("Generate JS compliant with given ES standard version (default 5)",[Platform Js; HasParam "version number"]) - | JsEnumsAsObjects -> "js_enums_as_objects",("Generate enum representation as object instead of as array",[Platform Js]) - | JsUnflatten -> "js_unflatten",("Generate nested objects for packages and types",[Platform Js]) - | JsSourceMap -> "js_source_map",("Generate JavaScript source map even in non-debug mode",[Platform Js]) - | SourceMap -> "source_map",("Generate source map for compiled files (Currently supported for php only)",[Platform Php]) - | KeepOldOutput -> "keep_old_output",("Keep old source files in the output directory (for C#/Java)",[Platforms [Cs;Java]]) - | LoopUnrollMaxCost -> "loop_unroll_max_cost",("Maximum cost (number of expressions * iterations) before loop unrolling is canceled (default 250)",[]) - | LuaJit -> "lua_jit",("Enable the jit compiler for lua (version 5.2 only)",[Platform Lua]) - | LuaVer -> "lua_ver",("The lua version to target",[Platform Lua]) - | Macro -> "macro",("Defined when code is compiled in the macro context",[]) - | MacroDebug -> "macro_debug",("Show warnings for potential macro problems (e.g. macro-in-macro calls)",[]) - | MacroTimes -> "macro_times",("Display per-macro timing when used with --times",[]) - | NetVer -> "net_ver",(" Sets the .NET version to be targeted",[Platform Cs]) - | NetTarget -> "net_target",(" Sets the .NET target. Defaults to \"net\". xbox, micro (Micro Framework), compact (Compact Framework) are some valid values",[Platform Cs]) - | NekoSource -> "neko_source",("Output neko source instead of bytecode",[Platform Neko]) - | NekoV1 -> "neko_v1",("Keep Neko 1.x compatibility",[Platform Neko]) - | NetworkSandbox -> "network-sandbox",("Use local network sandbox instead of local file access one",[Platform Flash]) - | NoCompilation -> "no-compilation",("Disable final compilation",[Platforms [Cs;Java;Cpp;Hl]]) - | NoCOpt -> "no_copt",("Disable completion optimization (for debug purposes)",[]) - | NoDebug -> "no_debug",("Remove all debug macros from cpp output",[]) - | NoDeprecationWarnings -> "no-deprecation-warnings",("Do not warn if fields annotated with @:deprecated are used",[]) - | NoFlashOverride -> "no-flash-override",("Change overrides on some basic classes into HX suffixed methods, flash only",[Platform Flash]) - | NoOpt -> "no_opt",("Disable optimizations",[]) - | NoInline -> "no_inline",("Disable inlining",[]) - | NoRoot -> "no_root",("Generate top-level types into haxe.root namespace",[Platform Cs]) - | NoMacroCache -> "no_macro_cache",("Disable macro context caching",[]) - | NoSwfCompress -> "no_swf_compress",("Disable SWF output compression",[Platform Flash]) - | NoTraces -> "no_traces",("Disable all trace calls",[]) - | Objc -> "objc",("Sets the hxcpp output to objective-c++ classes. Must be defined for interop",[Platform Cpp]) - | OldConstructorInline -> "old-constructor-inline",("Use old constructor inlining logic (from haxe 3.4.2) instead of the reworked version.",[]) - | OldErrorFormat -> "old-error-format",("Use Haxe 3.x zero-based column error messages instead of new one-based format.",[]) - | PhpPrefix -> "php_prefix",("Root namespace for generated php classes. E.g. if compiled with`--php-prefix some.sub`, then all classes will be generated in `\\some\\sub` namespace.",[Platform Php]) - | PhpLib -> "php_lib",("Select the name for the php lib folder.",[Platform Php]) - | PhpFront -> "php_front",("Select the name for the php front file (by default: `index.php`).", [Platform Php]) - | RealPosition -> "real_position",("Disables Haxe source mapping when targetting C#, removes position comments in Java and Php output",[Platforms [Cs;Java;Php]]) - | ReplaceFiles -> "replace_files",("GenCommon internal",[Platforms [Java;Cs]]) - | Scriptable -> "scriptable",("GenCPP internal",[Platform Cpp]) - | ShallowExpose -> "shallow-expose",("Expose types to surrounding scope of Haxe generated closure without writing to window object",[Platform Js]) - | SourceHeader -> "source-header",("Print value as comment on top of generated files, use '' value to disable",[]) - | SourceMapContent -> "source-map-content",("Include the hx sources as part of the JS source map",[Platform Js]) - | Swc -> "swc",("Output a SWC instead of a SWF",[Platform Flash]) - | SwfCompressLevel -> "swf_compress_level",(" Set the amount of compression for the SWF output",[Platform Flash]) - | SwfDebugPassword -> "swf_debug_password",("Set a password for debugging",[Platform Flash]) - | SwfDirectBlit -> "swf_direct_blit",("Use hardware acceleration to blit graphics",[Platform Flash]) - | SwfGpu -> "swf_gpu",("Use GPU compositing features when drawing graphics",[Platform Flash]) - | SwfMetadata -> "swf_metadata",(" Include contents of as metadata in the swf",[Platform Flash]) - | SwfPreloaderFrame -> "swf_preloader_frame",("Insert empty first frame in swf",[Platform Flash]) - | SwfProtected -> "swf_protected",("Compile Haxe private as protected in the SWF instead of public",[Platform Flash]) - | SwfScriptTimeout -> "swf_script_timeout",("Maximum ActionScript processing time before script stuck dialog box displays (in seconds)",[Platform Flash]) - | SwfUseDoAbc -> "swf_use_doabc",("Use DoAbc swf-tag instead of DoAbcDefine",[Platform Flash]) - | Sys -> "sys",("Defined for all system platforms",[]) - | Unsafe -> "unsafe",("Allow unsafe code when targeting C#",[Platform Cs]) - | UseNekoc -> "use_nekoc",("Use nekoc compiler instead of internal one",[Platform Neko]) - | UseRttiDoc -> "use_rtti_doc",("Allows access to documentation during compilation",[]) - | Vcproj -> "vcproj",("GenCPP internal",[Platform Cpp]) - | Last -> assert false - let get_documentation_list() = let m = ref 0 in let rec loop i = let d = Obj.magic i in if d <> Last then begin let t, (doc,flags) = infos d in - let pfs = ref [] in + let params = ref [] and pfs = ref [] in List.iter (function - | HasParam s -> () (* TODO *) - | Platform p -> pfs := p :: !pfs; - | Platforms pl -> pfs := pl @ !pfs; + | HasParam s -> params := s :: !params + | Platforms fl -> pfs := fl @ !pfs + | Link _ -> () ) flags; + let params = (match List.rev !params with + | [] -> "" + | l -> "<" ^ String.concat ">, <" l ^ "> " + ) in let pfs = platform_list_help (List.rev !pfs) in if String.length t > !m then m := String.length t; - ((String.concat "-" (ExtString.String.nsplit t "_")),doc ^ pfs) :: (loop (i + 1)) + ((String.concat "-" (ExtString.String.nsplit t "_")),params ^ doc ^ pfs) :: (loop (i + 1)) end else [] in @@ -256,13 +47,16 @@ let defined_value_safe ?default ctx v = try defined_value ctx v with Not_found -> match default with Some s -> s | None -> "" -let raw_define ctx v = - let k,v = try ExtString.String.split v "=" with _ -> v,"1" in +let raw_define_value ctx k v = ctx.values <- PMap.add k v ctx.values; let k = String.concat "_" (ExtString.String.nsplit k "-") in ctx.values <- PMap.add k v ctx.values; ctx.defines_signature <- None +let raw_define ctx v = + let k,v = try ExtString.String.split v "=" with _ -> v,"1" in + raw_define_value ctx k v + let define_value ctx k v = raw_define ctx (fst (infos k) ^ "=" ^ v) @@ -277,11 +71,16 @@ let get_signature def = (* don't make much difference between these special compilation flags *) match String.concat "_" (ExtString.String.nsplit k "-") with (* If we add something here that might be used in conditional compilation it should be added to - Parser.parse_macro_ident as well (issue #5682). *) - | "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin" -> acc + Parser.parse_macro_ident as well (issue #5682). + Note that we should removed flags like use_rtti_doc here. + *) + | "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin" + | "dump" | "dump_dependencies" | "dump_ignore_var_ids" -> acc | _ -> (k ^ "=" ^ v) :: acc ) def.values [] in let str = String.concat "@" (List.sort compare defines) in let s = Digest.string str in def.defines_signature <- Some s; - s \ No newline at end of file + s + +let is_haxe3_compat def = raw_defined def "hx3compat" diff --git a/src/core/display/completionItem.ml b/src/core/display/completionItem.ml new file mode 100644 index 00000000000..ac0a17785e8 --- /dev/null +++ b/src/core/display/completionItem.ml @@ -0,0 +1,718 @@ +open Globals +open Ast +open Type +open Genjson + +type toplevel_kind = + | TKExpr of pos + | TKType + | TKPattern of pos + | TKOverride + | TKField of pos + +module CompletionModuleKind = struct + type t = + | Class + | Interface + | Enum + | Abstract + | EnumAbstract + | TypeAlias + | Struct + | TypeParameter + + let to_int = function + | Class -> 0 + | Interface -> 1 + | Enum -> 2 + | Abstract -> 3 + | EnumAbstract -> 4 + | TypeAlias -> 5 + | Struct -> 6 + | TypeParameter -> 7 +end + +module ImportStatus = struct + type t = + | Imported + | Unimported + | Shadowed + + let to_int = function + | Imported -> 0 + | Unimported -> 1 + | Shadowed -> 2 +end + +module CompletionModuleType = struct + open CompletionModuleKind + + type not_bool = + | Yes + | YesButPrivate + | No + | Maybe + + type module_type_source = + | Syntax of type_def (* TODO: do we really want to keep this? *) + | Typed of module_type + + type t = { + pack : string list; + name : string; + module_name : string; + pos : pos; + is_private : bool; + params : Ast.type_param list; + meta: metadata; + doc : documentation; + is_extern : bool; + is_final : bool; + kind : CompletionModuleKind.t; + has_constructor : not_bool; + source : module_type_source; + } + + let of_type_decl pack module_name (td,p) = match td with + | EClass d -> + let ctor = + try + let cff = List.find (fun cff -> fst cff.cff_name = "new") d.d_data in + if List.mem HExtern d.d_flags || List.exists (fun (acc,_) -> acc = APublic) cff.cff_access then Yes + else YesButPrivate + with Not_found -> + if (List.exists (function HExtends _ -> true | _ -> false) d.d_flags) then Maybe + else No + in + { + pack = pack; + name = fst d.d_name; + module_name = module_name; + pos = p; + is_private = List.mem HPrivate d.d_flags; + params = d.d_params; + meta = d.d_meta; + doc = d.d_doc; + is_extern = List.mem HExtern d.d_flags; + is_final = List.mem HFinal d.d_flags; + kind = if List.mem HInterface d.d_flags then Interface else Class; + has_constructor = ctor; + source = Syntax td; + } + | EEnum d -> { + pack = pack; + name = fst d.d_name; + module_name = module_name; + pos = p; + is_private = List.mem EPrivate d.d_flags; + params = d.d_params; + meta = d.d_meta; + doc = d.d_doc; + is_extern = List.mem EExtern d.d_flags; + is_final = false; + kind = Enum; + has_constructor = No; + source = Syntax td; + } + | ETypedef d -> + let kind = match fst d.d_data with CTAnonymous _ -> Struct | _ -> TypeAlias in + { + pack = pack; + name = fst d.d_name; + module_name = module_name; + pos = p; + is_private = List.mem EPrivate d.d_flags; + params = d.d_params; + meta = d.d_meta; + doc = d.d_doc; + is_extern = List.mem EExtern d.d_flags; + is_final = false; + kind = kind; + has_constructor = if kind = Struct then No else Maybe; + source = Syntax td; + } + | EAbstract d -> + let ctor = + try + let cff = List.find (fun cff -> fst cff.cff_name = "new") d.d_data in + if List.exists (fun (acc,_) -> acc = APublic) cff.cff_access then Yes else YesButPrivate + with Not_found -> + No + in + { + pack = pack; + name = fst d.d_name; + module_name = module_name; + pos = p; + is_private = List.mem AbPrivate d.d_flags; + params = d.d_params; + meta = d.d_meta; + doc = d.d_doc; + is_extern = List.mem AbExtern d.d_flags; + is_final = false; + kind = if Meta.has Meta.Enum d.d_meta then EnumAbstract else Abstract; + has_constructor = ctor; + source = Syntax td; + } + | EImport _ | EUsing _ -> + raise Exit + + let of_module_type mt = + let actor a = match a.a_impl with + | None -> No + | Some c -> + try + let cf = PMap.find "_new" c.cl_statics in + if c.cl_extern || (has_class_field_flag cf CfPublic) then Yes else YesButPrivate + with Not_found -> + No + in + let ctor c = + try + let _,cf = get_constructor (fun cf -> cf.cf_type) c in + if c.cl_extern || (has_class_field_flag cf CfPublic) then Yes else YesButPrivate + with Not_found -> + No + in + let is_extern,is_final,kind,ctor = match mt with + | TClassDecl c -> + c.cl_extern,c.cl_final,(if c.cl_interface then Interface else Class),ctor c + | TEnumDecl en -> + en.e_extern,false,Enum,No + | TTypeDecl td -> + let kind,ctor = match follow td.t_type with + | TAnon _ -> Struct,No + | TInst(c,_) -> TypeAlias,ctor c + | TAbstract(a,_) -> TypeAlias,actor a + | _ -> TypeAlias,No + in + false,false,kind,ctor + | TAbstractDecl a -> + false,false,(if Meta.has Meta.Enum a.a_meta then EnumAbstract else Abstract),actor a + in + let infos = t_infos mt in + let convert_type_param (s,t) = match follow t with + | TInst(c,_) -> { + tp_name = s,null_pos; + tp_params = []; + tp_constraints = None; (* TODO? *) + tp_meta = c.cl_meta + } + | _ -> + assert false + in + { + pack = fst infos.mt_path; + name = snd infos.mt_path; + module_name = snd infos.mt_module.m_path; + pos = infos.mt_pos; + is_private = infos.mt_private; + params = List.map convert_type_param infos.mt_params; + meta = infos.mt_meta; + doc = infos.mt_doc; + is_extern = is_extern; + is_final = is_final; + kind = kind; + has_constructor = ctor; + source = Typed mt; + } + + let get_path cm = (cm.pack,cm.name) + + let to_json ctx cm is = + let fields = + ("path",jobject [ + ("pack",jlist jstring cm.pack); + ("moduleName",jstring cm.module_name); + ("typeName",jstring cm.name); + ("importStatus",jint (ImportStatus.to_int is)); + ]) :: + ("kind",jint (to_int cm.kind)) :: + (match ctx.generation_mode with + | GMFull | GMWithoutDoc -> + ("meta",generate_metadata ctx cm.meta) :: + ("pos",generate_pos ctx cm.pos) :: + ("params",jlist (generate_ast_type_param ctx) cm.params) :: + ("isExtern",jbool cm.is_extern) :: + ("isFinal",jbool cm.is_final) :: + (if ctx.generation_mode = GMFull then ["doc",jopt jstring cm.doc] else []) + | GMMinimum -> + match generate_minimum_metadata ctx cm.meta with + | None -> [] + | Some meta -> [("meta",meta)] + ) + in + jobject fields +end + +module ClassFieldOrigin = struct + type t = + | Self of module_type + | StaticImport of module_type + | Parent of module_type + | StaticExtension of module_type + | AnonymousStructure of tanon + | BuiltIn + | Unknown + + let to_json ctx cfo = + let i,args = match cfo with + | Self mt -> 0,if ctx.generation_mode = GMMinimum then None else Some (generate_module_type ctx mt) + | StaticImport mt -> 1,if ctx.generation_mode = GMMinimum then None else Some (generate_module_type ctx mt) + | Parent mt -> 2,if ctx.generation_mode = GMMinimum then None else Some (generate_module_type ctx mt) + | StaticExtension mt -> 3,if ctx.generation_mode = GMMinimum then None else Some (generate_module_type ctx mt) + | AnonymousStructure an -> 4,if ctx.generation_mode = GMMinimum then None else Some (generate_anon ctx an) + | BuiltIn -> 5,None + | Unknown -> 6,None + in + jobject ( + ("kind",jint i) :: (match args with None -> [] | Some arg -> ["args",arg]) + ) +end + +let decl_of_class c = match c.cl_kind with + | KAbstractImpl a -> TAbstractDecl a + | _ -> TClassDecl c + +module CompletionClassField = struct + type t = { + field : tclass_field; + scope : class_field_scope; + origin : ClassFieldOrigin.t; + is_qualified : bool; + } + + let make cf scope origin is_qualified = { + field = cf; + scope = scope; + origin = origin; + is_qualified = is_qualified; + } +end + +module CompletionEnumField = struct + type t = { + efield : tenum_field; + eorigin : ClassFieldOrigin.t; + eis_qualified : bool; + } + + let make ef origin is_qualified = { + efield = ef; + eorigin = origin; + eis_qualified = is_qualified; + } +end + +module PackageContentKind = struct + type t = + | PCKModule + | PCKPackage + + let to_int = function + | PCKModule -> 0 + | PCKPackage -> 1 +end + +module CompletionType = struct + + type ct_path_with_params = { + ct_pack : string list; + ct_type_name : string; + ct_module_name : string; + ct_params : t list; + ct_import_status : ImportStatus.t; + } + + and ct_function_argument = { + ct_name : string; + ct_optional : bool; + ct_type : t; + ct_value : Ast.expr option; + } + + and ct_function = { + ct_args : ct_function_argument list; + ct_return : t; + } + + and ct_anonymous_field = { + ctf_field : tclass_field; + ctf_type : t; + } + + and ct_anonymous = { + ct_fields : ct_anonymous_field list; + ct_status : anon_status; + } + + and t = + | CTMono + | CTInst of ct_path_with_params + | CTEnum of ct_path_with_params + | CTTypedef of ct_path_with_params + | CTAbstract of ct_path_with_params + | CTFunction of ct_function + | CTAnonymous of ct_anonymous + | CTDynamic of t option + + let rec generate_path_with_params ctx pwp = jobject [ + "path",jobject [ + "pack",jlist jstring pwp.ct_pack; + "moduleName",jstring pwp.ct_module_name; + "typeName",jstring pwp.ct_type_name; + "importStatus",jint (ImportStatus.to_int pwp.ct_import_status); + ]; + "params",jlist (generate_type ctx) pwp.ct_params; + ] + + and generate_function_argument ctx cfa = jobject [ + "name",jstring cfa.ct_name; + "opt",jbool cfa.ct_optional; + "t",generate_type ctx cfa.ct_type; + "value",jopt (fun e -> jobject [ + "string",jstring (Ast.Printer.s_expr e); + ]) cfa.ct_value; + ] + + and generate_function' ctx ctf = [ + "args",jlist (generate_function_argument ctx) ctf.ct_args; + "ret",generate_type ctx ctf.ct_return; + ] + + and generate_function ctx ctf = jobject (generate_function' ctx ctf) + + and generate_anon_field ctx af = + let fields = generate_class_field' ctx CFSMember af.ctf_field in + let fields = List.filter (fun (n,_) -> n <> "type") fields in + let fields = ("type",generate_type ctx af.ctf_type) :: fields in + jobject fields + + and generate_anon ctx cta = + let fields = List.sort (fun ctf1 ctf2 -> + compare ctf1.ctf_field.cf_name_pos.pmin ctf2.ctf_field.cf_name_pos.pmin + ) cta.ct_fields in + jobject [ + "status",generate_anon_status ctx cta.ct_status; + "fields",jlist (generate_anon_field ctx) fields; + ] + + and generate_type ctx ct = + let name,args = match ct with + | CTMono -> "TMono",None + | CTInst pwp -> "TInst",Some (generate_path_with_params ctx pwp) + | CTEnum pwp -> "TEnum",Some (generate_path_with_params ctx pwp) + | CTTypedef pwp -> "TType",Some (generate_path_with_params ctx pwp) + | CTAbstract pwp -> "TAbstract",Some (generate_path_with_params ctx pwp) + | CTFunction ctf -> "TFun",Some (generate_function ctx ctf) + | CTAnonymous cta -> "TAnonymous",Some (generate_anon ctx cta) + | CTDynamic cto -> "TDynamic",Option.map (generate_type ctx) cto; + in + generate_adt ctx None name args + + let to_json ctx ct = + generate_type ctx ct +end + +open CompletionModuleType +open CompletionClassField +open CompletionEnumField + +type t_kind = + | ITLocal of tvar + | ITClassField of CompletionClassField.t + | ITEnumField of CompletionEnumField.t + | ITEnumAbstractField of tabstract * CompletionClassField.t + | ITType of CompletionModuleType.t * ImportStatus.t + | ITPackage of path * (string * PackageContentKind.t) list + | ITModule of path + | ITLiteral of string + | ITTimer of string * string + | ITMetadata of Meta.strict_meta + | ITKeyword of keyword + | ITAnonymous of tanon + | ITExpression of texpr + | ITTypeParameter of tclass + +type t = { + ci_kind : t_kind; + ci_type : (Type.t * CompletionType.t) option; +} + +let make kind t = { + ci_kind = kind; + ci_type = t; +} + +let make_ci_local v t = make (ITLocal v) (Some t) +let make_ci_class_field ccf t = make (ITClassField ccf) (Some t) +let make_ci_enum_abstract_field a ccf t = make (ITEnumAbstractField(a,ccf)) (Some t) +let make_ci_enum_field cef t = make (ITEnumField cef) (Some t) +let make_ci_type mt import_status t = make (ITType(mt,import_status)) t +let make_ci_package path l = make (ITPackage(path,l)) None +let make_ci_module path = make (ITModule path) None +let make_ci_literal lit t = make (ITLiteral lit) (Some t) +let make_ci_timer name value = make (ITTimer(name,value)) None +let make_ci_metadata meta = make (ITMetadata meta) None +let make_ci_keyword kwd = make (ITKeyword kwd) None +let make_ci_anon an t = make (ITAnonymous an) (Some t) +let make_ci_expr e t = make (ITExpression e) (Some t) +let make_ci_type_param c t = make (ITTypeParameter c) (Some t) + +let get_index item = match item.ci_kind with + | ITLocal _ -> 0 + | ITClassField _ -> 1 + | ITEnumField _ -> 2 + | ITEnumAbstractField _ -> 3 + | ITType _ -> 4 + | ITPackage _ -> 5 + | ITModule _ -> 6 + | ITLiteral _ -> 7 + | ITTimer _ -> 8 + | ITMetadata _ -> 9 + | ITKeyword _ -> 10 + | ITAnonymous _ -> 11 + | ITExpression _ -> 12 + | ITTypeParameter _ -> 13 + +let get_sort_index tk item p expected_name = match item.ci_kind with + | ITLocal v -> + let i = p.pmin - v.v_pos.pmin in + let i = if i < 0 then 0 else i in + let s = Printf.sprintf "%05i" i in + let s = match expected_name with + | None -> s + | Some name -> + let i = StringError.levenshtein name v.v_name in + Printf.sprintf "%05i%s" i s + in + 0,s + | ITClassField ccf -> + let open ClassFieldOrigin in + let i = match ccf.origin,ccf.scope with + | Self _,(CFSMember | CFSConstructor) -> 10 + | Parent _,(CFSMember | CFSConstructor) -> 11 + | StaticExtension _,_ -> 12 + | Self _,CFSStatic -> 13 + | StaticImport _,_ -> 14 + | _ -> 15 + in + i,ccf.field.cf_name + | ITEnumField ef -> + (match tk with TKPattern _ | TKField _ -> -1 | _ -> 20),(Printf.sprintf "%04i" ef.efield.ef_index) + | ITEnumAbstractField(_,ccf) -> + (match tk with TKPattern _ | TKField _ -> -1 | _ -> 21),ccf.field.cf_name + | ITTypeParameter c -> + 30,snd c.cl_path + | ITType(cmt,is) -> + let open ImportStatus in + let i = match is with + | Imported -> 31 + | Unimported -> 32 + | Shadowed -> 33 + in + i,(s_type_path (cmt.pack,cmt.name)) + | ITPackage(path,_) -> + 40,s_type_path path + | ITModule path -> + 40,s_type_path path + | ITLiteral name -> + 50,name + | ITKeyword name -> + 60,s_keyword name + | ITAnonymous _ + | ITExpression _ + | ITTimer _ + | ITMetadata _ -> + 500,"" + +let legacy_sort item = match item.ci_kind with + | ITClassField(cf) | ITEnumAbstractField(_,cf) -> + begin match cf.field.cf_kind with + | Var _ -> 0,cf.field.cf_name + | Method _ -> 1,cf.field.cf_name + end + | ITEnumField ef -> + let ef = ef.efield in + begin match follow ef.ef_type with + | TFun _ -> 1,ef.ef_name + | _ -> 0,ef.ef_name + end + | ITType(cm,_) -> 2,cm.name + | ITModule path -> 3,snd path + | ITPackage(path,_) -> 4,snd path + | ITMetadata meta -> 5,Meta.to_string meta + | ITTimer(s,_) -> 6,s + | ITLocal v -> 7,v.v_name + | ITLiteral s -> 9,s + | ITKeyword kwd -> 10,s_keyword kwd + | ITAnonymous _ -> 11,"" + | ITExpression _ -> 12,"" + | ITTypeParameter _ -> 13,"" + +let get_name item = match item.ci_kind with + | ITLocal v -> v.v_name + | ITClassField(cf) | ITEnumAbstractField(_,cf) -> cf.field.cf_name + | ITEnumField ef -> ef.efield.ef_name + | ITType(cm,_) -> cm.name + | ITPackage(path,_) -> snd path + | ITModule path -> snd path + | ITLiteral s -> s + | ITTimer(s,_) -> s + | ITMetadata meta -> Meta.to_string meta + | ITKeyword kwd -> s_keyword kwd + | ITAnonymous _ -> "" + | ITExpression _ -> "" + | ITTypeParameter c -> snd c.cl_path + +let get_type item = item.ci_type + +let get_filter_name item = match item.ci_kind with + | ITLocal v -> v.v_name + | ITClassField(cf) | ITEnumAbstractField(_,cf) -> cf.field.cf_name + | ITEnumField ef -> ef.efield.ef_name + | ITType(cm,_) -> s_type_path (cm.pack,cm.name) + | ITPackage(path,_) -> s_type_path path + | ITModule path -> s_type_path path + | ITLiteral s -> s + | ITTimer(s,_) -> s + | ITMetadata meta -> Meta.to_string meta + | ITKeyword kwd -> s_keyword kwd + | ITAnonymous _ -> "" + | ITExpression _ -> "" + | ITTypeParameter c -> snd c.cl_path + +let get_documentation item = match item.ci_kind with + | ITClassField cf | ITEnumAbstractField(_,cf) -> cf.field.cf_doc + | ITEnumField ef -> ef.efield.ef_doc + | ITType(mt,_) -> mt.doc + | _ -> None + +let to_json ctx index item = + let open ClassFieldOrigin in + let kind,data = match item.ci_kind with + | ITLocal v -> "Local",generate_tvar ctx v + | ITClassField(cf) | ITEnumAbstractField(_,cf) -> + let name = match item.ci_kind with + | ITClassField _ -> "ClassField" + | _ -> "EnumAbstractField" + in + let qualifier = match cf.scope,cf.origin with + | CFSStatic,(Self mt | Parent mt | StaticExtension mt | StaticImport mt) -> + let infos = t_infos mt in + jstring (s_type_path (Path.full_dot_path (fst infos.mt_module.m_path) (snd infos.mt_module.m_path) (snd infos.mt_path))) + | CFSMember,Self _ -> + jstring "this" + | CFSMember,Parent _-> + jstring "super" + | _ -> + jnull + in + name,jobject [ + "field",generate_class_field ctx cf.scope cf.field; + "origin",ClassFieldOrigin.to_json ctx cf.origin; + "resolution",jobject [ + "isQualified",jbool cf.is_qualified; + "qualifier",qualifier; + ] + ] + | ITEnumField ef -> + let qualifier = match ef.eorigin with + | Self mt | StaticImport mt -> + let infos = t_infos mt in + jstring (s_type_path (Path.full_dot_path (fst infos.mt_module.m_path) (snd infos.mt_module.m_path) (snd infos.mt_path))) + | _ -> + jnull + in + "EnumField",jobject [ + "field",generate_enum_field ctx ef.efield; + "origin",ClassFieldOrigin.to_json ctx ef.eorigin; + "resolution",jobject [ + "isQualified",jbool ef.eis_qualified; + "qualifier",qualifier; + ] + ] + | ITType(kind,is) -> "Type",CompletionModuleType.to_json ctx kind is + | ITPackage(path,contents) -> + let generate_package_content (name,kind) = jobject [ + "name",jstring name; + "kind",jint (PackageContentKind.to_int kind); + ] in + "Package",jobject [ + "path",generate_package_path (fst path @ [snd path]); + "contents",jlist generate_package_content contents; + ] + | ITModule path -> "Module",jobject [ + "path",generate_module_path path; + ] + | ITLiteral s -> "Literal",jobject [ + "name",jstring s; + ] + | ITTimer(s,value) -> "Timer",jobject [ + "name",jstring s; + "value",jstring value; + ] + | ITMetadata meta -> + let open Meta in + let name,(doc,params) = Meta.get_info meta in + let name = "@" ^ name in + let usage_to_string = function + | TClass -> "TClass" + | TClassField -> "TClassField" + | TAbstract -> "TAbstract" + | TAbstractField -> "TAbstractField" + | TEnum -> "TEnum" + | TTypedef -> "TTypedef" + | TAnyField -> "TAnyField" + | TExpr -> "TExpr" + | TTypeParameter -> "TTypeParameter" + | TVariable -> "TVariable" + in + let rec loop internal params platforms targets links l = match l with + | HasParam s :: l -> loop internal (s :: params) platforms targets links l + | Platforms pls :: l -> loop internal params ((List.map platform_name pls) @ platforms) targets links l + | UsedOn usages :: l -> loop internal params platforms ((List.map usage_to_string usages) @ targets) links l + | UsedInternally :: l -> loop true params platforms targets links l + | Link url :: l -> loop internal params platforms targets (url :: links) l + | [] -> internal,params,platforms,targets,links + in + let internal,params,platforms,targets,links = loop false [] [] [] [] params in + "Metadata",jobject [ + "name",jstring name; + "doc",jstring doc; + "parameters",jlist jstring params; + "platforms",jlist jstring platforms; + "targets",jlist jstring targets; + "internal",jbool internal; + "links",jlist jstring links; + ] + | ITKeyword kwd ->"Keyword",jobject [ + "name",jstring (s_keyword kwd) + ] + | ITAnonymous an -> "AnonymousStructure",generate_anon ctx an + | ITExpression e -> "Expression",generate_texpr ctx e + | ITTypeParameter c -> + begin match c.cl_kind with + | KTypeParameter tl -> + "TypeParameter",jobject [ + "name",jstring (snd c.cl_path); + "meta",generate_metadata ctx c.cl_meta; + "constraints",jlist (generate_type ctx) tl; + ] + | _ -> assert false + end + in + let jindex = match index with + | None -> [] + | Some index -> ["index",jint index] + in + jobject ( + ("kind",jstring kind) :: + ("args",data) :: + (match item.ci_type with + | None -> + jindex + | Some t -> + ("type",CompletionType.to_json ctx (snd t)) :: jindex + ) + ) \ No newline at end of file diff --git a/src/core/display/displayPosition.ml b/src/core/display/displayPosition.ml new file mode 100644 index 00000000000..53394e529e9 --- /dev/null +++ b/src/core/display/displayPosition.ml @@ -0,0 +1,58 @@ +open Globals + +let encloses_position p_target p = + p_target.pmin <> -1 && p_target.pmax <> -1 && p.pmin <= p_target.pmin && p.pmax >= p_target.pmax + +let encloses_position_gt p_target p = + p_target.pmin <> -1 && p_target.pmax <> -1 && p.pmin <= p_target.pmin && p.pmax > p_target.pmax + +class display_position_container = + object (self) + (** Current display position *) + val mutable pos = null_pos + (** + Display position value which was set with the latest `display_position#set p` call. + Kept even after `display_position#reset` call. + *) + val mutable last_pos = null_pos + (** + Set current display position + *) + method set p = + pos <- p; + last_pos <- p + (** + Get current display position + *) + method get = + pos + (** + Clears current display position. + *) + method reset = + pos <- null_pos + (** + Check if `p` contains current display position + *) + method enclosed_in p = + encloses_position pos p + (** + Check if `file` contains current display position + *) + method is_in_file file = + file <> "?" && Path.unique_full_path file = pos.pfile + (** + Cut `p` at the position of the latest `display_position#set pos` call. + *) + method cut p = + { p with pmax = last_pos.pmax } + (** + Temporarily reset display position, run `fn` and then restore display position. + *) + method run_outside : 'a . (unit->'a) -> 'a = fun fn -> + let display_pos = self#get in + self#reset; + Std.finally (fun () -> self#set display_pos) fn () + end + +let display_position = new display_position_container \ No newline at end of file diff --git a/src/core/displayTypes.ml b/src/core/displayTypes.ml new file mode 100644 index 00000000000..39f9c30eaa5 --- /dev/null +++ b/src/core/displayTypes.ml @@ -0,0 +1,295 @@ +open Globals +open Path +open Ast +open Type +open Json +open Genjson + +module SymbolKind = struct + type t = + | Class + | Interface + | Enum + | Typedef + | Abstract + | Field + | Property + | Method + | Constructor + | Function + | Variable + + let to_int = function + | Class -> 1 + | Interface -> 2 + | Enum -> 3 + | Typedef -> 4 + | Abstract -> 5 + | Field -> 6 + | Property -> 7 + | Method -> 8 + | Constructor -> 9 + | Function -> 10 + | Variable -> 11 +end + +module SymbolInformation = struct + type t = { + name : string; + kind : SymbolKind.t; + pos : Globals.pos; + container_name : string option; + } + + let make name kind pos container_name = { + name = name; + kind = kind; + pos = pos; + container_name = container_name; + } +end + +module DiagnosticsSeverity = struct + type t = + | Error + | Warning + | Information + | Hint + + let to_int = function + | Error -> 1 + | Warning -> 2 + | Information -> 3 + | Hint -> 4 +end + +module DiagnosticsKind = struct + type t = + | DKUnusedImport + | DKUnresolvedIdentifier + | DKCompilerError + | DKRemovableCode + | DKParserError + | DKDeprecationWarning + + let to_int = function + | DKUnusedImport -> 0 + | DKUnresolvedIdentifier -> 1 + | DKCompilerError -> 2 + | DKRemovableCode -> 3 + | DKParserError -> 4 + | DKDeprecationWarning -> 5 +end + +module CompletionResultKind = struct + type t = + | CRField of CompletionItem.t * pos * Type.t option * (Type.t * Type.t) option + | CRStructureField + | CRToplevel of (CompletionItem.CompletionType.t * CompletionItem.CompletionType.t) option + | CRMetadata + | CRTypeHint + | CRExtends + | CRImplements + | CRStructExtension of bool + | CRImport + | CRUsing + | CRNew + | CRPattern of (CompletionItem.CompletionType.t * CompletionItem.CompletionType.t) option * bool + | CROverride + | CRTypeRelation + | CRTypeDecl + + let to_json ctx kind = + let expected_type_fields t = match t with + | None -> [] + | Some(ct1,ct2) -> [ + "expectedType",CompletionItem.CompletionType.to_json ctx ct1; + "expectedTypeFollowed",CompletionItem.CompletionType.to_json ctx ct2; + ] + in + let i,args = match kind with + | CRField(item,p,iterator,keyValueIterator) -> + let t = CompletionItem.get_type item in + let t = match t with + | None -> + None + | Some (t,ct) -> + try + let mt = module_type_of_type t in + let ctx = {ctx with generate_abstract_impl = true} in + let make mt = generate_module_type ctx mt in + let j_mt = make mt in + let j_mt_followed = if t == follow t then jnull else make (module_type_of_type (follow t)) in + Some (j_mt,j_mt_followed,CompletionItem.CompletionType.to_json ctx ct) + with _ -> + None + in + let fields = + ("item",CompletionItem.to_json ctx None item) :: + ("range",generate_pos_as_range p) :: + ("iterator", match iterator with + | None -> jnull + | Some t -> jobject ["type",generate_type ctx t] + ) :: + ("keyValueIterator", match keyValueIterator with + | None -> jnull + | Some (key,value) -> jobject [ + "key",generate_type ctx key; + "value",generate_type ctx value + ] + ) :: + (match t with + | None -> [] + | Some (mt,mt_followed,ct) -> ["type",ct;"moduleType",mt;"moduleTypeFollowed",mt_followed] + ) + in + 0,Some (jobject fields) + | CRStructureField -> 1,None + | CRToplevel t -> 2,Some (jobject (expected_type_fields t)) + | CRMetadata -> 3,None + | CRTypeHint -> 4,None + | CRExtends -> 5,None + | CRImplements -> 6,None + | CRStructExtension isIntersectionType -> 7,Some (jobject [ + "isIntersectionType",jbool isIntersectionType + ]) + | CRImport -> 8,None + | CRUsing -> 9,None + | CRNew -> 10,None + | CRPattern (t,isOutermostPattern) -> + let fields = + ("isOutermostPattern",jbool isOutermostPattern) :: + (expected_type_fields t) + in + 11,Some (jobject fields) + | CROverride -> 12,None + | CRTypeRelation -> 13,None + | CRTypeDecl -> 14,None + in + jobject ( + ("kind",jint i) :: (match args with None -> [] | Some arg -> ["args",arg]) + ) + +end + +module DisplayMode = struct + type t = + | DMNone + | DMDefault + | DMUsage of bool (* true = also report definition *) + | DMDefinition + | DMTypeDefinition + | DMResolve of string + | DMPackage + | DMHover + | DMModuleSymbols of string option + | DMDiagnostics of bool (* true = global, false = only in display file *) + | DMStatistics + | DMSignature + + type error_policy = + | EPIgnore + | EPCollect + | EPShow + + type display_file_policy = + | DFPOnly + | DFPAlso + | DFPNo + + type settings = { + dms_kind : t; + dms_display : bool; + dms_full_typing : bool; + dms_force_macro_typing : bool; + dms_error_policy : error_policy; + dms_collect_data : bool; + dms_check_core_api : bool; + dms_inline : bool; + dms_display_file_policy : display_file_policy; + dms_exit_during_typing : bool; + } + + let default_display_settings = { + dms_kind = DMDefault; + dms_display = true; + dms_full_typing = false; + dms_force_macro_typing = false; + dms_error_policy = EPIgnore; + dms_collect_data = false; + dms_check_core_api = false; + dms_inline = false; + dms_display_file_policy = DFPOnly; + dms_exit_during_typing = true; + } + + let default_compilation_settings = { + dms_kind = DMNone; + dms_display = false; + dms_full_typing = true; + dms_force_macro_typing = true; + dms_error_policy = EPShow; + dms_collect_data = false; + dms_check_core_api = true; + dms_inline = true; + dms_display_file_policy = DFPNo; + dms_exit_during_typing = false; + } + + let create dm = + let settings = { default_display_settings with dms_kind = dm } in + match dm with + | DMNone -> default_compilation_settings + | DMDefault | DMDefinition | DMTypeDefinition | DMResolve _ | DMPackage | DMHover | DMSignature -> settings + | DMUsage _ -> { settings with + dms_full_typing = true; + dms_force_macro_typing = true; + dms_collect_data = true; + dms_display_file_policy = DFPAlso; + dms_exit_during_typing = false + } + | DMModuleSymbols filter -> { settings with + dms_display_file_policy = if filter = None then DFPOnly else DFPNo; + dms_exit_during_typing = false; + dms_force_macro_typing = false; + } + | DMDiagnostics global -> { default_compilation_settings with + dms_kind = DMDiagnostics global; + dms_error_policy = EPCollect; + dms_collect_data = true; + dms_display_file_policy = if global then DFPNo else DFPAlso; + } + | DMStatistics -> { settings with + dms_full_typing = true; + dms_collect_data = true; + dms_inline = false; + dms_display_file_policy = DFPAlso; + dms_exit_during_typing = false; + dms_force_macro_typing = true; + } + + let to_string = function + | DMNone -> "none" + | DMDefault -> "field" + | DMDefinition -> "position" + | DMTypeDefinition -> "type-definition" + | DMResolve s -> "resolve " ^ s + | DMPackage -> "package" + | DMHover -> "type" + | DMUsage true -> "rename" + | DMUsage false -> "references" + | DMModuleSymbols None -> "module-symbols" + | DMModuleSymbols (Some s) -> "workspace-symbols " ^ s + | DMDiagnostics b -> (if b then "global " else "") ^ "diagnostics" + | DMStatistics -> "statistics" + | DMSignature -> "signature" +end + +type reference_kind = + | KVar + | KIdent + | KAnyField + | KClassField + | KEnumField + | KModuleType + | KConstructor \ No newline at end of file diff --git a/src/core/error.ml b/src/core/error.ml index 8e8447d21d2..0bdff27d74d 100644 --- a/src/core/error.ml +++ b/src/core/error.ml @@ -21,7 +21,7 @@ exception Fatal_error of string * Globals.pos exception Error of error_msg * Globals.pos let string_source t = match follow t with - | TInst(c,_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_fields + | TInst(c,tl) -> PMap.foldi (fun s _ acc -> s :: acc) (TClass.get_all_fields c tl) [] | TAnon a -> PMap.fold (fun cf acc -> cf.cf_name :: acc) a.a_fields [] | TAbstract({a_impl = Some c},_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_statics | _ -> [] @@ -66,15 +66,198 @@ let unify_error_msg ctx = function "Constraint check failure for " ^ name | Missing_overload (cf, t) -> cf.cf_name ^ " has no overload for " ^ s_type ctx t + | FinalInvariance -> + "Cannot unify final and non-final fields" + | Invalid_function_argument(i,_) -> + Printf.sprintf "Cannot unify argument %i" i + | Invalid_return_type -> + "Cannot unify return types" | Unify_custom msg -> msg +module BetterErrors = struct + type access_kind = + | Field of string + | FunctionArgument of int * int + | FunctionReturn + | TypeParameter of int + | Root + + type access = { + acc_kind : access_kind; + mutable acc_expected : Type.t; + mutable acc_actual : Type.t; + mutable acc_messages : unify_error list; + mutable acc_next : access option; + } + + let s_access_kind = function + | Field s -> "Field " ^ s + | FunctionArgument(i,l) -> Printf.sprintf "FunctionArgument(%i, %i)" i l + | FunctionReturn -> "FunctionReturn" + | TypeParameter i -> Printf.sprintf "TypeParameter %i" i + | Root -> "Root" + + let get_access_chain ctx l = + let make_acc kind actual expected = { + acc_kind = kind; + acc_expected = expected; + acc_actual = actual; + acc_messages = []; + acc_next = None; + } in + let root_acc = make_acc Root t_dynamic t_dynamic in + let current_acc = ref root_acc in + let add_message msg = + !current_acc.acc_messages <- msg :: !current_acc.acc_messages + in + let add_access kind = + let acc = make_acc kind t_dynamic t_dynamic in + !current_acc.acc_next <- Some acc; + current_acc := acc; + in + List.iter (fun err -> match err with + | Cannot_unify(t1,t2) -> + !current_acc.acc_actual <- t1; + !current_acc.acc_expected <- t2; + add_message err + | Invalid_field_type s -> + add_access (Field s); + | Invalid_function_argument(i,l) -> + add_access (FunctionArgument(i,l)); + | Invalid_return_type -> + add_access FunctionReturn; + | Invariant_parameter i -> + add_access (TypeParameter i); + | _ -> + add_message err + ) l; + root_acc + + (* non-recursive s_type *) + let rec s_type ctx t = + match t with + | TMono r -> + (match !r with + | None -> Printf.sprintf "Unknown<%d>" (try List.assq t (!ctx) with Not_found -> let n = List.length !ctx in ctx := (t,n) :: !ctx; n) + | Some t -> s_type ctx t) + | TEnum (e,tl) -> + s_type_path e.e_path ^ s_type_params ctx tl + | TInst (c,tl) -> + (match c.cl_kind with + | KExpr e -> Ast.Printer.s_expr e + | _ -> s_type_path c.cl_path ^ s_type_params ctx tl) + | TType (t,tl) -> + s_type_path t.t_path ^ s_type_params ctx tl + | TAbstract (a,tl) -> + s_type_path a.a_path ^ s_type_params ctx tl + | TFun ([],_) -> + "Void -> ..." + | TFun (l,t) -> + let args = match l with + | [] -> "()" + | ["",b,t] -> ("...") + | _ -> + let args = String.concat ", " (List.map (fun (s,b,t) -> + (if b then "?" else "") ^ ("...") + ) l) in + "(" ^ args ^ ")" + in + Printf.sprintf "%s -> ..." args + | TAnon a -> + begin + match !(a.a_status) with + | Statics c -> Printf.sprintf "{ Statics %s }" (s_type_path c.cl_path) + | EnumStatics e -> Printf.sprintf "{ EnumStatics %s }" (s_type_path e.e_path) + | AbstractStatics a -> Printf.sprintf "{ AbstractStatics %s }" (s_type_path a.a_path) + | _ -> + let fl = PMap.fold (fun f acc -> ((if Meta.has Meta.Optional f.cf_meta then " ?" else " ") ^ f.cf_name) :: acc) a.a_fields [] in + "{" ^ (if not (is_closed a) then "+" else "") ^ String.concat "," fl ^ " }" + end + | TDynamic t2 -> + "Dynamic" ^ s_type_params ctx (if t == t2 then [] else [t2]) + | TLazy f -> + s_type ctx (lazy_type f) + + and s_type_params ctx = function + | [] -> "" + | l -> "<" ^ String.concat ", " (List.map (fun _ -> "...") l) ^ ">" + + let better_error_message l = + let ctx = print_context() in + let rec loop acc l = match l with + | (Cannot_unify _) as err1 :: (Cannot_unify _) :: l -> + loop acc (err1 :: l) + | x :: l -> + loop (x :: acc) l + | [] -> + List.rev acc + in + let l = loop [] l in + let access = get_access_chain ctx l in + let message_buffer = Buffer.create 0 in + let rec fill s i acc k l = + if l = 0 then + List.rev acc + else begin + if k = i then fill s i (s :: acc) (k + 1) (l - 1) + else fill s i ("..." :: acc) (k + 1) (l - 1) + end + in + let rec loop access access_prev = + let loop () = match access.acc_next with + | Some access' -> loop access' access + | None -> + begin match access.acc_messages with + | err :: _ -> + let msg = unify_error_msg ctx err in + Buffer.add_string message_buffer msg; + | [] -> + () + end; + s_type ctx access.acc_actual,s_type ctx access.acc_expected + in + begin match access.acc_kind with + | Field s -> + let s1,s2 = loop() in + Printf.sprintf "{ %s: %s }" s s1,Printf.sprintf "{ %s: %s }" s s2 + | FunctionArgument(i,l) -> + let s1,s2 = loop() in + let sl1 = fill s1 i [] 1 l in + let sl2 = fill s2 i [] 1 l in + Printf.sprintf "(%s) -> ..." (String.concat ", " sl2),Printf.sprintf "(%s) -> ..." (String.concat ", " sl1) + | FunctionReturn -> + let s1,s2 = loop() in + Printf.sprintf "(...) -> %s" s1,Printf.sprintf "(...) -> %s" s2 + | TypeParameter i -> + let rec get_params t = match t with + | TInst({cl_path = path},params) | TEnum({e_path = path},params) | TAbstract({a_path = path},params) | TType({t_path = path},params) -> + path,params + | _ -> + assert false + in + let s1,s2 = loop() in + let path1,params1 = get_params access_prev.acc_actual in + let path2,params2 = get_params access_prev.acc_expected in + let sl1 = fill s1 i [] 1 (List.length params1) in + let sl2 = fill s2 i [] 1 (List.length params2) in + Printf.sprintf "%s<%s>" (s_type_path path1) (String.concat ", " sl1),Printf.sprintf "%s<%s>" (s_type_path path2) (String.concat ", " sl2) + | Root -> + loop() + end; + in + match access.acc_next with + | None -> + String.concat "\n" (List.rev_map (unify_error_msg ctx) access.acc_messages) + | Some access_next -> + let slhs,srhs = loop access_next access in + Printf.sprintf "error: %s\n have: %s\n want: %s" (Buffer.contents message_buffer) slhs srhs +end + let rec error_msg = function | Module_not_found m -> "Type not found : " ^ s_type_path m | Type_not_found (m,t) -> "Module " ^ s_type_path m ^ " does not define type " ^ t - | Unify l -> - let ctx = print_context() in - String.concat "\n" (List.map (unify_error_msg ctx) l) + | Unify l -> BetterErrors.better_error_message l | Unknown_ident s -> "Unknown identifier : " ^ s | Custom s -> s | Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2 @@ -91,4 +274,21 @@ and s_call_error = function let error msg p = raise (Error (Custom msg,p)) -let raise_error err p = raise (Error(err,p)) \ No newline at end of file +let raise_error err p = raise (Error(err,p)) + +let error_require r p = + if r = "" then + error "This field is not available with the current compilation flags" p + else + let r = if r = "sys" then + "a system platform (php,neko,cpp,etc.)" + else try + if String.sub r 0 5 <> "flash" then raise Exit; + let _, v = ExtString.String.replace (String.sub r 5 (String.length r - 5)) "_" "." in + "flash version " ^ v ^ " (use -swf-version " ^ v ^ ")" + with _ -> + "'" ^ r ^ "' to be enabled" + in + error ("Accessing this field requires " ^ r) p + +let invalid_assign p = error "Invalid assign" p \ No newline at end of file diff --git a/src/core/globals.ml b/src/core/globals.ml index 41a391e0daa..0fb245960f9 100644 --- a/src/core/globals.ml +++ b/src/core/globals.ml @@ -4,8 +4,11 @@ type pos = { pmax : int; } +type path = string list * string + module IntMap = Ptmap module StringMap = Map.Make(struct type t = string let compare = String.compare end) +module Int32Map = Map.Make(struct type t = Int32.t let compare = Int32.compare end) type platform = | Cross @@ -25,9 +28,12 @@ let version = 4000 let version_major = version / 1000 let version_minor = (version mod 1000) / 100 let version_revision = (version mod 100) +let version_pre = Some "rc.3" let macro_platform = ref Neko +let return_partial_type = ref false + let is_windows = Sys.os_type = "Win32" || Sys.os_type = "Cygwin" let platforms = [ @@ -65,4 +71,7 @@ let platform_list_help = function let null_pos = { pfile = "?"; pmin = -1; pmax = -1 } -let s_type_path (p,s) = match p with [] -> s | _ -> String.concat "." p ^ "." ^ s \ No newline at end of file +let s_type_path (p,s) = match p with [] -> s | _ -> String.concat "." p ^ "." ^ s + +let starts_with s c = + String.length s > 0 && s.[0] = c \ No newline at end of file diff --git a/src/core/json/genjson.ml b/src/core/json/genjson.ml new file mode 100644 index 00000000000..27a27a8030a --- /dev/null +++ b/src/core/json/genjson.ml @@ -0,0 +1,710 @@ +open Ast +open Globals +open Type +open Meta + +type generation_mode = + | GMFull + | GMWithoutDoc + | GMMinimum + +type context = { + generation_mode : generation_mode; + generate_abstract_impl : bool; + request : JsonRequest.json_request option +} + +let jnull = Json.JNull +let jstring s = Json.JString s +let jint i = Json.JInt i +let jfloat f = Json.JFloat f +let jbool b = Json.JBool b +let jarray l = Json.JArray l +let jobject l = Json.JObject l + +let jtodo = Json.JNull +let jopt f o = Option.map_default f Json.JNull o +let jlist f o = jarray (List.map f o) + +let generate_package_path' pack = [ + ("pack",jarray (List.map jstring pack)) +] + +let generate_package_path pack = jobject (generate_package_path' pack) + +let generate_module_path' mpath = + ("moduleName",jstring (snd mpath)) :: + generate_package_path' (fst mpath) + +let generate_module_path mpath = jobject (generate_module_path' mpath) + +let generate_type_path' mpath tpath = + ("typeName",jstring (snd tpath)) :: + generate_module_path' mpath + +let generate_type_path mpath tpath = jobject (generate_type_path' mpath tpath) + +let generate_adt ctx tpath name args = + let field = ("kind",jstring name) in + let fields = match args with + | None -> [field] + | Some arg -> [field;("args",arg)] + in + jobject fields + +let class_ref ctx c = generate_type_path c.cl_module.m_path c.cl_path +let enum_ref ctx en = generate_type_path en.e_module.m_path en.e_path +let typedef_ref ctx td = generate_type_path td.t_module.m_path td.t_path +let abstract_ref ctx a = generate_type_path a.a_module.m_path a.a_path +let moduletype_ref ctx mt = generate_module_path (t_path mt) +let classfield_ref ctx cf = jstring cf.cf_name +let enumfield_ref ctx ef = jstring ef.ef_name +let local_ref ctx v = jint v.v_id + +let generate_pos ctx p = + jobject [ + "file",jstring p.pfile; + "min",jint p.pmin; + "max",jint p.pmax; + ] + +let generate_expr_pos ctx p = + jtodo + +let generate_doc ctx d = match ctx.generation_mode with + | GMFull -> jopt jstring d + | GMWithoutDoc | GMMinimum -> jnull + +(** return a range JSON structure for given position + positions are 0-based and the result object looks like this: + { + start: {line: 0, character: 0}, + end: {line: 3, character: 42}, + } +*) +let pos_to_range p = + let l1, p1, l2, p2 = Lexer.get_pos_coords p in + let to_json l c = jobject [("line", jint (l - 1)); ("character", jint (c - 1))] in + [ + ("start", to_json l1 p1); + ("end", to_json l2 p2); + ] + +let generate_pos_as_range p = + if p.pmin = -1 then jnull + else jobject (pos_to_range p) + +let generate_pos_as_location p = + if p.pmin = -1 then + jnull + else + jobject [("file",jstring (Path.get_real_path p.pfile));"range",generate_pos_as_range p] + +(* AST expr *) + +let rec generate_binop ctx op = + let name,args = match op with + | OpAdd -> "OpAdd",None + | OpMult -> "OpMult",None + | OpDiv -> "OpDiv",None + | OpSub -> "OpSub",None + | OpAssign -> "OpAssign",None + | OpEq -> "OpEq",None + | OpNotEq -> "OpNotEq",None + | OpGt -> "OpGt",None + | OpGte -> "OpGte",None + | OpLt -> "OpLt",None + | OpLte -> "OpLte",None + | OpAnd -> "OpAnd",None + | OpOr -> "OpOr",None + | OpXor -> "OpXor",None + | OpBoolAnd -> "OpBoolAnd",None + | OpBoolOr -> "OpBoolOr",None + | OpShl -> "OpShl",None + | OpShr -> "OpShr",None + | OpUShr -> "OpUShr",None + | OpMod -> "OpMod",None + | OpAssignOp op -> "OpAssignOp", (Some (generate_binop ctx op)) + | OpInterval -> "OpInterval",None + | OpArrow -> "OpArrow",None + | OpIn -> "OpIn",None + in + generate_adt ctx (Some (["haxe";"macro"],"Binop")) name args + +let generate_unop ctx op = + let name = match op with + | Increment -> "OpIncrement" + | Decrement -> "OpDecrement" + | Not -> "OpNot" + | Neg -> "OpNeg" + | NegBits -> "OpNegBits" + in + jstring name + +let rec generate_expr ctx e = + jtodo + +(* metadata *) + +and generate_metadata_entry ctx (m,el,p) = + jobject [ + "name",jstring (Meta.to_string m); + "params",jlist (generate_expr ctx) el; + "pos",generate_pos ctx p; + ] + +and generate_metadata ctx ml = + let ml = List.filter (fun (m,_,_) -> + let (_,(_,flags)) = Meta.get_info m in + not (List.mem UsedInternally flags) + ) ml in + jlist (generate_metadata_entry ctx) ml + +and generate_minimum_metadata ctx ml = + match ctx.request with + | None -> None + | Some request -> + match request#get_requested_meta_list with + | None -> None + | Some requested -> + let ml = + List.filter + (fun (m,_,_) -> List.exists (fun r -> r = to_string m) requested) + ml + in + Some (jlist (generate_metadata_entry ctx) ml) + +(* AST.ml structures *) + +let rec generate_ast_type_param ctx tp = jobject [ + "name",jstring (fst tp.tp_name); + "params",jlist (generate_ast_type_param ctx) tp.tp_params; + "constraints",jtodo; + "metadata",generate_metadata ctx tp.tp_meta +] + +(* type instance *) + +let rec generate_type ctx t = + let rec loop t = match t with + | TMono r -> + begin match !r with + | None -> "TMono",None + | Some t -> loop t + end + | TLazy f -> + (* return_partial_type := true; *) + let t = lazy_type f in + (* return_partial_type := false; *) + loop t + | TDynamic t -> "TDynamic",Some (if t == t_dynamic then jnull else generate_type ctx t) + | TInst(c,tl) -> "TInst",Some (generate_type_path_with_params ctx c.cl_module.m_path c.cl_path tl) + | TEnum(en,tl) -> "TEnum",Some (generate_type_path_with_params ctx en.e_module.m_path en.e_path tl) + | TType(td,tl) -> "TType",Some (generate_type_path_with_params ctx td.t_module.m_path td.t_path tl) + | TAbstract(a,tl) -> "TAbstract",Some (generate_type_path_with_params ctx a.a_module.m_path a.a_path tl) + | TAnon an -> "TAnonymous", Some(generate_anon ctx an) + | TFun(tl,tr) -> "TFun", Some (jobject (generate_function_signature ctx tl tr)) + in + let name,args = loop t in + generate_adt ctx None name args + +and generate_anon_status ctx status = + let name,args = match status with + | Closed -> "AClosed",None + | Opened -> "AOpened",None + | Const -> "AConst",None + | Extend tl -> "AExtend", Some (generate_types ctx tl) + | Statics c -> "AClassStatics",Some (class_ref ctx c) + | EnumStatics en -> "AEnumStatics",Some (enum_ref ctx en) + | AbstractStatics a -> "AAbstractStatics", Some (abstract_ref ctx a) + in + generate_adt ctx None name args + +and generate_anon ctx an = + let generate_anon_fields () = + let fields = PMap.fold (fun cf acc -> generate_class_field ctx CFSMember cf :: acc) an.a_fields [] in + jarray fields + in + jobject [ + "fields",generate_anon_fields(); + "status",generate_anon_status ctx !(an.a_status); + ] + +and generate_function_argument ctx (name,opt,t) = + jobject [ + "name",jstring name; + "opt",jbool opt; + "t",generate_type ctx t; + ] + +and generate_function_signature ctx tl tr = + [ + "args",jlist (generate_function_argument ctx) tl; + "ret",generate_type ctx tr; + ] + +and generate_types ctx tl = + jlist (generate_type ctx) tl + +and generate_type_path_with_params ctx mpath tpath tl = + jobject [ + "path",generate_type_path mpath tpath; + "params",generate_types ctx tl; + ] + +(* type parameter *) + +and generate_type_parameter ctx (s,t) = + let generate_constraints () = match follow t with + | TInst({cl_kind = KTypeParameter tl},_) -> generate_types ctx tl + | _ -> assert false + in + jobject [ + "name",jstring s; + "constraints",generate_constraints (); + ] + +(* texpr *) + +and generate_tvar ctx v = + let generate_extra (params,eo) = jobject ( + ("params",jlist (generate_type_parameter ctx) params) :: + (match eo with + | None -> [] + | Some e -> ["expr",jobject [ + ("string",jstring (s_expr_pretty false "" false (s_type (print_context())) e)) + ]]); + ) in + let fields = [ + "id",jint v.v_id; + "name",jstring v.v_name; + "type",generate_type ctx v.v_type; + "capture",jbool v.v_capture; + "extra",jopt generate_extra v.v_extra; + "meta",generate_metadata ctx v.v_meta; + "pos",generate_pos ctx v.v_pos; + "isFinal",jbool v.v_final; + "isInline",jbool (match v.v_extra with Some (_,Some _) -> true | _ -> false); + ] in + let origin_to_int = function + | TVOLocalVariable -> 0 + | TVOArgument -> 1 + | TVOForVariable -> 2 + | TVOPatternVariable -> 3 + | TVOCatchVariable -> 4 + | TVOLocalFunction -> 5 + in + let fields = match v.v_kind with + | VUser origin -> ("origin",jint (origin_to_int origin)) :: fields + | _ -> fields + in + jobject fields + +and generate_tconstant ctx ct = + let name,args = match ct with + | TInt i32 -> "TInt",Some (jstring (Int32.to_string i32)) + | TFloat s -> "TFloat",Some (jstring s) + | TString s -> "TString",Some (jstring s) + | TBool b -> "TBool",Some (jbool b) + | TNull -> "TNull",None + | TThis -> "TThis",None + | TSuper -> "TSuper",None + in + generate_adt ctx None name args + +and generate_tfunction ctx tf = + let generate_arg (v,cto) = jobject [ + "v",generate_tvar ctx v; + "value",jopt (generate_texpr ctx) cto; + ] in + jobject [ + "args",jlist generate_arg tf.tf_args; + "ret",generate_type ctx tf.tf_type; + "expr",generate_expr ctx tf.tf_expr; + ] + +and generate_texpr ctx e = + jtodo + (* let name,args = match e.eexpr with + | TConst ct -> + "TConst",Some (generate_tconstant ctx ct) + | TLocal v -> + "TLocal",Some (local_ref ctx v) + | TArray(e1,e2) -> + "TArray",Some (jobject [ + "expr1",generate_texpr ctx e1; + "expr2",generate_texpr ctx e2; + ]) + | TBinop(op,e1,e2) -> + "TBinop",Some (jobject [ + "op",generate_binop ctx op; + "expr1",generate_texpr ctx e1; + "expr2",generate_texpr ctx e2; + ]); + | TField(e1,fa) -> + "TField",Some (jobject [ + "expr",generate_texpr ctx e1; + "name",jstring (field_name fa); + (* TODO *) + ]); + | TTypeExpr mt -> + "TTypeExpr",Some (moduletype_ref ctx mt) + | TParenthesis e1 -> + "TParenthesis",Some (generate_texpr ctx e1) + | TObjectDecl fl -> + let generate_quote_status qs = + let name = match qs with + | DoubleQuotes -> "DoubleQuotes" + | NoQuotes -> "NoQuotes" + in + generate_adt ctx None name None + in + let generate_key (name,pos,qs) = jobject [ + "name",jstring name; + "pos",generate_expr_pos ctx pos; + "quoteStatus",generate_quote_status qs; + ] in + let generate_entry (key,value) = jobject [ + "key",generate_key key; + "value",generate_texpr ctx value; + ] in + let fields = List.map generate_entry fl in + "TObjectDecl",Some (jarray fields) + | TArrayDecl el -> + let fields = List.map (generate_texpr ctx) el in + "TArrayDecl",Some (jarray fields) + | TCall(e1,el) -> + let args = List.map (generate_texpr ctx) el in + "TCall",Some (jobject [ + "expr",generate_texpr ctx e1; + "args",jarray args; + ]); + | TNew(c,tl,el) -> + let args = List.map (generate_texpr ctx) el in + "TNew",Some (jobject [ + "path",generate_type_path_with_params ctx c.cl_path tl; + "args",jarray args; + ]); + | TUnop(op,flag,e1) -> + "TUnop",Some (jobject [ + "op",generate_unop ctx op; + "prefix",jbool (flag = Prefix); + "expr",generate_texpr ctx e1; + ]); + | TFunction tf -> + "TFunction",Some (generate_tfunction ctx tf) + | TVar(v,eo) -> + "TVar",Some (jobject [ + "v",generate_tvar ctx v; + "expr",jopt (generate_texpr ctx) eo; + ]) + | TBlock el -> + let el = List.map (generate_texpr ctx) el in + "TBlock",Some (jarray el) + | TFor(v,e1,e2) -> + "TFor",Some (jobject [ + "v",generate_tvar ctx v; + "expr1",generate_texpr ctx e1; + "expr2",generate_texpr ctx e2; + ]); + | TIf(e1,e2,eo) -> + "TIf",Some (jobject [ + "eif",generate_texpr ctx e1; + "ethen",generate_expr ctx e1; + "eelse",jopt (generate_expr ctx) eo; + ]); + | TWhile(e1,e2,flag) -> + "TWhile",Some (jobject [ + "econd",generate_texpr ctx e1; + "ebody",generate_texpr ctx e2; + "isDoWhile",jbool (flag = DoWhile); + ]); + | TSwitch(e1,cases,edef) -> + let generate_case (el,e) = jobject [ + "patterns",jlist (generate_texpr ctx) el; + "expr",generate_texpr ctx e; + ] in + "TSwitch",Some (jobject [ + "subject",generate_texpr ctx e1; + "cases",jlist generate_case cases; + "def",jopt (generate_texpr ctx) edef; + ]) + | TTry(e1,catches) -> + let generate_catch (v,e) = jobject [ + "v",generate_tvar ctx v; + "expr",generate_texpr ctx e; + ] in + "TTry",Some (jobject [ + "expr",generate_texpr ctx e1; + "catches",jlist generate_catch catches; + ]) + | TReturn eo -> + "TReturn",Option.map (generate_texpr ctx) eo + | TBreak -> + "TBreak",None + | TContinue -> + "TContinue",None + | TThrow e1 -> + "TThrow",Some (generate_texpr ctx e1) + | TCast(e1,mto) -> + "TCast",Some (jobject [ + "expr",generate_texpr ctx e1; + "moduleType",jopt (moduletype_ref ctx) mto; + ]); + | TMeta(m,e1) -> + "TMeta",Some (jobject [ + "meta",generate_metadata_entry ctx m; + "expr",generate_texpr ctx e1; + ]) + | TEnumParameter(e1,ef,i) -> + "TEnumParameter",Some (jobject [ + "expr",generate_texpr ctx e1; + "enumField",enumfield_ref ctx ef; + "index",jint i; + ]); + | TEnumIndex e1 -> + "TEnumIndex",Some (generate_texpr ctx e1) + | TIdent s -> + "TIdent",Some (jstring s) + in + jobject [ + "expr",generate_adt ctx None name args; + (* TODO: pos? *) + "type",generate_type ctx e.etype; + ] *) + +(* fields *) + +and generate_class_field' ctx cfs cf = + let generate_class_kind () = + let generate_var_access va = + let name,args = match va with + | AccNormal -> "AccNormal",None + | AccNo -> "AccNo",None + | AccNever -> "AccNever",None + | AccCtor -> "AccCtor",None + | AccResolve -> "AccResolve",None + | AccCall -> "AccCall",None + | AccInline -> "AccInline",None + | AccRequire(s,so) -> "AccRequire",Some (jobject ["require",jstring s;"message",jopt jstring so]) + in + generate_adt ctx None name args + in + let generate_method_kind m = + let name = match m with + | MethNormal -> "MethNormal" + | MethInline -> "MethInline" + | MethDynamic -> "MethDynamic" + | MethMacro -> "MethMacro" + in + jstring name + in + let name,args = match cf.cf_kind with + | Var vk -> "FVar",Some (jobject ["read",generate_var_access vk.v_read;"write",generate_var_access vk.v_write]) + | Method m -> "FMethod", Some (generate_method_kind m) + in + generate_adt ctx None name args + in + let expr = match ctx.generation_mode with + | GMFull | GMWithoutDoc -> + let value = match cf.cf_kind with + | Method _ -> None + | Var _ -> + try + begin match Meta.get Meta.Value cf.cf_meta with + | (_,[e],_) -> Some e + | _ -> None + end + with Not_found -> + None + in + begin match value with + | None -> + if Meta.has (Meta.Custom ":testHack") cf.cf_meta then begin match cf.cf_expr with + | Some e -> jobject ["testHack",jstring (s_expr_pretty false "" false (s_type (print_context())) e)] (* TODO: haha *) + | None -> jnull + end else + jnull + | Some e -> jobject ["string",jstring (Ast.Printer.s_expr e)] + end + | GMMinimum -> + jnull + in + [ + "name",jstring cf.cf_name; + "type",generate_type ctx cf.cf_type; + "isPublic",jbool (has_class_field_flag cf CfPublic); + "isFinal",jbool (has_class_field_flag cf CfFinal); + "params",jlist (generate_type_parameter ctx) cf.cf_params; + "meta",generate_metadata ctx cf.cf_meta; + "kind",generate_class_kind (); + "expr",expr; + "pos",generate_pos ctx cf.cf_pos; + "doc",generate_doc ctx cf.cf_doc; + "overloads",jlist (generate_class_field ctx cfs) cf.cf_overloads; + "scope",jint (Obj.magic cfs); + ] + +and generate_class_field ctx cfs cf = + jobject (generate_class_field' ctx cfs cf) + +let generate_enum_field ctx ef = + jobject [ + "name",jstring ef.ef_name; + "type",generate_type ctx ef.ef_type; + "pos",generate_pos ctx ef.ef_pos; + "meta",generate_metadata ctx ef.ef_meta; + "index",jint ef.ef_index; + "doc",generate_doc ctx ef.ef_doc; + "params",jlist (generate_type_parameter ctx) ef.ef_params; + ] + +(* module type *) + +let generate_module_type_fields ctx inf = + [ + "pack",jlist jstring (fst inf.mt_path); + "name",jstring (snd inf.mt_path); + "moduleName",jstring (snd inf.mt_module.m_path); + "pos",generate_pos ctx inf.mt_pos; + "isPrivate",jbool inf.mt_private; + "params",jlist (generate_type_parameter ctx) inf.mt_params; + "meta",generate_metadata ctx inf.mt_meta; + "doc",generate_doc ctx inf.mt_doc; + ] + +let generate_class ctx c = + let generate_class_kind ck = + let ctor,args = match ck with + | KNormal -> "KNormal",None + | KTypeParameter tl -> "KTypeParameter",Some (generate_types ctx tl) + | KExpr e -> "KExpr",Some (generate_expr ctx e) + | KGeneric -> "KGeneric",None + | KGenericInstance(c,tl) -> "KGenericInstance",Some (generate_type_path_with_params ctx c.cl_module.m_path c.cl_path tl) + | KMacroType -> "KMacroType",None + | KGenericBuild _ -> "KGenericBuild",None + | KAbstractImpl a -> "KAbstractImpl",Some (abstract_ref ctx a) + in + generate_adt ctx (Some (["haxe";"macro"],"ClassKind")) ctor args + in + let generate_class_relation (c,tl) = + jobject [ + "t",class_ref ctx c; + "params",generate_types ctx tl; + ] + in + [ + "kind",generate_class_kind c.cl_kind; + "isInterface",jbool c.cl_interface; + "superClass",jopt generate_class_relation c.cl_super; + "interfaces",jlist generate_class_relation c.cl_implements; + "fields",jlist (generate_class_field ctx CFSMember) c.cl_ordered_fields; + "statics",jlist (generate_class_field ctx CFSStatic) c.cl_ordered_statics; + "constructor",jopt (generate_class_field ctx CFSConstructor) c.cl_constructor; + "init",jopt (generate_texpr ctx) c.cl_init; + "overrides",jlist (classfield_ref ctx) c.cl_overrides; + "isExtern",jbool c.cl_extern; + ] + +let generate_enum ctx e = + let generate_enum_constructors () = + jarray (List.map (fun s -> + let ef = PMap.find s e.e_constrs in + generate_enum_field ctx ef + ) e.e_names) + in + [ + "constructors",generate_enum_constructors (); + "isExtern",jbool e.e_extern; + ] + +let generate_typedef ctx td = + [ + "type",generate_type ctx td.t_type; + ] + +let generate_abstract ctx a = + let generate_cast_relation t cfo = + jobject [ + "t",generate_type ctx t; + "field",jopt (classfield_ref ctx) cfo + ] + in + let generate_casts fields casts = + let l1 = List.map (fun (t,cf) -> generate_cast_relation t (Some cf)) fields in + let l2 = List.map (fun t -> generate_cast_relation t None) casts in + jarray (l1 @ l2) + in + let generate_binop (op,cf) = + jobject [ + "op",generate_binop ctx op; + "field",classfield_ref ctx cf; + ] + in + let generate_unop (op,flag,cf) = + jobject [ + "op",generate_unop ctx op; + "postFix",jbool (flag = Postfix); + "field",classfield_ref ctx cf; + ] + in + let impl = match a.a_impl with + | None -> jnull + | Some c -> + if ctx.generate_abstract_impl then jobject (generate_class ctx c) + else class_ref ctx c + in + [ + "type",generate_type ctx a.a_this; + "impl",impl; + "binops",jlist generate_binop a.a_ops; + "unops",jlist generate_unop a.a_unops; + "from",generate_casts a.a_from_field a.a_from; + "to",generate_casts a.a_to_field a.a_to; + "array",jlist (classfield_ref ctx) a.a_array; + "read",jopt (classfield_ref ctx) a.a_read; + "write",jopt (classfield_ref ctx) a.a_write; + ] + +let generate_module_type ctx mt = + let fields1 = generate_module_type_fields ctx (t_infos mt) in + let kind,fields2 = match mt with + | TClassDecl c -> "class",generate_class ctx c + | TEnumDecl e -> "enum",generate_enum ctx e + | TTypeDecl t -> "typedef",generate_typedef ctx t + | TAbstractDecl a -> "abstract",generate_abstract ctx a + in + let fields1 = ("kind",jstring kind) :: fields1 @ [("args",jobject fields2)] in + jobject fields1 + +(* module *) + +let generate_module ctx m = + jobject [ + "id",jint m.m_id; + "path",generate_module_path m.m_path; + "types",jlist (fun mt -> generate_type_path m.m_path (t_infos mt).mt_path) m.m_types; + "file",jstring m.m_extra.m_file; + "sign",jstring (Digest.to_hex m.m_extra.m_sign); + "dependencies",jarray (PMap.fold (fun m acc -> (jobject [ + "path",jstring (s_type_path m.m_path); + "sign",jstring (Digest.to_hex m.m_extra.m_sign); + ]) :: acc) m.m_extra.m_deps []); + ] + +let create_context ?jsonrpc gm = { + generation_mode = gm; + generate_abstract_impl = false; + request = match jsonrpc with None -> None | Some jsonrpc -> Some (new JsonRequest.json_request jsonrpc) +} + +let generate types file = + let t = Timer.timer ["generate";"json";"construct"] in + let ctx = create_context GMFull in + let json = jarray (List.map (generate_module_type ctx) types) in + t(); + let t = Timer.timer ["generate";"json";"write"] in + let ch = open_out_bin file in + Json.write_json (output_string ch) json; + close_out ch; + t() \ No newline at end of file diff --git a/src/core/json.ml b/src/core/json/json.ml similarity index 98% rename from src/core/json.ml rename to src/core/json/json.ml index 81c10737b4f..32004992306 100644 --- a/src/core/json.ml +++ b/src/core/json/json.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -103,6 +103,11 @@ and write_object w o = write_iter write_el (fun() -> write_sep w) o; w "}" +let string_of_json json = + let b = Buffer.create 0 in + write_json (Buffer.add_string b) json; + Buffer.contents b; + module Reader = struct (* The following code is basically stripped down yojson (https://github.com/mjambon/yojson), diff --git a/src/core/json/jsonRequest.ml b/src/core/json/jsonRequest.ml new file mode 100644 index 00000000000..0e3a2828305 --- /dev/null +++ b/src/core/json/jsonRequest.ml @@ -0,0 +1,19 @@ +open Jsonrpc_handler + +class json_request (rpc:jsonrpc_handler) = object (self) + val mutable requested_meta_list = None + (** + The contents of `params.meta` field of the request json + *) + method get_requested_meta_list : string list option = + match requested_meta_list with + | Some result -> result + | None -> + let result = + rpc#get_opt_param + (fun () -> Some (List.map (rpc#get_string "Metadata name") (rpc#get_array_param "meta"))) + None + in + requested_meta_list <- Some result; + result +end \ No newline at end of file diff --git a/src/core/json/jsonRpc.ml b/src/core/json/jsonRpc.ml new file mode 100644 index 00000000000..180c9d62f89 --- /dev/null +++ b/src/core/json/jsonRpc.ml @@ -0,0 +1,79 @@ +open Json + +let jsonrpc_field = "jsonrpc", JString "2.0" + +let notification method_name params = + let fl = [ + jsonrpc_field; + "method", JString method_name; + ] in + let fl = Option.map_default (fun params -> ("params",params) :: fl) fl params in + JObject fl + +let result id data = + JObject [ + jsonrpc_field; + "id", id; + "result", data; + ] + +let error id code ?(data=None) message = + JObject [ + jsonrpc_field; + "id", id; + "error", JObject ( + ("code", JInt code) :: + ("message", JString message) :: + (match data with None -> [] | Some data -> ["data",data]) + ) + ] + +type json_rpc_error = + | Parse_error of string + | Invalid_request of string + | Method_not_found of Json.t * string (* id->methodname *) + | Invalid_params of Json.t + | Custom of Json.t * int * string (* id->code->message *) + +exception JsonRpc_error of json_rpc_error + +let raise_method_not_found id name = raise (JsonRpc_error (Method_not_found(id,name))) +let raise_custom id code message = raise (JsonRpc_error (Custom(id,code,message))) +let raise_invalid_params json = raise (JsonRpc_error (Invalid_params json)) + +let handle_jsonrpc_error f output = + try f () with JsonRpc_error e -> + match e with + | Parse_error s -> output (error JNull (-32700) s) + | Invalid_request s -> output (error JNull (-32600) s) + | Method_not_found (id,meth) -> output (error id (-32601) (Printf.sprintf "Method `%s` not found" meth)) + | Invalid_params id -> output (error id (-32602) "Invalid params") + | Custom (id,code,msg) -> output (error id code msg) + +let parse_request input = + let open Json.Reader in + let lexbuf = Sedlexing.Utf8.from_string input in + let json = try read_json lexbuf with Json_error s -> raise (JsonRpc_error (Parse_error s)) in + let fields = match json with JObject fl -> fl | _ -> raise (JsonRpc_error (Invalid_request "not an object")) in + let get_field name map = + let field = try List.find (fun (n,_) -> n = name) fields with Not_found -> raise (JsonRpc_error (Invalid_request ("no `" ^ name ^ "` field"))) in + let value = map (snd field) in + match value with + | None -> raise (JsonRpc_error (Invalid_request (Printf.sprintf "`%s` field has invalid data" name))) + | Some v -> v + in + let id = get_field "id" (fun v -> Some v) in + let meth = get_field "method" (function JString s -> Some s | _ -> None) in + let params = + try + let f = List.find (fun (n,_) -> n = "params") fields in + Some (snd f) + with Not_found -> + None + in + id,meth,params + +let process_request input handle output = + let id,meth,params = parse_request input in + let res = handle id meth params in + output id res \ No newline at end of file diff --git a/src/core/json/jsonRpcSocket.ml b/src/core/json/jsonRpcSocket.ml new file mode 100644 index 00000000000..41a71a74a66 --- /dev/null +++ b/src/core/json/jsonRpcSocket.ml @@ -0,0 +1,7 @@ +open Json + +let send_json socket json = + Socket.send_string socket (string_of_json json) + +let send_event socket event data = + send_json socket (JsonRpc.notification event data) \ No newline at end of file diff --git a/src/core/json/jsonrpc_handler.ml b/src/core/json/jsonrpc_handler.ml new file mode 100644 index 00000000000..a396f77b294 --- /dev/null +++ b/src/core/json/jsonrpc_handler.ml @@ -0,0 +1,86 @@ +open Json +open JsonRpc + +type haxe_json_error = + | MissingField of string * string + | BadType of string * string + +class jsonrpc_handler (id,name,params) = object(self) + val id = id + val method_name : string = name + val params = match params with + | Some json -> json + | None -> JNull + + method get_id = id + method get_method_name = method_name + + method raise_haxe_json_error : 'a . haxe_json_error -> 'a = function + | MissingField(name,on) -> raise_custom id 1 (Printf.sprintf "Missing param \"%s\" on \"%s\"" name on) + | BadType(desc,expected) -> raise_custom id 2 (Printf.sprintf "Unexpected value for \"%s\", expected %s" desc expected) + + method get_field desc fl name : Json.t = + try + List.assoc name fl + with Not_found -> + self#raise_haxe_json_error (MissingField(name,desc)) + + method get_string desc j = match j with + | JString s -> s + | _ -> self#raise_haxe_json_error (BadType(desc,"String")) + + method get_int desc j = match j with + | JInt i -> i + | _ -> self#raise_haxe_json_error (BadType(desc,"String")) + + method get_bool desc j = match j with + | JBool b -> b + | _ -> self#raise_haxe_json_error (BadType(desc,"Bool")) + + method get_array desc j : Json.t list = match j with + | JArray a -> a + | _ -> self#raise_haxe_json_error (BadType(desc,"Array")) + + method get_object desc j = match j with + | JObject o -> o + | _ -> self#raise_haxe_json_error (BadType(desc,"Object")) + + method get_string_field desc name fl = + self#get_string desc (self#get_field desc fl name) + + method get_int_field desc name fl = + self#get_int desc (self#get_field desc fl name) + + method get_bool_field desc name fl = + self#get_bool desc (self#get_field desc fl name) + + method get_array_field desc name fl = + self#get_array desc (self#get_field desc fl name) + + method get_object_field desc name fl = + self#get_object desc (self#get_field desc fl name) + + method private get_obj_params = match params with + | JObject fl -> fl + | _ -> invalid_arg "params" + + method get_string_param name = + self#get_string_field "params" name (self#get_obj_params) + + method get_int_param name = + self#get_int_field "params" name (self#get_obj_params) + + method get_bool_param name = + self#get_bool_field "params" name (self#get_obj_params) + + method get_array_param name = + self#get_array_field "params" name (self#get_obj_params) + + method get_object_param name = + self#get_object_field "params" name (self#get_obj_params) + + method get_opt_param : 'a . (unit -> 'a) -> 'a -> 'a = fun f def -> + try f() with JsonRpc_error _ -> def + + method get_params = params +end \ No newline at end of file diff --git a/src/core/meta.ml b/src/core/meta.ml index 0b69539a0de..6ea21382eef 100644 --- a/src/core/meta.ml +++ b/src/core/meta.ml @@ -1,374 +1,14 @@ open Globals - -type strict_meta = - | Abi - | Abstract - | Access - | Accessor - | Allow - | Analyzer - | Annotation - | ArrayAccess - | Ast - | AstSource - | AutoBuild - | Bind - | Bitmap - | BridgeProperties - | Build - | BuildXml - | Callable - | Class - | ClassCode - | Commutative - | CompilerGenerated - | Const - | CoreApi - | CoreType - | CppFileCode - | CppInclude - | CppNamespaceCode - | CsNative - | Dce - | Debug - | Decl - | DefParam - | Delegate - | Depend - | Deprecated - | DirectlyUsed - | DynamicObject - | Eager - | Enum - | EnumConstructorParam - | Event - | Exhaustive - | Expose - | Extern - | FakeEnum - | File - | FileXml - | Final - | Fixed - | FlatEnum - | Font - | ForLoopVariable - | Forward - | ForwardStatics - | From - | FunctionCode - | FunctionTailCode - | Generic - | GenericBuild - | GenericInstance - | Getter - | Hack - | HasUntyped - | HaxeGeneric - | HeaderClassCode - | HeaderCode - | HeaderInclude - | HeaderNamespaceCode - | HxGen - | IfFeature - | Impl - | PythonImport - | ImplicitCast - | Include - | InitPackage - | InlineConstructorArgument of int * int - | InlineConstructorVariable - | Internal - | IsVar - | JavaCanonical - | JavaNative - | JsRequire - | Keep - | KeepInit - | KeepSub - | LibType - | LoopLabel - | LuaRequire - | LuaDotMethod - | Meta - | Macro - | MaybeUsed - | MergeBlock - | MultiReturn - | MultiType - | Native - | NativeChildren - | NativeGen - | NativeGeneric - | NativeProperty - | NativeStaticExtension - | NoCompletion - | NoDebug - | NoDoc - | NoExpr - | NoImportGlobal - | NonVirtual - | NoPackageRestrict - | NoPrivateAccess - | NoStack - | NotNull - | NoUsing - | Ns - | Objc - | ObjcProtocol - | Op - | Optional - | Overload - | PhpGlobal - | PhpClassConst - | PhpMagic - | PhpNoConstructor - | Pos - | PrivateAccess - | Property - | Protected - | Public - | PublicFields - | Pure - | ReadOnly - | RealPath - | Remove - | Require - | RequiresAssign - | Resolve - | Rtti - | Runtime - | RuntimeValue - | Scalar - | SelfCall - | Setter - | SkipCtor - | SkipReflection - | Sound - | SourceFile - | StackOnly - | StoredTypedExpr - | Strict - | Struct - | StructAccess - | StructInit - | SuppressWarnings - | This - | Throws - | To - | ToString - | Transient - | TemplatedCall - | ValueUsed - | Volatile - | UnifyMinDynamic - | Unreflective - | Unsafe - | Usage - | Used - | UserVariable - | Value - | Void - | Last - (* do not put any custom metadata after Last *) - | Dollar of string - | Custom of string +include MetaList let has m ml = List.exists (fun (m2,_,_) -> m = m2) ml +let has_one_of ml1 ml2 = List.exists (fun (m2,_,_) -> List.mem m2 ml1) ml2 let get m ml = List.find (fun (m2,_,_) -> m = m2) ml -type meta_usage = - | TClass - | TClassField - | TAbstract - | TAbstractField - | TEnum - | TTypedef - | TAnyField - | TExpr - | TTypeParameter - -type meta_parameter = - | HasParam of string - | Platform of platform - | Platforms of platform list - | UsedOn of meta_usage - | UsedOnEither of meta_usage list - | UsedInternally - -let get_info = function - | Abi -> ":abi",("Function ABI/calling convention",[Platforms [Cpp]]) - | Abstract -> ":abstract",("Sets the underlying class implementation as 'abstract'",[Platforms [Java;Cs]]) - | Access -> ":access",("Forces private access to package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]]) - | Accessor -> ":accessor",("Used internally by DCE to mark property accessors",[UsedOn TClassField;UsedInternally]) - | Allow -> ":allow",("Allows private access from package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]]) - | Analyzer -> ":analyzer",("Used to configure the static analyzer",[]) - | Annotation -> ":annotation",("Annotation (@interface) definitions on -java-lib imports will be annotated with this metadata. Has no effect on types compiled by Haxe",[Platform Java; UsedOn TClass]) - | ArrayAccess -> ":arrayAccess",("Allows [] access on an abstract",[UsedOnEither [TAbstract;TAbstractField]]) - | Ast -> ":ast",("Internally used to pass the AST source into the typed AST",[UsedInternally]) - | AstSource -> ":astSource",("Filled by the compiler with the parsed expression of the field",[UsedOn TClassField]) - | AutoBuild -> ":autoBuild",("Extends @:build metadata to all extending and implementing classes",[HasParam "Build macro call";UsedOn TClass]) - | Bind -> ":bind",("Override Swf class declaration",[Platform Flash;UsedOn TClass]) - | Bitmap -> ":bitmap",("Embeds given bitmap data into the class (must extend flash.display.BitmapData)",[HasParam "Bitmap file path";UsedOn TClass;Platform Flash]) - | BridgeProperties -> ":bridgeProperties",("Creates native property bridges for all Haxe properties in this class",[UsedOn TClass;Platform Cs]) - | Build -> ":build",("Builds a class or enum from a macro",[HasParam "Build macro call";UsedOnEither [TClass;TEnum]]) - | BuildXml -> ":buildXml",("Specify xml data to be injected into Build.xml",[Platform Cpp]) - | Callable -> ":callable",("Abstract forwards call to its underlying type",[UsedOn TAbstract]) - | Class -> ":class",("Used internally to annotate an enum that will be generated as a class",[Platforms [Java;Cs]; UsedOn TEnum; UsedInternally]) - | ClassCode -> ":classCode",("Used to inject platform-native code into a class",[Platforms [Java;Cs]; UsedOn TClass]) - | Commutative -> ":commutative",("Declares an abstract operator as commutative",[UsedOn TAbstractField]) - | CompilerGenerated -> ":compilerGenerated",("Marks a field as generated by the compiler. Shouldn't be used by the end user",[Platforms [Java;Cs]]) - | Const -> ":const",("Allows a type parameter to accept expression values",[UsedOn TTypeParameter]) - | CoreApi -> ":coreApi",("Identifies this class as a core api class (forces Api check)",[UsedOnEither [TClass;TEnum;TTypedef;TAbstract]]) - | CoreType -> ":coreType",("Identifies an abstract as core type so that it requires no implementation",[UsedOn TAbstract]) - | CppFileCode -> ":cppFileCode",("Code to be injected into generated cpp file",[Platform Cpp]) - | CppInclude -> ":cppInclude",("File to be included in generated cpp file",[Platform Cpp]) - | CppNamespaceCode -> ":cppNamespaceCode",("",[Platform Cpp]) - | CsNative -> ":csNative",("Automatically added by -net-lib on classes generated from .NET DLL files",[Platform Cs; UsedOnEither[TClass;TEnum]; UsedInternally]) - | Dce -> ":dce",("Forces dead code elimination even when -dce full is not specified",[UsedOnEither [TClass;TEnum]]) - | Debug -> ":debug",("Forces debug information to be generated into the Swf even without -debug",[UsedOnEither [TClass;TClassField]; Platform Flash]) - | Decl -> ":decl",("",[Platform Cpp]) - | DefParam -> ":defParam",("Default function argument value loaded from the SWF and used for documentation in Genxml",[Platform Flash;UsedInternally]) - | Delegate -> ":delegate",("Automatically added by -net-lib on delegates",[Platform Cs; UsedOn TAbstract]) - | Depend -> ":depend",("",[Platform Cpp]) - | Deprecated -> ":deprecated",("Mark a type or field as deprecated",[]) - | DirectlyUsed -> ":directlyUsed",("Marks types that are directly referenced by non-extern code",[UsedInternally]) - | DynamicObject -> ":dynamicObject",("Used internally to identify the Dynamic Object implementation",[Platforms [Java;Cs]; UsedOn TClass; UsedInternally]) - | Eager -> ":eager",("Forces typedefs to be followed early",[UsedOn TTypedef]) - | Enum -> ":enum",("Defines finite value sets to abstract definitions",[UsedOn TAbstract]) - | EnumConstructorParam -> ":enumConstructorParam",("Used internally to annotate GADT type parameters",[UsedOn TClass; UsedInternally]) - | Event -> ":event",("Automatically added by -net-lib on events. Has no effect on types compiled by Haxe",[Platform Cs; UsedOn TClassField]) - | Exhaustive -> ":exhaustive",("",[UsedInternally]) - | Expose -> ":expose",("Includes the class or field in Haxe exports",[HasParam "?Name=Class path";UsedOnEither [TClass;TClassField];Platforms [Js;Lua]]) - | Extern -> ":extern",("Marks the field as extern so it is not generated",[UsedOn TClassField]) - | FakeEnum -> ":fakeEnum",("Treat enum as collection of values of the specified type",[HasParam "Type name";UsedOn TEnum]) - | File -> ":file",("Includes a given binary file into the target Swf and associates it with the class (must extend flash.utils.ByteArray)",[HasParam "File path";UsedOn TClass;Platform Flash]) - | FileXml -> ":fileXml",("Include xml attribute snippet in Build.xml entry for file",[UsedOn TClass;Platform Cpp]) - | Final -> ":final",("Prevents a class from being extended",[UsedOn TClass]) - | Fixed -> ":fixed",("Delcares an anonymous object to have fixed fields",[ (*UsedOn TObjectDecl(_)*)]) - | FlatEnum -> ":flatEnum",("Internally used to mark an enum as being flat, i.e. having no function constructors",[UsedOn TEnum; UsedInternally]) - | Font -> ":font",("Embeds the given TrueType font into the class (must extend flash.text.Font)",[HasParam "TTF path";HasParam "Range String";UsedOn TClass]) - | ForLoopVariable -> ":forLoopVariable",("Internally used to mark for-loop variables",[UsedInternally]) - | Forward -> ":forward",("Forwards field access to underlying type",[HasParam "List of field names";UsedOn TAbstract]) - | ForwardStatics -> ":forwardStatics",("Forwards static field access to underlying type",[HasParam "List of field names";UsedOn TAbstract]) - | From -> ":from",("Specifies that the field of the abstract is a cast operation from the type identified in the function",[UsedOn TAbstractField]) - | FunctionCode -> ":functionCode",("Used to inject platform-native code into a function",[Platforms [Cpp;Java;Cs]]) - | FunctionTailCode -> ":functionTailCode",("",[Platform Cpp]) - | Generic -> ":generic",("Marks a class or class field as generic so each type parameter combination generates its own type/field",[UsedOnEither [TClass;TClassField]]) - | GenericBuild -> ":genericBuild",("Builds instances of a type using the specified macro",[UsedOn TClass]) - | GenericInstance -> ":genericInstance",("Internally used to mark instances of @:generic methods",[UsedOn TClassField;UsedInternally]) - | Getter -> ":getter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash]) - | Hack -> ":hack",("Allows extending classes marked as @:final",[UsedOn TClass]) - | HasUntyped -> (":has_untyped",("Used by the typer to mark fields that have untyped expressions",[UsedInternally])) - | HaxeGeneric -> ":haxeGeneric",("Used internally to annotate non-native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; UsedInternally]) - | HeaderClassCode -> ":headerClassCode",("Code to be injected into the generated class, in the header",[Platform Cpp]) - | HeaderCode -> ":headerCode",("Code to be injected into the generated header file",[Platform Cpp]) - | HeaderInclude -> ":headerInclude",("File to be included in generated header file",[Platform Cpp]) - | HeaderNamespaceCode -> ":headerNamespaceCode",("",[Platform Cpp]) - | HxGen -> ":hxGen",("Annotates that an extern class was generated by Haxe",[Platforms [Java;Cs]; UsedOnEither [TClass;TEnum]]) - | IfFeature -> ":ifFeature",("Causes a field to be kept by DCE if the given feature is part of the compilation",[HasParam "Feature name";UsedOn TClassField]) - | Impl -> ":impl",("Used internally to mark abstract implementation fields",[UsedOn TAbstractField; UsedInternally]) - | PythonImport -> ":pythonImport",("Generates python import statement for extern classes",[Platforms [Python]; UsedOn TClass]) - | ImplicitCast -> ":implicitCast",("Generated automatically on the AST when an implicit abstract cast happens",[UsedInternally; UsedOn TExpr]) - | Include -> ":include",("",[Platform Cpp]) - | InitPackage -> ":initPackage",("Some weird thing for Genjs we want to remove someday",[UsedInternally; Platform Js]) - | InlineConstructorArgument _ -> ":inlineConstructorArgument",("Internally used to mark expressions that were passed as arguments of an inlined constructor",[UsedInternally]) - | InlineConstructorVariable -> ":inlineConstructorVariable",("Internally used to mark variables that come from inlined constructors",[UsedInternally]) - | Internal -> ":internal",("Generates the annotated field/class with 'internal' access",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum;TClassField]]) - | IsVar -> ":isVar",("Forces a physical field to be generated for properties that otherwise would not require one",[UsedOn TClassField]) - | JavaCanonical -> ":javaCanonical",("Used by the Java target to annotate the canonical path of the type",[HasParam "Output type package";HasParam "Output type name";UsedOnEither [TClass;TEnum]; Platform Java]) - | JavaNative -> ":javaNative",("Automatically added by -java-lib on classes generated from JAR/class files",[Platform Java; UsedOnEither[TClass;TEnum]; UsedInternally]) - | JsRequire -> ":jsRequire",("Generate javascript module require expression for given extern",[Platform Js; UsedOn TClass]) - | LuaRequire -> ":luaRequire",("Generate lua module require expression for given extern",[Platform Lua; UsedOn TClass]) - | LuaDotMethod -> ":luaDotMethod",("Indicates that the given extern type instance should have dot-style invocation for methods instead of colon.",[Platform Lua; UsedOnEither[TClass;TClassField]]) - | Keep -> ":keep",("Causes a field or type to be kept by DCE",[]) - | KeepInit -> ":keepInit",("Causes a class to be kept by DCE even if all its field are removed",[UsedOn TClass]) - | KeepSub -> ":keepSub",("Extends @:keep metadata to all implementing and extending classes",[UsedOn TClass]) - | LibType -> ":libType",("Used by -net-lib and -java-lib to mark a class that shouldn't be checked (overrides, interfaces, etc) by the type loader",[UsedInternally; UsedOn TClass; Platforms [Java;Cs]]) - | LoopLabel -> ":loopLabel",("Mark loop and break expressions with a label to support breaking from within switch",[UsedInternally]) - | Meta -> ":meta",("Internally used to mark a class field as being the metadata field",[]) - | Macro -> ":macro",("(deprecated)",[]) - | MaybeUsed -> ":maybeUsed",("Internally used by DCE to mark fields that might be kept",[UsedInternally]) - | MergeBlock -> ":mergeBlock",("Merge the annotated block into the current scope",[UsedOn TExpr]) - | MultiReturn -> ":multiReturn",("Annotates an extern class as the result of multi-return function",[UsedOn TClass; Platform Lua]) - | MultiType -> ":multiType",("Specifies that an abstract chooses its this-type from its @:to functions",[UsedOn TAbstract; HasParam "Relevant type parameters"]) - | Native -> ":native",("Rewrites the path of a class or enum during generation",[HasParam "Output type path";UsedOnEither [TClass;TEnum]]) - | NativeChildren -> ":nativeChildren",("Annotates that all children from a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs]; UsedOn TClass]) - | NativeGen -> ":nativeGen",("Annotates that a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs;Python]; UsedOnEither[TClass;TEnum]]) - | NativeGeneric -> ":nativeGeneric",("Used internally to annotate native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; UsedInternally]) - | NativeProperty -> ":nativeProperty",("Use native properties which will execute even with dynamic usage",[Platform Cpp]) - | NativeStaticExtension -> ":nativeStaticExtension",("Converts static function syntax into member call",[Platform Cpp]) - | NoCompletion -> ":noCompletion",("Prevents the compiler from suggesting completion on this field",[UsedOn TClassField]) - | NoDebug -> ":noDebug",("Does not generate debug information into the Swf even if -debug is set",[UsedOnEither [TClass;TClassField];Platform Flash]) - | NoDoc -> ":noDoc",("Prevents a type from being included in documentation generation",[]) - | NoExpr -> ":noExpr",("Internally used to mark abstract fields which have no expression by design",[UsedInternally]) - | NoImportGlobal -> ":noImportGlobal",("Prevents a static field from being imported with import Class.*",[UsedOn TAnyField]) - | NonVirtual -> ":nonVirtual",("Declares function to be non-virtual in cpp",[Platform Cpp]) - | NoPackageRestrict -> ":noPackageRestrict",("Allows a module to be accessed across all targets if found on its first type",[UsedInternally]) - | NoPrivateAccess -> ":noPrivateAccess",("Disallow private access to anything for the annotated expression",[UsedOn TExpr]) - | NoStack -> ":noStack",("",[Platform Cpp]) - | NotNull -> ":notNull",("Declares an abstract type as not accepting null values",[UsedOn TAbstract]) - | NoUsing -> ":noUsing",("Prevents a field from being used with 'using'",[UsedOn TClassField]) - | Ns -> ":ns",("Internally used by the Swf generator to handle namespaces",[Platform Flash]) - | Objc -> ":objc",("Declares a class or interface that is used to interoperate with Objective-C code",[Platform Cpp;UsedOn TClass]) - | ObjcProtocol -> ":objcProtocol",("Associates an interface with, or describes a function in, a native Objective-C protocol.",[Platform Cpp;UsedOnEither [TClass;TClassField] ]) - | Op -> ":op",("Declares an abstract field as being an operator overload",[HasParam "The operation";UsedOn TAbstractField]) - | Optional -> ":optional",("Marks the field of a structure as optional",[UsedOn TClassField]) - | Overload -> ":overload",("Allows the field to be called with different argument types",[HasParam "Function specification (no expression)";UsedOn TClassField]) - | PhpGlobal -> ":phpGlobal",("Indicates that static fields of an extern class actually are located in the global PHP namespace",[Platform Php;UsedOn TClass]) - | PhpClassConst -> ":phpClassConst",("Indicates that a static var of an extern class is a PHP class constant",[Platform Php;UsedOn TClassField]) - | PhpMagic -> ":phpMagic",("Treat annotated field as special PHP magic field. This meta makes compiler avoid renaming such fields on generating PHP code.",[Platform Php;UsedOn TClassField]) - | PhpNoConstructor -> ":phpNoConstructor",("Special meta for extern classes which do not have native constructor in PHP, but need a constructor in Haxe extern",[Platform Php;UsedOn TClass]) - | Pos -> ":pos",("Sets the position of a reified expression",[HasParam "Position";UsedOn TExpr]) - | Public -> ":public",("Marks a class field as being public",[UsedOn TClassField;UsedInternally]) - | PublicFields -> ":publicFields",("Forces all class fields of inheriting classes to be public",[UsedOn TClass]) - | PrivateAccess -> ":privateAccess",("Allow private access to anything for the annotated expression",[UsedOn TExpr]) - | Protected -> ":protected",("Marks a class field as being protected",[UsedOn TClassField;Platforms [Cs;Java;Flash]]) - | Property -> ":property",("Marks a property field to be compiled as a native C# property",[UsedOn TClassField;Platform Cs]) - | Pure -> ":pure",("Marks a class field, class or expression as pure (side-effect free)",[UsedOnEither [TClass;TClassField;TExpr]]) - | ReadOnly -> ":readOnly",("Generates a field with the 'readonly' native keyword",[Platform Cs; UsedOn TClassField]) - | RealPath -> ":realPath",("Internally used on @:native types to retain original path information",[UsedInternally]) - | Remove -> ":remove",("Causes an interface to be removed from all implementing classes before generation",[UsedOn TClass]) - | Require -> ":require",("Allows access to a field only if the specified compiler flag is set",[HasParam "Compiler flag to check";UsedOn TClassField]) - | RequiresAssign -> ":requiresAssign",("Used internally to mark certain abstract operator overloads",[UsedInternally]) - | Resolve -> ":resolve",("Abstract fields marked with this metadata can be used to resolve unknown fields",[UsedOn TClassField]) - | Rtti -> ":rtti",("Adds runtime type information",[UsedOn TClass]) - | Runtime -> ":runtime",("?",[]) - | RuntimeValue -> ":runtimeValue",("Marks an abstract as being a runtime value",[UsedOn TAbstract]) - | Scalar -> ":scalar",("Used by hxcpp to mark a custom coreType abstract",[UsedOn TAbstract; Platform Cpp]) - | SelfCall -> ":selfCall",("Translates method calls into calling object directly",[UsedOn TClassField; Platforms [Js;Lua]]) - | Setter -> ":setter",("Generates a native setter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash]) - | StackOnly -> ":stackOnly",("Instances of this type can only appear on the stack",[Platform Cpp]) - | StoredTypedExpr -> ":storedTypedExpr",("Used internally to reference a typed expression returned from a macro",[UsedInternally]) - | SkipCtor -> ":skipCtor",("Used internally to generate a constructor as if it were a native type (no __hx_ctor)",[Platforms [Java;Cs]; UsedInternally]) - | SkipReflection -> ":skipReflection",("Used internally to annotate a field that shouldn't have its reflection data generated",[Platforms [Java;Cs]; UsedOn TClassField; UsedInternally]) - | Sound -> ":sound",( "Includes a given .wav or .mp3 file into the target Swf and associates it with the class (must extend flash.media.Sound)",[HasParam "File path";UsedOn TClass;Platform Flash]) - | SourceFile -> ":sourceFile",("Source code filename for external class",[Platform Cpp]) - | Strict -> ":strict",("Used to declare a native C# attribute or a native Java metadata. Is type checked",[Platforms [Java;Cs]]) - | Struct -> ":struct",("Marks a class definition as a struct",[Platform Cs; UsedOn TClass]) - | StructAccess -> ":structAccess",("Marks an extern class as using struct access('.') not pointer('->')",[Platform Cpp; UsedOn TClass]) - | StructInit -> ":structInit",("Allows one to initialize the class with a structure that matches constructor parameters",[UsedOn TClass]) - | SuppressWarnings -> ":suppressWarnings",("Adds a SuppressWarnings annotation for the generated Java class",[Platform Java; UsedOn TClass]) - | TemplatedCall -> ":templatedCall",("Indicates that the first parameter of static call should be treated as a template argument",[Platform Cpp; UsedOn TClassField]) - | Throws -> ":throws",("Adds a 'throws' declaration to the generated function",[HasParam "Type as String"; Platform Java; UsedOn TClassField]) - | This -> ":this",("Internally used to pass a 'this' expression to macros",[UsedInternally; UsedOn TExpr]) - | To -> ":to",("Specifies that the field of the abstract is a cast operation to the type identified in the function",[UsedOn TAbstractField]) - | ToString -> ":toString",("Internally used",[UsedInternally]) - | Transient -> ":transient",("Adds the 'transient' flag to the class field",[Platform Java; UsedOn TClassField]) - | ValueUsed -> ":valueUsed",("Internally used by DCE to mark an abstract value as used",[UsedInternally]) - | Volatile -> ":volatile",("",[Platforms [Java;Cs]]) - | UnifyMinDynamic -> ":unifyMinDynamic",("Allows a collection of types to unify to Dynamic",[UsedOn TClassField]) - | Unreflective -> ":unreflective",("",[Platform Cpp]) - | Unsafe -> ":unsafe",("Declares a class, or a method with the C#'s 'unsafe' flag",[Platform Cs; UsedOnEither [TClass;TClassField]]) - | Usage -> ":usage",("Internal metadata used to mark a symbol for which usage request was invoked",[UsedInternally]) - | Used -> ":used",("Internally used by DCE to mark a class or field as used",[UsedInternally]) - | UserVariable -> ":userVariable",("Internally used to mark variables that come from user code",[UsedInternally]) - | Value -> ":value",("Used to store default values for fields and function arguments",[UsedOn TClassField]) - | Void -> ":void",("Use Cpp native 'void' return type",[Platform Cpp]) - | Last -> assert false - (* do not put any custom metadata after Last *) - | Dollar s -> "$" ^ s,("",[]) - | Custom s -> s,("",[]) +let rec remove m = function + | [] -> [] + | (m2,_,_) :: l when m = m2 -> l + | x :: l -> x :: remove m l let to_string m = fst (get_info m) @@ -398,15 +38,14 @@ let get_documentation d = let params = ref [] and used = ref [] and pfs = ref [] in List.iter (function | HasParam s -> params := s :: !params - | Platform f -> pfs := f :: !pfs | Platforms fl -> pfs := fl @ !pfs - | UsedOn u -> used := u :: !used - | UsedOnEither ul -> used := ul @ !used + | UsedOn ul -> used := ul @ !used | UsedInternally -> assert false + | Link _ -> () ) flags; let params = (match List.rev !params with | [] -> "" - | l -> "(" ^ String.concat "," l ^ ")" + | l -> "(<" ^ String.concat ">, <" l ^ ">) " ) in let pfs = platform_list_help (List.rev !pfs) in let str = "@" ^ t in @@ -428,3 +67,11 @@ let get_documentation_list () = in let all = List.sort (fun (s1,_) (s2,_) -> String.compare s1 s2) (loop 0) in all,!m + +let get_all () = + let rec loop i = + let d = Obj.magic i in + if d <> Last then d :: loop (i + 1) + else [] + in + loop 0 diff --git a/src/core/numeric.ml b/src/core/numeric.ml new file mode 100644 index 00000000000..1fbd80df9aa --- /dev/null +++ b/src/core/numeric.ml @@ -0,0 +1,74 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(* Taken from OCaml source typing/oprint.ml + + This is a better version of string_of_float which prints without loss of precision + so that float_of_string (float_repres x) = x for all floats x +*) +let valid_float_lexeme s = + let l = String.length s in + let rec loop i = + if i >= l then s ^ "." else + match s.[i] with + | '0' .. '9' | '-' -> loop (i+1) + | _ -> s + in loop 0 + +let float_repres f = + match classify_float f with + | FP_nan -> "nan" + | FP_infinite -> + if f < 0.0 then "neg_infinity" else "infinity" + | _ -> + let float_val = + let s1 = Printf.sprintf "%.12g" f in + if f = float_of_string s1 then s1 else + let s2 = Printf.sprintf "%.15g" f in + if f = float_of_string s2 then s2 else + Printf.sprintf "%.18g" f + in valid_float_lexeme float_val + +let parse_float s = + let rec loop sp i = + if i = String.length s then (if sp = 0 then s else String.sub s sp (i - sp)) else + match String.unsafe_get s i with + | ' ' when sp = i -> loop (sp + 1) (i + 1) + | '0'..'9' | '-' | '+' | 'e' | 'E' | '.' -> loop sp (i + 1) + | _ -> String.sub s sp (i - sp) + in + float_of_string (loop 0 0) + +let parse_int s = + let rec loop_hex i = + if i = String.length s then s else + match String.unsafe_get s i with + | '0'..'9' | 'a'..'f' | 'A'..'F' -> loop_hex (i + 1) + | _ -> String.sub s 0 i + in + let rec loop sp i = + if i = String.length s then (if sp = 0 then s else String.sub s sp (i - sp)) else + match String.unsafe_get s i with + | '0'..'9' -> loop sp (i + 1) + | ' ' when sp = i -> loop (sp + 1) (i + 1) + | '-' when i = 0 -> loop sp (i + 1) + | ('x' | 'X') when i = 1 && String.get s 0 = '0' -> loop_hex (i + 1) + | _ -> String.sub s sp (i - sp) + in + Int32.of_string (loop 0 0) \ No newline at end of file diff --git a/src/core/path.ml b/src/core/path.ml index 5684a0bde8c..11f5c550af6 100644 --- a/src/core/path.ml +++ b/src/core/path.ml @@ -1,3 +1,5 @@ +open StringHelper + let get_path_parts f = (* this function is quite weird: it tries to determine whether the given @@ -38,7 +40,7 @@ let parse_path f = | x :: l -> if String.length x = 0 then error "empty part" - else if x.[0] < 'a' || x.[0] > 'z' then + else if (x.[0] < 'a' || x.[0] > 'z') && x.[0] <> '_' then error "Package name must start with a lower case character"; invalid_char x; let path,name = loop l in @@ -46,15 +48,6 @@ let parse_path f = in loop cl -let starts_uppercase x = - x.[0] = '_' || (x.[0] >= 'A' && x.[0] <= 'Z') - -let check_uppercase x = - if String.length x = 0 then - failwith "empty part" - else if not (starts_uppercase x) then - failwith "Class name must start with uppercase character" - let parse_type_path s = let pack,name = parse_path s in check_uppercase name; @@ -159,6 +152,18 @@ let make_valid_filename s = let r = Str.regexp "[^A-Za-z0-9_\\-\\.,]" in Str.global_substitute r (fun s -> "_") s +let module_name_of_file file = + match List.rev (Str.split path_regex (get_real_path file)) with + | s :: _ -> + let s = match List.rev (ExtString.String.nsplit s ".") with + | [s] -> s + | _ :: sl -> String.concat "." (List.rev sl) + | [] -> "" + in + s + | [] -> + assert false + let rec create_file bin ext acc = function | [] -> assert false | d :: [] -> @@ -170,4 +175,80 @@ let rec create_file bin ext acc = function | d :: l -> let dir = String.concat "/" (List.rev (d :: acc)) in if not (Sys.file_exists (remove_trailing_slash dir)) then Unix.mkdir dir 0o755; - create_file bin ext (d :: acc) l \ No newline at end of file + create_file bin ext (d :: acc) l + +let rec mkdir_recursive base dir_list = + match dir_list with + | [] -> () + | dir :: remaining -> + let path = match base with + | "" -> dir + | "/" -> "/" ^ dir + | _ -> base ^ "/" ^ dir + in + let path_len = String.length path in + let path = + if path_len > 0 && (path.[path_len - 1] = '/' || path.[path_len - 1] == '\\') then + String.sub path 0 (path_len - 1) + else + path + in + if not ( (path = "") || ( (path_len = 2) && ((String.sub path 1 1) = ":") ) ) then + if not (Sys.file_exists path) then + Unix.mkdir path 0o755; + mkdir_recursive (if (path = "") then "/" else path) remaining + +let mkdir_from_path path = + let parts = Str.split_delim (Str.regexp "[\\/]+") path in + match parts with + | [] -> (* path was "" *) () + | _ -> + let dir_list = List.rev (List.tl (List.rev parts)) in + mkdir_recursive "" dir_list + +let full_dot_path pack mname tname = + if tname = mname then (pack,mname) else (pack @ [mname],tname) + +module FilePath = struct + type t = { + directory : string option; + file_name : string option; + extension : string option; + backslash : bool; + } + + let create directory file_name extension backslash = { + directory = directory; + file_name = file_name; + extension = extension; + backslash = backslash; + } + + let parse path = match path with + | "." | ".." -> + create (Some path) None None false + | _ -> + let c1 = String.rindex path '/' in + let c2 = String.rindex path '\\' in + let split s at = String.sub s 0 at,String.sub s (at + 1) (String.length s - at - 1) in + let dir,path,backslash = if c1 < c2 then begin + let dir,path = split path c2 in + Some dir,path,true + end else if c2 < c1 then begin + let dir,path = split path c1 in + Some dir,path,false + end else + None,path,false + in + let file,ext = if String.length path = 0 then + None,None + else begin + let cp = String.rindex path '.' in + if cp <> -1 then begin + let file,ext = split path cp in + Some file,Some ext + end else + Some path,None + end in + create dir file ext backslash +end \ No newline at end of file diff --git a/src/core/socket.ml b/src/core/socket.ml new file mode 100644 index 00000000000..58888134db8 --- /dev/null +++ b/src/core/socket.ml @@ -0,0 +1,63 @@ +open Unix + +type t = { + addr : Unix.inet_addr; + port : int; + mutable socket : Unix.file_descr option; + send_mutex : Mutex.t; +} + +let create host port = + let host = Unix.inet_addr_of_string host in + let socket = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in + Unix.connect socket (Unix.ADDR_INET (host,port)); + { + addr = host; + port = port; + socket = Some socket; + send_mutex = Mutex.create(); + } + +let read_byte this i = int_of_char (Bytes.get this i) + +let read_ui16 this i = + let ch1 = read_byte this i in + let ch2 = read_byte this (i + 1) in + ch1 lor (ch2 lsl 8) + +let read_string socket = + match socket.socket with + | None -> + failwith "no socket" (* TODO: reconnect? *) + | Some socket -> + let buf = Bytes.create 2 in + let _ = recv socket buf 0 2 [] in + let i = read_ui16 buf 0 in + let buf = Bytes.create i in + let _ = recv socket buf 0 i [] in + Bytes.to_string buf + +let send_string socket s = + match socket.socket with + | None -> + failwith "no socket" (* TODO: reconnect? *) + | Some socket -> + let b = Bytes.unsafe_of_string s in + let l = Bytes.length b in + let buf = Bytes.make 4 ' ' in + EvalBytes.write_i32 buf 0 (Int32.of_int l); + ignore(send socket buf 0 4 []); + let rec loop length offset = + if length <= 0 then + () + else begin + let k = min length 0xFFFF in + ignore(send socket b offset k []); + loop (length - k) (offset + k) + end + in + loop l 0 + +let send_string socket s = + Mutex.lock socket.send_mutex; + Std.finally (fun () -> Mutex.unlock socket.send_mutex) (send_string socket) s \ No newline at end of file diff --git a/src/core/stringError.ml b/src/core/stringError.ml new file mode 100644 index 00000000000..b16e43cba17 --- /dev/null +++ b/src/core/stringError.ml @@ -0,0 +1,73 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(* Source: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#OCaml *) +let levenshtein a b = + let x = Array.init (String.length a) (fun i -> a.[i]) in + let y = Array.init (String.length b) (fun i -> b.[i]) in + let minimum (x:int) y z = + let m' (a:int) b = if a < b then a else b in + m' (m' x y) z + in + let init_matrix n m = + let init_col = Array.init m in + Array.init n (function + | 0 -> init_col (function j -> j) + | i -> init_col (function 0 -> i | _ -> 0) + ) + in + match Array.length x, Array.length y with + | 0, n -> n + | m, 0 -> m + | m, n -> + let matrix = init_matrix (m + 1) (n + 1) in + for i = 1 to m do + let s = matrix.(i) and t = matrix.(i - 1) in + for j = 1 to n do + let cost = abs (compare x.(i - 1) y.(j - 1)) in + s.(j) <- minimum (t.(j) + 1) (s.(j - 1) + 1) (t.(j - 1) + cost) + done + done; + matrix.(m).(n) + +let filter_similar f cl = + let rec loop sl = match sl with + | (x,i) :: sl when f x i -> x :: loop sl + | _ -> [] + in + loop cl + +let get_similar s sl = + if sl = [] then [] else + let cl = List.map (fun s2 -> s2,levenshtein s s2) sl in + let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in + let cl = filter_similar (fun s2 i -> i <= (min (String.length s) (String.length s2)) / 3) cl in + cl + +let string_error_raise s sl msg = + if sl = [] then msg else + let cl = get_similar s sl in + match cl with + | [] -> raise Not_found + | [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s + | sl -> Printf.sprintf "%s (Suggestions: %s)" msg (String.concat ", " sl) + +let string_error s sl msg = + try string_error_raise s sl msg + with Not_found -> msg \ No newline at end of file diff --git a/src/core/stringHelper.ml b/src/core/stringHelper.ml new file mode 100644 index 00000000000..3168488e445 --- /dev/null +++ b/src/core/stringHelper.ml @@ -0,0 +1,42 @@ +let uppercase s = + let bytes = Bytes.of_string s in + Bytes.iteri + (fun idx char -> + let code = Char.code char in + if 97 <= code && code <= 122 then + Bytes.set bytes idx (Char.chr (code - 32)) + ) + bytes; + Bytes.to_string bytes + +let capitalize s = + if String.length s = 0 then "" + else + let bytes = Bytes.of_string s in + let code = Char.code (Bytes.get bytes 0) in + if 97 <= code && code <= 122 then + Bytes.set bytes 0 (Char.chr (code - 32)); + Bytes.to_string bytes + +let starts_uppercase x = + x.[0] = '_' || (x.[0] >= 'A' && x.[0] <= 'Z') + +let check_uppercase x = + if String.length x = 0 then + failwith "empty part" + else if not (starts_uppercase x) then + failwith "Class name must start with uppercase character" + +let s_escape ?(hex=true) s = + let b = Buffer.create (String.length s) in + for i = 0 to (String.length s) - 1 do + match s.[i] with + | '\n' -> Buffer.add_string b "\\n" + | '\t' -> Buffer.add_string b "\\t" + | '\r' -> Buffer.add_string b "\\r" + | '"' -> Buffer.add_string b "\\\"" + | '\\' -> Buffer.add_string b "\\\\" + | c when int_of_char c < 32 && hex -> Buffer.add_string b (Printf.sprintf "\\x%.2X" (int_of_char c)) + | c -> Buffer.add_char b c + done; + Buffer.contents b \ No newline at end of file diff --git a/src/core/texpr.ml b/src/core/texpr.ml new file mode 100644 index 00000000000..3752aef98f2 --- /dev/null +++ b/src/core/texpr.ml @@ -0,0 +1,535 @@ +open Globals +open Ast +open Type +open Error + +let equal_fa fa1 fa2 = match fa1,fa2 with + | FStatic(c1,cf1),FStatic(c2,cf2) -> c1 == c2 && cf1.cf_name == cf2.cf_name + | FInstance(c1,tl1,cf1),FInstance(c2,tl2,cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1.cf_name == cf2.cf_name + | FAnon cf1,FAnon cf2 -> cf1.cf_name = cf2.cf_name + | FDynamic s1,FDynamic s2 -> s1 = s2 + | FClosure(None,cf1),FClosure(None,cf2) -> cf1.cf_name == cf2.cf_name + | FClosure(Some(c1,tl1),cf1),FClosure(Some(c2,tl2),cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1.cf_name == cf2.cf_name + | FEnum(en1,ef1),FEnum(en2,ef2) -> en1 == en2 && ef1.ef_name == ef2.ef_name + | _ -> false + +let rec equal e1 e2 = match e1.eexpr,e2.eexpr with + | TConst ct1,TConst ct2 -> ct1 = ct2 + | TLocal v1,TLocal v2 -> v1 == v2 + | TArray(eb1,ei1),TArray(eb2,ei2) -> equal eb1 eb2 && equal ei1 ei2 + | TBinop(op1,lhs1,rhs1),TBinop(op2,lhs2,rhs2) -> op1 = op2 && equal lhs1 lhs2 && equal rhs1 rhs2 + | TField(e1,fa1),TField(e2,fa2) -> equal e1 e2 && equal_fa fa1 fa2 + | TTypeExpr (TClassDecl c1),TTypeExpr (TClassDecl c2) -> c1 == c2 + | TTypeExpr (TEnumDecl e1),TTypeExpr (TEnumDecl e2) -> e1 == e2 + | TTypeExpr (TTypeDecl t1),TTypeExpr (TTypeDecl t2) -> t1 == t2 + | TTypeExpr (TAbstractDecl a1),TTypeExpr (TAbstractDecl a2) -> a1 == a2 + | TTypeExpr _,TTypeExpr _ -> false + | TParenthesis e1,TParenthesis e2 -> equal e1 e2 + | TObjectDecl fl1,TObjectDecl fl2 -> safe_for_all2 (fun (s1,e1) (s2,e2) -> s1 = s2 && equal e1 e2) fl1 fl2 + | (TArrayDecl el1,TArrayDecl el2) | (TBlock el1,TBlock el2) -> safe_for_all2 equal el1 el2 + | TCall(e1,el1),TCall(e2,el2) -> equal e1 e2 && safe_for_all2 equal el1 el2 + | TNew(c1,tl1,el1),TNew(c2,tl2,el2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && safe_for_all2 equal el1 el2 + | TUnop(op1,flag1,e1),TUnop(op2,flag2,e2) -> op1 = op2 && flag1 = flag2 && equal e1 e2 + | TFunction tf1,TFunction tf2 -> tf1 == tf2 + | TVar(v1,None),TVar(v2,None) -> v1 == v2 + | TVar(v1,Some e1),TVar(v2,Some e2) -> v1 == v2 && equal e1 e2 + | TFor(v1,ec1,eb1),TFor(v2,ec2,eb2) -> v1 == v2 && equal ec1 ec2 && equal eb1 eb2 + | TIf(e1,ethen1,None),TIf(e2,ethen2,None) -> equal e1 e2 && equal ethen1 ethen2 + | TIf(e1,ethen1,Some eelse1),TIf(e2,ethen2,Some eelse2) -> equal e1 e2 && equal ethen1 ethen2 && equal eelse1 eelse2 + | TWhile(e1,eb1,flag1),TWhile(e2,eb2,flag2) -> equal e1 e2 && equal eb2 eb2 && flag1 = flag2 + | TSwitch(e1,cases1,eo1),TSwitch(e2,cases2,eo2) -> + equal e1 e2 && + safe_for_all2 (fun (el1,e1) (el2,e2) -> safe_for_all2 equal el1 el2 && equal e1 e2) cases1 cases2 && + (match eo1,eo2 with None,None -> true | Some e1,Some e2 -> equal e1 e2 | _ -> false) + | TTry(e1,catches1),TTry(e2,catches2) -> equal e1 e2 && safe_for_all2 (fun (v1,e1) (v2,e2) -> v1 == v2 && equal e1 e2) catches1 catches2 + | TReturn None,TReturn None -> true + | TReturn(Some e1),TReturn(Some e2) -> equal e1 e2 + | TThrow e1,TThrow e2 -> equal e1 e2 + | TCast(e1,None),TCast(e2,None) -> equal e1 e2 + | TCast(e1,Some mt1),TCast(e2,Some mt2) -> equal e1 e2 && mt1 == mt2 + | TMeta((m1,el1,_),e1),TMeta((m2,el2,_),e2) -> m1 = m2 && safe_for_all2 (fun e1 e2 -> (* TODO: cheating? *) (Ast.Printer.s_expr e1) = (Ast.Printer.s_expr e2)) el1 el2 && equal e1 e2 + | (TBreak,TBreak) | (TContinue,TContinue) -> true + | TEnumParameter(e1,ef1,i1),TEnumParameter(e2,ef2,i2) -> equal e1 e2 && ef1 == ef2 && i1 = i2 + | _ -> false + +let duplicate_tvars e = + let vars = Hashtbl.create 0 in + let copy_var v = + let v2 = alloc_var v.v_kind v.v_name v.v_type v.v_pos in + v2.v_meta <- v.v_meta; + v2.v_extra <- v.v_extra; + Hashtbl.add vars v.v_id v2; + v2; + in + let rec build_expr e = + match e.eexpr with + | TVar (v,eo) -> + let v2 = copy_var v in + {e with eexpr = TVar(v2, Option.map build_expr eo)} + | TFor (v,e1,e2) -> + let v2 = copy_var v in + {e with eexpr = TFor(v2, build_expr e1, build_expr e2)} + | TTry (e1,cl) -> + let cl = List.map (fun (v,e) -> + let v2 = copy_var v in + v2, build_expr e + ) cl in + {e with eexpr = TTry(build_expr e1, cl)} + | TFunction f -> + let args = List.map (fun (v,c) -> copy_var v, c) f.tf_args in + let f = { + tf_args = args; + tf_type = f.tf_type; + tf_expr = build_expr f.tf_expr; + } in + {e with eexpr = TFunction f} + | TLocal v -> + (try + let v2 = Hashtbl.find vars v.v_id in + {e with eexpr = TLocal v2} + with _ -> + e) + | _ -> + map_expr build_expr e + in + build_expr e + +let rec skip e = match e.eexpr with + | TParenthesis e1 | TMeta(_,e1) | TBlock [e1] | TCast(e1,None) -> skip e1 + | _ -> e + +let foldmap_list f acc el = + let rec loop acc el acc2 = (match el with + | [] -> acc,(List.rev acc2) + | e1 :: el -> + let acc,e1 = f acc e1 in + loop acc el (e1 :: acc2)) + in loop acc el [] + +let foldmap_opt f acc eo = match eo with + | Some(e) -> let acc,e = f acc e in acc,Some(e) + | None -> acc,eo + +let foldmap_pairs f acc pairs = + let acc,pairs = List.fold_left + (fun (acc,el) (v,e) -> let acc,e = f acc e in (acc,(v,e) :: el)) + (acc,[]) + pairs + in acc,(List.rev pairs) + +let foldmap f acc e = + begin match e.eexpr with + | TConst _ + | TLocal _ + | TBreak + | TContinue + | TTypeExpr _ + | TIdent _ -> + acc,e + | TArray (e1,e2) -> + let acc,e1 = f acc e1 in + let acc,e2 = f acc e2 in + acc,{ e with eexpr = TArray (e1, e2) } + | TBinop (op,e1,e2) -> + let acc,e1 = f acc e1 in + let acc,e2 = f acc e2 in + acc,{ e with eexpr = TBinop (op,e1,e2) } + | TFor (v,e1,e2) -> + let acc,e1 = f acc e1 in + let acc,e2 = f acc e2 in + acc,{ e with eexpr = TFor (v,e1,e2) } + | TWhile (e1,e2,flag) -> + let acc,e1 = f acc e1 in + let acc,e2 = f acc e2 in + acc,{ e with eexpr = TWhile (e1,e2,flag) } + | TThrow e1 -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TThrow (e1) } + | TEnumParameter (e1,ef,i) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TEnumParameter(e1,ef,i) } + | TEnumIndex e1 -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TEnumIndex e1 } + | TField (e1,v) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TField (e1,v) } + | TParenthesis e1 -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TParenthesis (e1) } + | TUnop (op,pre,e1) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TUnop (op,pre,e1) } + | TArrayDecl el -> + let acc,el = foldmap_list f acc el in + acc,{ e with eexpr = TArrayDecl el } + | TNew (t,pl,el) -> + let acc,el = foldmap_list f acc el in + acc,{ e with eexpr = TNew (t,pl,el) } + | TBlock el -> + let acc,el = foldmap_list f acc el in + acc,{ e with eexpr = TBlock (el) } + | TObjectDecl el -> + let acc,el = foldmap_pairs f acc el in + acc,{ e with eexpr = TObjectDecl el } + | TCall (e1,el) -> + let acc,e1 = f acc e1 in + let acc,el = foldmap_list f acc el in + acc,{ e with eexpr = TCall (e1,el) } + | TVar (v,eo) -> + let acc,eo = foldmap_opt f acc eo in + acc,{ e with eexpr = TVar (v, eo) } + | TFunction fu -> + let acc,e1 = f acc fu.tf_expr in + acc,{ e with eexpr = TFunction { fu with tf_expr = e1 } } + | TIf (ec,e1,eo) -> + let acc,ec = f acc ec in + let acc,e1 = f acc e1 in + let acc,eo = foldmap_opt f acc eo in + acc,{ e with eexpr = TIf (ec,e1,eo)} + | TSwitch (e1,cases,def) -> + let acc,e1 = f acc e1 in + let acc,cases = List.fold_left (fun (acc,cases) (el,e2) -> + let acc,el = foldmap_list f acc el in + let acc,e2 = f acc e2 in + acc,((el,e2) :: cases) + ) (acc,[]) cases in + let acc,def = foldmap_opt f acc def in + acc,{ e with eexpr = TSwitch (e1, cases, def) } + | TTry (e1,catches) -> + let acc,e1 = f acc e1 in + let acc,catches = foldmap_pairs f acc catches in + acc,{ e with eexpr = TTry (e1, catches) } + | TReturn eo -> + let acc,eo = foldmap_opt f acc eo in + acc,{ e with eexpr = TReturn eo } + | TCast (e1,t) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TCast (e1,t) } + | TMeta (m,e1) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TMeta(m,e1)} + end + +(* Collection of functions that return expressions *) +module Builder = struct + let make_static_this c p = + let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in + mk (TTypeExpr (TClassDecl c)) ta p + + let make_typeexpr mt pos = + let t = + match resolve_typedef mt with + | TClassDecl c -> TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } + | TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) } + | TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) } + | _ -> assert false + in + mk (TTypeExpr mt) t pos + + let make_static_field c cf p = + let e_this = make_static_this c p in + mk (TField(e_this,FStatic(c,cf))) cf.cf_type p + + let make_throw e p = + mk (TThrow e) t_dynamic p + + let make_int basic i p = + mk (TConst (TInt (Int32.of_int i))) basic.tint p + + let make_float basic f p = + mk (TConst (TFloat f)) basic.tfloat p + + let make_bool basic b p = + mk (TConst(TBool b)) basic.tbool p + + let make_string basic s p = + mk (TConst (TString s)) basic.tstring p + + let make_null t p = + mk (TConst TNull) t p + + let make_local v p = + mk (TLocal v) v.v_type p + + let make_const_texpr basic ct p = match ct with + | TString s -> mk (TConst (TString s)) basic.tstring p + | TInt i -> mk (TConst (TInt i)) basic.tint p + | TFloat f -> mk (TConst (TFloat f)) basic.tfloat p + | TBool b -> mk (TConst (TBool b)) basic.tbool p + | TNull -> mk (TConst TNull) (basic.tnull (mk_mono())) p + | _ -> error "Unsupported constant" p + + let field e name t p = + mk (TField (e,try quick_field e.etype name with Not_found -> assert false)) t p + + let fcall e name el ret p = + let ft = tfun (List.map (fun e -> e.etype) el) ret in + mk (TCall (field e name ft p,el)) ret p + + let mk_parent e = + mk (TParenthesis e) e.etype e.epos + + let mk_return e = + mk (TReturn (Some e)) t_dynamic e.epos + + let binop op a b t p = + mk (TBinop (op,a,b)) t p + + let index basic e index t p = + mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) basic.tint p)) t p +end + +let set_default basic a c p = + let t = a.v_type in + let ve = mk (TLocal a) t p in + let cond = TBinop (OpEq,ve,mk (TConst TNull) t p) in + mk (TIf (Builder.mk_parent (mk cond basic.tbool p), mk (TBinop (OpAssign,ve,c)) t p,None)) basic.tvoid p + +(* + Tells if the constructor might be called without any issue whatever its parameters +*) +let rec constructor_side_effects e = + match e.eexpr with + | TBinop (op,_,_) when op <> OpAssign -> + true + | TField (_,FEnum _) -> + false + | TUnop _ | TArray _ | TField _ | TEnumParameter _ | TEnumIndex _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ -> + true + | TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _ + | TFunction _ | TArrayDecl _ | TObjectDecl _ + | TParenthesis _ | TTypeExpr _ | TLocal _ | TMeta _ + | TConst _ | TContinue | TBreak | TCast _ | TIdent _ -> + try + Type.iter (fun e -> if constructor_side_effects e then raise Exit) e; + false; + with Exit -> + true + +let type_constant basic c p = + match c with + | Int s -> + if String.length s > 10 && String.sub s 0 2 = "0x" then error "Invalid hexadecimal integer" p; + (try mk (TConst (TInt (Int32.of_string s))) basic.tint p + with _ -> mk (TConst (TFloat s)) basic.tfloat p) + | Float f -> mk (TConst (TFloat f)) basic.tfloat p + | String s -> mk (TConst (TString s)) basic.tstring p + | Ident "true" -> mk (TConst (TBool true)) basic.tbool p + | Ident "false" -> mk (TConst (TBool false)) basic.tbool p + | Ident "null" -> mk (TConst TNull) (basic.tnull (mk_mono())) p + | Ident t -> error ("Invalid constant : " ^ t) p + | Regexp _ -> error "Invalid constant" p + +let rec type_constant_value basic (e,p) = + match e with + | EConst c -> + type_constant basic c p + | EParenthesis e -> + type_constant_value basic e + | EObjectDecl el -> + mk (TObjectDecl (List.map (fun (k,e) -> k,type_constant_value basic e) el)) (TAnon { a_fields = PMap.empty; a_status = ref Closed }) p + | EArrayDecl el -> + mk (TArrayDecl (List.map (type_constant_value basic) el)) (basic.tarray t_dynamic) p + | _ -> + error "Constant value expected" p + +let for_remap basic v e1 e2 p = + let v' = alloc_var v.v_kind v.v_name e1.etype e1.epos in + let ev' = mk (TLocal v') e1.etype e1.epos in + let t1 = (Abstract.follow_with_abstracts e1.etype) in + let ehasnext = mk (TField(ev',try quick_field t1 "hasNext" with Not_found -> error (s_type (print_context()) t1 ^ "has no field hasNext()") p)) (tfun [] basic.tbool) e1.epos in + let ehasnext = mk (TCall(ehasnext,[])) basic.tbool ehasnext.epos in + let enext = mk (TField(ev',quick_field t1 "next")) (tfun [] v.v_type) e1.epos in + let enext = mk (TCall(enext,[])) v.v_type e1.epos in + let eassign = mk (TVar(v,Some enext)) basic.tvoid p in + let ebody = Type.concat eassign e2 in + mk (TBlock [ + mk (TVar (v',Some e1)) basic.tvoid e1.epos; + mk (TWhile((mk (TParenthesis ehasnext) ehasnext.etype ehasnext.epos),ebody,NormalWhile)) basic.tvoid e1.epos; + ]) basic.tvoid p + +(* -------------------------------------------------------------------------- *) +(* BUILD META DATA OBJECT *) + +let build_metadata api t = + let p, meta, fields, statics = (match t with + | TClassDecl c -> + let fields = List.map (fun f -> f.cf_name,f.cf_meta) (c.cl_ordered_fields @ (match c.cl_constructor with None -> [] | Some f -> [{ f with cf_name = "_" }])) in + let statics = List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in + (c.cl_pos, ["",c.cl_meta],fields,statics) + | TEnumDecl e -> + (e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, []) + | TTypeDecl t -> + (t.t_pos, ["",t.t_meta],(match follow t.t_type with TAnon a -> PMap.fold (fun f acc -> (f.cf_name,f.cf_meta) :: acc) a.a_fields [] | _ -> []),[]) + | TAbstractDecl a -> + (a.a_pos, ["",a.a_meta],[],[]) + ) in + let filter l = + let l = List.map (fun (n,ml) -> n, ExtList.List.filter_map (fun (m,el,p) -> match m with Meta.Custom s when String.length s > 0 && s.[0] <> ':' -> Some (s,el,p) | _ -> None) ml) l in + List.filter (fun (_,ml) -> ml <> []) l + in + let meta, fields, statics = filter meta, filter fields, filter statics in + let make_meta_field ml = + let h = Hashtbl.create 0 in + mk (TObjectDecl (List.map (fun (f,el,p) -> + if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p; + Hashtbl.add h f (); + (f,null_pos,NoQuotes), mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value api) el)) (api.tarray t_dynamic) p + ) ml)) t_dynamic p + in + let make_meta l = + mk (TObjectDecl (List.map (fun (f,ml) -> (f,null_pos,NoQuotes),make_meta_field ml) l)) t_dynamic p + in + if meta = [] && fields = [] && statics = [] then + None + else + let meta_obj = [] in + let meta_obj = (if fields = [] then meta_obj else (("fields",null_pos,NoQuotes),make_meta fields) :: meta_obj) in + let meta_obj = (if statics = [] then meta_obj else (("statics",null_pos,NoQuotes),make_meta statics) :: meta_obj) in + let meta_obj = (try (("obj",null_pos,NoQuotes), make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in + Some (mk (TObjectDecl meta_obj) t_dynamic p) + +let dump_with_pos tabs e = + let buf = Buffer.create 0 in + let add = Buffer.add_string buf in + let rec loop' tabs e = + let p = e.epos in + let add s = add (Printf.sprintf "%4i-%4i %s%s\n" p.pmin p.pmax tabs s) in + let loop e = loop' (tabs ^ " ") e in + match e.eexpr with + | TConst ct -> add (s_const ct) + | TLocal v -> add ("TLocal " ^ v.v_name) + | TTypeExpr mt -> add ("TTypeExpr " ^ (s_type_path (t_infos mt).mt_path)) + | TIdent s -> add ("TIdent " ^ s) + | TEnumParameter(e1,ef,_) -> + add ("TEnumParameter " ^ ef.ef_name); + loop e1 + | TEnumIndex e1 -> + add "TEnumIndex"; + loop e1 + | TArray(e1,e2) -> + add "TArray"; + loop e1; + loop e2; + | TBinop(op,e1,e2) -> + add ("TBinop " ^ (s_binop op)); + loop e1; + loop e2; + | TField(e1,s) -> + add ("TField " ^ (field_name s)); + loop e1 + | TParenthesis e1 -> + add "TParenthesis"; + loop e1 + | TObjectDecl fl -> + add "TObjectDecl"; + List.iter (fun ((n,p,_),e1) -> + Buffer.add_string buf (Printf.sprintf "%4i-%4i %s%s\n" p.pmin p.pmax tabs n); + loop e1 + ) fl; + | TArrayDecl el -> + add "TArrayDecl"; + List.iter loop el + | TCall(e1,el) -> + add "TCall"; + loop e1; + List.iter loop el + | TNew(c,_,el) -> + add ("TNew " ^ s_type_path c.cl_path); + List.iter loop el + | TUnop(op,_,e1) -> + add ("TUnop " ^ (s_unop op)); + loop e1 + | TVar(v,eo) -> + add ("TVar " ^ v.v_name); + begin match eo with + | None -> () + | Some e -> + loop' (Printf.sprintf "%s " tabs) e + end + | TFunction tf -> + add "TFunction"; + loop tf.tf_expr; + | TBlock el -> + add "TBlock"; + List.iter loop el + | TFor(v,e1,e2) -> + add ("TFor " ^ v.v_name); + loop e1; + loop e2; + | TIf(e1,e2,eo) -> + add "TIf"; + loop e1; + loop e2; + Option.may loop eo; + | TWhile(e1,e2,_) -> + add "TWhile"; + loop e1; + loop e2; + | TSwitch(e1,cases,def) -> + add "TSwitch"; + loop e1; + List.iter (fun (el,e) -> + List.iter (loop' (tabs ^ " ")) el; + loop' (tabs ^ " ") e; + ) cases; + Option.may (loop' (tabs ^ " ")) def + | TTry(e1,catches) -> + add "TTry"; + loop e1; + List.iter (fun (v,e) -> + loop' (tabs ^ " ") e + ) catches + | TReturn eo -> + add "TReturn"; + Option.may loop eo; + | TBreak -> + add "TBreak"; + | TContinue -> + add "TContinue" + | TThrow e1 -> + add "EThrow"; + loop e1 + | TCast(e1,_) -> + add "TCast"; + loop e1; + | TMeta((m,_,_),e1) -> + add ("TMeta " ^ fst (Meta.get_info m)); + loop e1 + in + loop' tabs e; + Buffer.contents buf + +let collect_captured_vars e = + let known = Hashtbl.create 0 in + let unknown = ref [] in + let accesses_this = ref false in + let declare v = Hashtbl.add known v.v_id () in + let rec loop e = match e.eexpr with + | TLocal ({v_capture = true; v_id = id} as v) when not (Hashtbl.mem known id) -> + Hashtbl.add known id (); + unknown := v :: !unknown + | TConst (TThis | TSuper) -> + accesses_this := true; + | TVar(v,eo) -> + Option.may loop eo; + declare v + | TFor(v,e1,e2) -> + declare v; + loop e1; + loop e2; + | TFunction tf -> + List.iter (fun (v,_) -> declare v) tf.tf_args; + loop tf.tf_expr + | TTry(e1,catches) -> + loop e1; + List.iter (fun (v,e) -> + declare v; + loop e; + ) catches + | _ -> + Type.iter loop e + in + loop e; + List.rev !unknown,!accesses_this \ No newline at end of file diff --git a/src/core/timer.ml b/src/core/timer.ml new file mode 100644 index 00000000000..faae4985f94 --- /dev/null +++ b/src/core/timer.ml @@ -0,0 +1,171 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +type timer_infos = { + id : string list; + mutable start : float list; + mutable total : float; + mutable calls : int; +} + +let get_time = Extc.time +let htimers = Hashtbl.create 0 + +let new_timer id = + let key = String.concat "." id in + try + let t = Hashtbl.find htimers key in + t.start <- get_time() :: t.start; + t.calls <- t.calls + 1; + t + with Not_found -> + let t = { id = id; start = [get_time()]; total = 0.; calls = 1; } in + Hashtbl.add htimers key t; + t + +let curtime = ref [] + +let close t = + let start = (match t.start with + | [] -> assert false + | s :: l -> t.start <- l; s + ) in + let now = get_time() in + let dt = now -. start in + t.total <- t.total +. dt; + let rec loop() = + match !curtime with + | [] -> failwith ("Timer " ^ (String.concat "." t.id) ^ " closed while not active") + | tt :: l -> curtime := l; if t != tt then loop() + in + loop(); + (* because of rounding errors while adding small times, we need to make sure that we don't have start > now *) + List.iter (fun ct -> ct.start <- List.map (fun t -> let s = t +. dt in if s > now then now else s) ct.start) !curtime + +let timer id = + let t = new_timer id in + curtime := t :: !curtime; + (function() -> close t) + +let rec close_times() = + match !curtime with + | [] -> () + | t :: _ -> close t; close_times() + +(* Printing *) + +type timer_node = { + name : string; + path : string; + parent : timer_node; + info : string; + mutable time : float; + mutable num_calls : int; + mutable children : timer_node list; +} + +let build_times_tree () = + let nodes = Hashtbl.create 0 in + let rec root = { + name = ""; + path = ""; + parent = root; + info = ""; + time = 0.; + num_calls = 0; + children = []; + } in + Hashtbl.iter (fun _ timer -> + let rec loop parent sl = match sl with + | [] -> assert false + | s :: sl -> + let path = (match parent.path with "" -> "" | _ -> parent.path ^ ".") ^ s in + let node = try + let node = Hashtbl.find nodes path in + node.num_calls <- node.num_calls + timer.calls; + node.time <- node.time +. timer.total; + node + with Not_found -> + let name,info = try + let i = String.rindex s '.' in + String.sub s (i + 1) (String.length s - i - 1),String.sub s 0 i + with Not_found -> + s,"" + in + let node = { + name = name; + path = path; + parent = parent; + info = info; + time = timer.total; + num_calls = timer.calls; + children = []; + } in + Hashtbl.add nodes path node; + node + in + begin match sl with + | [] -> () + | _ -> + let child = loop node sl in + if not (List.memq child node.children) then + node.children <- child :: node.children; + end; + node + in + let node = loop root timer.id in + if not (List.memq node root.children) then + root.children <- node :: root.children + ) htimers; + let max_name = ref 0 in + let max_calls = ref 0 in + let rec loop depth node = + let l = (String.length node.name) + 2 * depth in + List.iter (fun child -> + if depth = 0 then begin + node.num_calls <- node.num_calls + child.num_calls; + node.time <- node.time +. child.time; + end; + loop (depth + 1) child; + ) node.children; + node.children <- List.sort (fun node1 node2 -> compare node2.time node1.time) node.children; + if node.num_calls > !max_calls then max_calls := node.num_calls; + if node.time > 0.0009 && l > !max_name then max_name := l; + in + loop 0 root; + !max_name,!max_calls,root + +let report_times print = + let max_name,max_calls,root = build_times_tree () in + let max_calls = String.length (string_of_int max_calls) in + print (Printf.sprintf "%-*s | %7s | %% | p%% | %*s | info" max_name "name" "time(s)" max_calls "#"); + let sep = String.make (max_name + max_calls + 27) '-' in + print sep; + let print_time name node = + if node.time > 0.0009 then + print (Printf.sprintf "%-*s | %7.3f | %3.0f | %3.0f | %*i | %s" max_name name node.time (node.time *. 100. /. root.time) (node.time *. 100. /. node.parent.time) max_calls node.num_calls node.info) + in + let rec loop depth node = + let name = (String.make (depth * 2) ' ') ^ node.name in + print_time name node; + List.iter (loop (depth + 1)) node.children + in + List.iter (loop 0) root.children; + print sep; + print_time "total" root \ No newline at end of file diff --git a/src/core/type.ml b/src/core/type.ml index f5bd718fcbb..81589cfc9a0 100644 --- a/src/core/type.ml +++ b/src/core/type.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -20,8 +20,6 @@ open Ast open Globals -type path = string list * string - type field_kind = | Var of var_kind | Method of method_kind @@ -53,7 +51,6 @@ type module_check_policy = | NoCheckDependencies | NoCheckShadowing - type t = | TMono of t option ref | TEnum of tenum * tparams @@ -87,18 +84,35 @@ and tconstant = and tvar_extra = (type_params * texpr option) option +and tvar_origin = + | TVOLocalVariable + | TVOArgument + | TVOForVariable + | TVOPatternVariable + | TVOCatchVariable + | TVOLocalFunction + +and tvar_kind = + | VUser of tvar_origin + | VGenerated + | VInlined + | VInlinedConstructorVariable + | VExtractorVariable + and tvar = { mutable v_id : int; mutable v_name : string; mutable v_type : t; + mutable v_kind : tvar_kind; mutable v_capture : bool; + mutable v_final : bool; mutable v_extra : tvar_extra; mutable v_meta : metadata; v_pos : pos; } and tfunc = { - tf_args : (tvar * tconstant option) list; + tf_args : (tvar * texpr option) list; tf_type : t; tf_expr : texpr; } @@ -165,7 +179,6 @@ and texpr = { and tclass_field = { mutable cf_name : string; mutable cf_type : t; - mutable cf_public : bool; cf_pos : pos; cf_name_pos : pos; mutable cf_doc : Ast.documentation; @@ -175,6 +188,7 @@ and tclass_field = { mutable cf_expr : texpr option; mutable cf_expr_unoptimized : tfunc option; mutable cf_overloads : tclass_field list; + mutable cf_flags : int; } and tclass_kind = @@ -198,6 +212,7 @@ and tinfos = { mt_doc : Ast.documentation; mutable mt_meta : metadata; mt_params : type_params; + mutable mt_using : (tclass * pos) list; } and tclass = { @@ -209,9 +224,11 @@ and tclass = { mutable cl_doc : Ast.documentation; mutable cl_meta : metadata; mutable cl_params : type_params; + mutable cl_using : (tclass * pos) list; (* do not insert any fields above *) mutable cl_kind : tclass_kind; mutable cl_extern : bool; + mutable cl_final : bool; mutable cl_interface : bool; mutable cl_super : (tclass * tparams) option; mutable cl_implements : (tclass * tparams) list; @@ -236,12 +253,12 @@ and tclass = { and tenum_field = { ef_name : string; - ef_type : t; + mutable ef_type : t; ef_pos : pos; ef_name_pos : pos; ef_doc : Ast.documentation; ef_index : int; - ef_params : type_params; + mutable ef_params : type_params; mutable ef_meta : metadata; } @@ -254,6 +271,7 @@ and tenum = { e_doc : Ast.documentation; mutable e_meta : metadata; mutable e_params : type_params; + mutable e_using : (tclass * pos) list; (* do not insert any fields above *) e_type : tdef; mutable e_extern : bool; @@ -270,6 +288,7 @@ and tdef = { t_doc : Ast.documentation; mutable t_meta : metadata; mutable t_params : type_params; + mutable t_using : (tclass * pos) list; (* do not insert any fields above *) mutable t_type : t; } @@ -283,6 +302,7 @@ and tabstract = { a_doc : Ast.documentation; mutable a_meta : metadata; mutable a_params : type_params; + mutable a_using : (tclass * pos) list; (* do not insert any fields above *) mutable a_ops : (Ast.binop * tclass_field) list; mutable a_unops : (Ast.unop * unop_flag * tclass_field) list; @@ -293,7 +313,8 @@ and tabstract = { mutable a_to : t list; mutable a_to_field : (t * tclass_field) list; mutable a_array : tclass_field list; - mutable a_resolve : tclass_field option; + mutable a_read : tclass_field option; + mutable a_write : tclass_field option; } and module_type = @@ -309,9 +330,15 @@ and module_def = { m_extra : module_def_extra; } +and module_def_display = { + mutable m_inline_calls : (pos * pos) list; (* calls whatever is at pos1 from pos2 *) + mutable m_type_hints : (pos * t) list; +} + and module_def_extra = { m_file : string; m_sign : string; + m_display : module_def_display; mutable m_check_policy : module_check_policy list; mutable m_time : float; mutable m_dirty : module_def option; @@ -321,7 +348,6 @@ and module_def_extra = { mutable m_processed : int; mutable m_kind : module_kind; mutable m_binded_res : (string, string) PMap.t; - mutable m_macro_calls : string list; mutable m_if_feature : (string *(tclass * tclass_field * bool)) list; mutable m_features : (string,bool) Hashtbl.t; } @@ -338,11 +364,69 @@ and build_state = | Building of tclass list | BuildMacro of (unit -> unit) list ref +type basic_types = { + mutable tvoid : t; + mutable tint : t; + mutable tfloat : t; + mutable tbool : t; + mutable tnull : t -> t; + mutable tstring : t; + mutable tarray : t -> t; +} + +type class_field_scope = + | CFSStatic + | CFSMember + | CFSConstructor + +type flag_tclass_field = + | CfPublic + | CfExtern (* This is only set if the field itself is extern, not just the class. *) + | CfFinal + | CfOverridden + | CfModifiesThis (* This is set for methods which reassign `this`. E.g. `this = value` *) + +(* Flags *) + +let has_flag flags flag = + flags land (1 lsl flag) > 0 + +let set_flag flags flag = + flags lor (1 lsl flag) + +let unset_flag flags flag = + flags land (lnot (1 lsl flag)) + +let int_of_class_field_flag (flag : flag_tclass_field) = + Obj.magic flag + +let add_class_field_flag cf (flag : flag_tclass_field) = + cf.cf_flags <- set_flag cf.cf_flags (int_of_class_field_flag flag) + +let remove_class_field_flag cf (flag : flag_tclass_field) = + cf.cf_flags <- unset_flag cf.cf_flags (int_of_class_field_flag flag) + +let has_class_field_flag cf (flag : flag_tclass_field) = + has_flag cf.cf_flags (int_of_class_field_flag flag) + (* ======= General utility ======= *) let alloc_var = let uid = ref 0 in - (fun n t p -> incr uid; { v_name = n; v_type = t; v_id = !uid; v_capture = false; v_extra = None; v_meta = []; v_pos = p }) + (fun kind n t p -> + incr uid; + { + v_kind = kind; + v_name = n; + v_type = t; + v_id = !uid; + v_capture = false; + v_final = (match kind with VUser TVOLocalFunction -> true | _ -> false); + v_extra = None; + v_meta = []; + v_pos = p + } + ) let alloc_mid = let mid = ref 0 in @@ -386,8 +470,10 @@ let mk_class m path pos name_pos = cl_private = false; cl_kind = KNormal; cl_extern = false; + cl_final = false; cl_interface = false; cl_params = []; + cl_using = []; cl_super = None; cl_implements = []; cl_fields = PMap.empty; @@ -408,6 +494,10 @@ let module_extra file sign time kind policy = { m_file = file; m_sign = sign; + m_display = { + m_inline_calls = []; + m_type_hints = []; + }; m_dirty = None; m_added = 0; m_mark = 0; @@ -416,26 +506,25 @@ let module_extra file sign time kind policy = m_deps = PMap.empty; m_kind = kind; m_binded_res = PMap.empty; - m_macro_calls = []; m_if_feature = []; m_features = Hashtbl.create 0; m_check_policy = policy; } -let mk_field name t p name_pos = { +let mk_field name ?(public = true) t p name_pos = { cf_name = name; cf_type = t; cf_pos = p; cf_name_pos = name_pos; cf_doc = None; cf_meta = []; - cf_public = true; cf_kind = Var { v_read = AccNormal; v_write = AccNormal }; cf_expr = None; cf_expr_unoptimized = None; cf_params = []; cf_overloads = []; + cf_flags = if public then set_flag 0 (int_of_class_field_flag CfPublic) else 0; } let null_module = { @@ -461,6 +550,7 @@ let null_abstract = { a_doc = None; a_meta = []; a_params = []; + a_using = []; a_ops = []; a_unops = []; a_impl = None; @@ -470,7 +560,8 @@ let null_abstract = { a_to = []; a_to_field = []; a_array = []; - a_resolve = None; + a_read = None; + a_write = None; } let add_dependency m mdep = @@ -543,7 +634,7 @@ let map loop t = | TDynamic t2 -> if t == t2 then t else TDynamic (loop t2) -let dup t = +let duplicate t = let monos = ref [] in let rec loop t = match t with @@ -559,8 +650,10 @@ let dup t = in loop t +exception ApplyParamsRecursion + (* substitute parameters with other types *) -let apply_params cparams params t = +let apply_params ?stack cparams params t = match cparams with | [] -> t | _ -> @@ -588,7 +681,52 @@ let apply_params cparams params t = | TType (t2,tl) -> (match tl with | [] -> t - | _ -> TType (t2,List.map loop tl)) + | _ -> + let new_applied_params = List.map loop tl in + (match stack with + | None -> () + | Some stack -> + List.iter (fun (subject, old_applied_params) -> + (* + E.g.: + ``` + typedef Rec = { function method():Rec> } + ``` + We need to make sure that we are not applying the result of previous + application to the same place, which would mean the result of current + application would go into `apply_params` again and then again and so on. + + Argument `stack` holds all previous results of `apply_params` to typedefs in current + unification process. + + Imagine we are trying to unify `Rec` with something. + + Once `apply_params Array Int Rec>` is called for the first time the result + will be `Rec< Array >`. Store `Array` into `stack` + + Then the next params application looks like this: + `apply_params Array Array Rec>` + Notice the second argument is actually the result of a previous `apply_params` call. + And the result of the current call is `Rec< Array> >`. + + The third call would be: + `apply_params Array Array> Rec>` + and so on. + + To stop infinite params application we need to check that we are trying to apply params + produced by the previous `apply_params Array _ Rec>` to the same `Rec>` + *) + if + subject == t (* Check the place that we're applying to is the same `Rec>` *) + && old_applied_params == params (* Check that params we're applying are the same params + produced by the previous call to + `apply_params Array _ Rec>` *) + then + raise ApplyParamsRecursion + ) !stack; + stack := (t, new_applied_params) :: !stack; + ); + TType (t2,new_applied_params)) | TAbstract (a,tl) -> (match tl with | [] -> t @@ -640,6 +778,21 @@ let apply_params cparams params t = let monomorphs eparams t = apply_params eparams (List.map (fun _ -> mk_mono()) eparams) t +let apply_params_stack = ref [] + +let try_apply_params_rec cparams params t success = + let old_stack = !apply_params_stack in + try + let result = success (apply_params ~stack:apply_params_stack cparams params t) in + apply_params_stack := old_stack; + result + with + | ApplyParamsRecursion -> + apply_params_stack := old_stack; + | err -> + apply_params_stack := old_stack; + raise err + let rec follow t = match t with | TMono r -> @@ -696,13 +849,13 @@ let rec is_null ?(no_lazy=false) = function (* Determines if we have a Null. Unlike is_null, this returns true even if the wrapped type is nullable itself. *) let rec is_explicit_null = function | TMono r -> - (match !r with None -> false | Some t -> is_null t) + (match !r with None -> false | Some t -> is_explicit_null t) | TAbstract ({ a_path = ([],"Null") },[t]) -> true | TLazy f -> - is_null (lazy_type f) + is_explicit_null (lazy_type f) | TType (t,tl) -> - is_null (apply_params t.t_params tl t.t_type) + is_explicit_null (apply_params t.t_params tl t.t_type) | _ -> false @@ -780,11 +933,16 @@ let extract_field = function | FAnon f | FInstance (_,_,f) | FStatic (_,f) | FClosure (_,f) -> Some f | _ -> None +let is_physical_var_field f = + match f.cf_kind with + | Var { v_read = AccNormal | AccInline | AccNo } | Var { v_write = AccNormal | AccNo } -> true + | Var _ -> Meta.has Meta.IsVar f.cf_meta + | _ -> false + let is_physical_field f = match f.cf_kind with | Method _ -> true - | Var { v_read = AccNormal | AccInline | AccNo } | Var { v_write = AccNormal | AccNo } -> true - | _ -> Meta.has Meta.IsVar f.cf_meta + | _ -> is_physical_var_field f let field_type f = match f.cf_params with @@ -891,6 +1049,12 @@ let rec get_constructor build_type c = let t, c = get_constructor build_type csup in apply_params csup.cl_params cparams t, c +let has_constructor c = + try + ignore(get_constructor (fun cf -> cf.cf_type) c); + true + with Not_found -> false + (* ======= Printing ======= *) let print_context() = ref [] @@ -928,7 +1092,7 @@ let rec s_type ctx t = s_type_path e.e_path ^ s_type_params ctx tl | TInst (c,tl) -> (match c.cl_kind with - | KExpr e -> Ast.s_expr e + | KExpr e -> Ast.Printer.s_expr e | _ -> s_type_path c.cl_path ^ s_type_params ctx tl) | TType (t,tl) -> s_type_path t.t_path ^ s_type_params ctx tl @@ -937,9 +1101,16 @@ let rec s_type ctx t = | TFun ([],t) -> "Void -> " ^ s_fun ctx t false | TFun (l,t) -> - String.concat " -> " (List.map (fun (s,b,t) -> - (if b then "?" else "") ^ (if s = "" then "" else s ^ " : ") ^ s_fun ctx t true - ) l) ^ " -> " ^ s_fun ctx t false + let args = match l with + | [] -> "()" + | ["",b,t] -> Printf.sprintf "%s%s" (if b then "?" else "") (s_fun ctx t true) + | _ -> + let args = String.concat ", " (List.map (fun (s,b,t) -> + (if b then "?" else "") ^ (if s = "" then "" else s ^ " : ") ^ s_fun ctx t true + ) l) in + "(" ^ args ^ ")" + in + Printf.sprintf "%s -> %s" args (s_fun ctx t false) | TAnon a -> begin match !(a.a_status) with @@ -1029,12 +1200,20 @@ let s_expr_kind e = let s_const = function | TInt i -> Int32.to_string i | TFloat s -> s - | TString s -> Printf.sprintf "\"%s\"" (Ast.s_escape s) + | TString s -> Printf.sprintf "\"%s\"" (StringHelper.s_escape s) | TBool b -> if b then "true" else "false" | TNull -> "null" | TThis -> "this" | TSuper -> "super" +let s_field_access s_type fa = match fa with + | FStatic (c,f) -> "static(" ^ s_type_path c.cl_path ^ "." ^ f.cf_name ^ ")" + | FInstance (c,_,f) -> "inst(" ^ s_type_path c.cl_path ^ "." ^ f.cf_name ^ " : " ^ s_type f.cf_type ^ ")" + | FClosure (c,f) -> "closure(" ^ (match c with None -> f.cf_name | Some (c,_) -> s_type_path c.cl_path ^ "." ^ f.cf_name) ^ ")" + | FAnon f -> "anon(" ^ f.cf_name ^ ")" + | FEnum (en,f) -> "enum(" ^ s_type_path en.e_path ^ "." ^ f.ef_name ^ ")" + | FDynamic f -> "dynamic(" ^ f ^ ")" + let rec s_expr s_type e = let sprintf = Printf.sprintf in let slist f l = String.concat "," (List.map f l) in @@ -1054,14 +1233,7 @@ let rec s_expr s_type e = | TEnumParameter (e1,_,i) -> sprintf "%s[%i]" (loop e1) i | TField (e,f) -> - let fstr = (match f with - | FStatic (c,f) -> "static(" ^ s_type_path c.cl_path ^ "." ^ f.cf_name ^ ")" - | FInstance (c,_,f) -> "inst(" ^ s_type_path c.cl_path ^ "." ^ f.cf_name ^ " : " ^ s_type f.cf_type ^ ")" - | FClosure (c,f) -> "closure(" ^ (match c with None -> f.cf_name | Some (c,_) -> s_type_path c.cl_path ^ "." ^ f.cf_name) ^ ")" - | FAnon f -> "anon(" ^ f.cf_name ^ ")" - | FEnum (en,f) -> "enum(" ^ s_type_path en.e_path ^ "." ^ f.ef_name ^ ")" - | FDynamic f -> "dynamic(" ^ f ^ ")" - ) in + let fstr = s_field_access s_type f in sprintf "%s.%s" (loop e) fstr | TTypeExpr m -> sprintf "TypeExpr %s" (s_type_path (t_path m)) @@ -1080,7 +1252,7 @@ let rec s_expr s_type e = | Prefix -> sprintf "(%s %s)" (s_unop op) (loop e) | Postfix -> sprintf "(%s %s)" (loop e) (s_unop op)) | TFunction f -> - let args = slist (fun (v,o) -> sprintf "%s : %s%s" (s_var v) (s_type v.v_type) (match o with None -> "" | Some c -> " = " ^ s_const c)) f.tf_args in + let args = slist (fun (v,o) -> sprintf "%s : %s%s" (s_var v) (s_type v.v_type) (match o with None -> "" | Some c -> " = " ^ loop c)) f.tf_args in sprintf "Function(%s) : %s = %s" args (s_type f.tf_type) (loop f.tf_expr) | TVar (v,eo) -> sprintf "Vars %s" (sprintf "%s : %s%s" (s_var v) (s_type v.v_type) (match eo with None -> "" | Some e -> " = " ^ loop e)) @@ -1111,7 +1283,7 @@ let rec s_expr s_type e = | TCast (e,t) -> sprintf "Cast %s%s" (match t with None -> "" | Some t -> s_type_path (t_path t) ^ ": ") (loop e) | TMeta ((n,el,_),e) -> - sprintf "@%s%s %s" (Meta.to_string n) (match el with [] -> "" | _ -> "(" ^ (String.concat ", " (List.map Ast.s_expr el)) ^ ")") (loop e) + sprintf "@%s%s %s" (Meta.to_string n) (match el with [] -> "" | _ -> "(" ^ (String.concat ", " (List.map Ast.Printer.s_expr el)) ^ ")") (loop e) | TIdent s -> "Ident " ^ s ) in @@ -1143,7 +1315,7 @@ let rec s_expr_pretty print_var_ids tabs top_level s_type e = | Prefix -> sprintf "%s %s" (s_unop op) (loop e) | Postfix -> sprintf "%s %s" (loop e) (s_unop op)) | TFunction f -> - let args = clist (fun (v,o) -> sprintf "%s:%s%s" (local v) (s_type v.v_type) (match o with None -> "" | Some c -> " = " ^ s_const c)) f.tf_args in + let args = clist (fun (v,o) -> sprintf "%s:%s%s" (local v) (s_type v.v_type) (match o with None -> "" | Some c -> " = " ^ loop c)) f.tf_args in sprintf "%s(%s) %s" (if top_level then "" else "function") args (loop f.tf_expr) | TVar (v,eo) -> sprintf "var %s" (sprintf "%s%s" (local v) (match eo with None -> "" | Some e -> " = " ^ loop e)) @@ -1182,7 +1354,7 @@ let rec s_expr_pretty print_var_ids tabs top_level s_type e = | TCast (e,Some mt) -> sprintf "cast (%s,%s)" (loop e) (s_type_path (t_path mt)) | TMeta ((n,el,_),e) -> - sprintf "@%s%s %s" (Meta.to_string n) (match el with [] -> "" | _ -> "(" ^ (String.concat ", " (List.map Ast.s_expr el)) ^ ")") (loop e) + sprintf "@%s%s %s" (Meta.to_string n) (match el with [] -> "" | _ -> "(" ^ (String.concat ", " (List.map Ast.Printer.s_expr el)) ^ ")") (loop e) | TIdent s -> s @@ -1205,12 +1377,12 @@ let rec s_expr_ast print_var_ids tabs s_type e = in let var_id v = if print_var_ids then v.v_id else 0 in let const c t = tag "Const" ~t [s_const c] in - let local v = sprintf "[Local %s(%i):%s]" v.v_name (var_id v) (s_type v.v_type) in + let local v t = sprintf "[Local %s(%i):%s%s]" v.v_name (var_id v) (s_type v.v_type) (match t with None -> "" | Some t -> ":" ^ (s_type t)) in let var v sl = sprintf "[Var %s(%i):%s]%s" v.v_name (var_id v) (s_type v.v_type) (tag_args tabs sl) in let module_type mt = sprintf "[TypeExpr %s:%s]" (s_type_path (t_path mt)) (s_type e.etype) in match e.eexpr with | TConst c -> const c (Some e.etype) - | TLocal v -> local v + | TLocal v -> local v (Some e.etype) | TArray (e1,e2) -> tag "Array" [loop e1; loop e2] | TBinop (op,e1,e2) -> tag "Binop" [loop e1; s_binop op; loop e2] | TUnop (op,flag,e1) -> tag "Unop" [s_unop op; if flag = Postfix then "Postfix" else "Prefix"; loop e1] @@ -1218,10 +1390,10 @@ let rec s_expr_ast print_var_ids tabs s_type e = | TEnumIndex e1 -> tag "EnumIndex" [loop e1] | TField (e1,fa) -> let sfa = match fa with - | FInstance(c,tl,cf) -> tag "FInstance" ~extra_tabs:"\t" [s_type (TInst(c,tl)); cf.cf_name] - | FStatic(c,cf) -> tag "FStatic" ~extra_tabs:"\t" [s_type_path c.cl_path; cf.cf_name] - | FClosure(co,cf) -> tag "FClosure" ~extra_tabs:"\t" [(match co with None -> "None" | Some (c,tl) -> s_type (TInst(c,tl))); cf.cf_name] - | FAnon cf -> tag "FAnon" ~extra_tabs:"\t" [cf.cf_name] + | FInstance(c,tl,cf) -> tag "FInstance" ~extra_tabs:"\t" [s_type (TInst(c,tl)); Printf.sprintf "%s:%s" cf.cf_name (s_type cf.cf_type)] + | FStatic(c,cf) -> tag "FStatic" ~extra_tabs:"\t" [s_type_path c.cl_path; Printf.sprintf "%s:%s" cf.cf_name (s_type cf.cf_type)] + | FClosure(co,cf) -> tag "FClosure" ~extra_tabs:"\t" [(match co with None -> "None" | Some (c,tl) -> s_type (TInst(c,tl))); Printf.sprintf "%s:%s" cf.cf_name (s_type cf.cf_type)] + | FAnon cf -> tag "FAnon" ~extra_tabs:"\t" [Printf.sprintf "%s:%s" cf.cf_name (s_type cf.cf_type)] | FDynamic s -> tag "FDynamic" ~extra_tabs:"\t" [s] | FEnum(en,ef) -> tag "FEnum" ~extra_tabs:"\t" [s_type_path en.e_path; ef.ef_name] in @@ -1234,7 +1406,7 @@ let rec s_expr_ast print_var_ids tabs s_type e = | TNew (c,tl,el) -> tag "New" ((s_type (TInst(c,tl))) :: (List.map loop el)) | TFunction f -> let arg (v,cto) = - tag "Arg" ~t:(Some v.v_type) ~extra_tabs:"\t" (match cto with None -> [local v] | Some ct -> [local v;const ct None]) + tag "Arg" ~t:(Some v.v_type) ~extra_tabs:"\t" (match cto with None -> [local v None] | Some ct -> [local v None;loop ct]) in tag "Function" ((List.map arg f.tf_args) @ [loop f.tf_expr]) | TVar (v,eo) -> var v (match eo with None -> [] | Some e -> [loop e]) @@ -1249,10 +1421,10 @@ let rec s_expr_ast print_var_ids tabs s_type e = | TReturn (Some e1) -> tag "Return" [loop e1] | TWhile (e1,e2,NormalWhile) -> tag "While" [loop e1; loop e2] | TWhile (e1,e2,DoWhile) -> tag "Do" [loop e1; loop e2] - | TFor (v,e1,e2) -> tag "For" [local v; loop e1; loop e2] + | TFor (v,e1,e2) -> tag "For" [local v None; loop e1; loop e2] | TTry (e1,catches) -> let sl = List.map (fun (v,e) -> - sprintf "Catch %s%s" (local v) (tag_args (tabs ^ "\t") [loop ~extra_tabs:"\t" e]); + sprintf "Catch %s%s" (local v None) (tag_args (tabs ^ "\t") [loop ~extra_tabs:"\t" e]); ) catches in tag "Try" ((loop e1) :: sl) | TSwitch (e1,cases,eo) -> @@ -1268,7 +1440,7 @@ let rec s_expr_ast print_var_ids tabs s_type e = let s = Meta.to_string m in let s = match el with | [] -> s - | _ -> sprintf "%s(%s)" s (String.concat ", " (List.map Ast.s_expr el)) + | _ -> sprintf "%s(%s)" s (String.concat ", " (List.map Ast.Printer.s_expr el)) in tag "Meta" [s; loop e1] | TIdent s -> @@ -1327,7 +1499,7 @@ module Printer = struct let s_doc = s_opt (fun s -> s) let s_metadata_entry (s,el,_) = - Printf.sprintf "@%s%s" (Meta.to_string s) (match el with [] -> "" | el -> "(" ^ (String.concat ", " (List.map Ast.s_expr el)) ^ ")") + Printf.sprintf "@%s%s" (Meta.to_string s) (match el with [] -> "" | el -> "(" ^ (String.concat ", " (List.map Ast.Printer.s_expr el)) ^ ")") let s_metadata metadata = s_list " " s_metadata_entry metadata @@ -1348,7 +1520,6 @@ module Printer = struct "cf_name",cf.cf_name; "cf_doc",s_doc cf.cf_doc; "cf_type",s_type_kind (follow cf.cf_type); - "cf_public",string_of_bool cf.cf_public; "cf_pos",s_pos cf.cf_pos; "cf_name_pos",s_pos cf.cf_name_pos; "cf_meta",s_metadata cf.cf_meta; @@ -1369,10 +1540,10 @@ module Printer = struct "cl_params",s_type_params c.cl_params; "cl_kind",s_class_kind c.cl_kind; "cl_extern",string_of_bool c.cl_extern; + "cl_final",string_of_bool c.cl_final; "cl_interface",string_of_bool c.cl_interface; "cl_super",s_opt (fun (c,tl) -> s_type (TInst(c,tl))) c.cl_super; "cl_implements",s_list ", " (fun (c,tl) -> s_type (TInst(c,tl))) c.cl_implements; - "cl_dynamic",s_opt s_type c.cl_dynamic; "cl_array_access",s_opt s_type c.cl_array_access; "cl_overrides",s_list "," (fun cf -> cf.cf_name) c.cl_overrides; "cl_init",s_opt (s_expr_ast true "" s_type) c.cl_init; @@ -1441,7 +1612,8 @@ module Printer = struct "a_from_field",s_list ", " (fun (t,cf) -> Printf.sprintf "%s: %s" (s_type_kind t) cf.cf_name) a.a_from_field; "a_to_field",s_list ", " (fun (t,cf) -> Printf.sprintf "%s: %s" (s_type_kind t) cf.cf_name) a.a_to_field; "a_array",s_list ", " (fun cf -> cf.cf_name) a.a_array; - "a_resolve",s_opt (fun cf -> cf.cf_name) a.a_resolve; + "a_read",s_opt (fun cf -> cf.cf_name) a.a_read; + "a_write",s_opt (fun cf -> cf.cf_name) a.a_write; ] let s_tvar_extra (tl,eo) = @@ -1476,7 +1648,6 @@ module Printer = struct "m_processed",string_of_int me.m_processed; "m_kind",s_module_kind me.m_kind; "m_binded_res",""; (* TODO *) - "m_macro_calls",String.concat ", " me.m_macro_calls; "m_if_feature",""; (* TODO *) "m_features",""; (* TODO *) ] @@ -1502,6 +1673,7 @@ module Printer = struct | HPrivate -> "HPrivate" | HExtends tp -> "HExtends " ^ (s_type_path (fst tp)) | HImplements tp -> "HImplements " ^ (s_type_path (fst tp)) + | HFinal -> "HFinal" let s_placed f (x,p) = s_pair (f x) (s_pos p) @@ -1512,7 +1684,7 @@ module Printer = struct "cff_doc",s_opt (fun s -> s) cff.cff_doc; "cff_pos",s_pos cff.cff_pos; "cff_meta",s_metadata cff.cff_meta; - "cff_access",s_list ", " Ast.s_access cff.cff_access; + "cff_access",s_list ", " Ast.s_placed_access cff.cff_access; ] end @@ -1552,47 +1724,94 @@ let rec link e a b = true end +let would_produce_recursive_anon field_acceptor field_donor = + try + (match !(field_acceptor.a_status) with + | Opened -> + PMap.iter (fun n field -> + match follow field.cf_type with + | TAnon a when field_acceptor == a -> raise Exit + | _ -> () + ) field_donor.a_fields; + | _ -> ()); + false + with Exit -> true + let link_dynamic a b = match follow a,follow b with | TMono r,TDynamic _ -> r := Some b | TDynamic _,TMono r -> r := Some a | _ -> () -let rec fast_eq a b = +let fast_eq_check type_param_check a b = if a == b then true else match a , b with | TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 -> - List.for_all2 (fun (_,_,t1) (_,_,t2) -> fast_eq t1 t2) l1 l2 && fast_eq r1 r2 + List.for_all2 (fun (_,_,t1) (_,_,t2) -> type_param_check t1 t2) l1 l2 && type_param_check r1 r2 | TType (t1,l1), TType (t2,l2) -> - t1 == t2 && List.for_all2 fast_eq l1 l2 + t1 == t2 && List.for_all2 type_param_check l1 l2 | TEnum (e1,l1), TEnum (e2,l2) -> - e1 == e2 && List.for_all2 fast_eq l1 l2 + e1 == e2 && List.for_all2 type_param_check l1 l2 | TInst (c1,l1), TInst (c2,l2) -> - c1 == c2 && List.for_all2 fast_eq l1 l2 + c1 == c2 && List.for_all2 type_param_check l1 l2 | TAbstract (a1,l1), TAbstract (a2,l2) -> - a1 == a2 && List.for_all2 fast_eq l1 l2 + a1 == a2 && List.for_all2 type_param_check l1 l2 | _ , _ -> false +let rec fast_eq a b = fast_eq_check fast_eq a b + let rec fast_eq_mono ml a b = - if a == b then + if fast_eq_check (fast_eq_mono ml) a b then true else match a , b with - | TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 -> - List.for_all2 (fun (_,_,t1) (_,_,t2) -> fast_eq_mono ml t1 t2) l1 l2 && fast_eq_mono ml r1 r2 - | TType (t1,l1), TType (t2,l2) -> - t1 == t2 && List.for_all2 (fast_eq_mono ml) l1 l2 - | TEnum (e1,l1), TEnum (e2,l2) -> - e1 == e2 && List.for_all2 (fast_eq_mono ml) l1 l2 - | TInst (c1,l1), TInst (c2,l2) -> - c1 == c2 && List.for_all2 (fast_eq_mono ml) l1 l2 - | TAbstract (a1,l1), TAbstract (a2,l2) -> - a1 == a2 && List.for_all2 (fast_eq_mono ml) l1 l2 | TMono _, _ -> List.memq a ml | _ , _ -> false +let rec fast_eq_anon ?(mono_equals_dynamic=false) a b = + if fast_eq_check (fast_eq_anon ~mono_equals_dynamic) a b then + true + else match a , b with + (* + `mono_equals_dynamic` is here because of https://github.com/HaxeFoundation/haxe/issues/8588#issuecomment-520138371 + Generally unbound monomorphs should not be considered equal to anything, + because it's unknown, which types they would be bound to. + *) + | t, TMono { contents = None } when t == t_dynamic -> mono_equals_dynamic + | TMono { contents = None }, t when t == t_dynamic -> mono_equals_dynamic + | TMono { contents = Some t1 }, TMono { contents = Some t2 } -> + fast_eq_anon t1 t2 + | TAnon a1, TAnon a2 -> + let fields_eq() = + let rec loop fields1 fields2 = + match fields1, fields2 with + | [], [] -> true + | _, [] | [], _ -> false + | f1 :: rest1, f2 :: rest2 -> + f1.cf_name = f2.cf_name + && (try fast_eq_anon f1.cf_type f2.cf_type with Not_found -> false) + && loop rest1 rest2 + in + let fields1 = PMap.fold (fun field fields -> field :: fields) a1.a_fields [] + and fields2 = PMap.fold (fun field fields -> field :: fields) a2.a_fields [] + and sort_compare f1 f2 = compare f1.cf_name f2.cf_name in + loop (List.sort sort_compare fields1) (List.sort sort_compare fields2) + in + (match !(a2.a_status), !(a1.a_status) with + | Statics c, Statics c2 -> c == c2 + | EnumStatics e, EnumStatics e2 -> e == e2 + | AbstractStatics a, AbstractStatics a2 -> a == a2 + | Extend tl1, Extend tl2 -> fields_eq() && List.for_all2 fast_eq_anon tl1 tl2 + | Closed, Closed -> fields_eq() + | Opened, Opened -> fields_eq() + | Const, Const -> fields_eq() + | _ -> false + ) + | _ , _ -> + false + (* perform unification with subtyping. the first type is always the most down in the class hierarchy it's also the one that is pointed by the position. @@ -1608,9 +1827,12 @@ type unify_error = | Invalid_visibility of string | Not_matching_optional of string | Cant_force_optional - | Invariant_parameter of t * t + | Invariant_parameter of int | Constraint_failure of string | Missing_overload of tclass_field * t + | FinalInvariance (* nice band name *) + | Invalid_function_argument of int (* index *) * int (* total *) + | Invalid_return_type | Unify_custom of string exception Unify_error of unify_error list @@ -1661,37 +1883,57 @@ let unify_kind k1 k2 = | MethDynamic, MethNormal -> true | _ -> false -let eq_stack = ref [] +type 'a rec_stack = { + mutable rec_stack : 'a list; +} + +let new_rec_stack() = { rec_stack = [] } +let rec_stack_exists f s = List.exists f s.rec_stack +let rec_stack_memq v s = List.memq v s.rec_stack +let rec_stack_loop stack value f arg = + stack.rec_stack <- value :: stack.rec_stack; + try + let r = f arg in + stack.rec_stack <- List.tl stack.rec_stack; + r + with e -> + stack.rec_stack <- List.tl stack.rec_stack; + raise e + +let eq_stack = new_rec_stack() let rec_stack stack value fcheck frun ferror = - if not (List.exists fcheck !stack) then begin + if not (rec_stack_exists fcheck stack) then begin try - stack := value :: !stack; + stack.rec_stack <- value :: stack.rec_stack; let v = frun() in - stack := List.tl !stack; + stack.rec_stack <- List.tl stack.rec_stack; v with Unify_error l -> - stack := List.tl !stack; + stack.rec_stack <- List.tl stack.rec_stack; ferror l | e -> - stack := List.tl !stack; + stack.rec_stack <- List.tl stack.rec_stack; raise e end +let rec_stack_default stack value fcheck frun def = + if not (rec_stack_exists fcheck stack) then rec_stack_loop stack value frun () else def + let rec_stack_bool stack value fcheck frun = - if (List.exists fcheck !stack) then false else begin + if (rec_stack_exists fcheck stack) then false else begin try - stack := value :: !stack; + stack.rec_stack <- value :: stack.rec_stack; frun(); - stack := List.tl !stack; + stack.rec_stack <- List.tl stack.rec_stack; true with Unify_error l -> - stack := List.tl !stack; + stack.rec_stack <- List.tl stack.rec_stack; false | e -> - stack := List.tl !stack; + stack.rec_stack <- List.tl stack.rec_stack; raise e end @@ -1721,8 +1963,14 @@ let rec type_eq param a b = (match !t with | None -> if param = EqCoreType || not (link t b a) then error [cannot_unify a b] | Some t -> type_eq param a t) + | TAbstract ({a_path=[],"Null"},[t1]),TAbstract ({a_path=[],"Null"},[t2]) -> + type_eq param t1 t2 + | TAbstract ({a_path=[],"Null"},[t]),_ when param <> EqDoNotFollowNull -> + type_eq param t b + | _,TAbstract ({a_path=[],"Null"},[t]) when param <> EqDoNotFollowNull -> + type_eq param a t | TType (t1,tl1), TType (t2,tl2) when (t1 == t2 || (param = EqCoreType && t1.t_path = t2.t_path)) && List.length tl1 = List.length tl2 -> - List.iter2 (type_eq param) tl1 tl2 + type_eq_params param a b tl1 tl2 | TType (t,tl) , _ when can_follow a -> type_eq param (apply_params t.t_params tl t.t_type) b | _ , TType (t,tl) when can_follow b -> @@ -1732,41 +1980,45 @@ let rec type_eq param a b = (fun l -> error (cannot_unify a b :: l)) | TEnum (e1,tl1) , TEnum (e2,tl2) -> if e1 != e2 && not (param = EqCoreType && e1.e_path = e2.e_path) then error [cannot_unify a b]; - List.iter2 (type_eq param) tl1 tl2 + type_eq_params param a b tl1 tl2 | TInst (c1,tl1) , TInst (c2,tl2) -> if c1 != c2 && not (param = EqCoreType && c1.cl_path = c2.cl_path) && (match c1.cl_kind, c2.cl_kind with KExpr _, KExpr _ -> false | _ -> true) then error [cannot_unify a b]; - List.iter2 (type_eq param) tl1 tl2 + type_eq_params param a b tl1 tl2 | TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 -> + let i = ref 0 in (try type_eq param r1 r2; List.iter2 (fun (n,o1,t1) (_,o2,t2) -> + incr i; if o1 <> o2 then error [Not_matching_optional n]; type_eq param t1 t2 ) l1 l2 with - Unify_error l -> error (cannot_unify a b :: l)) + Unify_error l -> + let msg = if !i = 0 then Invalid_return_type else Invalid_function_argument(!i,List.length l1) in + error (cannot_unify a b :: msg :: l) + ) | TDynamic a , TDynamic b -> type_eq param a b - | TAbstract ({a_path=[],"Null"},[t1]),TAbstract ({a_path=[],"Null"},[t2]) -> - type_eq param t1 t2 - | TAbstract ({a_path=[],"Null"},[t]),_ when param <> EqDoNotFollowNull -> - type_eq param t b - | _,TAbstract ({a_path=[],"Null"},[t]) when param <> EqDoNotFollowNull -> - type_eq param a t | TAbstract (a1,tl1) , TAbstract (a2,tl2) -> if a1 != a2 && not (param = EqCoreType && a1.a_path = a2.a_path) then error [cannot_unify a b]; - List.iter2 (type_eq param) tl1 tl2 + type_eq_params param a b tl1 tl2 | TAnon a1, TAnon a2 -> (try + (match !(a2.a_status) with + | Statics c -> (match !(a1.a_status) with Statics c2 when c == c2 -> () | _ -> error []) + | EnumStatics e -> (match !(a1.a_status) with EnumStatics e2 when e == e2 -> () | _ -> error []) + | AbstractStatics a -> (match !(a1.a_status) with AbstractStatics a2 when a == a2 -> () | _ -> error []) + | _ -> () + ); + if would_produce_recursive_anon a1 a2 || would_produce_recursive_anon a2 a1 then error [cannot_unify a b]; PMap.iter (fun n f1 -> try let f2 = PMap.find n a2.a_fields in if f1.cf_kind <> f2.cf_kind && (param = EqStrict || param = EqCoreType || not (unify_kind f1.cf_kind f2.cf_kind)) then error [invalid_kind n f1.cf_kind f2.cf_kind]; let a = f1.cf_type and b = f2.cf_type in - rec_stack eq_stack (a,b) - (fun (a2,b2) -> fast_eq a a2 && fast_eq b b2) - (fun() -> type_eq param a b) - (fun l -> error (invalid_field n :: l)) + (try type_eq param a b with Unify_error l -> error (invalid_field n :: l)); + if (has_class_field_flag f1 CfPublic) != (has_class_field_flag f2 CfPublic) then error [invalid_visibility n]; with Not_found -> if is_closed a2 then error [has_no_field b n]; @@ -1790,6 +2042,17 @@ let rec type_eq param a b = else error [cannot_unify a b] +and type_eq_params param a b tl1 tl2 = + let i = ref 0 in + List.iter2 (fun t1 t2 -> + incr i; + try + type_eq param t1 t2 + with Unify_error l -> + let err = cannot_unify a b in + error (err :: (Invariant_parameter !i) :: l) + ) tl1 tl2 + let type_iseq a b = try type_eq EqStrict a b; @@ -1804,19 +2067,19 @@ let type_iseq_strict a b = with Unify_error _ -> false -let unify_stack = ref [] -let abstract_cast_stack = ref [] -let unify_new_monos = ref [] +let unify_stack = new_rec_stack() +let abstract_cast_stack = new_rec_stack() +let unify_new_monos = new_rec_stack() let print_stacks() = let ctx = print_context() in let st = s_type ctx in print_endline "unify_stack"; - List.iter (fun (a,b) -> Printf.printf "\t%s , %s\n" (st a) (st b)) !unify_stack; + List.iter (fun (a,b) -> Printf.printf "\t%s , %s\n" (st a) (st b)) unify_stack.rec_stack; print_endline "monos"; - List.iter (fun m -> print_endline ("\t" ^ st m)) !unify_new_monos; + List.iter (fun m -> print_endline ("\t" ^ st m)) unify_new_monos.rec_stack; print_endline "abstract_cast_stack"; - List.iter (fun (a,b) -> Printf.printf "\t%s , %s\n" (st a) (st b)) !abstract_cast_stack + List.iter (fun (a,b) -> Printf.printf "\t%s , %s\n" (st a) (st b)) abstract_cast_stack.rec_stack let rec unify a b = if a == b then @@ -1835,12 +2098,12 @@ let rec unify a b = | TType (t,tl) , _ -> rec_stack unify_stack (a,b) (fun(a2,b2) -> fast_eq a a2 && fast_eq b b2) - (fun() -> unify (apply_params t.t_params tl t.t_type) b) + (fun() -> try_apply_params_rec t.t_params tl t.t_type (fun a -> unify a b)) (fun l -> error (cannot_unify a b :: l)) | _ , TType (t,tl) -> rec_stack unify_stack (a,b) (fun(a2,b2) -> fast_eq a a2 && fast_eq b b2) - (fun() -> unify a (apply_params t.t_params tl t.t_type)) + (fun() -> try_apply_params_rec t.t_params tl t.t_type (unify a)) (fun l -> error (cannot_unify a b :: l)) | TEnum (ea,tl1) , TEnum (eb,tl2) -> if ea != eb then error [cannot_unify a b]; @@ -1892,7 +2155,7 @@ let rec unify a b = | TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 -> let i = ref 0 in (try - (match r2 with + (match follow r2 with | TAbstract ({a_path=[],"Void"},_) -> incr i | _ -> unify r1 r2; incr i); List.iter2 (fun (_,o1,t1) (_,o2,t2) -> @@ -1902,8 +2165,8 @@ let rec unify a b = ) l2 l1 (* contravariance *) with Unify_error l -> - let msg = if !i = 0 then "Cannot unify return types" else "Cannot unify argument " ^ (string_of_int !i) in - error (cannot_unify a b :: Unify_custom msg :: l)) + let msg = if !i = 0 then Invalid_return_type else Invalid_function_argument(!i,List.length l1) in + error (cannot_unify a b :: msg :: l)) | TInst (c,tl) , TAnon an -> if PMap.is_empty an.a_fields then (match c.cl_kind with | KTypeParameter pl -> @@ -1928,31 +2191,31 @@ let rec unify a b = let _, ft, f1 = (try raw_class_field make_type c tl n with Not_found -> error [has_no_field a n]) in let ft = apply_params c.cl_params tl ft in if not (unify_kind f1.cf_kind f2.cf_kind) then error [invalid_kind n f1.cf_kind f2.cf_kind]; - if f2.cf_public && not f1.cf_public then error [invalid_visibility n]; + if (has_class_field_flag f2 CfPublic) && not (has_class_field_flag f1 CfPublic) then error [invalid_visibility n]; (match f2.cf_kind with | Var { v_read = AccNo } | Var { v_read = AccNever } -> (* we will do a recursive unification, so let's check for possible recursion *) - let old_monos = !unify_new_monos in - unify_new_monos := !monos @ !unify_new_monos; + let old_monos = unify_new_monos.rec_stack in + unify_new_monos.rec_stack <- !monos @ unify_new_monos.rec_stack; rec_stack unify_stack (ft,f2.cf_type) - (fun (a2,b2) -> fast_eq b2 f2.cf_type && fast_eq_mono !unify_new_monos ft a2) - (fun() -> try unify_with_access ft f2 with e -> unify_new_monos := old_monos; raise e) + (fun (a2,b2) -> fast_eq b2 f2.cf_type && fast_eq_mono unify_new_monos.rec_stack ft a2) + (fun() -> try unify_with_access f1 ft f2 with e -> unify_new_monos.rec_stack <- old_monos; raise e) (fun l -> error (invalid_field n :: l)); - unify_new_monos := old_monos; + unify_new_monos.rec_stack <- old_monos; | Method MethNormal | Method MethInline | Var { v_write = AccNo } | Var { v_write = AccNever } -> (* same as before, but unification is reversed (read-only var) *) - let old_monos = !unify_new_monos in - unify_new_monos := !monos @ !unify_new_monos; + let old_monos = unify_new_monos.rec_stack in + unify_new_monos.rec_stack <- !monos @ unify_new_monos.rec_stack; rec_stack unify_stack (f2.cf_type,ft) - (fun(a2,b2) -> fast_eq_mono !unify_new_monos b2 ft && fast_eq f2.cf_type a2) - (fun() -> try unify_with_access ft f2 with e -> unify_new_monos := old_monos; raise e) + (fun(a2,b2) -> fast_eq_mono unify_new_monos.rec_stack b2 ft && fast_eq f2.cf_type a2) + (fun() -> try unify_with_access f1 ft f2 with e -> unify_new_monos.rec_stack <- old_monos; raise e) (fun l -> error (invalid_field n :: l)); - unify_new_monos := old_monos; + unify_new_monos.rec_stack <- old_monos; | _ -> (* will use fast_eq, which have its own stack *) try - unify_with_access ft f2 + unify_with_access f1 ft f2 with Unify_error l -> error (invalid_field n :: l)); @@ -1962,10 +2225,25 @@ let rec unify a b = then error [Missing_overload (f1, f2o.cf_type)] ) f2.cf_overloads; (* we mark the field as :?used because it might be used through the structure *) - if not (Meta.has Meta.MaybeUsed f1.cf_meta) then f1.cf_meta <- (Meta.MaybeUsed,[],f1.cf_pos) :: f1.cf_meta; + if not (Meta.has Meta.MaybeUsed f1.cf_meta) then begin + f1.cf_meta <- (Meta.MaybeUsed,[],f1.cf_pos) :: f1.cf_meta; + match f2.cf_kind with + | Var vk -> + let check name = + try + let _,_,cf = raw_class_field make_type c tl name in + if not (Meta.has Meta.MaybeUsed cf.cf_meta) then + cf.cf_meta <- (Meta.MaybeUsed,[],f1.cf_pos) :: cf.cf_meta + with Not_found -> + () + in + (match vk.v_read with AccCall -> check ("get_" ^ f1.cf_name) | _ -> ()); + (match vk.v_write with AccCall -> check ("set_" ^ f1.cf_name) | _ -> ()); + | _ -> () + end; (match f1.cf_kind with | Method MethInline -> - if (c.cl_extern || Meta.has Meta.Extern f1.cf_meta) && not (Meta.has Meta.Runtime f1.cf_meta) then error [Has_no_runtime_field (a,n)]; + if (c.cl_extern || has_class_field_flag f1 CfExtern) && not (Meta.has Meta.Runtime f1.cf_meta) then error [Has_no_runtime_field (a,n)]; | _ -> ()); ) an.a_fields; (match !(an.a_status) with @@ -1998,7 +2276,7 @@ let rec unify a b = if not (List.exists (fun t -> match follow t with TAbstract({a_path = ["haxe"],"Constructible"},[t2]) -> type_iseq t1 t2 | _ -> false) tl) then error [cannot_unify a b] | _ -> let _,t,cf = class_field c tl "new" in - if not cf.cf_public then error [invalid_visibility "new"]; + if not (has_class_field_flag cf CfPublic) then error [invalid_visibility "new"]; begin try unify t t1 with Unify_error l -> error (cannot_unify a b :: l) end end @@ -2072,6 +2350,7 @@ and unify_abstracts a b a1 tl1 a2 tl2 = error [cannot_unify a b] and unify_anons a b a1 a2 = + if would_produce_recursive_anon a1 a2 then error [cannot_unify a b]; (try PMap.iter (fun n f2 -> try @@ -2081,9 +2360,13 @@ and unify_anons a b a1 a2 = | Opened, Var { v_read = AccNormal; v_write = AccNo }, Var { v_read = AccNormal; v_write = AccNormal } -> f1.cf_kind <- f2.cf_kind; | _ -> error [invalid_kind n f1.cf_kind f2.cf_kind]); - if f2.cf_public && not f1.cf_public then error [invalid_visibility n]; + if (has_class_field_flag f2 CfPublic) && not (has_class_field_flag f1 CfPublic) then error [invalid_visibility n]; try - unify_with_access (field_type f1) f2; + let f1_type = + if fast_eq f1.cf_type f2.cf_type then f1.cf_type + else field_type f1 + in + unify_with_access f1 f1_type f2; (match !(a1.a_status) with | Statics c when not (Meta.has Meta.MaybeUsed f1.cf_meta) -> f1.cf_meta <- (Meta.MaybeUsed,[],f1.cf_pos) :: f1.cf_meta | _ -> ()); @@ -2120,7 +2403,7 @@ and unify_from ab tl a b ?(allow_transitive_cast=true) t = (fun (a2,b2) -> fast_eq a a2 && fast_eq b b2) (fun() -> let t = apply_params ab.a_params tl t in - let unify_func = if allow_transitive_cast then unify else type_eq EqStrict in + let unify_func = if allow_transitive_cast then unify else type_eq EqRightDynamic in unify_func a t) and unify_to ab tl b ?(allow_transitive_cast=true) t = @@ -2206,12 +2489,14 @@ and unify_with_variance f t1 t2 = error [cannot_unify t1 t2] and unify_type_params a b tl1 tl2 = + let i = ref 0 in List.iter2 (fun t1 t2 -> + incr i; try with_variance (type_eq EqRightDynamic) t1 t2 with Unify_error l -> let err = cannot_unify a b in - error (err :: (Invariant_parameter (t1,t2)) :: l) + error (err :: (Invariant_parameter !i) :: l) ) tl1 tl2 and with_variance f t1 t2 = @@ -2222,15 +2507,24 @@ and with_variance f t1 t2 = with Unify_error _ -> raise (Unify_error l) -and unify_with_access t1 f2 = +and unify_with_access f1 t1 f2 = match f2.cf_kind with (* write only *) | Var { v_read = AccNo } | Var { v_read = AccNever } -> unify f2.cf_type t1 (* read only *) - | Method MethNormal | Method MethInline | Var { v_write = AccNo } | Var { v_write = AccNever } -> unify t1 f2.cf_type + | Method MethNormal | Method MethInline | Var { v_write = AccNo } | Var { v_write = AccNever } -> + if (has_class_field_flag f1 CfFinal) <> (has_class_field_flag f2 CfFinal) then raise (Unify_error [FinalInvariance]); + unify t1 f2.cf_type (* read/write *) | _ -> with_variance (type_eq EqBothDynamic) t1 f2.cf_type +let does_unify a b = + try + unify a b; + true + with Unify_error _ -> + false + (* ======= Mapping and iterating ======= *) let iter f e = @@ -2284,6 +2578,39 @@ let iter f e = | TReturn eo -> (match eo with None -> () | Some e -> f e) +(** + Returns `true` if `predicate` is evaluated to `true` for at least one of sub-expressions. + Returns `false` otherwise. + Does not evaluate `predicate` for the `e` expression. +*) +let check_expr predicate e = + match e.eexpr with + | TConst _ | TLocal _ | TBreak | TContinue | TTypeExpr _ | TIdent _ -> + false + | TArray (e1,e2) | TBinop (_,e1,e2) | TFor (_,e1,e2) | TWhile (e1,e2,_) -> + predicate e1 || predicate e2; + | TThrow e | TField (e,_) | TEnumParameter (e,_,_) | TEnumIndex e | TParenthesis e + | TCast (e,_) | TUnop (_,_,e) | TMeta(_,e) -> + predicate e + | TArrayDecl el | TNew (_,_,el) | TBlock el -> + List.exists predicate el + | TObjectDecl fl -> + List.exists (fun (_,e) -> predicate e) fl + | TCall (e,el) -> + predicate e || List.exists predicate el + | TVar (_,eo) | TReturn eo -> + (match eo with None -> false | Some e -> predicate e) + | TFunction fu -> + predicate fu.tf_expr + | TIf (e,e1,e2) -> + predicate e || predicate e1 || (match e2 with None -> false | Some e -> predicate e) + | TSwitch (e,cases,def) -> + predicate e + || List.exists (fun (el,e2) -> List.exists predicate el || predicate e2) cases + || (match def with None -> false | Some e -> predicate e) + | TTry (e,catches) -> + predicate e || List.exists (fun (_,e) -> predicate e) catches + let map_expr f e = match e.eexpr with | TConst _ @@ -2460,13 +2787,13 @@ module TExprToExpr = struct CTPath { tpackage = fst p; tname = snd p; - tparams = List.map (fun t -> TPType t) pl; + tparams = pl; tsub = None; } else CTPath { tpackage = fst mp; tname = snd mp; - tparams = List.map (fun t -> TPType t) pl; + tparams = pl; tsub = Some (snd p); } @@ -2482,26 +2809,28 @@ module TExprToExpr = struct CTPath { tpackage = []; tname = name; - tparams = List.map (fun t -> TPType (convert_type' t)) tl; + tparams = List.map tparam tl; tsub = None; } | TEnum (e,pl) -> - tpath e.e_path e.e_module.m_path (List.map convert_type' pl) + tpath e.e_path e.e_module.m_path (List.map tparam pl) + | TInst({cl_kind = KExpr e} as c,pl) -> + tpath ([],snd c.cl_path) ([],snd c.cl_path) (List.map tparam pl) | TInst({cl_kind = KTypeParameter _} as c,pl) -> - tpath ([],snd c.cl_path) ([],snd c.cl_path) (List.map convert_type' pl) + tpath ([],snd c.cl_path) ([],snd c.cl_path) (List.map tparam pl) | TInst (c,pl) -> - tpath c.cl_path c.cl_module.m_path (List.map convert_type' pl) + tpath c.cl_path c.cl_module.m_path (List.map tparam pl) | TType (t,pl) as tf -> (* recurse on type-type *) - if (snd t.t_path).[0] = '#' then convert_type (follow tf) else tpath t.t_path t.t_module.m_path (List.map convert_type' pl) + if (snd t.t_path).[0] = '#' then convert_type (follow tf) else tpath t.t_path t.t_module.m_path (List.map tparam pl) | TAbstract (a,pl) -> - tpath a.a_path a.a_module.m_path (List.map convert_type' pl) + tpath a.a_path a.a_module.m_path (List.map tparam pl) | TFun (args,ret) -> CTFunction (List.map (fun (_,_,t) -> convert_type' t) args, (convert_type' ret)) | TAnon a -> begin match !(a.a_status) with - | Statics c -> tpath ([],"Class") ([],"Class") [tpath c.cl_path c.cl_path [],null_pos] - | EnumStatics e -> tpath ([],"Enum") ([],"Enum") [tpath e.e_path e.e_path [],null_pos] + | Statics c -> tpath ([],"Class") ([],"Class") [TPType (tpath c.cl_path c.cl_path [],null_pos)] + | EnumStatics e -> tpath ([],"Enum") ([],"Enum") [TPType (tpath e.e_path e.e_path [],null_pos)] | _ -> CTAnonymous (PMap.foldi (fun _ f acc -> { @@ -2515,13 +2844,17 @@ module TExprToExpr = struct ) a.a_fields []) end | (TDynamic t2) as t -> - tpath ([],"Dynamic") ([],"Dynamic") (if t == t_dynamic then [] else [convert_type' t2]) + tpath ([],"Dynamic") ([],"Dynamic") (if t == t_dynamic then [] else [tparam t2]) | TLazy f -> convert_type (lazy_type f) and convert_type' t = convert_type t,null_pos + and tparam = function + | TInst ({cl_kind = KExpr e}, _) -> TPExpr e + | t -> TPType (convert_type' t) + and mk_type_hint t p = match follow t with | TMono _ -> None @@ -2558,10 +2891,10 @@ module TExprToExpr = struct | TNew (c,pl,el) -> ENew ((match (try convert_type (TInst (c,pl)) with Exit -> convert_type (TInst (c,[]))) with CTPath p -> p,null_pos | _ -> assert false),List.map convert_expr el) | TUnop (op,p,e) -> EUnop (op,p,convert_expr e) | TFunction f -> - let arg (v,c) = (v.v_name,v.v_pos), false, v.v_meta, mk_type_hint v.v_type null_pos, (match c with None -> None | Some c -> Some (EConst (tconst_to_const c),e.epos)) in + let arg (v,c) = (v.v_name,v.v_pos), false, v.v_meta, mk_type_hint v.v_type null_pos, (match c with None -> None | Some c -> Some (convert_expr c)) in EFunction (None,{ f_params = []; f_args = List.map arg f.tf_args; f_type = mk_type_hint f.tf_type null_pos; f_expr = Some (convert_expr f.tf_expr) }) | TVar (v,eo) -> - EVars ([(v.v_name,v.v_pos), mk_type_hint v.v_type v.v_pos, eopt eo]) + EVars ([(v.v_name,v.v_pos), v.v_final, mk_type_hint v.v_type v.v_pos, eopt eo]) | TBlock el -> EBlock (List.map convert_expr el) | TFor (v,it,e) -> let ein = (EBinop (OpIn,(EConst (Ident v.v_name),it.epos),convert_expr it),it.epos) in @@ -2605,272 +2938,160 @@ module TExprToExpr = struct end -module Texpr = struct - let equal_fa fa1 fa2 = match fa1,fa2 with - | FStatic(c1,cf1),FStatic(c2,cf2) -> c1 == c2 && cf1 == cf2 - | FInstance(c1,tl1,cf1),FInstance(c2,tl2,cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1 == cf2 - (* TODO: This is technically not correct but unfortunately the compiler makes a distinct tclass_field for each anon field access. *) - | FAnon cf1,FAnon cf2 -> cf1.cf_name = cf2.cf_name - | FDynamic s1,FDynamic s2 -> s1 = s2 - | FClosure(None,cf1),FClosure(None,cf2) -> cf1 == cf2 - | FClosure(Some(c1,tl1),cf1),FClosure(Some(c2,tl2),cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1 == cf2 - | FEnum(en1,ef1),FEnum(en2,ef2) -> en1 == en2 && ef1 == ef2 +module ExtType = struct + let is_mono = function + | TMono { contents = None } -> true | _ -> false - let rec equal e1 e2 = match e1.eexpr,e2.eexpr with - | TConst ct1,TConst ct2 -> ct1 = ct2 - | TLocal v1,TLocal v2 -> v1 == v2 - | TArray(eb1,ei1),TArray(eb2,ei2) -> equal eb1 eb2 && equal ei1 ei2 - | TBinop(op1,lhs1,rhs1),TBinop(op2,lhs2,rhs2) -> op1 = op2 && equal lhs1 lhs2 && equal rhs1 rhs2 - | TField(e1,fa1),TField(e2,fa2) -> equal e1 e2 && equal_fa fa1 fa2 - | TTypeExpr mt1,TTypeExpr mt2 -> mt1 == mt2 - | TParenthesis e1,TParenthesis e2 -> equal e1 e2 - | TObjectDecl fl1,TObjectDecl fl2 -> safe_for_all2 (fun (s1,e1) (s2,e2) -> s1 = s2 && equal e1 e2) fl1 fl2 - | (TArrayDecl el1,TArrayDecl el2) | (TBlock el1,TBlock el2) -> safe_for_all2 equal el1 el2 - | TCall(e1,el1),TCall(e2,el2) -> equal e1 e2 && safe_for_all2 equal el1 el2 - | TNew(c1,tl1,el1),TNew(c2,tl2,el2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && safe_for_all2 equal el1 el2 - | TUnop(op1,flag1,e1),TUnop(op2,flag2,e2) -> op1 = op2 && flag1 = flag2 && equal e1 e2 - | TFunction tf1,TFunction tf2 -> tf1 == tf2 - | TVar(v1,None),TVar(v2,None) -> v1 == v2 - | TVar(v1,Some e1),TVar(v2,Some e2) -> v1 == v2 && equal e1 e2 - | TFor(v1,ec1,eb1),TFor(v2,ec2,eb2) -> v1 == v2 && equal ec1 ec2 && equal eb1 eb2 - | TIf(e1,ethen1,None),TIf(e2,ethen2,None) -> equal e1 e2 && equal ethen1 ethen2 - | TIf(e1,ethen1,Some eelse1),TIf(e2,ethen2,Some eelse2) -> equal e1 e2 && equal ethen1 ethen2 && equal eelse1 eelse2 - | TWhile(e1,eb1,flag1),TWhile(e2,eb2,flag2) -> equal e1 e2 && equal eb2 eb2 && flag1 = flag2 - | TSwitch(e1,cases1,eo1),TSwitch(e2,cases2,eo2) -> - equal e1 e2 && - safe_for_all2 (fun (el1,e1) (el2,e2) -> safe_for_all2 equal el1 el2 && equal e1 e2) cases1 cases2 && - (match eo1,eo2 with None,None -> true | Some e1,Some e2 -> equal e1 e2 | _ -> false) - | TTry(e1,catches1),TTry(e2,catches2) -> equal e1 e2 && safe_for_all2 (fun (v1,e1) (v2,e2) -> v1 == v2 && equal e1 e2) catches1 catches2 - | TReturn None,TReturn None -> true - | TReturn(Some e1),TReturn(Some e2) -> equal e1 e2 - | TThrow e1,TThrow e2 -> equal e1 e2 - | TCast(e1,None),TCast(e2,None) -> equal e1 e2 - | TCast(e1,Some mt1),TCast(e2,Some mt2) -> equal e1 e2 && mt1 == mt2 - | TMeta((m1,el1,_),e1),TMeta((m2,el2,_),e2) -> m1 = m2 && safe_for_all2 (fun e1 e2 -> (* TODO: cheating? *) (Ast.s_expr e1) = (Ast.s_expr e2)) el1 el2 && equal e1 e2 - | (TBreak,TBreak) | (TContinue,TContinue) -> true - | TEnumParameter(e1,ef1,i1),TEnumParameter(e2,ef2,i2) -> equal e1 e2 && ef1 == ef2 && i1 = i2 + let is_void = function + | TAbstract({a_path=[],"Void"},_) -> true | _ -> false - let duplicate_tvars e = - let vars = Hashtbl.create 0 in - let copy_var v = - let v2 = alloc_var v.v_name v.v_type v.v_pos in - v2.v_meta <- v.v_meta; - v2.v_extra <- v.v_extra; - Hashtbl.add vars v.v_id v2; - v2; + let is_int t = match t with + | TAbstract({a_path=[],"Int"},_) -> true + | _ -> false + + let is_float t = match t with + | TAbstract({a_path=[],"Float"},_) -> true + | _ -> false + + let is_numeric t = match t with + | TAbstract({a_path=[],"Float"},_) -> true + | TAbstract({a_path=[],"Int"},_) -> true + | _ -> false + + let is_string t = match t with + | TInst({cl_path=[],"String"},_) -> true + | _ -> false + + let is_bool t = match t with + | TAbstract({a_path=[],"Bool"},_) -> true + | _ -> false + + type semantics = + | VariableSemantics + | ReferenceSemantics + | ValueSemantics + + let semantics_name = function + | VariableSemantics -> "variable" + | ReferenceSemantics -> "reference" + | ValueSemantics -> "value" + + let has_semantics t sem = + let name = semantics_name sem in + let check meta = + has_meta_option meta Meta.Semantics name in - let rec build_expr e = - match e.eexpr with - | TVar (v,eo) -> - let v2 = copy_var v in - {e with eexpr = TVar(v2, Option.map build_expr eo)} - | TFor (v,e1,e2) -> - let v2 = copy_var v in - {e with eexpr = TFor(v2, build_expr e1, build_expr e2)} - | TTry (e1,cl) -> - let cl = List.map (fun (v,e) -> - let v2 = copy_var v in - v2, build_expr e - ) cl in - {e with eexpr = TTry(build_expr e1, cl)} - | TFunction f -> - let args = List.map (fun (v,c) -> copy_var v, c) f.tf_args in - let f = { - tf_args = args; - tf_type = f.tf_type; - tf_expr = build_expr f.tf_expr; - } in - {e with eexpr = TFunction f} - | TLocal v -> - (try - let v2 = Hashtbl.find vars v.v_id in - {e with eexpr = TLocal v2} - with _ -> - e) + let rec loop t = match t with + | TInst(c,_) -> check c.cl_meta + | TEnum(en,_) -> check en.e_meta + | TType(t,tl) -> check t.t_meta || (loop (apply_params t.t_params tl t.t_type)) + | TAbstract(a,_) -> check a.a_meta + | TLazy f -> loop (lazy_type f) + | TMono r -> + (match !r with + | Some t -> loop t + | _ -> false) | _ -> - map_expr build_expr e + false in - build_expr e - - let rec skip e = match e.eexpr with - | TParenthesis e1 | TMeta(_,e1) | TBlock [e1] | TCast(e1,None) -> skip e1 - | _ -> e - - let foldmap_list f acc el = - let rec loop acc el acc2 = (match el with - | [] -> acc,(List.rev acc2) - | e1 :: el -> - let acc,e1 = f acc e1 in - loop acc el (e1 :: acc2)) - in loop acc el [] - - let foldmap_opt f acc eo = match eo with - | Some(e) -> let acc,e = f acc e in acc,Some(e) - | None -> acc,eo - - let foldmap_pairs f acc pairs = - let acc,pairs = List.fold_left - (fun (acc,el) (v,e) -> let acc,e = f acc e in (acc,(v,e) :: el)) - (acc,[]) - pairs - in acc,(List.rev pairs) - - let foldmap f acc e = - begin match e.eexpr with - | TConst _ - | TLocal _ - | TBreak - | TContinue - | TTypeExpr _ - | TIdent _ -> - acc,e - | TArray (e1,e2) -> - let acc,e1 = f acc e1 in - let acc,e2 = f acc e2 in - acc,{ e with eexpr = TArray (e1, e2) } - | TBinop (op,e1,e2) -> - let acc,e1 = f acc e1 in - let acc,e2 = f acc e2 in - acc,{ e with eexpr = TBinop (op,e1,e2) } - | TFor (v,e1,e2) -> - let acc,e1 = f acc e1 in - let acc,e2 = f acc e2 in - acc,{ e with eexpr = TFor (v,e1,e2) } - | TWhile (e1,e2,flag) -> - let acc,e1 = f acc e1 in - let acc,e2 = f acc e2 in - acc,{ e with eexpr = TWhile (e1,e2,flag) } - | TThrow e1 -> - let acc,e1 = f acc e1 in - acc,{ e with eexpr = TThrow (e1) } - | TEnumParameter (e1,ef,i) -> - let acc,e1 = f acc e1 in - acc,{ e with eexpr = TEnumParameter(e1,ef,i) } - | TEnumIndex e1 -> - let acc,e1 = f acc e1 in - acc,{ e with eexpr = TEnumIndex e1 } - | TField (e1,v) -> - let acc,e1 = f acc e1 in - acc,{ e with eexpr = TField (e1,v) } - | TParenthesis e1 -> - let acc,e1 = f acc e1 in - acc,{ e with eexpr = TParenthesis (e1) } - | TUnop (op,pre,e1) -> - let acc,e1 = f acc e1 in - acc,{ e with eexpr = TUnop (op,pre,e1) } - | TArrayDecl el -> - let acc,el = foldmap_list f acc el in - acc,{ e with eexpr = TArrayDecl el } - | TNew (t,pl,el) -> - let acc,el = foldmap_list f acc el in - acc,{ e with eexpr = TNew (t,pl,el) } - | TBlock el -> - let acc,el = foldmap_list f acc el in - acc,{ e with eexpr = TBlock (el) } - | TObjectDecl el -> - let acc,el = foldmap_pairs f acc el in - acc,{ e with eexpr = TObjectDecl el } - | TCall (e1,el) -> - let acc,e1 = f acc e1 in - let acc,el = foldmap_list f acc el in - acc,{ e with eexpr = TCall (e1,el) } - | TVar (v,eo) -> - let acc,eo = foldmap_opt f acc eo in - acc,{ e with eexpr = TVar (v, eo) } - | TFunction fu -> - let acc,e1 = f acc fu.tf_expr in - acc,{ e with eexpr = TFunction { fu with tf_expr = e1 } } - | TIf (ec,e1,eo) -> - let acc,ec = f acc ec in - let acc,e1 = f acc e1 in - let acc,eo = foldmap_opt f acc eo in - acc,{ e with eexpr = TIf (ec,e1,eo)} - | TSwitch (e1,cases,def) -> - let acc,e1 = f acc e1 in - let acc,cases = List.fold_left (fun (acc,cases) (el,e2) -> - let acc,el = foldmap_list f acc el in - let acc,e2 = f acc e2 in - acc,((el,e2) :: cases) - ) (acc,[]) cases in - let acc,def = foldmap_opt f acc def in - acc,{ e with eexpr = TSwitch (e1, cases, def) } - | TTry (e1,catches) -> - let acc,e1 = f acc e1 in - let acc,catches = foldmap_pairs f acc catches in - acc,{ e with eexpr = TTry (e1, catches) } - | TReturn eo -> - let acc,eo = foldmap_opt f acc eo in - acc,{ e with eexpr = TReturn eo } - | TCast (e1,t) -> - let acc,e1 = f acc e1 in - acc,{ e with eexpr = TCast (e1,t) } - | TMeta (m,e1) -> - let acc,e1 = f acc e1 in - acc,{ e with eexpr = TMeta(m,e1)} - end -end + loop t -module ExtType = struct - let is_void = function - | TAbstract({a_path=[],"Void"},_) -> true - | _ -> false + let has_variable_semantics t = has_semantics t VariableSemantics + let has_reference_semantics t = has_semantics t ReferenceSemantics + let has_value_semantics t = has_semantics t ValueSemantics end -module StringError = struct - (* Source: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#OCaml *) - let levenshtein a b = - let x = Array.init (String.length a) (fun i -> a.[i]) in - let y = Array.init (String.length b) (fun i -> b.[i]) in - let minimum (x:int) y z = - let m' (a:int) b = if a < b then a else b in - m' (m' x y) z - in - let init_matrix n m = - let init_col = Array.init m in - Array.init n (function - | 0 -> init_col (function j -> j) - | i -> init_col (function 0 -> i | _ -> 0) - ) +let class_module_type c = { + t_path = [],"Class<" ^ (s_type_path c.cl_path) ^ ">" ; + t_module = c.cl_module; + t_doc = None; + t_pos = c.cl_pos; + t_name_pos = null_pos; + t_type = TAnon { + a_fields = c.cl_statics; + a_status = ref (Statics c); + }; + t_private = true; + t_params = []; + t_using = []; + t_meta = no_meta; +} + +let enum_module_type m path p = { + t_path = [], "Enum<" ^ (s_type_path path) ^ ">"; + t_module = m; + t_doc = None; + t_pos = p; + t_name_pos = null_pos; + t_type = mk_mono(); + t_private = true; + t_params = []; + t_using = []; + t_meta = []; +} + +let abstract_module_type a tl = { + t_path = [],Printf.sprintf "Abstract<%s%s>" (s_type_path a.a_path) (s_type_params (ref []) tl); + t_module = a.a_module; + t_doc = None; + t_pos = a.a_pos; + t_name_pos = null_pos; + t_type = TAnon { + a_fields = PMap.empty; + a_status = ref (AbstractStatics a); + }; + t_private = true; + t_params = []; + t_using = []; + t_meta = no_meta; +} + +module TClass = struct + let get_member_fields' self_too c0 tl = + let rec loop acc c tl = + let apply = apply_params c.cl_params tl in + let maybe_add acc cf = + if not (PMap.mem cf.cf_name acc) then begin + let cf = if tl = [] then cf else {cf with cf_type = apply cf.cf_type} in + PMap.add cf.cf_name (c,cf) acc + end else acc + in + let acc = if self_too || c != c0 then List.fold_left maybe_add acc c.cl_ordered_fields else acc in + if c.cl_interface then + List.fold_left (fun acc (i,tl) -> loop acc i (List.map apply tl)) acc c.cl_implements + else + match c.cl_super with + | Some(c,tl) -> loop acc c (List.map apply tl) + | None -> acc in - match Array.length x, Array.length y with - | 0, n -> n - | m, 0 -> m - | m, n -> - let matrix = init_matrix (m + 1) (n + 1) in - for i = 1 to m do - let s = matrix.(i) and t = matrix.(i - 1) in - for j = 1 to n do - let cost = abs (compare x.(i - 1) y.(j - 1)) in - s.(j) <- minimum (t.(j) + 1) (s.(j - 1) + 1) (t.(j - 1) + cost) - done - done; - matrix.(m).(n) - - let filter_similar f cl = - let rec loop sl = match sl with - | (x,i) :: sl when f x i -> x :: loop sl - | _ -> [] + loop PMap.empty c0 tl + + let get_all_super_fields c = + get_member_fields' false c (List.map snd c.cl_params) + + let get_all_fields c tl = + get_member_fields' true c tl + + let get_overridden_fields c cf = + let rec loop acc c = match c.cl_super with + | None -> + acc + | Some(c,_) -> + begin try + let cf' = PMap.find cf.cf_name c.cl_fields in + loop (cf' :: acc) c + with Not_found -> + loop acc c + end in - loop cl - - let get_similar s sl = - if sl = [] then [] else - let cl = List.map (fun s2 -> s2,levenshtein s s2) sl in - let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in - let cl = filter_similar (fun s2 i -> i <= (min (String.length s) (String.length s2)) / 3) cl in - cl - - let string_error_raise s sl msg = - if sl = [] then msg else - let cl = get_similar s sl in - match cl with - | [] -> raise Not_found - | [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s - | sl -> Printf.sprintf "%s (Suggestions: %s)" msg (String.concat ", " sl) - - let string_error s sl msg = - try string_error_raise s sl msg - with Not_found -> msg + loop [] c end + +let s_class_path c = + let path = match c.cl_kind with + | KAbstractImpl a -> a.a_path + | _ -> c.cl_path + in + s_type_path path \ No newline at end of file diff --git a/src/core/withType.ml b/src/core/withType.ml new file mode 100644 index 00000000000..99d1e32f181 --- /dev/null +++ b/src/core/withType.ml @@ -0,0 +1,31 @@ +open Type + +type with_type_source = + | FunctionArgument of string + | StructureField of string + | ImplicitReturn + +type t = + | NoValue + | Value of with_type_source option + | WithType of Type.t * with_type_source option + +let with_type t = WithType(t,None) +let of_implicit_return t = WithType(t,Some ImplicitReturn) +let with_argument t name = WithType(t,Some(FunctionArgument name)) +let with_structure_field t name = WithType(t,Some(StructureField name)) +let value = Value None +let named_argument name = Value (Some(FunctionArgument name)) +let named_structure_field name = Value (Some(StructureField name)) +let no_value = NoValue + +let to_string = function + | NoValue -> "NoValue" + | Value (None | Some ImplicitReturn) -> "Value" + | Value (Some(FunctionArgument s | StructureField s)) -> "Value " ^ s + | WithType(t,s) -> + let name = match s with + | Some(FunctionArgument s | StructureField s) -> s + | _ -> "None" + in + Printf.sprintf "WithType(%s, %s)" (s_type (print_context()) t) name diff --git a/src/filters/ES6Ctors.ml b/src/filters/ES6Ctors.ml new file mode 100644 index 00000000000..766cbbb5de3 --- /dev/null +++ b/src/filters/ES6Ctors.ml @@ -0,0 +1,243 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) +open Common +open Globals +open Type +open Texpr.Builder + +(* name of the method to which the constructor is extracted *) +let ctor_method_name = "_hx_constructor" + +(* name of the static bool flag to skip constructor body execution *) +let skip_ctor_flag_name = "_hx_skip_constructor" + +(* replace super(a,b,c) with super._hx_constructor(a,b,c) *) +let rec replace_super_call e = + match e.eexpr with + | TCall ({ eexpr = TConst TSuper } as e_super, args) -> + let e_super_hxctor = { e_super with eexpr = TField (e_super, FDynamic ctor_method_name) } in + { e with eexpr = TCall (e_super_hxctor, args) } + | _ -> + map_expr replace_super_call e + +exception Accessed_this of texpr + +(* return whether given expression has `this` access before calling `super` *) +let has_this_before_super e = + let rec loop e = + match e.eexpr with + | TCall ({ eexpr = TConst TSuper }, args) -> + List.iter loop args; + raise Exit + | TConst TThis -> + raise (Accessed_this e) + | _ -> + Type.iter loop e + in + try + (loop e; None) + with + | Exit -> None + | Accessed_this e -> Some e + +let get_num_args cf = + match follow cf.cf_type with + | TFun (args, _) -> List.length args + | _ -> assert false + +(* + the filter works in two passes: + - mark classes whether they need to support constructor skipping and/or they skip parent's constructor + - change the constructors of marked classes (extract body into method and/or add skipping super calls) +*) +let rewrite_ctors com = + (* we mark classes that need changing by storing them in these two maps *) + let needs_ctor_skipping, does_ctor_skipping, inject_super = + let l = List.length com.types in + Hashtbl.create l, Hashtbl.create l, Hashtbl.create l + in + + (* + we're using a reference to the root of the inheritance chain so we can easily + generate RootClass._hx_skip_constructor expressions + *) + let mark_does_ctor_skipping cl cl_super p_this_access = + let rec mark_needs_ctor_skipping cl = + (* for non haxe-generated extern classes we can't generate any valid code, so just fail *) + if cl.cl_extern && not (Meta.has Meta.HxGen cl.cl_meta) then begin + abort "Must call `super()` constructor before accessing `this` in classes derived from an extern class with constructor" p_this_access; + end; + try + Hashtbl.find needs_ctor_skipping cl.cl_path + with Not_found -> + let root = + match cl.cl_super with + | Some ({ cl_constructor = Some ctor_super } as cl_super,_) -> + let root = mark_needs_ctor_skipping cl_super in + Option.may (fun ctor -> + (* if parent's constructor receives less arguments than needed for this - we need to override the constructor *) + if get_num_args ctor > get_num_args ctor_super then + Hashtbl.add does_ctor_skipping cl.cl_path root; + ) cl.cl_constructor; + root + | _ -> + cl + in + Hashtbl.add needs_ctor_skipping cl.cl_path root; + root + in + let root_cl = mark_needs_ctor_skipping cl_super in + Hashtbl.add does_ctor_skipping cl.cl_path root_cl; + in + + let e_empty_super_call = (* super() *) + let e_super = mk (TConst TSuper) t_dynamic null_pos in + mk (TCall (e_super,[])) com.basic.tvoid null_pos + in + + let activated = ref false in + let mark t = + match t with + | TClassDecl ({ cl_constructor = Some { cf_expr = Some { eexpr = TFunction tf } }; cl_super = Some (cl_super,_) } as cl) -> + if Type.has_constructor cl_super then begin + (* if parent class has a constructor, check for `this` accesses before calling `super()` *) + let this_before_super = has_this_before_super tf.tf_expr in + Option.may (fun e_this_access -> + activated := true; + mark_does_ctor_skipping cl cl_super e_this_access.epos + ) this_before_super + end else begin + (* if there was no ctor in the parent class, we still gotta call `super` *) + Hashtbl.add inject_super cl.cl_path cl; + end + | _ -> () + in + List.iter mark com.types; + + if !activated then begin + (* just some helper common exprs *) + let e_false = (make_bool com.basic false null_pos) in + let e_true = (make_bool com.basic true null_pos) in + let e_hx_ctor = (* this._hx_constructor *) + let ethis = mk (TConst TThis) t_dynamic null_pos in + mk (TField (ethis, FDynamic ctor_method_name)) t_dynamic null_pos + in + + let change t = + match t with + | TClassDecl ({ cl_constructor = Some ({ cf_expr = Some ({ eexpr = TFunction tf_ctor } as ctor_expr) } as cf_ctor) } as cl) -> + let does_ctor_skipping = try Some (Hashtbl.find does_ctor_skipping cl.cl_path) with Not_found -> None in + + let add_hx_ctor_method () = + let cf_fun_ctor = mk_field ctor_method_name cf_ctor.cf_type cf_ctor.cf_pos null_pos in + cf_fun_ctor.cf_expr <- Some (replace_super_call ctor_expr); + cf_fun_ctor.cf_kind <- Method MethNormal; + cl.cl_ordered_fields <- cf_fun_ctor :: cl.cl_ordered_fields; + cl.cl_fields <- PMap.add cf_fun_ctor.cf_name cf_fun_ctor cl.cl_fields; + in + + let make_hx_ctor_call e_skip_flag = (* this._hx_constructor(a,b,c) *) + let hxctor_call_args = List.map (fun (v,_) -> make_local v null_pos) tf_ctor.tf_args in + let hx_ctor_call = mk (TCall (e_hx_ctor, hxctor_call_args)) com.basic.tvoid null_pos in + if does_ctor_skipping <> None then + mk (TBlock [ + mk (TBinop (OpAssign, e_skip_flag, e_true)) com.basic.tbool null_pos; + e_empty_super_call; + mk (TBinop (OpAssign, e_skip_flag, e_false)) com.basic.tbool null_pos; + hx_ctor_call + ]) com.basic.tvoid null_pos + else + hx_ctor_call + in + + let make_skip_flag root_cl = (* TopClass._hx_skip_constructor *) + let e_top = mk (TTypeExpr (TClassDecl root_cl)) t_dynamic null_pos in + mk (TField (e_top, FDynamic skip_ctor_flag_name)) com.basic.tbool null_pos + in + + (match (try Some (Hashtbl.find needs_ctor_skipping cl.cl_path) with Not_found -> None) with + | Some root -> + add_hx_ctor_method (); + + if does_ctor_skipping = None && cl != root then + (* for intermediate classes that support skipping but don't do skipping themselves, we can just remove the constructor altogether, + because the skipping logic is implemented in the parent constructor, and the actual constructor body is moved into _hx_constructor *) + cf_ctor.cf_expr <- None + else begin + let e_skip = + let e_return = (mk (TReturn None) t_dynamic null_pos) in + if cl.cl_super = None || (Hashtbl.mem inject_super cl.cl_path) then + (* just `return` *) + e_return + else + (* `{ super(); return; }` *) + mk (TBlock [ + e_empty_super_call; + e_return; + ]) com.basic.tvoid null_pos + in + + let e_skip_flag = make_skip_flag root in + + let e_ctor_replaced = { tf_ctor.tf_expr with + eexpr = TBlock [ + mk (TIf (mk_parent e_skip_flag, e_skip, None)) com.basic.tvoid null_pos; + make_hx_ctor_call e_skip_flag + ] + } in + + cf_ctor.cf_expr <- Some { ctor_expr with eexpr = TFunction { tf_ctor with tf_expr = e_ctor_replaced } }; + end; + + if cl == root then begin + let cf_skip_ctor = mk_field skip_ctor_flag_name com.basic.tbool null_pos null_pos in + cf_skip_ctor.cf_expr <- Some e_false; + cl.cl_ordered_statics <- cf_skip_ctor :: cl.cl_ordered_statics; + cl.cl_statics <- PMap.add cf_skip_ctor.cf_name cf_skip_ctor cl.cl_statics; + end + | None -> + (match does_ctor_skipping with + | Some root -> + + add_hx_ctor_method (); + + let e_skip_flag = make_skip_flag root in + + let e_ctor_replaced = { tf_ctor.tf_expr with + eexpr = TBlock [ + make_hx_ctor_call e_skip_flag + ] + } in + cf_ctor.cf_expr <- Some { ctor_expr with eexpr = TFunction { tf_ctor with tf_expr = e_ctor_replaced } }; + + | None -> ()) + ) + | _ -> + () + in + List.iter change com.types + end; + + Hashtbl.iter (fun _ cl -> + match cl with + | { cl_constructor = Some ({ cf_expr = Some ({ eexpr = TFunction tf } as e_ctor) } as cf_ctor); cl_super = Some (cl_super,_) } -> + cl.cl_constructor <- Some { cf_ctor with cf_expr = Some { e_ctor with eexpr = TFunction { tf with tf_expr = { tf.tf_expr with eexpr = TBlock [e_empty_super_call; tf.tf_expr] } } } }; + | _ -> + assert false + ) inject_super; diff --git a/src/filters/capturedVars.ml b/src/filters/capturedVars.ml index b0828f19012..b8396312a1c 100644 --- a/src/filters/capturedVars.ml +++ b/src/filters/capturedVars.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -63,14 +63,14 @@ let captured_vars com e = let t = match v.v_type with TInst (_, [t]) -> t | _ -> assert false in mk (TNew (cnativearray,[t],[eone])) v.v_type p | Some e -> - { (Optimizer.mk_untyped_call "__array__" p [e]) with etype = v.v_type } + { (Inline.mk_untyped_call "__array__" p [e]) with etype = v.v_type } method mk_ref_access e v = mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos method mk_init av v pos = let elocal = mk (TLocal v) v.v_type pos in - let earray = { (Optimizer.mk_untyped_call "__array__" pos [elocal]) with etype = av.v_type } in + let earray = { (Inline.mk_untyped_call "__array__" pos [elocal]) with etype = av.v_type } in mk (TVar (av,Some earray)) t.tvoid pos end (* default implementation - use haxe array *) @@ -87,7 +87,7 @@ let captured_vars com e = in let mk_var v used = - let v2 = alloc_var v.v_name (PMap.find v.v_id used) v.v_pos in + let v2 = alloc_var v.v_kind v.v_name (PMap.find v.v_id used) v.v_pos in v2.v_meta <- v.v_meta; v2 in @@ -128,6 +128,11 @@ let captured_vars com e = let tmp_used = ref used in let rec browse = function | Block f | Loop f | Function f -> f browse + | Use ({ v_extra = Some( _ :: _, _) }) + | Assign ({ v_extra = Some( _ :: _, _) }) when com.platform = Cs || (com.platform = Java && not (Common.defined com Define.Jvm)) -> + (* Java and C# deal with functions with type parameters in a different way *) + (* so they do should not be wrapped *) + () | Use v | Assign v -> if PMap.mem v.v_id !tmp_used then fused := PMap.add v.v_id v !fused; | Declare v -> @@ -153,7 +158,7 @@ let captured_vars com e = *) if com.config.pf_capture_policy = CPLoopVars then (* We don't want to duplicate any variable declarations, so let's make copies (issue #3902). *) - let new_vars = List.map (fun v -> v.v_id,alloc_var v.v_name v.v_type v.v_pos) vars in + let new_vars = List.map (fun v -> v.v_id,alloc_var v.v_kind v.v_name v.v_type v.v_pos) vars in let rec loop e = match e.eexpr with | TLocal v -> begin try @@ -168,7 +173,7 @@ let captured_vars com e = in let e = loop e in mk (TCall ( - Codegen.mk_parent (mk (TFunction { + Texpr.Builder.mk_parent (mk (TFunction { tf_args = List.map (fun (_,v) -> v, None) new_vars; tf_type = e.etype; tf_expr = mk_block (mk (TReturn (Some e)) e.etype e.epos); @@ -214,6 +219,10 @@ let captured_vars com e = incr depth; f (collect_vars false); decr depth; + | Use ({ v_extra = Some( _ :: _, _) }) + | Assign ({ v_extra = Some( _ :: _, _) }) when com.platform = Cs || (com.platform = Java && not (Common.defined com Define.Jvm)) -> + (* Java/C# use a special handling for functions with type parmaters *) + () | Declare v -> if in_loop then vars := PMap.add v.v_id !depth !vars; | Use v | Assign v -> @@ -247,6 +256,9 @@ let captured_vars com e = decr depth; | Declare v -> vars := PMap.add v.v_id !depth !vars; + | Use ({ v_extra = Some( _ :: _, _) }) + | Assign ({ v_extra = Some( _ :: _, _) }) when com.platform = Cs || (com.platform = Java && not (Common.defined com Define.Jvm)) -> + () | Use v -> (try let d = PMap.find v.v_id !vars in diff --git a/src/filters/defaultArguments.ml b/src/filters/defaultArguments.ml index 3724067c510..bf8379ed83c 100644 --- a/src/filters/defaultArguments.ml +++ b/src/filters/defaultArguments.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -19,7 +19,7 @@ open Common open Type open Codegen -open Codegen.ExprBuilder +open Texpr.Builder (* This Module Filter will go through all defined functions in all modules and change them @@ -33,8 +33,7 @@ let gen_check basic t nullable_var const pos = (is_null t1) <> (is_null t2) in - let const_t = const_type basic const t in - let const = mk (TConst const) const_t pos in + let const_t = const.etype in let const = if needs_cast t const_t then mk_cast const t pos else const in let arg = make_local nullable_var pos in @@ -45,14 +44,14 @@ let gen_check basic t nullable_var const pos = let add_opt com block pos (var,opt) = match opt with - | None | Some TNull -> + | None | Some {eexpr = TConst TNull} -> (var,opt) - | Some (TString str) -> - block := Codegen.set_default com var (TString str) pos :: !block; + | Some ({eexpr = TConst (TString str)} as e) -> + block := Texpr.set_default com.basic var e pos :: !block; (var, opt) | Some const -> let basic = com.basic in - let nullable_var = alloc_var var.v_name (basic.tnull var.v_type) pos in + let nullable_var = alloc_var var.v_kind var.v_name (basic.tnull var.v_type) pos in (* var v = (temp_var == null) ? const : cast temp_var; *) let evar = mk (TVar(var, Some(gen_check basic var.v_type nullable_var const pos))) basic.tvoid pos in block := evar :: !block; diff --git a/src/filters/filters.ml b/src/filters/filters.ml index 802d9cc4fa1..21446296d1a 100644 --- a/src/filters/filters.ml +++ b/src/filters/filters.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -23,24 +23,9 @@ open Type open Typecore open Error open Globals +open FiltersCommon -(** retrieve string from @:native metadata or raise Not_found *) -let get_native_name meta = - let rec get_native meta = match meta with - | [] -> raise Not_found - | (Meta.Native,[v],p as meta) :: _ -> - meta - | _ :: meta -> - get_native meta - in - let (_,e,mp) = get_native meta in - match e with - | [Ast.EConst (Ast.String name),p] -> - name,p - | [] -> - raise Not_found - | _ -> - error "String expected" mp +let get_native_name = TypeloadCheck.get_native_name (* PASS 1 begin *) @@ -81,33 +66,6 @@ let rec add_final_return e = { e with eexpr = TFunction f } | _ -> e -let rec wrap_js_exceptions com e = - let rec is_error t = - match follow t with - | TInst ({cl_path = (["js"],"Error")},_) -> true - | TInst ({cl_super = Some (csup,tl)}, _) -> is_error (TInst (csup,tl)) - | _ -> false - in - let rec loop e = - match e.eexpr with - | TThrow eerr when not (is_error eerr.etype) -> - let terr = List.find (fun mt -> match mt with TClassDecl {cl_path = ["js";"_Boot"],"HaxeError"} -> true | _ -> false) com.types in - let cerr = match terr with TClassDecl c -> c | _ -> assert false in - (match eerr.etype with - | TDynamic _ -> - let eterr = Codegen.ExprBuilder.make_static_this cerr e.epos in - let ewrap = Codegen.fcall eterr "wrap" [eerr] t_dynamic e.epos in - { e with eexpr = TThrow ewrap } - | _ -> - let ewrap = { eerr with eexpr = TNew (cerr,[],[eerr]); etype = TInst (cerr,[]) } in - { e with eexpr = TThrow ewrap } - ) - | _ -> - Type.map_expr loop e - in - - loop e - (* -------------------------------------------------------------------------- *) (* CHECK LOCAL VARS INIT *) @@ -137,7 +95,7 @@ let check_local_vars_init e = | TVar (v,eo) -> begin match eo with - | None when Meta.has Meta.InlineConstructorVariable v.v_meta -> + | None when v.v_kind = VInlinedConstructorVariable -> () | None -> declared := v.v_id :: !declared; @@ -391,12 +349,57 @@ let check_unification ctx e t = end; e +let rec fix_return_dynamic_from_void_function ctx return_is_void e = + match e.eexpr with + | TFunction fn -> + let is_void = ExtType.is_void (follow fn.tf_type) in + let body = fix_return_dynamic_from_void_function ctx is_void fn.tf_expr in + { e with eexpr = TFunction { fn with tf_expr = body } } + | TReturn (Some return_expr) when return_is_void && t_dynamic == follow return_expr.etype -> + let return_pos = { e.epos with pmax = return_expr.epos.pmin - 1 } in + let exprs = [ + fix_return_dynamic_from_void_function ctx return_is_void return_expr; + { e with eexpr = TReturn None; epos = return_pos }; + ] in + { e with + eexpr = TMeta ( + (Meta.MergeBlock, [], null_pos), + mk (TBlock exprs) e.etype e.epos + ); + } + | _ -> Type.map_expr (fix_return_dynamic_from_void_function ctx return_is_void) e + +let check_abstract_as_value e = + let rec loop e = + match e.eexpr with + | TField ({ eexpr = TTypeExpr _ }, _) -> () + | TTypeExpr(TClassDecl {cl_kind = KAbstractImpl a}) when not (Meta.has Meta.RuntimeValue a.a_meta) -> + error "Cannot use abstract as value" e.epos + | _ -> Type.iter loop e + in + loop e; + e + (* PASS 1 end *) (* Saves a class state so it can be restored later, e.g. after DCE or native path rewrite *) let save_class_state ctx t = match t with | TClassDecl c -> + let vars = ref [] in + let rec save_vars e = + let add v = vars := (v, v.v_type) :: !vars in + match e.eexpr with + | TFunction fn -> + List.iter (fun (v, _) -> add v) fn.tf_args; + save_vars fn.tf_expr + | TVar (v, e) -> + add v; + Option.may save_vars e + | _ -> + iter save_vars e + in let mk_field_restore f = + Option.may save_vars f.cf_expr; let rec mk_overload_restore f = f.cf_name,f.cf_kind,f.cf_expr,f.cf_type,f.cf_meta,f.cf_params in @@ -421,6 +424,7 @@ let save_class_state ctx t = match t with let ofr = List.map (mk_field_restore) c.cl_ordered_fields in let osr = List.map (mk_field_restore) c.cl_ordered_statics in let init = c.cl_init in + Option.may save_vars init; c.cl_restore <- (fun() -> c.cl_super <- sup; c.cl_implements <- impl; @@ -435,31 +439,13 @@ let save_class_state ctx t = match t with c.cl_constructor <- Option.map restore_field csr; c.cl_overrides <- over; c.cl_descendants <- []; + List.iter (fun (v, t) -> v.v_type <- t) !vars; ) | _ -> () (* PASS 2 begin *) -let rec is_removable_class c = - match c.cl_kind with - | KGeneric -> - (Meta.has Meta.Remove c.cl_meta || - (match c.cl_super with - | Some (c,_) -> is_removable_class c - | _ -> false) || - List.exists (fun (_,t) -> match follow t with - | TInst(c,_) -> - has_ctor_constraint c || Meta.has Meta.Const c.cl_meta - | _ -> - false - ) c.cl_params) - | KTypeParameter _ -> - (* this shouldn't happen, have to investigate (see #4092) *) - true - | _ -> - false - let remove_generic_base ctx t = match t with | TClassDecl c when is_removable_class c -> c.cl_extern <- true @@ -563,7 +549,7 @@ let add_field_inits reserved ctx t = let apply c = let ethis = mk (TConst TThis) (TInst (c,List.map snd c.cl_params)) c.cl_pos in (* TODO: we have to find a variable name which is not used in any of the functions *) - let v = alloc_var "_g" ethis.etype ethis.epos in + let v = alloc_var VGenerated "_g" ethis.etype ethis.epos in let need_this = ref false in let inits,fields = List.fold_left (fun (inits,fields) cf -> match cf.cf_kind,cf.cf_expr with @@ -599,9 +585,9 @@ let add_field_inits reserved ctx t = match cf.cf_expr with | None -> assert false | Some e -> - let lhs = mk (TField(ethis,FInstance (c,List.map snd c.cl_params,cf))) cf.cf_type e.epos in + let lhs = mk (TField({ ethis with epos = cf.cf_pos },FInstance (c,List.map snd c.cl_params,cf))) cf.cf_type cf.cf_pos in cf.cf_expr <- None; - let eassign = mk (TBinop(OpAssign,lhs,e)) e.etype e.epos in + let eassign = mk (TBinop(OpAssign,lhs,e)) cf.cf_type e.epos in if is_as3 then begin let echeck = mk (TBinop(OpEq,lhs,(mk (TConst TNull) lhs.etype e.epos))) ctx.com.basic.tbool e.epos in mk (TIf(echeck,eassign,None)) eassign.etype e.epos @@ -650,7 +636,7 @@ let add_field_inits reserved ctx t = (* Adds the __meta__ field if required *) let add_meta_field ctx t = match t with | TClassDecl c -> - (match Codegen.build_metadata ctx.com t with + (match Texpr.build_metadata ctx.com.basic t with | None -> () | Some e -> add_feature ctx.com "has_metadata"; @@ -686,7 +672,7 @@ let check_cs_events com t = match t with let check fields f = match f.cf_kind with | Var { v_read = AccNormal; v_write = AccNormal } when Meta.has Meta.Event f.cf_meta -> - if f.cf_public then error "@:event fields must be private" f.cf_pos; + if (has_class_field_flag f CfPublic) then error "@:event fields must be private" f.cf_pos; (* prevent generating reflect helpers for the event in gencommon *) f.cf_meta <- (Meta.SkipReflection, [], f.cf_pos) :: f.cf_meta; @@ -776,37 +762,6 @@ let check_reserved_type_paths ctx t = (* PASS 3 end *) -let run_expression_filters ctx filters t = - let run e = - List.fold_left (fun e f -> f e) e filters - in - match t with - | TClassDecl c when is_removable_class c -> () - | TClassDecl c -> - ctx.curclass <- c; - let rec process_field f = - ctx.curfield <- f; - (match f.cf_expr with - | Some e when not (is_removable_field ctx f) -> - AbstractCast.cast_stack := f :: !AbstractCast.cast_stack; - f.cf_expr <- Some (run e); - AbstractCast.cast_stack := List.tl !AbstractCast.cast_stack; - | _ -> ()); - List.iter process_field f.cf_overloads - in - List.iter process_field c.cl_ordered_fields; - List.iter process_field c.cl_ordered_statics; - (match c.cl_constructor with - | None -> () - | Some f -> process_field f); - (match c.cl_init with - | None -> () - | Some e -> - c.cl_init <- Some (run e)); - | TEnumDecl _ -> () - | TTypeDecl _ -> () - | TAbstractDecl _ -> () - let pp_counter = ref 1 let is_cached t = @@ -834,25 +789,65 @@ let iter_expressions fl mt = () let filter_timer detailed s = - timer (if detailed then "filters" :: s else ["filters"]) + Timer.timer (if detailed then "filters" :: s else ["filters"]) + +module ForRemap = struct + let apply ctx e = + let rec loop e = match e.eexpr with + | TFor(v,e1,e2) -> + let e1 = loop e1 in + let e2 = loop e2 in + let iterator = ForLoop.IterationKind.of_texpr ctx e1 (ForLoop.is_cheap_enough_t ctx e2) e.epos in + let restore = save_locals ctx in + let e = ForLoop.IterationKind.to_texpr ctx v iterator e2 e.epos in + restore(); + e + | _ -> + Type.map_expr loop e + in + loop e +end let run com tctx main = let detail_times = Common.raw_defined com "filter-times" in let new_types = List.filter (fun t -> - (match t with + let cached = is_cached t in + begin match t with | TClassDecl cls -> List.iter (fun (iface,_) -> add_descendant iface cls) cls.cl_implements; - (match cls.cl_super with + begin match cls.cl_super with | Some (csup,_) -> add_descendant csup cls - | None -> ()) - | _ -> ()); - not (is_cached t) + | None -> () + end; + (* Save cf_expr_unoptimized early: We want to inline with the original expression + on the next compilation. *) + if not cached then begin + let field cf = match cf.cf_expr with + | Some {eexpr = TFunction tf} -> cf.cf_expr_unoptimized <- Some tf + | _ -> () + in + List.iter field cls.cl_ordered_fields; + List.iter field cls.cl_ordered_statics; + Option.may field cls.cl_constructor; + end; + | _ -> () + end; + not cached ) com.types in + NullSafety.run com new_types; (* PASS 1: general expression filters *) let filters = [ + (* ForRemap.apply tctx; *) VarLazifier.apply com; AbstractCast.handle_abstract_casts tctx; + ] in + let t = filter_timer detail_times ["expr 0"] in + List.iter (run_expression_filters tctx filters) new_types; + t(); + let filters = [ + fix_return_dynamic_from_void_function tctx true; check_local_vars_init; + check_abstract_as_value; if Common.defined com Define.OldConstructorInline then Optimizer.inline_constructors tctx else InlineConstructors.inline_constructors tctx; Optimizer.reduce_expression tctx; CapturedVars.captured_vars com; @@ -864,11 +859,13 @@ let run com tctx main = filters @ [ TryCatchWrapper.configure_cs com ] - | Java -> + | Java when not (Common.defined com Jvm)-> SetHXGen.run_filter com new_types; filters @ [ TryCatchWrapper.configure_java com ] + | Js -> + filters @ [JsExceptions.init tctx]; | _ -> filters in let t = filter_timer detail_times ["expr 1"] in @@ -897,8 +894,9 @@ let run com tctx main = let filters = [ Optimizer.sanitize com; if com.config.pf_add_final_return then add_final_return else (fun e -> e); - if com.platform = Js then wrap_js_exceptions com else (fun e -> e); - rename_local_vars tctx reserved; + (match com.platform with + | Eval -> (fun e -> e) + | _ -> rename_local_vars tctx reserved); mark_switch_break_loops; ] in let t = filter_timer detail_times ["expr 2"] in @@ -906,11 +904,14 @@ let run com tctx main = t(); next_compilation(); let t = filter_timer detail_times ["callbacks"] in - List.iter (fun f -> f()) (List.rev com.callbacks.before_dce); (* macros onGenerate etc. *) + List.iter (fun f -> f()) (List.rev com.callbacks#get_before_save); (* macros onGenerate etc. *) t(); let t = filter_timer detail_times ["save state"] in List.iter (save_class_state tctx) new_types; t(); + let t = filter_timer detail_times ["callbacks"] in + List.iter (fun f -> f()) (List.rev com.callbacks#get_after_save); (* macros onGenerate etc. *) + t(); let t = filter_timer detail_times ["type 2"] in (* PASS 2: type filters pre-DCE *) List.iter (fun t -> @@ -928,12 +929,13 @@ let run com tctx main = else (try Common.defined_value com Define.Dce with _ -> "no") in - begin match dce_mode with - | "full" -> Dce.run com main (not (Common.defined com Define.Interp)) - | "std" -> Dce.run com main false - | "no" -> Dce.fix_accessors com + let dce_mode = match dce_mode with + | "full" -> if Common.defined com Define.Interp then Dce.DceNo else DceFull + | "std" -> DceStd + | "no" -> DceNo | _ -> failwith ("Unknown DCE mode " ^ dce_mode) - end; + in + Dce.run com main dce_mode; t(); (* PASS 3: type filters post-DCE *) let type_filters = [ @@ -949,8 +951,10 @@ let run com tctx main = ] in let type_filters = match com.platform with | Cs -> type_filters @ [ fun _ t -> InterfaceProps.run t ] + | Js -> JsExceptions.inject_callstack com type_filters | _ -> type_filters in let t = filter_timer detail_times ["type 3"] in List.iter (fun t -> List.iter (fun f -> f tctx t) type_filters) com.types; - t() + t(); + List.iter (fun f -> f()) (List.rev com.callbacks#get_after_filters) diff --git a/src/filters/filtersCommon.ml b/src/filters/filtersCommon.ml new file mode 100644 index 00000000000..fc31b179382 --- /dev/null +++ b/src/filters/filtersCommon.ml @@ -0,0 +1,68 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*) +open Type +open Typecore + +let rec is_removable_class c = + match c.cl_kind with + | KGeneric -> + (Meta.has Meta.Remove c.cl_meta || + (match c.cl_super with + | Some (c,_) -> is_removable_class c + | _ -> false) || + List.exists (fun (_,t) -> match follow t with + | TInst(c,_) -> + has_ctor_constraint c || Meta.has Meta.Const c.cl_meta + | _ -> + false + ) c.cl_params) + | KTypeParameter _ -> + (* this shouldn't happen, have to investigate (see #4092) *) + true + | _ -> + false + +let run_expression_filters ctx filters t = + let run e = + List.fold_left (fun e f -> f e) e filters + in + match t with + | TClassDecl c when is_removable_class c -> () + | TClassDecl c -> + ctx.curclass <- c; + let rec process_field f = + ctx.curfield <- f; + (match f.cf_expr with + | Some e when not (is_removable_field ctx f) -> + f.cf_expr <- Some (rec_stack_loop AbstractCast.cast_stack f run e); + | _ -> ()); + List.iter process_field f.cf_overloads + in + List.iter process_field c.cl_ordered_fields; + List.iter process_field c.cl_ordered_statics; + (match c.cl_constructor with + | None -> () + | Some f -> process_field f); + (match c.cl_init with + | None -> () + | Some e -> + c.cl_init <- Some (run e)); + | TEnumDecl _ -> () + | TTypeDecl _ -> () + | TAbstractDecl _ -> () diff --git a/src/filters/jsExceptions.ml b/src/filters/jsExceptions.ml new file mode 100644 index 00000000000..c7f537d6360 --- /dev/null +++ b/src/filters/jsExceptions.ml @@ -0,0 +1,212 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(* + This filter handles everything related to exceptions for the JavaScript target: + + - wrapping non-js.Error types in HaxeError on throwing + - unwrapping HaxeError on catch + - transforming series of catches into a single catch with Std.is checks (optimized) + - re-throwing caught exception with js.Lib.rethrow + - storing caught exception in haxe.CallStack.lastException (if haxe.CallStack is used) + + Basically it translates this: + + try throw "fail" + catch (e:String) { trace(e); js.Lib.rethrow(); } + catch (e:Bool) {} + + into something like this (JS): + + try { + throw new HaxeError("fail"); + } catch (e) { + haxe.CallStack.lastException = e; + var e1 = (e instanceof HaxeError) e.val : e; + if (typeof e1 == "string") { + trace(e1); + throw e; + } else if (typeof e1 == "boolean") { + } else { + throw e; + } + } +*) + +open Common +open Type +open Typecore +open Texpr.Builder + +let follow = Abstract.follow_with_abstracts + +let rec is_js_error c = + match c with + | { cl_path = ["js";"lib"],"Error" } -> true + | { cl_super = Some (csup,_) } -> is_js_error csup + | _ -> false + +let find_cl com path = + ExtList.List.find_map (function + | TClassDecl c when c.cl_path = path -> Some c + | _ -> None + ) com.types + +let init ctx = + let cJsError = find_cl ctx.com (["js";"lib"],"Error") in + let cHaxeError = find_cl ctx.com (["js";"_Boot"],"HaxeError") in + let cStd = find_cl ctx.com ([],"Std") in + let cBoot = find_cl ctx.com (["js"],"Boot") in + let cSyntax = find_cl ctx.com (["js"],"Syntax") in + + let dynamic_wrap e = + let eHaxeError = make_static_this cHaxeError e.epos in + fcall eHaxeError "wrap" [e] (TInst (cJsError, [])) e.epos + in + + let static_wrap e = + { e with eexpr = TNew (cHaxeError,[],[e]); etype = TInst (cHaxeError,[]) } + in + + let rec loop vrethrow e = + match e.eexpr with + | TThrow eexc -> + let eexc = loop vrethrow eexc in + let eexc = + match follow eexc.etype with + | TDynamic _ | TMono _ -> + (match eexc.eexpr with + | TConst (TInt _ | TFloat _ | TString _ | TBool _ | TNull) -> static_wrap eexc + | _ -> dynamic_wrap eexc) + | TInst (c,_) when (is_js_error c) -> + eexc + | _ -> + static_wrap eexc + in + { e with eexpr = TThrow eexc } + + | TCall ({ eexpr = TField (_, FStatic ({ cl_path = ["js"],"Lib" }, { cf_name = "getOriginalException" })) }, _) -> + (match vrethrow with + | Some erethrowvar -> erethrowvar + | None -> abort "js.Lib.getOriginalException can only be called inside a catch block" e.epos) + + | TCall ({ eexpr = TField (_, FStatic ({ cl_path = ["js"],"Lib" }, { cf_name = "rethrow" })) }, _) -> + (match vrethrow with + | Some erethrowvar -> { e with eexpr = TThrow erethrowvar } + | None -> abort "js.Lib.rethrow can only be called inside a catch block" e.epos) + + | TTry (etry, catches) -> + let etry = loop vrethrow etry in + + let catchall_name, catchall_kind = match catches with [(v,_)] -> v.v_name, (VUser TVOCatchVariable) | _ -> "e", VGenerated in + let vcatchall = alloc_var catchall_kind catchall_name t_dynamic e.epos in + let ecatchall = make_local vcatchall e.epos in + let erethrow = mk (TThrow ecatchall) t_dynamic e.epos in + + let eSyntax = make_static_this cSyntax e.epos in + let eHaxeError = make_static_this cHaxeError e.epos in + let eInstanceof = fcall eSyntax "instanceof" [ecatchall;eHaxeError] ctx.com.basic.tbool e.epos in + let eVal = field { ecatchall with etype = TInst (cHaxeError,[]) } "val" t_dynamic e.epos in + let eunwrap = mk (TIf (eInstanceof, eVal, Some (ecatchall))) t_dynamic e.epos in + + let vunwrapped = alloc_var catchall_kind catchall_name t_dynamic e.epos in + vunwrapped.v_kind <- VGenerated; + let eunwrapped = make_local vunwrapped e.epos in + + let ecatch = List.fold_left (fun acc (v,ecatch) -> + let ecatch = loop (Some ecatchall) ecatch in + + (* it's not really compiler-generated, but it kind of is, since it was used as catch identifier and we add a TVar for it *) + v.v_kind <- VGenerated; + + match follow v.v_type with + | TDynamic _ -> + { ecatch with + eexpr = TBlock [ + mk (TVar (v, Some eunwrapped)) ctx.com.basic.tvoid ecatch.epos; + ecatch; + ] + } + | t -> + let etype = make_typeexpr (module_type_of_type t) e.epos in + let args = [eunwrapped;etype] in + let echeck = + match Inline.api_inline ctx cStd "is" args e.epos with + | Some e -> e + | None -> + let eBoot = make_static_this cBoot e.epos in + fcall eBoot "__instanceof" [eunwrapped;etype] ctx.com.basic.tbool e.epos + in + let ecatch = { ecatch with + eexpr = TBlock [ + mk (TVar (v, Some eunwrapped)) ctx.com.basic.tvoid ecatch.epos; + ecatch; + ] + } in + mk (TIf (echeck, ecatch, Some acc)) e.etype e.epos + ) erethrow (List.rev catches) in + + let ecatch = { ecatch with + eexpr = TBlock [ + mk (TVar (vunwrapped, Some eunwrap)) ctx.com.basic.tvoid e.epos; + ecatch; + ] + } in + { e with eexpr = TTry (etry, [(vcatchall,ecatch)]) } + | _ -> + Type.map_expr (loop vrethrow) e + in + loop None + +let inject_callstack com type_filters = + let cCallStack = + if Common.has_dce com then + if Common.has_feature com "haxe.CallStack.lastException" then + Some (find_cl com (["haxe"],"CallStack")) + else + None + else + try Some (find_cl com (["haxe"],"CallStack")) with Not_found -> None + in + match cCallStack with + | Some cCallStack -> + let run mt e = + let rec loop e = + match e.eexpr with + | TTry (etry,[(v,ecatch)]) -> + let etry = loop etry in + let ecatch = loop ecatch in + add_dependency (t_infos mt).mt_module cCallStack.cl_module; + let eCallStack = make_static_this cCallStack ecatch.epos in + let elastException = field eCallStack "lastException" t_dynamic ecatch.epos in + let elocal = make_local v ecatch.epos in + let eStoreException = mk (TBinop (Ast.OpAssign, elastException, elocal)) ecatch.etype ecatch.epos in + let ecatch = Type.concat eStoreException ecatch in + { e with eexpr = TTry (etry,[(v,ecatch)]) } + | TTry _ -> + (* this should be handled by the filter above *) + assert false + | _ -> + Type.map_expr loop e + in + loop e + in + type_filters @ [ fun ctx t -> FiltersCommon.run_expression_filters ctx [run t] t ] + | None -> + type_filters diff --git a/src/filters/localUsage.ml b/src/filters/localUsage.ml index 8820e5efd4c..28ea565b596 100644 --- a/src/filters/localUsage.ml +++ b/src/filters/localUsage.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/filters/tryCatchWrapper.ml b/src/filters/tryCatchWrapper.ml index 34c1c11473e..e7e4e4c92c5 100644 --- a/src/filters/tryCatchWrapper.ml +++ b/src/filters/tryCatchWrapper.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,7 +21,7 @@ open Common open Ast open Type open Codegen -open Codegen.ExprBuilder +open Texpr.Builder (* ******************************************* *) (* Try / Catch + throw native types handling *) @@ -79,9 +79,9 @@ let init com (should_wrap:t->bool) (wrap_throw:texpr->texpr) (unwrap_expr:texpr- | _, (v, c) :: _ -> let pos = c.epos in - let temp_var = alloc_var "catchallException" catchall_type pos in + let temp_var = alloc_var VGenerated "catchallException" catchall_type pos in let temp_local = make_local temp_var pos in - let catchall_var = alloc_var "realException" t_dynamic pos in + let catchall_var = alloc_var VGenerated "realException" t_dynamic pos in let catchall_local = make_local catchall_var pos in (* if it is of type wrapper_type, unwrap it *) @@ -138,11 +138,11 @@ let configure_cs com = let e_wrap = fcall e_hxexception "wrap" [expr] base_exception_t expr.epos in make_throw e_wrap expr.epos in - let unwrap_expr local_to_unwrap = Codegen.field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in + let unwrap_expr local_to_unwrap = field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in let rethrow_expr rethrow = make_throw e_rethrow rethrow.epos in let catch_map v e = let e_exc = make_static_this exc_cl e.epos in - let e_field = Codegen.field e_exc "exception" base_exception_t e.epos in + let e_field = field e_exc "exception" base_exception_t e.epos in let e_setstack = binop OpAssign e_field (make_local v e.epos) v.v_type e.epos in Type.concat e_setstack e in @@ -171,7 +171,7 @@ let configure_java com = let e_wrap = fcall e_hxexception "wrap" [expr] base_exception_t expr.epos in make_throw e_wrap expr.epos in - let unwrap_expr local_to_unwrap = Codegen.field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in + let unwrap_expr local_to_unwrap = field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in let rethrow_expr exc = { exc with eexpr = TThrow exc } in let catch_map v e = let exc = make_static_this exc_cl e.epos in diff --git a/src/filters/varLazifier.ml b/src/filters/varLazifier.ml index cb9461ba91f..b22dba8d263 100644 --- a/src/filters/varLazifier.ml +++ b/src/filters/varLazifier.ml @@ -3,13 +3,13 @@ open Type let apply com e = let rec loop var_inits e = match e.eexpr with - | TVar(v,Some e1) when (Meta.has (Meta.Custom ":extractorVariable") v.v_meta) -> - let var_inits,e1 = loop var_inits e1 in + | TVar(v,Some e1) when v.v_kind = VExtractorVariable -> let var_inits = PMap.add v.v_id e1 var_inits in var_inits,{e with eexpr = TVar(v,None)} | TLocal v -> begin try let e_init = PMap.find v.v_id var_inits in + let var_inits,e_init = loop var_inits e_init in let e = {e with eexpr = TBinop(OpAssign,e,e_init)} in let e = {e with eexpr = TParenthesis e} in let var_inits = PMap.remove v.v_id var_inits in diff --git a/src/generators/flashProps.ml b/src/generators/flashProps.ml new file mode 100644 index 00000000000..18e29d442be --- /dev/null +++ b/src/generators/flashProps.ml @@ -0,0 +1,60 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) +open Type + +let is_getter_name name = ExtString.String.starts_with name "get_" +let is_setter_name name = ExtString.String.starts_with name "set_" +let get_property_name accessor_name = String.sub accessor_name 4 (String.length accessor_name - 4) +let is_flash_property cf = Meta.has Meta.FlashProperty cf.cf_meta + +let find_property_for_accessor ~isget cl tl accessor_name = + let prop_name = get_property_name accessor_name in + try + match Type.class_field cl tl prop_name with + | Some (prop_cl, prop_tl), _, prop_cf -> + (match prop_cf.cf_kind with + | Var { v_read = AccCall; v_write = AccCall | AccNever } when isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf) + | Var { v_read = AccCall | AccNever; v_write = AccCall } when not isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf) + | _ -> None) + | _ -> None + with Not_found -> + None + +let is_extern_instance_accessor ~isget cl tl cf = + if cl.cl_extern && (if isget then is_getter_name cf.cf_name else is_setter_name cf.cf_name) then + find_property_for_accessor ~isget cl tl cf.cf_name + else + None + +let find_static_property_for_accessor ~isget cl accessor_name = + let prop_name = get_property_name accessor_name in + try + let prop_cf = PMap.find prop_name cl.cl_statics in + (match prop_cf.cf_kind with + | Var { v_read = AccCall; v_write = AccCall | AccNever } when isget && is_flash_property prop_cf -> Some prop_cf + | Var { v_read = AccCall | AccNever; v_write = AccCall } when not isget && is_flash_property prop_cf -> Some prop_cf + | _ -> None) + with Not_found -> + None + +let is_extern_static_accessor ~isget cl cf = + if cl.cl_extern && (if isget then is_getter_name cf.cf_name else is_setter_name cf.cf_name) then + find_static_property_for_accessor ~isget cl cf.cf_name + else + None diff --git a/src/generators/genas3.ml b/src/generators/genas3.ml index 478346f1698..accb48768d6 100644 --- a/src/generators/genas3.ml +++ b/src/generators/genas3.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -19,6 +19,7 @@ open Type open Common +open FlashProps type context_infos = { com : Common.context; @@ -28,7 +29,7 @@ type context = { inf : context_infos; ch : out_channel; buf : Buffer.t; - path : path; + path : Globals.path; mutable get_sets : (string * bool,string) Hashtbl.t; mutable curclass : tclass; mutable tabs : string; @@ -75,7 +76,7 @@ let is_fixed_override cf t = let protect name = match name with - | "Error" | "Namespace" -> "_" ^ name + | "Error" | "Namespace" | "Object" -> "_" ^ name | _ -> name let s_path ctx stat path p = @@ -146,7 +147,7 @@ let valid_as3_ident s = let anon_field s = let s = s_ident s in - if not (valid_as3_ident s) then "\"" ^ (Ast.s_escape s) ^ "\"" else s + if not (valid_as3_ident s) then "\"" ^ (StringHelper.s_escape s) ^ "\"" else s let rec create_dir acc = function | [] -> () @@ -263,24 +264,10 @@ let rec type_str ctx t p = | [], "Int" -> "int" | [], "Float" -> "Number" | [], "Bool" -> "Boolean" + | ["flash"], "AnyType" -> "*" | _ -> s_path ctx true a.a_path p) | TEnum (e,_) -> - if e.e_extern then (match e.e_path with - | [], "Void" -> "void" - | [], "Bool" -> "Boolean" - | _ -> - let rec loop = function - | [] -> "Object" - | (Meta.FakeEnum,[Ast.EConst (Ast.Ident n),_],_) :: _ -> - (match n with - | "Int" -> "int" - | "UInt" -> "uint" - | _ -> n) - | _ :: l -> loop l - in - loop e.e_meta - ) else - s_path ctx true e.e_path p + if e.e_extern then "Object" else s_path ctx true e.e_path p | TInst ({ cl_path = ["flash"],"Vector" },[pt]) -> (match pt with | TInst({cl_kind = KTypeParameter _},_) -> "*" @@ -352,7 +339,7 @@ let generate_resources infos = k := !k + 1; print ctx "\t\t[Embed(source = \"__res/%s\", mimeType = \"application/octet-stream\")]\n" (Bytes.unsafe_to_string (Base64.str_encode name)); print ctx "\t\tpublic static var %s:Class;\n" varname; - inits := ("list[\"" ^ Ast.s_escape name ^ "\"] = " ^ varname ^ ";") :: !inits; + inits := ("list[\"" ^ StringHelper.s_escape name ^ "\"] = " ^ varname ^ ";") :: !inits; ) infos.com.resources; spr ctx "\t\tstatic public function __init__():void {\n"; spr ctx "\t\t\tlist = new Dictionary();\n"; @@ -368,13 +355,13 @@ let generate_resources infos = let gen_constant ctx p = function | TInt i -> print ctx "%ld" i | TFloat s -> spr ctx s - | TString s -> print ctx "\"%s\"" (Ast.s_escape s) + | TString s -> print ctx "\"%s\"" (StringHelper.s_escape s) | TBool b -> spr ctx (if b then "true" else "false") | TNull -> spr ctx "null" | TThis -> spr ctx (this ctx) | TSuper -> spr ctx "super" -let gen_function_header ctx name f params p = +let rec gen_function_header ctx name f params p = let old = ctx.in_value in let old_t = ctx.local_types in let old_bi = ctx.block_inits in @@ -382,10 +369,10 @@ let gen_function_header ctx name f params p = ctx.local_types <- List.map snd params @ ctx.local_types; let init () = List.iter (fun (v,o) -> match o with - | Some c when is_nullable v.v_type && c <> TNull -> + | Some c when is_nullable v.v_type && c.eexpr <> TConst TNull -> newline ctx; print ctx "if(%s==null) %s=" v.v_name v.v_name; - gen_constant ctx p c; + gen_expr ctx c; | _ -> () ) f.tf_args; ctx.block_inits <- None; @@ -410,9 +397,11 @@ let gen_function_header ctx name f params p = match c with | None -> if ctx.constructor_block then print ctx " = %s" (default_value tstr); - | Some c -> + | Some ({eexpr = TConst _ } as e) -> spr ctx " = "; - gen_constant ctx p c + gen_expr ctx e + | _ -> + spr ctx " = null" ) f.tf_args; print ctx ") : %s " (type_str ctx f.tf_type p); (fun () -> @@ -421,7 +410,7 @@ let gen_function_header ctx name f params p = ctx.block_inits <- old_bi; ) -let rec gen_call ctx e el r = +and gen_call ctx e el r = match e.eexpr , el with | TCall (x,_) , el -> spr ctx "("; @@ -494,6 +483,9 @@ let rec gen_call ctx e el r = spr ctx ")"; | TIdent "__unprotect__", [e] -> gen_value ctx e + | TIdent "__vector__", [] -> + let t = match r with TAbstract ({a_path = [],"Class"}, [vt]) -> vt | _ -> assert false in + spr ctx (type_str ctx t e.epos); | TIdent "__vector__", [e] -> spr ctx (type_str ctx r e.epos); spr ctx "("; @@ -534,11 +526,55 @@ let rec gen_call ctx e el r = concat ctx "," (gen_value ctx) el; spr ctx ")"; print ctx ") as %s)" s + | TField (e1, f), el -> + begin + let default () = gen_call_default ctx e el in + let mk_prop_acccess prop_cl prop_tl prop_cf = mk (TField (e1, FInstance (prop_cl, prop_tl, prop_cf))) prop_cf.cf_type e.epos in + let mk_static_acccess cl prop_cf = mk (TField (e1, FStatic (cl, prop_cf))) prop_cf.cf_type e.epos in + let gen_assign lhs rhs = gen_expr ctx (mk (TBinop (OpAssign, lhs, rhs)) rhs.etype e.epos) in + match f, el with + | FInstance (cl, tl, cf), [] -> + (match is_extern_instance_accessor ~isget:true cl tl cf with + | Some (prop_cl, prop_tl, prop_cf) -> + let efield = mk_prop_acccess prop_cl prop_tl prop_cf in + gen_expr ctx efield + | None -> + default ()) + + | FInstance (cl, tl, cf), [evalue] -> + (match is_extern_instance_accessor ~isget:false cl tl cf with + | Some (prop_cl, prop_tl, prop_cf) -> + let efield = mk_prop_acccess prop_cl prop_tl prop_cf in + gen_assign efield evalue + | None -> + default ()) + + | FStatic (cl, cf), [] -> + (match is_extern_static_accessor ~isget:true cl cf with + | Some prop_cf -> + let efield = mk_static_acccess cl prop_cf in + gen_expr ctx efield + | None -> + default ()) + + | FStatic (cl, cf), [evalue] -> + (match is_extern_static_accessor ~isget:false cl cf with + | Some prop_cf -> + let efield = mk_static_acccess cl prop_cf in + gen_assign efield evalue + | None -> + default ()) + | _ -> + default () + end | _ -> - gen_value ctx e; - spr ctx "("; - concat ctx "," (gen_value ctx) el; - spr ctx ")" + gen_call_default ctx e el + +and gen_call_default ctx e el = + gen_value ctx e; + spr ctx "("; + concat ctx "," (gen_value ctx) el; + spr ctx ")" and gen_value_op ctx e = match e.eexpr with @@ -676,7 +712,7 @@ and gen_expr ctx e = let bend = open_block ctx in let cb = (if not ctx.constructor_block then (fun () -> ()) - else if not (Codegen.constructor_side_effects e) then begin + else if not (Texpr.constructor_side_effects e) then begin ctx.constructor_block <- false; (fun () -> ()) end else begin @@ -842,7 +878,7 @@ and gen_value ctx e = let value block = let old = ctx.in_value in let t = type_str ctx e.etype e.epos in - let r = alloc_var (gen_local ctx "$r") e.etype e.epos in + let r = alloc_var VGenerated (gen_local ctx "$r") e.etype e.epos in ctx.in_value <- Some r; if ctx.in_static then print ctx "function() : %s " t @@ -967,9 +1003,6 @@ and gen_value ctx e = )) e.etype e.epos); v() -let final m = - if Meta.has Meta.Final m then " final " else "" - let generate_field ctx static f = newline ctx; ctx.in_static <- static; @@ -997,16 +1030,19 @@ let generate_field ctx static f = print ctx "]"; | _ -> () ) f.cf_meta; - let public = f.cf_public || Hashtbl.mem ctx.get_sets (f.cf_name,static) || (f.cf_name = "main" && static) + let cfl_overridden = TClass.get_overridden_fields ctx.curclass f in + let overrides_public = List.exists (fun cf -> Meta.has Meta.Public cf.cf_meta) cfl_overridden in + let public = (has_class_field_flag f CfPublic) || Hashtbl.mem ctx.get_sets (f.cf_name,static) || (f.cf_name = "main" && static) || f.cf_name = "resolve" || Meta.has Meta.Public f.cf_meta (* consider all abstract methods public to avoid issues with inlined private access *) || (match ctx.curclass.cl_kind with KAbstractImpl _ -> true | _ -> false) + || overrides_public in let rights = (if static then "static " else "") ^ (if public then "public" else "protected") in let p = ctx.curclass.cl_pos in match f.cf_expr, f.cf_kind with | Some { eexpr = TFunction fd }, Method (MethNormal | MethInline) -> - print ctx "%s%s " rights (if static then "" else final f.cf_meta); + print ctx "%s%s " rights (if static || not (has_class_field_flag f CfFinal) then "" else " final "); let rec loop c = match c.cl_super with | None -> () @@ -1099,7 +1135,7 @@ let generate_class ctx c = define_getset ctx false c; ctx.local_types <- List.map snd c.cl_params; let pack = open_block ctx in - print ctx "\tpublic %s%s%s %s " (final c.cl_meta) (match c.cl_dynamic with None -> "" | Some _ -> if c.cl_interface then "" else "dynamic ") (if c.cl_interface then "interface" else "class") (snd c.cl_path); + print ctx "\tpublic %s%s%s %s " (if c.cl_final then " final " else "") "" (if c.cl_interface then "interface" else "class") (snd c.cl_path); (match c.cl_super with | None -> () | Some (csup,_) -> print ctx "extends %s " (s_path ctx true csup.cl_path c.cl_pos)); @@ -1115,7 +1151,7 @@ let generate_class ctx c = | Some f -> let f = { f with cf_name = snd c.cl_path; - cf_public = true; + cf_flags = set_flag f.cf_flags (int_of_class_field_flag CfPublic); cf_kind = Method MethNormal; } in ctx.constructor_block <- true; @@ -1204,13 +1240,13 @@ let generate_enum ctx e = print ctx "public static var %s : %s = new %s(\"%s\",%d)" c.ef_name ename ename c.ef_name c.ef_index; ) e.e_constrs; newline ctx; - (match Codegen.build_metadata ctx.inf.com (TEnumDecl e) with + (match Texpr.build_metadata ctx.inf.com.basic (TEnumDecl e) with | None -> () | Some e -> print ctx "public static var __meta__ : * = "; gen_expr ctx e; newline ctx); - print ctx "public static var __constructs__ : Array = [%s];" (String.concat "," (List.map (fun s -> "\"" ^ Ast.s_escape s ^ "\"") e.e_names)); + print ctx "public static var __constructs__ : Array = [%s];" (String.concat "," (List.map (fun s -> "\"" ^ StringHelper.s_escape s ^ "\"") e.e_names)); cl(); newline ctx; print ctx "}"; @@ -1242,6 +1278,7 @@ let generate_base_enum ctx = newline ctx let generate com = + com.warning "-as3 target is deprecated. Use -swf instead. See https://github.com/HaxeFoundation/haxe/issues/8295" Globals.null_pos; let infos = { com = com; } in diff --git a/src/generators/gencpp.ml b/src/generators/gencpp.ml index 1fb6fa91215..5f2d4c9c6d6 100644 --- a/src/generators/gencpp.ml +++ b/src/generators/gencpp.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -176,7 +176,7 @@ let cached_source_writer common_ctx filename = new source_writer common_ctx (add_header) (add_buf) (close) ;; -let make_class_directories = Common.mkdir_recursive;; +let make_class_directories = Path.mkdir_recursive;; let make_base_directory dir = make_class_directories "" ( ( Str.split_delim (Str.regexp "[\\/]+") dir ) );; @@ -387,7 +387,7 @@ let keyword_remap name = | "_Complex" | "INFINITY" | "NAN" | "INT_MIN" | "INT_MAX" | "INT8_MIN" | "INT8_MAX" | "UINT8_MAX" | "INT16_MIN" | "INT16_MAX" | "UINT16_MAX" | "INT32_MIN" | "INT32_MAX" | "UINT32_MAX" - | "asm" | "near" | "far" + | "asm" | "near" | "far" | "_w64" | "HX_" | "HXLINE" | "HXDLIN" | "NO" | "YES" | "abstract" | "decltype" | "finally" | "nullptr" | "static_assert" @@ -985,18 +985,6 @@ let rec is_dynamic_accessor name acc field class_def = && (match class_def.cl_super with None -> true | Some (parent,_) -> is_dynamic_accessor name acc field parent ) ;; - -(* Check to see if we are the first object in the parent tree to implement a dynamic interface *) -let implement_dynamic_here class_def = - let implements_dynamic c = match c.cl_dynamic with None -> false | _ -> true in - let rec super_implements_dynamic c = match c.cl_super with - | None -> false - | Some (csup, _) -> if (implements_dynamic csup) then true else - super_implements_dynamic csup; - in - ( (implements_dynamic class_def) && (not (super_implements_dynamic class_def) ) );; - - let gen_hash32 seed str = let h = ref (Int32.of_int seed) in let cycle = Int32.of_int 223 in @@ -1014,15 +1002,6 @@ let gen_hash_small seed str = Printf.sprintf "%08lx" (gen_hash32 seed str) ;; -let gen_string_hash str = - let h = gen_hash32 0 str in - Printf.sprintf "\"\\x%02lx\",\"\\x%02lx\",\"\\x%02lx\",\"\\x%02lx\"" - (Int32.shift_right_logical (Int32.shift_left h 24) 24) - (Int32.shift_right_logical (Int32.shift_left h 16) 24) - (Int32.shift_right_logical (Int32.shift_left h 8) 24) - (Int32.shift_right_logical h 24) -;; - let gen_qstring_hash str = let h = gen_hash32 0 str in Printf.sprintf "%02lx,%02lx,%02lx,%02lx" @@ -1032,32 +1011,16 @@ let gen_qstring_hash str = (Int32.shift_right_logical h 24) ;; +let gen_wqstring_hash str = + let h = gen_hash32 0 str in + Printf.sprintf "%04lx,%04lx" + (Int32.shift_right_logical (Int32.shift_left h 16) 16) + (Int32.shift_right_logical h 16) +;; -(* Make string printable for c++ code *) -(* Here we know there are no utf8 characters, so use the L"" notation to avoid conversion *) -let escape_stringw s l = - let b = Buffer.create 0 in - Buffer.add_char b 'L'; - Buffer.add_char b '"'; - let skip = ref 0 in - for i = 0 to String.length s - 1 do - if (!skip>0) then begin - skip := !skip -1; - l := !l-1; - end else - match Char.code (String.unsafe_get s i) with - | c when (c>127) -> - let encoded = ((c land 0x3F) lsl 6) lor ( Char.code ((String.unsafe_get s (i+1))) land 0x7F) in - skip := 1; - Buffer.add_string b (Printf.sprintf "\\x%X\"L\"" encoded) - | c when (c < 32) -> Buffer.add_string b (Printf.sprintf "\\x%X\"L\"" c) - | c -> Buffer.add_char b (Char.chr c) - done; - Buffer.add_char b '"'; - Buffer.contents b;; let special_to_hex s = let l = String.length s in @@ -1097,7 +1060,7 @@ let escape_command s = let gen_str macro gen s = let rec split s plus = - let escaped = Ast.s_escape ~hex:false s in + let escaped = StringHelper.s_escape ~hex:false s in let hexed = (special_to_hex escaped) in if (String.length hexed <= 16000 ) then plus ^ " HX_CSTRING(\"" ^ hexed ^ "\")" @@ -1107,7 +1070,7 @@ let gen_str macro gen s = (split (String.sub s 0 half) plus ) ^ (split (String.sub s half (len-half)) "+" ) end in - let escaped = Ast.s_escape ~hex:false s in + let escaped = StringHelper.s_escape ~hex:false s in let hexed = (special_to_hex escaped) in if (String.length hexed <= 16000 ) then macro ^ "(\"" ^ hexed ^ "\"," ^ (gen s) ^ ")" @@ -1115,13 +1078,32 @@ let gen_str macro gen s = "(" ^ (split s "" ) ^ ")" ;; -let str s = gen_str "HX_HCSTRING" gen_string_hash s;; -let strq s = gen_str "HX_" gen_qstring_hash s;; +let strq ctx s = + if (Common.defined ctx Define.HxcppSmartStings) && (has_utf8_chars s) then + let b = Buffer.create 0 in + + let add ichar = + match ichar with + | 92 (* \ *) -> Buffer.add_string b "\\\\" + | 39 (* ' *) -> Buffer.add_string b "\\\'" + | 34 -> Buffer.add_string b "\\\"" + | 13 (* \r *) -> Buffer.add_string b "\\r" + | 10 (* \n *) -> Buffer.add_string b "\\n" + | 9 (* \t *) -> Buffer.add_string b "\\t" + | c when c < 32 || (c >= 127 && c <= 0xFFFF) -> Buffer.add_string b (Printf.sprintf "\\u%04x" c) + | c when c > 0xFFFF -> Buffer.add_string b (Printf.sprintf "\\U%08x" c) + | c -> Buffer.add_char b (Char.chr c) + in + UTF8.iter (fun c -> add (UChar.code c) ) s; + "HX_W(u\"" ^ (Buffer.contents b) ^ "\"," ^ (gen_wqstring_hash s) ^ ")" + else + gen_str "HX_" gen_qstring_hash s +;; let const_char_star s = - let escaped = Ast.s_escape ~hex:false s in + let escaped = StringHelper.s_escape ~hex:false s in "\"" ^ special_to_hex escaped ^ "\""; ;; @@ -1278,16 +1260,6 @@ let is_matching_interface_type t0 t1 = -let default_value_string = function - | TInt i -> Printf.sprintf "%ld" i - | TFloat float_as_string -> "((Float)" ^ float_as_string ^ ")" - | TString s -> str s - | TBool b -> (if b then "true" else "false") - | TNull -> "null()" - | _ -> "/* Hmmm */" -;; - - let get_nth_type field index = match follow field.ef_type with @@ -1304,12 +1276,6 @@ let get_nth_type field index = -let has_default_values args = - List.exists ( fun (_,o) -> match o with - | Some TNull -> false - | Some _ -> true - | _ -> false ) args ;; - exception PathFound of string;; @@ -1331,7 +1297,7 @@ let strip_file ctx file = (match Common.defined ctx Common.Define.AbsolutePath w let hx_stack_push ctx output clazz func_name pos gc_stack = if ctx.ctx_debug_level > 0 then begin let stripped_file = strip_file ctx.ctx_common pos.pfile in - let esc_file = (Ast.s_escape stripped_file) in + let esc_file = (StringHelper.s_escape stripped_file) in ctx.ctx_file_info := PMap.add stripped_file pos.pfile !(ctx.ctx_file_info); let full_name = clazz ^ "." ^ func_name ^ ( if (clazz="*") then @@ -1406,7 +1372,7 @@ and tcppexpr = { and tcpp_closure = { close_type : tcpp; - close_args : (tvar * tconstant option) list; + close_args : (tvar * texpr option) list; close_expr : tcppexpr; close_id : int; close_undeclared : (string,tvar) Hashtbl.t; @@ -1762,43 +1728,48 @@ let cpp_is_dynamic_type = function ;; -let rec cpp_type_of ctx haxe_type = - (match haxe_type with - | TMono r -> (match !r with None -> TCppDynamic | Some t -> cpp_type_of ctx t) +let rec cpp_type_of stack ctx haxe_type = + if List.exists (fast_eq haxe_type) stack then + TCppDynamic + else begin + let stack = haxe_type :: stack in + (match haxe_type with + | TMono r -> (match !r with None -> TCppDynamic | Some t -> cpp_type_of stack ctx t) - | TEnum (enum,params) -> TCppEnum(enum) + | TEnum (enum,params) -> TCppEnum(enum) - | TInst ({ cl_path=([],"Array"); cl_kind = KTypeParameter _},_) - -> TCppObject + | TInst ({ cl_path=([],"Array"); cl_kind = KTypeParameter _},_) + -> TCppObject - | TInst ({ cl_kind = KTypeParameter _},_) - -> TCppDynamic + | TInst ({ cl_kind = KTypeParameter _},_) + -> TCppDynamic - | TInst (klass,params) -> - cpp_instance_type ctx klass params + | TInst (klass,params) -> + cpp_instance_type stack ctx klass params - | TAbstract (abs,pl) when not (Meta.has Meta.CoreType abs.a_meta) -> - cpp_type_from_path ctx abs.a_path pl (fun () -> - cpp_type_of ctx (Abstract.get_underlying_type abs pl) ) + | TAbstract (abs,pl) when not (Meta.has Meta.CoreType abs.a_meta) -> + cpp_type_from_path stack ctx abs.a_path pl (fun () -> + cpp_type_of stack ctx (Abstract.get_underlying_type abs pl) ) - | TAbstract (a,params) -> - cpp_type_from_path ctx a.a_path params (fun () -> - if is_scalar_abstract a then begin - let native = get_meta_string a.a_meta Meta.Native in - TCppScalar(if native="" then join_class_path a.a_path "::" else native) - end else - TCppDynamic) + | TAbstract (a,params) -> + cpp_type_from_path stack ctx a.a_path params (fun () -> + if is_scalar_abstract a then begin + let native = get_meta_string a.a_meta Meta.Native in + TCppScalar(if native="" then join_class_path a.a_path "::" else native) + end else + TCppDynamic) - | TType (type_def,params) -> - cpp_type_from_path ctx type_def.t_path params (fun () -> - cpp_type_of ctx (apply_params type_def.t_params params type_def.t_type) ) + | TType (type_def,params) -> + cpp_type_from_path stack ctx type_def.t_path params (fun () -> + cpp_type_of stack ctx (apply_params type_def.t_params params type_def.t_type) ) - | TFun _ -> TCppObject - | TAnon _ -> TCppObject - | TDynamic _ -> TCppDynamic - | TLazy func -> cpp_type_of ctx (lazy_type func) - ) - and cpp_type_from_path ctx path params default = + | TFun _ -> TCppObject + | TAnon _ -> TCppObject + | TDynamic _ -> TCppDynamic + | TLazy func -> cpp_type_of stack ctx (lazy_type func) + ) + end + and cpp_type_from_path stack ctx path params default = match path,params with | ([],"Void"),_ -> TCppVoid | ([],"void"),_ -> TCppVoid (* for old code with @:void *) @@ -1829,25 +1800,25 @@ let rec cpp_type_of ctx haxe_type = (* Things with type parameters hxcpp knows about ... *) | (["cpp"],"FastIterator"), [p] -> - TCppFastIterator(cpp_type_of ctx p) + TCppFastIterator(cpp_type_of stack ctx p) | (["cpp"],"Pointer"), [p] -> - TCppPointer("Pointer", cpp_type_of ctx p) + TCppPointer("Pointer", cpp_type_of stack ctx p) | (["cpp"],"ConstPointer"), [p] -> - TCppPointer("ConstPointer", cpp_type_of ctx p) + TCppPointer("ConstPointer", cpp_type_of stack ctx p) | (["cpp"],"RawPointer"), [p] -> - TCppRawPointer("", cpp_type_of ctx p) + TCppRawPointer("", cpp_type_of stack ctx p) | (["cpp"],"RawConstPointer"), [p] -> - TCppRawPointer("const ", cpp_type_of ctx p) + TCppRawPointer("const ", cpp_type_of stack ctx p) | (["cpp"],"Function"), [function_type; abi] -> - cpp_function_type_of ctx function_type abi; + cpp_function_type_of stack ctx function_type abi; | (["cpp"],"Callable"), [function_type] | (["cpp"],"CallableData"), [function_type] -> - cpp_function_type_of_string ctx function_type ""; + cpp_function_type_of_string stack ctx function_type ""; | (("cpp"::["objc"]),"ObjcBlock"), [function_type] -> - let args,ret = (cpp_function_type_of_args_ret ctx function_type) in + let args,ret = (cpp_function_type_of_args_ret stack ctx function_type) in TCppObjCBlock(args,ret) | (["haxe";"extern"], "Rest"),[rest] -> - TCppRest(cpp_type_of ctx rest) + TCppRest(cpp_type_of stack ctx rest) | (("cpp"::["objc"]),"Protocol"), [interface_type] -> (match follow interface_type with | TInst (klass,[]) when klass.cl_interface -> @@ -1857,16 +1828,16 @@ let rec cpp_type_of ctx haxe_type = assert false; ) | (["cpp"],"Reference"), [param] -> - TCppReference(cpp_type_of ctx param) + TCppReference(cpp_type_of stack ctx param) | (["cpp"],"Struct"), [param] -> - TCppStruct(cpp_type_of ctx param) + TCppStruct(cpp_type_of stack ctx param) | (["cpp"],"Star"), [param] -> - TCppStar(cpp_type_of ctx param,false) + TCppStar(cpp_type_of_pointer stack ctx param,false) | (["cpp"],"ConstStar"), [param] -> - TCppStar(cpp_type_of ctx param,true) + TCppStar(cpp_type_of_pointer stack ctx param,true) | ([],"Array"), [p] -> - let arrayOf = cpp_type_of ctx p in + let arrayOf = cpp_type_of stack ctx p in (match arrayOf with | TCppVoid (* ? *) | TCppDynamic -> @@ -1891,52 +1862,55 @@ let rec cpp_type_of ctx haxe_type = ) | ([],"Null"), [p] -> - cpp_type_of_null ctx p + cpp_type_of_null stack ctx p | _ -> default () - and cpp_type_of_null ctx p = - let baseType = cpp_type_of ctx p in + and cpp_type_of_null stack ctx p = + let baseType = cpp_type_of stack ctx p in if (type_has_meta_key p Meta.NotNull) || (is_cpp_scalar baseType) then TCppObject else baseType - + and cpp_type_of_pointer stack ctx p = + match p with + | TAbstract ({ a_path = ([],"Null") },[t]) -> cpp_type_of stack ctx t + | x -> cpp_type_of stack ctx x (* Optional types are Dynamic if they norally could not be null *) - and cpp_fun_arg_type_of ctx tvar opt = + and cpp_fun_arg_type_of stack ctx tvar opt = match opt with - | Some _ -> cpp_type_of_null ctx tvar.t_type - | _ -> cpp_type_of ctx tvar.t_type + | Some _ -> cpp_type_of_null stack ctx tvar.t_type + | _ -> cpp_type_of stack ctx tvar.t_type - and cpp_tfun_arg_type_of ctx opt t = - if opt then cpp_type_of_null ctx t else cpp_type_of ctx t + and cpp_tfun_arg_type_of stack ctx opt t = + if opt then cpp_type_of_null stack ctx t else cpp_type_of stack ctx t - and cpp_function_type_of ctx function_type abi = + and cpp_function_type_of stack ctx function_type abi = let abi = (match follow abi with | TInst (klass1,_) -> get_meta_string klass1.cl_meta Meta.Abi | _ -> assert false ) in - cpp_function_type_of_string ctx function_type abi - and cpp_function_type_of_string ctx function_type abi_string = - let args,ret = cpp_function_type_of_args_ret ctx function_type in + cpp_function_type_of_string stack ctx function_type abi + and cpp_function_type_of_string stack ctx function_type abi_string = + let args,ret = cpp_function_type_of_args_ret stack ctx function_type in TCppFunction(args, ret, abi_string) - and cpp_function_type_of_args_ret ctx function_type = + and cpp_function_type_of_args_ret stack ctx function_type = match follow function_type with | TFun(args,ret) -> (* Optional types are Dynamic if they norally could not be null *) let cpp_arg_type_of = fun(_,optional,haxe_type) -> if optional then - cpp_type_of_null ctx haxe_type + cpp_type_of_null stack ctx haxe_type else - cpp_type_of ctx haxe_type + cpp_type_of stack ctx haxe_type in - List.map cpp_arg_type_of args, cpp_type_of ctx ret + List.map cpp_arg_type_of args, cpp_type_of stack ctx ret | _ -> (* ? *) [TCppVoid], TCppVoid - and cpp_instance_type ctx klass params = - cpp_type_from_path ctx klass.cl_path params (fun () -> + and cpp_instance_type stack ctx klass params = + cpp_type_from_path stack ctx klass.cl_path params (fun () -> if is_objc_class klass then TCppObjC(klass) else if klass.cl_interface && is_native_gen_class klass then @@ -1948,6 +1922,17 @@ let rec cpp_type_of ctx haxe_type = else TCppInst(klass) ) + +let cpp_type_of ctx = cpp_type_of [] ctx +and cpp_type_from_path ctx = cpp_type_from_path [] ctx +and cpp_type_of_null ctx = cpp_type_of_null [] ctx +and cpp_type_of_pointer ctx = cpp_type_of_pointer [] ctx +and cpp_fun_arg_type_of ctx = cpp_fun_arg_type_of [] ctx +and cpp_tfun_arg_type_of ctx = cpp_tfun_arg_type_of [] ctx +and cpp_function_type_of ctx = cpp_function_type_of [] ctx +and cpp_function_type_of_string ctx = cpp_function_type_of_string [] ctx +and cpp_function_type_of_args_ret ctx = cpp_function_type_of_args_ret [] ctx +and cpp_instance_type ctx = cpp_instance_type [] ctx ;; @@ -2107,7 +2092,7 @@ let ctx_arg_type_name ctx name default_val arg_type prefix = let remap_name = keyword_remap name in let type_str = (ctx_type_string ctx arg_type) in match default_val with - | Some TNull -> (type_str,remap_name) + | Some {eexpr = TConst TNull} -> (type_str,remap_name) | Some constant when (ctx_cant_be_null ctx arg_type) -> ("hx::Null< " ^ type_str ^ " > ",prefix ^ remap_name) | Some constant -> (type_str,prefix ^ remap_name) | _ -> (type_str,remap_name);; @@ -2193,7 +2178,7 @@ let cpp_var_debug_name_of v = let cpp_no_debug_synbol ctx var = - (ctx.ctx_debug_level<=1) || (has_meta_key var.v_meta Meta.CompilerGenerated) || + (ctx.ctx_debug_level<=1) || (match var.v_kind with VUser _ -> false | _ -> true) || match cpp_type_of ctx var.v_type with | TCppStar _ | TCppReference _ -> true | TCppInst (class_def) when (has_meta_key class_def.cl_meta Meta.StructAccess) -> true @@ -2322,9 +2307,11 @@ let cpp_enum_name_of field = keyword_remap field.ef_name ;; -let is_gc_element ctx member_type = - Common.defined ctx.ctx_common Define.HxcppGcGenerational && +let is_object_element ctx member_type = match member_type with + | TCppInst x + | TCppInterface x + -> not (is_extern_class x) | TCppDynamic | TCppObject | TCppObjectPtr @@ -2335,15 +2322,15 @@ let is_gc_element ctx member_type = | TCppObjectArray _ | TCppWrapped _ | TCppScalarArray _ - | TCppInst _ - | TCppInterface _ | TCppClass -> true | _ -> false - ;; - +let is_gc_element ctx member_type = + Common.defined ctx.ctx_common Define.HxcppGcGenerational && + (is_object_element ctx member_type) +;; let retype_expression ctx request_type function_args function_type expression_tree forInjection = let rev_closures = ref [] in @@ -2622,7 +2609,7 @@ let retype_expression ctx request_type function_args function_type expression_tr else if fieldName="cca" && obj.cpptype=TCppString then CppFunction( FuncInternal(obj,"cca","."), TCppScalar("int")), TCppDynamic else if fieldName="__s" && obj.cpptype=TCppString then - CppVar( VarInternal(obj,".","__s")), TCppPointer("ConstPointer", TCppScalar("char")) + CppVar( VarInternal(obj,".","utf8_str()")), TCppPointer("ConstPointer", TCppScalar("char")) else if fieldName="__Index" then CppEnumIndex(obj), TCppScalar("int") else if is_internal_member fieldName || cpp_is_real_array obj then begin @@ -2692,7 +2679,17 @@ let retype_expression ctx request_type function_args function_type expression_tr | CppFunction( FuncStatic(obj, false, member), _ ) when member.cf_name = "hx::AddressOf" -> let arg = retype TCppUnchanged (List.hd args) in - CppAddressOf(arg), TCppRawPointer("", arg.cpptype) + let rawType = match arg.cpptype with | TCppReference(x) -> x | x -> x in + CppAddressOf(arg), TCppRawPointer("", rawType) + + | CppFunction( FuncStatic(obj, false, member), _ ) when member.cf_name = "hx::StarOf" -> + let arg = retype TCppUnchanged (List.hd args) in + let rawType = match arg.cpptype with | TCppReference(x) -> x | x -> x in + CppAddressOf(arg), TCppStar(rawType,false) + + | CppFunction( FuncStatic(obj, false, member), _ ) when member.cf_name = "hx::Dereference" -> + let arg = retype TCppUnchanged (List.hd args) in + CppDereference(arg), arg.cpptype | CppFunction( FuncStatic(obj, false, member), _ ) when member.cf_name = "_hx_create_array_length" -> let retypedArgs = List.map (retype TCppDynamic ) args in @@ -2896,6 +2893,7 @@ let retype_expression ctx request_type function_args function_type expression_tr | OpBoolAnd | OpBoolOr -> TCppScalar("bool") | OpAnd | OpOr | OpXor | OpShl | OpShr | OpUShr -> TCppScalar("int") | OpAssign -> (retype TCppUnchanged left).cpptype + | OpMult | OpSub -> cpp_type_of expr.etype | _ -> TCppUnchanged in let e1 = retype binOpType left in @@ -2938,7 +2936,12 @@ let retype_expression ctx request_type function_args function_type expression_tr | _ -> CppBinop(op,e1,e2) in - reference, cpp_type_of expr.etype + (match op,e1.cpptype,e2.cpptype with + (* Variant + Variant = Variant *) + | OpAdd, _, TCppVariant | OpAdd, TCppVariant, _ + -> reference, TCppVariant + | _,_,_ -> reference, cpp_type_of expr.etype + ) | TUnop (op,pre,e1) -> let targetType = match op with @@ -3089,6 +3092,7 @@ let retype_expression ctx request_type function_args function_type expression_tr else (match return_type with | TCppObjC(k) -> CppCastObjC(baseCpp,k), return_type | TCppPointer(_,_) + | TCppStar(_) | TCppInst(_) -> CppCast(baseCpp,return_type), return_type | TCppString -> CppCastScalar(baseCpp,"::String"), return_type | TCppCode(t) when baseStr <> (tcpp_to_string t) -> @@ -3103,16 +3107,16 @@ let retype_expression ctx request_type function_args function_type expression_tr | TCast (base,Some t) -> let baseCpp = retype (cpp_type_of base.etype) base in let baseStr = (tcpp_to_string baseCpp.cpptype) in - let return_type = if return_type=TCppUnchanged then cpp_type_of expr.etype else return_type in + let default_return_type = if return_type=TCppUnchanged then cpp_type_of expr.etype else return_type in + let return_type = cpp_type_from_path ctx (t_path t) [] (fun () -> default_return_type ) in let returnStr = (tcpp_to_string return_type) in if baseStr=returnStr then baseCpp.cppexpr, baseCpp.cpptype (* nothing to do *) else (match return_type with | TCppNativePointer(klass) -> CppCastNative(baseCpp), return_type - | TCppVoid -> baseCpp.cppexpr, TCppVoid - | TCppInterface _ -> - baseCpp.cppexpr, return_type + | TCppVoid -> + CppTCast(baseCpp, cpp_type_of expr.etype), return_type | TCppDynamic -> baseCpp.cppexpr, baseCpp.cpptype | _ -> @@ -3128,7 +3132,7 @@ let retype_expression ctx request_type function_args function_type expression_tr match cpp_variant_type_of cppExpr.cpptype with | TCppVoidStar | TCppScalar _ -> cppExpr - | TCppString -> mk_cppexpr (CppVar(VarInternal(cppExpr,".","__s"))) (TCppPointer("ConstPointer", TCppScalar("char"))) + | TCppString -> mk_cppexpr (CppVar(VarInternal(cppExpr,".","raw_ptr()"))) (TCppPointer("ConstPointer", TCppScalar("char"))) | TCppDynamic -> mk_cppexpr (CppCastNative(cppExpr)) TCppVoidStar | _ -> let toDynamic = mk_cppexpr (CppCast(cppExpr, TCppDynamic)) TCppDynamic in mk_cppexpr (CppCastNative(toDynamic)) TCppVoidStar @@ -3274,28 +3278,64 @@ let cpp_arg_type_name ctx tvar default_val prefix = let remap_name = (cpp_var_name_of tvar) in let type_str = (cpp_var_type_of ctx tvar) in match default_val with - | Some TNull -> (tcpp_to_string (cpp_type_of_null ctx tvar.v_type)),remap_name + | Some {eexpr = TConst TNull} -> (tcpp_to_string (cpp_type_of_null ctx tvar.v_type)),remap_name | Some constant -> (tcpp_to_string (cpp_type_of_null ctx tvar.v_type)),prefix ^ remap_name | _ -> type_str,remap_name ;; + +let string_of_path path = + "::" ^ (join_class_path_remap path "::") ^ "_obj" +;; + +let default_value_string ctx value = +match value.eexpr with + | TConst (TInt i) -> Printf.sprintf "%ld" i + | TConst (TFloat float_as_string) -> "((Float)" ^ float_as_string ^ ")" + | TConst (TString s) -> strq ctx s + | TConst (TBool b) -> (if b then "true" else "false") + | TConst TNull -> "null()" + | TField (_, FEnum(enum,field) ) -> (string_of_path enum.e_path) ^ "::" ^ (cpp_enum_name_of field) ^ "_dyn()" + | _ -> "/* Hmmm " ^ (s_expr_kind value) ^ " */" +;; + + + let cpp_gen_default_values ctx args prefix = List.iter ( fun (tvar,o) -> + let vtype = cpp_type_of ctx tvar.v_type in + let not_null = (type_has_meta_key tvar.v_type Meta.NotNull) || (is_cpp_scalar vtype) in match o with - | Some TNull -> () + | Some {eexpr = TConst TNull} -> () | Some const -> let name = cpp_var_name_of tvar in - ctx.ctx_output ((cpp_var_type_of ctx tvar) ^ " " ^ name ^ " = " ^ prefix ^ name ^ ".Default(" ^ - (default_value_string const) ^ ");\n") + let spacer = if (ctx.ctx_debug_level>0) then " \t" else "" in + let pname = prefix ^ name in + ctx.ctx_output ( spacer ^ "\t" ^ (tcpp_to_string vtype) ^ " " ^ name ^ " = " ^ pname ); + ctx.ctx_output ( if not_null then + ".Default(" ^ (default_value_string ctx.ctx_common const) ^ ");\n" + else + ";\n" ^ spacer ^ "\tif (hx::IsNull(" ^ pname ^ ")) " ^ name ^ " = " ^ (default_value_string ctx.ctx_common const) ^ ";\n" + ); | _ -> () ) args; ;; -let is_constant_zero expr = +let ctx_default_values ctx args prefix = + cpp_gen_default_values ctx args prefix +;; + +let cpp_class_hash interface = + gen_hash 0 (join_class_path interface.cl_path "::" ) +;; + + +let rec is_constant_zero expr = match expr.cppexpr with | CppFloat x when (float_of_string x) = 0.0 -> true | CppInt i when i = Int32.of_int 0 -> true + | CppCastScalar(expr,_) -> is_constant_zero(expr) | _ -> false ;; @@ -3322,13 +3362,26 @@ let cpp_arg_list ctx args prefix = ;; -let ctx_default_values ctx args prefix = - cpp_gen_default_values ctx args prefix +let gen_type ctx haxe_type = + ctx.ctx_output (ctx_type_string ctx haxe_type) ;; -let gen_type ctx haxe_type = - ctx.ctx_output (ctx_type_string ctx haxe_type) + + + +let rec implements_native_interface class_def = + List.exists (fun (intf_def,_) -> + is_native_gen_class intf_def || + implements_native_interface intf_def + ) class_def.cl_implements || + (match class_def.cl_super with + | Some (i,_) -> implements_native_interface i + | _ -> false ) +;; + +let can_quick_alloc klass = + not (implements_native_interface klass) ;; @@ -3337,6 +3390,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ let out = ctx.ctx_output in let lastLine = ref (-1) in let tempId = ref 0 in + let strq = strq ctx.ctx_common in let spacer = if (ctx.ctx_debug_level>0) then " \t" else "" in let output_i value = out spacer; writer#write_i value in @@ -3359,7 +3413,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ let class_hash = gen_hash_small 0 class_name in (*let genGc = Common.defined ctx.ctx_common Define.HxcppGcGenerational in*) - let rec gen_with_injection injection expr = + let rec gen_with_injection injection expr new_line = (match expr.cppexpr with | CppBlock(exprs,closures,gc_stack) -> writer#begin_block; @@ -3377,7 +3431,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ ) exprs; (match injection with Some inject -> out inject.inj_tail | _ -> () ); out spacer; - writer#end_block; + if new_line then writer#end_block else writer#end_block_line; | CppInt i -> out (Printf.sprintf (if i> Int32.of_int(-1000000000) && i< Int32.of_int(1000000000) then "%ld" else "(int)%ld") i) | CppFloat float_as_string -> out ("((Float)" ^ float_as_string ^")") @@ -3485,7 +3539,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ expr.cpppos); out " ]" - | CppCall(FuncNew( TCppInst klass), args) -> + | CppCall(FuncNew( TCppInst klass), args) when can_quick_alloc klass -> out ((cpp_class_path_of klass) ^ "_obj::__alloc( HX_CTX "); List.iter (fun arg -> out ","; gen arg ) args; out (")") @@ -3880,8 +3934,8 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ | DoWhile -> out ("do "); lastLine := -1; - gen block; - out "while("; gen condition; out ")" + gen_with_injection None block false; + out " while("; gen condition; out ");\n" ); if loop_id > -1 then output_i ((label_name loop_id) ^ ":"); @@ -3907,7 +3961,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ let prologue = fun _ -> output_i ( varType ^ " " ^ (cpp_var_name_of tvar) ^ " = __it->next();\n" ); in - gen_with_injection (mk_injection prologue "" "") loop; + gen_with_injection (mk_injection prologue "" "") loop true; | CppTry(block,catches) -> @@ -3917,25 +3971,34 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ ) catches in out ("try "); - gen_with_injection (mk_injection prologue "" "" ) block; + gen_with_injection (mk_injection prologue "" "" ) block (List.length catches < 0); if (List.length catches > 0 ) then begin - output_i "catch( ::Dynamic _hx_e)"; + out " catch( ::Dynamic _hx_e) "; writer#begin_block; let seen_dynamic = ref false in let else_str = ref "" in List.iter (fun (v,catch) -> let type_name = cpp_var_type_of ctx v in - if (type_name="Dynamic") then begin - seen_dynamic := true; - output_i !else_str; - end else - output_i (!else_str ^ "if (_hx_e.IsClass< " ^ type_name ^ " >() )"); + (match cpp_type_of ctx v.v_type with + | TCppInterface(klass) -> + let hash = (cpp_class_hash klass) in + output_i (!else_str ^ "if (hx::TIsInterface< (int)" ^ hash ^ " >(_hx_e.mPtr))") + | TCppString -> + output_i (!else_str ^ "if (_hx_e.IsClass< ::String >() && _hx_e->toString()!=null() )"); + | _ -> + if (type_name="Dynamic") then begin + seen_dynamic := true; + output_i !else_str; + end else + output_i (!else_str ^ "if (_hx_e.IsClass< " ^ type_name ^ " >() )"); + ); + let prologue = function _ -> output_i "HX_STACK_BEGIN_CATCH\n"; output_i (type_name ^ " " ^ (cpp_var_name_of v) ^ " = _hx_e;\n"); in - gen_with_injection (mk_injection prologue "" "") catch; + gen_with_injection (mk_injection prologue "" "") catch true; else_str := "else "; ) catches; @@ -3951,11 +4014,19 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ | CppCode(value, exprs) -> Codegen.interpolate_code ctx.ctx_common (format_code value) exprs out (fun e -> gen e) expr.cpppos | CppTCast(expr,cppType) -> - let toType = tcpp_to_string cppType in - if toType="Dynamic" then - (out " ::Dynamic("; gen expr; out ")") - else - (out ("hx::TCast< " ^ toType ^ " >::cast("); gen expr; out ")") + (match cppType with + | TCppInterface(i) -> + out " hx::interface_check("; + gen expr; + out ("," ^ (cpp_class_hash i) ^")") + | _ -> begin + let toType = tcpp_to_string cppType in + if toType="Dynamic" then + (out " ::Dynamic("; gen expr; out ")") + else + (out ("hx::TCast< " ^ toType ^ " >::cast("); gen expr; out ")") + end + ) | CppCastStatic(expr,toType) -> let close = match expr.cpptype with @@ -4006,7 +4077,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ out ("/* " ^ (s_tcpp expr.cppexpr) ^ ":" ^ tcpp_to_string expr.cpptype ^ " */") and gen expr = - gen_with_injection None expr + gen_with_injection None expr true and gen_lvalue lvalue = match lvalue with @@ -4094,8 +4165,6 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ | OpArrow -> "->" | OpIn -> " in " | OpAssign | OpAssignOp _ -> abort "Unprocessed OpAssign" pos - and string_of_path path = - "::" ^ (join_class_path_remap path "::") ^ "_obj" and gen_closure closure = let argc = Hashtbl.length closure.close_undeclared in @@ -4130,8 +4199,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ out ("HXLINE(" ^ lineName ^ ")\n" ); end in - - gen_with_injection (mk_injection prologue "" "") closure.close_expr; + gen_with_injection (mk_injection prologue "" "") closure.close_expr true; let return = match closure.close_type with TCppVoid -> "(void)" | _ -> "return" in @@ -4141,7 +4209,7 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_ (*out "\t";*) - gen_with_injection injection cppTree; + gen_with_injection injection cppTree true; ;; @@ -4215,21 +4283,59 @@ let is_override class_def field = List.exists (fun f -> f.cf_name = field) class_def.cl_overrides ;; -let current_virtual_functions clazz = - List.rev (List.fold_left (fun result elem -> match follow elem.cf_type, elem.cf_kind with - | _, Method MethDynamic -> result - | TFun (args,return_type), Method _ when not (is_override clazz elem.cf_name ) -> (elem,args,return_type) :: result - | _,_ -> result ) [] clazz.cl_ordered_fields) +(* + Functions are added in reverse order (oldest on right), then list is reversed because this is easier in ocaml + The order is important because cppia looks up functions by index +*) + + +let current_virtual_functions_rev clazz base_functions = + List.fold_left (fun result elem -> match follow elem.cf_type, elem.cf_kind with + | _, Method MethDynamic -> result + | TFun (args,return_type), Method _ -> + if (is_override clazz elem.cf_name ) then + List.map (fun (e,a,r) -> if e.cf_name<>elem.cf_name then (e,a,r) else (elem,args,return_type) ) result + else + (elem,args,return_type) :: result + | _,_ -> result + ) base_functions clazz.cl_ordered_fields ;; let all_virtual_functions clazz = - let rec all_virtual_functions clazz = - (match clazz.cl_super with - | Some def -> all_virtual_functions (fst def) - | _ -> [] ) @ current_virtual_functions clazz + let rec all_virtual_functions_rec clazz = + current_virtual_functions_rev clazz (match clazz.cl_super with + | Some def -> all_virtual_functions_rec (fst def) + | _ -> [] + ) + in + List.rev (all_virtual_functions_rec clazz) +;; + + + +(* +let current_virtual_functions clazz parents override_types = + List.fold_left (fun result elem -> match follow elem.cf_type, elem.cf_kind with + | _, Method MethDynamic -> result + | TFun (args,return_type), Method _ -> + if override_types then + (elem,args,return_type) :: (List.filter (fun (e,a,r) -> e.cf_name<>elem.cf_name) result) + else if (is_override clazz elem.cf_name ) then + result + else + (elem,args,return_type) :: result + | _,_ -> result ) parents (List.rev clazz.cl_ordered_fields) +;; + +let all_virtual_functions clazz override_types = + let rec all_virtual_functions clazz = + current_virtual_functions clazz (match clazz.cl_super with + | Some def -> all_virtual_functions (fst def) + | _ -> [] ) false in all_virtual_functions clazz ;; +*) let rec unreflective_type t = @@ -4360,7 +4466,7 @@ let gen_field ctx class_def class_name ptr_name dot_name is_static is_interface | TCppStar (t,const) -> output ("(cpp::" ^ (if const then "Const" else "") ^"Pointer<" ^ (tcpp_to_string t)^" >) ") | TCppInst(t) when has_meta_key t.cl_meta Meta.StructAccess -> - output ("(cpp::Struct< " ^ (tcpp_to_string return_type) ^ " >) "); + output ("(cpp::Struct< " ^ (tcpp_to_string arg) ^ " >) "); | _ -> () ); output ("a" ^ (string_of_int i)); ) tcpp_args; @@ -4445,10 +4551,6 @@ let cpp_interface_impl_name ctx interface = ;; -let cpp_class_hash interface = - gen_hash 0 (join_class_path interface.cl_path "::" ) -;; - let has_field_init field = @@ -4478,7 +4580,7 @@ let gen_member_def ctx class_def is_static is_interface field = output (if (not is_static) then ")=0;\n" else ");\n"); if (reflective class_def field) then begin if (Common.defined ctx.ctx_common Define.DynamicInterfaceClosures) then - output (" inline ::Dynamic " ^ remap_name ^ "_dyn() { return __Field( " ^ (str field.cf_name) ^ ", hx::paccDynamic); }\n" ) + output (" inline ::Dynamic " ^ remap_name ^ "_dyn() { return __Field( " ^ (strq ctx.ctx_common field.cf_name) ^ ", hx::paccDynamic); }\n" ) else output (" virtual ::Dynamic " ^ remap_name ^ "_dyn()=0;\n" ); end @@ -4487,7 +4589,7 @@ let gen_member_def ctx class_def is_static is_interface field = let returnType = ctx_type_string ctx return_type in let returnStr = if returnType = "void" then "" else "return " in let commaArgList = if argList="" then argList else "," ^ argList in - let cast = "static_cast< ::" ^ join_class_path_remap class_def.cl_path "::" ^ "_obj *>" in + let cast = "hx::interface_cast< ::" ^ join_class_path_remap class_def.cl_path "::" ^ "_obj *>" in output (" " ^ returnType ^ " (hx::Object :: *_hx_" ^ remap_name ^ ")(" ^ argList ^ "); \n"); output (" static inline " ^ returnType ^ " " ^ remap_name ^ "( ::Dynamic _hx_" ^ commaArgList ^ ") {\n"); output (" " ^ returnStr ^ "(_hx_.mPtr->*( " ^ cast ^ "(_hx_.mPtr->_hx_getInterface(" ^ (cpp_class_hash class_def) ^ ")))->_hx_" ^ remap_name ^ ")(" ^ cpp_arg_names args ^ ");\n }\n" ); @@ -4545,7 +4647,7 @@ let gen_member_def ctx class_def is_static is_interface field = output (tcppStr ^ " " ^ remap_name ^ ";\n" ); if not is_static && (is_gc_element ctx tcpp) then begin - let getPtr = match tcpp with | TCppString -> ".__s" | _ -> ".mPtr" in + let getPtr = match tcpp with | TCppString -> ".raw_ref()" | _ -> ".mPtr" in output ("\t\tinline " ^ tcppStr ^ " _hx_set_" ^ remap_name ^ "(hx::StackContext *_hx_ctx," ^ tcppStr ^ " _hx_v) { HX_OBJ_WB(this,_hx_v" ^ getPtr ^ ") return " ^ remap_name ^ "=_hx_v; }\n"); end; @@ -4582,6 +4684,11 @@ let path_of_string path = *) let find_referenced_types_flags ctx obj field_name super_deps constructor_deps header_only for_depends include_super_args = let types = ref PMap.empty in + if for_depends then begin + let include_file = get_meta_string_path (t_infos obj).mt_meta Meta.Depend in + if (include_file<>"") then + types := (PMap.add ( path_of_string include_file ) true !types); + end; let rec add_type_flag isNative in_path = if ( not (PMap.mem in_path !types)) then begin types := (PMap.add in_path isNative !types); @@ -4736,7 +4843,7 @@ let find_referenced_types_flags ctx obj field_name super_deps constructor_deps h | _ -> () ); ) enum_def.e_constrs; if (not header_only) then begin - let meta = Codegen.build_metadata ctx.ctx_common (TEnumDecl enum_def) in + let meta = Texpr.build_metadata ctx.ctx_common.basic (TEnumDecl enum_def) in match meta with Some expr -> visit_params expr | _ -> (); end; in @@ -4971,6 +5078,7 @@ let generate_enum_files baseCtx enum_def super_deps meta = then 0 else 1 in let ctx = file_context baseCtx cpp_file debug false in + let strq = strq ctx.ctx_common in if (debug>1) then print_endline ("Found enum definition:" ^ (join_class_path class_path "::" )); @@ -5070,7 +5178,7 @@ let generate_enum_files baseCtx enum_def super_deps meta = output_cpp ("Dynamic __Create_" ^ class_name ^ "() { return new " ^ class_name ^ "; }\n\n"); output_cpp ("void " ^ class_name ^ "::__register()\n{\n"); - let text_name = str (join_class_path class_path ".") in + let text_name = strq (join_class_path class_path ".") in output_cpp ("\nhx::Static(__mClass) = hx::_hx_RegisterClass(" ^ text_name ^ ", hx::TCanCast< " ^ class_name ^ " >," ^ class_name ^ "_sStaticFields,0,\n"); output_cpp ("\t&__Create_" ^ class_name ^ ", &__Create,\n"); @@ -5092,7 +5200,7 @@ let generate_enum_files baseCtx enum_def super_deps meta = match constructor.ef_type with | TFun (_,_) -> () | _ -> - output_cpp ( (keyword_remap name) ^ " = hx::CreateConstEnum< " ^ class_name ^ " >(" ^ (str name) ^ "," ^ + output_cpp ( (keyword_remap name) ^ " = hx::CreateConstEnum< " ^ class_name ^ " >(" ^ (strq name) ^ "," ^ (string_of_int constructor.ef_index) ^ ");\n" ) ) enum_def.e_constrs; output_cpp ("}\n\n"); @@ -5115,6 +5223,8 @@ let generate_enum_files baseCtx enum_def super_deps meta = List.iter2 (fun r f -> gen_forward_decl h_file r f) referenced flags; + output_h ( get_code enum_def.e_meta Meta.HeaderCode ); + gen_open_namespace output_h class_path; output_h "\n\n"; @@ -5127,8 +5237,8 @@ let generate_enum_files baseCtx enum_def super_deps meta = output_h ("\t\tstatic void __boot();\n"); output_h ("\t\tstatic void __register();\n"); output_h ("\t\tstatic bool __GetStatic(const ::String &inName, Dynamic &outValue, hx::PropertyAccess inCallProp);\n"); - output_h ("\t\t::String GetEnumName( ) const { return " ^ (str (join_class_path class_path ".")) ^ "; }\n" ); - output_h ("\t\t::String __ToString() const { return " ^ (str (just_class_name ^ ".") )^ " + _hx_tag; }\n\n"); + output_h ("\t\t::String GetEnumName( ) const { return " ^ (strq (join_class_path class_path ".")) ^ "; }\n" ); + output_h ("\t\t::String __ToString() const { return " ^ (strq (just_class_name ^ ".") )^ " + _hx_tag; }\n\n"); PMap.iter (fun _ constructor -> @@ -5162,14 +5272,12 @@ let list_iteri func in_list = ;; let has_new_gc_references ctx class_def = - match class_def.cl_dynamic with - | Some _ -> true - | _ -> ( + ( let is_gc_reference field = (should_implement_field field) && (is_data_member field) && not (ctx_cant_be_null ctx field.cf_type) in List.exists is_gc_reference class_def.cl_ordered_fields - ) + ) ;; @@ -5225,7 +5333,7 @@ let is_writable class_def field = let statics_except_meta class_def = (List.filter (fun static -> static.cf_name <> "__meta__" && static.cf_name <> "__rtti") class_def.cl_ordered_statics);; let has_set_member_field class_def = - implement_dynamic_here class_def || ( + ( let reflect_fields = List.filter (reflective class_def) (class_def.cl_ordered_fields) in let reflect_writable = List.filter (is_writable class_def) reflect_fields in List.exists variable_field reflect_writable @@ -5241,14 +5349,14 @@ let has_set_static_field class_def = let has_get_fields class_def = - implement_dynamic_here class_def || ( + ( let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in List.exists is_data_field class_def.cl_ordered_fields ) ;; let has_get_member_field class_def = - implement_dynamic_here class_def || ( + ( let reflect_fields = List.filter (reflective class_def) (class_def.cl_ordered_fields) in List.exists (is_readable class_def) reflect_fields ) @@ -5260,6 +5368,9 @@ let has_get_static_field class_def = List.exists (is_readable class_def) reflect_fields ;; +let has_compare_field class_def = + List.exists (fun f -> f.cf_name="__compare") class_def.cl_ordered_fields +;; let has_boot_field class_def = @@ -5328,11 +5439,13 @@ let script_type t optional = if optional then begin | _ -> "Object" end else match type_string t with | "bool" -> "Int" - | "int" -> "Int" + | "int" | "::cpp::Int32" -> "Int" | "Float" -> "Float" | "::String" -> "String" | "Null" -> "Void" | "Void" -> "Void" + | "float" | "::cpp::Float32" | "::cpp::Float64" -> "Float" + | "::cpp::Int64" | "::cpp::UInt64" -> "Object" | _ -> "Object" ;; @@ -5494,7 +5607,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta let classIdTxt = Printf.sprintf "0x%08lx" classId in (* Config *) - let implement_dynamic = implement_dynamic_here class_def in let override_iteration = (not nativeGen) && (has_new_gc_references baseCtx class_def) in let dynamic_interface_closures = (Common.defined baseCtx.ctx_common Define.DynamicInterfaceClosures) in @@ -5574,43 +5686,49 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta let isContainer = if (has_gc_references common_ctx class_def) then "true" else "false" in + let can_quick_alloc = can_quick_alloc class_def in + let outputConstructor ctx out isHeader = let classScope = if isHeader then "" else class_name ^ "::" in - out (ptr_name ^ " " ^ classScope ^ "__new(" ^constructor_type_args ^") {\n"); + let staticHead = if isHeader then "inline static " else "" in + out (staticHead ^ ptr_name ^ " " ^ classScope ^ "__new(" ^constructor_type_args ^") {\n"); out ("\t" ^ ptr_name ^ " __this = new " ^ class_name ^ "();\n"); out ("\t__this->__construct(" ^ constructor_args ^ ");\n"); out ("\treturn __this;\n"); out ("}\n\n"); - out ((if isHeader then "static " else "") ^ ptr_name ^ " " ^ classScope ^ "__alloc(hx::Ctx *_hx_ctx" ^ (if constructor_type_args="" then "" else "," ^constructor_type_args) ^") {\n"); - out ("\t" ^ class_name ^ " *__this = (" ^ class_name ^ "*)(hx::Ctx::alloc(_hx_ctx, sizeof(" ^ class_name ^ "), " ^ isContainer ^", " ^ gcName ^ "));\n"); - out ("\t*(void **)__this = " ^ class_name ^ "::_hx_vtable;\n"); - let rec dump_dynamic class_def = - if has_dynamic_member_functions class_def then - out ("\t" ^ (join_class_path_remap class_def.cl_path "::") ^ "_obj::__alloc_dynamic_functions(_hx_ctx,__this);\n") - else match class_def.cl_super with - | Some super -> dump_dynamic (fst super) - | _ -> () - in - dump_dynamic class_def; - - if isHeader then begin - match class_def.cl_constructor with - | Some ( { cf_expr = Some ( { eexpr = TFunction(function_def) } ) } as definition ) -> - let old_debug = ctx.ctx_debug_level in - if has_meta_key definition.cf_meta Meta.NoDebug then - ctx.ctx_debug_level <- 0; - ctx.ctx_real_this_ptr <- false; - gen_cpp_function_body ctx class_def false "new" function_def "" "" (has_meta_key definition.cf_meta Meta.NoDebug); - out "\n"; - - ctx.ctx_debug_level <- old_debug; - | _ -> () - end else - out ("\t__this->__construct(" ^ constructor_args ^ ");\n"); + if can_quick_alloc then begin + out (staticHead ^ ptr_name ^ " " ^ classScope ^ "__alloc(hx::Ctx *_hx_ctx" ^ + (if constructor_type_args="" then "" else "," ^constructor_type_args) ^") {\n"); + out ("\t" ^ class_name ^ " *__this = (" ^ class_name ^ "*)(hx::Ctx::alloc(_hx_ctx, sizeof(" ^ class_name ^ "), " ^ isContainer ^", " ^ gcName ^ "));\n"); + out ("\t*(void **)__this = " ^ class_name ^ "::_hx_vtable;\n"); + let rec dump_dynamic class_def = + if has_dynamic_member_functions class_def then + out ("\t" ^ (join_class_path_remap class_def.cl_path "::") ^ "_obj::__alloc_dynamic_functions(_hx_ctx,__this);\n") + else match class_def.cl_super with + | Some super -> dump_dynamic (fst super) + | _ -> () + in + dump_dynamic class_def; + + if isHeader then begin + match class_def.cl_constructor with + | Some ( { cf_expr = Some ( { eexpr = TFunction(function_def) } ) } as definition ) -> + let old_debug = ctx.ctx_debug_level in + if has_meta_key definition.cf_meta Meta.NoDebug then + ctx.ctx_debug_level <- 0; + ctx.ctx_real_this_ptr <- false; + gen_cpp_function_body ctx class_def false "new" function_def "" "" (has_meta_key definition.cf_meta Meta.NoDebug); + out "\n"; + + ctx.ctx_debug_level <- old_debug; + | _ -> () + end else + out ("\t__this->__construct(" ^ constructor_args ^ ");\n"); - out ("\treturn __this;\n"); - out ("}\n\n"); + out ("\treturn __this;\n"); + out ("}\n\n"); + end; in (* State *) @@ -5629,6 +5747,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta (*let cpp_file = new_cpp_file common_ctx.file class_path in*) let ctx = cpp_ctx in let output_cpp = (cpp_file#write) in + let strq = strq ctx.ctx_common in let class_super_name = (match class_def.cl_super with | Some (klass, params) -> (tcpp_to_string_suffix "_obj" (cpp_instance_type ctx klass params) ) @@ -5732,17 +5851,19 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta *) let castKey = if interface_name="_hx_haxe_IMap" && realName="set" then castKey ^ "*" else castKey in let implementationKey = realName ^ "::" ^ class_implementation in - if castKey <> implementationKey && not (Hashtbl.mem alreadyGlued castKey) then begin - Hashtbl.replace alreadyGlued castKey (); + if castKey <> implementationKey then begin let glue = Printf.sprintf "%s_%08lx" field.cf_name (gen_hash32 0 cast) in - let argList = ctx_tfun_arg_list ctx true args in - let returnType = ctx_type_string ctx return_type in - let returnStr = if returnType="void" then "" else "return " in - let cppCode = returnType ^ " " ^ class_name ^ "::" ^ glue ^ "(" ^ argList ^ ") {\n" ^ - "\t\t\t" ^ returnStr ^ realName ^ "(" ^ cpp_arg_names args ^ ");\n}\n" in - let headerCode = "\t\t" ^ returnType ^ " " ^ glue ^ "(" ^ argList ^ ");\n" in - header_glue := headerCode :: !header_glue; - cpp_glue := cppCode :: !cpp_glue; + if not (Hashtbl.mem alreadyGlued castKey) then begin + Hashtbl.replace alreadyGlued castKey (); + let argList = ctx_tfun_arg_list ctx true args in + let returnType = ctx_type_string ctx return_type in + let returnStr = if returnType="void" then "" else "return " in + let cppCode = returnType ^ " " ^ class_name ^ "::" ^ glue ^ "(" ^ argList ^ ") {\n" ^ + "\t\t\t" ^ returnStr ^ realName ^ "(" ^ cpp_arg_names args ^ ");\n}\n" in + let headerCode = "\t\t" ^ returnType ^ " " ^ glue ^ "(" ^ argList ^ ");\n" in + header_glue := headerCode :: !header_glue; + cpp_glue := cppCode :: !cpp_glue; + end; output_cpp (" " ^ cast ^ "&" ^ implname ^ "::" ^ glue ^ ",\n"); end else output_cpp (" " ^ cast ^ "&" ^ implname ^ "::" ^ realName ^ ",\n"); @@ -5791,7 +5912,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta | _ -> ()); - let dump_field_name = (fun field -> output_cpp ("\t" ^ (str field.cf_name) ^ ",\n")) in + let dump_field_name = (fun field -> output_cpp ("\t" ^ (strq field.cf_name) ^ ",\n")) in List.iter (gen_field ctx class_def class_name smart_class_name dot_name false class_def.cl_interface) @@ -5855,8 +5976,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta (* MARK function - explicitly mark all child pointers *) output_cpp ("void " ^ class_name ^ "::__Mark(HX_MARK_PARAMS)\n{\n"); output_cpp ("\tHX_MARK_BEGIN_CLASS(" ^ smart_class_name ^ ");\n"); - if (implement_dynamic) then - output_cpp "\tHX_MARK_DYNAMIC;\n"; List.iter (dump_field_iterator "HX_MARK_MEMBER_NAME") implemented_instance_fields; (match super_needs_iteration with | "" -> () @@ -5866,8 +5985,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta (* Visit function - explicitly visit all child pointers *) output_cpp ("void " ^ class_name ^ "::__Visit(HX_VISIT_PARAMS)\n{\n"); - if (implement_dynamic) then - output_cpp "\tHX_VISIT_DYNAMIC;\n"; List.iter (dump_field_iterator "HX_VISIT_MEMBER_NAME") implemented_instance_fields; (match super_needs_iteration with | "" -> () @@ -5888,7 +6005,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta output_cpp ("\tcase " ^ (string_of_int l) ^ ":\n"); len_case := l; end; - output_cpp ("\t\tif (HX_FIELD_EQ(inName,\"" ^ (Ast.s_escape field) ^ "\") ) { " ^ result ^ " }\n"); + output_cpp ("\t\tif (HX_FIELD_EQ(inName,\"" ^ (StringHelper.s_escape field) ^ "\") ) { " ^ result ^ " }\n"); ) sfields; output_cpp "\t}\n"; end; @@ -5929,8 +6046,6 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta ) ) ) in dump_quick_field_test (get_field_dat reflect_member_readable); - if (implement_dynamic) then - output_cpp "\tHX_CHECK_DYNAMIC_GET_FIELD(inName);\n"; output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n"); end; @@ -5985,12 +6100,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta ) in dump_quick_field_test (set_field_dat reflect_write_member_variables); - if (implement_dynamic) then begin - output_cpp ("\ttry { return super::__SetField(inName,inValue,inCallProp); }\n"); - output_cpp ("\tcatch(Dynamic e) { HX_DYNAMIC_SET_FIELD(inName,inValue); }\n"); - output_cpp "\treturn inValue;\n}\n\n"; - end else - output_cpp ("\treturn super::__SetField(inName,inValue,inCallProp);\n}\n\n"); + output_cpp ("\treturn super::__SetField(inName,inValue,inCallProp);\n}\n\n"); end; if (has_set_static_field class_def) then begin @@ -6022,36 +6132,35 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta (* For getting a list of data members (eg, for serialization) *) if (has_get_fields class_def) then begin let append_field = - (fun field -> output_cpp ("\toutFields->push(" ^( str field.cf_name )^ ");\n")) in + (fun field -> output_cpp ("\toutFields->push(" ^( strq field.cf_name )^ ");\n")) in let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in output_cpp ("void " ^ class_name ^ "::__GetFields(Array< ::String> &outFields)\n{\n"); List.iter append_field (List.filter is_data_field class_def.cl_ordered_fields); - if (implement_dynamic) then - output_cpp "\tHX_APPEND_DYNAMIC_FIELDS(outFields);\n"; output_cpp "\tsuper::__GetFields(outFields);\n"; output_cpp "};\n\n"; end; - let storage field = match type_string field.cf_type with - | "bool" -> "hx::fsBool" - | "int" -> "hx::fsInt" - | "Float" -> "hx::fsFloat" - | "::String" -> "hx::fsString" - | str -> "hx::fsObject" ^ " /*" ^ str ^ "*/ " + let storage field = match (cpp_type_of ctx field.cf_type) with + | TCppScalar("bool") -> "hx::fsBool" + | TCppScalar("int") -> "hx::fsInt" + | TCppScalar("Float") -> "hx::fsFloat" + | TCppString -> "hx::fsString" + | o when is_object_element ctx o -> "hx::fsObject" ^ " /* " ^ (tcpp_to_string o ) ^ " */ " + | u -> "hx::fsUnknown" ^ " /* " ^ (tcpp_to_string u) ^ " */ " in let dump_member_storage = (fun field -> output_cpp ("\t{" ^ (storage field) ^ ",(int)offsetof(" ^ class_name ^"," ^ (keyword_remap field.cf_name) ^")," ^ - (str field.cf_name) ^ "},\n") + (strq field.cf_name) ^ "},\n") ) in let dump_static_storage = (fun field -> output_cpp ("\t{" ^ (storage field) ^ ",(void *) &" ^ class_name ^"::" ^ (keyword_remap field.cf_name) ^"," ^ - (str field.cf_name) ^ "},\n") + (strq field.cf_name) ^ "},\n") ) in - output_cpp "#if HXCPP_SCRIPTABLE\n"; + output_cpp "#ifdef HXCPP_SCRIPTABLE\n"; let stored_fields = List.filter is_data_member implemented_instance_fields in if ( (List.length stored_fields) > 0) then begin @@ -6107,22 +6216,38 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta let generate_script_function isStatic field scriptName callName = match follow field.cf_type with | TFun (args,return_type) when not (is_data_member field) -> + let isTemplated = not isStatic && not class_def.cl_interface in + if isTemplated then output_cpp ("\ntemplate"); output_cpp ("\nstatic void CPPIA_CALL " ^ scriptName ^ "(hx::CppiaCtx *ctx) {\n"); - let ret = script_signature return_type false in + let ret = match cpp_type_of ctx return_type with TCppScalar("bool") -> "b" | _ -> script_signature return_type false in if (ret<>"v") then output_cpp ("ctx->return" ^ (script_type return_type false) ^ "("); - if class_def.cl_interface then begin - output_cpp (class_name ^ "::" ^ callName ^ "(ctx->getThis()" ^ (if (List.length args) > 0 then "," else "")); - end else if isStatic then - output_cpp (class_name ^ "::" ^ callName ^ "(") - else - output_cpp ("((" ^ class_name ^ "*)ctx->getThis())->" ^ callName ^ "("); - let (signature,_,_) = List.fold_left (fun (signature,sep,size) (_,opt,t) -> - output_cpp (sep ^ "ctx->get" ^ (script_type t opt) ^ "(" ^ size ^ ")"); - (signature ^ (script_signature t opt ), ",", (size^"+sizeof(" ^ (script_size_type t opt) ^ ")") ) ) (ret,"","sizeof(void*)") args + + let dump_call cast = + if class_def.cl_interface then begin + output_cpp (class_name ^ "::" ^ callName ^ "(ctx->getThis()" ^ (if (List.length args) > 0 then "," else "")); + end else if isStatic then + output_cpp (class_name ^ "::" ^ callName ^ "(") + else + output_cpp ("((" ^ class_name ^ "*)ctx->getThis())->" ^ cast ^ callName ^ "("); + + let (signature,_,_) = List.fold_left (fun (signature,sep,size) (_,opt,t) -> + output_cpp (sep ^ "ctx->get" ^ (script_type t opt) ^ "(" ^ size ^ ")"); + (signature ^ (script_signature t opt ), ",", (size^"+sizeof(" ^ (script_size_type t opt) ^ ")") ) ) (ret,"","sizeof(void*)") args + in + output_cpp ")"; + signature + in + let signature = + if isTemplated then begin + output_cpp (" _HX_SUPER ? "); + ignore( dump_call (class_name ^ "::") ); + output_cpp (" : "); + dump_call "" + end else + dump_call ""; in - output_cpp ")"; if (ret<>"v") then output_cpp (")"); output_cpp (";\n}\n"); signature; @@ -6187,7 +6312,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta let new_sctipt_functions = if newInteface then all_virtual_functions class_def else - current_virtual_functions class_def + List.rev (current_virtual_functions_rev class_def []) in let sctipt_name = class_name ^ "__scriptable" in @@ -6206,8 +6331,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta output_cpp (" HX_DEFINE_SCRIPTABLE_INTERFACE\n") else begin output_cpp (" HX_DEFINE_SCRIPTABLE(HX_ARR_LIST" ^ (string_of_int (List.length constructor_var_list) ) ^ ")\n"); - if (not implement_dynamic) then - output_cpp "\tHX_DEFINE_SCRIPTABLE_DYNAMIC;\n"; + output_cpp "\tHX_DEFINE_SCRIPTABLE_DYNAMIC;\n"; end; end; @@ -6231,14 +6355,20 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta in List.iter dump_script_static class_def.cl_ordered_statics; + output_cpp "#ifndef HXCPP_CPPIA_SUPER_ARG\n"; + output_cpp "#define HXCPP_CPPIA_SUPER_ARG(x)\n"; + output_cpp "#endif\n"; output_cpp "static hx::ScriptNamedFunction __scriptableFunctions[] = {\n"; let dump_func f isStaticFlag = let s = try Hashtbl.find sigs f.cf_name with Not_found -> "v" in - output_cpp (" hx::ScriptNamedFunction(\"" ^ f.cf_name ^ "\",__s_" ^ f.cf_name ^ ",\"" ^ s ^ "\", " ^ isStaticFlag ^ " ),\n" ) + output_cpp (" hx::ScriptNamedFunction(\"" ^ f.cf_name ^ "\",__s_" ^ f.cf_name ^ ",\"" ^ s ^ "\", " ^ isStaticFlag ^ " " ); + let superCall = if (isStaticFlag="true") || class_def.cl_interface then "0" else ("__s_" ^ f.cf_name ^ "") in + output_cpp ("HXCPP_CPPIA_SUPER_ARG(" ^ superCall ^")" ); + output_cpp (" ),\n" ) in List.iter (fun (f,_,_) -> dump_func f "false") new_sctipt_functions; List.iter (fun f -> dump_func f "true") static_functions; - output_cpp " hx::ScriptNamedFunction(0,0,0) };\n"; + output_cpp " hx::ScriptNamedFunction(0,0,0 HXCPP_CPPIA_SUPER_ARG(0) ) };\n"; end else output_cpp "static hx::ScriptNamedFunction *__scriptableFunctions = 0;\n"; @@ -6284,7 +6414,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta output_cpp ("\t" ^ class_name ^ " _hx_dummy;\n"); output_cpp ("\t" ^ class_name ^ "::_hx_vtable = *(void **)&_hx_dummy;\n"); output_cpp ("\thx::Static(__mClass) = new hx::Class_obj();\n"); - output_cpp ("\t__mClass->mName = " ^ (str class_name_text) ^ ";\n"); + output_cpp ("\t__mClass->mName = " ^ (strq class_name_text) ^ ";\n"); output_cpp ("\t__mClass->mSuper = &super::__SGetClass();\n"); output_cpp ("\t__mClass->mConstructEmpty = &__CreateEmpty;\n"); output_cpp ("\t__mClass->mConstructArgs = &__Create;\n"); @@ -6314,7 +6444,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta output_cpp ("void " ^ class_name ^ "::__register()\n{\n"); output_cpp ("\thx::Static(__mClass) = new hx::Class_obj();\n"); - output_cpp ("\t__mClass->mName = " ^ (str class_name_text) ^ ";\n"); + output_cpp ("\t__mClass->mName = " ^ (strq class_name_text) ^ ";\n"); output_cpp ("\t__mClass->mSuper = &super::__SGetClass();\n"); if hasMarkFunc then output_cpp ("\t__mClass->mMarkFunc = " ^ class_name ^ "_sMarkStatics;\n"); @@ -6367,6 +6497,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta let h_file = new_header_file common_ctx common_ctx.file class_path in let ctx = file_context baseCtx h_file debug true in + let strq = strq ctx.ctx_common in let parent,super = match class_def.cl_super with @@ -6456,7 +6587,9 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta outputConstructor ctx (fun str -> output_h ("\t\t" ^ str) ) true end else begin output_h ("\t\tstatic " ^ptr_name^ " __new(" ^constructor_type_args ^");\n"); - output_h ("\t\tstatic " ^ptr_name^ " __alloc(hx::Ctx *_hx_ctx" ^ (if constructor_type_args="" then "" else "," ^constructor_type_args) ^");\n"); + if can_quick_alloc then + output_h ("\t\tstatic " ^ptr_name^ " __alloc(hx::Ctx *_hx_ctx" ^ + (if constructor_type_args="" then "" else "," ^constructor_type_args) ^");\n"); end; output_h ("\t\tstatic void * _hx_vtable;\n"); output_h ("\t\tstatic Dynamic __CreateEmpty();\n"); @@ -6478,8 +6611,10 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta if (has_get_fields class_def) then output_h ("\t\tvoid __GetFields(Array< ::String> &outFields);\n"); - if (implement_dynamic) then - output_h ("\t\tHX_DECLARE_IMPLEMENT_DYNAMIC;\n"); + if (has_compare_field class_def) then + output_h ("\t\tint __Compare(const hx::Object *inRHS) const { " ^ + "return const_cast<" ^ class_name ^ " *>(this)->__compare(Dynamic((hx::Object *)inRHS)); }\n"); + output_h ("\t\tstatic void __register();\n"); if (override_iteration) then begin output_h ("\t\tvoid __Mark(HX_MARK_PARAMS);\n"); @@ -6512,7 +6647,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta if (has_init_field class_def) then output_h "\t\tstatic void __init__();\n\n"; - output_h ("\t\t::String __ToString() const { return " ^ (str smart_class_name) ^ "; }\n\n"); + output_h ("\t\t::String __ToString() const { return " ^ (strq smart_class_name) ^ "; }\n\n"); end else if not nativeGen then begin output_h ("\t\tHX_DO_INTERFACE_RTTI;\n\n"); end else begin @@ -6558,8 +6693,8 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta generate_class_header () ;; -let generate_class_deps ctx class_def super_deps constructor_deps = - find_referenced_types ctx (TClassDecl class_def) super_deps constructor_deps false true false +let generate_class_deps ctx class_def super_deps constructor_deps scriptable = + find_referenced_types ctx (TClassDecl class_def) super_deps constructor_deps false true scriptable ;; @@ -6574,7 +6709,7 @@ let write_resources common_ctx = let resource_file = new_cpp_file common_ctx common_ctx.file (["resources"],id) in resource_file#write "namespace hx {\n"; resource_file#write_i ("unsigned char " ^ id ^ "[] = {\n"); - resource_file#write_i "0xff, 0xff, 0xff, 0xff,\n"; + resource_file#write_i "0x80, 0x00, 0x00, 0x80,\n"; for i = 0 to String.length data - 1 do let code = Char.code (String.unsafe_get data i) in resource_file#write (Printf.sprintf "%d," code); @@ -6606,7 +6741,7 @@ let write_resources common_ctx = Hashtbl.iter (fun name data -> let id = "__res_" ^ (string_of_int !idx) in resource_file#write_i - ("{ " ^ (str name) ^ "," ^ (string_of_int (String.length data)) ^ "," ^ + ("{ " ^ (strq common_ctx name) ^ "," ^ (string_of_int (String.length data)) ^ "," ^ "hx::" ^ id ^ " + 4 },\n"); incr idx; ) common_ctx.resources; @@ -6645,8 +6780,8 @@ let write_build_data common_ctx filename classes main_deps boot_deps build_extra in output_string buildfile "\n"; - output_string buildfile ("\n"); + let api_string = (Common.defined_value common_ctx Define.HxcppApiLevel) in + output_string buildfile ("\n"); output_string buildfile "\n"; output_string buildfile "\n"; List.iter add_classdef_to_buildfile classes; @@ -6678,6 +6813,8 @@ let write_build_data common_ctx filename classes main_deps boot_deps build_extra output_string buildfile ("\n"); output_string buildfile "\n"; output_string buildfile build_extra; + if (Common.defined common_ctx Define.HxcppSmartStings) then + output_string buildfile ("\n"); output_string buildfile "\n"; close_out buildfile;; @@ -7238,15 +7375,10 @@ class script_writer ctx filename asciiOut = this#begin_expr; this#writePos function_def.tf_expr; this#write ( (this#op IaFun) ^ (this#typeText function_def.tf_type) ^ (string_of_int (List.length args)) ^ "\n" ); - List.iter (fun(arg,init) -> - this#write (indent ^ indent_str ); - this#writeVar arg; - match init with - | Some const -> this#write ("1 " ^ (this#constText const) ^ "\n") - | _ -> this#write "0\n"; - ) function_def.tf_args; + let close = this#gen_func_args function_def.tf_args in this#gen_expression_tree cppExpr; this#end_expr; + close() end else this#gen_expression e | _ -> print_endline ("Missing function body for " ^ funcName ); @@ -7339,25 +7471,72 @@ class script_writer ctx filename asciiOut = this#gen_expression expr; end + method gen_func_args args = + let gen_inits = ref [] in + List.iter (fun(arg,init) -> + this#write (indent ^ indent_str ); + this#writeVar arg; + match init with + | Some ({eexpr = TConst TNull}) -> this#write "0\n" + | Some const -> + let argType = (cpp_type_of ctx const.etype) in + if (is_cpp_scalar argType || argType==TCppString ) then begin + this#write ("1 "); + this#gen_expression_only const; + this#write "\n"; + end else begin + gen_inits := (arg, const) :: !gen_inits; + this#write "0\n"; + end + | _ -> this#write "0\n"; + ) args; + + if (List.length !gen_inits)==0 then begin + fun () -> ( ) + end else begin + this#begin_expr; + this#writePos (snd (List.hd !gen_inits) ); + this#writeList (this#op IaBlock) ((List.length !gen_inits) + 1); + List.iter (fun(arg,const) -> + let start_expr( ) = this#begin_expr; this#writePos const; in + let local_var( ) = + this#begin_expr; + this#writePos const; + this#write ((this#op IaVar) ^ (string_of_int arg.v_id) ^ (this#commentOf arg.v_name) ); + this#end_expr; + in + + start_expr(); + this#writeOpLine IaIf; + start_expr(); + this#writeOpLine IaIsNull; + local_var(); + this#end_expr; + start_expr(); + this#writeOpLine IaSet; + local_var(); + this#gen_expression const; + this#end_expr; + this#begin_expr; + ) !gen_inits; + fun () -> this#end_expr; + end + method gen_expression expr = + this#begin_expr; + this#writePos expr; + this#gen_expression_only expr; + this#end_expr; - method gen_expression expr = (* { *) + method gen_expression_only expr = (* { *) let expression = remove_parens expr in - this#begin_expr; - (*this#write ( (this#fileText expression.epos.pfile) ^ "\t" ^ (string_of_int (Lexer.get_error_line expression.epos) ) ^ indent);*) - this#writePos expression; (match expression.eexpr with | TFunction function_def -> this#write ( (this#op IaFun) ^ (this#typeText function_def.tf_type) ^ (string_of_int (List.length function_def.tf_args)) ^ "\n" ); - List.iter (fun(arg,init) -> - this#write (indent ^ indent_str ); - this#writeVar arg; - match init with - | Some const -> this#write ("1 " ^ (this#constText const) ^ "\n") - | _ -> this#write "0\n"; - ) function_def.tf_args; + let close = this#gen_func_args function_def.tf_args in let pop = this#pushReturn function_def.tf_type in this#gen_expression function_def.tf_expr; pop (); + close() | TBlock expr_list -> this#writeList (this#op IaBlock) (List.length expr_list); List.iter this#gen_expression expr_list; | TConst const -> this#write (this#constText const) @@ -7593,7 +7772,6 @@ class script_writer ctx filename asciiOut = | TMeta(_,_) -> abort "Unexpected meta" expression.epos | TIdent _ -> abort "Unexpected ident" expression.epos ); - this#end_expr; (* } *) method gen_expression_tree expression_tree = (* { *) let rec gen_expression expression = @@ -7784,14 +7962,9 @@ class script_writer ctx filename asciiOut = | CppClosure closure -> this#write ( (this#op IaFun) ^ (this#astType closure.close_type) ^ (string_of_int (List.length closure.close_args)) ^ "\n" ); - List.iter (fun(arg,init) -> - this#write (indent ^ indent_str ); - this#writeVar arg; - match init with - | Some const -> this#write ("1 " ^ (this#constText const) ^ "\n") - | _ -> this#write "0\n"; - ) closure.close_args; + let close = this#gen_func_args closure.close_args in gen_expression closure.close_expr; + close() | CppObjectDecl (values,isStruct) ->this#write ( (this#op IaObjDef) ^ (string_of_int (List.length values))); this#write " "; @@ -7875,6 +8048,10 @@ class script_writer ctx filename asciiOut = this#writeOpLine IaCastInt; gen_expression expr; + | CppCastScalar(expr,"Float") -> + this#write ((this#op IaTCast) ^ (this#astType (TCppScalar("Float"))) ^ "\n"); + gen_expression expr; + | CppCastScalar(expr,_) -> match_expr expr | CppCastVariant(expr) -> match_expr expr | CppCastStatic(expr,_) -> match_expr expr @@ -7983,7 +8160,6 @@ let generate_script_class common_ctx script class_def = script#write ((string_of_int ( (List.length ordered_fields) + (List.length ordered_statics) + (match class_def.cl_constructor with Some _ -> 1 | _ -> 0 ) + - (if (implement_dynamic_here class_def) then 1 else 0) + (match class_def.cl_init with Some _ -> 1 | _ -> 0 ) ) ) ^ "\n"); @@ -8024,8 +8200,6 @@ let generate_script_class common_ctx script class_def = List.iter (generate_field false) ordered_fields; List.iter (generate_field true) ordered_statics; - if (implement_dynamic_here class_def) then - script#implDynamic; script#write "\n"; ;; @@ -8076,7 +8250,7 @@ let generate_cppia ctx = if (is_internal) then (if (debug>=4) then print_endline (" internal enum " ^ (join_class_path enum_def.e_path ".") )) else begin - let meta = Codegen.build_metadata common_ctx object_def in + let meta = Texpr.build_metadata common_ctx.basic object_def in if (enum_def.e_extern) then (if (debug>=4) then print_endline ("external enum " ^ (join_class_path enum_def.e_path ".") )); generate_script_enum common_ctx script enum_def meta @@ -8160,7 +8334,7 @@ let generate_source ctx = else if not (has_meta_key class_def.cl_meta Meta.NativeGen) then nonboot_classes := class_def.cl_path :: !nonboot_classes; jobs := (fun () -> generate_class_files ctx super_deps constructor_deps class_def scriptable ) :: !jobs; - let deps = generate_class_deps ctx class_def super_deps constructor_deps in + let deps = generate_class_deps ctx class_def super_deps constructor_deps scriptable in if not (class_def.cl_interface && (is_native_gen_class class_def)) then exe_classes := (class_def.cl_path, deps, object_def) :: !exe_classes; end @@ -8171,7 +8345,7 @@ let generate_source ctx = if (is_internal) then (if (debug>1) then print_endline (" internal enum " ^ name )) else begin - let meta = Codegen.build_metadata common_ctx object_def in + let meta = Texpr.build_metadata common_ctx.basic object_def in if (enum_def.e_extern) then (if (debug>1) then print_endline ("external enum " ^ name )); boot_enums := enum_def.e_path :: !boot_enums; @@ -8260,7 +8434,7 @@ let generate_source ctx = | _ -> cmd_defines := !cmd_defines ^ " -D" ^ name ^ "=\"" ^ (escape_command value) ^ "\"" ) common_ctx.defines.Define.values; write_build_options common_ctx (common_ctx.file ^ "/Options.txt") common_ctx.defines.Define.values; if ( not (Common.defined common_ctx Define.NoCompilation) ) then begin - let t = Common.timer ["generate";"cpp";"native compilation"] in + let t = Timer.timer ["generate";"cpp";"native compilation"] in let old_dir = Sys.getcwd() in Sys.chdir common_ctx.file; let cmd = ref "haxelib run hxcpp Build.xml haxe" in diff --git a/src/generators/gencs.ml b/src/generators/gencs.ml index 8db11566257..27cc5b7681a 100644 --- a/src/generators/gencs.ml +++ b/src/generators/gencs.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -25,10 +25,25 @@ open Type open Gencommon open Gencommon.SourceWriter open Codegen +open Texpr.Builder open Printf open Option open ExtString +type cs_native_constraint = + | CsStruct + | CsClass + | CsUnmanaged + | CsConstructible + | CsConstraint of string + +let get_constraint = function + | CsStruct -> "struct" + | CsClass -> "class" + | CsUnmanaged -> "unmanaged" + | CsConstructible -> "new()" + | CsConstraint s -> s + let rec is_cs_basic_type t = match follow t with | TInst( { cl_path = (["haxe"], "Int32") }, [] ) @@ -45,7 +60,7 @@ let rec is_cs_basic_type t = true | TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> is_cs_basic_type (Abstract.get_underlying_type a pl) - | TEnum(e, _) when not (Meta.has Meta.Class e.e_meta) -> true + | TEnum(e, _) as t when not (is_hxgen_t t) -> true | TInst(cl, _) when Meta.has Meta.Struct cl.cl_meta -> true | _ -> false @@ -133,6 +148,62 @@ let rec change_md = function TAbstractDecl a | md -> md +(** + Generates method overloads for a method with trailing optional arguments. + E.g. for `function method(a:Int, b:Bool = false) {...}` + generates `function method(a:Int) { method(a, false); }` +*) +let get_overloads_for_optional_args gen cl cf is_static = + match cf.cf_params,cf.cf_kind with + | [],Method (MethNormal | MethDynamic | MethInline) -> + (match cf.cf_expr, follow cf.cf_type with + | Some ({ eexpr = TFunction fn } as method_expr), TFun (args, return_type) -> + let type_params = List.map snd cl.cl_params in + let rec collect_overloads tf_args_rev args_rev default_values_rev = + match tf_args_rev, args_rev with + | (_, Some default_value) :: rest_tf_args_rev, _ :: rest_args_rev -> + let field_expr = + let cl_type = TInst (cl,type_params) in + if cf.cf_name = "new" then + mk (TConst TThis) cl_type cf.cf_pos + else if is_static then + let class_expr = + mk (TTypeExpr (TClassDecl cl)) cl_type cf.cf_pos + in + mk (TField (class_expr, FStatic(cl,cf))) cf.cf_type cf.cf_pos + else + let this_expr = + mk (TConst TThis) cl_type cf.cf_pos + in + mk (TField (this_expr, FInstance(cl,type_params,cf))) cf.cf_type cf.cf_pos + in + let default_values_rev = default_values_rev @ [default_value] in + let args_exprs = + List.rev ( + default_values_rev + @ (List.map (fun (v,_) -> mk_local v v.v_pos ) rest_tf_args_rev) + ) + in + let call = { fn.tf_expr with eexpr = TCall (field_expr, args_exprs) } in + let fn_body = + if ExtType.is_void (follow return_type) then call + else { fn.tf_expr with eexpr = TReturn (Some call) } + in + let fn = + { fn with tf_args = List.rev rest_tf_args_rev; tf_expr = mk_block fn_body } + in + { cf with + cf_overloads = []; + cf_type = TFun (List.rev rest_args_rev, return_type); + cf_expr = Some { method_expr with eexpr = TFunction fn }; + } :: collect_overloads rest_tf_args_rev rest_args_rev default_values_rev + | _ -> [] + in + collect_overloads (List.rev fn.tf_args) (List.rev args) [] + | _ -> [] + ) + | _ -> [] + (* used in c#-specific filters to skip some of them for the special haxe.lang.Runtime class *) let in_runtime_class gen = match gen.gcurrent_class with @@ -336,11 +407,11 @@ struct let configure gen runtime_cl = let basic = gen.gcon.basic in - let tchar = match ( get_type gen (["cs"], "Char16") ) with + (* let tchar = match ( get_type gen (["cs"], "Char16") ) with | TTypeDecl t -> TType(t,[]) | TAbstractDecl a -> TAbstract(a,[]) | _ -> assert false - in + in *) let string_ext = get_cl ( get_type gen (["haxe";"lang"], "StringExt")) in let ti64 = match ( get_type gen (["cs"], "Int64") ) with | TTypeDecl t -> TType(t,[]) | TAbstractDecl a -> TAbstract(a,[]) | _ -> assert false in let boxed_ptr = @@ -381,7 +452,7 @@ struct { e with eexpr = TField(run ef, FDynamic "ToUpperInvariant") } | TCall( { eexpr = TField(_, FStatic({ cl_path = [], "String" }, { cf_name = "fromCharCode" })) }, [cc] ) -> - { e with eexpr = TNew(get_cl_from_t basic.tstring, [], [mk_cast tchar (run cc); ExprBuilder.make_int gen.gcon 1 cc.epos]) } + { e with eexpr = TCall(mk_static_field_access_infer string_ext "fromCharCode" e.epos [], [run cc]) } | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charAt" as field) })) }, args ) | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charCodeAt" as field) })) }, args ) | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("indexOf" as field) })) }, args ) @@ -535,7 +606,7 @@ let add_cast_handler gen = epos = e.epos }; { - eexpr = TVar(i, Some( ExprBuilder.make_int gen.gcon (-1) e.epos )); + eexpr = TVar(i, Some( make_int gen.gcon.basic (-1) e.epos )); etype = basic.tvoid; epos = e.epos }; @@ -598,7 +669,8 @@ let add_cast_handler gen = } in - Hashtbl.add gen.gtparam_cast (["cs"], "NativeArray") gtparam_cast_native_array + Hashtbl.add gen.gtparam_cast (["cs"], "NativeArray") gtparam_cast_native_array; + Hashtbl.add gen.gtparam_cast (["haxe";"lang"], "Null") (fun e to_t -> mk_cast to_t e) (* end set gtparam_cast *) let connecting_string = "?" (* ? see list here http://www.fileformat.info/info/unicode/category/index.htm and here for C# http://msdn.microsoft.com/en-us/library/aa664670.aspx *) @@ -615,7 +687,7 @@ let reserved = let res = Hashtbl.create 120 in "stackalloc"; "static"; "string"; "struct"; "switch"; "this"; "throw"; "true"; "try"; "typeof"; "uint"; "ulong"; "unchecked"; "unsafe"; "ushort"; "using"; "virtual"; "volatile"; "void"; "while"; "add"; "ascending"; "by"; "descending"; "dynamic"; "equals"; "from"; "get"; "global"; "group"; "into"; "join"; "let"; "on"; "orderby"; "partial"; - "remove"; "select"; "set"; "value"; "var"; "where"; "yield"]; + "remove"; "select"; "set"; "value"; "var"; "where"; "yield"; "await"]; res let dynamic_anon = TAnon( { a_fields = PMap.empty; a_status = ref Closed } ) @@ -628,13 +700,13 @@ let rec get_class_modifiers meta cl_type cl_access cl_modifiers = | (Meta.Internal,[],_) :: meta -> get_class_modifiers meta cl_type "internal" cl_modifiers (* no abstract for now | (":abstract",[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("abstract" :: cl_modifiers) | (":static",[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("static" :: cl_modifiers) TODO: support those types *) - | (Meta.Final,[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("sealed" :: cl_modifiers) | (Meta.Unsafe,[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("unsafe" :: cl_modifiers) | _ :: meta -> get_class_modifiers meta cl_type cl_access cl_modifiers let rec get_fun_modifiers meta access modifiers = match meta with | [] -> access,modifiers + | (Meta.Private,[],_) :: meta -> get_fun_modifiers meta "private" modifiers | (Meta.Protected,[],_) :: meta -> get_fun_modifiers meta "protected" modifiers | (Meta.Internal,[],_) :: meta -> get_fun_modifiers meta "internal" modifiers | (Meta.ReadOnly,[],_) :: meta -> get_fun_modifiers meta access ("readonly" :: modifiers) @@ -734,9 +806,34 @@ let generate con = ns in + let change_class_field cl name = + let change_ctor name = if name = "new" then snd cl.cl_path else name in + let rec gen name = + let name = name ^ "_" ^ name in + if PMap.mem name cl.cl_fields || PMap.mem name cl.cl_statics then gen name + else name + in + change_id (if name = snd cl.cl_path then gen name else (change_ctor name)) + in + let change_enum_field enum name = + let rec gen name = + let name = name ^ "_" ^ name in + if PMap.mem name enum.e_constrs then gen name + else name + in + change_id (if name = snd enum.e_path then gen name else name) + in let change_field = change_id in let write_id w name = write w (change_id name) in + let write_class_field cl w name = write w (change_class_field cl name) in + let write_enum_field enum w name = write w (change_enum_field enum name) in let write_field w name = write w (change_field name) in + let get_write_field field_access = + match field_access with + | FInstance (cl,_,f) | FStatic (cl,f) | FClosure (Some (cl,_),f) -> write_class_field cl + | FEnum (enum,f) -> write_enum_field enum + | _ -> write_field + in let ptr = if Common.defined gen.gcon Define.Unsafe then @@ -821,60 +918,65 @@ let generate con = ) tl in - let rec real_type t = + let rec real_type stack t = let t = gen.gfollow#run_f t in - let ret = match t with - | TAbstract({ a_path = ([], "Null") }, [t]) -> - (* - Null<> handling is a little tricky. - It will only change to haxe.lang.Null<> when the actual type is non-nullable or a type parameter - It works on cases such as Hash returning Null since cast_detect will invoke real_type at the original type, - Null, which will then return the type haxe.lang.Null<> - *) - if erase_generics then - if is_cs_basic_type t then - t_dynamic + if List.exists (fast_eq t) stack then + t_dynamic + else begin + let stack = t :: stack in + let ret = match t with + | TAbstract({ a_path = ([], "Null") }, [t]) -> + (* + Null<> handling is a little tricky. + It will only change to haxe.lang.Null<> when the actual type is non-nullable or a type parameter + It works on cases such as Hash returning Null since cast_detect will invoke real_type at the original type, + Null, which will then return the type haxe.lang.Null<> + *) + if erase_generics then + if is_cs_basic_type t then + t_dynamic + else + real_type stack t else - real_type t - else - (match real_type t with - | TInst( { cl_kind = KTypeParameter _ }, _ ) -> TInst(null_t, [t]) - | t when is_cs_basic_type t -> TInst(null_t, [t]) - | _ -> real_type t) - | TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) -> - real_type (Abstract.get_underlying_type a pl) - | TAbstract ({ a_path = (["cs";"_Flags"], "EnumUnderlying") }, [t]) -> - real_type t - | TInst( { cl_path = (["cs";"system"], "String") }, [] ) -> - gen.gcon.basic.tstring; - | TInst( { cl_path = (["haxe"], "Int32") }, [] ) -> gen.gcon.basic.tint - | TInst( { cl_path = (["haxe"], "Int64") }, [] ) -> ti64 - | TAbstract( { a_path = [],"Class" }, _ ) - | TAbstract( { a_path = [],"Enum" }, _ ) - | TAbstract( { a_path = ["haxe";"extern"],"Rest" }, _ ) - | TInst( { cl_path = ([], "Class") }, _ ) - | TInst( { cl_path = ([], "Enum") }, _ ) -> TInst(ttype,[]) - | TInst( ({ cl_kind = KTypeParameter _ } as cl), _ ) when erase_generics && not (Meta.has Meta.NativeGeneric cl.cl_meta) -> - t_dynamic - | TInst({ cl_kind = KExpr _ }, _) -> t_dynamic - | TEnum(_, []) - | TInst(_, []) -> t - | TInst(cl, params) when - has_tdyn params && - Hashtbl.mem ifaces cl.cl_path -> - TInst(Hashtbl.find ifaces cl.cl_path, []) - | TEnum(e, params) -> - TEnum(e, List.map (fun _ -> t_dynamic) params) - | TInst(cl, params) when Meta.has Meta.Enum cl.cl_meta -> - TInst(cl, List.map (fun _ -> t_dynamic) params) - | TInst(cl, params) -> TInst(cl, change_param_type (TClassDecl cl) params) - | TAbstract _ - | TType _ -> t - | TAnon (anon) when (match !(anon.a_status) with | Statics _ | EnumStatics _ | AbstractStatics _ -> true | _ -> false) -> t - | TFun _ -> TInst(fn_cl,[]) - | _ -> t_dynamic - in - ret + (match real_type stack t with + | TInst( { cl_kind = KTypeParameter _ }, _ ) -> TInst(null_t, [t]) + | t when is_cs_basic_type t -> TInst(null_t, [t]) + | _ -> real_type stack t) + | TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) -> + real_type stack (Abstract.get_underlying_type a pl) + | TAbstract ({ a_path = (["cs";"_Flags"], "EnumUnderlying") }, [t]) -> + real_type stack t + | TInst( { cl_path = (["cs";"system"], "String") }, [] ) -> + gen.gcon.basic.tstring; + | TInst( { cl_path = (["haxe"], "Int32") }, [] ) -> gen.gcon.basic.tint + | TInst( { cl_path = (["haxe"], "Int64") }, [] ) -> ti64 + | TAbstract( { a_path = [],"Class" }, _ ) + | TAbstract( { a_path = [],"Enum" }, _ ) + | TAbstract( { a_path = ["haxe";"extern"],"Rest" }, _ ) + | TInst( { cl_path = ([], "Class") }, _ ) + | TInst( { cl_path = ([], "Enum") }, _ ) -> TInst(ttype,[]) + | TInst( ({ cl_kind = KTypeParameter _ } as cl), _ ) when erase_generics && not (Meta.has Meta.NativeGeneric cl.cl_meta) -> + t_dynamic + | TInst({ cl_kind = KExpr _ }, _) -> t_dynamic + | TEnum(_, []) + | TInst(_, []) -> t + | TInst(cl, params) when + has_tdyn params && + Hashtbl.mem ifaces cl.cl_path -> + TInst(Hashtbl.find ifaces cl.cl_path, []) + | TEnum(e, params) -> + TEnum(e, List.map (fun _ -> t_dynamic) params) + | TInst(cl, params) when Meta.has Meta.Enum cl.cl_meta -> + TInst(cl, List.map (fun _ -> t_dynamic) params) + | TInst(cl, params) -> TInst(cl, change_param_type stack (TClassDecl cl) params) + | TAbstract _ + | TType _ -> t + | TAnon (anon) when (match !(anon.a_status) with | Statics _ | EnumStatics _ | AbstractStatics _ -> true | _ -> false) -> t + | TFun _ -> TInst(fn_cl,[]) + | _ -> t_dynamic + in + ret + end and (* @@ -885,7 +987,7 @@ let generate con = To avoid confusion between Generic (which has a different meaning in hxcs AST), all those references are using dynamic_anon, which means Generic<{}> *) - change_param_type md tl = + change_param_type stack md tl = let types = match md with | TClassDecl c -> c.cl_params | TEnumDecl e -> [] @@ -894,7 +996,7 @@ let generate con = in let is_hxgeneric = if types = [] then is_hxgen md else (RealTypeParams.is_hxgeneric md) in let ret t = - let t_changed = real_type t in + let t_changed = real_type stack t in match is_hxgeneric, t_changed with | false, _ -> t (* @@ -902,6 +1004,7 @@ let generate con = Null<> type parameters will be transformed into Dynamic. *) | true, TInst ( { cl_path = (["haxe";"lang"], "Null") }, _ ) -> dynamic_anon + | true, TInst ( { cl_path = ([], "String") }, _ ) -> t | true, TInst ( { cl_kind = KTypeParameter _ }, _ ) -> t | true, TInst _ | true, TEnum _ @@ -916,6 +1019,9 @@ let generate con = List.map ret tl in + let real_type = real_type [] + and change_param_type = change_param_type [] in + let is_dynamic t = match real_type t with | TMono _ | TDynamic _ | TInst({ cl_kind = KTypeParameter _ }, _) -> true @@ -1095,7 +1201,7 @@ let generate con = let cur_line = Lexer.get_error_line p in let file = Path.get_full_path p.pfile in if cur_line <> ((!last_line)+1) then - let line = Ast.s_escape file in + let line = StringHelper.s_escape file in if String.length line <= 256 then begin print w "#line %d \"%s\"" cur_line line; newline w end else (* Compiler Error CS1560 https://msdn.microsoft.com/en-us/library/z3t5e5sw(v=vs.90).aspx *) @@ -1168,9 +1274,9 @@ let generate con = List.rev !ret in - let expr_s w e = + let expr_s is_in_value w e = last_line := -1; - in_value := false; + in_value := is_in_value; let rec expr_s w e = let was_in_value = !in_value in in_value := true; @@ -1204,7 +1310,7 @@ let generate con = if is_event (gen.greal_type ef.etype) propname then begin expr_s w ef; write w "."; - write_field w propname; + (get_write_field f) w propname; write w " += "; expr_s w ev end else @@ -1215,7 +1321,7 @@ let generate con = if is_event (gen.greal_type ef.etype) propname then begin expr_s w ef; write w "."; - write_field w propname; + (get_write_field f) w propname; write w " -= "; expr_s w ev end else @@ -1223,11 +1329,15 @@ let generate con = | TCall( ({ eexpr = TField(ef,f) } as e), [] ) when String.starts_with (field_name f) "get_" -> let name = field_name f in let propname = String.sub name 4 (String.length name - 4) in - if is_extern_prop (gen.greal_type ef.etype) propname then begin - expr_s w ef; - write w "."; - write_field w propname - end else + if is_extern_prop (gen.greal_type ef.etype) propname then + if not was_in_value then + write w "{}" + else begin + expr_s w ef; + write w "."; + (get_write_field f) w propname + end + else do_call w e [] | TCall( ({ eexpr = TField(ef,f) } as e), [v] ) when String.starts_with (field_name f) "set_" -> let name = field_name f in @@ -1235,17 +1345,17 @@ let generate con = if is_extern_prop (gen.greal_type ef.etype) propname then begin expr_s w ef; write w "."; - write_field w propname; + (get_write_field f) w propname; write w " = "; expr_s w v end else do_call w e [v] - | TField (e, (FStatic(_, cf) | FInstance(_, _, cf))) when Meta.has Meta.Native cf.cf_meta -> + | TField (e, ((FStatic(_, cf) | FInstance(_, _, cf)) as f)) when Meta.has Meta.Native cf.cf_meta -> let rec loop meta = match meta with | (Meta.Native, [EConst (String s), _],_) :: _ -> - expr_s w e; write w "."; write_field w s + expr_s w e; write w "."; (get_write_field f) w s | _ :: tl -> loop tl - | [] -> expr_s w e; write w "."; write_field w (cf.cf_name) + | [] -> expr_s w e; write w "."; (get_write_field f) w (cf.cf_name) in loop cf.cf_meta | TConst c -> @@ -1288,14 +1398,17 @@ let generate con = | TIdent "__sizeof__" -> write w "sizeof" | TLocal var -> write_id w var.v_name - | TField (_, FEnum(e, ef)) -> + | TField (_, (FEnum(e, ef) as f)) -> let s = ef.ef_name in - print w "%s." ("global::" ^ module_s (TEnumDecl e)); write_field w s + print w "%s." ("global::" ^ module_s (TEnumDecl e)); (get_write_field f) w s | TArray (e1, e2) -> expr_s w e1; write w "["; expr_s w e2; write w "]" | TBinop ((Ast.OpAssign as op), e1, e2) | TBinop ((Ast.OpAssignOp _ as op), e1, e2) -> expr_s w e1; write w ( " " ^ (Ast.s_binop op) ^ " " ); expr_s w e2 + (* hack to dodge #7034 *) + | TBinop (OpMod,_,e2) when (match (Texpr.skip e2).eexpr with TConst (TInt i32) -> i32 = Int32.zero | _ -> false) -> + write w ("System.Double.NaN") | TBinop (op, e1, e2) -> write w "( "; expr_s w e1; write w ( " " ^ (Ast.s_binop op) ^ " " ); expr_s w e2; @@ -1313,7 +1426,7 @@ let generate con = | TAbstractDecl a -> write w (t_s (TAbstract(a, List.map (fun _ -> t_empty) a.a_params))) ); write w "."; - write_field w (field_name s) + (get_write_field s) w (field_name s) | TField (e, s) when is_pointer gen e.etype -> (* take off the extra cast if possible *) let e = match e.eexpr with @@ -1321,9 +1434,9 @@ let generate con = e1 | _ -> e in - expr_s w e; write w "->"; write_field w (field_name s) + expr_s w e; write w "->"; (get_write_field s) w (field_name s) | TField (e, s) -> - expr_s w e; write w "."; write_field w (field_name s) + expr_s w e; write w "."; (get_write_field s) w (field_name s) | TTypeExpr mt -> (match change_md mt with | TClassDecl { cl_path = (["haxe"], "Int64") } -> write w ("global::" ^ module_s mt) @@ -1385,8 +1498,11 @@ let generate con = expr_s w e; write w "]" | TCall ({ eexpr = TIdent "__unsafe__" }, [ e ] ) -> - write w "unsafe"; - expr_s w (mk_block e) + write w "unsafe "; + begin_block w; + expr_s w (mk_block e); + write w ";"; + end_block w | TCall ({ eexpr = TIdent "__checked__" }, [ e ] ) -> write w "checked"; expr_s w (mk_block e) @@ -1820,12 +1936,12 @@ let generate con = match cl_params with | (_ :: _) when not (erase_generics && is_hxgeneric (TClassDecl cl)) -> let get_param_name t = match follow t with TInst(cl, _) -> snd cl.cl_path | _ -> assert false in + let combination_error c1 c2 = + gen.gcon.error ("The " ^ (get_constraint c1) ^ " constraint cannot be combined with the " ^ (get_constraint c2) ^ " constraint.") cl.cl_pos in + let params = sprintf "<%s>" (String.concat ", " (List.map (fun (_, tcl) -> get_param_name tcl) cl_params)) in let params_extends = - if hxgen - (* this is temprorary, see https://github.com/HaxeFoundation/haxe/issues/3526 *) - || not (Meta.has (Meta.Custom ":nativeTypeConstraints") cl.cl_meta) - then + if hxgen || not (Meta.has (Meta.NativeGen) cl.cl_meta) then [""] else List.fold_left (fun acc (name, t) -> @@ -1840,22 +1956,62 @@ let generate con = acc (* non-sealed class *) - | TInst ({ cl_interface = false; cl_meta = meta},_) when not (Meta.has Meta.Final meta) -> - base_class_constraints := (t_s t) :: !base_class_constraints; + | TInst ({ cl_interface = false; cl_final = false},_) -> + base_class_constraints := (CsConstraint (t_s t)) :: !base_class_constraints; acc; (* interface *) | TInst ({ cl_interface = true}, _) -> - (t_s t) :: acc + (CsConstraint (t_s t)) :: acc + + (* cs constraints *) + (* See https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters *) + | TAbstract({ a_path = (_, c); a_module = { m_path = ([pack],"Constraints") } }, params) -> + (match pack, c with + | "haxe", "Constructible" -> + (match params with + (* Only for parameterless constructors *) + | [TFun ([],TAbstract({a_path=[],"Void"},_))] -> + if (List.memq CsStruct acc) then combination_error CsConstructible CsStruct; + if (List.memq CsUnmanaged acc) then combination_error CsUnmanaged CsConstructible; + CsConstructible :: acc; + | _ -> acc; + ) + | "cs", "CsStruct" -> + if (List.memq CsClass acc) then combination_error CsClass CsStruct; + if (List.memq CsConstructible acc) then combination_error CsConstructible CsStruct; + if (List.memq CsUnmanaged acc) then combination_error CsUnmanaged CsStruct; + CsStruct :: acc; + | "cs", "CsUnmanaged" -> + if (List.memq CsStruct acc) then combination_error CsUnmanaged CsStruct; + if (List.memq CsConstructible acc) then combination_error CsUnmanaged CsConstructible; + CsUnmanaged :: acc; + | "cs", "CsClass" -> + if (List.memq CsStruct acc) then combination_error CsClass CsStruct; + CsClass :: acc; + | _, _ -> acc; + ) (* skip anything other *) | _ -> acc ) [] constraints in - let s_constraints = (!base_class_constraints @ other_constraints) in + let s_constraints = (List.sort + (* C# expects some ordering for built-in constraints: *) + (fun c1 c2 -> match c1, c2 with + | a, b when a == b -> 0 + (* - "new()" type constraint should be last *) + | CsConstructible, _ -> 1 + | _, CsConstructible -> -1 + (* - "class", "struct" and "unmanaged" should be first *) + | CsClass, _ | CsStruct, _ | CsUnmanaged, _ -> -1 + | _, CsClass | _, CsStruct | _, CsUnmanaged -> 1 + | _, _ -> 0 + ) (!base_class_constraints @ other_constraints)) in + if s_constraints <> [] then - (sprintf " where %s : %s" (get_param_name t) (String.concat ", " s_constraints) :: acc) + (sprintf " where %s : %s" (get_param_name t) (String.concat ", " (List.map get_constraint s_constraints)) :: acc) else acc; | _ -> acc @@ -1879,7 +2035,7 @@ let generate con = let visibility = if is_interface then "" else "public" in let visibility, modifiers = get_fun_modifiers event.cf_meta visibility ["event"] in let v_n = if is_static then "static" else "" in - gen_field_decl w visibility v_n modifiers (t_s (run_follow gen t)) (change_field event.cf_name); + gen_field_decl w visibility v_n modifiers (t_s (run_follow gen t)) (change_class_field cl event.cf_name); if custom && not is_interface then begin write w " "; begin_block w; @@ -1900,10 +2056,10 @@ let generate con = let fn_is_final = function | None -> true | Some ({ cf_kind = Method mkind } as m) -> - (match mkind with | MethInline -> true | _ -> false) || Meta.has Meta.Final m.cf_meta + (match mkind with | MethInline -> true | _ -> false) || (has_class_field_flag m CfFinal) | _ -> assert false in - let is_virtual = not (is_interface || is_final || Meta.has Meta.Final prop.cf_meta || fn_is_final get || fn_is_final set) in + let is_virtual = not (is_interface || is_final || (has_class_field_flag prop CfFinal) || fn_is_final get || fn_is_final set) in let fn_is_override = function | Some cf -> List.memq cf cl.cl_overrides @@ -1915,7 +2071,7 @@ let generate con = let v_n = if is_static then "static" else if is_override && not is_interface then "override" else if is_virtual then "virtual" else "" in gen_nocompletion w prop.cf_meta; - gen_field_decl w visibility v_n modifiers (t_s (run_follow gen t)) (change_field prop.cf_name); + gen_field_decl w visibility v_n modifiers (t_s (run_follow gen t)) (change_class_field cl prop.cf_name); let check cf = match cf with | Some ({ cf_overloads = o :: _ } as cf) -> @@ -1986,7 +2142,7 @@ let generate con = gen_attributes w cf.cf_meta; let is_interface = cl.cl_interface in let name, is_new, is_explicit_iface = match cf.cf_name with - | "new" -> snd cl.cl_path, true, false + | "new" -> cf.cf_name, true, false | name when String.contains name '.' -> let fn_name, path = parse_explicit_iface name in (s_type_path path) ^ "." ^ fn_name, false, true @@ -2027,18 +2183,18 @@ let generate con = let access, modifiers = get_fun_modifiers cf.cf_meta "public" [] in let modifiers = modifiers @ modf in gen_nocompletion w cf.cf_meta; - gen_field_decl w access (if is_static then "static" else "") modifiers (t_s (run_follow gen cf.cf_type)) (change_field name); + gen_field_decl w access (if is_static then "static" else "") modifiers (t_s (run_follow gen cf.cf_type)) (change_class_field cl name); (match cf.cf_expr with | Some e -> write w " = "; - expr_s w e; + expr_s true w e; | None -> () ); write w ";" end (* TODO see how (get,set) variable handle when they are interfaces *) | Method _ when not (Type.is_physical_field cf) || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) -> List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then - gen_class_field w ~is_overload:true is_static cl (Meta.has Meta.Final cf.cf_meta) cf + gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf ) cf.cf_overloads | Var _ | Method MethDynamic -> () | Method _ when is_new && Meta.has Meta.Struct cl.cl_meta && fst (get_fun cf.cf_type) = [] -> @@ -2058,15 +2214,22 @@ let generate con = | _ -> ()); List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then - gen_class_field w ~is_overload:true is_static cl (Meta.has Meta.Final cf.cf_meta) cf + gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf ) cf.cf_overloads; | Method mkind -> + let overloads = + match cf.cf_overloads with + | [] when is_overload -> [] + | [] when has_meta Meta.NativeGen cl.cl_meta -> + get_overloads_for_optional_args gen cl cf is_static + | overloads -> overloads + in List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then - gen_class_field w ~is_overload:true is_static cl (Meta.has Meta.Final cf.cf_meta) cf - ) cf.cf_overloads; + gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf + ) overloads; let is_virtual = not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false in - let is_virtual = if not is_virtual || Meta.has Meta.Final cf.cf_meta then false else is_virtual in + let is_virtual = if not is_virtual || (has_class_field_flag cf CfFinal) then false else is_virtual in let is_override = List.memq cf cl.cl_overrides in let is_override = is_override || match cf.cf_name, follow cf.cf_type with | "Equals", TFun([_,_,targ], tret) -> @@ -2078,7 +2241,7 @@ let generate con = in let is_override = if Meta.has (Meta.Custom "?prop_impl") cf.cf_meta then false else is_override in - let is_virtual = is_virtual && not (Meta.has Meta.Final cl.cl_meta) && not (is_interface) in + let is_virtual = is_virtual && not cl.cl_final && not (is_interface) in let visibility = if is_interface then "" else "public" in let visibility, modifiers = get_fun_modifiers cf.cf_meta visibility [] in @@ -2090,7 +2253,7 @@ let generate con = gen_nocompletion w cf.cf_meta; (* public static void funcName *) - gen_field_decl w visibility v_n modifiers (if not is_new then (rett_s (run_follow gen ret_type)) else "") (change_field name); + gen_field_decl w visibility v_n modifiers (if not is_new then (rett_s (run_follow gen ret_type)) else "") (change_class_field cl name); let params, params_ext = get_string_params cl cf.cf_params in (* (string arg1, object arg2) with T : object *) @@ -2124,8 +2287,8 @@ let generate con = | TBlock _ -> let unchecked = needs_unchecked e in if unchecked then (begin_block w; write w "unchecked "); - let t = Common.timer ["expression to string"] in - expr_s w e; + let t = Timer.timer ["expression to string"] in + expr_s false w e; t(); line_reset_directive w; if unchecked then end_block w @@ -2145,14 +2308,22 @@ let generate con = None, el in match expr.eexpr with + (* auto-generated ctor overloading for optional args (see get_overloads_for_optional_args) *) + | TBlock([{ eexpr = TCall ({ eexpr = TConst TThis }, args) } as this_call]) -> + write w ": "; + let t = Timer.timer ["expression to string"] in + expr_s false w this_call; + write w " "; + t(); + write w "{}" | TBlock(bl) -> let super_call, rest = get_super_call bl in (match super_call with | None -> () | Some sc -> write w ": "; - let t = Common.timer ["expression to string"] in - expr_s w sc; + let t = Timer.timer ["expression to string"] in + expr_s false w sc; write w " "; t() ); @@ -2316,7 +2487,7 @@ let generate con = in if prop v.v_read && prop v.v_write && (v.v_read = AccCall || v.v_write = AccCall) then begin let this = if static then - ExprBuilder.make_static_this cl f.cf_pos + make_static_this cl f.cf_pos else { eexpr = TConst TThis; etype = TInst(cl,List.map snd cl.cl_params); epos = f.cf_pos } in @@ -2327,7 +2498,7 @@ let generate con = write w "get"; begin_block w; write w "return "; - expr_s w this; + expr_s true w this; print w ".get_%s();" f.cf_name; end_block w | _ -> ()); @@ -2335,7 +2506,7 @@ let generate con = | AccCall -> write w "set"; begin_block w; - expr_s w this; + expr_s false w this; print w ".set_%s(value);" f.cf_name; end_block w | _ -> ()); @@ -2390,10 +2561,10 @@ let generate con = (if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "global::cs.Boot.init();"; newline w); (match gen.gcon.main with | None -> - expr_s w { eexpr = TTypeExpr(TClassDecl cl); etype = t_dynamic; epos = null_pos }; + expr_s true w { eexpr = TTypeExpr(TClassDecl cl); etype = t_dynamic; epos = null_pos }; write w ".main();" | Some expr -> - expr_s w (mk_block expr)); + expr_s false w (mk_block expr)); end_block w; end_block w; newline w; @@ -2403,7 +2574,8 @@ let generate con = in let clt, access, modifiers = get_class_modifiers cl.cl_meta (if cl.cl_interface then "interface" else "class") "public" [] in - let is_final = clt = "struct" || Meta.has Meta.Final cl.cl_meta in + let modifiers = if cl.cl_final then "sealed" :: modifiers else modifiers in + let is_final = clt = "struct" || cl.cl_final in let modifiers = [access] @ modifiers in print w "%s %s %s" (String.concat " " modifiers) clt (change_clname (snd cl.cl_path)); @@ -2437,21 +2609,42 @@ let generate con = | None -> write w "main();"; | Some expr -> - expr_s w (mk_block expr)); + expr_s false w (mk_block expr)); end_block w end; (match cl.cl_init with | None -> () | Some init -> + let needs_block,write_expr = + let unchecked = needs_unchecked init in + if cl.cl_params = [] then + unchecked, (fun() -> + if unchecked then write w "unchecked"; + expr_s false w (mk_block init) + ) + else begin + write w "static bool __hx_init_called = false;"; + newline w; + true, (fun() -> + let flag = (t_s (TInst(cl, List.map (fun _ -> t_empty) cl.cl_params))) ^ ".__hx_init_called" in + write w ("if(" ^ flag ^ ") return;"); + newline w; + write w (flag ^ " = true;"); + newline w; + if unchecked then write w "unchecked"; + expr_s false w (mk_block init); + newline w + ) + end + in print w "static %s() " (snd cl.cl_path); - if needs_unchecked init then begin + if needs_block then begin begin_block w; - write w "unchecked "; - expr_s w (mk_block init); + write_expr(); end_block w; end else - expr_s w (mk_block init); + write_expr(); line_reset_directive w; newline w; newline w @@ -2739,7 +2932,7 @@ let generate con = let cl_arg_exc = get_cl (get_type gen (["System"],"ArgumentException")) in let cl_arg_exc_t = TInst (cl_arg_exc, []) in - let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_arg_exc_t pos in + let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [make_string gen.gcon.basic msg pos])) cl_arg_exc_t pos in let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 mk_arg_exception in ClosuresToClass.configure gen closure_t; @@ -2766,17 +2959,13 @@ let generate con = let rcf_static_lookup = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "lookupHash" null_pos [] in let rcf_static_insert, rcf_static_remove = - if erase_generics then begin - let get_specialized_postfix t = match t with - | TAbstract({a_path = [],("Float" | "Int" as name)}, _) -> name - | TAnon _ | TDynamic _ -> "Dynamic" - | _ -> print_endline (debug_type t); assert false - in - (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("insert" ^ get_specialized_postfix t) null_pos []), - (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("remove" ^ get_specialized_postfix t) null_pos []) - end else - (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "insert" null_pos [t]), - (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "remove" null_pos [t]) + let get_specialized_postfix t = match t with + | TAbstract({a_path = [],("Float" | "Int" as name)}, _) -> name + | TAnon _ | TDynamic _ -> "Dynamic" + | _ -> print_endline (debug_type t); assert false + in + (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("insert" ^ get_specialized_postfix t) null_pos []), + (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("remove" ^ get_specialized_postfix t) null_pos []) in let can_be_float = like_float in @@ -2842,7 +3031,7 @@ let generate con = let cl_field_exc = get_cl (get_type gen (["System"],"MemberAccessException")) in let cl_field_exc_t = TInst (cl_field_exc, []) in - let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_field_exc_t pos in + let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [make_string gen.gcon.basic msg pos])) cl_field_exc_t pos in let rcf_ctx = ReflectionCFs.new_ctx @@ -3069,13 +3258,13 @@ let generate con = { e with eexpr = TBinop(op, e1, mk_cast t2 e2) } | _ -> let handler = if is_string e1.etype then begin - { e1 with eexpr = TCall(mk_static_field_access_infer string_cl "Compare" e1.epos [], [ e1; e2 ]); etype = gen.gcon.basic.tint } + { e1 with eexpr = TCall(mk_static_field_access_infer string_cl "CompareOrdinal" e1.epos [], [ e1; e2 ]); etype = gen.gcon.basic.tint } end else begin let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in { eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos } end in - let zero = ExprBuilder.make_int gen.gcon 0 e.epos in + let zero = make_int gen.gcon.basic 0 e.epos in { e with eexpr = TBinop(op, handler, zero) } ); @@ -3101,12 +3290,14 @@ let generate con = ExpressionUnwrap.configure gen; - UnnecessaryCastsRemoval.configure gen; + (* UnnecessaryCastsRemoval.configure gen; *) IntDivisionSynf.configure gen; UnreachableCodeEliminationSynf.configure gen false; + ArraySpliceOptimization.configure gen; + ArrayDeclSynf.configure gen native_arr_cl change_param_type; CSharpSpecificSynf.configure gen runtime_cl; @@ -3122,7 +3313,7 @@ let generate con = Hashtbl.iter (fun name v -> let name = Codegen.escape_res_name name true in let full_path = src ^ "/" ^ name in - mkdir_from_path full_path; + Path.mkdir_from_path full_path; let f = open_out_bin full_path in output_string f v; @@ -3156,15 +3347,16 @@ let generate con = let hashes = Hashtbl.fold (fun i s acc -> incr nhash; (normalize_i i,s) :: acc) rcf_ctx.rcf_hash_fields [] in let hashes = List.sort (fun (i,s) (i2,s2) -> compare i i2) hashes in - let haxe_libs = List.filter (function (_,_,_,lookup) -> is_some (lookup (["haxe";"lang"], "DceNo"))) gen.gcon.net_libs in + let haxe_libs = List.filter (function net_lib -> is_some (net_lib#lookup (["haxe";"lang"], "DceNo"))) gen.gcon.native_libs.net_libs in (try (* first let's see if we're adding a -net-lib that has already a haxe.lang.FieldLookup *) - let name,_,_,_ = List.find (function (_,_,_,lookup) -> is_some (lookup (["haxe";"lang"], "FieldLookup"))) gen.gcon.net_libs in + let net_lib = List.find (function net_lib -> is_some (net_lib#lookup (["haxe";"lang"], "FieldLookup"))) gen.gcon.native_libs.net_libs in + let name = net_lib#get_name in if not (Common.defined gen.gcon Define.DllImport) then begin gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly. Please define `-D dll_import` to handle Haxe-generated dll import correctly") null_pos; raise Not_found end; - if not (List.exists (function (n,_,_,_) -> n = name) haxe_libs) then + if not (List.exists (function net_lib -> net_lib#get_name = name) haxe_libs) then gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly, however it wasn't compiled with `-dce no`. Recompilation with `-dce no` is recommended") null_pos; (* it has; in this case, we need to add the used fields on each __init__ *) flookup_cl.cl_extern <- true; @@ -3216,8 +3408,8 @@ let generate con = | (p,_) -> p in let path = (pack, snd c.cl_path ^ extra) in - ignore (List.find (function (_,_,_,lookup) -> - is_some (lookup path)) haxe_libs); + ignore (List.find (function net_lib -> + is_some (net_lib#lookup path)) haxe_libs); c.cl_extern <- true; with | Not_found -> ()) | _ -> ()) gen.gtypes @@ -3225,7 +3417,7 @@ let generate con = RenameTypeParameters.run gen.gtypes_list; - mkdir_from_path gen.gcon.file; + Path.mkdir_from_path gen.gcon.file; List.iter (fun md_def -> let source_dir = gen.gcon.file ^ "/src/" ^ (String.concat "/" (fst (path_of_md_def md_def))) in diff --git a/src/generators/genhl.ml b/src/generators/genhl.ml index 5854dfa7e29..eb2cc900fea 100644 --- a/src/generators/genhl.ml +++ b/src/generators/genhl.ml @@ -46,7 +46,7 @@ type allocator = { mutable a_hold : int list; } -type lassign = (string index * int * int) +type lassign = (string index * int) type method_context = { mid : int; @@ -79,23 +79,28 @@ type array_impl = { af64 : tclass; } +type constval = + | CString of string + type context = { com : Common.context; cglobals : (string, ttype) lookup; cstrings : (string, string) lookup; + cbytes : (bytes, bytes) lookup; cfloats : (float, float) lookup; cints : (int32, int32) lookup; - cnatives : (string, (string index * string index * ttype * functable index)) lookup; + cnatives : (string * int, (string index * string index * ttype * functable index)) lookup; cfids : (string * path, unit) lookup; cfunctions : fundecl DynArray.t; + cconstants : (constval, (global * int array)) lookup; optimize : bool; overrides : (string * path, bool) Hashtbl.t; defined_funs : (int,unit) Hashtbl.t; is_macro : bool; mutable dump_out : (unit IO.output) option; - mutable cached_types : (path, ttype) PMap.t; + mutable cached_types : (string list, ttype) PMap.t; mutable m : method_context; - mutable anons_cache : (tanon * ttype) list; + mutable anons_cache : (tanon, ttype) PMap.t; mutable method_wrappers : ((ttype * ttype), int) PMap.t; mutable rec_cache : (Type.t * ttype option ref) list; mutable cached_tuples : (ttype list, ttype) PMap.t; @@ -108,8 +113,8 @@ type context = { core_enum : tclass; ref_abstract : tabstract; cdebug_files : (string, string) lookup; - cdebug_locals : (string, string ) lookup; - cdebug_assigns : (lassign array) DynArray.t; + mutable ct_delayed : (unit -> unit) list; + mutable ct_depth : int; } (* --- *) @@ -135,7 +140,7 @@ let is_to_string t = | _ -> false let is_extern_field f = - not (Type.is_physical_field f) || (match f.cf_kind with Method MethNormal -> List.exists (fun (m,_,_) -> m = Meta.Custom ":hlNative") f.cf_meta | _ -> false) || Meta.has Meta.Extern f.cf_meta + not (Type.is_physical_field f) || (match f.cf_kind with Method MethNormal -> List.exists (fun (m,_,_) -> m = Meta.HlNative) f.cf_meta | _ -> false) || has_class_field_flag f CfExtern let is_array_class name = match name with @@ -147,6 +152,10 @@ let is_array_type t = | HObj p -> is_array_class p.pname | _ -> false +let max_pos e = + let p = e.epos in + { p with pmin = p.pmax } + let to_utf8 str p = let u8 = try UTF8.validate str; @@ -163,7 +172,7 @@ let to_utf8 str p = let c = UChar.code c in if (c >= 0xD800 && c <= 0xDFFF) || c >= 0x110000 then abort "Invalid unicode char" p; incr ccount; - if c > 0x10000 then incr ccount; + if c >= 0x10000 then incr ccount; ) u8; u8, !ccount @@ -258,6 +267,9 @@ let alloc_i32 ctx i = let alloc_string ctx s = lookup ctx.cstrings s (fun() -> s) +let alloc_bytes ctx s = + lookup ctx.cbytes s (fun() -> s) + let array_class ctx t = match t with | HI32 -> @@ -340,6 +352,18 @@ let fake_tnull = a_params = ["T",t_dynamic]; } +let get_rec_cache ctx t none_callback not_found_callback = + try + match !(List.assq t ctx.rec_cache) with + | None -> none_callback() + | Some t -> t + with Not_found -> + let tref = ref None in + ctx.rec_cache <- (t,tref) :: ctx.rec_cache; + let t = not_found_callback tref in + ctx.rec_cache <- List.tl ctx.rec_cache; + t + let rec to_type ?tref ctx t = match t with | TMono r -> @@ -347,17 +371,11 @@ let rec to_type ?tref ctx t = | None -> HDyn | Some t -> to_type ?tref ctx t) | TType (td,tl) -> - let t = (try - match !(List.assq t ctx.rec_cache) with - | None -> abort "Unsupported recursive type" td.t_pos - | Some t -> t - with Not_found -> - let tref = ref None in - ctx.rec_cache <- (t,tref) :: ctx.rec_cache; - let t = to_type ~tref ctx (apply_params td.t_params tl td.t_type) in - ctx.rec_cache <- List.tl ctx.rec_cache; - t - ) in + let t = + get_rec_cache ctx t + (fun() -> abort "Unsupported recursive type" td.t_pos) + (fun tref -> to_type ~tref ctx (apply_params td.t_params tl td.t_type)) + in (match td.t_path with | ["haxe";"macro"], name -> Hashtbl.replace ctx.macro_typedefs name t; t | _ -> t) @@ -376,10 +394,11 @@ let rec to_type ?tref ctx t = enum_class ctx e | _ -> assert false) | TAnon a -> + if PMap.is_empty a.a_fields then HDyn else (try (* can't use physical comparison in PMap since addresses might change in GC compact, maybe add an uid to tanon if too slow ? *) - List.assq a ctx.anons_cache + PMap.find a ctx.anons_cache with Not_found -> let vp = { vfields = [||]; @@ -389,28 +408,12 @@ let rec to_type ?tref ctx t = (match tref with | None -> () | Some r -> r := Some t); - ctx.anons_cache <- (a,t) :: ctx.anons_cache; - let fields = PMap.fold (fun cf acc -> - match cf.cf_kind with - | Var _ when (match follow cf.cf_type with TAnon _ | TFun _ -> true | _ -> false) -> - (* - if it's another virtual or a method, it might not match our own (might be larger, or class) - *) - acc - | Method _ -> - acc - | _ -> - (cf.cf_name,alloc_string ctx cf.cf_name,to_type ctx cf.cf_type) :: acc - ) a.a_fields [] in - if fields = [] then - let t = HDyn in - ctx.anons_cache <- (a,t) :: List.tl ctx.anons_cache; - t - else - let fields = List.sort (fun (n1,_,_) (n2,_,_) -> compare n1 n2) fields in - vp.vfields <- Array.of_list fields; - Array.iteri (fun i (n,_,_) -> vp.vindex <- PMap.add n i vp.vindex) vp.vfields; - t + ctx.anons_cache <- PMap.add a t ctx.anons_cache; + let fields = PMap.fold (fun cf acc -> cfield_type ctx cf :: acc) a.a_fields [] in + let fields = List.sort (fun (n1,_,_) (n2,_,_) -> compare n1 n2) fields in + vp.vfields <- Array.of_list fields; + Array.iteri (fun i (n,_,_) -> vp.vindex <- PMap.add n i vp.vindex) vp.vfields; + t ) | TDynamic _ -> HDyn @@ -432,7 +435,7 @@ let rec to_type ?tref ctx t = | _ -> class_type ~tref ctx c pl false) | TAbstract ({a_path = [],"Null"},[t1]) -> let t = to_type ?tref ctx t1 in - if not (is_nullable t) then HNull t else t + if not (is_nullable t) && t <> HVoid then HNull t else t | TAbstract (a,pl) -> if Meta.has Meta.CoreType a.a_meta then (match a.a_path with @@ -457,7 +460,9 @@ let rec to_type ?tref ctx t = | ["haxe";"macro"], "Position" -> HAbstract ("macro_pos", alloc_string ctx "macro_pos") | _ -> failwith ("Unknown core type " ^ s_type_path a.a_path)) else - to_type ?tref ctx (Abstract.get_underlying_type a pl) + get_rec_cache ctx t + (fun() -> HDyn) + (fun tref -> to_type ~tref ctx (Abstract.get_underlying_type a pl)) and resolve_class ctx c pl statics = let not_supported() = @@ -473,6 +478,14 @@ and resolve_class ctx c pl statics = | _ -> c +and cfield_type ctx cf = + let t = to_type ctx cf.cf_type in + let t = (match cf.cf_kind, t with + | Method (MethNormal|MethInline), HFun (args,ret) -> HMethod (args,ret) + | _ -> t + ) in + (cf.cf_name,alloc_string ctx cf.cf_name,t) + and field_type ctx f p = match f with | FInstance (c,pl,f) | FClosure (Some (c,pl),f) -> @@ -507,8 +520,9 @@ and real_type ctx e = | TInst ({cl_kind=KTypeParameter _},_), TFun _ -> a2 (* If we have a number, it is more accurate to cast it to the type parameter before wrapping it as dynamic + Ignore dynamic method (#7166) *) - | TInst ({cl_kind=KTypeParameter _},_), t when is_number (to_type ctx t) -> + | TInst ({cl_kind=KTypeParameter _},_), t when is_number (to_type ctx t) && (match f with FInstance (_,_,{ cf_kind = Var _ | Method MethDynamic }) -> false | _ -> true) -> (name, opt, TAbstract (fake_tnull,[t])) | _ -> a @@ -516,13 +530,21 @@ and real_type ctx e = | _ -> ft) | TLocal v -> v.v_type | TParenthesis e -> loop e + | TArray (arr,_) -> + let rec loop t = + match follow t with + | TInst({ cl_path = [],"Array" },[t]) -> t + | TAbstract (a,pl) -> loop (Abstract.get_underlying_type a pl) + | _ -> t_dynamic + in + loop arr.etype | _ -> e.etype in to_type ctx (loop e) and class_type ?(tref=None) ctx c pl statics = let c = if c.cl_extern then resolve_class ctx c pl statics else c in - let key_path = (if statics then fst c.cl_path, "$" ^ snd c.cl_path else c.cl_path) in + let key_path = (if statics then "$" ^ snd c.cl_path else snd c.cl_path) :: fst c.cl_path in try PMap.find key_path ctx.cached_types with Not_found when c.cl_interface && not statics -> @@ -531,17 +553,17 @@ and class_type ?(tref=None) ctx c pl statics = vindex = PMap.empty; } in let t = HVirtual vp in - ctx.cached_types <- PMap.add c.cl_path t ctx.cached_types; + ctx.cached_types <- PMap.add key_path t ctx.cached_types; let rec loop c = let fields = List.fold_left (fun acc (i,_) -> loop i @ acc) [] c.cl_implements in - PMap.fold (fun cf acc -> (cf.cf_name,alloc_string ctx cf.cf_name,to_type ctx cf.cf_type) :: acc) c.cl_fields fields + PMap.fold (fun cf acc -> cfield_type ctx cf :: acc) c.cl_fields fields in let fields = loop c in vp.vfields <- Array.of_list fields; Array.iteri (fun i (n,_,_) -> vp.vindex <- PMap.add n i vp.vindex) vp.vfields; t | Not_found -> - let pname = s_type_path key_path in + let pname = s_type_path (List.tl key_path, List.hd key_path) in let p = { pname = pname; pid = alloc_string ctx pname; @@ -556,10 +578,11 @@ and class_type ?(tref=None) ctx c pl statics = pinterfaces = PMap.empty; pbindings = []; } in - let t = HObj p in + let t = (if Meta.has Meta.Struct c.cl_meta && not statics then HStruct p else HObj p) in (match tref with | None -> () | Some r -> r := Some t); + ctx.ct_depth <- ctx.ct_depth + 1; ctx.cached_types <- PMap.add key_path t ctx.cached_types; if c.cl_path = ([],"Array") then assert false; if c == ctx.base_class then begin @@ -572,16 +595,26 @@ and class_type ?(tref=None) ctx c pl statics = ) in let start_field, virtuals = (match tsup with | None -> 0, [||] - | Some (HObj psup) -> + | Some ((HObj psup | HStruct psup) as pt) -> + if is_struct t <> is_struct pt then abort (if is_struct t then "Struct cannot extend a not struct class" else "Class cannot extend a struct") c.cl_pos; if psup.pnfields < 0 then assert false; p.psuper <- Some psup; - p.pfunctions <- psup.pfunctions; - p.pinterfaces <- psup.pinterfaces; psup.pnfields, psup.pvirtuals | _ -> assert false ) in let fa = DynArray.create() and pa = DynArray.create() and virtuals = DynArray.of_array virtuals in - let todo = ref [] in + let add_field name get_t = + let fid = DynArray.length fa + start_field in + let str = if name = "" then 0 else alloc_string ctx name in + p.pindex <- PMap.add name (fid, HVoid) p.pindex; + DynArray.add fa (name, str, HVoid); + ctx.ct_delayed <- (fun() -> + let t = get_t() in + p.pindex <- PMap.add name (fid, t) p.pindex; + Array.set p.pfields (fid - start_field) (name, str, t); + ) :: ctx.ct_delayed; + fid + in List.iter (fun f -> if is_extern_field f || (statics && f.cf_name = "__meta__") then () else let fid = (match f.cf_kind with @@ -605,15 +638,8 @@ and class_type ?(tref=None) ctx c pl statics = | Method MethDynamic when List.exists (fun ff -> ff.cf_name = f.cf_name) c.cl_overrides -> Some (try fst (get_index f.cf_name p) with Not_found -> assert false) | _ -> - let fid = DynArray.length fa in - p.pindex <- PMap.add f.cf_name (fid + start_field, t) p.pindex; - DynArray.add fa (f.cf_name, alloc_string ctx f.cf_name, HVoid); - todo := (fun() -> - let t = to_type ctx f.cf_type in - p.pindex <- PMap.add f.cf_name (fid + start_field, t) p.pindex; - Array.set p.pfields fid (f.cf_name, alloc_string ctx f.cf_name, t) - ) :: !todo; - Some (fid + start_field) + let fid = add_field f.cf_name (fun() -> to_type ctx f.cf_type) in + Some fid ) in match f.cf_kind, fid with | Method _, Some fid -> p.pbindings <- (fid, alloc_fun_path ctx c.cl_path f.cf_name) :: p.pbindings @@ -622,10 +648,12 @@ and class_type ?(tref=None) ctx c pl statics = if not statics then begin (* add interfaces *) List.iter (fun (i,pl) -> - let fid = DynArray.length fa in - let t = to_type ctx (TInst (i,pl)) in - p.pinterfaces <- PMap.add t (fid + start_field) p.pinterfaces; - DynArray.add fa ("", 0, t); + let rid = ref (-1) in + rid := add_field "" (fun() -> + let t = to_type ctx (TInst (i,pl)) in + p.pinterfaces <- PMap.add t !rid p.pinterfaces; + t + ); ) c.cl_implements; (* check toString *) (try @@ -644,13 +672,19 @@ and class_type ?(tref=None) ctx c pl statics = p.pfields <- DynArray.to_array fa; p.pproto <- DynArray.to_array pa; p.pvirtuals <- DynArray.to_array virtuals; - List.iter (fun f -> f()) !todo; + ctx.ct_depth <- ctx.ct_depth - 1; + if ctx.ct_depth = 0 then begin + let todo = ctx.ct_delayed in + ctx.ct_delayed <- []; + List.iter (fun f -> f()) todo; + end; if not statics && c != ctx.core_type && c != ctx.core_enum then p.pclassglobal <- Some (fst (class_global ctx (if statics then ctx.base_class else c))); t and enum_type ?(tref=None) ctx e = + let key_path = snd e.e_path :: fst e.e_path in try - PMap.find e.e_path ctx.cached_types + PMap.find key_path ctx.cached_types with Not_found -> let ename = s_type_path e.e_path in let et = { @@ -663,7 +697,7 @@ and enum_type ?(tref=None) ctx e = (match tref with | None -> () | Some r -> r := Some t); - ctx.cached_types <- PMap.add e.e_path t ctx.cached_types; + ctx.cached_types <- PMap.add key_path t ctx.cached_types; et.efields <- Array.of_list (List.map (fun f -> let f = PMap.find f e.e_constrs in let args = (match f.ef_type with @@ -677,11 +711,11 @@ and enum_type ?(tref=None) ctx e = t and enum_class ctx e = - let cpath = (fst e.e_path,"$" ^ snd e.e_path) in + let key_path = ("$" ^ snd e.e_path) :: fst e.e_path in try - PMap.find cpath ctx.cached_types + PMap.find key_path ctx.cached_types with Not_found -> - let pname = s_type_path cpath in + let pname = s_type_path (List.tl key_path, List.hd key_path) in let p = { pname = pname; pid = alloc_string ctx pname; @@ -697,7 +731,7 @@ and enum_class ctx e = pbindings = []; } in let t = HObj p in - ctx.cached_types <- PMap.add cpath t ctx.cached_types; + ctx.cached_types <- PMap.add key_path t ctx.cached_types; p.psuper <- Some (match class_type ctx ctx.base_enum [] false with HObj o -> o | _ -> assert false); t @@ -734,7 +768,7 @@ let resolve_type ctx path = let alloc_std ctx name args ret = let lib = "std" in (* different from :hlNative to prevent mismatch *) - let nid = lookup ctx.cnatives ("$" ^ name ^ "@" ^ lib) (fun() -> + let nid = lookup ctx.cnatives ("$" ^ name ^ "@" ^ lib, -1) (fun() -> let fid = alloc_fun_path ctx ([],"std") name in Hashtbl.add ctx.defined_funs fid (); (alloc_string ctx lib, alloc_string ctx name,HFun (args,ret),fid) @@ -772,7 +806,7 @@ let rtype ctx r = DynArray.get ctx.m.mregs.arr r let hold ctx r = - if not ctx.optimize || Hashtbl.mem ctx.m.mvars r then () else + if not ctx.optimize then () else let t = rtype ctx r in let a = PMap.find t ctx.m.mallocs in let rec loop l = @@ -785,7 +819,7 @@ let hold ctx r = a.a_hold <- r :: a.a_hold let free ctx r = - if not ctx.optimize || Hashtbl.mem ctx.m.mvars r then () else + if not ctx.optimize then () else let t = rtype ctx r in let a = PMap.find t ctx.m.mallocs in let last = ref true in @@ -820,17 +854,25 @@ let alloc_var ctx v new_var = Hashtbl.add ctx.m.mvars v.v_id r; r + +let push_op ctx o = + DynArray.add ctx.m.mdebug ctx.m.mcurpos; + DynArray.add ctx.m.mops o + let op ctx o = match o with - | OMov (a,b) when a = b -> () + | OMov (a,b) when a = b -> + () | _ -> - DynArray.add ctx.m.mdebug ctx.m.mcurpos; - DynArray.add ctx.m.mops o + push_op ctx o + +let set_op ctx pos o = + DynArray.set ctx.m.mops pos o let jump ctx f = let pos = current_pos ctx in op ctx (OJAlways (-1)); (* loop *) - (fun() -> DynArray.set ctx.m.mops pos (f (current_pos ctx - pos - 1))) + (fun() -> set_op ctx pos (f (current_pos ctx - pos - 1))) let jump_back ctx = let pos = current_pos ctx in @@ -911,7 +953,8 @@ let common_type ctx e1 e2 for_eq p = | _ when for_eq && safe_cast t2 t1 -> t1 | HBool, HNull HBool when for_eq -> t2 | HNull HBool, HBool when for_eq -> t1 - | HObj _, HVirtual _ | HVirtual _, HObj _ -> HDyn + | HObj _, HVirtual _ | HVirtual _, HObj _ | HVirtual _ , HVirtual _ -> HDyn + | HFun _, HFun _ -> HDyn | _ -> abort ("Don't know how to compare " ^ tstr t1 ^ " and " ^ tstr t2) p in @@ -926,16 +969,23 @@ let real_name v = | (Meta.RealPath,[EConst (String name),_],_) :: _ -> name | _ :: l -> loop l in - loop v.v_meta + match loop v.v_meta with + | "_gthis" -> "this" + | name -> name + +let is_gen_local ctx v = match v.v_kind with + | VUser _ -> false + | _ -> true -let add_assign ctx v r = +let add_assign ctx v = + if is_gen_local ctx v then () else let name = real_name v in - ctx.m.massign <- (lookup ctx.cdebug_locals name (fun() -> name), DynArray.length ctx.m.mops, r) :: ctx.m.massign + ctx.m.massign <- (alloc_string ctx name, current_pos ctx - 1) :: ctx.m.massign let add_capture ctx r = Array.iter (fun v -> let name = real_name v in - ctx.m.massign <- (lookup ctx.cdebug_locals name (fun() -> name), -1, r) :: ctx.m.massign + ctx.m.massign <- (alloc_string ctx name, -(r+2)) :: ctx.m.massign ) ctx.m.mcaptured.c_vars let before_return ctx = @@ -983,8 +1033,26 @@ let type_value ctx t p = assert false let rec eval_to ctx e (t:ttype) = - let r = eval_expr ctx e in - cast_to ctx r t e.epos + match e.eexpr, t with + | TConst (TInt i), HF64 -> + let r = alloc_tmp ctx t in + op ctx (OFloat (r,alloc_float ctx (Int32.to_float i))); + r + (* this causes a bug with NG, to be reviewed later + | TConst (TInt i), HF32 -> + let r = alloc_tmp ctx t in + let bits = Int32.bits_of_float (Int32.to_float i) in + op ctx (OFloat (r,alloc_float ctx (Int64.float_of_bits (Int64.of_int32 bits)))); + r + | TConst (TFloat f), HF32 -> + let r = alloc_tmp ctx t in + let bits = Int32.bits_of_float (float_of_string f) in + op ctx (OFloat (r,alloc_float ctx (Int64.float_of_bits (Int64.of_int32 bits)))); + r + *) + | _ -> + let r = eval_expr ctx e in + cast_to ctx r t e.epos and cast_to ?(force=false) ctx (r:reg) (t:ttype) p = let rt = rtype ctx r in @@ -1035,7 +1103,15 @@ and cast_to ?(force=false) ctx (r:reg) (t:ttype) p = | HObj o, HVirtual _ -> let out = alloc_tmp ctx t in (try - let fid = PMap.find t o.pinterfaces in + let rec lookup_intf o = + try + PMap.find t o.pinterfaces + with Not_found -> + match o.psuper with + | None -> raise Not_found + | Some o -> lookup_intf o + in + let fid = lookup_intf o in (* memoisation *) let need_null_check r = not (r = 0 && ctx.m.mhasthis) @@ -1092,6 +1168,15 @@ and cast_to ?(force=false) ctx (r:reg) (t:ttype) p = j(); op ctx (ONull out); out + | HRef t1, HNull t2 -> + let j = jump ctx (fun n -> OJNull (r,n)) in + let rtmp = alloc_tmp ctx t1 in + op ctx (OUnref (rtmp,r)); + let out = cast_to ctx rtmp t p in + op ctx (OJAlways 1); + j(); + op ctx (ONull out); + out | (HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64), HNull ((HF32 | HF64) as t) -> let tmp = alloc_tmp ctx t in op ctx (OToSFloat (tmp, r)); @@ -1128,6 +1213,18 @@ and cast_to ?(force=false) ctx (r:reg) (t:ttype) p = let out = alloc_tmp ctx t in op ctx (OSafeCast (out, r)); out + | HNull _, HRef t2 -> + let out = alloc_tmp ctx t in + op ctx (OJNotNull (r,2)); + op ctx (ONull out); + let j = jump ctx (fun n -> OJAlways n) in + let r = cast_to ctx r t2 p in + let r2 = alloc_tmp ctx t2 in + op ctx (OMov (r2, r)); + hold ctx r2; (* retain *) + op ctx (ORef (out,r2)); + j(); + out | _, HRef t2 -> let r = cast_to ctx r t2 p in let r2 = alloc_tmp ctx t2 in @@ -1144,7 +1241,7 @@ and cast_to ?(force=false) ctx (r:reg) (t:ttype) p = else abort ("Don't know how to cast " ^ tstr rt ^ " to " ^ tstr t) p -and unsafe_cast_to ctx (r:reg) (t:ttype) p = +and unsafe_cast_to ?(debugchk=true) ctx (r:reg) (t:ttype) p = let rt = rtype ctx r in if safe_cast rt t then r @@ -1164,7 +1261,7 @@ and unsafe_cast_to ctx (r:reg) (t:ttype) p = if is_dynamic (rtype ctx r) && is_dynamic t then let r2 = alloc_tmp ctx t in op ctx (OUnsafeCast (r2,r)); - if ctx.com.debug then begin + if ctx.com.debug && debugchk then begin hold ctx r2; let r3 = cast_to ~force:true ctx r t p in let j = jump ctx (fun n -> OJEq (r2,r3,n)) in @@ -1178,7 +1275,7 @@ and unsafe_cast_to ctx (r:reg) (t:ttype) p = and object_access ctx eobj t f = match t with - | HObj p -> + | HObj p | HStruct p -> (try let fid = fst (get_index f.cf_name p) in if f.cf_kind = Method MethNormal then @@ -1333,10 +1430,20 @@ and jump_expr ctx e jcond = jump_expr ctx e (not jcond) | TBinop (OpEq,{ eexpr = TConst(TNull) },e) | TBinop (OpEq,e,{ eexpr = TConst(TNull) }) -> let r = eval_expr ctx e in - jump ctx (fun i -> if jcond then OJNull (r,i) else OJNotNull (r,i)) + if is_nullable(rtype ctx r) then + jump ctx (fun i -> if jcond then OJNull (r,i) else OJNotNull (r,i)) + else if not jcond then + jump ctx (fun i -> OJAlways i) + else + (fun i -> ()) | TBinop (OpNotEq,{ eexpr = TConst(TNull) },e) | TBinop (OpNotEq,e,{ eexpr = TConst(TNull) }) -> let r = eval_expr ctx e in - jump ctx (fun i -> if jcond then OJNotNull (r,i) else OJNull (r,i)) + if is_nullable(rtype ctx r) then + jump ctx (fun i -> if jcond then OJNotNull (r,i) else OJNull (r,i)) + else if jcond then + jump ctx (fun i -> OJAlways i) + else + (fun i -> ()) | TBinop (OpEq | OpNotEq | OpGt | OpGte | OpLt | OpLte as jop, e1, e2) -> let t = common_type ctx e1 e2 (match jop with OpEq | OpNotEq -> true | _ -> false) e.epos in let r1 = eval_to ctx e1 t in @@ -1394,15 +1501,23 @@ and eval_null_check ctx e = | _ -> op ctx (ONullCheck r)); r +and make_const ctx c p = + let cidx = lookup ctx.cconstants c (fun() -> + let fields, t = (match c with + | CString s -> + let str, len = to_utf8 s p in + [alloc_string ctx str; alloc_i32 ctx (Int32.of_int len)], to_type ctx ctx.com.basic.tstring + ) in + let g = lookup_alloc ctx.cglobals t in + g, Array.of_list fields + ) in + let g, _ = DynArray.get ctx.cconstants.arr cidx in + g + and make_string ctx s p = - let str, len = to_utf8 s p in - let r = alloc_tmp ctx HBytes in - let s = alloc_tmp ctx (to_type ctx ctx.com.basic.tstring) in - op ctx (ONew s); - op ctx (OString (r,alloc_string ctx str)); - op ctx (OSetField (s,0,r)); - op ctx (OSetField (s,1,reg_int ctx len)); - s + let r = alloc_tmp ctx (to_type ctx ctx.com.basic.tstring) in + op ctx (OGetGlobal (r, make_const ctx (CString s) p)); + r and get_enum_index ctx v = let r = alloc_tmp ctx HI32 in @@ -1453,8 +1568,8 @@ and eval_expr ctx e = match captured_index ctx v with | None -> let r = alloc_var ctx v true in - op ctx (OMov (r,ri)); - add_assign ctx v r; + push_op ctx (OMov (r,ri)); + add_assign ctx v; | Some idx -> op ctx (OSetEnumField (ctx.m.mcaptreg, idx, ri)); ); @@ -1878,7 +1993,9 @@ and eval_expr ctx e = op ctx (ONew ro); op ctx (OString (rb,alloc_string ctx k)); op ctx (OSetField (ro,0,rb)); - op ctx (OBytes (rb,alloc_string ctx (v ^ "\x00"))); (* add a \x00 to prevent clashing with existing string *) + (* fix for Resource.getString *) + let str = try ignore(String.index v '\x00'); v with Not_found -> v ^ "\x00" in + op ctx (OBytes (rb,alloc_bytes ctx (Bytes.of_string str))); op ctx (OSetField (ro,1,rb)); if has_len then op ctx (OSetField (ro,2,reg_int ctx (String.length v))); op ctx (OSetArray (arr,ridx,ro)); @@ -1912,7 +2029,7 @@ and eval_expr ctx e = let rt = HAbstract ("macro_pos",alloc_string ctx "macro_pos") in let r = alloc_tmp ctx rt in let rfile = alloc_tmp ctx HBytes in - op ctx (OBytes (rfile, alloc_string ctx file)); + op ctx (OBytes (rfile, alloc_bytes ctx (Bytes.of_string file))); hold ctx rfile; let min = eval_expr ctx min in hold ctx min; let max = eval_expr ctx max in @@ -1928,6 +2045,24 @@ and eval_expr ctx e = get_enum_index ctx v | TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Type" },{ cf_name = "enumIndex" })) },[v]) when (match follow v.etype with TEnum _ -> true | _ -> false) -> get_enum_index ctx v + | TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Std" },{ cf_name = "instance" })) },[v;vt]) + | TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Std" },{ cf_name = "downcast" })) },[v;vt]) -> + let r = eval_expr ctx v in + hold ctx r; + let c = eval_to ctx vt (class_type ctx ctx.base_type [] false) in + hold ctx c; + let rv = alloc_tmp ctx (to_type ctx e.etype) in + let rb = alloc_tmp ctx HBool in + op ctx (OCall2 (rb, alloc_fun_path ctx (["hl"],"BaseType") "check",c,r)); + let jnext = jump ctx (fun n -> OJFalse (rb,n)) in + op ctx (OMov (rv, unsafe_cast_to ~debugchk:false ctx r (to_type ctx e.etype) e.epos)); + let jend = jump ctx (fun n -> OJAlways n) in + jnext(); + op ctx (ONull rv); + jend(); + free ctx r; + free ctx c; + rv | TCall (ec,args) -> let tfun = real_type ctx ec in let el() = eval_args ctx args tfun e.epos in @@ -2024,7 +2159,14 @@ and eval_expr ctx e = op ctx (match ethis.eexpr with TConst TThis -> OGetThis (r,fid) | _ -> OField (r,robj,fid)); | AInstanceProto (ethis,fid) | AVirtualMethod (ethis, fid) -> let robj = eval_null_check ctx ethis in - op ctx (OVirtualClosure (r,robj,fid)); + (match rtype ctx robj with + | HObj _ -> + op ctx (OVirtualClosure (r,robj,fid)) + | HVirtual vp -> + let _, sid, _ = vp.vfields.(fid) in + op ctx (ODynGet (r,robj, sid)) + | _ -> + assert false) | ADynamic (ethis, f) -> let robj = eval_null_check ctx ethis in op ctx (ODynGet (r,robj,f)) @@ -2037,7 +2179,7 @@ and eval_expr ctx e = let eargs, et = (match follow ef.ef_type with TFun (args,ret) -> args, ret | _ -> assert false) in let ct = ctx.com.basic in let p = ef.ef_pos in - let eargs = List.map (fun (n,o,t) -> Type.alloc_var n t en.e_pos, if o then Some TNull else None) eargs in + let eargs = List.map (fun (n,o,t) -> Type.alloc_var VGenerated n t en.e_pos, if o then Some (mk (TConst TNull) t_dynamic null_pos) else None) eargs in let ecall = mk (TCall (e,List.map (fun (v,_) -> mk (TLocal v) v.v_type p) eargs)) et p in let f = { tf_args = eargs; @@ -2049,7 +2191,10 @@ and eval_expr ctx e = op ctx (OStaticClosure (r,fid)); | ANone | ALocal _ | AArray _ | ACaptured _ -> abort "Invalid access" e.epos); - unsafe_cast_to ctx r (to_type ctx e.etype) e.epos + let to_t = to_type ctx e.etype in + (match to_t with + | HFun _ -> cast_to ctx r to_t e.epos + | _ -> unsafe_cast_to ctx r to_t e.epos) | TObjectDecl fl -> (match to_type ctx e.etype with | HVirtual vp as t when Array.length vp.vfields = List.length fl && not (List.exists (fun ((s,_,_),e) -> s = "toString" && is_to_string e.etype) fl) -> @@ -2106,7 +2251,9 @@ and eval_expr ctx e = let t = to_type ctx e.etype in let out = alloc_tmp ctx t in let j = jump_expr ctx cond false in - if t = HVoid then ignore(eval_expr ctx eif) else op ctx (OMov (out,eval_to ctx eif t)); + let rif = if t = HVoid then eval_expr ctx eif else eval_to ctx eif t in + set_curpos ctx (max_pos eif); + if t <> HVoid then op ctx (OMov (out,rif)); (match eelse with | None -> j() | Some e -> @@ -2234,8 +2381,8 @@ and eval_expr ctx e = r | ALocal (v,l) -> let r = value() in - op ctx (OMov (l, r)); - add_assign ctx v l; + push_op ctx (OMov (l, r)); + add_assign ctx v; r | AArray (ra,(at,vt),ridx) -> hold ctx ra; @@ -2306,8 +2453,8 @@ and eval_expr ctx e = (match get_access ctx e1 with | ALocal (v,l) -> let r = eval_to ctx { e with eexpr = TBinop (bop,e1,e2) } (to_type ctx e1.etype) in - op ctx (OMov (l, r)); - add_assign ctx v l; + push_op ctx (OMov (l, r)); + add_assign ctx v; r | acc -> gen_assign_op ctx acc e1 (fun r -> @@ -2363,19 +2510,34 @@ and eval_expr ctx e = op ctx (OSafeCast (tmp,r)); unop tmp; op ctx (OToDyn (r,tmp)); + | HDyn when uop = Increment -> + hold ctx r; + let tmp = alloc_tmp ctx HDyn in + free ctx r; + op ctx (OToDyn (tmp, reg_int ctx 1)); + op ctx (OCall2 (r,alloc_fun_path ctx ([],"Std") "__add__",r,tmp)) + | HDyn when uop = Decrement -> + let r2 = alloc_tmp ctx HF64 in + hold ctx r2; + let tmp = alloc_tmp ctx HF64 in + free ctx r2; + op ctx (OSafeCast (r2, r)); + op ctx (OFloat (tmp, alloc_float ctx 1.)); + op ctx (OSub (r2, r2, tmp)); + op ctx (OSafeCast (r, r2)); | _ -> assert false in (match get_access ctx v, fix with | ALocal (v,r), Prefix -> unop r; - add_assign ctx v r; r | ALocal (v,r), Postfix -> let r2 = alloc_tmp ctx (rtype ctx r) in + hold ctx r2; op ctx (OMov (r2,r)); unop r; - add_assign ctx v r; + free ctx r2; r2 | acc, _ -> let ret = ref 0 in @@ -2426,6 +2588,7 @@ and eval_expr ctx e = let ret = jump_back ctx in let j = jump_expr ctx cond false in ignore(eval_expr ctx eloop); + set_curpos ctx (max_pos e); ret(); j(); List.iter (fun f -> f (current_pos ctx)) ctx.m.mbreaks; @@ -2445,6 +2608,7 @@ and eval_expr ctx e = let j = jump_expr ctx cond false in start(); ignore(eval_expr ctx eloop); + set_curpos ctx (max_pos e); ret(); j(); List.iter (fun f -> f (current_pos ctx)) ctx.m.mbreaks; @@ -2534,7 +2698,7 @@ and eval_expr ctx e = | TMeta (_,e) -> eval_expr ctx e | TFor (v,it,loop) -> - eval_expr ctx (Codegen.for_remap ctx.com v it loop e.epos) + eval_expr ctx (Texpr.for_remap ctx.com.basic v it loop e.epos) | TSwitch (en,cases,def) -> let rt = to_type ctx e.etype in let r = alloc_tmp ctx rt in @@ -2576,7 +2740,7 @@ and eval_expr ctx e = if rt <> HVoid then op ctx (OMov (r,re)); jends := jump ctx (fun i -> OJAlways i) :: !jends ) cases; - DynArray.set ctx.m.mops (switch_pos - 1) (OSwitch (ridx,indexes,current_pos ctx - switch_pos)); + set_op ctx (switch_pos - 1) (OSwitch (ridx,indexes,current_pos ctx - switch_pos)); List.iter (fun j -> j()) (!jends); with Exit -> let jends = ref [] in @@ -2642,20 +2806,28 @@ and eval_expr ctx e = ); r | TEnumParameter (ec,f,index) -> - let r = alloc_tmp ctx (match to_type ctx ec.etype with HEnum e -> let _,_,args = e.efields.(f.ef_index) in args.(index) | _ -> assert false) in - op ctx (OEnumField (r,eval_expr ctx ec,f.ef_index,index)); + let pt, is_single = (match to_type ctx ec.etype with + | HEnum e -> + let _,_,args = e.efields.(f.ef_index) in + args.(index), Array.length e.efields = 1 + | _ -> assert false + ) in + let er = eval_expr ctx ec in + if is_single then op ctx (ONullCheck er); (* #7560 *) + let r = alloc_tmp ctx pt in + op ctx (OEnumField (r,er,f.ef_index,index)); cast_to ctx r (to_type ctx e.etype) e.epos | TContinue -> before_break_continue ctx; let pos = current_pos ctx in op ctx (OJAlways (-1)); (* loop *) - ctx.m.mcontinues <- (fun target -> DynArray.set ctx.m.mops pos (OJAlways (target - (pos + 1)))) :: ctx.m.mcontinues; + ctx.m.mcontinues <- (fun target -> set_op ctx pos (OJAlways (target - (pos + 1)))) :: ctx.m.mcontinues; alloc_tmp ctx HVoid | TBreak -> before_break_continue ctx; let pos = current_pos ctx in op ctx (OJAlways (-1)); (* loop *) - ctx.m.mbreaks <- (fun target -> DynArray.set ctx.m.mops pos (OJAlways (target - (pos + 1)))) :: ctx.m.mbreaks; + ctx.m.mbreaks <- (fun target -> set_op ctx pos (OJAlways (target - (pos + 1)))) :: ctx.m.mbreaks; alloc_tmp ctx HVoid | TTry (etry,catches) -> let pos = current_pos ctx in @@ -2669,7 +2841,7 @@ and eval_expr ctx e = ctx.m.mtrys <- ctx.m.mtrys - 1; op ctx (OEndTrap true); let j = jump ctx (fun n -> OJAlways n) in - DynArray.set ctx.m.mops pos (OTrap (rtrap, current_pos ctx - (pos + 1))); + set_op ctx pos (OTrap (rtrap, current_pos ctx - (pos + 1))); let rec loop l = match l with | [] -> @@ -2677,7 +2849,7 @@ and eval_expr ctx e = [] | (v,ec) :: next -> let rv = alloc_var ctx v true in - let jnext = if v.v_type == t_dynamic then begin + let jnext = if follow v.v_type == t_dynamic then begin op ctx (OMov (rv, rtrap)); (fun() -> ()) end else @@ -2693,12 +2865,12 @@ and eval_expr ctx e = let rb = alloc_tmp ctx HBool in op ctx (OCall2 (rb, alloc_fun_path ctx (["hl"],"BaseType") "check",r,rtrap)); let jnext = jump ctx (fun n -> OJFalse (rb,n)) in - op ctx (OMov (rv, unsafe_cast_to ctx rtrap (to_type ctx v.v_type) ec.epos)); + op ctx (OMov (rv, unsafe_cast_to ~debugchk:false ctx rtrap (to_type ctx v.v_type) ec.epos)); jnext in let r = eval_expr ctx ec in if tret <> HVoid then op ctx (OMov (result,cast_to ctx r tret ec.epos)); - if v.v_type == t_dynamic then [] else + if follow v.v_type == t_dynamic then [] else let jend = jump ctx (fun n -> OJAlways n) in jnext(); jend :: loop next @@ -2711,14 +2883,29 @@ and eval_expr ctx e = | TCast (ev,Some _) -> let t = to_type ctx e.etype in let re = eval_expr ctx ev in - let r = alloc_tmp ctx t in + let rt = alloc_tmp ctx t in if safe_cast (rtype ctx re) t then - op ctx (OMov (r,re)) - else - op ctx (OSafeCast (r,re)); - r + op ctx (OMov (rt,re)) + else (match Abstract.follow_with_abstracts e.etype with + | TInst({ cl_interface = true } as c,_) -> + hold ctx re; + let c = eval_to ctx { eexpr = TTypeExpr(TClassDecl c); epos = e.epos; etype = t_dynamic } (class_type ctx ctx.base_type [] false) in + hold ctx c; + let rb = alloc_tmp ctx HBool in + op ctx (OCall2 (rb, alloc_fun_path ctx (["hl"],"BaseType") "check",c,re)); + let jnext = jump ctx (fun n -> OJTrue (rb,n)) in + let jnext2 = jump ctx (fun n -> OJNull (re,n)) in + op ctx (OThrow (make_string ctx "Cast error" e.epos)); + jnext(); + jnext2(); + op ctx (OMov (rt, unsafe_cast_to ~debugchk:false ctx re (to_type ctx e.etype) e.epos)); + free ctx c; + free ctx re; + | _ -> + op ctx (OSafeCast (rt,re))); + rt | TIdent s -> - assert false + abort ("Unbound identifier " ^ s) e.epos and gen_assign_op ctx acc e1 f = let f r = @@ -2815,14 +3002,15 @@ and gen_assign_op ctx acc e1 f = r | ADynamic (eobj, fid) -> let robj = eval_null_check ctx eobj in + hold ctx robj; let t = real_type ctx e1 in let r = alloc_tmp ctx t in op ctx (ODynGet (r,robj,fid)); - hold ctx robj; let r = cast_to ctx r (to_type ctx e1.etype) e1.epos in let r = f r in + let r = cast_to ctx r t e1.epos in free ctx robj; - op ctx (ODynSet (robj,fid,cast_to ctx r t e1.epos)); + op ctx (ODynSet (robj,fid,r)); r | ANone | ALocal _ | AStaticFun _ | AInstanceFun _ | AInstanceProto _ | AVirtualMethod _ | AEnum _ -> assert false @@ -2890,7 +3078,7 @@ and gen_method_wrapper ctx rt t p = hold ctx r; r ) targs in - let casts = List.map2 (fun r t -> let r2 = cast_to ctx r t p in hold ctx r2; free ctx r; r2) rargs iargs in + let casts = List.map2 (fun r t -> let r2 = cast_to ~force:true ctx r t p in hold ctx r2; free ctx r; r2) rargs iargs in List.iter (free ctx) casts; let rret = alloc_tmp ctx iret in op ctx (OCallClosure (rret,rfun,casts)); @@ -2902,10 +3090,10 @@ and gen_method_wrapper ctx rt t p = regs = DynArray.to_array ctx.m.mregs.arr; code = DynArray.to_array ctx.m.mops; debug = make_debug ctx ctx.m.mdebug; + assigns = Array.of_list (List.rev ctx.m.massign); } in ctx.m <- old; DynArray.add ctx.cfunctions f; - DynArray.add ctx.cdebug_assigns [||]; fid and make_fun ?gen_content ctx name fidx f cthis cparent = @@ -2943,7 +3131,7 @@ and make_fun ?gen_content ctx name fidx f cthis cparent = let args = List.map (fun (v,o) -> let t = to_type ctx v.v_type in let r = alloc_var ctx (if o = None then v else { v with v_type = if not (is_nullable t) then TAbstract(ctx.ref_abstract,[v.v_type]) else v.v_type }) true in - add_assign ctx v r; + add_assign ctx v; (* record var name *) rtype ctx r ) f.tf_args in @@ -2966,65 +3154,66 @@ and make_fun ?gen_content ctx name fidx f cthis cparent = let vt = to_type ctx v.v_type in let capt = captured_index ctx v in (match o with - | None | Some TNull -> () + | None | Some {eexpr = TConst TNull} -> () | Some c when not (is_nullable vt) -> (* if optional but not null, turn into a not nullable here *) let j = jump ctx (fun n -> OJNotNull (r,n)) in let t = alloc_tmp ctx vt in (match vt with | HUI8 | HUI16 | HI32 | HI64 -> - (match c with - | TInt i -> op ctx (OInt (t,alloc_i32 ctx i)) - | TFloat s -> op ctx (OInt (t,alloc_i32 ctx (Int32.of_float (float_of_string s)))) + (match c.eexpr with + | TConst (TInt i) -> op ctx (OInt (t,alloc_i32 ctx i)) + | TConst (TFloat s) -> op ctx (OInt (t,alloc_i32 ctx (Int32.of_float (float_of_string s)))) | _ -> assert false) | HF32 | HF64 -> - (match c with - | TInt i -> op ctx (OFloat (t,alloc_float ctx (Int32.to_float i))) - | TFloat s -> op ctx (OFloat (t,alloc_float ctx (float_of_string s))) + (match c.eexpr with + | TConst (TInt i) -> op ctx (OFloat (t,alloc_float ctx (Int32.to_float i))) + | TConst (TFloat s) -> op ctx (OFloat (t,alloc_float ctx (float_of_string s))) | _ -> assert false) | HBool -> - (match c with - | TBool b -> op ctx (OBool (t,b)) + (match c.eexpr with + | TConst (TBool b) -> op ctx (OBool (t,b)) | _ -> assert false) | _ -> assert false); - if capt = None then add_assign ctx v t; + if capt = None then add_assign ctx v; let jend = jump ctx (fun n -> OJAlways n) in j(); op ctx (OUnref (t,r)); - if capt = None then add_assign ctx v t; + if capt = None then add_assign ctx v; jend(); Hashtbl.replace ctx.m.mvars v.v_id t; free ctx r; hold ctx t | Some c -> let j = jump ctx (fun n -> OJNotNull (r,n)) in - (match c with - | TNull | TThis | TSuper -> assert false - | TInt i when (match to_type ctx (follow v.v_type) with HUI8 | HUI16 | HI32 | HI64 | HDyn -> true | _ -> false) -> + (match c.eexpr with + | TConst (TNull | TThis | TSuper) -> assert false + | TConst (TInt i) when (match to_type ctx (Abstract.follow_with_abstracts v.v_type) with HUI8 | HUI16 | HI32 | HI64 | HDyn -> true | _ -> false) -> let tmp = alloc_tmp ctx HI32 in op ctx (OInt (tmp, alloc_i32 ctx i)); op ctx (OToDyn (r, tmp)); - | TFloat s when (match to_type ctx (follow v.v_type) with HUI8 | HUI16 | HI32 | HI64 -> true | _ -> false) -> + | TConst (TFloat s) when (match to_type ctx (Abstract.follow_with_abstracts v.v_type) with HUI8 | HUI16 | HI32 | HI64 -> true | _ -> false) -> let tmp = alloc_tmp ctx HI32 in op ctx (OInt (tmp, alloc_i32 ctx (Int32.of_float (float_of_string s)))); op ctx (OToDyn (r, tmp)); - | TInt i -> + | TConst (TInt i) -> let tmp = alloc_tmp ctx HF64 in op ctx (OFloat (tmp, alloc_float ctx (Int32.to_float i))); op ctx (OToDyn (r, tmp)); - | TFloat s -> + | TConst (TFloat s) -> let tmp = alloc_tmp ctx HF64 in op ctx (OFloat (tmp, alloc_float ctx (float_of_string s))); op ctx (OToDyn (r, tmp)); - | TBool b -> + | TConst (TBool b) -> let tmp = alloc_tmp ctx HBool in op ctx (OBool (tmp, b)); op ctx (OToDyn (r, tmp)); - | TString s -> + | TConst (TString s) -> op ctx (OMov (r, make_string ctx s f.tf_expr.epos)) + | _ -> + op ctx (OMov (r, eval_to ctx c vt)) ); - if capt = None then add_assign ctx v r; j(); ); (match capt with @@ -3047,6 +3236,7 @@ and make_fun ?gen_content ctx name fidx f cthis cparent = | TReturn _ -> false | _ -> true in + set_curpos ctx (max_pos f.tf_expr); if tret = HVoid then op ctx (ORet (alloc_tmp ctx HVoid)) else if has_final_jump f.tf_expr then begin @@ -3059,44 +3249,59 @@ and make_fun ?gen_content ctx name fidx f cthis cparent = op ctx (ORet r) end; let fargs = (match tthis with None -> [] | Some t -> [t]) @ (match rcapt with None -> [] | Some r -> [rtype ctx r]) @ args in - let f = { + let hlf = { fpath = name; findex = fidx; ftype = HFun (fargs, tret); regs = DynArray.to_array ctx.m.mregs.arr; code = DynArray.to_array ctx.m.mops; debug = make_debug ctx ctx.m.mdebug; + assigns = Array.of_list (List.rev ctx.m.massign); } in - let assigns = Array.of_list (List.rev ctx.m.massign) in ctx.m <- old; Hashtbl.add ctx.defined_funs fidx (); - let f = if ctx.optimize then Hlopt.optimize ctx.dump_out f else f in + let f = if ctx.optimize && (gen_content = None || name <> ("","")) then begin + let t = Timer.timer ["generate";"hl";"opt"] in + let f = Hlopt.optimize ctx.dump_out (DynArray.get ctx.cstrings.arr) hlf f in + t(); + f + end else + hlf + in DynArray.add ctx.cfunctions f; - DynArray.add ctx.cdebug_assigns assigns; capt let generate_static ctx c f = match f.cf_kind with | Var _ -> () - | Method _ when Meta.has Meta.Extern f.cf_meta -> + | Method _ when has_class_field_flag f CfExtern -> () | Method m -> let add_native lib name = - ignore(lookup ctx.cnatives (name ^ "@" ^ lib) (fun() -> - let fid = alloc_fid ctx c f in + let fid = alloc_fid ctx c f in + ignore(lookup ctx.cnatives (name ^ "@" ^ lib,fid) (fun() -> Hashtbl.add ctx.defined_funs fid (); (alloc_string ctx lib, alloc_string ctx name,to_type ctx f.cf_type,fid) )); in let rec loop = function - | (Meta.Custom ":hlNative",[(EConst(String(lib)),_);(EConst(String(name)),_)] ,_ ) :: _ -> + | (Meta.HlNative,[(EConst(String(lib)),_);(EConst(String(name)),_)] ,_ ) :: _ -> add_native lib name - | (Meta.Custom ":hlNative",[(EConst(String(lib)),_)] ,_ ) :: _ -> + | (Meta.HlNative,[(EConst(String(lib)),_)] ,_ ) :: _ -> add_native lib f.cf_name - | (Meta.Custom ":hlNative",[] ,_ ) :: _ -> + | (Meta.HlNative,[(EConst(Float(ver)),_)] ,_ ) :: _ -> + let cur_ver = (try Common.raw_defined_value ctx.com "hl-ver" with Not_found -> "") in + if cur_ver < ver then + let gen_content() = + op ctx (OThrow (make_string ctx ("Requires compiling with -D hl-ver=" ^ ver ^ " or higher") null_pos)); + in + ignore(make_fun ctx ~gen_content (s_type_path c.cl_path,f.cf_name) (alloc_fid ctx c f) (match f.cf_expr with Some { eexpr = TFunction f } -> f | _ -> abort "Missing function body" f.cf_pos) None None) + else add_native "std" f.cf_name - | (Meta.Custom ":hlNative",_ ,p) :: _ -> + | (Meta.HlNative,[] ,_ ) :: _ -> + add_native "std" f.cf_name + | (Meta.HlNative,_ ,p) :: _ -> abort "Invalid @:hlNative decl" p | [] -> ignore(make_fun ctx (s_type_path c.cl_path,f.cf_name) (alloc_fid ctx c f) (match f.cf_expr with Some { eexpr = TFunction f } -> f | _ -> abort "Missing function body" f.cf_pos) None None) @@ -3114,7 +3319,7 @@ let rec generate_member ctx c f = let gen_content = if f.cf_name <> "new" then None else Some (fun() -> let o = (match class_type ctx c (List.map snd c.cl_params) false with - | HObj o -> o + | HObj o | HStruct o -> o | _ -> assert false ) in @@ -3152,7 +3357,7 @@ let generate_type ctx t = List.iter (fun f -> List.iter (fun (name,args,pos) -> match name with - | Meta.Custom ":hlNative" -> generate_static ctx c f + | Meta.HlNative -> generate_static ctx c f | _ -> () ) f.cf_meta ) c.cl_ordered_statics @@ -3160,7 +3365,22 @@ let generate_type ctx t = List.iter (generate_static ctx c) c.cl_ordered_statics; (match c.cl_constructor with | None -> () - | Some f -> generate_member ctx c f); + | Some f -> + let merge_inits e = + match e with + | Some ({ eexpr = TFunction ({ tf_expr = { eexpr = TBlock el } as ef } as f) } as e) -> + let merge ei = + let rec loop ei = + let ei = Type.map_expr loop ei in + { ei with epos = e.epos } + in + if ei.epos.pmin < e.epos.pmin || ei.epos.pmax > e.epos.pmax then loop ei else ei + in + Some { e with eexpr = TFunction({ f with tf_expr = { ef with eexpr = TBlock (List.map merge el) }}) } + | _ -> + e + in + generate_member ctx c { f with cf_expr = merge_inits f.cf_expr }); List.iter (generate_member ctx c) c.cl_ordered_fields; | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ -> () @@ -3260,7 +3480,7 @@ let generate_static_init ctx types main = op ctx (OSetGlobal (g, rt)); end; - (match Codegen.build_metadata ctx.com (TClassDecl c) with + (match Texpr.build_metadata ctx.com.basic (TClassDecl c) with | None -> () | Some e -> let r = eval_to ctx e HDyn in @@ -3306,7 +3526,7 @@ let generate_static_init ctx types main = op ctx (OSetGlobal (g,r)); ) e.e_names; - (match Codegen.build_metadata ctx.com (TEnumDecl e) with + (match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with | None -> () | Some e -> op ctx (OSetField (r,index "__meta__",eval_to ctx e HDyn))); @@ -3345,10 +3565,11 @@ let generate_static_init ctx types main = ) types; in (* init class statics *) + let init_exprs = ref [] in List.iter (fun t -> + (match t with TClassDecl { cl_init = Some e } -> init_exprs := e :: !init_exprs | _ -> ()); match t with | TClassDecl c when not c.cl_extern -> - (match c.cl_init with None -> () | Some e -> exprs := e :: !exprs); List.iter (fun f -> match f.cf_kind, f.cf_expr with | Var _, Some e -> @@ -3365,7 +3586,8 @@ let generate_static_init ctx types main = | None -> () | Some e -> exprs := e :: !exprs); let fid = lookup_alloc ctx.cfids () in - ignore(make_fun ~gen_content ctx ("","") fid { tf_expr = mk (TBlock (List.rev !exprs)) t_void null_pos; tf_args = []; tf_type = t_void } None None); + let exprs = List.rev !init_exprs @ List.rev !exprs in + ignore(make_fun ~gen_content ctx ("","") fid { tf_expr = mk (TBlock exprs) t_void null_pos; tf_args = []; tf_type = t_void } None None); fid (* --------------------------------------------------------------------------------------------------------------------- *) @@ -3499,10 +3721,12 @@ let write_code ch code debug = write_index (Array.length code.ints); write_index (Array.length code.floats); write_index (Array.length code.strings); + if code.version >= 5 then write_index (Array.length code.bytes); write_index (Array.length all_types); write_index (Array.length code.globals); write_index (Array.length code.natives); write_index (Array.length code.functions); + write_index (Array.length code.constants); write_index code.entrypoint; Array.iter (IO.write_real_i32 ch) code.ints; @@ -3517,6 +3741,19 @@ let write_code ch code debug = in write_strings code.strings; + let write_bytes bytes = + let bytes_length = ref 0 in + Array.iter (fun b -> bytes_length := !bytes_length + Bytes.length b) bytes; + IO.write_i32 ch !bytes_length; + Array.iter (IO.nwrite ch) bytes; + let bytes_pos = ref 0 in + Array.iter (fun b -> + write_index (!bytes_pos); + bytes_pos := !bytes_pos + Bytes.length b + ) bytes; + in + if code.version >= 5 then write_bytes code.bytes; + if debug then begin write_index (Array.length code.debugfiles); write_strings code.debugfiles; @@ -3534,15 +3771,15 @@ let write_code ch code debug = | HBool -> byte 7 | HBytes -> byte 8 | HDyn -> byte 9 - | HFun (args,ret) -> + | HFun (args,ret) | HMethod (args,ret) -> let n = List.length args in if n > 0xFF then assert false; - byte 10; + byte (match t with HFun _ -> 10 | _ -> 20); byte n; List.iter write_type args; write_type ret - | HObj p -> - byte 11; + | HObj p | HStruct p -> + byte (if is_struct t then 21 else 11); write_index p.pid; (match p.psuper with | None -> write_index (-1) @@ -3647,8 +3884,20 @@ let write_code ch code debug = write_index (Array.length f.code); Array.iter write_type f.regs; Array.iter write_op f.code; - if debug then write_debug_infos f.debug; - ) code.functions + if debug then begin + write_debug_infos f.debug; + write_index (Array.length f.assigns); + Array.iter (fun (i,p) -> + write_index i; + write_index (p + 1); + ) f.assigns; + end; + ) code.functions; + Array.iter (fun (g,fields) -> + write_index g; + write_index (Array.length fields); + Array.iter write_index fields; + ) code.constants (* --------------------------------------------------------------------------------------------------------------------- *) @@ -3679,9 +3928,11 @@ let create_context com is_macro dump = m = method_context 0 HVoid null_capture false; cints = new_lookup(); cstrings = new_lookup(); + cbytes = new_lookup(); cfloats = new_lookup(); cglobals = new_lookup(); cnatives = new_lookup(); + cconstants = new_lookup(); cfunctions = DynArray.create(); overrides = Hashtbl.create 0; cached_types = PMap.empty; @@ -3704,13 +3955,13 @@ let create_context com is_macro dump = core_type = get_class "CoreType"; core_enum = get_class "CoreEnum"; ref_abstract = get_abstract "Ref"; - anons_cache = []; + anons_cache = PMap.empty; rec_cache = []; method_wrappers = PMap.empty; cdebug_files = new_lookup(); macro_typedefs = Hashtbl.create 0; - cdebug_locals = new_lookup(); - cdebug_assigns = DynArray.create(); + ct_delayed = []; + ct_depth = 0; } in ignore(alloc_string ctx ""); ignore(class_type ctx ctx.base_class [] false); @@ -3732,7 +3983,7 @@ let add_types ctx types = in if not ctx.is_macro then List.iter (fun f -> ignore(loop c.cl_super f)) c.cl_overrides; List.iter (fun (m,args,p) -> - if m = Meta.Custom ":hlNative" then + if m = Meta.HlNative then let lib, prefix = (match args with | [(EConst (String lib),_)] -> lib, "" | [(EConst (String lib),_);(EConst (String p),_)] -> lib, p @@ -3741,11 +3992,11 @@ let add_types ctx types = (* adds :hlNative for all empty methods *) List.iter (fun f -> match f.cf_kind with - | Method MethNormal when not (List.exists (fun (m,_,_) -> m = Meta.Custom ":hlNative") f.cf_meta) -> + | Method MethNormal when not (List.exists (fun (m,_,_) -> m = Meta.HlNative) f.cf_meta) -> (match f.cf_expr with | Some { eexpr = TFunction { tf_expr = { eexpr = TBlock ([] | [{ eexpr = TReturn (Some { eexpr = TConst _ })}]) } } } | None -> let name = prefix ^ String.lowercase (Str.global_replace (Str.regexp "[A-Z]+") "_\\0" f.cf_name) in - f.cf_meta <- (Meta.Custom ":hlNative", [(EConst (String lib),p);(EConst (String name),p)], p) :: f.cf_meta; + f.cf_meta <- (Meta.HlNative, [(EConst (String lib),p);(EConst (String name),p)], p) :: f.cf_meta; | _ -> ()) | _ -> () ) c.cl_ordered_statics @@ -3756,16 +4007,19 @@ let add_types ctx types = let build_code ctx types main = let ep = generate_static_init ctx types main in + let bytes = DynArray.to_array ctx.cbytes.arr in { - version = 2; + version = if Array.length bytes = 0 then 4 else 5; entrypoint = ep; strings = DynArray.to_array ctx.cstrings.arr; + bytes = bytes; ints = DynArray.to_array ctx.cints.arr; floats = DynArray.to_array ctx.cfloats.arr; globals = DynArray.to_array ctx.cglobals.arr; natives = DynArray.to_array ctx.cnatives.arr; functions = DynArray.to_array ctx.cfunctions; debugfiles = DynArray.to_array ctx.cdebug_files.arr; + constants = DynArray.to_array ctx.cconstants.arr; } let check ctx = @@ -3800,7 +4054,7 @@ let generate com = check ctx; Hlinterp.check code false; end; - let t = Common.timer ["write";"hl"] in + let t = Timer.timer ["generate";"hl";"write"] in let escape_command s = let b = Buffer.create 0 in @@ -3809,47 +4063,28 @@ let generate com = in if file_extension com.file = "c" then begin - Hl2c.write_c com com.file code; - let t = Common.timer ["nativecompile";"hl"] in + let gnames = Array.create (Array.length code.globals) "" in + PMap.iter (fun n i -> gnames.(i) <- n) ctx.cglobals.map; + Hl2c.write_c com com.file code gnames; + let t = Timer.timer ["nativecompile";"hl"] in if not (Common.defined com Define.NoCompilation) && com.run_command ("haxelib run hashlink build " ^ escape_command com.file) <> 0 then failwith "Build failed"; t(); end else begin let ch = IO.output_string() in - write_code ch code true; + write_code ch code (not (Common.raw_defined com "hl-no-debug")); let str = IO.close_out ch in let ch = open_out_bin com.file in output_string ch str; close_out ch; -(* - let ch = IO.output_string() in - let byte = IO.write_byte ch in - let write_index = write_index_gen byte in - write_index (DynArray.length ctx.cdebug_locals.arr); - DynArray.iter (fun s -> - write_index (String.length s); - IO.write_string ch s; - ) ctx.cdebug_locals.arr; - write_index (DynArray.length ctx.cdebug_assigns); - DynArray.iter (fun a -> - write_index (Array.length a); - Array.iter (fun (i,p,r) -> - write_index i; - write_index p; - write_index r; - ) a; - ) ctx.cdebug_assigns; - let str = IO.close_out ch in - let dbg = open_out_bin (com.file ^ "d") in - output_string dbg str; - close_out dbg; *) end; + Hlopt.clean_cache(); t(); if Common.raw_defined com "run" then begin if com.run_command ("haxelib run hashlink run " ^ escape_command com.file) <> 0 then failwith "Failed to run HL"; end; if Common.defined com Define.Interp then try - let t = Common.timer ["generate";"hl";"interp"] in + let t = Timer.timer ["generate";"hl";"interp"] in let ctx = Hlinterp.create true in Hlinterp.add_code ctx code; t(); diff --git a/src/generators/genhxold.ml b/src/generators/genhxold.ml new file mode 100644 index 00000000000..943798a86bd --- /dev/null +++ b/src/generators/genhxold.ml @@ -0,0 +1,303 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals +open Ast +open Type +open Common +open ExtString + +let rec create_dir acc = function + | [] -> () + | d :: l -> + let path = acc ^ "/" ^ d in + (try Unix.mkdir path 0o777 with _ -> ()); + create_dir path l + + +let conv_path p = + match List.rev (fst p) with + | x :: l when starts_with x '_' -> List.rev (("priv" ^ x) :: l), snd p + | _ -> p + +let get_real_path meta path = + try + let real_path = match Meta.get Meta.RealPath meta with + | (_,[(EConst(String s),_)],_) -> + s + | _ -> raise Not_found + in + match List.rev (String.nsplit real_path ".") with + | name :: pack -> + (List.rev pack), name + | _ -> raise Not_found + with | Not_found -> + path + +let generate_type com t = + let base_path = "hxclasses" in + match t with TClassDecl { cl_kind = KAbstractImpl _ } -> () | _ -> + let pack, name = + let info = t_infos t in + get_real_path info.mt_meta info.mt_path + in + create_dir "." (base_path :: pack); + match pack, name with + | ["flash";"net"], "NetStreamPlayTransitions" + | ["flash";"filters"], "BitmapFilterQuality" + | ["flash";"display"], ("BitmapDataChannel" | "GraphicsPathCommand") -> () + | _ -> + let f = open_out_bin (base_path ^ "/" ^ (match pack with [] -> "" | l -> String.concat "/" l ^ "/") ^ name ^ ".hx") in + let ch = IO.output_channel f in + let p fmt = IO.printf ch fmt in + if pack <> [] then IO.printf ch "package %s;\n\n" (String.concat "." pack); + let rec notnull t = + match t with + | TMono r -> + (match !r with + | None -> t + | Some t -> notnull t) + | TLazy f -> + notnull (lazy_type f) + | TAbstract ({ a_path = [],"Null" },[t]) -> + t + | _ -> + t + in + let rec path meta p tl = + let p = conv_path (get_real_path meta p) in + (if fst p = pack then snd p else s_type_path p) ^ (match tl with [] -> "" | _ -> "<" ^ String.concat "," (List.map stype tl) ^ ">") + and stype t = + match t with + | TMono r -> + (match !r with + | None -> "Unknown" + | Some t -> stype t) + | TInst ({ cl_kind = KTypeParameter _ } as c,tl) -> + path [] ([],snd c.cl_path) tl + | TInst (c,tl) -> + path c.cl_meta c.cl_path tl + | TEnum (e,tl) -> + path e.e_meta e.e_path tl + | TType (t,tl) -> + path t.t_meta t.t_path tl + | TAbstract (a,tl) -> + path a.a_meta a.a_path tl + | TAnon a -> + let fields = PMap.fold (fun f acc -> (f.cf_name ^ " : " ^ stype f.cf_type) :: acc) a.a_fields [] in + "{" ^ String.concat ", " fields ^ "}" + | TLazy f -> + stype (lazy_type f) + | TDynamic t2 -> + if t == t2 then "Dynamic" else "Dynamic<" ^ stype t2 ^ ">" + | TFun ([],ret) -> + "Void -> " ^ ftype ret + | TFun (args,ret) -> + String.concat " -> " (List.map (fun (_,_,t) -> ftype t) args) ^ " -> " ^ ftype ret + and ftype t = + match t with + | TMono r -> + (match !r with + | None -> stype t + | Some t -> ftype t) + | TLazy f -> + ftype (lazy_type f) + | TFun _ -> + "(" ^ stype t ^ ")" + | _ -> + stype t + in + let sparam (n,v,t) = + match v with + | None -> + n ^ " : " ^ stype t + | Some (Ident "null") -> + if is_nullable (notnull t) then + "?" ^ n ^ " : " ^ stype (notnull t) + else + (* we have not found a default value stored in metadata, let's generate it *) + n ^ " : " ^ stype t ^ " = " ^ (match follow t with + | TAbstract ({ a_path = [],("Int"|"Float"|"UInt") },_) -> "0" + | TAbstract ({ a_path = [],"Bool" },_) -> "false" + | _ -> "null") + | Some v -> + n ^ " : " ^ stype t ^ " = " ^ (match s_constant v with "nan" -> "0./*NaN*/" | v -> v) + in + let print_meta ml = + List.iter (fun (m,pl,_) -> + match m with + | Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed | Meta.FlatEnum | Meta.Value | Meta.DirectlyUsed | Meta.Enum | Meta.Impl -> () + | _ -> + match pl with + | [] -> p "@%s " (Meta.to_string m) + | l -> p "@%s(%s) " (Meta.to_string m) (String.concat "," (List.map Ast.Printer.s_expr pl)) + ) ml + in + let access is_read a = s_access is_read a in + let rec print_field stat f = + p "\t"; + print_meta f.cf_meta; + if not (has_class_field_flag f CfPublic) then p "private "; + if stat then p "static "; + let name = try (match Meta.get Meta.RealPath f.cf_meta with + | (Meta.RealPath, [EConst( String s ), _], _) -> + s + | _ -> + raise Not_found) + with Not_found -> + f.cf_name + in + (match f.cf_kind with + | Var v -> + if has_class_field_flag f CfFinal then + p "final %s" name + else begin + p "var %s" name; + if v.v_read <> AccNormal || v.v_write <> AccNormal then p "(%s,%s)" (access true v.v_read) (access false v.v_write); + end; + p " : %s" (stype f.cf_type); + | Method m -> + let params, ret = (match follow f.cf_type with + | TFun (args,ret) -> + List.map (fun (a,o,t) -> + let rec loop = function + | [] -> Ident "null" + | (Meta.DefParam,[(EConst (String p),_);(EConst v,_)],_) :: _ when p = a -> + (match v with + | Float "1.#QNAN" -> Float "0./*NaN*/" + | Float "4294967295." -> Int "0xFFFFFFFF" + | Int "16777215" -> Int "0xFFFFFF" + | Float x -> + (try + let f = float_of_string x in + let s = string_of_int (int_of_float f) in + if s ^ "." = x then Int s else v + with _ -> + v) + | _ -> v) + | _ :: l -> loop l + in + a,(if o then Some (loop f.cf_meta) else None ),t + ) args, ret + | _ -> + assert false + ) in + let tparams = (match f.cf_params with [] -> "" | l -> "<" ^ String.concat "," (List.map fst l) ^ ">") in + p "function %s%s(%s) : %s" name tparams (String.concat ", " (List.map sparam params)) (stype ret); + ); + p ";\n"; + if Meta.has Meta.Overload f.cf_meta then List.iter (fun f -> print_field stat f) f.cf_overloads + in + (match t with + | TClassDecl c -> + print_meta c.cl_meta; + let finalmod = if c.cl_final then "final " else "" in + p "extern %s%s %s" finalmod (if c.cl_interface then "interface" else "class") (stype (TInst (c,List.map snd c.cl_params))); + let ext = (match c.cl_super with + | None -> [] + | Some (c,pl) -> [" extends " ^ stype (TInst (c,pl))] + ) in + let ext = List.fold_left (fun acc (i,pl) -> ((if c.cl_interface then " extends " else " implements ") ^ stype (TInst (i,pl))) :: acc) ext c.cl_implements in + let ext = (match c.cl_dynamic with + | None -> ext + | Some t -> + (match c.cl_path with + | ["flash";"errors"], _ -> ext + | _ when t == t_dynamic -> " implements Dynamic" :: ext + | _ -> (" implements Dynamic<" ^ stype t ^ ">") :: ext) + ) in + let ext = (match c.cl_path with + | ["flash";"utils"], "ByteArray" -> " implements ArrayAccess" :: ext + | ["flash";"utils"], "Dictionary" -> [" implements ArrayAccess"] + | ["flash";"xml"], "XML" -> [" implements Dynamic"] + | ["flash";"xml"], "XMLList" -> [" implements ArrayAccess"] + | ["flash";"display"],"MovieClip" -> [" extends Sprite #if !flash_strict implements Dynamic #end"] + | ["flash";"errors"], "Error" -> [" #if !flash_strict implements Dynamic #end"] + | _ -> ext + ) in + p "%s" (String.concat "" (List.rev ext)); + p " {\n"; + let sort l = + let a = Array.of_list (List.filter (fun f -> not (List.memq f c.cl_overrides)) l) in + let name = function "new" -> "" | n -> n in + Array.sort (fun f1 f2 -> + match f1.cf_kind, f2.cf_kind with + | Var _, Var _ | Method _ , Method _ -> compare (name f1.cf_name) (name f2.cf_name) + | Var _, _ -> -1 + | _ -> 1 + ) a; + Array.to_list a + in + List.iter (print_field false) (sort (match c.cl_constructor with None -> c.cl_ordered_fields | Some f -> f :: c.cl_ordered_fields)); + List.iter (print_field true) (sort c.cl_ordered_statics); + p "}\n"; + | TEnumDecl e -> + print_meta e.e_meta; + p "extern enum %s {\n" (stype (TEnum(e,List.map snd e.e_params))); + List.iter (fun n -> + let c = PMap.find n e.e_constrs in + p "\t%s" c.ef_name; + (match follow c.ef_type with + | TFun (args,_) -> p "(%s)" (String.concat ", " (List.map sparam (List.map (fun (a,o,t) -> a,(if o then Some (Ident "null") else None),t) args))) + | _ -> ()); + p ";\n"; + ) e.e_names; + p "}\n" + | TTypeDecl t -> + print_meta t.t_meta; + p "typedef %s = " (stype (TType (t,List.map snd t.t_params))); + p "%s" (stype t.t_type); + p "\n"; + | TAbstractDecl a -> + print_meta a.a_meta; + Option.may (fun c -> try print_meta [Meta.get Meta.Require c.cl_meta] with Not_found -> ()) a.a_impl; + p "extern "; + let is_enum = Meta.has Meta.Enum a.a_meta in + if is_enum then p "enum "; + p "abstract %s" (stype (TAbstract (a,List.map snd a.a_params))); + if not (Meta.has Meta.CoreType a.a_meta) then p "(%s)" (stype a.a_this); + p " {\n"; + Option.may (fun c -> + let fields = c.cl_ordered_statics in + let fields = + if is_enum then + let sort l = + let a = Array.of_list l in + Array.sort (fun a b -> compare a.cf_name b.cf_name) a; + Array.to_list a + in + sort fields + else + fields + in + + List.iter (fun f -> + let static = not (Meta.has Meta.Impl f.cf_meta) in + if not static && is_enum && Meta.has Meta.Enum f.cf_meta then begin + p "\tvar %s;\n" f.cf_name; + end else + print_field static f + ) fields + ) a.a_impl; + p "}\n"; + ); + IO.close_out ch + +let generate com = + List.iter (generate_type com) com.types diff --git a/src/generators/genjava.ml b/src/generators/genjava.ml index 1501de834fc..77ae7963950 100644 --- a/src/generators/genjava.ml +++ b/src/generators/genjava.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -198,7 +198,6 @@ let mk_cast_if_needed t_to e = else mk_cast t_to e - (* ******************************************* *) (* JavaSpecificESynf *) (* ******************************************* *) @@ -299,13 +298,18 @@ struct | TClassDecl{ cl_path = (["haxe"], "Int64") } -> mk_is true obj i64_md | TAbstractDecl{ a_path = ([], "Dynamic") } - | TClassDecl{ cl_path = ([], "Dynamic") } -> + | TClassDecl{ cl_path = ([], "Dynamic") } when not (is_nullable obj.etype) -> (match obj.eexpr with | TLocal _ | TConst _ -> { e with eexpr = TConst(TBool true) } | _ -> { e with eexpr = TBlock([run obj; { e with eexpr = TConst(TBool true) }]) } ) | _ -> - mk_is false obj md + if not (is_java_basic_type obj.etype) then + try + Type.unify obj.etype (type_of_module_type md); + mk_is false obj md + with Unify_error _ -> e + else e ) (* end Std.is() *) | _ -> Type.map_expr run e @@ -412,7 +416,7 @@ struct and modify it to: { var execute_def = true; - switch(str.hashCode()) + switch(str == null ? 0 : str.hashCode()) { case (hashcode of a): if (str == "a") @@ -575,7 +579,9 @@ struct (el, e) in - let switch = { eswitch with + let is_not_null_check = mk (TBinop (OpNotEq, local, { local with eexpr = TConst TNull })) basic.tbool local.epos in + let if_not_null e = { e with eexpr = TIf (is_not_null_check, e, None) } in + let switch = if_not_null { eswitch with eexpr = TSwitch(!local_hashcode, List.map change_case (reorder_cases ecases []), None); } in (if !has_case then begin @@ -940,7 +946,6 @@ let rec get_class_modifiers meta cl_type cl_access cl_modifiers = | (Meta.Internal,[],_) :: meta -> get_class_modifiers meta cl_type "" cl_modifiers (* no abstract for now | (":abstract",[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("abstract" :: cl_modifiers) | (Meta.Static,[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("static" :: cl_modifiers) TODO: support those types *) - | (Meta.Final,[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("final" :: cl_modifiers) | _ :: meta -> get_class_modifiers meta cl_type cl_access cl_modifiers let rec get_fun_modifiers meta access modifiers = @@ -957,12 +962,12 @@ let rec get_fun_modifiers meta access modifiers = let generate con = let exists = ref false in - con.java_libs <- List.map (fun (file,std,close,la,gr) -> - if String.ends_with file "hxjava-std.jar" then begin + List.iter (fun java_lib -> + if String.ends_with java_lib#get_file_path "hxjava-std.jar" then begin exists := true; - (file,true,close,la,gr) - end else - (file,std,close,la,gr)) con.java_libs; + java_lib#add_flag NativeLibraries.FlagIsStd; + end; + ) con.native_libs.java_libs; if not !exists then failwith "Your version of hxjava is outdated. Please update it by running: `haxelib update hxjava`"; let gen = new_ctx con in @@ -1210,68 +1215,72 @@ let generate con = | _ -> false in - let rec t_s pos t = - match real_type t with - (* basic types *) - | TAbstract ({ a_path = ([], "Bool") },[]) -> "boolean" - | TAbstract ({ a_path = ([], "Void") },[]) -> - path_s_import pos (["java";"lang"], "Object") [] - | TAbstract ({ a_path = ([],"Float") },[]) -> "double" - | TAbstract ({ a_path = ([],"Int") },[]) -> "int" - | TType ({ t_path = ["java"], "Int64" },[]) - | TAbstract ({ a_path = ["java"], "Int64" },[]) -> "long" - | TType ({ t_path = ["java"],"Int8" },[]) - | TAbstract ({ a_path = ["java"],"Int8" },[]) -> "byte" - | TType ({ t_path = ["java"],"Int16" },[]) - | TAbstract ({ a_path = ["java"],"Int16" },[]) -> "short" - | TType ({ t_path = ["java"],"Char16" },[]) - | TAbstract ({ a_path = ["java"],"Char16" },[]) -> "char" - | TType ({ t_path = [],"Single" },[]) - | TAbstract ({ a_path = [],"Single" },[]) -> "float" - | TInst ({ cl_path = ["haxe"],"Int32" },[]) - | TAbstract ({ a_path = ["haxe"],"Int32" },[]) -> "int" - | TInst ({ cl_path = ["haxe"],"Int64" },[]) - | TAbstract ({ a_path = ["haxe"],"Int64" },[]) -> "long" - | TInst({ cl_path = (["java"], "NativeArray") }, [param]) -> - let rec check_t_s t = - match real_type t with - | TInst({ cl_path = (["java"], "NativeArray") }, [param]) -> - (check_t_s param) ^ "[]" - | _ -> t_s pos (run_follow gen t) - in - (check_t_s param) ^ "[]" - - (* end of basic types *) - | TInst ({ cl_kind = KTypeParameter _; cl_path=p }, []) -> snd p - | TAbstract ({ a_path = [], "Dynamic" },[]) -> - path_s_import pos (["java";"lang"], "Object") [] - | TMono r -> (match !r with | None -> "java.lang.Object" | Some t -> t_s pos (run_follow gen t)) - | TInst ({ cl_path = [], "String" }, []) -> - path_s_import pos (["java";"lang"], "String") [] - | TAbstract ({ a_path = [], "Class" }, [p]) | TAbstract ({ a_path = [], "Enum" }, [p]) - | TInst ({ cl_path = [], "Class" }, [p]) | TInst ({ cl_path = [], "Enum" }, [p]) -> - path_param_s pos (TClassDecl cl_cl) (["java";"lang"], "Class") [p] [] - | TAbstract ({ a_path = [], "Class" }, _) | TAbstract ({ a_path = [], "Enum" }, _) - | TInst ({ cl_path = [], "Class" }, _) | TInst ({ cl_path = [], "Enum" }, _) -> - path_s_import pos (["java";"lang"], "Class") [] - | TEnum ({e_path = p; e_meta = meta}, _) -> - path_s_import pos p meta - | TInst (({cl_path = p; cl_meta = meta} as cl), _) when Meta.has Meta.Enum cl.cl_meta -> - path_s_import pos p meta - | TInst (({cl_path = p; cl_meta = meta} as cl), params) -> (path_param_s pos (TClassDecl cl) p params meta) - | TType (({t_path = p; t_meta = meta} as t), params) -> (path_param_s pos (TTypeDecl t) p params meta) - | TAnon (anon) -> - (match !(anon.a_status) with - | Statics _ | EnumStatics _ | AbstractStatics _ -> - path_s_import pos (["java";"lang"], "Class") [] - | _ -> - path_s_import pos (["java";"lang"], "Object") []) - | TDynamic _ -> + let rec t_s stack pos t = + if List.exists (fast_eq t) stack then + path_s_import pos (["java";"lang"], "Object") [] + else begin + let stack = t :: stack in + match real_type t with + (* basic types *) + | TAbstract ({ a_path = ([], "Bool") },[]) -> "boolean" + | TAbstract ({ a_path = ([], "Void") },[]) -> path_s_import pos (["java";"lang"], "Object") [] - (* No Lazy type nor Function type made. That's because function types will be at this point be converted into other types *) - | _ -> if !strict_mode then begin trace ("[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"); assert false end else "[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]" + | TAbstract ({ a_path = ([],"Float") },[]) -> "double" + | TAbstract ({ a_path = ([],"Int") },[]) -> "int" + | TType ({ t_path = ["java"], "Int64" },[]) + | TAbstract ({ a_path = ["java"], "Int64" },[]) -> "long" + | TType ({ t_path = ["java"],"Int8" },[]) + | TAbstract ({ a_path = ["java"],"Int8" },[]) -> "byte" + | TType ({ t_path = ["java"],"Int16" },[]) + | TAbstract ({ a_path = ["java"],"Int16" },[]) -> "short" + | TType ({ t_path = ["java"],"Char16" },[]) + | TAbstract ({ a_path = ["java"],"Char16" },[]) -> "char" + | TType ({ t_path = [],"Single" },[]) + | TAbstract ({ a_path = [],"Single" },[]) -> "float" + | TInst ({ cl_path = ["haxe"],"Int32" },[]) + | TAbstract ({ a_path = ["haxe"],"Int32" },[]) -> "int" + | TInst ({ cl_path = ["haxe"],"Int64" },[]) + | TAbstract ({ a_path = ["haxe"],"Int64" },[]) -> "long" + | TInst({ cl_path = (["java"], "NativeArray") }, [param]) -> + let rec check_t_s t = + match real_type t with + | TInst({ cl_path = (["java"], "NativeArray") }, [param]) -> + (check_t_s param) ^ "[]" + | _ -> t_s stack pos (run_follow gen t) + in + (check_t_s param) ^ "[]" - and param_t_s pos t = + (* end of basic types *) + | TInst ({ cl_kind = KTypeParameter _; cl_path=p }, []) -> snd p + | TAbstract ({ a_path = [], "Dynamic" },[]) -> + path_s_import pos (["java";"lang"], "Object") [] + | TMono r -> (match !r with | None -> "java.lang.Object" | Some t -> t_s stack pos (run_follow gen t)) + | TInst ({ cl_path = [], "String" }, []) -> + path_s_import pos (["java";"lang"], "String") [] + | TAbstract ({ a_path = [], "Class" }, [p]) | TAbstract ({ a_path = [], "Enum" }, [p]) + | TInst ({ cl_path = [], "Class" }, [p]) | TInst ({ cl_path = [], "Enum" }, [p]) -> + path_param_s stack pos (TClassDecl cl_cl) (["java";"lang"], "Class") [p] [] + | TAbstract ({ a_path = [], "Class" }, _) | TAbstract ({ a_path = [], "Enum" }, _) + | TInst ({ cl_path = [], "Class" }, _) | TInst ({ cl_path = [], "Enum" }, _) -> + path_s_import pos (["java";"lang"], "Class") [] + | TEnum ({e_path = p; e_meta = meta}, _) -> + path_s_import pos p meta + | TInst (({cl_path = p; cl_meta = meta} as cl), _) when Meta.has Meta.Enum cl.cl_meta -> + path_s_import pos p meta + | TInst (({cl_path = p; cl_meta = meta} as cl), params) -> (path_param_s stack pos (TClassDecl cl) p params meta) + | TType (({t_path = p; t_meta = meta} as t), params) -> (path_param_s stack pos (TTypeDecl t) p params meta) + | TAnon (anon) -> + (match !(anon.a_status) with + | Statics _ | EnumStatics _ | AbstractStatics _ -> + path_s_import pos (["java";"lang"], "Class") [] + | _ -> + path_s_import pos (["java";"lang"], "Object") []) + | TDynamic _ -> + path_s_import pos (["java";"lang"], "Object") [] + (* No Lazy type nor Function type made. That's because function types will be at this point be converted into other types *) + | _ -> if !strict_mode then begin trace ("[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"); assert false end else "[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]" + end + and param_t_s stack pos t = match run_follow gen t with | TAbstract ({ a_path = ([], "Bool") },[]) -> path_s_import pos (["java";"lang"], "Boolean") [] @@ -1301,18 +1310,22 @@ let generate con = | TAbstract ({ a_path = [],"Single" },[]) -> path_s_import pos (["java";"lang"], "Float") [] | TDynamic _ -> "?" - | TInst (cl, params) -> t_s pos (TInst(cl, change_param_type (TClassDecl cl) params)) - | TType (cl, params) -> t_s pos (TType(cl, change_param_type (TTypeDecl cl) params)) - | TEnum (e, params) -> t_s pos (TEnum(e, change_param_type (TEnumDecl e) params)) - | _ -> t_s pos t + | TInst (cl, params) -> t_s stack pos (TInst(cl, change_param_type (TClassDecl cl) params)) + | TType (cl, params) -> t_s stack pos (TType(cl, change_param_type (TTypeDecl cl) params)) + | TEnum (e, params) -> t_s stack pos (TEnum(e, change_param_type (TEnumDecl e) params)) + | _ -> t_s stack pos t - and path_param_s pos md path params meta = + and path_param_s stack pos md path params meta = match params with | [] -> path_s_import pos path meta | _ when has_tdynamic (change_param_type md params) -> path_s_import pos path meta - | _ -> sprintf "%s<%s>" (path_s_import pos path meta) (String.concat ", " (List.map (fun t -> param_t_s pos t) (change_param_type md params))) + | _ -> sprintf "%s<%s>" (path_s_import pos path meta) (String.concat ", " (List.map (fun t -> param_t_s stack pos t) (change_param_type md params))) in + let t_s = t_s [] + and param_t_s = param_t_s [] + and path_param_s = path_param_s [] in + let rett_s pos t = match t with | TAbstract ({ a_path = ([], "Void") },[]) -> "void" @@ -1397,7 +1410,7 @@ let generate con = else fun w p -> let cur_line = Lexer.get_error_line p in let file = Path.get_full_path p.pfile in - print w "//line %d \"%s\"" cur_line (Ast.s_escape file); newline w + print w "//line %d \"%s\"" cur_line (StringHelper.s_escape file); newline w in let extract_statements expr = @@ -1549,9 +1562,9 @@ let generate con = ) 0 el); write w "}" | TCall( ( { eexpr = TField(_, FStatic({ cl_path = ([], "String") }, { cf_name = "fromCharCode" })) } ), [cc] ) -> - write w "Character.toString((char) "; + write w "new java.lang.String( java.lang.Character.toChars((int) "; expr_s w cc; - write w ")" + write w ") )" | TCall ({ eexpr = TIdent "__is__" }, [ expr; { eexpr = TTypeExpr(md) } ] ) -> write w "( "; expr_s w expr; @@ -1930,13 +1943,13 @@ let generate con = end (* TODO see how (get,set) variable handle when they are interfaces *) | Method _ when not (Type.is_physical_field cf) || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) -> List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then - gen_class_field w ~is_overload:true is_static cl (Meta.has Meta.Final cf.cf_meta) cf + gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf ) cf.cf_overloads | Var _ | Method MethDynamic -> () | Method mkind -> List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then - gen_class_field w ~is_overload:true is_static cl (Meta.has Meta.Final cf.cf_meta) cf + gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf ) cf.cf_overloads; let is_virtual = is_new || (not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false) in let is_override = match cf.cf_name with @@ -2094,7 +2107,8 @@ let generate con = gen_annotations w cl.cl_meta; let clt, access, modifiers = get_class_modifiers cl.cl_meta (if cl.cl_interface then "interface" else "class") "public" [] in - let is_final = Meta.has Meta.Final cl.cl_meta in + let modifiers = if cl.cl_final then "final" :: modifiers else modifiers in + let is_final = cl.cl_final in write_parts w (access :: modifiers @ [clt; (change_clname (snd cl.cl_path))]); @@ -2149,6 +2163,8 @@ let generate con = | _ -> () with | Not_found -> () ); + write w "haxe.java.Init.init();"; + newline w; (match gen.gcon.main with | Some(expr) -> expr_s w (mk_block expr) @@ -2288,7 +2304,7 @@ let generate con = let cl_arg_exc = get_cl (get_type gen (["java";"lang"],"IllegalArgumentException")) in let cl_arg_exc_t = TInst (cl_arg_exc, []) in - let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_arg_exc_t pos in + let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [Texpr.Builder.make_string gen.gcon.basic msg pos])) cl_arg_exc_t pos in let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 mk_arg_exception in ClosuresToClass.configure gen closure_t; @@ -2379,7 +2395,7 @@ let generate con = let cl_field_exc = get_cl (get_type gen (["java";"lang"],"RuntimeException")) in let cl_field_exc_t = TInst (cl_field_exc, []) in - let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_field_exc_t pos in + let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [Texpr.Builder.make_string gen.gcon.basic msg pos])) cl_field_exc_t pos in let rcf_ctx = ReflectionCFs.new_ctx @@ -2557,7 +2573,7 @@ let generate con = { eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos } end in - let zero = ExprBuilder.make_int gen.gcon 0 e.epos in + let zero = Texpr.Builder.make_int gen.gcon.basic 0 e.epos in { e with eexpr = TBinop(op, handler, zero) } ); @@ -2585,12 +2601,14 @@ let generate con = ExpressionUnwrap.configure gen; - UnnecessaryCastsRemoval.configure gen; + (* UnnecessaryCastsRemoval.configure gen; *) IntDivisionSynf.configure gen; UnreachableCodeEliminationSynf.configure gen true; + ArraySpliceOptimization.configure gen; + ArrayDeclSynf.configure gen native_arr_cl change_param_type; JavaSpecificSynf.configure gen runtime_cl; @@ -2600,7 +2618,7 @@ let generate con = let str_cl = match gen.gcon.basic.tstring with | TInst(cl,_) -> cl | _ -> assert false in str_cl.cl_super <- Some (get_cl (get_type gen (["haxe";"lang"], "NativeString")), []); - mkdir_from_path (gen.gcon.file ^ "/src"); + Path.mkdir_from_path (gen.gcon.file ^ "/src"); let out_files = ref [] in @@ -2610,7 +2628,7 @@ let generate con = res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = null_pos } :: !res; let name = Codegen.escape_res_name name true in let full_path = gen.gcon.file ^ "/src/" ^ name in - mkdir_from_path full_path; + Path.mkdir_from_path full_path; let f = open_out_bin full_path in output_string f v; @@ -2629,7 +2647,7 @@ let generate con = RenameTypeParameters.run gen.gtypes_list; let parts = Str.split_delim (Str.regexp "[\\/]+") gen.gcon.file in - mkdir_recursive "" parts; + Path.mkdir_recursive "" parts; let source_dir = gen.gcon.file ^ "/src" in List.iter (fun md -> diff --git a/src/generators/genjs.ml b/src/generators/genjs.ml index 2d2078d9582..2c92cd328c9 100644 --- a/src/generators/genjs.ml +++ b/src/generators/genjs.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -27,13 +27,17 @@ type sourcemap = { sources_hash : (string, int) Hashtbl.t; mappings : Rbuffer.t; - mutable source_last_line : int; - mutable source_last_col : int; - mutable source_last_file : int; + mutable source_last_pos : sourcemap_pos; mutable print_comma : bool; mutable output_last_col : int; mutable output_current_col : int; - mutable current_expr : texpr option; + mutable current_expr : sourcemap_pos option; +} + +and sourcemap_pos = { + file : int; + line : int; + col : int; } type ctx = { @@ -44,8 +48,9 @@ type ctx = { smap : sourcemap option; js_modern : bool; js_flatten : bool; + has_resolveClass : bool; + has_interface_check : bool; es_version : int; - store_exception_stack : bool; mutable current : tclass; mutable statics : (tclass * string * texpr) list; mutable inits : texpr list; @@ -78,9 +83,6 @@ let s_path ctx = if ctx.js_flatten then Path.flat_path else dot_path let kwds = Hashtbl.create 0 -let setup_kwds lst = - List.iter (fun s -> Hashtbl.add kwds s ()) lst - let es3kwds = [ "abstract"; "boolean"; "break"; "byte"; "case"; "catch"; "char"; "class"; "const"; "continue"; "debugger"; "default"; "delete"; "do"; "double"; "else"; "enum"; "export"; "extends"; "false"; "final"; @@ -99,6 +101,12 @@ let es5kwds = [ "true"; "try"; "typeof"; "var"; "void"; "while"; "with"; "yield" ] +let setup_kwds com = + Hashtbl.reset kwds; + let es_version = get_es_version com in + let lst = if es_version >= 5 then es5kwds else es3kwds in + List.iter (fun s -> Hashtbl.add kwds s ()) lst + (* Identifiers Haxe reserves to make the JS output cleaner. These can still be used in untyped code (TLocal), but are escaped upon declaration. *) let kwds2 = @@ -124,25 +132,81 @@ let valid_js_ident s = with Exit -> false -let field s = if Hashtbl.mem kwds s || not (valid_js_ident s) then "[\"" ^ s ^ "\"]" else "." ^ s +let field s = if not (valid_js_ident s) then "[\"" ^ s ^ "\"]" else "." ^ s let ident s = if Hashtbl.mem kwds s then "$" ^ s else s let check_var_declaration v = if Hashtbl.mem kwds2 v.v_name then v.v_name <- "$" ^ v.v_name let anon_field s = if Hashtbl.mem kwds s || not (valid_js_ident s) then "'" ^ s ^ "'" else s -let static_field c s = - match s with - | "length" | "name" when not c.cl_extern || Meta.has Meta.HxGen c.cl_meta-> ".$" ^ s - | s -> field s +let static_field ctx c s = + match s with + | "length" | "name" when not c.cl_extern || Meta.has Meta.HxGen c.cl_meta-> + let with_dollar = ".$" ^ s in + if get_es_version ctx.com >= 6 then + try + let f = PMap.find s c.cl_statics in + match f.cf_kind with + | Method _ -> "." ^ s + | _ -> with_dollar + with Not_found -> + with_dollar + else + with_dollar + | s -> field s let has_feature ctx = Common.has_feature ctx.com let add_feature ctx = Common.add_feature ctx.com let unsupported p = abort "This expression cannot be compiled to Javascript" p +let encode_mapping smap pos = + if smap.print_comma then + Rbuffer.add_char smap.mappings ',' + else + smap.print_comma <- true; + + let base64_vlq number = + let encode_digit digit = + let chars = [| + 'A';'B';'C';'D';'E';'F';'G';'H';'I';'J';'K';'L';'M';'N';'O';'P'; + 'Q';'R';'S';'T';'U';'V';'W';'X';'Y';'Z';'a';'b';'c';'d';'e';'f'; + 'g';'h';'i';'j';'k';'l';'m';'n';'o';'p';'q';'r';'s';'t';'u';'v'; + 'w';'x';'y';'z';'0';'1';'2';'3';'4';'5';'6';'7';'8';'9';'+';'/' + |] in + Array.unsafe_get chars digit + in + let to_vlq number = + if number < 0 then + ((-number) lsl 1) + 1 + else + number lsl 1 + in + let rec loop vlq = + let shift = 5 in + let base = 1 lsl shift in + let mask = base - 1 in + let continuation_bit = base in + let digit = vlq land mask in + let next = vlq asr shift in + Rbuffer.add_char smap.mappings (encode_digit ( + if next > 0 then digit lor continuation_bit else digit)); + if next > 0 then loop next else () + in + loop (to_vlq number) + in + + base64_vlq (smap.output_current_col - smap.output_last_col); + base64_vlq (pos.file - smap.source_last_pos.file); + base64_vlq (pos.line - smap.source_last_pos.line); + base64_vlq (pos.col - smap.source_last_pos.col); + + smap.source_last_pos <- pos; + smap.output_last_col <- smap.output_current_col + +let noop () = () + +let add_mapping smap pos = + if pos.pmin < 0 then noop else -let add_mapping smap force e = - if e.epos.pmin < 0 then () else - let pos = e.epos in let file = try Hashtbl.find smap.sources_hash pos.pfile with Not_found -> @@ -151,55 +215,23 @@ let add_mapping smap force e = DynArray.add smap.sources pos.pfile; length in - let line, col = Lexer.find_pos pos in - let line = line - 1 in - if force || smap.source_last_file != file || smap.source_last_line != line || smap.source_last_col != col then begin - smap.current_expr <- Some e; - if smap.print_comma then - Rbuffer.add_char smap.mappings ',' - else - smap.print_comma <- true; - - let base64_vlq number = - let encode_digit digit = - let chars = [| - 'A';'B';'C';'D';'E';'F';'G';'H';'I';'J';'K';'L';'M';'N';'O';'P'; - 'Q';'R';'S';'T';'U';'V';'W';'X';'Y';'Z';'a';'b';'c';'d';'e';'f'; - 'g';'h';'i';'j';'k';'l';'m';'n';'o';'p';'q';'r';'s';'t';'u';'v'; - 'w';'x';'y';'z';'0';'1';'2';'3';'4';'5';'6';'7';'8';'9';'+';'/' - |] in - Array.unsafe_get chars digit - in - let to_vlq number = - if number < 0 then - ((-number) lsl 1) + 1 - else - number lsl 1 - in - let rec loop vlq = - let shift = 5 in - let base = 1 lsl shift in - let mask = base - 1 in - let continuation_bit = base in - let digit = vlq land mask in - let next = vlq asr shift in - Rbuffer.add_char smap.mappings (encode_digit ( - if next > 0 then digit lor continuation_bit else digit)); - if next > 0 then loop next else () - in - loop (to_vlq number) - in - base64_vlq (smap.output_current_col - smap.output_last_col); - base64_vlq (file - smap.source_last_file); - base64_vlq (line - smap.source_last_line); - base64_vlq (col - smap.source_last_col); + let pos = + let line, col = Lexer.find_pos pos in + let line = line - 1 in + { file = file; line = line; col = col } + in - smap.source_last_file <- file; - smap.source_last_line <- line; - smap.source_last_col <- col; - smap.output_last_col <- smap.output_current_col - end + if smap.source_last_pos <> pos then begin + let old_current_expr = smap.current_expr in + smap.current_expr <- Some pos; + encode_mapping smap pos; + (fun () -> smap.current_expr <- old_current_expr) + end else + noop + +let add_mapping ctx e = + Option.map_default (fun smap -> add_mapping smap e.epos) noop ctx.smap let handle_newlines ctx str = Option.may (fun smap -> @@ -210,7 +242,7 @@ let handle_newlines ctx str = smap.output_last_col <- 0; smap.output_current_col <- 0; smap.print_comma <- false; - Option.may (fun e -> add_mapping smap true e) smap.current_expr; + Option.may (encode_mapping smap) smap.current_expr; loop next end with Not_found -> smap.output_current_col <- smap.output_current_col + (String.length str - from); @@ -236,7 +268,7 @@ let print ctx = let write_mappings ctx smap = let basefile = Filename.basename ctx.com.file in - print ctx "\n//# sourceMappingURL=%s.map" basefile; + print ctx "\n//# sourceMappingURL=%s.map" (url_encode_s basefile); let channel = open_out_bin (ctx.com.file ^ ".map") in let sources = DynArray.to_list smap.sources in let to_url file = @@ -251,7 +283,7 @@ let write_mappings ctx smap = "],\n"); if Common.defined ctx.com Define.SourceMapContent then begin output_string channel ("\"sourcesContent\":[" ^ - (String.concat "," (List.map (fun s -> try "\"" ^ Ast.s_escape (Std.input_file ~bin:true s) ^ "\"" with _ -> "null") sources)) ^ + (String.concat "," (List.map (fun s -> try "\"" ^ StringHelper.s_escape (Std.input_file ~bin:true s) ^ "\"" with _ -> "null") sources)) ^ "],\n"); end; output_string channel "\"names\":[],\n"; @@ -287,8 +319,8 @@ let rec concat ctx s f = function let fun_block ctx f p = let e = List.fold_left (fun e (a,c) -> match c with - | None | Some TNull -> e - | Some c -> Type.concat (Codegen.set_default ctx.com a c p) e + | None | Some {eexpr = TConst TNull} -> e + | Some c -> Type.concat (Texpr.set_default ctx.com.basic a c p) e ) f.tf_expr f.tf_args in e @@ -330,15 +362,18 @@ let is_dynamic_iterator ctx e = let gen_constant ctx p = function | TInt i -> print ctx "%ld" i | TFloat s -> spr ctx s - | TString s -> print ctx "\"%s\"" (Ast.s_escape s) + | TString s -> print ctx "\"%s\"" (StringHelper.s_escape s) | TBool b -> spr ctx (if b then "true" else "false") | TNull -> spr ctx "null" | TThis -> spr ctx (this ctx) - | TSuper -> assert false + | TSuper -> assert (ctx.es_version >= 6); spr ctx "super" + +let print_deprecation_message com msg p = + com.warning msg p let rec gen_call ctx e el in_value = match e.eexpr , el with - | TConst TSuper , params -> + | TConst TSuper , params when ctx.es_version < 6 -> (match ctx.current.cl_super with | None -> abort "Missing api.setCurrentClass" e.epos | Some (c,_) -> @@ -346,7 +381,7 @@ let rec gen_call ctx e el in_value = List.iter (fun p -> print ctx ","; gen_value ctx p) params; spr ctx ")"; ); - | TField ({ eexpr = TConst TSuper },f) , params -> + | TField ({ eexpr = TConst TSuper },f) , params when ctx.es_version < 6 -> (match ctx.current.cl_super with | None -> abort "Missing api.setCurrentClass" e.epos | Some (c,_) -> @@ -362,46 +397,26 @@ let rec gen_call ctx e el in_value = spr ctx "("; concat ctx "," (gen_value ctx) el; spr ctx ")"; - | TIdent "__new__", { eexpr = TConst (TString cl) } :: params -> - print ctx "new %s(" cl; - concat ctx "," (gen_value ctx) params; - spr ctx ")"; - | TIdent "__new__", e :: params -> - spr ctx "new "; - gen_value ctx e; - spr ctx "("; - concat ctx "," (gen_value ctx) params; - spr ctx ")"; - | TIdent "__js__", [{ eexpr = TConst (TString "this") }] -> - spr ctx (this ctx) - | TIdent "__js__", [{ eexpr = TConst (TString code) }] -> - spr ctx (String.concat "\n" (ExtString.String.nsplit code "\r\n")) - | TIdent "__js__", { eexpr = TConst (TString code); epos = p } :: tl -> - Codegen.interpolate_code ctx.com code tl (spr ctx) (gen_expr ctx) p - | TIdent "__instanceof__", [o;t] -> - spr ctx "("; - gen_value ctx o; - print ctx " instanceof "; - gen_value ctx t; - spr ctx ")"; - | TIdent "__typeof__", [o] -> - spr ctx "typeof("; - gen_value ctx o; - spr ctx ")"; - | TIdent "__strict_eq__" , [x;y] -> - (* add extra parenthesis here because of operator precedence *) - spr ctx "(("; - gen_value ctx x; - spr ctx ") === "; - gen_value ctx y; - spr ctx ")"; - | TIdent "__strict_neq__" , [x;y] -> - (* add extra parenthesis here because of operator precedence *) - spr ctx "(("; - gen_value ctx x; - spr ctx ") !== "; - gen_value ctx y; - spr ctx ")"; + | TField (_, FStatic ({ cl_path = ["js"],"Syntax" }, { cf_name = meth })), args -> + gen_syntax ctx meth args e.epos + | TIdent "__new__", args -> + print_deprecation_message ctx.com "__new__ is deprecated, use js.Syntax.construct instead" e.epos; + gen_syntax ctx "construct" args e.epos + | TIdent "__js__", args -> + (* TODO: add deprecation warning when we figure out what to do with purity here *) + gen_syntax ctx "code" args e.epos + | TIdent "__instanceof__", args -> + print_deprecation_message ctx.com "__instanceof__ is deprecated, use js.Syntax.instanceof instead" e.epos; + gen_syntax ctx "instanceof" args e.epos + | TIdent "__typeof__", args -> + print_deprecation_message ctx.com "__typeof__ is deprecated, use js.Syntax.typeof instead" e.epos; + gen_syntax ctx "typeof" args e.epos + | TIdent "__strict_eq__" , args -> + print_deprecation_message ctx.com "__strict_eq__ is deprecated, use js.Syntax.strictEq instead" e.epos; + gen_syntax ctx "strictEq" args e.epos + | TIdent "__strict_neq__" , args -> + print_deprecation_message ctx.com "__strict_neq__ is deprecated, use js.Syntax.strictNeq instead" e.epos; + gen_syntax ctx "strictNeq" args e.epos | TIdent "__define_feature__", [_;e] -> gen_expr ctx e | TIdent "__feature__", { eexpr = TConst (TString f) } :: eif :: eelse -> @@ -410,8 +425,6 @@ let rec gen_call ctx e el in_value = else match eelse with | [] -> () | e :: _ -> gen_value ctx e) - | TIdent "__rethrow__", [] -> - spr ctx "throw $hx_rethrow"; | TIdent "__resources__", [] -> spr ctx "["; concat ctx "," (fun (name,data) -> @@ -444,6 +457,11 @@ let rec gen_call ctx e el in_value = gen_value ctx e; spr ctx ")"; end + | TField (x,f), [] when field_name f = "iterator" && is_dynamic_iterator ctx e -> + add_feature ctx "use.$getIterator"; + print ctx "$getIterator("; + gen_value ctx x; + print ctx ")"; | _ -> gen_value ctx e; spr ctx "("; @@ -464,7 +482,7 @@ and add_objectdecl_parens e = loop e and gen_expr ctx e = - Option.may (fun smap -> add_mapping smap false e) ctx.smap; + let clear_mapping = add_mapping ctx e in (match e.eexpr with | TConst c -> gen_constant ctx e.epos c | TLocal v -> spr ctx (ident v.v_name) @@ -523,15 +541,15 @@ and gen_expr ctx e = print ctx ",$bind($_,$_%s))" (if Meta.has Meta.SelfCall f.cf_meta then "" else (field f.cf_name))) | TEnumIndex x -> gen_value ctx x; - if Common.defined ctx.com Define.JsEnumsAsObjects then + if not (Common.defined ctx.com Define.JsEnumsAsArrays) then print ctx "._hx_index" else print ctx "[1]" | TEnumParameter (x,f,i) -> gen_value ctx x; - if Common.defined ctx.com Define.JsEnumsAsObjects then + if not (Common.defined ctx.com Define.JsEnumsAsArrays) then let fname = (match f.ef_type with TFun((args,_)) -> let fname,_,_ = List.nth args i in fname | _ -> assert false ) in - print ctx ".%s" (fname) + print ctx ".%s" (ident fname) else print ctx "[%i]" (i + 2) | TField (_, FStatic ({cl_path = [],""},f)) -> @@ -547,7 +565,7 @@ and gen_expr ctx e = let x = skip x in gen_value ctx x; let name = field_name f in - spr ctx (match f with FStatic(c,_) -> static_field c name | FEnum _ | FInstance _ | FAnon _ | FDynamic _ | FClosure _ -> field name) + spr ctx (match f with FStatic(c,_) -> static_field ctx c name | FEnum _ | FInstance _ | FAnon _ | FDynamic _ | FClosure _ -> field name) | TTypeExpr t -> spr ctx (ctx.type_accessor t) | TParenthesis e -> @@ -586,18 +604,7 @@ and gen_expr ctx e = newline ctx; print ctx "}"; | TFunction f -> - let old = ctx.in_value, ctx.in_loop in - ctx.in_value <- None; - ctx.in_loop <- false; - let args = List.map (fun (v,_) -> - check_var_declaration v; - ident v.v_name - ) f.tf_args in - print ctx "function(%s) " (String.concat "," args); - gen_expr ctx (fun_block ctx f e.epos); - ctx.in_value <- fst old; - ctx.in_loop <- snd old; - ctx.separator <- true + gen_function ctx f e.epos | TCall (e,el) -> gen_call ctx e el false | TArrayDecl el -> @@ -666,7 +673,7 @@ and gen_expr ctx e = | TObjectDecl fields -> spr ctx "{ "; concat ctx ", " (fun ((f,_,qs),e) -> (match qs with - | DoubleQuotes -> print ctx "\"%s\" : " (Ast.s_escape f); + | DoubleQuotes -> print ctx "\"%s\" : " (StringHelper.s_escape f); | NoQuotes -> print ctx "%s : " (anon_field f)); gen_value ctx e ) fields; @@ -696,110 +703,14 @@ and gen_expr ctx e = newline ctx; spr ctx "}"; ctx.in_loop <- old_in_loop - | TTry (e,catchs) -> + | TTry (etry,[(v,ecatch)]) -> spr ctx "try "; - gen_expr ctx e; - let vname = (match catchs with [(v,_)] -> check_var_declaration v; v.v_name | _ -> - let id = ctx.id_counter in - ctx.id_counter <- ctx.id_counter + 1; - "$e" ^ string_of_int id - ) in - print ctx " catch( %s ) {" vname; - let bend = open_block ctx in - let last = ref false in - let else_block = ref false in - - if ctx.store_exception_stack then begin - newline ctx; - print ctx "%s.lastException = %s" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["haxe"],"CallStack" })) vname - end; - - if (has_feature ctx "js.Lib.rethrow") then begin - let has_rethrow (_,e) = - let rec loop e = match e.eexpr with - | TCall({eexpr = TIdent "__rethrow__"}, []) -> raise Exit - | _ -> Type.iter loop e - in - try (loop e; false) with Exit -> true - in - if List.exists has_rethrow catchs then begin - newline ctx; - print ctx "var $hx_rethrow = %s" vname; - end - end; - - if (has_feature ctx "js.Boot.HaxeError") then begin - let catch_var_used = - try - List.iter (fun (v,e) -> - match follow v.v_type with - | TDynamic _ -> (* Dynamic catch - unrap if the catch value is used *) - let rec loop e = match e.eexpr with - | TLocal v2 when v2 == v -> raise Exit - | _ -> Type.iter loop e - in - loop e - | _ -> (* not a Dynamic catch - we need to unwrap the error for type-checking *) - raise Exit - ) catchs; - false - with Exit -> - true - in - if catch_var_used then begin - newline ctx; - print ctx "if (%s instanceof %s) %s = %s.val" vname (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js";"_Boot"],"HaxeError" })) vname vname; - end; - end; - - List.iter (fun (v,e) -> - if !last then () else - let t = (match follow v.v_type with - | TEnum (e,_) -> Some (TEnumDecl e) - | TInst (c,_) -> Some (TClassDecl c) - | TAbstract (a,_) -> Some (TAbstractDecl a) - | TFun _ - | TLazy _ - | TType _ - | TAnon _ -> - assert false - | TMono _ - | TDynamic _ -> - None - ) in - match t with - | None -> - last := true; - if !else_block then print ctx "{"; - if vname <> v.v_name then begin - newline ctx; - print ctx "var %s = %s" v.v_name vname; - end; - gen_block_element ctx e; - if !else_block then begin - newline ctx; - print ctx "}"; - end - | Some t -> - if not !else_block then newline ctx; - print ctx "if( %s.__instanceof(%s," (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js"],"Boot" })) vname; - gen_value ctx (mk (TTypeExpr t) (mk_mono()) e.epos); - spr ctx ") ) {"; - let bend = open_block ctx in - if vname <> v.v_name then begin - newline ctx; - print ctx "var %s = %s" v.v_name vname; - end; - gen_block_element ctx e; - bend(); - newline ctx; - spr ctx "} else "; - else_block := true - ) catchs; - if not !last then print ctx "throw(%s)" vname; - bend(); - newline ctx; - spr ctx "}"; + gen_expr ctx etry; + check_var_declaration v; + print ctx " catch( %s ) " v.v_name; + gen_expr ctx ecatch + | TTry _ -> + abort "Unhandled try/catch, please report" e.epos | TSwitch (e,cases,def) -> spr ctx "switch"; gen_value ctx e; @@ -838,15 +749,28 @@ and gen_expr ctx e = gen_expr ctx e | TCast (e1,Some t) -> print ctx "%s.__cast(" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js"],"Boot" })); - gen_expr ctx e1; + gen_value ctx e1; spr ctx " , "; spr ctx (ctx.type_accessor t); spr ctx ")" | TIdent s -> spr ctx s ); - Option.may (fun smap -> smap.current_expr <- None) ctx.smap + clear_mapping () +and gen_function ?(keyword="function") ctx f pos = + let old = ctx.in_value, ctx.in_loop in + ctx.in_value <- None; + ctx.in_loop <- false; + let args = List.map (fun (v,_) -> + check_var_declaration v; + ident v.v_name + ) f.tf_args in + print ctx "%s(%s) " keyword (String.concat "," args); + gen_expr ctx (fun_block ctx f pos); + ctx.in_value <- fst old; + ctx.in_loop <- snd old; + ctx.separator <- true and gen_block_element ?(after=false) ctx e = match e.eexpr with @@ -869,7 +793,7 @@ and gen_block_element ?(after=false) ctx e = if after then newline ctx and gen_value ctx e = - Option.may (fun smap -> add_mapping smap false e) ctx.smap; + let clear_mapping = add_mapping ctx e in let assign e = mk (TBinop (Ast.OpAssign, mk (TLocal (match ctx.in_value with None -> assert false | Some v -> v)) t_dynamic e.epos, @@ -878,7 +802,7 @@ and gen_value ctx e = in let value() = let old = ctx.in_value, ctx.in_loop in - let r = alloc_var "$r" t_dynamic e.epos in + let r = alloc_var VGenerated "$r" t_dynamic e.epos in ctx.in_value <- Some r; ctx.in_loop <- false; spr ctx "(function($this) "; @@ -983,8 +907,82 @@ and gen_value ctx e = List.map (fun (v,e) -> v, block (assign e)) catchs )) e.etype e.epos); v()); - Option.may (fun smap -> smap.current_expr <- None) ctx.smap + clear_mapping () +and gen_syntax ctx meth args pos = + match meth, args with + | "construct", cl :: params -> + spr ctx "new "; + begin + match cl.eexpr with + | TConst (TString cl) -> + spr ctx cl + | _ -> + gen_value ctx cl + end; + spr ctx "("; + concat ctx "," (gen_value ctx) params; + spr ctx ")" + | "instanceof", [o;t] -> + spr ctx "(("; + gen_value ctx o; + print ctx ") instanceof "; + gen_value ctx t; + spr ctx ")" + | "typeof", [o] -> + spr ctx "typeof("; + gen_value ctx o; + spr ctx ")" + | "strictEq" , [x;y] -> + (* add extra parenthesis here because of operator precedence *) + spr ctx "(("; + gen_value ctx x; + spr ctx ") === "; + gen_value ctx y; + spr ctx ")"; + | "strictNeq" , [x;y] -> + (* add extra parenthesis here because of operator precedence *) + spr ctx "(("; + gen_value ctx x; + spr ctx ") !== "; + gen_value ctx y; + spr ctx ")"; + | "delete" , [o;f] -> + spr ctx "delete("; + gen_value ctx o; + spr ctx "["; + gen_value ctx f; + spr ctx "]"; + spr ctx ")"; + | "code", code :: args -> + let code, code_pos = + match code.eexpr with + | TConst (TString s) -> s, code.epos + | _ -> abort "The `code` argument for js.Syntax must be a string constant" code.epos + in + begin + match args with + | [] -> + if code = "this" then + spr ctx (this ctx) + else + spr ctx (String.concat "\n" (ExtString.String.nsplit code "\r\n")) + | _ -> + Codegen.interpolate_code ctx.com code args (spr ctx) (gen_value ctx) code_pos + end + | "field" , [eobj;efield] -> + gen_value ctx eobj; + (match Texpr.skip efield with + | { eexpr = TConst(TString(s)) } when valid_js_ident s -> + spr ctx "."; + spr ctx s; + | _ -> + spr ctx "["; + gen_value ctx efield; + spr ctx "]"; + ) + | _ -> + abort (Printf.sprintf "Unknown js.Syntax method `%s` with %d arguments" meth (List.length args)) pos let generate_package_create ctx (p,_) = let rec loop acc = function @@ -1031,13 +1029,13 @@ let gen_class_static_field ctx c f = | None when not (is_physical_field f) -> () | None -> - print ctx "%s%s = null" (s_path ctx c.cl_path) (static_field c f.cf_name); + print ctx "%s%s = null" (s_path ctx c.cl_path) (static_field ctx c f.cf_name); newline ctx | Some e -> match e.eexpr with | TFunction _ -> - let path = (s_path ctx c.cl_path) ^ (static_field c f.cf_name) in - let dot_path = (dot_path c.cl_path) ^ (static_field c f.cf_name) in + let path = (s_path ctx c.cl_path) ^ (static_field ctx c f.cf_name) in + let dot_path = (dot_path c.cl_path) ^ (static_field ctx c f.cf_name) in ctx.id_counter <- 0; print ctx "%s = " path; (match (get_exposed ctx dot_path f.cf_meta) with [s] -> print ctx "$hx_exports%s = " (path_to_brackets s) | _ -> ()); @@ -1070,26 +1068,30 @@ let generate_class___name__ ctx c = if has_feature ctx "js.Boot.isClass" then begin let p = s_path ctx c.cl_path in print ctx "%s.__name__ = " p; - if has_feature ctx "Type.getClassName" then - print ctx "[%s]" (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst c.cl_path @ [snd c.cl_path]))) - else - print ctx "true"; + (match has_feature ctx "Type.getClassName", c.cl_path with + | true, _ + | _, ([], ("Array" | "String")) -> + print ctx "\"%s\"" (dot_path c.cl_path) + | _ -> + print ctx "true" + ); newline ctx; end -let generate_class ctx c = - ctx.current <- c; - ctx.id_counter <- 0; - (match c.cl_path with - | [],"Function" -> abort "This class redefine a native one" c.cl_pos - | _ -> ()); +let generate_class___isInterface__ ctx c = + if c.cl_interface && has_feature ctx "js.Boot.isInterface" then begin + let p = s_path ctx c.cl_path in + print ctx "%s.__isInterface__ = true" p; + newline ctx; + end + +let generate_class_es3 ctx c = let p = s_path ctx c.cl_path in - let hxClasses = has_feature ctx "Type.resolveClass" in if ctx.js_flatten then print ctx "var " else generate_package_create ctx c.cl_path; - if ctx.js_modern || not hxClasses then + if ctx.js_modern || not ctx.has_resolveClass then print ctx "%s = " p else print ctx "%s = $hxClasses[\"%s\"] = " p (dot_path c.cl_path); @@ -1104,17 +1106,20 @@ let generate_class ctx c = | _ -> (print ctx "function() { }"); ctx.separator <- true) ); newline ctx; - if ctx.js_modern && hxClasses then begin + if ctx.js_modern && ctx.has_resolveClass then begin print ctx "$hxClasses[\"%s\"] = %s" (dot_path c.cl_path) p; newline ctx; end; generate_class___name__ ctx c; - (match c.cl_implements with - | [] -> () - | l -> - print ctx "%s.__interfaces__ = [%s]" p (String.concat "," (List.map (fun (i,_) -> ctx.type_accessor (TClassDecl i)) l)); - newline ctx; - ); + generate_class___isInterface__ ctx c; + + if ctx.has_interface_check then + (match c.cl_implements with + | [] -> () + | l -> + print ctx "%s.__interfaces__ = [%s]" p (String.concat "," (List.map (fun (i,_) -> ctx.type_accessor (TClassDecl i)) l)); + newline ctx; + ); let gen_props props = String.concat "," (List.map (fun (p,v) -> p ^":\""^v^"\"") props) in @@ -1171,60 +1176,256 @@ let generate_class ctx c = end; flush ctx +let generate_class_es6 ctx c = + let p = s_path ctx c.cl_path in + + let cls_name = + if not ctx.js_flatten && (fst c.cl_path) <> [] then begin + generate_package_create ctx c.cl_path; + print ctx "%s = " p; + Path.flat_path c.cl_path + end else + p + in + print ctx "class %s" cls_name; + + Option.may (fun (csup,_) -> + let psup = ctx.type_accessor (TClassDecl csup) in + print ctx " extends %s" psup + ) c.cl_super; + + spr ctx " {"; + let close_block = open_block ctx in + + (match c.cl_constructor with + | Some { cf_expr = Some ({ eexpr = TFunction f; epos = p }) } -> + newline ctx; + gen_function ~keyword:"constructor" ctx f p; + ctx.separator <- false + | _ -> ()); + + let method_def_name cf = + if valid_js_ident cf.cf_name then cf.cf_name else "\"" ^ cf.cf_name ^ "\"" + in + + let nonmethod_fields = + List.filter (fun cf -> + match cf.cf_kind, cf.cf_expr with + | Method _, Some { eexpr = TFunction f; epos = pos } -> + check_field_name c cf; + newline ctx; + gen_function ~keyword:(method_def_name cf) ctx f pos; + ctx.separator <- false; + false + | _ -> + true + ) c.cl_ordered_fields + in + + let exposed_static_methods = ref [] in + let nonmethod_statics = + List.filter (fun cf -> + match cf.cf_kind, cf.cf_expr with + | Method _, Some { eexpr = TFunction f; epos = pos } -> + check_field_name c cf; + newline ctx; + gen_function ~keyword:("static " ^ (method_def_name cf)) ctx f pos; + ctx.separator <- false; + + (match get_exposed ctx ((dot_path c.cl_path) ^ (static_field ctx c cf.cf_name)) cf.cf_meta with + | [s] -> exposed_static_methods := (s,cf.cf_name) :: !exposed_static_methods; + | _ -> ()); + + false + | _ -> true + ) c.cl_ordered_statics + in + + close_block (); + newline ctx; + spr ctx "}"; + newline ctx; + + List.iter (fun (path,name) -> + print ctx "$hx_exports%s = %s.%s;" (path_to_brackets path) p name; + newline ctx + ) !exposed_static_methods; + + List.iter (gen_class_static_field ctx c) nonmethod_statics; + + let expose = (match get_exposed ctx (dot_path c.cl_path) c.cl_meta with [s] -> "$hx_exports" ^ (path_to_brackets s) | _ -> "") in + if expose <> "" || ctx.has_resolveClass then begin + if ctx.has_resolveClass then begin + print ctx "$hxClasses[\"%s\"] = " (dot_path c.cl_path) + end; + if expose <> "" then begin + print ctx "%s = " expose + end; + spr ctx p; + newline ctx; + end; + + generate_class___name__ ctx c; + generate_class___isInterface__ ctx c; + + if ctx.has_interface_check then + (match c.cl_implements with + | [] -> () + | l -> + print ctx "%s.__interfaces__ = [%s]" p (String.concat "," (List.map (fun (i,_) -> ctx.type_accessor (TClassDecl i)) l)); + newline ctx; + ); + + let has_property_reflection = + (has_feature ctx "Reflect.getProperty") || (has_feature ctx "Reflect.setProperty") + in + let gen_props props = + String.concat "," (List.map (fun (p,v) -> p ^": \""^v^"\"") props) + in + + if has_property_reflection then begin + (match Codegen.get_properties nonmethod_statics with + | [] -> () + | props -> + print ctx "%s.__properties__ = {%s}" p (gen_props props); + ctx.separator <- true; + newline ctx); + end; + + (match c.cl_super with + | Some (csup,_) -> + if ctx.has_interface_check || has_feature ctx "Type.getSuperClass" then begin + let psup = ctx.type_accessor (TClassDecl csup) in + print ctx "%s.__super__ = %s" p psup; + newline ctx + end + | None -> ()); + + let has_class = has_feature ctx "js.Boot.getClass" && (c.cl_super <> None || c.cl_ordered_fields <> [] || c.cl_constructor <> None) in + let props_to_generate = if has_property_reflection then Codegen.get_properties c.cl_ordered_fields else [] in + let fields_to_generate = + if has_feature ctx "Type.getInstanceFields" then + if c.cl_interface then + List.filter is_physical_field c.cl_ordered_fields + else + List.filter is_physical_var_field nonmethod_fields + else + [] + in + + if has_class || props_to_generate <> [] || fields_to_generate <> [] then begin + print ctx "Object.assign(%s.prototype, {" p; + let bend = open_block ctx in + + if has_class then begin + newprop ctx; + print ctx "__class__: %s" p + end; + + if fields_to_generate <> [] then begin + List.iter (gen_class_field ctx c) fields_to_generate; + end; + + if props_to_generate <> [] then begin + newprop ctx; + match c.cl_super with + | Some (csup, _) when Codegen.has_properties csup -> + let psup = ctx.type_accessor (TClassDecl csup) in + print ctx "__properties__: Object.assign({}, %s.prototype.__properties__, {%s})" psup (gen_props props_to_generate) + | _ -> + print ctx "__properties__: {%s}" (gen_props props_to_generate) + end; + + bend(); + print ctx "\n})"; + newline ctx + end; + + flush ctx + +let generate_class ctx c = + ctx.current <- c; + ctx.id_counter <- 0; + (match c.cl_path with + | [],"Function" -> abort "This class redefine a native one" c.cl_pos + | _ -> ()); + if ctx.es_version >= 6 then + generate_class_es6 ctx c + else + generate_class_es3 ctx c + let generate_enum ctx e = let p = s_path ctx e.e_path in - let ename = List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst e.e_path @ [snd e.e_path]) in + let dotp = dot_path e.e_path in + let has_enum_feature = has_feature ctx "has_enum" in if ctx.js_flatten then print ctx "var " else generate_package_create ctx e.e_path; print ctx "%s = " p; - if has_feature ctx "Type.resolveEnum" then print ctx "$hxClasses[\"%s\"] = " (dot_path e.e_path); - print ctx "{"; - if has_feature ctx "js.Boot.isEnum" then print ctx " __ename__ : %s," (if has_feature ctx "Type.getEnumName" then "[" ^ String.concat "," ename ^ "]" else "true"); - print ctx " __constructs__ : [%s] }" (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" s) e.e_names)); - ctx.separator <- true; - let as_objects = Common.defined ctx.com Define.JsEnumsAsObjects in - if as_objects then begin - newline ctx; - print ctx "$hxEnums[\"%s\"] = %s" p p - end; - newline ctx; + let as_objects = not (Common.defined ctx.com Define.JsEnumsAsArrays) in + (if as_objects then + print ctx "$hxEnums[\"%s\"] = " dotp + else if has_feature ctx "Type.resolveEnum" then + print ctx "$hxClasses[\"%s\"] = " (dot_path e.e_path)); + spr ctx "{"; + if has_feature ctx "js.Boot.isEnum" then print ctx " __ename__ : %s," (if has_feature ctx "Type.getEnumName" then "\"" ^ dotp ^ "\"" else "true"); + print ctx " __constructs__ : [%s]" (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" s) e.e_names)); + let bend = + if not as_objects then begin + spr ctx " }"; + ctx.separator <- true; + newline ctx; + fun () -> () + end else begin + open_block ctx + end; + in List.iter (fun n -> let f = PMap.find n e.e_constrs in - print ctx "%s%s = " p (field f.ef_name); + if as_objects then begin + newprop ctx; + print ctx "%s: " (anon_field f.ef_name) + end else + print ctx "%s%s = " p (field f.ef_name); (match f.ef_type with | TFun (args,_) -> let sargs = String.concat "," (List.map (fun (n,_,_) -> ident n) args) in begin - if as_objects then - let sfields = String.concat "," (List.map (fun (n,_,_) -> (ident n) ^ ":" ^ (ident n) ) args) in - print ctx "function(%s) { var $x = {_hx_index:%d,%s,__enum__:\"%s\"};" sargs f.ef_index sfields p; - else - print ctx "function(%s) { var $x = [\"%s\",%d,%s]; $x.__enum__ = %s;" sargs f.ef_name f.ef_index sargs p; - end; - if has_feature ctx "has_enum" then - spr ctx " $x.toString = $estr;"; - spr ctx " return $x; }"; if as_objects then begin + let sfields = String.concat "," (List.map (fun (n,_,_) -> (ident n) ^ ":" ^ (ident n) ) args) in let sparams = String.concat "," (List.map (fun (n,_,_) -> "\"" ^ (ident n) ^ "\"" ) args) in - newline ctx; - print ctx "%s%s.__params__ = [%s];" p (field f.ef_name) sparams - end; - ctx.separator <- true; + print ctx "($_=function(%s) { return {_hx_index:%d,%s,__enum__:\"%s\"" sargs f.ef_index sfields dotp; + if has_enum_feature then + spr ctx ",toString:$estr"; + print ctx "}; },$_.__params__ = [%s],$_)" sparams + end else begin + print ctx "function(%s) { var $x = [\"%s\",%d,%s]; $x.__enum__ = %s;" sargs f.ef_name f.ef_index sargs p; + if has_enum_feature then + spr ctx " $x.toString = $estr;"; + spr ctx " return $x; }"; + end end; | _ -> if as_objects then - print ctx "{_hx_index:%d};" f.ef_index - else + print ctx "{_hx_index:%d,__enum__:\"%s\"%s}" f.ef_index dotp (if has_enum_feature then ",toString:$estr" else "") + else begin print ctx "[\"%s\",%d]" f.ef_name f.ef_index; - newline ctx; - if has_feature ctx "has_enum" then begin - print ctx "%s%s.toString = $estr" p (field f.ef_name); newline ctx; - end; - print ctx "%s%s.__enum__ = %s" p (field f.ef_name) (if as_objects then "\"" ^ p ^"\"" else p); + if has_feature ctx "has_enum" then begin + print ctx "%s%s.toString = $estr" p (field f.ef_name); + newline ctx; + end; + print ctx "%s%s.__enum__ = %s" p (field f.ef_name) p; + end ); - newline ctx + if not as_objects then + newline ctx ) e.e_names; + bend(); + if as_objects then begin + spr ctx "\n}"; + ctx.separator <- true; + newline ctx; + end; if has_feature ctx "Type.allEnums" then begin let ctors_without_args = List.filter (fun s -> let ef = PMap.find s e.e_constrs in @@ -1235,7 +1436,7 @@ let generate_enum ctx e = print ctx "%s.__empty_constructs__ = [%s]" p (String.concat "," (List.map (fun s -> Printf.sprintf "%s.%s" p s) ctors_without_args)); newline ctx end; - begin match Codegen.build_metadata ctx.com (TEnumDecl e) with + begin match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with | None -> () | Some e -> print ctx "%s.__meta__ = " p; @@ -1245,7 +1446,7 @@ let generate_enum ctx e = flush ctx let generate_static ctx (c,f,e) = - print ctx "%s%s = " (s_path ctx c.cl_path) (static_field c f); + print ctx "%s%s = " (s_path ctx c.cl_path) (static_field ctx c f); gen_value ctx e; newline ctx @@ -1268,6 +1469,11 @@ let generate_require ctx path meta = newline ctx +let need_to_generate_interface ctx cl_iface = + ctx.has_resolveClass (* generate so we can resolve it for whatever reason *) + || ctx.has_interface_check (* generate because we need __interfaces__ for run-time type checks *) + || is_directly_used ctx.com cl_iface.cl_meta (* generate because it's just directly accessed in code *) + let generate_type ctx = function | TClassDecl c -> (match c.cl_init with @@ -1280,9 +1486,10 @@ let generate_type ctx = function (* Another special case for Std because we do not want to generate it if it's empty. *) if p = "Std" && c.cl_ordered_statics = [] then () - else if not c.cl_extern then - generate_class ctx c - else if Meta.has Meta.JsRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then + else if not c.cl_extern then begin + if (not c.cl_interface) || (need_to_generate_interface ctx c) then + generate_class ctx c + end else if Meta.has Meta.JsRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then generate_require ctx c.cl_path c.cl_meta else if not ctx.js_flatten && Meta.has Meta.InitPackage c.cl_meta then (match c.cl_path with @@ -1297,13 +1504,11 @@ let generate_type ctx = function let set_current_class ctx c = ctx.current <- c -let alloc_ctx com = +let alloc_ctx com es_version = let smap = - if com.debug || Common.defined com Define.JsSourceMap then + if com.debug || Common.defined com Define.JsSourceMap || Common.defined com Define.SourceMap then Some { - source_last_line = 0; - source_last_col = 0; - source_last_file = 0; + source_last_pos = { file = 0; line = 0; col = 0}; print_comma = false; output_last_col = 0; output_current_col = 0; @@ -1323,8 +1528,9 @@ let alloc_ctx com = smap = smap; js_modern = not (Common.defined com Define.JsClassic); js_flatten = not (Common.defined com Define.JsUnflatten); - es_version = (try int_of_string (Common.defined_value com Define.JsEs) with _ -> 0); - store_exception_stack = if Common.has_dce com then (Common.has_feature com "haxe.CallStack.exceptionStack") else List.exists (function TClassDecl { cl_path=["haxe"],"CallStack" } -> true | _ -> false) com.types; + has_resolveClass = Common.has_feature com "Type.resolveClass"; + has_interface_check = Common.has_feature com "js.Boot.__interfLoop"; + es_version = es_version; statics = []; inits = []; current = null_class; @@ -1357,14 +1563,20 @@ let generate com = (match com.js_gen with | Some g -> g() | None -> - let ctx = alloc_ctx com in + + let es_version = get_es_version com in + + if es_version >= 6 then + ES6Ctors.rewrite_ctors com; + + let ctx = alloc_ctx com es_version in Codegen.map_source_header com (fun s -> print ctx "// %s\n" s); if has_feature ctx "Class" || has_feature ctx "Type.getClassName" then add_feature ctx "js.Boot.isClass"; if has_feature ctx "Enum" || has_feature ctx "Type.getEnumName" then add_feature ctx "js.Boot.isEnum"; let nodejs = Common.raw_defined com "nodejs" in - setup_kwds (if ctx.es_version >= 5 then es5kwds else es3kwds); + setup_kwds com; let exposed = List.concat (List.map (fun t -> match t with @@ -1372,7 +1584,7 @@ let generate com = let path = dot_path c.cl_path in let class_exposed = get_exposed ctx path c.cl_meta in let static_exposed = List.map (fun f -> - get_exposed ctx (path ^ static_field c f.cf_name) f.cf_meta + get_exposed ctx (path ^ static_field ctx c f.cf_name) f.cf_meta ) c.cl_ordered_statics in List.concat (class_exposed :: static_exposed) | _ -> [] @@ -1405,7 +1617,7 @@ let generate com = match file with | path, "top" -> let file_content = Std.input_file ~bin:true (fst file) in - print ctx "%s\n" file_content; + print ctx "%s\n;" file_content; () | _ -> () ) include_files; @@ -1425,12 +1637,7 @@ let generate com = "typeof window != \"undefined\" ? window : typeof global != \"undefined\" ? global : typeof self != \"undefined\" ? self : this" ) in - let closureArgs = [] in - let closureArgs = if has_feature ctx "js.Lib.global" then - var_global :: closureArgs - else - closureArgs - in + let closureArgs = [var_global] in let closureArgs = if (anyExposed && not (Common.defined com Define.ShallowExpose)) then var_exports :: closureArgs else @@ -1473,7 +1680,7 @@ let generate com = match file with | path, "closure" -> let file_content = Std.input_file ~bin:true (fst file) in - print ctx "%s\n" file_content; + print ctx "%s\n;" file_content; () | _ -> () ) include_files; @@ -1482,19 +1689,27 @@ let generate com = if (not ctx.js_modern) && (ctx.es_version < 5) then add_feature ctx "js.Lib.global"; (* console polyfill will check console from $global *) - if (not ctx.js_modern) && (has_feature ctx "js.Lib.global") then + if (not ctx.js_modern) then print ctx "var %s = %s;\n" (fst var_global) (snd var_global); if (not ctx.js_modern) && (ctx.es_version < 5) then spr ctx "var console = $global.console || {log:function(){}};\n"; + let enums_as_objects = not (Common.defined com Define.JsEnumsAsArrays) in + (* TODO: fix $estr *) let vars = [] in - let vars = (if has_feature ctx "Type.resolveClass" || has_feature ctx "Type.resolveEnum" then ("$hxClasses = " ^ (if ctx.js_modern then "{}" else "$hxClasses || {}")) :: vars else vars) in + let vars = (if ctx.has_resolveClass || (not enums_as_objects && has_feature ctx "Type.resolveEnum") then ("$hxClasses = " ^ (if ctx.js_modern then "{}" else "$hxClasses || {}")) :: vars else vars) in let vars = if has_feature ctx "has_enum" then ("$estr = function() { return " ^ (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js"],"Boot" })) ^ ".__string_rec(this,''); }") :: vars else vars in - let vars = if Common.defined com Define.JsEnumsAsObjects then "$hxEnums = {}" :: vars else vars in + let vars = if (enums_as_objects && (has_feature ctx "has_enum" || has_feature ctx "Type.resolveEnum")) then "$hxEnums = $hxEnums || {}" :: vars else vars in + let vars,has_dollar_underscore = + if List.exists (function TEnumDecl { e_extern = false } -> true | _ -> false) com.types then + "$_" :: vars,true + else + vars,false + in (match List.rev vars with | [] -> () | vl -> @@ -1502,14 +1717,21 @@ let generate com = ctx.separator <- true; newline ctx ); - if List.exists (function TClassDecl { cl_extern = false; cl_super = Some _ } -> true | _ -> false) com.types then begin - print ctx "function $extend(from, fields) { - function Inherit() {} Inherit.prototype = from; var proto = new Inherit(); - for (var name in fields) proto[name] = fields[name]; - if( fields.toString !== Object.prototype.toString ) proto.toString = fields.toString; - return proto; -} -"; + if ctx.es_version < 6 && List.exists (function TClassDecl { cl_extern = false; cl_super = Some _ } -> true | _ -> false) com.types then begin + let extend_code = + "function $extend(from, fields) {\n" ^ + ( + if ctx.es_version < 5 then + " function Inherit() {} Inherit.prototype = from; var proto = new Inherit();\n" + else + " var proto = Object.create(from);\n" + ) ^ + " for (var name in fields) proto[name] = fields[name];\n" ^ + " if( fields.toString !== Object.prototype.toString ) proto.toString = fields.toString;\n" ^ + " return proto;\n" ^ + "}\n" + in + spr ctx extend_code end; List.iter (generate_type ctx) com.types; let rec chk_features e = @@ -1517,6 +1739,8 @@ let generate com = match e.eexpr with | TField (_,FClosure _) -> add_feature ctx "use.$bind" + | TCall ({ eexpr = TField (_,f) } as ef, []) when field_name f = "iterator" && is_dynamic_iterator ctx ef -> + add_feature ctx "use.$getIterator"; | _ -> Type.iter chk_features e in @@ -1527,22 +1751,48 @@ let generate com = print ctx "function $iterator(o) { if( o instanceof Array ) return function() { return HxOverrides.iter(o); }; return typeof(o.iterator) == 'function' ? $bind(o,o.iterator) : o.iterator; }"; newline ctx; end; - if has_feature ctx "use.$bind" then begin - print ctx "var $_, $fid = 0"; + if has_feature ctx "use.$getIterator" then begin + print ctx "function $getIterator(o) { if( o instanceof Array ) return HxOverrides.iter(o); else return o.iterator(); }"; newline ctx; - print ctx "function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $fid++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; o.hx__closures__[m.__id__] = f; } return f; }"; + end; + if has_feature ctx "use.$bind" then begin + add_feature ctx "$global.$haxeUID"; + if not has_dollar_underscore then begin + print ctx "var $_"; + newline ctx; + end; + (if ctx.es_version < 5 then + print ctx "function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $global.$haxeUID++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; o.hx__closures__[m.__id__] = f; } return f; }" + else + print ctx "function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $global.$haxeUID++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = m.bind(o); o.hx__closures__[m.__id__] = f; } return f; }" + ); newline ctx; end; if has_feature ctx "use.$arrayPush" then begin print ctx "function $arrayPush(x) { this.push(x); }"; newline ctx end; + if has_feature ctx "$global.$haxeUID" then begin + add_feature ctx "js.Lib.global"; + print ctx "if(typeof $global.$haxeUID == \"undefined\") $global.$haxeUID = 0;\n"; + end; List.iter (gen_block_element ~after:true ctx) (List.rev ctx.inits); List.iter (generate_static ctx) (List.rev ctx.statics); (match com.main with | None -> () | Some e -> gen_expr ctx e; newline ctx); if ctx.js_modern then begin + let closureArgs = + if has_feature ctx "js.Lib.global" then + closureArgs + else + (* no need for `typeof window != "undefined" ? window : typeof global != "undefined" ? <...>` *) + match List.rev closureArgs with + | (global_name,global_value) :: rest -> + List.rev ((global_name,"{}") :: rest) + | _ -> + closureArgs + in print ctx "})(%s)" (String.concat ", " (List.map snd closureArgs)); newline ctx; end; diff --git a/src/generators/genjvm.ml b/src/generators/genjvm.ml new file mode 100644 index 00000000000..897efdb7b42 --- /dev/null +++ b/src/generators/genjvm.ml @@ -0,0 +1,3092 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals +open Ast +open Common +open Type +open Path +open JvmGlobals +open MethodAccessFlags +open FieldAccessFlags +open JvmData +open JvmAttribute +open JvmSignature +open JvmMethod +open JvmBuilder + +(* Note: This module is the bridge between Haxe structures and JVM structures. No module in generators/jvm should reference any + Haxe-specific type. *) + +(* hacks *) + +let rec pow a b = match b with + | 0 -> Int32.one + | 1 -> a + | _ -> Int32.mul a (pow a (b - 1)) + +let java_hash s = + let h = ref Int32.zero in + let l = String.length s in + let i31 = Int32.of_int 31 in + String.iteri (fun i char -> + let char = Int32.of_int (int_of_char char) in + h := Int32.add !h (Int32.mul char (pow i31 (l - (i + 1)))) + ) s; + !h + +let find_overload map_type c cf el = + let matches = ref [] in + let rec loop cfl = match cfl with + | cf :: cfl -> + begin match follow (monomorphs cf.cf_params (map_type cf.cf_type)) with + | TFun(tl'',_) as tf -> + let rec loop2 acc el tl = match el,tl with + | e :: el,(n,o,t) :: tl -> + begin try + Type.unify e.etype t; + loop2 ((e,o) :: acc) el tl + with _ -> + loop cfl + end + | [],[] -> + matches := ((List.rev acc),tf,(c,cf)) :: !matches; + loop cfl + | _ -> + loop cfl + in + loop2 [] el tl'' + | t -> + loop cfl + end; + | [] -> + List.rev !matches + in + loop (cf :: cf.cf_overloads) + +let find_overload_rec' is_ctor map_type c name el = + let candidates = ref [] in + let has_function t1 (_,t2,_) = + begin match follow t1,t2 with + | TFun(tl1,_),TFun(tl2,_) -> type_iseq (TFun(tl1,t_dynamic)) (TFun(tl2,t_dynamic)) + | _ -> false + end + in + let rec loop map_type c = + begin try + let cf = if is_ctor then + (match c.cl_constructor with Some cf -> cf | None -> raise Not_found) + else + PMap.find name c.cl_fields + in + begin match find_overload map_type c cf el with + | [] -> raise Not_found + | l -> + List.iter (fun ((_,t,_) as ca) -> + if not (List.exists (has_function t) !candidates) then candidates := ca :: !candidates + ) l + end; + if Meta.has Meta.Overload cf.cf_meta || cf.cf_overloads <> [] then raise Not_found + with Not_found -> + if c.cl_interface then + List.iter (fun (c,tl) -> loop (fun t -> apply_params c.cl_params (List.map map_type tl) t) c) c.cl_implements + else match c.cl_super with + | None -> () + | Some(c,tl) -> loop (fun t -> apply_params c.cl_params (List.map map_type tl) t) c + end; + in + loop map_type c; + match Overloads.Resolution.reduce_compatible (List.rev !candidates) with + | [_,_,(c,cf)] -> Some(c,cf) + | [] -> None + | ((_,_,(c,cf)) :: _) (* as resolved *) -> + (* let st = s_type (print_context()) in + print_endline (Printf.sprintf "Ambiguous overload for %s(%s)" name (String.concat ", " (List.map (fun e -> st e.etype) el))); + List.iter (fun (_,t,(c,cf)) -> + print_endline (Printf.sprintf "\tCandidate: %s.%s(%s)" (s_type_path c.cl_path) cf.cf_name (st t)); + ) resolved; *) + Some(c,cf) + +let find_overload_rec is_ctor map_type c cf el = + if Meta.has Meta.Overload cf.cf_meta || cf.cf_overloads <> [] then + find_overload_rec' is_ctor map_type c cf.cf_name el + else + Some(c,cf) + +let get_construction_mode c cf = + if Meta.has Meta.HxGen cf.cf_meta then ConstructInitPlusNew + else ConstructInit + +(* Haxe *) + +exception HarderFailure of string + +type field_generation_info = { + mutable has_this_before_super : bool; + (* This is an ordered list of fields that are targets of super() calls which is determined during + pre-processing. The generator can pop from this list assuming that it processes the expression + in the same order (which it should). *) + mutable super_call_fields : (tclass * tclass_field) list; +} + +type generation_context = { + com : Common.context; + jar : Zip.out_file; + t_exception : Type.t; + t_throwable : Type.t; + anon_lut : ((string * jsignature) list,jpath) Hashtbl.t; + anon_path_lut : (path,jpath) Hashtbl.t; + field_infos : field_generation_info DynArray.t; + implicit_ctors : (path,(path * jsignature,tclass * tclass_field) PMap.t) Hashtbl.t; + default_export_config : export_config; + mutable current_field_info : field_generation_info option; + mutable anon_num : int; +} + +type ret = + | RValue of jsignature option + | RVoid + | RReturn + +type method_type = + | MStatic + | MInstance + | MConstructor + +type access_kind = + | AKPost + | AKPre + | AKNone + +type compare_kind = + | CmpNormal of jcmp * jsignature + | CmpSpecial of (unit -> jbranchoffset ref) + +type block_exit = + | ExitExecute of (unit -> unit) + | ExitLoop + +open NativeSignatures + +let rec jsignature_of_type stack t = + if List.exists (fast_eq t) stack then object_sig else + let jsignature_of_type = jsignature_of_type (t :: stack) in + let jtype_argument_of_type t = jtype_argument_of_type stack t in + match t with + | TAbstract(a,tl) -> + begin match a.a_path with + | [],"Bool" -> TBool + | ["java"],"Int8" -> TByte + | ["java"],"Int16" -> TShort + | [],"Int" -> TInt + | ["haxe"],"Int32" -> TInt + | ["haxe"],"Int64" -> TLong + | ["java"],"Int64" -> TLong + | ["java"],"Char16" -> TChar + | [],"Single" -> TFloat + | [],"Float" -> TDouble + | [],"Null" -> + begin match tl with + | [t] -> get_boxed_type (jsignature_of_type t) + | _ -> assert false + end + | (["haxe";"ds"],"Vector") | (["haxe";"extern"],"Rest") -> + begin match tl with + | [t] -> TArray(jsignature_of_type t,None) + | _ -> assert false + end + | [],"Dynamic" -> + object_sig + | [],("Class" | "Enum") -> + java_class_sig + | [],"EnumValue" -> + java_enum_sig object_sig + | _ -> + if Meta.has Meta.CoreType a.a_meta then + TObject(a.a_path,List.map jtype_argument_of_type tl) + else + jsignature_of_type (Abstract.get_underlying_type a tl) + end + | TDynamic _ -> object_sig + | TMono r -> + begin match !r with + | Some t -> jsignature_of_type t + | None -> object_sig + end + | TInst({cl_path = (["haxe";"root"],"String")},[]) -> string_sig + | TInst({cl_path = (["haxe";"root"],"Array")},[t]) -> + let t = get_boxed_type (jsignature_of_type t) in + TObject((["haxe";"root"],"Array"),[TType(WNone,t)]) + | TInst({cl_path = (["java"],"NativeArray")},[t]) -> + TArray(jsignature_of_type t,None) + | TInst({cl_kind = KTypeParameter [t]},_) -> jsignature_of_type t + | TInst({cl_kind = KTypeParameter _; cl_path = (_,name)},_) -> TTypeParameter name + | TInst({cl_path = ["_Class"],"Class_Impl_"},_) -> java_class_sig + | TInst({cl_path = ["_Enum"],"Enum_Impl_"},_) -> java_class_sig + | TInst(c,tl) -> TObject(c.cl_path,List.map jtype_argument_of_type tl) + | TEnum(en,tl) -> TObject(en.e_path,List.map jtype_argument_of_type tl) + | TFun(tl,tr) -> method_sig (List.map (fun (_,o,t) -> + let jsig = jsignature_of_type t in + let jsig = if o then get_boxed_type jsig else jsig in + jsig + ) tl) (if ExtType.is_void (follow tr) then None else Some (jsignature_of_type tr)) + | TAnon an -> object_sig + | TType(td,tl) -> jsignature_of_type (apply_params td.t_params tl td.t_type) + | TLazy f -> jsignature_of_type (lazy_type f) + +and jtype_argument_of_type stack t = + TType(WNone,jsignature_of_type stack t) + +let jsignature_of_type t = + jsignature_of_type [] t + +module TAnonIdentifiaction = struct + let convert_fields fields = + let l = PMap.fold (fun cf acc -> cf :: acc) fields [] in + let l = List.sort (fun cf1 cf2 -> compare cf1.cf_name cf2.cf_name) l in + List.map (fun cf -> cf.cf_name,jsignature_of_type cf.cf_type) l + + let identify gctx fields = + if PMap.is_empty fields then + haxe_dynamic_object_path,[] + else begin + let l = convert_fields fields in + try + Hashtbl.find gctx.anon_lut l,l + with Not_found -> + let id = gctx.anon_num in + gctx.anon_num <- gctx.anon_num + 1; + let path = (["haxe";"generated"],Printf.sprintf "Anon%i" id) in + Hashtbl.add gctx.anon_lut l path; + path,l + end + + let identify_as gctx path fields = + if not (PMap.is_empty fields) && not (Hashtbl.mem gctx.anon_path_lut path) then begin + let fields = convert_fields fields in + Hashtbl.add gctx.anon_lut fields path; + Hashtbl.add gctx.anon_path_lut path path; + end + +end + +module AnnotationHandler = struct + let generate_annotations builder meta = + let parse_path e = + let sl = try string_list_of_expr_path_raise e with Exit -> Error.error "Field expression expected" (pos e) in + let path = match sl with + | s :: sl -> List.rev sl,s + | _ -> Error.error "Field expression expected" (pos e) + in + path + in + let rec parse_value e = match fst e with + | EConst (Int s) -> AInt (Int32.of_string s) + | EConst (Float s) -> ADouble (float_of_string s) + | EConst (String s) -> AString s + | EConst (Ident "true") -> ABool true + | EConst (Ident "false") -> ABool false + | EArrayDecl el -> AArray (List.map parse_value el) + | EField(e1,s) -> + let path = parse_path e1 in + AEnum(object_path_sig path,s) + | _ -> Error.error "Expected value expression" (pos e) + in + let parse_value_pair e = match fst e with + | EBinop(OpAssign,(EConst(Ident s),_),e1) -> + s,parse_value e1 + | _ -> + Error.error "Assignment expression expected" (pos e) + in + let parse_expr e = match fst e with + | ECall(e1,el) -> + let path = parse_path e1 in + let _,name = ExtString.String.replace (snd path) "." "$" in + let path = (fst path,name) in + let values = List.map parse_value_pair el in + path,values + | _ -> + Error.error "Call expression expected" (pos e) + in + List.iter (fun (m,el,_) -> match m,el with + | Meta.Meta,[e] -> + let path,annotation = parse_expr e in + builder#add_annotation path annotation; + | _ -> + () + ) meta +end + +let enum_ctor_sig = + let ta = TArray(object_sig,None) in + method_sig [TInt;ta] None + +let convert_cmp_op = function + | OpEq -> CmpEq + | OpNotEq -> CmpNe + | OpLt -> CmpLt + | OpLte -> CmpLe + | OpGt -> CmpGt + | OpGte -> CmpGe + | _ -> assert false + +let flip_cmp_op = function + | CmpEq -> CmpNe + | CmpNe -> CmpEq + | CmpLt -> CmpGe + | CmpLe -> CmpGt + | CmpGt -> CmpLe + | CmpGe -> CmpLt + +let resolve_class com path = + let rec loop types = match types with + | (TClassDecl c) :: types when c.cl_path = path -> + c + | _ :: types -> + loop types + | [] -> + jerror ("No such type: " ^ s_type_path path) + in + loop com.types + +let write_class jar path jc = + let dir = match path with + | ([],s) -> s + | (sl,s) -> String.concat "/" sl ^ "/" ^ s + in + let path = dir ^ ".class" in + let t = Timer.timer ["jvm";"write"] in + let ch = IO.output_bytes() in + JvmWriter.write_jvm_class ch jc; + Zip.add_entry (Bytes.unsafe_to_string (IO.close_out ch)) jar path; + t() + +let is_const_int_pattern (el,_) = + List.for_all (fun e -> match e.eexpr with + | TConst (TInt _) -> true + | _ -> false + ) el + +let is_const_string_pattern (el,_) = + List.for_all (fun e -> match e.eexpr with + | TConst (TString _) -> true + | _ -> false + ) el + +let is_interface_var_access c cf = + c.cl_interface && match cf.cf_kind with + | Var _ | Method MethDynamic -> true + | _ -> false + +let type_unifies a b = + try Type.unify a b; true with _ -> false + +let get_field_info gctx ml = + let rec loop ml = match ml with + | (Meta.Custom ":jvm.fieldInfo",[(EConst (Int s),_)],_) :: _ -> + Some (DynArray.get gctx.field_infos (int_of_string s)) + | _ :: ml -> + loop ml + | [] -> + None + in + loop ml + +let follow = Abstract.follow_with_abstracts + +class haxe_exception gctx (t : Type.t) = object(self) + val native_exception = + if follow t == t_dynamic then + throwable_sig,false + else if type_unifies t gctx.t_exception then + jsignature_of_type t,true + else + haxe_exception_sig,false + + val mutable native_exception_path = None + + method is_assignable_to (exc2 : haxe_exception) = + match self#is_native_exception,exc2#is_native_exception with + | true, true -> + (* Native exceptions are assignable if they unify *) + type_unifies t exc2#get_type + | false,false -> + (* Haxe exceptions are always assignable to each other *) + true + | false,true -> + (* Haxe exception is assignable to native only if caught type is java.lang.Exception/Throwable *) + let exc2_native_exception_type = exc2#get_native_exception_type in + exc2_native_exception_type = throwable_sig || exc2_native_exception_type = exception_sig + | _ -> + (* Native to Haxe is never assignable *) + false + + method is_native_exception = snd native_exception + method get_native_exception_type = fst native_exception + + method get_native_exception_path = + match native_exception_path with + | None -> + let path = (match (fst native_exception) with TObject(path,_) -> path | _ -> assert false) in + native_exception_path <- Some path; + path + | Some path -> + path + + method get_type = t +end + +class closure_context (jsig : jsignature) = object(self) + val lut = Hashtbl.create 0 + val sigs = DynArray.create() + + method add (var_id : int) (var_name : string) (var_sig : jsignature) = + DynArray.add sigs ((var_id,var_name),var_sig); + Hashtbl.add lut var_id (var_sig,var_name) + + method get (code : JvmCode.builder) (var_id : int) = + let var_sig,var_name = Hashtbl.find lut var_id in + if DynArray.length sigs > 1 then begin + (-1), + (fun () -> + code#aload jsig 0; + let offset = code#get_pool#add_field self#get_path var_name var_sig FKField in + code#getfield offset jsig var_sig + ), + (fun () -> + code#aload jsig 0; + let offset = code#get_pool#add_field self#get_path var_name var_sig FKField in + code#putfield offset jsig var_sig + ) + end else begin + (-1), + (fun () -> + code#aload jsig 0; + ), + (fun () -> + code#aload jsig 0; + ) + end + + method get_constructor_sig = + method_sig (List.map snd (DynArray.to_list sigs)) None + + method get_jsig = jsig + method get_path = match jsig with TObject(path,_) -> path | _ -> assert false + + method get_args = DynArray.to_list sigs +end + +let create_context_class gctx jc jm name vl = match vl with + | [(vid,vname,vsig)] -> + let jsig = get_boxed_type vsig in + let ctx_class = new closure_context jsig in + ctx_class#add vid vname jsig; + ctx_class + | _ -> + let jc = jc#spawn_inner_class (Some jm) object_path None in + let path = jc#get_this_path in + let ctx_class = new closure_context (object_path_sig path) in + let jsigs = List.map (fun (_,_,vsig) -> vsig) vl in + let jm_ctor = jc#spawn_method "" (method_sig jsigs None) [MPublic] in + jm_ctor#load_this; + jm_ctor#call_super_ctor ConstructInit (method_sig [] None); + List.iter2 (fun (vid,vname,vtype) jsig -> + jm_ctor#add_argument_and_field vname jsig; + ctx_class#add vid vname jsig; + ) vl jsigs; + jm_ctor#get_code#return_void; + write_class gctx.jar path (jc#export_class gctx.default_export_config); + ctx_class + +let rvalue_any = RValue None +let rvalue_sig jsig = RValue (Some jsig) +let rvalue_type t = RValue (Some (jsignature_of_type t)) + +class texpr_to_jvm gctx (jc : JvmClass.builder) (jm : JvmMethod.builder) (return_type : Type.t) = object(self) + val com = gctx.com + val code = jm#get_code + val pool : JvmConstantPool.constant_pool = jc#get_pool + + val mutable local_lookup = Hashtbl.create 0; + val mutable last_line = 0 + + val mutable breaks = [] + val mutable continue = 0 + val mutable caught_exceptions = [] + val mutable block_exits = [] + val mutable env = None + + method vtype t = + jsignature_of_type t + + method mknull t = com.basic.tnull (follow t) + + (* locals *) + + method add_named_local (name : string) (jsig : jsignature) = + jm#add_local name jsig VarArgument + + method add_local v init_state : (int * (unit -> unit) * (unit -> unit)) = + let t = self#vtype v.v_type in + let slot,load,store = jm#add_local v.v_name t init_state in + Hashtbl.add local_lookup v.v_id (slot,load,store); + slot,load,store + + method get_local_by_id (vid,vname) = + if vid = 0 then + (0,(fun () -> jm#load_this),(fun () -> assert false)) + else try + Hashtbl.find local_lookup vid + with Not_found -> try + begin match env with + | Some env -> + env#get code vid + | None -> + raise Not_found + end + with Not_found -> + failwith ("Unbound local: " ^ vname) + + method get_local v = + self#get_local_by_id (v.v_id,v.v_name) + + method set_context (ctx : closure_context) = + env <- Some ctx + + (* casting *) + + method expect_reference_type = jm#expect_reference_type + + method cast t = + if follow t != t_dynamic then begin + let vt = self#vtype t in + jm#cast vt + end else + self#expect_reference_type + + method cast_expect ret t = match ret with + | RValue (Some jsig) -> jm#cast jsig + | _ -> self#cast t + + method tfunction e tf = + let name = jc#get_next_closure_name in + let outside = match Texpr.collect_captured_vars e with + | [],false -> + None + | vl,accesses_this -> + let vl = List.map (fun v -> v.v_id,v.v_name,jsignature_of_type v.v_type) vl in + let vl = if accesses_this then (0,"this",jc#get_jsig) :: vl else vl in + let ctx_class = create_context_class gctx jc jm name vl in + Some ctx_class + in + let jsig = + let args = List.map (fun (v,cto) -> + if cto <> None then v.v_type <- self#mknull v.v_type; + self#vtype v.v_type + ) tf.tf_args in + let args = match outside with + | None -> args + | Some ctx_class -> ctx_class#get_jsig :: args + in + method_sig args (if ExtType.is_void (follow tf.tf_type) then None else Some (self#vtype tf.tf_type)) + in + begin + let jm = jc#spawn_method name jsig [MPublic;MStatic] in + let handler = new texpr_to_jvm gctx jc jm tf.tf_type in + begin match outside with + | None -> () + | Some ctx_class -> + handler#set_context ctx_class; + let name = match ctx_class#get_args with + | [(_,name),_] -> name + | _ -> "_hx_ctx" + in + ignore(handler#add_named_local name ctx_class#get_jsig) + end; + let inits = List.map (fun (v,cto) -> + let _,load,save = handler#add_local v VarArgument in + match cto with + | Some e when (match e.eexpr with TConst TNull -> false | _ -> true) -> + let f () = + load(); + let jsig = self#vtype v.v_type in + jm#if_then + (fun () -> jm#get_code#if_nonnull_ref jsig) + (fun () -> + handler#texpr (rvalue_sig jsig) e; + jm#cast jsig; + save(); + ) + in + Some f + | _ -> + None + ) tf.tf_args in + jm#finalize_arguments; + List.iter (function + | None -> () + | Some f -> f() + ) inits; + handler#texpr RReturn tf.tf_expr; + end; + jm#read_closure true jc#get_this_path name jsig; + outside + + (* access *) + + method read_native_array vta vte = + NativeArray.read code vta vte + + method write_native_array vta vte = + NativeArray.write code vta vte + + method read cast e1 fa = + match fa with + | FStatic({cl_path = (["java";"lang"],"Math")},({cf_name = "NaN" | "POSITIVE_INFINITY" | "NEGATIVE_INFINITY"} as cf)) -> + jm#getstatic double_path cf.cf_name TDouble + | FStatic({cl_path = (["java";"lang"],"Math")},({cf_name = "isNaN" | "isFinite"} as cf)) -> + jm#read_closure true double_path cf.cf_name (jsignature_of_type cf.cf_type); + | FStatic({cl_path = (["java";"lang"],"String")},({cf_name = "fromCharCode"} as cf)) -> + jm#read_closure true (["haxe";"jvm"],"StringExt") cf.cf_name (jsignature_of_type cf.cf_type); + | FStatic(c,({cf_kind = Method (MethNormal | MethInline)} as cf)) -> + jm#read_closure true c.cl_path cf.cf_name (jsignature_of_type cf.cf_type); + | FStatic(c,cf) -> + jm#getstatic c.cl_path cf.cf_name (self#vtype cf.cf_type); + cast(); + | FInstance({cl_path = (["java";"lang"],"String")},_,{cf_name = "length"}) -> + self#texpr rvalue_any e1; + jm#invokevirtual string_path "length" (method_sig [] (Some TInt)) + | FInstance({cl_path = (["java"],"NativeArray")},_,{cf_name = "length"}) -> + self#texpr rvalue_any e1; + let vtobj = self#vtype e1.etype in + code#arraylength vtobj; + | FInstance(c,tl,cf) | FClosure(Some(c,tl),({cf_kind = Method MethDynamic} as cf)) when not (is_interface_var_access c cf) -> + self#texpr rvalue_any e1; + jm#getfield c.cl_path cf.cf_name (self#vtype cf.cf_type); + cast(); + | FEnum(en,ef) when not (match follow ef.ef_type with TFun _ -> true | _ -> false) -> + let jsig = self#vtype ef.ef_type in + let offset = pool#add_field en.e_path ef.ef_name jsig FKField in + code#getstatic offset jsig; + cast(); + | FAnon ({cf_name = s} as cf) -> + self#texpr rvalue_any e1; + let default () = + jm#string s; + jm#invokestatic haxe_jvm_path "readField" (method_sig [object_sig;string_sig] (Some object_sig)); + cast(); + in + begin match follow e1.etype with + | TAnon an -> + let path,_ = TAnonIdentifiaction.identify gctx an.a_fields in + code#dup; + code#instanceof path; + jm#if_then_else + (fun () -> code#if_ref CmpEq) + (fun () -> + jm#cast (object_path_sig path); + jm#getfield path s (self#vtype cf.cf_type); + cast(); + ) + (fun () -> default()); + | _ -> + default(); + end + | FDynamic s | FInstance(_,_,{cf_name = s}) | FEnum(_,{ef_name = s}) | FClosure(Some({cl_interface = true},_),{cf_name = s}) | FClosure(None,{cf_name = s}) -> + self#texpr rvalue_any e1; + jm#string s; + jm#invokestatic haxe_jvm_path "readField" (method_sig [object_sig;string_sig] (Some object_sig)); + cast(); + | FClosure((Some(c,_)),cf) -> + let jsig = self#vtype cf.cf_type in + jm#read_closure false c.cl_path cf.cf_name jsig; + self#texpr rvalue_any e1; + jm#invokevirtual method_handle_path "bindTo" (method_sig [object_sig] (Some method_handle_sig)); + + method read_write ret ak e (f : unit -> unit) = + let apply dup = + if ret <> RVoid && ak = AKPost then dup(); + f(); + if ret <> RVoid && ak <> AKPost then dup(); + in + match (Texpr.skip e).eexpr with + | TLocal v -> + let _,load,store = self#get_local v in + if ak <> AKNone then load(); + apply (fun () -> code#dup); + store(); + | TField(_,FStatic(c,cf)) -> + let jsig_cf = self#vtype cf.cf_type in + if ak <> AKNone then jm#getstatic c.cl_path cf.cf_name jsig_cf; + apply (fun () -> code#dup); + jm#putstatic c.cl_path cf.cf_name jsig_cf; + | TField(e1,FInstance(c,tl,cf)) when not (is_interface_var_access c cf) -> + self#texpr rvalue_any e1; + let jsig_cf = self#vtype cf.cf_type in + if ak <> AKNone then begin + code#dup; + jm#getfield c.cl_path cf.cf_name jsig_cf + end; + apply (fun () -> code#dup_x1); + self#cast cf.cf_type; + jm#putfield c.cl_path cf.cf_name jsig_cf + | TField(e1,(FDynamic s | FAnon {cf_name = s} | FInstance(_,_,{cf_name = s}))) -> + self#texpr rvalue_any e1; + if ak <> AKNone then code#dup; + jm#string s; + if ak <> AKNone then begin + code#dup_x1; + jm#invokestatic haxe_jvm_path "readField" (method_sig [object_sig;string_sig] (Some object_sig)); + self#cast_expect ret e.etype; + end; + apply (fun () -> code#dup_x2); + self#cast (self#mknull e.etype); + jm#invokestatic haxe_jvm_path "writeField" (method_sig [object_sig;string_sig;object_sig] None) + | TArray(e1,e2) -> + begin match follow e1.etype with + | TInst({cl_path = (["haxe";"root"],"Array")} as c,[t]) -> + let t = self#mknull t in + self#texpr rvalue_any e1; + if ak <> AKNone then code#dup; + self#texpr rvalue_any e2; + jm#cast TInt; + if ak <> AKNone then begin + code#dup_x1; + jm#invokevirtual c.cl_path "__get" (method_sig [TInt] (Some object_sig)); + self#cast_expect ret e.etype; + end; + apply (fun () -> code#dup_x2;); + self#cast t; + jm#invokevirtual c.cl_path "__set" (method_sig [TInt;object_sig] None); + | TInst({cl_path = (["java"],"NativeArray")},[t]) -> + let vte = self#vtype t in + let vta = self#vtype e1.etype in + self#texpr rvalue_any e1; + if ak <> AKNone then code#dup; + self#texpr rvalue_any e2; + if ak <> AKNone then begin + code#dup_x1; + self#read_native_array vta vte + end; + apply (fun () -> code#dup_x2); + self#cast t; + self#write_native_array vta vte + | _ -> + self#texpr rvalue_any e1; + if ak <> AKNone then code#dup; + self#texpr rvalue_any e2; + jm#cast TInt; + if ak <> AKNone then begin + code#dup_x1; + jm#invokestatic haxe_jvm_path "arrayRead" (method_sig [object_sig;TInt] (Some object_sig)); + end; + apply (fun () -> code#dup_x2;); + self#cast e.etype; + self#expect_reference_type; + jm#invokestatic haxe_jvm_path "arrayWrite" (method_sig [object_sig;TInt;object_sig] None); + end + | _ -> + print_endline (s_expr_ast false "" (s_type (print_context())) e); + assert false + + (* branching *) + + method apply_cmp = function + | CmpNormal(op,_) -> (fun () -> code#if_ref op) + | CmpSpecial f -> f + + method if_null t = + (fun () -> code#if_null_ref t) + + method if_not_null t = + (fun () -> code#if_nonnull_ref t) + + method condition e = match (Texpr.skip e).eexpr with + | TBinop((OpEq | OpNotEq | OpLt | OpGt | OpLte | OpGte) as op,e1,e2) -> + let op = convert_cmp_op op in + self#binop_compare op e1 e2 + | _ -> + self#texpr rvalue_any e; + jm#cast TBool; + CmpNormal(CmpEq,TBool) + + method switch ret e1 cases def = + (* TODO: hack because something loses the exhaustiveness marker before we get here *) + let is_exhaustive = OptimizerTexpr.is_exhaustive e1 || (ExtType.is_bool (follow e1.etype) && List.length cases > 1) in + if cases = [] then + self#texpr ret e1 + else if List.for_all is_const_int_pattern cases then begin + let cases = List.map (fun (el,e) -> + let il = List.map (fun e -> match e.eexpr with + | TConst (TInt i32) -> i32 + | _ -> assert false + ) el in + (il,(fun () -> self#texpr ret e)) + ) cases in + let def = match def with + | None -> None + | Some e -> Some (fun () -> self#texpr ret e) + in + self#texpr rvalue_any e1; + jm#cast TInt; + ignore(jm#int_switch is_exhaustive cases def); + end else if List.for_all is_const_string_pattern cases then begin + let cases = List.map (fun (el,e) -> + let il = List.map (fun e -> match e.eexpr with + | TConst (TString s) -> java_hash s + | _ -> assert false + ) el in + (il,(fun () -> self#texpr ret e)) + ) cases in + let def = match def with + | None -> None + | Some e -> Some (fun () -> self#texpr ret e) + in + self#texpr rvalue_any e1; + jm#cast string_sig; + let r = ref 0 in + (* all strings can be null and we're not supposed to cause NPEs here... *) + code#dup; + jm#if_then + (fun () -> jm#get_code#if_nonnull_ref string_sig) + (fun () -> + code#pop; + r := code#get_fp; + code#goto r + ); + jm#invokevirtual string_path "hashCode" (method_sig [] (Some TInt)); + let r_default = jm#int_switch is_exhaustive cases def in + r := r_default - !r; + end else begin + (* TODO: rewriting this is stupid *) + let pop_scope = jm#push_scope in + self#texpr rvalue_any e1; + let v = alloc_var VGenerated "tmp" e1.etype null_pos in + let _,_,store = self#add_local v VarWillInit in + self#cast v.v_type; + store(); + let ev = mk (TLocal v) v.v_type null_pos in + let el = List.rev_map (fun (el,e) -> + let f e' = mk (TBinop(OpEq,ev,e')) com.basic.tbool e'.epos in + let e_cond = match el with + | [] -> assert false + | [e] -> f e + | e :: el -> + List.fold_left (fun eacc e -> + mk (TBinop(OpBoolOr,eacc,f e)) com.basic.tbool e.epos + ) (f e) el + in + (e_cond,e) + ) cases in + (* If we rewrite an exhaustive switch that has no default value, treat the last case as the default case to satisfy control flow. *) + let cases,def = if is_exhaustive && def = None then (match List.rev cases with (_,e) :: cases -> List.rev cases,Some e | _ -> assert false) else cases,def in + let e = List.fold_left (fun e_else (e_cond,e_then) -> Some (mk (TIf(e_cond,e_then,e_else)) e_then.etype e_then.epos)) def el in + self#texpr ret (Option.get e); + pop_scope() + end + + (* binops *) + + method binop_exprs cast_type f1 f2 = + f1(); + jm#cast ~allow_to_string:true cast_type; + f2(); + jm#cast ~allow_to_string:true cast_type; + + method get_binop_type_sig jsig1 jsig2 = match jsig1,jsig2 with + | TObject((["java";"lang"],"String"),_),_ + | _,TObject((["java";"lang"],"String"),_) -> + string_sig + | TLong,_ | _,TLong -> TLong + | TDouble,_ | _,TDouble -> TDouble + | TFloat,_ | _,TFloat -> TFloat + | TInt,_ | _,TInt -> TInt + | TShort,_ | _,TShort -> TShort + | TChar,_ | _,TChar -> TChar + | TByte,_ | _,TByte -> TByte + | TBool,_ | _,TBool -> TBool + | jsig1,jsig2 -> + if jsig1 = string_sig || jsig2 = string_sig then + string_sig + else + object_sig + + method get_binop_type t1 t2 = self#get_binop_type_sig (jsignature_of_type t1) (jsignature_of_type t2) + + method do_compare op = + match code#get_stack#get_stack_items 2 with + | [TInt | TByte | TChar | TBool;TInt | TByte | TChar | TBool] -> + let op = flip_cmp_op op in + CmpSpecial (fun () -> code#if_icmp_ref op) + | [TObject((["java";"lang"],"String"),[]);TObject((["java";"lang"],"String"),[])] -> + jm#invokestatic haxe_jvm_path "stringCompare" (method_sig [string_sig;string_sig] (Some TInt)); + let op = flip_cmp_op op in + CmpNormal(op,TBool) + | [TObject((["java";"lang"],"Object"),[]) | TTypeParameter _;_] + | [_;TObject((["java";"lang"],"Object"),[]) | TTypeParameter _] -> + jm#invokestatic haxe_jvm_path "compare" (method_sig [object_sig;object_sig] (Some TInt)); + let op = flip_cmp_op op in + CmpNormal(op,TBool) + | [(TObject _ | TArray _ | TMethod _) as t1;(TObject _ | TArray _ | TMethod _) as t2] -> + CmpSpecial (fun () -> (if op = CmpEq then code#if_acmp_ne_ref else code#if_acmp_eq_ref) t1 t2) + | [TDouble;TDouble] -> + let op = flip_cmp_op op in + begin match op with + | CmpGe | CmpGt -> code#dcmpg; + | _ -> code#dcmpl; + end; + CmpNormal(op,TDouble) + | [TFloat;TFloat] -> + let op = flip_cmp_op op in + begin match op with + | CmpGe | CmpGt -> code#fcmpg; + | _ -> code#fcmpl; + end; + CmpNormal(op,TFloat) + | [TLong;TLong] -> + let op = flip_cmp_op op in + code#lcmpl; + CmpNormal(op,TLong) + | [t1;t2] -> + jerror (Printf.sprintf "Can't compare %s and %s" (generate_signature false t1) (generate_signature false t2)) + | tl -> + jerror (Printf.sprintf "Bad stack: %s" (String.concat ", " (List.map (generate_signature false) tl))); + + method binop_compare op e1 e2 = + let sig1 = jsignature_of_type e1.etype in + let sig2 = jsignature_of_type e2.etype in + match (Texpr.skip e1),(Texpr.skip e2) with + | {eexpr = TConst TNull},_ when not (is_unboxed sig2) -> + self#texpr rvalue_any e2; + CmpSpecial ((if op = CmpEq then self#if_not_null else self#if_null) sig2) + | _,{eexpr = TConst TNull} when not (is_unboxed sig1) -> + self#texpr rvalue_any e1; + CmpSpecial ((if op = CmpEq then self#if_not_null else self#if_null) sig1) + | {eexpr = TConst (TInt i32);etype = t2},e1 when Int32.to_int i32 = 0 && sig2 = TInt -> + let op = match op with + | CmpGt -> CmpGe + | CmpLt -> CmpLe + | CmpLe -> CmpLt + | CmpGe -> CmpGt + | CmpEq -> CmpNe + | CmpNe -> CmpEq + in + self#texpr rvalue_any e1; + self#cast t2; + CmpNormal(op,TInt) + | e1,{eexpr = TConst (TInt i32); etype = t2;} when Int32.to_int i32 = 0 && sig1 = TInt-> + let op = flip_cmp_op op in + self#texpr rvalue_any e1; + self#cast t2; + CmpNormal(op,TInt) + | _ -> + match is_unboxed sig1,is_unboxed sig2 with + | true,true -> + let f e () = self#texpr rvalue_any e in + self#binop_exprs (self#get_binop_type e1.etype e2.etype) (f e1) (f e2); + self#do_compare op + | false,false -> + let sig_unboxed1 = get_unboxed_type sig1 in + let sig_unboxed2 = get_unboxed_type sig2 in + if sig1 = sig_unboxed1 && sig2 = sig_unboxed2 then begin + (* No basic types involved, do normal comparison *) + self#texpr rvalue_any e1; + self#texpr rvalue_any e2; + self#do_compare op + end else begin + (* At least one of the types is a wrapped numeric one *) + let cast_type = self#get_binop_type_sig sig_unboxed1 sig_unboxed2 in + self#texpr rvalue_any e1; + jm#get_code#dup; + jm#if_then_else + (self#if_not_null sig1) + (fun () -> + jm#get_code#pop; + self#texpr rvalue_any e2; + self#boolop (CmpSpecial (self#if_not_null sig2)) + ) + (fun () -> + jm#cast ~not_null:true cast_type; + self#texpr rvalue_any e2; + jm#get_code#dup; + jm#if_then_else + (self#if_not_null sig2) + (fun () -> + jm#get_code#pop; + jm#get_code#pop; + jm#get_code#bconst (op = CmpNe); + ) + (fun () -> + jm#cast ~not_null:true cast_type; + self#boolop (self#do_compare op); + ) + ); + CmpNormal(CmpEq,TBool) + end + | false,true -> + self#texpr rvalue_any e1; + jm#get_code#dup; + jm#if_then_else + (self#if_not_null sig1) + (fun () -> + jm#get_code#pop; + jm#get_code#bconst (op = CmpNe) + ) + (fun () -> + (match (get_unboxed_type sig1), sig2 with + | (TFloat | TDouble as unboxed_sig1), TInt -> + jm#cast ~not_null:true unboxed_sig1; + self#texpr rvalue_any e2; + jm#cast ~not_null:true unboxed_sig1 + | _ -> + jm#cast ~not_null:true sig2; + self#texpr rvalue_any e2 + ); + self#boolop (self#do_compare op) + ); + CmpNormal(CmpEq,TBool) + | true,false -> + self#texpr rvalue_any e1; + let cast = + match sig1, (get_unboxed_type sig2) with + | TInt, (TFloat | TDouble as unboxed_sig2) -> + jm#cast ~not_null:true unboxed_sig2; + self#texpr rvalue_any e2; + (fun() -> jm#cast ~not_null:true unboxed_sig2) + | _ -> + self#texpr rvalue_any e2; + (fun() -> jm#cast ~not_null:true sig1) + in + jm#get_code#dup; + jm#if_then_else + (self#if_not_null sig2) + (fun () -> + jm#get_code#pop; + jm#get_code#pop; + jm#get_code#bconst (op = CmpNe); + ) + (fun () -> + cast(); + self#boolop (self#do_compare op) + ); + CmpNormal(CmpEq,TBool) + + method binop_basic ret op cast_type f1 f2 = + let emit_exprs () = self#binop_exprs cast_type f1 f2 in + let method_name () = match op with + | OpAdd -> "opAdd" + | OpSub -> "opSub" + | OpMult -> "opMul" + | OpDiv -> "opDiv" + | OpMod -> "opMod" + | OpAnd -> "opAnd" + | OpOr -> "opOr" + | OpXor -> "opXor" + | OpShl -> "opShl" + | OpShr -> "opShr" + | OpUShr -> "opUshr" + | _ -> assert false + in + begin match cast_type with + | TByte | TShort | TInt -> + begin match op with + | OpAdd -> + emit_exprs(); + code#iadd + | OpSub -> + emit_exprs(); + code#isub + | OpMult -> + emit_exprs(); + code#imul + | OpDiv -> + f1(); + jm#cast TDouble; + f2(); + jm#cast TDouble; + code#ddiv; + | OpAnd -> + emit_exprs(); + code#iand + | OpOr -> + emit_exprs(); + code#ior + | OpXor -> + emit_exprs(); + code#ixor + | OpShl -> + emit_exprs(); + code#ishl + | OpShr -> + emit_exprs(); + code#ishr + | OpUShr -> + emit_exprs(); + code#iushr + | OpMod -> + emit_exprs(); + code#irem + | _ -> jerror (Printf.sprintf "Unsupported binop on TInt: %s" (s_binop op)) + end + | TFloat -> + emit_exprs(); + begin match op with + | OpAdd -> code#fadd + | OpSub -> code#fsub + | OpMult -> code#fmul + | OpDiv -> code#fdiv + | OpMod -> code#frem + | _ -> jerror (Printf.sprintf "Unsupported binop on TFloat: %s" (s_binop op)) + end + | TDouble -> + emit_exprs(); + begin match op with + | OpAdd -> code#dadd + | OpSub -> code#dsub + | OpMult -> code#dmul + | OpDiv -> code#ddiv + | OpMod -> code#drem + | _ -> jerror (Printf.sprintf "Unsupported binop on TDouble: %s" (s_binop op)) + end + | TLong -> + begin match op with + | OpAdd -> + emit_exprs(); + code#ladd + | OpSub -> + emit_exprs(); + code#lsub + | OpMult -> + emit_exprs(); + code#lmul + | OpDiv -> + emit_exprs(); + code#ldiv + | OpAnd -> + emit_exprs(); + code#land_ + | OpOr -> + emit_exprs(); + code#lor_ + | OpXor -> + emit_exprs(); + code#lxor_ + | OpShl -> + f1(); + jm#cast TLong; + f2(); + jm#cast TInt; + code#lshl; + | OpShr -> + f1(); + jm#cast TLong; + f2(); + jm#cast TInt; + code#lshr; + | OpUShr -> + f1(); + jm#cast TLong; + f2(); + jm#cast TInt; + code#lushr; + | OpMod -> + emit_exprs(); + code#lrem + | _ -> jerror (Printf.sprintf "Unsupported binop on TInt: %s" (s_binop op)) + end + | TBool | TObject((["java";"lang"],"Object"),_) | TTypeParameter _ -> + begin match op with + | OpBoolAnd -> + let operand f = + f(); + jm#cast TBool; + in + operand f1; + jm#if_then_else + (fun () -> code#if_ref CmpEq) + (fun () -> operand f2) + (fun () -> code#bconst false) + | OpBoolOr -> + let operand f = + f(); + jm#cast TBool; + in + operand f1; + jm#if_then_else + (fun () -> code#if_ref CmpEq) + (fun () -> code#bconst true) + (fun () -> operand f2) + | _ -> + emit_exprs(); + let name = method_name () in + jm#invokestatic haxe_jvm_path name (method_sig [object_sig;object_sig] (Some object_sig)) + end + | TObject(path,_) -> + emit_exprs(); + if path = string_path then + jm#invokestatic haxe_jvm_path "stringConcat" (method_sig [object_sig;object_sig] (Some string_sig)) + else begin + let name = method_name () in + jm#invokestatic haxe_jvm_path name (method_sig [object_sig;object_sig] (Some object_sig)) + end + | _ -> + jerror (Printf.sprintf "Unsupported operation %s on %s" (s_binop op) (generate_signature false cast_type)) + end; + + method boolop cmp = + jm#if_then_else + (self#apply_cmp cmp) + (fun () -> code#bconst true) + (fun () -> code#bconst false) + + method var_slot_is_in_int8_range v = + let slot,_,_ = self#get_local v in + in_range true Int8Range slot + + method binop ret op e1 e2 = match op with + | OpEq | OpNotEq | OpLt | OpGt | OpLte | OpGte -> + let op = convert_cmp_op op in + self#boolop (self#binop_compare op e1 e2) + | OpAssign -> + let f () = + self#texpr (rvalue_type e1.etype) e2; + self#cast e1.etype; + in + self#read_write ret AKNone e1 f + | OpAssignOp op -> + let jsig1 = jsignature_of_type e1.etype in + begin match op,(Texpr.skip e1).eexpr,(Texpr.skip e2).eexpr with + | OpAdd,TLocal v,TConst (TInt i32) when ExtType.is_int v.v_type && in_range false Int8Range (Int32.to_int i32) && self#var_slot_is_in_int8_range v-> + let slot,load,_ = self#get_local v in + let i = Int32.to_int i32 in + code#iinc slot i; + if ret <> RVoid then load(); + | OpSub,TLocal v,TConst (TInt i32) when ExtType.is_int v.v_type && in_range false Int8Range (-Int32.to_int i32) && self#var_slot_is_in_int8_range v -> + let slot,load,_ = self#get_local v in + let i = -Int32.to_int i32 in + code#iinc slot i; + if ret <> RVoid then load(); + | _ -> + let f () = + self#binop_basic ret op (self#get_binop_type e1.etype e2.etype) (fun () -> ()) (fun () -> self#texpr rvalue_any e2); + jm#cast jsig1; + in + self#read_write ret AKPre e1 f + end + | _ -> + let f e () = self#texpr rvalue_any e in + self#binop_basic ret op (self#get_binop_type e1.etype e2.etype) (f e1) (f e2) + + method unop ret op flag e = + match op,(Texpr.skip e).eexpr with + | (Increment | Decrement),TLocal v when ExtType.is_int v.v_type && self#var_slot_is_in_int8_range v -> + let slot,load,_ = self#get_local v in + if flag = Postfix && ret <> RVoid then load(); + code#iinc slot (if op = Increment then 1 else -1); + if flag = Prefix && ret <> RVoid then load(); + | (Increment | Decrement),_ -> + let is_null = is_null e.etype in + let f () = + begin match jm#get_code#get_stack#top with + | TLong -> + code#lconst Int64.one; + if op = Increment then code#ladd else code#lsub + | TDouble -> + code#dconst 1.; + if op = Increment then code#dadd else code#dsub + | TByte | TShort | TInt -> + code#iconst Int32.one; + if op = Increment then code#iadd else code#isub; + if is_null then self#expect_reference_type; + | _ -> + jm#invokestatic haxe_jvm_path (if op = Increment then "opIncrement" else "opDecrement") (method_sig [object_sig] (Some object_sig)) + end + in + self#read_write ret (if flag = Prefix then AKPre else AKPost) e f; + | Neg,_ -> + self#texpr rvalue_any e; + let jsig = jsignature_of_type (follow e.etype) in + jm#cast jsig; + begin match jsig with + | TLong -> code#lneg; + | TDouble -> code#dneg; + | TByte | TShort | TInt -> code#ineg; + | _ -> jm#invokestatic haxe_jvm_path "opNeg" (method_sig [object_sig] (Some object_sig)) + end; + self#cast e.etype; + | Not,_ -> + jm#if_then_else + (self#apply_cmp (self#condition e)) + (fun () -> code#bconst false) + (fun () -> code#bconst true) + | NegBits,_ -> + let jsig = jsignature_of_type (follow e.etype) in + self#texpr rvalue_any e; + jm#cast jsig; + begin match jsig with + | TByte | TShort | TInt -> + code#iconst Int32.minus_one; + code#ixor; + | TLong -> + code#lconst Int64.minus_one; + code#lxor_; + | _ -> + jm#invokestatic haxe_jvm_path "opNegBits" (method_sig [object_sig] (Some object_sig)) + end; + self#cast e.etype; + + (* calls *) + + method get_argument_signatures t el = + match jsignature_of_type t with + | TMethod(jsigs,r) -> jsigs,r + | _ -> List.map (fun _ -> object_sig) el,(Some object_sig) + + method call_arguments t el = + let tl,tr = self#get_argument_signatures t el in + let varargs_type = match follow t with + | TFun(tl,_) -> + begin match List.rev tl with + | (_,_,(TAbstract({a_path = ["haxe";"extern"],"Rest"},[t]))) :: _ -> Some (jsignature_of_type t) + | _ -> None + end + | _ -> + None + in + let rec loop acc tl el = match tl,el with + | jsig :: tl,e :: el -> + begin match tl,varargs_type with + | [],Some jsig' -> + self#new_native_array jsig' (e :: el); + List.rev (jsig :: acc) + | _ -> + self#texpr (rvalue_sig jsig) e; + jm#cast jsig; + loop (jsig :: acc) tl el + end + | _,[] -> List.rev acc + | [],e :: el -> + (* TODO: this sucks *) + self#texpr rvalue_any e; + loop (self#vtype e.etype :: acc) [] el + in + let tl = loop [] tl el in + tl,tr + + method call ret tr e1 el = + let retype tr = match tr with None -> [] | Some t -> [t] in + let tro = match (Texpr.skip e1).eexpr with + | TField(_,FStatic({cl_path = ["haxe";"jvm"],"Jvm"},({cf_name = "referenceEquals"} as cf))) -> + let tl,tr = self#call_arguments cf.cf_type el in + begin match tl with + | [t1;t2] -> self#boolop (CmpSpecial (fun () -> code#if_acmp_ne_ref t1 t2)) + | _ -> assert false + end; + tr + | TField(_,FStatic({cl_path = ["haxe";"jvm"],"Jvm"},({cf_name = "instanceof"}))) -> + begin match el with + | [e1;{eexpr = TTypeExpr mt;epos = pe}] -> + self#texpr rvalue_any e1; + self#expect_reference_type; + let path = match jsignature_of_type (type_of_module_type mt) with + | TObject(path,_) -> path + | _ -> Error.error "Class expected" pe + in + code#instanceof path; + Some TBool + | _ -> Error.error "Type expression expected" e1.epos + end; + | TField(_,FStatic({cl_path = ["haxe";"jvm"],"Jvm"},({cf_name = "invokedynamic"}))) -> + begin match el with + | e_bsm :: {eexpr = TConst (TString name)} :: {eexpr = TArrayDecl el_static_args} :: el -> + let t = tfun (List.map (fun e -> e.etype) el) tr in + let tl,tr = self#call_arguments t el in + let path,mname = match e_bsm.eexpr with + | TField(_,FStatic(c,cf)) -> c.cl_path,cf.cf_name + | _ -> Error.error "Reference to bootstrap method expected" e_bsm.epos + in + let rec loop consts jsigs static_args = match static_args with + | e :: static_args -> + let const,jsig = match e.eexpr with + | TConst (TString s) -> pool#add_const_string s,string_sig + | TConst (TInt i) -> pool#add (ConstInt i),TInt + | TConst (TFloat f) -> pool#add (ConstDouble (float_of_string f)),TDouble + | TField(_,FStatic(c,cf)) -> + let offset = pool#add_field c.cl_path cf.cf_name (self#vtype cf.cf_type) FKMethod in + pool#add (ConstMethodHandle(6, offset)),method_handle_sig + | _ -> Error.error "Invalid static argument" e.epos + in + loop (const :: consts) (jsig :: jsigs) static_args + | [] -> + List.rev consts,List.rev jsigs + in + let consts,jsigs = loop [] [] el_static_args in + let mtl = method_lookup_sig :: string_sig :: method_type_sig :: jsigs in + let index = jc#get_bootstrap_method path mname (method_sig mtl (Some call_site_sig)) consts in + let jsig_method = method_sig tl tr in + let offset_info = pool#add_name_and_type name jsig_method FKMethod in + let offset = pool#add (ConstInvokeDynamic(index,offset_info)) in + code#invokedynamic offset tl (retype tr); + tr + | _ -> + Error.error "Bad invokedynamic call" e1.epos + end + | TField(_,FStatic({cl_path = (["java";"lang"],"Math")},{cf_name = ("isNaN" | "isFinite") as name})) -> + begin match el with + | [e1] -> + self#texpr rvalue_any e1; + jm#cast TDouble; + jm#invokestatic (["java";"lang"],"Double") name (method_sig [TDouble] (Some TBool)); + Some TBool + | _ -> + assert false + end; + | TField(_,FStatic({cl_path = (["java";"lang"],"Math")},{cf_name = ("floor" | "ceil" | "round") as name})) -> + begin match el with + | [e1] -> + self#texpr rvalue_any e1; + jm#cast TDouble; + let rsig = if name = "round" then TLong else TDouble in + jm#invokestatic (["java";"lang"],"Math") name (method_sig [TDouble] (Some rsig)); + jm#cast TInt; + Some TInt + | _ -> + assert false + end; + | TField(_,FStatic({cl_path = (["java";"lang"],"Math")} as c,({cf_name = ("ffloor" | "fceil")} as cf))) -> + let tl,tr = self#call_arguments cf.cf_type el in + jm#invokestatic c.cl_path (String.sub cf.cf_name 1 (String.length cf.cf_name - 1)) (method_sig tl tr); + tr + | TField(_,FStatic({cl_path = (["haxe";"_Int64"],"Int64_Impl_")},{cf_name = "make"})) -> + begin match el with + | [{eexpr = TConst (TInt i1)};{eexpr = TConst (TInt i2)}] -> + let high = Int64.of_int32 i1 in + let high = Int64.shift_left high 32 in + let low = Int64.of_int32 i2 in + let low = Int64.logand low (Int64.of_string "0xFFFFFFFF") in + let i = Int64.logor high low in + jm#get_code#lconst i; + Some TLong + | [e1;e2] -> + self#texpr (rvalue_sig TLong) e1; + jm#cast TLong; + jm#get_code#iconst (Int32.of_int 32); + jm#get_code#lshl; + self#texpr (rvalue_sig TLong) e2; + jm#cast TLong; + jm#get_code#lconst (Int64.of_string "0xFFFFFFFF"); + jm#get_code#land_; + jm#get_code#lor_; + Some TLong + | _ -> + assert false + end + | TIdent "__array__" | TField(_,FStatic({cl_path = (["java"],"NativeArray")},{cf_name = "make"})) -> + begin match follow tr with + | TInst({cl_path = (["java"],"NativeArray")},[t]) -> + let jsig = self#vtype t in + self#new_native_array jsig el; + Some (array_sig jsig) + | _ -> + Error.error (Printf.sprintf "Bad __array__ type: %s" (s_type (print_context()) tr)) e1.epos; + end + | TField(e1,FStatic(c,({cf_kind = Method (MethNormal | MethInline)} as cf))) -> + let tl,tr = self#call_arguments cf.cf_type el in + jm#invokestatic c.cl_path cf.cf_name (method_sig tl tr); + tr + | TField(e1,FInstance(c,tl,({cf_kind = Method (MethNormal | MethInline)} as cf))) -> + let is_super = match e1.eexpr with + | TConst TSuper -> + code#aload jc#get_jsig 0; + true + | _ -> + self#texpr rvalue_any e1; + false + in + begin match find_overload_rec false (apply_params c.cl_params tl) c cf el with + | None -> Error.error "Could not find overload" e1.epos + | Some(c,cf) -> + let tl,tr = self#call_arguments cf.cf_type el in + (if is_super then jm#invokespecial else if c.cl_interface then jm#invokeinterface else jm#invokevirtual) c.cl_path cf.cf_name (self#vtype cf.cf_type); + tr + end + | TField(_,FEnum(en,ef)) -> + let tl,_ = self#call_arguments ef.ef_type el in + let tr = self#vtype tr in + jm#invokestatic en.e_path ef.ef_name (method_sig tl (Some tr)); + Some tr + | TConst TSuper -> + let c,cf = match gctx.current_field_info with + | Some ({super_call_fields = hd :: tl} as info) -> + info.super_call_fields <- tl; + hd + | _ -> + Error.error "Something went wrong" e1.epos + in + let kind = get_construction_mode c cf in + begin match kind with + | ConstructInitPlusNew when jm#get_name = "" -> + jm#load_this; + jm#get_code#aconst_null haxe_empty_constructor_sig; + jm#call_super_ctor ConstructInit (method_sig [haxe_empty_constructor_sig] None); + | _ -> + () + end; + jm#load_this; + let tl,_ = self#call_arguments cf.cf_type el in + jm#call_super_ctor kind (method_sig tl None); + None + | TIdent "__lock__" -> + begin match el with + | [e1;e2] -> + self#texpr rvalue_any e1; + jm#get_code#dup; + let _,load,save = jm#add_local "tmp" (self#vtype e1.etype) VarWillInit in + save(); + jm#get_code#monitorenter; + let f_exit () = + load(); + jm#get_code#monitorexit; + in + block_exits <- (ExitExecute f_exit) :: block_exits; + let fp_from = jm#get_code#get_fp in + self#texpr RVoid e2; + let term_try = jm#is_terminated in + if not jm#is_terminated then f_exit(); + let fp_to = jm#get_code#get_fp in + let r_try = jm#maybe_make_jump in + let fp_target = jm#get_code#get_fp in + let pop_scope = jm#push_scope in + code#get_stack#push throwable_sig; + jm#add_stack_frame; + jm#add_exception { + exc_start_pc = fp_from; + exc_end_pc = fp_to; + exc_handler_pc = fp_target; + exc_catch_type = None; + }; + begin + let _,load,save = jm#add_local "tmp" throwable_sig VarWillInit in + save(); + f_exit(); + jm#add_exception { + exc_start_pc = fp_target; + exc_end_pc = jm#get_code#get_fp; + exc_handler_pc = fp_target; + exc_catch_type = None; + }; + load(); + jm#get_code#athrow; + end; + pop_scope(); + block_exits <- List.tl block_exits; + if not term_try then jm#add_stack_frame; + jm#close_jumps true ([term_try,r_try]); + None + | _ -> assert false + end + | _ -> + let rec has_unknown_args jsig = + is_dynamic_at_runtime jsig || match jsig with + | TMethod(jsigs,_) -> List.exists has_unknown_args jsigs + | _ -> false + in + if has_unknown_args (jsignature_of_type e1.etype) then begin + self#texpr rvalue_any e1; + jm#cast method_handle_sig; + self#new_native_array object_sig el; + jm#invokestatic haxe_jvm_path "call" (method_sig [method_handle_sig;array_sig object_sig] (Some object_sig)); + Some object_sig + end else begin + self#texpr rvalue_any e1; + jm#cast method_handle_sig; + let tl,tr = self#call_arguments e1.etype el in + jm#invokevirtual method_handle_path "invoke" (method_sig tl tr); + tr + end + in + match ret = RVoid,tro with + | true,Some _ -> code#pop + | true,None -> () + | false,Some _ -> self#cast tr; + | false,None -> assert false + + (* exceptions *) + + method throw vt = + jm#expect_reference_type; + jm#invokestatic (["haxe";"jvm"],"Exception") "wrap" (method_sig [object_sig] (Some exception_sig)); + code#athrow; + jm#set_terminated true + + method try_catch ret e1 catches = + let restore = jm#start_branch in + let fp_from = code#get_fp in + let old_exceptions = caught_exceptions in + let excl = List.map (fun (v,e) -> + let exc = new haxe_exception gctx v.v_type in + caught_exceptions <- exc :: caught_exceptions; + exc,v,e + ) catches in + self#texpr ret e1; + caught_exceptions <- old_exceptions; + let term_try = jm#is_terminated in + let r_try = jm#maybe_make_jump in + let fp_to = code#get_fp in + let unwrap () = + code#dup; + code#instanceof haxe_exception_path; + jm#if_then_else + (fun () -> code#if_ref CmpEq) + (fun () -> + jm#cast haxe_exception_sig; + jm#getfield (["haxe";"jvm"],"Exception") "value" object_sig; + ) + (fun () -> jm#cast object_sig); + in + let start_exception_block path jsig = + restore(); + let fp_target = code#get_fp in + let offset = pool#add_path path in + jm#add_exception { + exc_start_pc = fp_from; + exc_end_pc = fp_to; + exc_handler_pc = fp_target; + exc_catch_type = Some offset; + }; + code#get_stack#push jsig; + jm#add_stack_frame; + jm#get_code#dup; + jm#invokestatic haxe_exception_path "setException" (method_sig [throwable_sig] None); + in + let run_catch_expr v e = + let pop_scope = jm#push_scope in + let _,_,store = self#add_local v VarWillInit in + store(); + self#texpr ret e; + pop_scope(); + jm#is_terminated + in + let add_catch (exc,v,e) = + start_exception_block exc#get_native_exception_path exc#get_native_exception_type; + if not exc#is_native_exception then begin + unwrap(); + self#cast v.v_type + end; + let term = run_catch_expr v e in + let r = jm#maybe_make_jump in + term,r + in + let commit_instanceof_checks excl = + start_exception_block throwable_path throwable_sig; + let pop_scope = jm#push_scope in + let _,load,save = jm#add_local "exc" throwable_sig VarWillInit in + code#dup; + save(); + unwrap(); + let restore = jm#start_branch in + let rl = ref [] in + let rec loop excl = match excl with + | [] -> + code#pop; + load(); + code#athrow; + jm#set_terminated true + | (_,v,e) :: excl -> + code#dup; + let path = match self#vtype (self#mknull v.v_type) with TObject(path,_) -> path | _ -> assert false in + if path = object_path then begin + code#pop; + restore(); + let term = run_catch_expr v e in + rl := (term,ref 0) :: !rl; + end else begin + code#instanceof path; + jm#if_then_else + (fun () -> code#if_ref CmpEq) + (fun () -> + restore(); + self#cast v.v_type; + let term = run_catch_expr v e in + rl := (term,ref 0) :: !rl; + ) + (fun () -> loop excl) + end + in + loop excl; + pop_scope(); + !rl + in + let rec loop acc excl = match excl with + | (exc,v,e) :: excl -> + if List.exists (fun (exc',_,_) -> exc'#is_assignable_to exc) excl || excl = [] && not exc#is_native_exception then begin + let res = commit_instanceof_checks ((exc,v,e) :: excl) in + acc @ res + end else begin + let res = add_catch (exc,v,e) in + loop (res :: acc) excl + end + | [] -> + acc + in + let rl = loop [] excl in + jm#close_jumps true ((term_try,r_try) :: rl) + + method emit_block_exits is_loop_exit = + let rec loop stack = match stack with + | [] -> + () + | ExitLoop :: stack -> + if not is_loop_exit then loop stack + | ExitExecute f :: stack -> + f(); + loop stack + in + loop block_exits + + (* texpr *) + + method const ret t ct = match ct with + | Type.TInt i32 -> code#iconst i32 + | TFloat f -> + begin match ret with + | RValue (Some (TFloat | TObject((["java";"lang"],"Float"),_))) -> code#fconst (float_of_string f) + | _ -> code#dconst (float_of_string f) + end + | TBool true -> code#bconst true + | TBool false -> code#bconst false + | TNull -> code#aconst_null (self#vtype t) + | TThis -> + let _,load,_ = self#get_local_by_id (0,"this") in + load() + | TString s -> jm#string s + | TSuper -> failwith "Invalid super access" + + method new_native_array jsig el = + jm#new_native_array jsig (List.map (fun e -> fun () -> self#texpr (rvalue_sig jsig) e) el) + + method basic_type_path name = + let offset = pool#add_field (["java";"lang"],name) "TYPE" java_class_sig FKField in + code#getstatic offset java_class_sig + + method type_expr = function + | TByte -> self#basic_type_path "Byte" + | TChar -> self#basic_type_path "Character" + | TDouble -> self#basic_type_path "Double" + | TFloat -> self#basic_type_path "Float" + | TInt -> self#basic_type_path "Integer" + | TLong -> self#basic_type_path "Long" + | TShort -> self#basic_type_path "Short" + | TBool -> self#basic_type_path "Boolean" + | TObject(path,_) -> + let offset = pool#add_path path in + let t = object_path_sig path in + code#ldc offset (TObject(java_class_path,[TType(WNone,t)])) + | TMethod _ -> + let offset = pool#add_path method_handle_path in + code#ldc offset (TObject(java_class_path,[TType(WNone,method_handle_sig)])) + | TTypeParameter _ -> + let offset = pool#add_path object_path in + code#ldc offset (TObject(java_class_path,[TType(WNone,object_sig)])) + | TArray _ as t -> + (* TODO: this seems hacky *) + let offset = pool#add_path ([],generate_signature false t) in + code#ldc offset (TObject(java_class_path,[TType(WNone,object_sig)])) + | jsig -> + print_endline (generate_signature false jsig); + assert false + + method texpr ret e = + try + if not jm#is_terminated then self#texpr' ret e + with Failure s -> + raise (HarderFailure (Printf.sprintf "Expr %s\n%s" (s_expr_pretty false "" false (s_type (print_context())) e) s)) + + method texpr' ret e = + code#set_line (Lexer.get_error_line e.epos); + match e.eexpr with + | TVar(v,Some e1) -> + self#texpr (rvalue_type v.v_type) e1; + self#cast v.v_type; + let _,_,store = self#add_local v VarWillInit in + store() + | TVar(v,None) -> + ignore(self#add_local v VarNeedDefault); + | TLocal _ | TConst _ | TTypeExpr _ when ret = RVoid -> + () + | TLocal v -> + let _,load,_ = self#get_local v in + load() + | TTypeExpr mt -> + self#type_expr (jsignature_of_type (type_of_module_type mt)) + | TUnop(op,flag,e1) -> + begin match op with + | Not | Neg | NegBits when ret = RVoid -> self#texpr ret e1 + | _ -> self#unop ret op flag e1 + end + | TBinop(OpAdd,e1,e2) when ExtType.is_string (follow e.etype) -> + let string_builder_path = (["java";"lang"],"StringBuilder") in + let string_builder_sig = object_path_sig string_builder_path in + jm#construct ConstructInit string_builder_path (fun () -> []); + let rec loop e = match e.eexpr with + | TBinop(OpAdd,e1,e2) when ExtType.is_string (follow e.etype) -> + loop e1; + loop e2; + | _ -> + self#texpr rvalue_any e; + let jsig = jm#get_code#get_stack#top in + let jsig = match jsig with + | TByte | TBool | TChar | TShort | TInt | TLong -> + jsig + | TFloat | TDouble -> + (* Haxe mandates 2.0 be printed as 2, so we have to wrap here... *) + jm#expect_reference_type; + jm#invokestatic haxe_jvm_path "toString" (method_sig [object_sig] (Some string_sig)); + string_sig + | _ -> + object_sig + in + jm#invokevirtual string_builder_path "append" (method_sig [jsig] (Some string_builder_sig)); + in + loop e1; + loop e2; + jm#invokevirtual string_builder_path "toString" (method_sig [] (Some string_sig)); + | TBinop(op,e1,e2) -> + begin match op with + | OpAssign | OpAssignOp _ -> self#binop ret op e1 e2 + | _ when ret = RVoid -> + self#texpr ret e1; + self#texpr ret e2; + | _ -> + self#binop ret op e1 e2 + end + | TConst ct -> + self#const ret e.etype ct + | TIf(e1,e2,None) -> + jm#if_then + (self#apply_cmp (self#condition e1)) + (fun () -> self#texpr RVoid (mk_block e2)) + | TIf(e1,e2,Some e3) -> + jm#if_then_else + (self#apply_cmp (self#condition e1)) + (fun () -> + self#texpr ret (mk_block e2); + if ret <> RVoid then self#cast e.etype + ) + (fun () -> + self#texpr ret (mk_block e3); + if ret <> RVoid then self#cast e.etype; + ) + | TSwitch(e1,cases,def) -> + self#switch ret e1 cases def + | TWhile(e1,e2,flag) -> (* TODO: do-while *) + (* TODO: could optimize a bit *) + block_exits <- ExitLoop :: block_exits; + let is_true_loop = match (Texpr.skip e1).eexpr with TConst (TBool true) -> true | _ -> false in + jm#add_stack_frame; + let fp = code#get_fp in + let old_continue = continue in + continue <- fp; + let old_breaks = breaks in + breaks <- []; + let restore = jm#start_branch in + let jump_then = if not is_true_loop then self#apply_cmp (self#condition e1) () else ref 0 in + let pop_scope = jm#push_scope in + self#texpr RVoid e2; + if not jm#is_terminated then code#goto (ref (fp - code#get_fp)); + pop_scope(); + restore(); + if not is_true_loop || breaks <> [] then begin + jump_then := code#get_fp - !jump_then; + let fp' = code#get_fp in + List.iter (fun r -> r := fp' - !r) breaks; + jm#add_stack_frame + end else + jm#set_terminated true; + continue <- old_continue; + breaks <- old_breaks; + block_exits <- List.tl block_exits; + | TBreak -> + self#emit_block_exits true; + let r = ref (code#get_fp) in + code#goto r; + breaks <- r :: breaks; + jm#set_terminated true; + | TContinue -> + self#emit_block_exits true; + code#goto (ref (continue - code#get_fp)); + jm#set_terminated true; + | TTry(e1,catches) -> + self#try_catch ret e1 catches + | TField(e1,fa) -> + if ret = RVoid then self#texpr ret e1 + else self#read (fun () -> self#cast_expect ret e.etype) e1 fa; + | TCall(e1,el) -> + self#call ret e.etype e1 el + | TNew({cl_path = (["java"],"NativeArray")},[t],[e1]) -> + self#texpr (match ret with RVoid -> RVoid | _ -> rvalue_any) e1; + (* Technically this could throw... but whatever *) + if ret <> RVoid then ignore(NativeArray.create jm#get_code jc#get_pool (jsignature_of_type t)) + | TNew(c,tl,el) -> + begin match get_constructor (fun cf -> cf.cf_type) c with + |_,cf -> + begin match find_overload_rec true (apply_params c.cl_params tl) c cf el with + | None -> Error.error "Could not find overload" e.epos + | Some (c',cf) -> + let f () = + let tl,_ = self#call_arguments cf.cf_type el in + tl + in + jm#construct ~no_value:(if ret = RVoid then true else false) (get_construction_mode c' cf) c.cl_path f + end + end + | TReturn None -> + self#emit_block_exits false; + code#return_void; + jm#set_terminated true; + | TReturn (Some e1) -> + self#texpr rvalue_any e1; + self#cast return_type; + let vt = self#vtype return_type in + self#emit_block_exits false; + code#return_value vt; + jm#set_terminated true; + | TFunction tf -> + begin match self#tfunction e tf with + | None -> + () + | Some ctx_class -> + begin match ctx_class#get_args with + | [(arg,jsig)] -> + let _,load,_ = self#get_local_by_id arg in + load(); + self#expect_reference_type; + jm#invokevirtual method_handle_path "bindTo" (method_sig [object_sig] (Some method_handle_sig)); + | args -> + let f () = + let tl = List.map (fun (arg,jsig) -> + let _,load,_ = self#get_local_by_id arg in + load(); + jm#cast jsig; + jsig + ) args in + tl + in + jm#construct ConstructInit ctx_class#get_path f; + jm#invokevirtual method_handle_path "bindTo" (method_sig [object_sig] (Some method_handle_sig)); + end + end + | TArrayDecl el when ret = RVoid -> + List.iter (self#texpr ret) el + | TArrayDecl el -> + begin match follow e.etype with + | TInst({cl_path = (["haxe";"root"],"Array")},[t]) -> + self#new_native_array (jsignature_of_type (self#mknull t)) el; + jm#invokestatic (["haxe";"root"],"Array") "ofNative" (method_sig [array_sig object_sig] (Some (object_path_sig (["haxe";"root"],"Array")))); + self#cast e.etype + | _ -> + assert false + end + | TArray(e1,e2) when ret = RVoid -> + (* Array access never throws so this should be fine... *) + self#texpr ret e1; + self#texpr ret e2; + | TArray(e1,e2) -> + begin match follow e1.etype with + | TInst({cl_path = (["haxe";"root"],"Array")} as c,[t]) -> + self#texpr rvalue_any e1; + self#texpr (rvalue_sig TInt) e2; + jm#cast TInt; + jm#invokevirtual c.cl_path "__get" (method_sig [TInt] (Some object_sig)); + self#cast e.etype + | TInst({cl_path = (["java"],"NativeArray")},[t]) -> + self#texpr rvalue_any e1; + let vt = self#vtype e1.etype in + let vte = self#vtype t in + self#texpr rvalue_any e2; + self#read_native_array vt vte + | t -> + self#texpr rvalue_any e1; + self#texpr rvalue_any e2; + jm#cast TInt; + jm#invokestatic (["haxe";"jvm"],"Jvm") "arrayRead" (method_sig [object_sig;TInt] (Some object_sig)); + self#cast e.etype; + end + | TBlock [] -> + if ret = RReturn && not jm#is_terminated then code#return_void; + | TBlock el -> + let rec loop el = match el with + | [] -> assert false + | [e1] -> + self#texpr (if ret = RReturn then RVoid else ret) e1; + if ret = RReturn && not jm#is_terminated then code#return_void; + | e1 :: el -> + self#texpr RVoid e1; + loop el + in + let pop_scope = jm#push_scope in + loop el; + pop_scope(); + | TCast(e1,None) -> + self#texpr ret e1; + if ret <> RVoid then self#cast e.etype + | TCast(e1,Some mt) -> + self#texpr rvalue_any e1; + let jsig = jsignature_of_type (type_of_module_type mt) in + if is_unboxed jsig || is_unboxed jm#get_code#get_stack#top then jm#cast jsig + else code#checkcast (t_infos mt).mt_path; + if ret = RVoid then code#pop; + | TParenthesis e1 | TMeta(_,e1) -> + self#texpr ret e1 + | TFor(v,e1,e2) -> + self#texpr ret (Texpr.for_remap com.basic v e1 e2 e.epos) + | TEnumIndex e1 -> + self#texpr rvalue_any e1; + jm#invokevirtual java_enum_path "ordinal" (method_sig [] (Some TInt)) + | TEnumParameter(e1,ef,i) -> + self#texpr rvalue_any e1; + let path,name,jsig_arg = match follow ef.ef_type with + | TFun(tl,TEnum(en,_)) -> + let n,_,t = List.nth tl i in + en.e_path,n,self#vtype t + | _ -> assert false + in + let cpath = ((fst path),Printf.sprintf "%s$%s" (snd path) ef.ef_name) in + let jsig = (object_path_sig cpath) in + jm#cast jsig; + jm#getfield cpath name jsig_arg; + self#cast e.etype; + | TThrow e1 -> + self#texpr rvalue_any e1; + let exc = new haxe_exception gctx e1.etype in + if not (List.exists (fun exc' -> exc#is_assignable_to exc') caught_exceptions) then jm#add_thrown_exception exc#get_native_exception_path; + if not exc#is_native_exception then begin + let vt = self#vtype (self#mknull e1.etype) in + self#throw vt + end else begin + code#athrow; + jm#set_terminated true + end + | TObjectDecl fl -> + begin match follow e.etype with + (* The guard is here because in the case of quoted fields like `"a-b"`, the field is not part of the + type. In this case we have to do full dynamic construction. *) + | TAnon an when List.for_all (fun ((name,_,_),_) -> PMap.mem name an.a_fields) fl -> + let path,fl' = TAnonIdentifiaction.identify gctx an.a_fields in + jm#construct ConstructInit path (fun () -> + (* We have to respect declaration order, so let's temp var where necessary *) + let rec loop fl fl' ok acc = match fl,fl' with + | ((name,_,_),e) :: fl,(name',jsig) :: fl' -> + if ok && name = name' then begin + self#texpr rvalue_any e; + jm#cast jsig; + loop fl fl' ok acc + end else begin + let load = match (Texpr.skip e).eexpr with + | TConst _ | TTypeExpr _ | TFunction _ -> + (fun () -> self#texpr rvalue_any e) + | _ -> + let _,load,save = jm#add_local (Printf.sprintf "_hx_tmp_%s" name) (self#vtype e.etype) VarWillInit in + self#texpr rvalue_any e; + save(); + load + in + loop fl fl' false ((name,load) :: acc) + end + | [],[] -> + acc + | (_,e) :: fl,[] -> + self#texpr RVoid e; + loop fl fl' ok acc + | [],(_,jsig) :: fl' -> + jm#load_default_value jsig; + loop [] fl' ok acc + in + let vars = loop fl fl' true [] in + let vars = List.sort (fun (name1,_) (name2,_) -> compare name1 name2) vars in + List.iter (fun (_,load) -> + load(); + ) vars; + List.map snd fl'; + ) + | _ -> + jm#construct ConstructInit haxe_dynamic_object_path (fun () -> []); + List.iter (fun ((name,_,_),e) -> + code#dup; + jm#string name; + self#texpr rvalue_any e; + self#expect_reference_type; + jm#invokevirtual haxe_dynamic_object_path "_hx_setField" (method_sig [string_sig;object_sig] None); + ) fl; + end + | TIdent _ -> + Error.error (s_expr_ast false "" (s_type (print_context())) e) e.epos; + + (* api *) + + method object_constructor = + let path = jc#get_super_path in + let offset = pool#add_field path "" (method_sig [] None) FKMethod in + jm#load_this; + code#invokespecial offset jc#get_jsig [] []; + jm#set_this_initialized +end + +type super_ctor_mode = + | SCNone + | SCJava + | SCHaxe + +let failsafe p f = + try + f () + with Failure s | HarderFailure s -> + Error.error s p + +let generate_dynamic_access gctx (jc : JvmClass.builder) fields is_anon = + begin match fields with + | [] -> + () + | _ -> + let jsig = method_sig [string_sig] (Some object_sig) in + let jm = jc#spawn_method "_hx_getField" jsig [MPublic;MSynthetic] in + let _,load,_ = jm#add_local "name" string_sig VarArgument in + jm#finalize_arguments; + load(); + jm#invokevirtual string_path "hashCode" (method_sig [] (Some TInt)); + let cases = List.map (fun (name,jsig,kind) -> + let hash = java_hash name in + [hash],(fun () -> + begin match kind with + | Method (MethNormal | MethInline) -> + jm#read_closure false jc#get_this_path name jsig; + jm#load_this; + jm#invokevirtual method_handle_path "bindTo" (method_sig [object_sig] (Some method_handle_sig)); + | _ -> + jm#load_this; + jm#getfield jc#get_this_path name jsig; + jm#expect_reference_type; + end; + ignore(jm#get_code#get_stack#pop); + jm#get_code#get_stack#push object_sig; + ) + ) fields in + let def = (fun () -> + jm#load_this; + load(); + jm#invokespecial jc#get_super_path "_hx_getField" jsig; + ) in + ignore(jm#int_switch false cases (Some def)); + jm#return + end; + let fields = List.filter (fun (_,_,kind) -> match kind with + | Method (MethNormal | MethInline) -> false + | Var {v_write = AccNever} -> false + | _ -> true + ) fields in + begin match fields with + | [] -> + () + | _ -> + let jsig = method_sig [string_sig;object_sig] None in + let jm = jc#spawn_method "_hx_setField" jsig [MPublic;MSynthetic] in + let _,load1,_ = jm#add_local "name" string_sig VarArgument in + let _,load2,_ = jm#add_local "value" object_sig VarArgument in + jm#finalize_arguments; + load1(); + jm#invokevirtual string_path "hashCode" (method_sig [] (Some TInt)); + let def = (fun () -> + jm#load_this; + load1(); + load2(); + jm#invokespecial jc#get_super_path "_hx_setField" jsig; + ) in + let cases = List.map (fun (name,jsig,_) -> + let hash = java_hash name in + [hash],(fun () -> + jm#load_this; + load2(); + jm#cast jsig; + jm#putfield jc#get_this_path name jsig; + (* Have to deal with Reflect.deleteField crap here... *) + if is_anon then begin + jm#load_this; + jm#getfield jc#get_this_path "_hx_deletedAField" boolean_sig; + jm#if_then + (fun () -> jm#get_code#if_null_ref boolean_sig) + (fun () -> + def(); + ) + end; + ) + ) fields in + ignore(jm#int_switch false cases (Some def)); + jm#return + end + +class tclass_to_jvm gctx c = object(self) + val is_annotation = Meta.has Meta.Annotation c.cl_meta + val field_inits = DynArray.create () + val delayed_field_inits = DynArray.create () + + val jc = new JvmClass.builder c.cl_path (match c.cl_super with + | Some(c,_) -> c.cl_path + | None -> + if c.cl_interface || Meta.has Meta.NativeGen c.cl_meta then object_path else haxe_object_path + ) + + method private set_access_flags = + jc#add_access_flag 1; (* public *) + if c.cl_final then jc#add_access_flag 0x10; + if c.cl_interface then begin + jc#add_access_flag 0x200; + jc#add_access_flag 0x400; + end; + if is_annotation then begin + jc#add_access_flag 0x2000; + jc#add_interface (["java";"lang";"annotation"],"Annotation"); + (* TODO: this should be done via Haxe metadata instead of hardcoding it here *) + jc#add_annotation retention_path ["value",(AEnum(retention_policy_sig,"RUNTIME"))]; + end; + if c.cl_path = (["haxe";"jvm"],"Enum") then jc#add_access_flag 0x4000; (* enum *) + + method private handle_relation_type_params = + let map_type_params t = + let has_type_param = ref false in + let rec loop t = match follow t with + | TInst({cl_kind = KTypeParameter tl},_) -> + has_type_param := true; + begin match tl with + | [t] -> t + | _ -> t_dynamic + end + | _ -> Type.map loop t + in + let t = match follow t with + | TFun(tl,tr) -> + let tl = List.map (fun (n,o,t) -> n,o,loop t) tl in + let tr = loop tr in + TFun(tl,tr) + | _ -> + assert false + in + if !has_type_param then Some t else None + in + let make_bridge cf_impl t = + let jsig = jsignature_of_type t in + if not (jc#has_method cf_impl.cf_name jsig) then begin + begin match follow t with + | TFun(tl,tr) -> + let jm = jc#spawn_method cf_impl.cf_name jsig [MPublic;MSynthetic;MBridge] in + jm#load_this; + let jsig_impl = jsignature_of_type cf_impl.cf_type in + let jsigs,_ = match jsig_impl with TMethod(jsigs,jsig) -> jsigs,jsig | _ -> assert false in + List.iter2 (fun (n,_,t) jsig -> + let _,load,_ = jm#add_local n (jsignature_of_type t) VarArgument in + load(); + jm#cast jsig; + ) tl jsigs; + jm#invokevirtual c.cl_path cf_impl.cf_name jsig_impl; + if not (ExtType.is_void (follow tr)) then jm#cast (jsignature_of_type tr); + jm#return; + | _ -> + () + end + end + in + let check is_interface cf cf_impl = + match map_type_params cf.cf_type with + | Some t -> + make_bridge cf_impl t + | None -> + (* If we implement an interface with variance, we need a bridge method too (#8528). *) + if is_interface && not (type_iseq cf.cf_type cf_impl.cf_type) then make_bridge cf_impl cf.cf_type + in + let check is_interface cf cf_impl = + check is_interface cf cf_impl; + (* TODO: I think this is incorrect... have to investigate though *) + (* List.iter (fun cf -> check is_interface cf cf_impl) cf.cf_overloads *) + in + let rec loop map_type c_int = + List.iter (fun (c_int,tl) -> + let map_type t = apply_params c_int.cl_params tl (map_type t) in + List.iter (fun cf -> + match cf.cf_kind,raw_class_field (fun cf -> map_type cf.cf_type) c (List.map snd c.cl_params) cf.cf_name with + | (Method (MethNormal | MethInline)),(Some(c',_),_,cf_impl) when c' == c -> + let tl = match follow (map_type cf.cf_type) with + | TFun(tl,_) -> tl + | _ -> assert false + in + begin match find_overload_rec' false map_type c cf.cf_name (List.map (fun (_,_,t) -> Texpr.Builder.make_null t null_pos) tl) with + | Some(_,cf_impl) -> check true cf cf_impl + | None -> () + end; + | _ -> + () + ) c_int.cl_ordered_fields; + loop map_type c_int + ) c_int.cl_implements + in + loop (fun t -> t) c; + begin match c.cl_overrides,c.cl_super with + | [],_ -> + () + | fields,Some(c_sup,tl) -> + List.iter (fun cf_impl -> + match cf_impl.cf_kind,raw_class_field (fun cf -> apply_params c_sup.cl_params tl cf.cf_type) c_sup tl cf_impl.cf_name with + | (Method (MethNormal | MethInline)),(Some(c,tl),_,cf) -> check false cf cf_impl + | _ -> () + ) fields + | _ -> + assert false + end + + method private set_interfaces = + List.iter (fun (c_int,tl) -> + if is_annotation && c_int.cl_path = (["java";"lang";"annotation"],"Annotation") then + () + else begin + jc#add_interface c_int.cl_path + end + ) c.cl_implements + + method private generate_empty_ctor = + let jsig_empty = method_sig [haxe_empty_constructor_sig] None in + let jm_empty_ctor = jc#spawn_method "" jsig_empty [MPublic] in + let _,load,_ = jm_empty_ctor#add_local "_" haxe_empty_constructor_sig VarArgument in + jm_empty_ctor#load_this; + if c.cl_constructor = None then begin + let handler = new texpr_to_jvm gctx jc jm_empty_ctor gctx.com.basic.tvoid in + DynArray.iter (fun e -> + handler#texpr RVoid e; + ) field_inits; + end; + begin match c.cl_super with + | None -> + (* Haxe type with no parent class, call Object.() *) + jm_empty_ctor#call_super_ctor ConstructInit (method_sig [] None) + | _ -> + (* Parent class exists, call SuperClass.(EmptyConstructor) *) + load(); + jm_empty_ctor#call_super_ctor ConstructInit jsig_empty + end; + if c.cl_constructor = None then begin + let handler = new texpr_to_jvm gctx jc jm_empty_ctor gctx.com.basic.tvoid in + DynArray.iter (fun e -> + handler#texpr RVoid e; + ) delayed_field_inits; + end; + jm_empty_ctor#get_code#return_void; + + method private generate_implicit_ctors = + try + let sm = Hashtbl.find gctx.implicit_ctors c.cl_path in + PMap.iter (fun _ (c,cf) -> + let cmode = get_construction_mode c cf in + let jm = jc#spawn_method (if cmode = ConstructInit then "" else "new") (jsignature_of_type cf.cf_type) [MPublic] in + let handler = new texpr_to_jvm gctx jc jm gctx.com.basic.tvoid in + jm#load_this; + DynArray.iter (fun e -> + handler#texpr RVoid e; + ) field_inits; + let tl = match follow cf.cf_type with TFun(tl,_) -> tl | _ -> assert false in + List.iter (fun (n,_,t) -> + let _,load,_ = jm#add_local n (jsignature_of_type t) VarArgument in + load(); + ) tl; + jm#call_super_ctor cmode jm#get_jsig; + DynArray.iter (fun e -> + handler#texpr RVoid e; + ) delayed_field_inits; + jm#return + ) sm + with Not_found -> + () + + method generate_expr gctx jc jm e is_method scmode mtype = + let e,args,tr = match e.eexpr with + | TFunction tf when is_method -> + tf.tf_expr,tf.tf_args,tf.tf_type + | _ -> + e,[],t_dynamic + in + let handler = new texpr_to_jvm gctx jc jm tr in + List.iter (fun (v,_) -> + ignore(handler#add_local v VarArgument); + ) args; + jm#finalize_arguments; + begin match mtype with + | MConstructor -> + DynArray.iter (fun e -> + handler#texpr RVoid e; + ) field_inits; + begin match scmode with + | SCJava -> + handler#object_constructor + | SCHaxe -> + jm#load_this; + jm#get_code#aconst_null jc#get_jsig; + jm#call_super_ctor ConstructInit (method_sig [haxe_empty_constructor_sig] None); + | SCNone -> + () + end; + DynArray.iter (fun e -> + handler#texpr RVoid e; + ) delayed_field_inits; + | _ -> + () + end; + handler#texpr RReturn e + + method generate_method gctx jc c mtype cf = + gctx.current_field_info <- get_field_info gctx cf.cf_meta; + let jsig = jsignature_of_type cf.cf_type in + let flags = [MPublic] in + let flags = if c.cl_interface then MAbstract :: flags else flags in + let flags = if mtype = MStatic then MethodAccessFlags.MStatic :: flags else flags in + let flags = if has_class_field_flag cf CfFinal then MFinal :: flags else flags in + let name,scmode,flags = match mtype with + | MConstructor -> + let rec has_super_ctor c = match c.cl_super with + | None -> false + | Some(c,_) -> c.cl_constructor <> None || has_super_ctor c + in + let get_scmode () = if c.cl_super = None then SCJava else if not (has_super_ctor c) then SCHaxe else SCNone in + if get_construction_mode c cf = ConstructInit then "",get_scmode(),flags + else cf.cf_name,SCNone,flags + | _ -> cf.cf_name,SCNone,flags + in + let jm = jc#spawn_method name jsig flags in + begin match cf.cf_expr with + | None -> () + | Some e -> + self#generate_expr gctx jc jm e true scmode mtype; + end; + begin match cf.cf_params with + | [] when c.cl_params = [] -> + () + | _ -> + let stl = String.concat "" (List.map (fun (n,_) -> + Printf.sprintf "%s:Ljava/lang/Object;" n + ) cf.cf_params) in + let ssig = generate_method_signature true (jsignature_of_type cf.cf_type) in + let s = if cf.cf_params = [] then ssig else Printf.sprintf "<%s>%s" stl ssig in + let offset = jc#get_pool#add_string s in + jm#add_attribute (AttributeSignature offset); + end; + AnnotationHandler.generate_annotations (jm :> JvmBuilder.base_builder) cf.cf_meta; + + method generate_field gctx (jc : JvmClass.builder) c mtype cf = + let jsig = jsignature_of_type cf.cf_type in + let flags = [FdPublic] in + let flags = if mtype = MStatic then FdStatic :: flags else flags in + let jm = jc#spawn_field cf.cf_name jsig flags in + let default e = + let p = null_pos in + let efield = Texpr.Builder.make_static_field c cf p in + let eop = mk (TBinop(OpAssign,efield,e)) cf.cf_type p in + begin match c.cl_init with + | None -> c.cl_init <- Some eop + | Some e -> c.cl_init <- Some (concat e eop) + end + in + begin match cf.cf_expr with + | None -> + if c.cl_path = (["haxe"],"Resource") && cf.cf_name = "content" then begin + let el = Hashtbl.fold (fun name _ acc -> + Texpr.Builder.make_string gctx.com.basic name null_pos :: acc + ) gctx.com.resources [] in + let e = mk (TArrayDecl el) (gctx.com.basic.tarray gctx.com.basic.tstring) null_pos in + default e; + end; + | Some e when mtype <> MStatic -> + let tl = List.map snd c.cl_params in + let ethis = mk (TConst TThis) (TInst(c,tl)) null_pos in + let efield = mk (TField(ethis,FInstance(c,tl,cf))) cf.cf_type null_pos in + let eop = mk (TBinop(OpAssign,efield,e)) cf.cf_type null_pos in + DynArray.add (match cf.cf_kind with Method MethDynamic -> delayed_field_inits | _ -> field_inits) eop; + | Some e -> + match e.eexpr with + | TConst ct -> + begin match ct with + | TInt i32 when not (is_nullable cf.cf_type) -> + let offset = jc#get_pool#add (ConstInt i32) in + jm#add_attribute (AttributeConstantValue offset); + | TString s -> + let offset = jc#get_pool#add_const_string s in + jm#add_attribute (AttributeConstantValue offset); + | _ -> + default e; + end + | _ -> + default e; + end; + let ssig = generate_signature true (jsignature_of_type cf.cf_type) in + let offset = jc#get_pool#add_string ssig in + jm#add_attribute (AttributeSignature offset) + + method generate_main = + let jsig = method_sig [array_sig string_sig] None in + let jm = jc#spawn_method "main" jsig [MPublic;MStatic] in + let _,load,_ = jm#add_local "args" (TArray(string_sig,None)) VarArgument in + if has_feature gctx.com "haxe.root.Sys.args" then begin + load(); + jm#putstatic (["haxe";"root"],"Sys") "_args" (TArray(string_sig,None)) + end; + jm#invokestatic (["haxe"; "java"], "Init") "init" (method_sig [] None); + jm#invokestatic jc#get_this_path "main" (method_sig [] None); + jm#return + + method private generate_fields = + let field mtype cf = match cf.cf_kind with + | Method (MethNormal | MethInline) -> + List.iter (fun cf -> + failsafe cf.cf_pos (fun () -> self#generate_method gctx jc c mtype cf); + if cf.cf_name = "main" then self#generate_main; + ) (cf :: List.filter (fun cf -> Meta.has Meta.Overload cf.cf_meta) cf.cf_overloads) + | _ -> + if not c.cl_interface && is_physical_field cf then failsafe cf.cf_pos (fun () -> self#generate_field gctx jc c mtype cf) + in + List.iter (field MStatic) c.cl_ordered_statics; + List.iter (field MInstance) c.cl_ordered_fields; + begin match c.cl_constructor,c.cl_super with + | Some cf,Some _ -> field MConstructor cf + | Some cf,None -> field MConstructor cf + | None,_ -> () + end; + begin match c.cl_init with + | None -> + () + | Some e -> + let cf = mk_field "" (tfun [] gctx.com.basic.tvoid) null_pos null_pos in + cf.cf_kind <- Method MethNormal; + let tf = { + tf_args = []; + tf_type = gctx.com.basic.tvoid; + tf_expr = mk_block e; + } in + let e = mk (TFunction tf) cf.cf_type null_pos in + cf.cf_expr <- Some e; + field MStatic cf + end + + method private generate_signature = + let stl = match c.cl_params with + | [] -> "" + | params -> + let stl = String.concat "" (List.map (fun (n,_) -> + Printf.sprintf "%s:Ljava/lang/Object;" n + ) c.cl_params) in + Printf.sprintf "<%s>" stl + in + let ssuper = match c.cl_super with + | Some(c,tl) -> generate_method_signature true (jsignature_of_type (TInst(c,tl))) + | None -> generate_method_signature true object_sig + in + let sinterfaces = String.concat "" (List.map (fun(c,tl) -> + generate_method_signature true (jsignature_of_type (TInst(c,tl))) + ) c.cl_implements) in + let s = Printf.sprintf "%s%s%s" stl ssuper sinterfaces in + let offset = jc#get_pool#add_string s in + jc#add_attribute (AttributeSignature offset) + + method generate_annotations = + AnnotationHandler.generate_annotations (jc :> JvmBuilder.base_builder) c.cl_meta; + jc#add_annotation (["haxe";"jvm";"annotation"],"ClassReflectionInformation") (["hasSuperClass",(ABool (c.cl_super <> None))]) + + method generate = + self#set_access_flags; + self#generate_fields; + self#set_interfaces; + if not c.cl_interface then begin + self#generate_empty_ctor; + self#generate_implicit_ctors; + self#handle_relation_type_params; + end; + self#generate_signature; + if not (Meta.has Meta.NativeGen c.cl_meta) then + generate_dynamic_access gctx jc (List.map (fun cf -> cf.cf_name,jsignature_of_type cf.cf_type,cf.cf_kind) c.cl_ordered_fields) false; + self#generate_annotations; + jc#add_attribute (AttributeSourceFile (jc#get_pool#add_string c.cl_pos.pfile)); + let jc = jc#export_class gctx.default_export_config in + write_class gctx.jar c.cl_path jc +end + +let generate_class gctx c = + let conv = new tclass_to_jvm gctx c in + conv#generate + +let generate_enum gctx en = + let jc_enum = new JvmClass.builder en.e_path haxe_enum_path in + jc_enum#add_access_flag 0x1; (* public *) + jc_enum#add_access_flag 0x400; (* abstract *) + jc_enum#add_access_flag 0x4000; (* enum *) + begin + let jsig = haxe_enum_sig (object_path_sig en.e_path) in + let s = generate_signature true jsig in + let offset = jc_enum#get_pool#add_string s in + jc_enum#add_attribute (AttributeSignature offset) + end; + let jsig_enum_ctor = method_sig [TInt;string_sig] None in + (* Create base constructor *) + begin + let jm_ctor = jc_enum#spawn_method "" jsig_enum_ctor [MProtected] in + jm_ctor#load_this; + let _,load1,_ = jm_ctor#add_local "index" TInt VarArgument in + let _,load2,_ = jm_ctor#add_local "name" string_sig VarArgument in + load1(); + load2(); + jm_ctor#call_super_ctor ConstructInit jsig_enum_ctor; + jm_ctor#get_code#return_void; + end; + let inits = DynArray.create () in + let names = List.map (fun name -> + let ef = PMap.find name en.e_constrs in + let args = match follow ef.ef_type with + | TFun(tl,_) -> List.map (fun (n,_,t) -> n,jsignature_of_type t) tl + | _ -> [] + in + let jsigs = List.map snd args in + (* Create class for constructor *) + let jc_ctor = begin + let jc_ctor = jc_enum#spawn_inner_class None jc_enum#get_this_path (Some ef.ef_name) in + jc_ctor#add_access_flag 0x10; (* final *) + jc_ctor#add_access_flag 0x4000; (* enum *) + let jsig_method = method_sig jsigs None in + let jm_ctor = jc_ctor#spawn_method "" jsig_method [MPublic] in + jm_ctor#load_this; + jm_ctor#get_code#iconst (Int32.of_int ef.ef_index); + jm_ctor#string ef.ef_name; + jm_ctor#call_super_ctor ConstructInit jsig_enum_ctor; + List.iter (fun (n,jsig) -> + jm_ctor#add_argument_and_field n jsig + ) args; + jm_ctor#get_code#return_void; + jc_ctor#add_annotation (["haxe";"jvm";"annotation"],"EnumValueReflectionInformation") (["argumentNames",AArray (List.map (fun (name,_) -> AString name) args)]); + if args <> [] then begin + let jm_params = jc_ctor#spawn_method "_hx_getParameters" (method_sig [] (Some (array_sig object_sig))) [MPublic] in + let fl = List.map (fun (n,jsig) -> + (fun () -> + jm_params#load_this; + jm_params#getfield jc_ctor#get_this_path n jsig; + jm_params#cast object_sig; + ) + ) args in + jm_params#new_native_array object_sig fl; + jm_params#return + end; + jc_ctor + end in + write_class gctx.jar jc_ctor#get_this_path (jc_ctor#export_class gctx.default_export_config); + begin match args with + | [] -> + (* Create static field for ctor without args *) + let jm_static = jc_enum#spawn_field ef.ef_name jc_enum#get_jsig [FdPublic;FdStatic;FdFinal;FdEnum] in + DynArray.add inits (jm_static,jc_ctor); + | _ -> + (* Create static function for ctor with args *) + let jsig_static = method_sig jsigs (Some jc_enum#get_jsig) in + let jm_static = jc_enum#spawn_method ef.ef_name jsig_static [MPublic;MStatic] in + jm_static#construct ConstructInit jc_ctor#get_this_path (fun () -> + List.iter (fun (n,jsig) -> + let _,load,_ = jm_static#add_local n jsig VarArgument in + load(); + ) args; + jsigs; + ); + jm_static#get_code#return_value jc_enum#get_jsig; + end; + AString name + ) en.e_names in + if DynArray.length inits > 0 then begin + (* Assign static fields for ctors without args *) + let jm_clinit = jc_enum#spawn_method "" (method_sig [] None) [MStatic] in + let jm_values = jc_enum#spawn_method "values" (method_sig [] (Some (array_sig (object_path_sig jc_enum#get_this_path)))) [MPublic;MStatic] in + let inits = DynArray.to_list inits in + let fl = List.map (fun (jm_static,jc_ctor) -> + jm_clinit#construct ConstructInit jc_ctor#get_this_path (fun () -> []); + jm_clinit#putstatic jc_enum#get_this_path jm_static#get_name jm_static#get_jsig; + (fun () -> + jm_values#getstatic jc_enum#get_this_path jm_static#get_name jm_static#get_jsig; + ) + ) inits in + jm_values#new_native_array (object_path_sig jc_enum#get_this_path) fl; + jm_values#return; + (* Add __meta__ TODO: do this via annotations instead? *) + begin match Texpr.build_metadata gctx.com.basic (TEnumDecl en) with + | None -> + () + | Some e -> + ignore(jc_enum#spawn_field "__meta__" object_sig [FdStatic;FdPublic]); + let handler = new texpr_to_jvm gctx jc_enum jm_clinit (gctx.com.basic.tvoid) in + handler#texpr rvalue_any e; + jm_clinit#putstatic jc_enum#get_this_path "__meta__" object_sig + end; + jm_clinit#get_code#return_void; + end; + AnnotationHandler.generate_annotations (jc_enum :> JvmBuilder.base_builder) en.e_meta; + jc_enum#add_annotation (["haxe";"jvm";"annotation"],"EnumReflectionInformation") (["constructorNames",AArray names]); + write_class gctx.jar en.e_path (jc_enum#export_class gctx.default_export_config) + +let generate_abstract gctx a = + let super_path = object_path in + let jc = new JvmClass.builder a.a_path super_path in + jc#add_access_flag 1; (* public *) + let jc = jc#export_class gctx.default_export_config in + write_class gctx.jar a.a_path jc + +let debug_path path = match path with + (* | ([],"Main") | (["haxe";"jvm"],_) -> true *) + | (["haxe";"lang"],_) -> false (* Old Haxe/Java stuff that's weird *) + | _ -> true + +let is_extern_abstract a = match a.a_impl with + | Some {cl_extern = true} -> true + | _ -> false + +let generate_module_type ctx mt = + failsafe (t_infos mt).mt_pos (fun () -> + match mt with + | TClassDecl c when not c.cl_extern && debug_path c.cl_path -> generate_class ctx c + | TEnumDecl en when not en.e_extern -> generate_enum ctx en + | TAbstractDecl a when not (is_extern_abstract a) && Meta.has Meta.CoreType a.a_meta -> generate_abstract ctx a + | _ -> () + ) + +module Preprocessor = struct + + let is_normal_anon an = match !(an.a_status) with + | Closed | Const | Opened -> true + | _ -> false + + let check_anon gctx e = match e.etype,follow e.etype with + | TType(td,_),TAnon an when is_normal_anon an -> + ignore(TAnonIdentifiaction.identify_as gctx td.t_path an.a_fields) + | _ -> + () + + let add_implicit_ctor gctx c c' cf = + let jsig = jsignature_of_type cf.cf_type in + try + let sm = Hashtbl.find gctx.implicit_ctors c.cl_path in + Hashtbl.replace gctx.implicit_ctors c.cl_path (PMap.add (c'.cl_path,jsig) (c',cf) sm); + with Not_found -> + Hashtbl.add gctx.implicit_ctors c.cl_path (PMap.add (c'.cl_path,jsig) (c',cf) PMap.empty) + + let make_native cf = + cf.cf_meta <- (Meta.NativeGen,[],null_pos) :: cf.cf_meta + + let make_haxe cf = + cf.cf_meta <- (Meta.HxGen,[],null_pos) :: cf.cf_meta + + let preprocess_constructor_expr gctx c cf e = + let used_this = ref false in + let this_before_super = ref false in + let super_call_fields = DynArray.create () in + let is_on_current_class cf = PMap.mem cf.cf_name c.cl_fields in + let find_super_ctor el = + let csup,map_type = match c.cl_super with + | Some(c,tl) -> c,apply_params c.cl_params tl + | _ -> assert false + in + match find_overload_rec' true map_type csup "new" el with + | Some(c,cf) -> + let rec loop csup = + if c != csup then begin + match csup.cl_super with + | Some(c',_) -> + add_implicit_ctor gctx csup c' cf; + loop c' + | None -> assert false + end + in + loop csup; + (c,cf) + | None -> Error.error "Could not find overload constructor" e.epos + in + let rec promote_this_before_super c cf = match get_field_info gctx cf.cf_meta with + | None -> jerror "Something went wrong" + | Some info -> + if not info.has_this_before_super then begin + make_haxe cf; + (* print_endline (Printf.sprintf "promoted this_before_super to %s.new : %s" (s_type_path c.cl_path) (s_type (print_context()) cf.cf_type)); *) + info.has_this_before_super <- true; + List.iter (fun (c,cf) -> promote_this_before_super c cf) info.super_call_fields + end + in + let rec loop e = + check_anon gctx e; + begin match e.eexpr with + | TBinop(OpAssign,{eexpr = TField({eexpr = TConst TThis},FInstance(_,_,cf))},e2) when is_on_current_class cf-> + (* Assigning this.field = value is fine if field is declared on our current class *) + loop e2; + | TConst TThis -> + used_this := true + | TCall({eexpr = TConst TSuper},el) -> + List.iter loop el; + if !used_this then begin + this_before_super := true; + make_haxe cf; + (* print_endline (Printf.sprintf "inferred this_before_super on %s.new : %s" (s_type_path c.cl_path) (s_type (print_context()) cf.cf_type)); *) + end; + let c,cf = find_super_ctor el in + if !this_before_super then promote_this_before_super c cf; + DynArray.add super_call_fields (c,cf); + | _ -> + Type.iter loop e + end; + in + loop e; + { + has_this_before_super = !this_before_super; + super_call_fields = DynArray.to_list super_call_fields; + } + + let preprocess_expr gctx e = + let rec loop e = + check_anon gctx e; + Type.iter loop e + in + loop e + + let check_overrides c = match c.cl_overrides with + | []-> + () + | fields -> + let csup,map_type = match c.cl_super with + | Some(c,tl) -> c,apply_params c.cl_params tl + | None -> assert false + in + let fix_covariant_return cf = + let tl = match follow cf.cf_type with + | TFun(tl,_) -> tl + | _ -> assert false + in + match find_overload_rec' false map_type csup cf.cf_name (List.map (fun (_,_,t) -> Texpr.Builder.make_null t null_pos) tl) with + | Some(_,cf') -> + let tr = match follow cf'.cf_type with + | TFun(_,tr) -> tr + | _ -> assert false + in + cf.cf_type <- TFun(tl,tr); + cf.cf_expr <- begin match cf.cf_expr with + | Some ({eexpr = TFunction tf} as e) -> + Some {e with eexpr = TFunction {tf with tf_type = tr}} + | e -> + e + end; + | None -> + () + (* TODO: this should never happen if we get the unification right *) + (* Error.error "Could not find overload" cf.cf_pos *) + in + List.iter (fun cf -> + fix_covariant_return cf; + List.iter fix_covariant_return cf.cf_overloads + ) fields + + let rec get_constructor c = + match c.cl_constructor, c.cl_super with + | Some cf, _ -> c,cf + | None, None -> raise Not_found + | None, Some (csup,cparams) -> get_constructor csup + + let preprocess_class gctx c = + let field cf = match cf.cf_expr with + | None -> + () + | Some e -> + preprocess_expr gctx e + in + let has_dynamic_instance_method = ref false in + let has_field_init = ref false in + let field mtype cf = + List.iter field (cf :: cf.cf_overloads); + match mtype with + | MConstructor -> + () + | MInstance -> + begin match cf.cf_kind with + | Method MethDynamic -> has_dynamic_instance_method := true + | Var _ when cf.cf_expr <> None && not !has_field_init && c.cl_constructor = None && c.cl_super = None -> + has_field_init := true; + add_implicit_ctor gctx c c (mk_field "new" (tfun [] gctx.com.basic.tvoid) null_pos null_pos) + | _ -> () + end; + | MStatic -> + () + in + check_overrides c; + List.iter (field MStatic) c.cl_ordered_statics; + List.iter (field MInstance) c.cl_ordered_fields; + match c.cl_constructor with + | None -> + begin try + let csup,cf = get_constructor c in + List.iter (fun cf -> add_implicit_ctor gctx c csup cf) (cf :: cf.cf_overloads) + with Not_found -> + () + end; + | Some cf -> + let field cf = + if !has_dynamic_instance_method then make_haxe cf; + begin match cf.cf_expr with + | None -> + () + | Some e -> + let info = preprocess_constructor_expr gctx c cf e in + let index = DynArray.length gctx.field_infos in + DynArray.add gctx.field_infos info; + cf.cf_meta <- (Meta.Custom ":jvm.fieldInfo",[(EConst (Int (string_of_int index)),null_pos)],null_pos) :: cf.cf_meta; + if not (Meta.has Meta.HxGen cf.cf_meta) then begin + let rec loop next c = + if c.cl_extern then make_native cf + else match c.cl_constructor with + | Some cf' when Meta.has Meta.HxGen cf'.cf_meta -> make_haxe cf + | Some cf' when Meta.has Meta.NativeGen cf'.cf_meta -> make_native cf + | _ -> next c + in + let rec up c = match c.cl_super with + | None -> () + | Some(c,_) -> loop up c + in + let rec down c = List.iter (fun c -> loop down c) c.cl_descendants in + loop up c; + loop down c + end; + end + in + List.iter field (cf :: cf.cf_overloads) + + let make_root path = + ["haxe";"root"],snd path + + let preprocess gctx = + List.iter (fun mt -> + match mt with + | TClassDecl c -> + if fst c.cl_path = [] then c.cl_path <- make_root c.cl_path; + if debug_path c.cl_path && not c.cl_interface then preprocess_class gctx c + | TEnumDecl en -> + if fst en.e_path = [] then en.e_path <- make_root en.e_path; + | _ -> () + ) gctx.com.types +end + +let file_name_and_extension file = + match List.rev (ExtString.String.nsplit file "/") with + | e1 :: _ -> e1 + | _ -> assert false + +let generate com = + mkdir_from_path com.file; + let jar_name,manifest_suffix = match com.main_class with + | Some path -> + let pack = match fst path with + | [] -> ["haxe";"root"] + | pack -> pack + in + let name = snd path in + name,"\nMain-Class: " ^ (s_type_path (pack,name)) + | None -> "jar","" + in + let jar_name = if com.debug then jar_name ^ "-Debug" else jar_name in + let jar_dir = add_trailing_slash com.file in + let jar_path = Printf.sprintf "%s%s.jar" jar_dir jar_name in + let gctx = { + com = com; + jar = Zip.open_out jar_path; + t_exception = TInst(resolve_class com (["java";"lang"],"Exception"),[]); + t_throwable = TInst(resolve_class com (["java";"lang"],"Throwable"),[]); + anon_lut = Hashtbl.create 0; + anon_path_lut = Hashtbl.create 0; + anon_num = 0; + implicit_ctors = Hashtbl.create 0; + field_infos = DynArray.create(); + current_field_info = None; + default_export_config = { + export_debug = com.debug; + } + } in + Std.finally (Timer.timer ["generate";"java";"preprocess"]) Preprocessor.preprocess gctx; + let class_paths = ExtList.List.filter_map (fun java_lib -> + if java_lib#has_flag NativeLibraries.FlagIsStd then None + else begin + let dir = Printf.sprintf "%slib/" jar_dir in + Path.mkdir_from_path dir; + let name = file_name_and_extension java_lib#get_file_path in + let ch_in = open_in_bin java_lib#get_file_path in + let ch_out = open_out_bin (Printf.sprintf "%s%s" dir name) in + let b = IO.read_all (IO.input_channel ch_in) in + output_string ch_out b; + close_in ch_in; + close_out ch_out; + Some (Printf.sprintf "lib/%s" name) + end + ) com.native_libs.java_libs in + let manifest_content = + "Manifest-Version: 1.0\n" ^ + (match class_paths with [] -> "" | _ -> "Class-Path: " ^ (String.concat " " class_paths ^ "\n")) ^ + "Created-By: Haxe (Haxe Foundation)" ^ + manifest_suffix ^ + "\n\n" + in + Zip.add_entry manifest_content gctx.jar "META-INF/MANIFEST.MF"; + Hashtbl.iter (fun name v -> + let filename = Codegen.escape_res_name name true in + Zip.add_entry v gctx.jar filename; + ) com.resources; + List.iter (generate_module_type gctx) com.types; + Hashtbl.iter (fun fields path -> + let jc = new JvmClass.builder path haxe_dynamic_object_path in + jc#add_access_flag 0x1; + begin + let jm_ctor = jc#spawn_method "" (method_sig (List.map snd fields) None) [MPublic] in + jm_ctor#load_this; + jm_ctor#get_code#aconst_null haxe_empty_constructor_sig; + jm_ctor#call_super_ctor ConstructInit (method_sig [haxe_empty_constructor_sig] None); + List.iter (fun (name,jsig) -> + jm_ctor#add_argument_and_field name jsig; + ) fields; + jm_ctor#get_code#return_void; + end; + begin + let string_map_path = (["haxe";"ds"],"StringMap") in + let string_map_sig = object_path_sig string_map_path in + let jm_fields = jc#spawn_method "_hx_getKnownFields" (method_sig [] (Some string_map_sig)) [MProtected] in + let _,load,save = jm_fields#add_local "tmp" string_map_sig VarWillInit in + jm_fields#construct ConstructInit string_map_path (fun () -> []); + save(); + List.iter (fun (name,jsig) -> + load(); + let offset = jc#get_pool#add_const_string name in + jm_fields#get_code#sconst (string_sig) offset; + jm_fields#load_this; + jm_fields#getfield jc#get_this_path name jsig; + jm_fields#expect_reference_type; + jm_fields#invokevirtual string_map_path "set" (method_sig [string_sig;object_sig] None); + ) fields; + load(); + jm_fields#get_code#return_value string_map_sig + end; + generate_dynamic_access gctx jc (List.map (fun (name,jsig) -> name,jsig,Var {v_write = AccNormal;v_read = AccNormal}) fields) true; + write_class gctx.jar path (jc#export_class gctx.default_export_config) + ) gctx.anon_lut; + Zip.close_out gctx.jar \ No newline at end of file diff --git a/src/generators/genlua.ml b/src/generators/genlua.ml index 2e974fdfefd..a5a947b3a73 100644 --- a/src/generators/genlua.ml +++ b/src/generators/genlua.ml @@ -47,6 +47,7 @@ type ctx = { mutable separator : bool; mutable found_expose : bool; mutable lua_jit : bool; + mutable lua_vanilla : bool; mutable lua_ver : float; } @@ -83,7 +84,7 @@ let dot_path = Globals.s_type_path let s_path ctx = flat_path (* Lua requires decimal encoding for characters, rather than the hex *) -(* provided by Ast.s_escape *) +(* provided by StringHelper.s_escape *) let s_escape_lua ?(dec=true) s = let b = Buffer.create (String.length s) in for i = 0 to (String.length s) - 1 do @@ -189,8 +190,8 @@ let rec concat ctx s f = function let fun_block ctx f p = let e = List.fold_left (fun e (a,c) -> match c with - | None | Some TNull -> e - | Some c -> Type.concat (Codegen.set_default ctx.com a c p) e + | None | Some {eexpr = TConst TNull} -> e + | Some c -> Type.concat (Texpr.set_default ctx.com.basic a c p) e ) f.tf_expr f.tf_args in e @@ -208,23 +209,6 @@ let is_dot_access e cf = | _ -> false -let is_dynamic_iterator ctx e = - let check x = - has_feature ctx "HxOverrides.iter" && (match follow x.etype with - | TInst ({ cl_path = [],"Array" },_) - | TInst ({ cl_kind = KTypeParameter _}, _) - | TAnon _ - | TDynamic _ - | TMono _ -> - true - | _ -> false - ) - in - match e.eexpr with - | TField (x,f) when field_name f = "iterator" -> check x - | _ -> - false - (* return index of a first element in the list for which `f` returns true TODO: is there some standard function to do that? @@ -244,7 +228,7 @@ let index_of f l = (* create a __lua__ call *) let mk_lua_code com code args t pos = let lua_local = mk (TIdent "__lua__") t_dynamic pos in - let code_const = Codegen.ExprBuilder.make_string com code pos in + let code_const = Texpr.Builder.make_string com code pos in mk (TCall (lua_local, code_const :: args)) t pos (* create a multi-return boxing call for given expr *) @@ -258,7 +242,7 @@ let mk_mr_box ctx e = add_feature ctx "use._hx_box_mr"; add_feature ctx "use._hx_table"; let code = Printf.sprintf "_hx_box_mr(_hx_table.pack({0}), {%s})" s_fields in - mk_lua_code ctx.com code [e] e.etype e.epos + mk_lua_code ctx.com.basic code [e] e.etype e.epos (* create a multi-return select call for given expr and field name *) let mk_mr_select com e ecall name = @@ -338,7 +322,44 @@ let gen_constant ctx p = function | TThis -> spr ctx (this ctx) | TSuper -> assert false -let rec gen_call ctx e el = + + +let rec is_function_type t = + match follow(t) with + | TFun _ -> true + | TAbstract({a_path=["haxe"],"Function" },_) -> true + | _ -> false + +and gen_argument ?(reflect=false) ctx e = begin + match e.eexpr with + | TField (x,((FInstance (_,_,f)| FAnon(f) | FClosure(_,f)))) when (is_function_type e.etype) -> + ( + if reflect then ( + add_feature ctx "use._hx_funcToField"; + spr ctx "_hx_funcToField("; + ); + + add_feature ctx "use._hx_bind"; + print ctx "_hx_bind("; + gen_value ctx x; + print ctx ","; + gen_value ctx x; + print ctx "%s)" (if Meta.has Meta.SelfCall f.cf_meta then "" else (field f.cf_name)); + + if reflect then + print ctx ")"; + ); + | _ -> + gen_value ctx e; +end + +and gen_paren_arguments ctx el = begin + spr ctx "("; + concat ctx ", " (gen_argument ctx) el; + spr ctx ")"; +end + +and gen_call ctx e el = ctx.iife_assign <- true; (match e.eexpr , el with | TConst TSuper , params -> @@ -346,7 +367,7 @@ let rec gen_call ctx e el = | None -> error "Missing api.setCurrentClass" e.epos | Some (c,_) -> print ctx "%s.super(%s" (ctx.type_accessor (TClassDecl c)) (this ctx); - List.iter (fun p -> print ctx ","; gen_value ctx p) params; + List.iter (fun p -> print ctx ","; gen_argument ctx p) params; spr ctx ")"; ); | TField ({ eexpr = TConst TSuper },f) , params -> @@ -355,34 +376,41 @@ let rec gen_call ctx e el = | Some (c,_) -> let name = field_name f in print ctx "%s.prototype%s(%s" (ctx.type_accessor (TClassDecl c)) (field name) (this ctx); - List.iter (fun p -> print ctx ","; gen_value ctx p) params; + List.iter (fun p -> print ctx ","; gen_argument ctx p) params; spr ctx ")"; ); + | TField (_, FStatic( { cl_path = ([],"Reflect") }, { cf_name = "callMethod" })), (obj :: fld :: args :: rest) -> + gen_expr ctx e; + spr ctx "("; + gen_argument ctx obj; + spr ctx ","; + gen_argument ~reflect:true ctx fld; + spr ctx ","; + gen_argument ctx args; + spr ctx ")"; | TCall (x,_) , el when (match x.eexpr with TIdent "__lua__" -> false | _ -> true) -> gen_paren ctx [e]; - gen_paren ctx el; + gen_paren_arguments ctx el; | TIdent "__new__", { eexpr = TConst (TString cl) } :: params -> - print ctx "%s.new(" cl; - concat ctx "," (gen_value ctx) params; - spr ctx ")"; + print ctx "%s.new" cl; + gen_paren_arguments ctx params; | TIdent "__new__", e :: params -> gen_value ctx e; - spr ctx ".new("; - concat ctx "," (gen_value ctx) params; - spr ctx ")"; + spr ctx ".new"; + gen_paren_arguments ctx params; | TIdent "__callself__", { eexpr = TConst (TString head) } :: { eexpr = TConst (TString tail) } :: el -> print ctx "%s:%s" head tail; - gen_paren ctx el; + gen_paren_arguments ctx el; | TIdent "__call__", { eexpr = TConst (TString code) } :: el -> spr ctx code; - gen_paren ctx el; + gen_paren_arguments ctx el; | TIdent "__lua_length__", [e]-> spr ctx "#"; gen_value ctx e; | TIdent "__lua_table__", el -> let count = ref 0 in spr ctx "({"; List.iter (fun e -> - (match e with + (match Texpr.skip e with | { eexpr = TArrayDecl arr } -> if (!count > 0 && List.length(arr) > 0) then spr ctx ","; concat ctx "," (gen_value ctx) arr; @@ -458,29 +486,40 @@ let rec gen_call ctx e el = gen_value ctx e; print ctx ",'%s'" (field_name ef); spr ctx ")("; - concat ctx "," (gen_value ctx) (e::el); + concat ctx "," (gen_argument ctx) (e::el); spr ctx ")"; - | TField (e, ((FInstance _ | FAnon _ | FDynamic _) as ef)), el -> + | TField (field_owner, ((FInstance _ | FAnon _ | FDynamic _) as ef)), el -> let s = (field_name ef) in if Hashtbl.mem kwds s || not (valid_lua_ident s) then begin add_feature ctx "use._hx_apply_self"; spr ctx "_hx_apply_self("; - gen_value ctx e; + gen_value ctx field_owner; print ctx ",\"%s\"" (field_name ef); if List.length(el) > 0 then spr ctx ","; - concat ctx "," (gen_value ctx) el; + concat ctx "," (gen_argument ctx) el; spr ctx ")"; end else begin - gen_value ctx e; - if is_dot_access e ef then - print ctx ".%s" (field_name ef) - else - print ctx ":%s" (field_name ef); - gen_paren ctx el; + let el = + if (match ef with FAnon _ | FDynamic _ -> true | _ -> false) && is_possible_string_field field_owner s then + begin + gen_expr ctx e; + field_owner :: el + end + else + begin + gen_value ctx field_owner; + if is_dot_access field_owner ef then + print ctx ".%s" (field_name ef) + else + print ctx ":%s" (field_name ef); + el + end + in + gen_paren_arguments ctx el; end; | _ -> gen_value ctx e; - gen_paren ctx el); + gen_paren_arguments ctx el); ctx.iife_assign <- false; and has_continue e = @@ -563,6 +602,23 @@ and is_possible_string_field e field_name= false +and ttype_multireturn t = match t with + | TInst (c,_) -> + Meta.has Meta.MultiReturn c.cl_meta + | TType (c,_) -> + Meta.has Meta.MultiReturn c.t_meta + | _ -> + false +and check_multireturn_param ctx t pos = + match t with + TAbstract(_,p) | TInst(_,p) -> + if List.exists ttype_multireturn p then + error "MultiReturns must not be type parameters" pos + else + () + | _ -> + (); + and gen_expr ?(local=true) ctx e = begin match e.eexpr with TConst c -> @@ -580,11 +636,6 @@ and gen_expr ?(local=true) ctx e = begin spr ctx "]"; | TBinop (op,e1,e2) -> gen_tbinop ctx op e1 e2; - | TField (x,f) when field_name f = "iterator" && is_dynamic_iterator ctx e -> - add_feature ctx "use._iterator"; - print ctx "_iterator("; - gen_value ctx x; - print ctx ")"; | TField (x,FClosure (_,f)) -> add_feature ctx "use._hx_bind"; (match x.eexpr with @@ -604,9 +655,15 @@ and gen_expr ?(local=true) ctx e = begin | TEnumIndex x -> gen_value ctx x; print ctx "[1]" - | TField (e, ef) when is_string_expr e && field_name ef = "length"-> - spr ctx "#"; - gen_value ctx e; + | TField (e, ef) when is_string_expr e && field_name ef = "length" -> + if ctx.lua_vanilla then ( + spr ctx "#"; + gen_value ctx e; + ) else ( + spr ctx "__lua_lib_luautf8_Utf8.len("; + gen_value ctx e; + spr ctx ")"; + ) | TField (e, ef) when is_possible_string_field e (field_name ef) -> add_feature ctx "use._hx_wrap_if_string_field"; add_feature ctx "use.string"; @@ -740,7 +797,13 @@ and gen_expr ?(local=true) ctx e = begin (* we have to box it in an object conforming to a multi-return extern class *) let is_boxed_multireturn = Meta.has (Meta.Custom ":lua_mr_box") v.v_meta in let e = if is_boxed_multireturn then mk_mr_box ctx e else e in - gen_value ctx e; + (match e.eexpr with + | TCast ({ eexpr = TTypeExpr mt } as e1, None) when (match mt with TClassDecl {cl_path = ([],"Array")} -> false | _ -> true) -> + add_feature ctx "use._hx_staticToInstance"; + spr ctx "_hx_staticToInstance("; + gen_expr ctx e1; + spr ctx ")"; + | _ -> gen_value ctx e); end | TNew (c,_,el) -> (match c.cl_constructor with @@ -992,7 +1055,13 @@ and gen_block_element ctx e = begin match e.eexpr with | TTypeExpr _ | TConst _ | TLocal _ | TFunction _ -> () - | TCast (e',_) | TParenthesis e' | TMeta (_,e') -> + | TCast (e1, Some t)-> + print ctx "%s.__cast(" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["lua"],"Boot" })); + gen_expr ctx e1; + spr ctx " , "; + spr ctx (ctx.type_accessor t); + spr ctx ")" + | TCast (e', None) | TParenthesis e' | TMeta (_,e') -> gen_block_element ctx e' | TArray (e1,e2) -> gen_block_element ctx e1; @@ -1071,7 +1140,7 @@ and gen_anon_value ctx e = ctx.in_value <- fst old; ctx.in_loop <- snd old; ctx.separator <- true - | _ when (is_function_type ctx e.etype) && not (is_const_null e) -> + | _ when (is_function_type e.etype) && not (is_const_null e) -> spr ctx "function(_,...) return "; gen_value ctx e; spr ctx "(...) end"; @@ -1088,7 +1157,7 @@ and gen_value ctx e = let value() = let old = ctx.in_value, ctx.in_loop in let r_id = temp ctx in - let r = alloc_var r_id t_dynamic e.epos in + let r = alloc_var VGenerated r_id t_dynamic e.epos in ctx.in_value <- Some r; ctx.in_loop <- false; spr ctx "(function() "; @@ -1136,13 +1205,6 @@ and gen_value ctx e = | TBreak | TContinue -> unsupported e.epos - (* TODO: this is just a hack because this specific case is a TestReflect unit test. I don't know how to address this properly - at the moment. - Simon *) - | TCast ({ eexpr = TTypeExpr mt } as e1, None) when (match mt with TClassDecl {cl_path = ([],"Array")} -> false | _ -> true) -> - add_feature ctx "use._hx_staticToInstance"; - spr ctx "_hx_staticToInstance("; - gen_expr ctx e1; - spr ctx ")"; | TCast (e1, Some t) -> print ctx "%s.__cast(" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["lua"],"Boot" })); gen_value ctx e1; @@ -1215,11 +1277,6 @@ and gen_value ctx e = )) e.etype e.epos); v() -and is_function_type ctx t = - match follow(t) with - | TFun _ -> true - | _ -> false; - and gen_tbinop ctx op e1 e2 = (match op, e1.eexpr, e2.eexpr with | Ast.OpAssign, TField(e3, FInstance _), TFunction f -> @@ -1264,13 +1321,20 @@ and gen_tbinop ctx op e1 e2 = spr ctx "_hx_funcToField("; gen_value ctx e2; spr ctx ")"; - | TField(_, FInstance _ ), TLocal t when (is_function_type ctx t.v_type) -> + | TField(_, FInstance _ ), TLocal t when (is_function_type t.v_type) -> gen_value ctx e1; print ctx " %s " (Ast.s_binop op); add_feature ctx "use._hx_funcToField"; spr ctx "_hx_funcToField("; gen_value ctx e2; spr ctx ")"; + | _, TCast ({ eexpr = TTypeExpr mt } as e1, None) when (match mt with TClassDecl {cl_path = ([],"Array")} -> false | _ -> true) -> + add_feature ctx "use._hx_staticToInstance"; + gen_value ctx e1; + print ctx " %s " (Ast.s_binop op); + spr ctx "_hx_staticToInstance("; + gen_expr ctx e2; + spr ctx ")"; | _ -> gen_value ctx e1; print ctx " %s " (Ast.s_binop op); @@ -1283,10 +1347,10 @@ and gen_tbinop ctx op e1 e2 = | Ast.OpAssignOp(op2), TArray(e3,e4), _ -> (* TODO: Figure out how to rewrite this expression more cleanly *) println ctx "(function() "; - let idx = alloc_var "idx" e4.etype e4.epos in + let idx = alloc_var VGenerated "idx" e4.etype e4.epos in let idx_var = mk (TVar( idx , Some(e4))) e4.etype e4.epos in gen_expr ctx idx_var; - let arr = alloc_var "arr" e3.etype e3.epos in + let arr = alloc_var VGenerated "arr" e3.etype e3.epos in let arr_var = mk (TVar(arr, Some(e3))) e3.etype e3.epos in gen_expr ctx arr_var; newline ctx; @@ -1301,7 +1365,7 @@ and gen_tbinop ctx op e1 e2 = | Ast.OpAssignOp(op2), TField(e3,e4), _ -> (* TODO: Figure out how to rewrite this expression more cleanly *) println ctx "(function() "; - let obj = alloc_var "obj" e3.etype e3.epos in + let obj = alloc_var VGenerated "obj" e3.etype e3.epos in spr ctx "local fld = "; (match e4 with | FInstance(_,_,fld) @@ -1394,7 +1458,7 @@ and gen_return ctx e eo = spr ctx "do return end" | Some e -> (match e.eexpr with - | TField (e2, ((FClosure (_, tcf) | FAnon tcf |FInstance (_,_,tcf)))) when is_function_type ctx tcf.cf_type -> + | TField (e2, ((FClosure (_, tcf) | FAnon tcf |FInstance (_,_,tcf)))) when (is_function_type tcf.cf_type) -> (* See issue #6259 *) add_feature ctx "use._hx_bind"; spr ctx "do return "; @@ -1529,7 +1593,7 @@ let generate_class___name__ ctx c = let p = s_path ctx c.cl_path in print ctx "%s.__name__ = " p; if has_feature ctx "Type.getClassName" then - println ctx "{%s}" (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" (s_escape_lua s)) (fst c.cl_path @ [snd c.cl_path]))) + println ctx "\"%s\"" (String.concat "." (List.map s_escape_lua (fst c.cl_path @ [snd c.cl_path]))) else println ctx "true"; end @@ -1584,7 +1648,7 @@ let generate_class ctx c = ); newline ctx; - (match (get_exposed ctx (s_path ctx c.cl_path) c.cl_meta) with [s] -> (print ctx "_hx_exports%s = %s" (path_to_brackets s) p; newline ctx) | _ -> ()); + (match (get_exposed ctx (dot_path c.cl_path) c.cl_meta) with [s] -> (print ctx "_hx_exports%s = %s" (path_to_brackets s) p; newline ctx) | _ -> ()); if hxClasses then println ctx "_hxClasses[\"%s\"] = %s" (dot_path c.cl_path) p; generate_class___name__ ctx c; @@ -1640,7 +1704,7 @@ let generate_class ctx c = let generate_enum ctx e = let p = s_path ctx e.e_path in - let ename = List.map (fun s -> Printf.sprintf "\"%s\"" (s_escape_lua s)) (fst e.e_path @ [snd e.e_path]) in + let ename = List.map s_escape_lua (fst e.e_path @ [snd e.e_path]) in (* TODO: Unify the _hxClasses declaration *) if has_feature ctx "Type.resolveEnum" then begin @@ -1649,7 +1713,7 @@ let generate_enum ctx e = if has_feature ctx "lua.Boot.isEnum" then begin print ctx "_hxClasses[\"%s\"] = {" (dot_path e.e_path); if has_feature ctx "lua.Boot.isEnum" then begin - print ctx " __ename__ = %s," (if has_feature ctx "Type.getEnumName" then "{" ^ String.concat "," ename ^ "}" else "true"); + print ctx " __ename__ = %s," (if has_feature ctx "Type.getEnumName" then "\"" ^ String.concat "." ename ^ "\"" else "true"); end; (* TODO : Come up with a helper function for _hx_tab_array declarations *) spr ctx " __constructs__ = _hx_tab_array({"; @@ -1713,7 +1777,7 @@ let generate_static ctx (c,f,e) = let generate_enumMeta_fields ctx = function | TEnumDecl e -> begin let p = s_path ctx e.e_path in - match Codegen.build_metadata ctx.com (TEnumDecl e) with + match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with | None -> () | Some e -> print ctx "%s.__meta__ = " p; @@ -1797,6 +1861,7 @@ let alloc_ctx com = separator = false; found_expose = false; lua_jit = Common.defined com Define.LuaJit; + lua_vanilla = Common.defined com Define.LuaVanilla; lua_ver = try float_of_string (PMap.find "lua_ver" com.defines.Define.values) with | Not_found -> 5.2; @@ -1815,19 +1880,20 @@ let alloc_ctx com = let transform_multireturn ctx = function | TClassDecl c -> let transform_field f = + check_multireturn_param ctx f.cf_type f.cf_pos; match f.cf_expr with | Some e -> + let is_multireturn t = + match follow t with + | TInst (c, _) when Meta.has Meta.MultiReturn c.cl_meta -> true + | _ -> false + in let rec loop e = - let is_multireturn t = - match follow t with - | TInst (c, _) when Meta.has Meta.MultiReturn c.cl_meta -> true - | _ -> false - in match e.eexpr with - (* - if we found a var declaration initialized by a multi-return call, mark it with @:multiReturn meta, - so it will later be generated as multiple locals unpacking the value - *) + (* + if we found a var declaration initialized by a multi-return call, mark it with @:multiReturn meta, + so it will later be generated as multiple locals unpacking the value + *) | TVar (v, Some ({ eexpr = TCall _ } as ecall)) when is_multireturn v.v_type -> v.v_meta <- (Meta.MultiReturn,[],v.v_pos) :: v.v_meta; let ecall = Type.map_expr loop ecall in @@ -1836,7 +1902,7 @@ let transform_multireturn ctx = function (* if we found a field access for the multi-return call, generate select call *) | TField ({ eexpr = TCall _ } as ecall, f) when is_multireturn ecall.etype -> let ecall = Type.map_expr loop ecall in - mk_mr_select ctx.com e ecall (field_name f) + mk_mr_select ctx.com.basic e ecall (field_name f) (* if we found a multi-return call used as a value, box it *) | TCall _ when is_multireturn e.etype -> @@ -1889,13 +1955,24 @@ let generate com = if has_feature ctx "Class" || has_feature ctx "Type.getClassName" then add_feature ctx "lua.Boot.isClass"; if has_feature ctx "Enum" || has_feature ctx "Type.getEnumName" then add_feature ctx "lua.Boot.isEnum"; + let print_file path = + let file_content = Std.input_file ~bin:true path in + print ctx "%s\n" file_content; + in + + (* table-to-array helper *) + print_file (Common.find_file com "lua/_lua/_hx_tab_array.lua"); + + (* lua workarounds for basic anonymous object functionality *) + print_file (Common.find_file com "lua/_lua/_hx_anon.lua"); + + (* class reflection metadata *) + print_file (Common.find_file com "lua/_lua/_hx_classes.lua"); + let include_files = List.rev com.include_files in List.iter (fun file -> match file with - | path, "top" -> - let file_content = Std.input_file ~bin:true (fst file) in - print ctx "%s\n" file_content; - () + | path, "top" -> print_file path | _ -> () ) include_files; @@ -1979,27 +2056,8 @@ let generate com = List.iter (generate_type ctx) com.types; if has_feature ctx "use._bitop" || has_feature ctx "lua.Boot.clamp" then begin - println ctx "_hx_bit_clamp = function(v) "; - println ctx " if v <= 2147483647 and v >= -2147483648 then"; - println ctx " if v > 0 then return _G.math.floor(v)"; - println ctx " else return _G.math.ceil(v)"; - println ctx " end"; - println ctx " end"; - println ctx " if v > 2251798999999999 then v = v*2 end;"; - println ctx " if (v ~= v or math.abs(v) == _G.math.huge) then return nil end"; - println ctx " return _hx_bit.band(v, 2147483647 ) - math.abs(_hx_bit.band(v, 2147483648))"; - println ctx "end"; - println ctx "pcall(require, 'bit')"; (* require this for lua 5.1 *) - println ctx "if bit then"; - println ctx " _hx_bit = bit"; - println ctx "elseif bit32 then"; - println ctx " local _hx_bit_raw = bit32"; - println ctx " _hx_bit = setmetatable({}, { __index = _hx_bit_raw });"; - println ctx " _hx_bit.bnot = function(...) return _hx_bit_clamp(_hx_bit_raw.bnot(...)) end;"; (* lua 5.2 weirdness *) - println ctx " _hx_bit.bxor = function(...) return _hx_bit_clamp(_hx_bit_raw.bxor(...)) end;"; (* lua 5.2 weirdness *) - println ctx "else"; - println ctx " _G.error(\"Bitop library is missing. Please install luabitop\");"; - println ctx "end"; + print_file (Common.find_file com "lua/_lua/_hx_bit_clamp.lua"); + print_file (Common.find_file com "lua/_lua/_hx_bit.lua"); end; (* Array is required, always patch it *) @@ -2012,123 +2070,50 @@ let generate com = List.iter (generate_static ctx) (List.rev ctx.statics); (* Localize init variables inside a do-block *) (* Note: __init__ logic can modify static variables. *) - (* Generate statics *) + (* Generate static inits *) List.iter (gen_block_element ctx) (List.rev ctx.inits); b(); newline ctx; println ctx "end"; newline ctx; - if has_feature ctx "use._iterator" then begin - add_feature ctx "use._hx_bind"; - println ctx "function _hx_iterator(o) if ( lua.Boot.__instanceof(o, Array) ) then return function() return HxOverrides.iter(o) end elseif (typeof(o.iterator) == 'function') then return _hx_bind(o,o.iterator) else return o.iterator end end"; - end; - if has_feature ctx "use._hx_bind" then begin - println ctx "_hx_bind = function(o,m)"; - println ctx " if m == nil then return nil end;"; - println ctx " local f;"; - println ctx " if o._hx__closures == nil then"; - println ctx " _G.rawset(o, '_hx__closures', {});"; - println ctx " else "; - println ctx " f = o._hx__closures[m];"; - println ctx " end"; - println ctx " if (f == nil) then"; - println ctx " f = function(...) return m(o, ...) end;"; - println ctx " o._hx__closures[m] = f;"; - println ctx " end"; - println ctx " return f;"; - println ctx "end"; + print_file (Common.find_file com "lua/_lua/_hx_bind.lua"); end; if has_feature ctx "use._hx_staticToInstance" then begin - println ctx "_hx_staticToInstance = function (tab)"; - println ctx " return setmetatable({}, {"; - println ctx " __index = function(t,k)"; - println ctx " if type(rawget(tab,k)) == 'function' then "; - println ctx " return function(self,...)"; - println ctx " return rawget(tab,k)(...)"; - println ctx " end"; - println ctx " else"; - println ctx " return rawget(tab,k)"; - println ctx " end"; - println ctx " end"; - println ctx " })"; - println ctx "end"; + print_file (Common.find_file com "lua/_lua/_hx_static_to_instance.lua"); end; if has_feature ctx "use._hx_funcToField" then begin - println ctx "_hx_funcToField = function(f)"; - println ctx " if type(f) == 'function' then "; - println ctx " return function(self,...) "; - println ctx " return f(...) "; - println ctx " end"; - println ctx " else "; - println ctx " return f"; - println ctx " end"; - println ctx "end"; + print_file (Common.find_file com "lua/_lua/_hx_func_to_field.lua"); end; if has_feature ctx "Math.random" then begin - println ctx "_G.math.randomseed(_G.os.time());" + print_file (Common.find_file com "lua/_lua/_hx_random_init.lua"); end; if has_feature ctx "use._hx_print" then - println ctx "_hx_print = print or (function() end)"; + print_file (Common.find_file com "lua/_lua/_hx_print.lua"); if has_feature ctx "use._hx_apply_self" then begin - println ctx "_hx_apply_self = function(self, f, ...)"; - println ctx " return self[f](self,...)"; - println ctx "end"; + print_file (Common.find_file com "lua/_lua/_hx_apply_self.lua"); end; if has_feature ctx "use._hx_box_mr" then begin - println ctx "_hx_box_mr = function(x,nt)"; - println ctx " res = _hx_o({__fields__={}})"; - println ctx " for i,v in ipairs(nt) do"; - println ctx " res[v] = x[i]"; - println ctx " end"; - println ctx " return res"; - println ctx "end"; + print_file (Common.find_file com "lua/_lua/_hx_box_mr.lua"); end; if has_feature ctx "use._hx_table" then begin - println ctx "_hx_table = {}"; - println ctx "_hx_table.pack = _G.table.pack or function(...)"; - println ctx " return {...}"; - println ctx "end"; - println ctx "_hx_table.unpack = _G.table.unpack or _G.unpack"; - println ctx "_hx_table.maxn = _G.table.maxn or function(t)"; - println ctx " local maxn=0;"; - println ctx " for i in pairs(t) do"; - println ctx " maxn=type(i)=='number'and i>maxn and i or maxn"; - println ctx " end"; - println ctx " return maxn"; - println ctx "end;"; + print_file (Common.find_file com "lua/_lua/_hx_table.lua"); end; if has_feature ctx "use._hx_wrap_if_string_field" then begin - println ctx "_hx_wrap_if_string_field = function(o, fld)"; - println ctx " if _G.type(o) == 'string' then"; - println ctx " if fld == 'length' then"; - println ctx " return _G.string.len(o)"; - println ctx " else"; - println ctx " return String.prototype[fld]"; - println ctx " end"; - println ctx " else"; - println ctx " return o[fld]"; - println ctx " end"; - println ctx "end"; + print_file (Common.find_file com "lua/_lua/_hx_wrap_if_string_field.lua"); end; if has_feature ctx "use._hx_dyn_add" then begin - println ctx "_hx_dyn_add = function(a,b)"; - println ctx " if (_G.type(a) == 'string' or _G.type(b) == 'string') then "; - println ctx " return Std.string(a)..Std.string(b)"; - println ctx " else "; - println ctx " return a + b;"; - println ctx " end;"; - println ctx "end;"; + print_file (Common.find_file com "lua/_lua/_hx_dyn_add.lua"); end; println ctx "_hx_static_init();"; diff --git a/src/generators/genneko.ml b/src/generators/genneko.ml index 665a43103ce..713e2cbf9b3 100644 --- a/src/generators/genneko.ml +++ b/src/generators/genneko.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -295,8 +295,8 @@ and gen_expr ctx e = acc in match c with - | None | Some TNull -> acc - | Some c -> gen_expr ctx (Codegen.set_default ctx.com a c e.epos) :: acc + | None | Some {eexpr = TConst TNull} -> acc + | Some c -> gen_expr ctx (Texpr.set_default ctx.com.basic a c e.epos) :: acc ) [] f.tf_args in let e = gen_expr ctx f.tf_expr in let e = (match inits with [] -> e | _ -> EBlock (List.rev (e :: inits)),p) in @@ -630,7 +630,7 @@ let gen_name ctx acc t = let setname = (EBinop ("=",field p path "__ename__",arr),p) in let arr = call p (field p (ident p "Array") "new1") [array p (List.map (fun n -> gen_constant ctx e.e_pos (TString n)) e.e_names); int p (List.length e.e_names)] in let setconstrs = (EBinop ("=", field p path "__constructs__", arr),p) in - let meta = (match Codegen.build_metadata ctx.com (TEnumDecl e) with + let meta = (match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with | None -> [] | Some e -> [EBinop ("=",field p path "__meta__", gen_expr ctx e),p] ) in @@ -794,7 +794,7 @@ let generate com = let use_nekoc = Common.defined com Define.UseNekoc in if not use_nekoc then begin try - mkdir_from_path com.file; + Path.mkdir_from_path com.file; let ch = IO.output_channel (open_out_bin com.file) in Nbytecode.write ch (Ncompile.compile ctx.version e); IO.close_out ch; diff --git a/src/generators/genphp7.ml b/src/generators/genphp7.ml index 8e4ac560135..cae0cb7701f 100644 --- a/src/generators/genphp7.ml +++ b/src/generators/genphp7.ml @@ -9,12 +9,6 @@ open Meta open Globals open Sourcemaps -let debug = ref false -(** - Do not add comments with Haxe positions before each line of generated php code -*) -let skip_line_directives = ref false - (** Escape string for constant strings generation. Copy-pasted from genphp. @@ -46,6 +40,41 @@ let write_resource dir name data = output_string ch data; close_out ch +(** + Copy file from `src` to `dst`. + If `dst` exists it will be overwritten. +*) +let copy_file src dst = + let buffer_size = 8192 in + let buffer = String.create buffer_size in + let fd_in = Unix.openfile src [O_RDONLY] 0 in + let fd_out = Unix.openfile dst [O_WRONLY; O_CREAT; O_TRUNC] 0o644 in + let rec copy_loop () = + match Unix.read fd_in buffer 0 buffer_size with + | 0 -> () + | r -> ignore (Unix.write fd_out buffer 0 r); copy_loop () + in + copy_loop (); + Unix.close fd_in; + Unix.close fd_out + +type used_type = { + ut_alias : string; + ut_type_path : (string list * string) +} + +type php_generator_context = { + pgc_common : Common.context; + (** Do not add comments with Haxe positions before each line of generated php code *) + pgc_skip_line_directives : bool; + (** The value of `-D php-prefix=value` split by dots *) + pgc_prefix : string list; + (** php.Boot *) + pgc_boot : tclass; + (** see type_name_used_in_namespace *) + pgc_namespaces_types_cache : (string list, string) Hashtbl.t +} + (** Get list of keys in Hashtbl *) @@ -123,26 +152,31 @@ let bool_type_path = ([], "Bool") let std_type_path = ([], "Std") (** - Stub to use when you need a `Ast.pos` instance, but don't have one + The name of a file with polyfills for some functions which are not available in PHP 7.0 *) -let dummy_pos = { pfile = ""; pmin = 0; pmax = 0 } +let polyfills_file = "_polyfills.php" + +let php_keywords_list = + ["__halt_compiler"; "abstract"; "and"; "array"; "as"; "break"; "callable"; "case"; "catch"; "class"; + "clone"; "const"; "continue"; "declare"; "default"; "die"; "do"; "echo"; "else"; "elseif"; "empty"; + "enddeclare"; "endfor"; "endforeach"; "endif"; "endswitch"; "endwhile"; "eval"; "exit"; "extends"; "final"; + "finally"; "for"; "foreach"; "function"; "global"; "goto"; "if"; "implements"; "include"; "include_once"; + "instanceof"; "insteadof"; "interface"; "isset"; "list"; "namespace"; "new"; "or"; "print"; "private"; + "protected"; "public"; "require"; "require_once"; "return"; "static"; "switch"; "throw"; "trait"; "try"; + "unset"; "use"; "var"; "while"; "xor"; "yield"; "__class__"; "__dir__"; "__file__"; "__function__"; "__line__"; + "__method__"; "__trait__"; "__namespace__"; "int"; "float"; "bool"; "string"; "true"; "false"; "null"; "parent"; + "void"; "iterable"; "object"; "fn"] + +let php_keywords_tbl = begin + let tbl = Hashtbl.create 100 in + List.iter (fun kwd -> Hashtbl.add tbl kwd ()) php_keywords_list; + tbl +end (** Check if specified string is a reserved word in PHP *) -let is_keyword str = - match String.lowercase str with - | "__halt_compiler" | "abstract" | "and" | "array" | "as" | "break" | "callable" | "case" | "catch" | "class" - | "clone" | "const" | "continue" | "declare" | "default" | "die" | "do" | "echo" | "else" | "elseif" | "empty" - | "enddeclare" | "endfor" | "endforeach" | "endif" | "endswitch" | "endwhile" | "eval" | "exit" | "extends" - | "final" | "finally" | "for" | "foreach" | "function" | "global" | "goto" | "if" | "implements" | "include" - | "include_once" | "instanceof" | "insteadof" | "interface" | "isset" | "list" | "namespace" | "new" | "or" - | "print" | "private" | "protected" | "public" | "require" | "require_once" | "return" | "static" | "switch" - | "throw" | "trait" | "try" | "unset" | "use" | "var" | "while" | "xor" | "yield" | "__class__" | "__dir__" - | "__file__" | "__function__" | "__line__" | "__method__" | "__trait__" | "__namespace__" | "int" | "float" - | "bool" | "string" | "true" | "false" | "null" | "parent" | "void" | "iterable" - -> true - | _ -> false +let is_keyword str = Hashtbl.mem php_keywords_tbl (String.lowercase str) (** Check if specified type is Void @@ -175,34 +209,14 @@ let get_real_path path = List.map get_real_name path *) let rec follow = Abstract.follow_with_abstracts -let prefix = ref None (** - Returns value of `--php-prefix` compiler flag -*) -let get_php_prefix ctx = - match !prefix with - | Some prefix -> prefix - | None -> - let lst = - match Common.defined_value_safe ctx Define.PhpPrefix with - | "" -> [] - | str -> - if String.length str = 0 then - [] - else - Str.split (Str.regexp "\\.") str - in - prefix := Some lst; - lst - -(** - Adds packages specified by `--php-prefix` to `type_path`. - E.g. if `--php-prefix some.sub` and `type_path` is `(["pack"], "MyClass")`, then this function + Adds packages specified by `-D php-prefix` to `type_path`. + E.g. if `-D php-prefix=some.sub` and `type_path` is `(["pack"], "MyClass")`, then this function will return `(["some", "sub", "pack"], "MyClass")` *) let add_php_prefix ctx type_path = match type_path with - | (pack, name) -> ((get_php_prefix ctx) @ pack, name) + | (pack, name) -> (ctx.pgc_prefix @ pack, name) (** If `expr` is a TCast or TMeta, then returns underlying expression (recursively bypassing nested casts). @@ -238,20 +252,21 @@ let error_message pos message = (stringify_pos pos) ^ ": " ^ message (** Terminates compiler process and prints user-friendly instructions about filing an issue in compiler repo. *) -let fail hxpos mlpos = +let fail ?msg hxpos mlpos = + let msg = + error_message + hxpos + ( + (match msg with Some msg -> msg | _ -> "") + ^ " Unexpected expression. Please submit an issue with expression example and following information:" + ) + in match mlpos with | (file, line, _, _) -> - Printf.printf "%s\n" (error_message hxpos "Unexpected expression. Please submit an issue with expression example and following information:"); - Printf.printf "%s:%d\n" file line; + Printf.eprintf "%s\n" msg; + Printf.eprintf "%s:%d\n" file line; assert false -(** - Print compilation error message and abort compilation process. -*) -let error_and_exit pos message = - Printf.printf "%s" (error_message pos message); - exit 1 - (** Check if `target` is a `Dynamic` type *) @@ -295,10 +310,20 @@ let is_string_type t = match follow t with TInst ({ cl_path = ([], "String") }, *) let is_string expr = is_string_type expr.etype +(** + Check if specified type is Array +*) +let is_array_type t = match follow t with TInst ({ cl_path = ([], "Array") }, _) -> true | _ -> false + +(** + Check if specified type represents a function +*) +let is_function_type t = match follow t with TFun _ -> true | _ -> false + (** Check if `expr` is an access to a method of special `php.PHP` class *) -let is_lang_extern expr = +let is_syntax_extern expr = match expr.eexpr with | TField ({ eexpr = TTypeExpr (TClassDecl { cl_path = path }) }, _) when path = syntax_type_path -> true | _ -> false @@ -316,42 +341,6 @@ let is_generic_parameter (target:Type.t) = *) let is_unknown_type (target:Type.t) = is_dynamic_type target || is_generic_parameter target -(** - @return `Type.t` instance for `Void` -*) -let void = ref None -let get_void ctx : Type.t = - match !void with - | Some value -> value - | None -> - let find com_type = - match com_type with - | TAbstractDecl ({ a_path = ([], "Void") } as abstr) -> void := Some (TAbstract (abstr, [])); - | _ -> () - in - List.iter find ctx.types; - match !void with - | Some value -> value - | None -> fail dummy_pos __POS__ - -(** - @return `tclass` instance for `php.Boot` -*) -let boot = ref None -let get_boot ctx : tclass = - match !boot with - | Some value -> value - | None -> - let find com_type = - match com_type with - | TClassDecl ({ cl_path = path } as cls) when path = boot_type_path -> boot := Some cls; - | _ -> () - in - List.iter find ctx.types; - match !boot with - | Some value -> value - | None -> fail dummy_pos __POS__ - (** @return `expr` wrapped in parenthesis *) @@ -361,7 +350,7 @@ let parenthesis expr = {eexpr = TParenthesis expr; etype = expr.etype; epos = ex Check if `current` binary should be surrounded with parenthesis *) let need_parenthesis_for_binop current parent = - if current = parent then + if current = parent && current != OpNotEq && current != OpEq then false else match (current, parent) with @@ -393,7 +382,8 @@ let needs_dereferencing for_assignment expr = (* some of `php.Syntax` methods *) | TCall ({ eexpr = TField (_, FStatic ({ cl_path = syntax_type_path }, { cf_name = name })) }, _) -> (match name with - | "binop" | "object" | "array" -> for_assignment + | "codeDeref" -> for_assignment + | "coalesce" -> for_assignment | _ -> false ) | _ -> false @@ -519,20 +509,27 @@ let create_dir_recursive (path:string list) = (** @return String representation of specified type path. E.g. returns "\example\Test" for (["example"], "Test") *) -let get_full_type_name ?escape ?omit_first_slash (type_path:path) = +let get_full_type_name ?(escape=false) ?(omit_first_slash=false) (type_path:path) = let name = match type_path with + | ([], type_name) -> + if omit_first_slash then + type_name + else + "\\" ^ type_name | (module_path, type_name) -> let parts = - match omit_first_slash with - | Some true -> get_real_path module_path - | _ -> "" :: get_real_path module_path + if omit_first_slash then + get_real_path module_path + else + "" :: get_real_path module_path in (String.concat "\\" parts) ^ "\\" ^ type_name in - match escape with - | Some true -> String.escaped name - | _ -> name + if escape then + String.escaped name + else + name (** Check if `target` is or implements native PHP `Throwable` interface @@ -612,15 +609,15 @@ let is_inline_var (field:tclass_field) = (** @return New TBlock expression which is composed of setting default values for optional arguments and function body. *) -let inject_defaults (ctx:Common.context) (func:tfunc) = +let inject_defaults (ctx:php_generator_context) (func:tfunc) = let rec inject args body_exprs = match args with | [] -> body_exprs | (_, None) :: rest -> inject rest body_exprs - | (_, Some TNull) :: rest -> inject rest body_exprs + | (_, Some {eexpr = TConst TNull}) :: rest -> inject rest body_exprs | (var, Some const) :: rest -> - let expr = Codegen.set_default ctx var const func.tf_expr.epos in - expr :: (inject rest body_exprs) + let expr = Texpr.set_default ctx.pgc_common.basic var const func.tf_expr.epos in + expr :: (inject rest body_exprs) in let exprs = match func.tf_expr.eexpr with @@ -718,10 +715,21 @@ let need_boot_equal expr1 expr2 = if is_constant_null expr1 || is_constant_null expr2 then false else - (is_int expr1 && (is_float expr2 || is_unknown_type expr2.etype)) - || (is_float expr1 && (is_float expr2 || is_int expr2 || is_unknown_type expr2.etype)) - || (is_unknown_type expr1.etype && (is_int expr2 || is_float expr2)) - || (is_unknown_type expr1.etype && is_unknown_type expr2.etype) + let unknown1 = is_unknown_type expr1.etype + and unknown2 = is_unknown_type expr2.etype in + if unknown1 && unknown2 then + true + else if is_function_type expr1.etype || is_function_type expr2.etype then + true + else + let int1 = is_int expr1 + and int2 = is_int expr2 + and float1 = is_float expr1 + and float2 = is_float expr2 in + (int1 && float2) + || (float1 && (float2 || int2)) + || (unknown1 && (int2 || float2)) + || ((int1 || float1) && unknown2) (** Adds `return` expression to block if it does not have one already @@ -761,7 +769,7 @@ let unpack_single_expr_block expr = Check if specified type has rtti meta *) let has_rtti_meta ctx mtype = - match Codegen.build_metadata ctx mtype with + match Texpr.build_metadata ctx.basic mtype with | None -> false | Some _ -> true @@ -818,8 +826,13 @@ let is_object_declaration expr = Check if `subject_arg` and `type_arg` can be generated as `$subject instanceof Type` expression. *) let instanceof_compatible (subject_arg:texpr) (type_arg:texpr) : bool = + let is_real_class path = + match path with + | ([], "String") | ([], "Class") | (["php";"_NativeArray"], "NativeArray_Impl_") -> false + | _ -> true + in match (reveal_expr_with_parenthesis type_arg).eexpr with - | TTypeExpr (TClassDecl { cl_path = path }) when path <> ([], "String") && path <> ([], "Class") -> + | TTypeExpr (TClassDecl { cl_path = path }) when is_real_class path -> let subject_arg = reveal_expr_with_parenthesis subject_arg in (match subject_arg.eexpr with | TLocal _ | TField _ | TCall _ | TArray _ | TConst TThis -> not (is_magic subject_arg) @@ -937,7 +950,7 @@ class class_wrapper (cls) = | Some body -> let path = match cls.cl_path with - | (pack, name) -> (pack @ ["_" ^ name], ("_extern_" ^ name)) + | (pack, name) -> (pack, ("_extern_" ^ name)) in let additional_cls = { cls with @@ -1097,21 +1110,21 @@ let clear_wrappers () = (** Check if specified type name is used in specified namespace *) -let namespaces_types_cache = Hashtbl.create 512 -let type_name_used_in_namespace ctx name namespace = - let types = Hashtbl.find_all namespaces_types_cache namespace in - match types with - | [] -> - List.iter - (fun ctx_type -> - let wrapper = get_wrapper ctx_type in - Hashtbl.add namespaces_types_cache wrapper#get_namespace wrapper#get_name - ) - ctx.types; - let types = Hashtbl.find_all namespaces_types_cache namespace in - List.mem name types - | _ -> - List.mem name types +let type_name_used_in_namespace ctx type_path as_name namespace = + let types = + match Hashtbl.find_all ctx.pgc_namespaces_types_cache namespace with + | [] -> + List.iter + (fun ctx_type -> + let wrapper = get_wrapper ctx_type in + Hashtbl.add ctx.pgc_namespaces_types_cache wrapper#get_namespace wrapper#get_name + ) + ctx.pgc_common.types; + Hashtbl.find_all ctx.pgc_namespaces_types_cache namespace + | types -> types + in + List.mem as_name types + && (namespace, as_name) <> type_path (** Simple list intersection implementation. @@ -1212,7 +1225,7 @@ class local_vars = (** Consumes expressions and generates php code to output buffer. *) -class code_writer (ctx:Common.context) hx_type_path php_name = +class code_writer (ctx:php_generator_context) hx_type_path php_name = object (self) (** Namespace path. E.g. ["some"; "pack"] for "some.pack.MyType" *) val namespace = get_module_path hx_type_path @@ -1230,6 +1243,8 @@ class code_writer (ctx:Common.context) hx_type_path php_name = val mutable sourcemap : sourcemap_builder option = None (** Indicates if `super()` expressions should be generated if spotted. *) val mutable has_super_constructor = true + (** The latest string written to the output buffer via `self#write_pos` method *) + val mutable last_written_pos = "" (** Get php name of current type *) @@ -1292,7 +1307,8 @@ class code_writer (ctx:Common.context) hx_type_path php_name = method use ?prefix (type_path:path) = if type_path = hx_type_path then php_name - else + else begin + let orig_type_path = type_path in let type_path = match type_path with (pack, name) -> (pack, get_real_name name) in let type_path = match prefix with @@ -1306,31 +1322,40 @@ class code_writer (ctx:Common.context) hx_type_path php_name = let alias_source = ref (List.rev module_path) in let get_alias_next_part () = match !alias_source with - | [] -> failwith ("Failed to find already used type: " ^ get_full_type_name type_path) + | [] -> fail ~msg:("Failed to find already used type: " ^ get_full_type_name type_path) self#pos __POS__ | name :: rest -> - alias_source := rest; - String.capitalize name + alias_source := (match rest with + | [] -> [name] + | _ -> rest + ); + StringHelper.capitalize name and added = ref false and alias = ref (get_type_name type_path) in - if !alias = php_name then - alias := get_alias_next_part () ^ !alias; + let alias_upper = ref (StringHelper.uppercase !alias) in + let prepend_alias prefix = + alias := prefix ^ !alias; + alias_upper := StringHelper.uppercase !alias + in + if !alias_upper = (StringHelper.uppercase php_name) then + prepend_alias (get_alias_next_part ()); while not !added do try - if (get_module_path type_path) <> namespace && type_name_used_in_namespace ctx !alias namespace then - alias := get_alias_next_part () ^ !alias + if (get_module_path type_path) <> namespace && type_name_used_in_namespace ctx orig_type_path !alias namespace then + prepend_alias (get_alias_next_part ()) else - let used_type = Hashtbl.find use_table !alias in - if used_type = type_path then + let used_type = Hashtbl.find use_table !alias_upper in + if used_type.ut_type_path = type_path then added := true else - alias := get_alias_next_part () ^ !alias; + prepend_alias (get_alias_next_part ()); with | Not_found -> - Hashtbl.add use_table !alias type_path; + Hashtbl.add use_table !alias_upper { ut_alias = !alias; ut_type_path = type_path; }; added := true | _ -> fail self#pos __POS__ done; !alias + end (** Extracts type path from Type.t value and execute self#use on it @return Unique alias for specified type. @@ -1350,13 +1375,13 @@ class code_writer (ctx:Common.context) hx_type_path php_name = | TFun _ -> self#use ~prefix:false ([], "Closure") | TAnon _ -> "object" | TDynamic _ -> "mixed" - | TLazy _ -> failwith "TLazy not implemented" + | TLazy _ -> fail ~msg:"TLazy not implemented" self#pos __POS__ | TMono mono -> (match !mono with | None -> "mixed" | Some t -> self#use_t t ) - | TType _ -> failwith "TType not implemented" + | TType _ -> fail ~msg:"TType not implemented" self#pos __POS__ | TAbstract (abstr, _) -> match abstr.a_path with | ([],"Int") -> "int" @@ -1373,7 +1398,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = method pos = match expr_hierarchy with | { epos = pos } :: _ -> pos - | _ -> dummy_pos + | _ -> null_pos (** Indicates whether current expression nesting level is a top level of a block *) @@ -1453,8 +1478,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = ``` *) method dereference expr = - let boot_cls = get_boot ctx in - let deref_field = PMap.find "deref" boot_cls.cl_statics in + let deref_field = PMap.find "deref" ctx.pgc_boot.cl_statics in match expr.eexpr with | TField (target_expr, access) -> { @@ -1464,9 +1488,9 @@ class code_writer (ctx:Common.context) hx_type_path php_name = { target_expr with eexpr = TField ( { - target_expr with eexpr = TTypeExpr (TClassDecl boot_cls) + target_expr with eexpr = TTypeExpr (TClassDecl ctx.pgc_boot) }, - FStatic (boot_cls, deref_field) + FStatic (ctx.pgc_boot, deref_field) ) }, [ target_expr ] @@ -1483,9 +1507,9 @@ class code_writer (ctx:Common.context) hx_type_path php_name = { target_expr with eexpr = TField ( { - target_expr with eexpr = TTypeExpr (TClassDecl boot_cls) + target_expr with eexpr = TTypeExpr (TClassDecl ctx.pgc_boot) }, - FStatic (boot_cls, deref_field) + FStatic (ctx.pgc_boot, deref_field) ) }, [ target_expr ] @@ -1515,12 +1539,18 @@ class code_writer (ctx:Common.context) hx_type_path php_name = Writes fixed amount of empty lines (E.g. between methods) *) method write_empty_lines = - self#write "\n\n" + self#write "\n" (** Writes current indentation to output buffer *) method write_indentation = self#write indentation + (** + Writes current indentation followed by `str` to output buffer + *) + method write_with_indentation str = + self#write indentation; + self#write str (** Writes specified line to output buffer and appends \n *) @@ -1536,28 +1566,39 @@ class code_writer (ctx:Common.context) hx_type_path php_name = *) method write_use = self#indent 0; - let write alias type_path = - if (get_module_path type_path) <> namespace then - if get_type_name type_path = alias then - self#write_statement ("use " ^ (get_full_type_name type_path)) + let write _ used_type = + let namespace = + if hx_type_path = ([],"") then namespace (* ([],"") is for index.php *) + else ctx.pgc_prefix @ namespace + in + if (get_module_path used_type.ut_type_path) <> namespace then + if get_type_name used_type.ut_type_path = used_type.ut_alias then + self#write_statement ("use " ^ (get_full_type_name used_type.ut_type_path)) else - let full_name = get_full_type_name type_path in - self#write_statement ("use " ^ full_name ^ " as " ^ alias) + let full_name = get_full_type_name used_type.ut_type_path in + self#write_statement ("use " ^ full_name ^ " as " ^ used_type.ut_alias) in Hashtbl.iter write use_table (** Writes array item declaration to output buffer and appends ",\n" + Adds indentation and ",\n" if `separate_line` is `true`. *) - method write_array_item ?key value_expr = + method write_array_item ?separate_line ?key value_expr = + let separate_line = match separate_line with Some true -> true | _ -> false in + if separate_line then self#write_indentation; (match key with | None -> - self#write_indentation; self#write_expr value_expr; | Some key_str -> - self#write (indentation ^ "\"" ^ (String.escaped key_str) ^ "\" => "); + let key_str = + Str.global_replace (Str.regexp "\\$") + "\\$" + (String.escaped key_str) + in + self#write ("\"" ^ key_str ^ "\" => "); self#write_expr value_expr ); - self#write ",\n" + if separate_line then self#write ",\n" (** Writes expression to output buffer *) @@ -1570,6 +1611,8 @@ class code_writer (ctx:Common.context) hx_type_path php_name = vars#used var.v_name; self#write ("$" ^ var.v_name) | TArray (target, index) -> self#write_expr_array_access target index + | TBinop (OpAssign, { eexpr = TArray (target, index) }, value) when is_array_type target.etype -> + self#write_expr_set_array_item target index value | TBinop (operation, expr1, expr2) when needs_dereferencing (is_assignment_binop operation) expr1 -> self#write_expr { expr with eexpr = TBinop (operation, self#dereference expr1, expr2) } | TBinop (operation, expr1, expr2) -> self#write_expr_binop operation expr1 expr2 @@ -1584,11 +1627,14 @@ class code_writer (ctx:Common.context) hx_type_path php_name = self#write ")" | TObjectDecl fields -> self#write_expr_object_declaration fields | TArrayDecl exprs -> self#write_expr_array_decl exprs - | TCall (target, [arg1; arg2]) when is_std_is target && instanceof_compatible arg1 arg2 -> self#write_expr_lang_instanceof [arg1; arg2] - | TCall (_, [arg]) when is_native_struct_array_cast expr && is_object_declaration arg -> self#write_assoc_array_decl arg - | TCall ({ eexpr = TIdent name}, args) when is_magic expr -> self#write_expr_magic name args + | TCall (target, [arg1; arg2]) when is_std_is target && instanceof_compatible arg1 arg2 -> self#write_expr_syntax_instanceof [arg1; arg2] + | TCall (_, [arg]) when is_native_struct_array_cast expr && is_object_declaration arg -> + (match (reveal_expr arg).eexpr with TObjectDecl fields -> self#write_assoc_array_decl fields | _ -> fail self#pos __POS__) + | TCall ({ eexpr = TIdent name}, args) when is_magic expr -> + ctx.pgc_common.warning ("untyped " ^ name ^ " is deprecated. Use php.Syntax instead.") self#pos; + self#write_expr_magic name args | TCall ({ eexpr = TField (expr, access) }, args) when is_string expr -> self#write_expr_call_string expr access args - | TCall (expr, args) when is_lang_extern expr -> self#write_expr_call_lang_extern expr args + | TCall (expr, args) when is_syntax_extern expr -> self#write_expr_call_syntax_extern expr args | TCall (target, args) when is_sure_var_field_access target -> self#write_expr_call (parenthesis target) args | TCall (target, args) -> self#write_expr_call target args | TNew (_, _, args) when is_string expr -> write_args self#write self#write_expr args @@ -1601,12 +1647,18 @@ class code_writer (ctx:Common.context) hx_type_path php_name = | TBlock exprs -> self#write_expr_block expr | TFor (var, iterator, body) -> fail self#pos __POS__ | TIf (condition, if_expr, else_expr) -> self#write_expr_if condition if_expr else_expr - | TWhile (condition, expr, do_while) -> self#write_expr_while condition expr do_while + | TWhile (condition, expr, do_while) -> + (match (reveal_expr_with_parenthesis condition).eexpr with + | TField (_, FStatic ({ cl_path = path }, { cf_name = "foreachCondition" })) when path = syntax_type_path -> + self#write_expr_syntax_foreach expr + | _ -> + self#write_expr_while condition expr do_while + ) | TSwitch (switch, cases, default ) -> self#write_expr_switch switch cases default | TTry (try_expr, catches) -> self#write_expr_try_catch try_expr catches | TReturn expr -> self#write_expr_return expr - | TBreak -> self#write_expr_loop_flow "break" - | TContinue -> self#write_expr_loop_flow "continue" + | TBreak -> self#write "break" + | TContinue -> self#write "continue" | TThrow expr -> self#write_expr_throw expr | TCast (expr, mtype) -> self#write_expr_cast expr mtype | TMeta (_, expr) -> self#write_expr expr @@ -1615,23 +1667,6 @@ class code_writer (ctx:Common.context) hx_type_path php_name = | TIdent s -> self#write s ); expr_hierarchy <- List.tl expr_hierarchy - (** - Writes `continue N` or `break N` with required N depending on nearest parent loop and amount of `switch` between loop and - `continue/break` - *) - method write_expr_loop_flow word = - let rec count_N parent_exprs count = - match parent_exprs with - | [] -> count - | { eexpr = TWhile _ } :: _ -> count - | { eexpr = TSwitch _ } :: rest -> count_N rest (count + 1) - | _ :: rest -> count_N rest count - in - let count = count_N expr_hierarchy 1 in - if count > 1 then - self#write (word ^ " " ^ (string_of_int count)) - else - self#write word (** Writes TConst to output buffer *) @@ -1672,35 +1707,34 @@ class code_writer (ctx:Common.context) hx_type_path php_name = | _ -> self#write ((self#use array_type_path) ^ "::wrap([\n"); self#indent_more; - List.iter (fun expr -> self#write_array_item expr) exprs; + List.iter (fun expr -> self#write_array_item ~separate_line:true expr) exprs; self#indent_less; - self#write_indentation; - self#write "])" + self#write_with_indentation "])" (** - Write associative array declaration (used for NativeStructArray) + Write associative array declaration *) - method write_assoc_array_decl object_decl = - match (reveal_expr object_decl).eexpr with - | TObjectDecl fields -> - if List.length fields = 0 then - self#write "[]" - else begin - self#write "[\n"; - self#indent_more; - List.iter - (fun ((name,_,_), field) -> - self#write_indentation; - self#write_const_string name; - self#write " => "; - self#write_expr field; - self#write ",\n" - ) - fields; - self#indent_less; - self#write_indentation; - self#write "]"; - end - | _ -> fail object_decl.epos __POS__ + method write_assoc_array_decl fields = + match fields with + | [] -> self#write "[]" + | [((key, _, _), value)] -> + self#write "["; + self#write_array_item ~key:key value; + self#write "]" + | _ -> + self#write "[\n"; + self#indent_more; + let write_field ((key,_,_), value) = self#write_array_item ~separate_line:true ~key:key value in + List.iter write_field fields; + self#indent_less; + self#write_with_indentation "]" + (** + Writes `target[index] = value` assuming `target` is of `Array` type + *) + method write_expr_set_array_item target index value = + self#write_expr target; + self#write "->offsetSet("; + write_args self#write self#write_expr [index; value]; + self#write ")" (** Writes TArray to output buffer *) @@ -1807,16 +1841,26 @@ class code_writer (ctx:Common.context) hx_type_path php_name = Emulates TBlock for parent expression and writes `expr` as inlined block *) method write_fake_block expr = - self#write_indentation; - let fake_block = { expr with eexpr = TBlock [expr] } in - expr_hierarchy <- fake_block :: expr_hierarchy; - self#write_as_block ~inline:true expr; - expr_hierarchy <- List.tl expr_hierarchy + match expr.eexpr with + | TBlock [] -> () + | _ -> + self#write_indentation; + let fake_block = { expr with eexpr = TBlock [expr] } in + expr_hierarchy <- fake_block :: expr_hierarchy; + self#write_as_block ~inline:true expr; + expr_hierarchy <- List.tl expr_hierarchy (** Write position of specified expression to output buffer *) method write_pos expr = - self#write ("#" ^ (stringify_pos expr.epos) ^ "\n"); + let pos = ("#" ^ (stringify_pos expr.epos) ^ "\n") in + if pos = last_written_pos then + false + else begin + last_written_pos <- pos; + self#write pos; + true + end (** Writes "{ }" to output buffer *) @@ -1825,10 +1869,8 @@ class code_writer (ctx:Common.context) hx_type_path php_name = and exprs = match expr.eexpr with TBlock exprs -> exprs | _ -> [expr] in let write_body () = let write_expr expr = - if not !skip_line_directives && not (is_block expr) then begin - self#write_pos expr; - self#write_indentation - end; + if not ctx.pgc_skip_line_directives && not (is_block expr) then + if self#write_pos expr then self#write_indentation; self#write_expr expr; match expr.eexpr with | TBlock _ | TIf _ | TTry _ | TSwitch _ | TWhile (_, _, NormalWhile) -> self#write "\n" @@ -1878,8 +1920,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = write_body () ); self#indent_less; - self#write_indentation; - self#write "}" + self#write_with_indentation "}" (** Writes TReturn to output buffer *) @@ -1941,8 +1982,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = self#write_indentation; self#write_as_block ~inline:true expr; self#indent_less; - self#write_indentation; - self#write "}"; + self#write_with_indentation "}"; end; if not !dynamic then self#write " else "; first_catch := false; @@ -1951,7 +1991,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = self#write_as_block try_expr; self#write " catch (\\Throwable $__hx__caught_e) {\n"; self#indent_more; - if has_feature ctx "haxe.CallStack.exceptionStack" then + if has_feature ctx.pgc_common "haxe.CallStack.exceptionStack" then self#write_statement ((self#use (["haxe"], "CallStack")) ^ "::saveExceptionTrace($__hx__caught_e)"); self#write_statement ("$__hx__real_e = ($__hx__caught_e instanceof " ^ haxe_exception ^ " ? $__hx__caught_e->e : $__hx__caught_e)"); self#write_indentation; @@ -1961,8 +2001,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = else (match catches with [_] -> () | _ -> self#write "\n"); self#indent_less; - self#write_indentation; - self#write "}" + self#write_with_indentation "}" (** Writes TCast to output buffer *) @@ -1980,15 +2019,15 @@ class code_writer (ctx:Common.context) hx_type_path php_name = @see http://old.haxe.org/doc/advanced/magic#php-magic *) method write_expr_magic name args = - let error = error_message self#pos ("Invalid arguments for " ^ name ^ " magic call") in + let error = ("Invalid arguments for " ^ name ^ " magic call") in match args with - | [] -> failwith error + | [] -> fail ~msg:error self#pos __POS__ | { eexpr = TConst (TString code) } as expr :: args -> (match name with | "__php__" -> (match expr.eexpr with | TConst (TString php) -> - Codegen.interpolate_code ctx php args self#write self#write_expr self#pos + Codegen.interpolate_code ctx.pgc_common php args self#write self#write_expr self#pos | _ -> fail self#pos __POS__ ) | "__call__" -> @@ -1998,7 +2037,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = | "__physeq__" -> (match args with | [expr2] -> self#write_expr_binop OpEq expr expr2 - | _ -> failwith error + | _ -> fail ~msg:error self#pos __POS__ ) | "__var__" -> (match args with @@ -2008,20 +2047,20 @@ class code_writer (ctx:Common.context) hx_type_path php_name = self#write ("$" ^ code ^ "["); self#write_expr expr2; self#write "]" - | _ -> failwith error + | _ -> fail ~msg:error self#pos __POS__ ) - | _ -> failwith error + | _ -> fail ~msg:error self#pos __POS__ ) | [expr1; expr2] -> (match name with | "__physeq__" -> (match args with | [expr1; expr2] -> self#write_expr_binop OpEq expr1 expr2 - | _ -> failwith error + | _ -> fail ~msg:error self#pos __POS__ ) - | _ -> failwith error + | _ -> fail ~msg:error self#pos __POS__ ) - | _ -> failwith error + | _ -> fail ~msg:error self#pos __POS__ (** Writes TTypeExpr to output buffer *) @@ -2058,7 +2097,11 @@ class code_writer (ctx:Common.context) hx_type_path php_name = self#write ")" in let write_for_concat expr = - if ((is_constant expr) && not (is_constant_null expr)) || (is_concatenation expr) then + if ((is_constant expr) && not (is_constant_null expr)) + || (is_concatenation expr) + || is_php_global expr + || is_php_class_const expr + then self#write_expr expr else begin self#write "("; @@ -2133,8 +2176,11 @@ class code_writer (ctx:Common.context) hx_type_path php_name = | OpAssignOp OpMod -> if is_int expr1 && is_int expr2 then write_binop " %= " - else + else begin + self#write_expr expr1; + self#write " = "; write_method "fmod" + end | OpAssignOp OpUShr -> self#write_expr expr1; self#write " = "; @@ -2172,7 +2218,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = method write_expr_field expr access = match access with | FInstance ({ cl_path = [], "String"}, _, { cf_name = "length"; cf_kind = Var _ }) -> - self#write "strlen("; + self#write "mb_strlen("; self#write_expr expr; self#write ")" | FInstance (_, _, field) -> self#write_expr_for_field_access expr "->" (field_name field) @@ -2225,7 +2271,9 @@ class code_writer (ctx:Common.context) hx_type_path php_name = self#write "()" end (** - Writes field access on Dynamic expression to output buffer + Writes field access on Dynamic expression to output buffer. + Returns `true` if requested field is most likely belongs to String (and field resolution will be handled at runtime). + Otherwise returns `false` *) method write_expr_field_if_string expr field_name = (* Special case for String fields *) @@ -2281,7 +2329,8 @@ class code_writer (ctx:Common.context) hx_type_path php_name = *) method write_static_method_closure expr field_name = let expr = reveal_expr expr in - self#write ("new " ^ (self#use hxclosure_type_path) ^ "("); + self#write ((self#use boot_type_path) ^ "::getStaticClosure("); + (* self#write ("new " ^ (self#use hxclosure_type_path) ^ "("); *) (match (reveal_expr expr).eexpr with | TTypeExpr (TClassDecl { cl_path = ([], "String") }) -> self#write ((self#use hxstring_type_path) ^ "::class") @@ -2306,7 +2355,8 @@ class code_writer (ctx:Common.context) hx_type_path php_name = self#write_expr expr; self#write ("->" ^ (field_name field)) else - let new_closure = "new " ^ (self#use hxclosure_type_path) in + (* let new_closure = "new " ^ (self#use hxclosure_type_path) in *) + let new_closure = ((self#use boot_type_path) ^ "::getInstanceClosure") in match expr.eexpr with | TTypeExpr mtype -> let class_name = self#use_t (type_of_module_type mtype) in @@ -2329,13 +2379,9 @@ class code_writer (ctx:Common.context) hx_type_path php_name = match fields with | [] -> self#write ("new " ^ (self#use hxanon_type_path) ^ "()") | _ -> - self#write ("new " ^ (self#use hxanon_type_path) ^ "([\n"); - self#indent_more; - let write_field ((key,_,_), value) = self#write_array_item ~key:key value in - List.iter write_field fields; - self#indent_less; - self#write_indentation; - self#write "])" + self#write ("new " ^ (self#use hxanon_type_path) ^ "("); + self#write_assoc_array_decl fields; + self#write ")" (** Writes specified type to output buffer depending on type of expression. *) @@ -2354,43 +2400,49 @@ class code_writer (ctx:Common.context) hx_type_path php_name = (** Write language specific expression declared in `php.Syntax` extern *) - method write_expr_call_lang_extern expr args = + method write_expr_call_syntax_extern expr args = let name = match expr.eexpr with | TField (_, FStatic (_, field)) -> field_name field | _ -> fail self#pos __POS__ in match name with - | "int" | "float" - | "string" | "bool" - | "object" | "array" -> self#write_expr_lang_cast name args - | "binop" -> self#write_expr_lang_binop args - | "instanceof" -> self#write_expr_lang_instanceof args - | "foreach" -> self#write_expr_lang_foreach args - | "construct" -> self#write_expr_lang_construct args - | "getField" -> self#write_expr_lang_get_field args - | "setField" -> self#write_expr_lang_set_field args - | "getStaticField" -> self#write_expr_lang_get_static_field args - | "setStaticField" -> self#write_expr_lang_set_static_field args - | "call" -> self#write_expr_lang_call args - | "staticCall" -> self#write_expr_lang_static_call args - | "arrayDecl" -> self#write_expr_lang_array_decl args - | "splat" -> self#write_expr_lang_splat args - | "suppress" -> self#write_expr_lang_suppress args + | "code" | "codeDeref" -> self#write_expr_syntax_code args + | "coalesce" -> self#write_expr_syntax_coalesce args + | "instanceof" -> self#write_expr_syntax_instanceof args + | "nativeClassName" -> self#write_expr_syntax_native_class_name args + | "construct" -> self#write_expr_syntax_construct args + | "field" | "getField" -> self#write_expr_syntax_get_field args + | "setField" -> self#write_expr_syntax_set_field args + | "getStaticField" -> self#write_expr_syntax_get_static_field args + | "setStaticField" -> self#write_expr_syntax_set_static_field args + | "call" -> self#write_expr_syntax_call args + | "staticCall" -> self#write_expr_syntax_static_call args + | "arrayDecl" -> self#write_expr_syntax_array_decl args + | "assocDecl" -> self#write_expr_syntax_assoc_decl args + | "suppress" -> self#write_expr_syntax_suppress args | "keepVar" -> () - | _ -> fail self#pos __POS__ + | _ -> ctx.pgc_common.error ("php.Syntax." ^ name ^ "() is not supported.") self#pos (** - Writes splat operator (for `php.Syntax.splat()`) + Writes plain php code (for `php.Syntax.code()`) *) - method write_expr_lang_splat args = + method write_expr_syntax_code args = match args with - | [ args_expr ] -> - self#write "..."; - self#write_expr args_expr - | _ -> fail self#pos __POS__ + | [] -> fail self#pos __POS__ + | { eexpr = TConst (TString php) } :: args -> + let args = List.map + (fun arg -> + match (reveal_expr arg).eexpr with + | TBinop _ | TUnop _ -> parenthesis arg + | _ -> arg + ) + args + in + Codegen.interpolate_code ctx.pgc_common php args self#write self#write_expr self#pos + | _ -> ctx.pgc_common.error "First argument of php.Syntax.code() must be a constant string." self#pos (** Writes error suppression operator (for `php.Syntax.suppress()`) *) - method write_expr_lang_suppress args = + method write_expr_syntax_suppress args = match args with | [ args_expr ] -> self#write "@"; @@ -2399,14 +2451,22 @@ class code_writer (ctx:Common.context) hx_type_path php_name = (** Writes native array declaration (for `php.Syntax.arrayDecl()`) *) - method write_expr_lang_array_decl args = + method write_expr_syntax_array_decl args = self#write "["; write_args self#write (fun e -> self#write_expr e) args; self#write "]" + (** + Writes native array declaration (for `php.Syntax.arrayDecl()`) + *) + method write_expr_syntax_assoc_decl args = + match args with + | [] -> self#write_assoc_array_decl [] + | { eexpr = TObjectDecl fields } :: [] -> self#write_assoc_array_decl fields + | _ -> ctx.pgc_common.error "php.Syntax.assocDecl() accepts object declaration only." self#pos (** Writes a call to instance method (for `php.Syntax.call()`) *) - method write_expr_lang_call args = + method write_expr_syntax_call args = match args with | obj_expr :: method_expr :: args -> self#write_expr obj_expr; @@ -2419,7 +2479,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = (** Writes a call to a static method (for `php.Syntax.staticCall()`) *) - method write_expr_lang_static_call args = + method write_expr_syntax_static_call args = match args with | type_expr :: method_expr :: args -> self#write_type type_expr; @@ -2432,7 +2492,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = (** Writes field access for reading (for `php.Syntax.getField()`) *) - method write_expr_lang_get_field args = + method write_expr_syntax_get_field args = match args with | obj_expr :: field_expr :: [] -> self#write_expr obj_expr; @@ -2443,7 +2503,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = (** Writes field access for writing (for `php.Syntax.setField()`) *) - method write_expr_lang_set_field args = + method write_expr_syntax_set_field args = match args with | obj_expr :: field_expr :: value_expr :: [] -> self#write_expr obj_expr; @@ -2456,7 +2516,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = (** Writes static field access for reading (for `php.Syntax.getStaticField()`) *) - method write_expr_lang_get_static_field args = + method write_expr_syntax_get_static_field args = match args with | type_expr :: field_expr :: [] -> self#write_type type_expr; @@ -2467,7 +2527,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name = (** Writes static field access for writing (for `php.Syntax.setField()`) *) - method write_expr_lang_set_static_field args = + method write_expr_syntax_set_static_field args = match args with | type_expr :: field_expr :: value_expr :: [] -> self#write_expr type_expr; @@ -2480,52 +2540,36 @@ class code_writer (ctx:Common.context) hx_type_path php_name = (** Writes `new` expression with class name taken local variable (for `php.Syntax.construct()`) *) - method write_expr_lang_construct args = + method write_expr_syntax_construct args = let (class_expr, args) = match args with | class_expr :: args -> (class_expr, args) | _ -> fail self#pos __POS__ in self#write "new "; self#write_expr class_expr; + (match follow class_expr.etype with + | TInst ({ cl_path = ([], "String") }, _) -> () + | _ -> self#write "->phpClassName" + ); self#write "("; write_args self#write (fun e -> self#write_expr e) args; self#write ")" (** - Writes native php type conversion to output buffer (e.g. `php.Syntax.int()`) + Writes `$left ?? $right` expression to output buffer (for `php.Syntax.coalesce()`) *) - method write_expr_lang_cast type_name args = + method write_expr_syntax_coalesce args = match args with - | expr :: [] -> - let add_parentheses = match self#parent_expr with Some e -> is_access e | None -> false - and expr = match expr.eexpr with - | TLocal e -> expr - | _ -> parenthesis expr - in - if add_parentheses then self#write "("; - self#write ("(" ^ type_name ^")"); - self#write_expr expr; - if add_parentheses then self#write ")" - | _ -> fail self#pos __POS__ - (** - Generates binary operation to output buffer (for `php.Syntax.binop()`) - *) - method write_expr_lang_binop args = - match args with - | val_expr1 :: operator_expr :: val_expr2 :: [] -> - let operator = match operator_expr.eexpr with - | TConst (TString operator) -> operator - | _ -> error_and_exit self#pos "Second argument for php.Syntax.binop() must be a constant string" - in + | left :: right :: [] -> self#write "("; - self#write_expr val_expr1; - self#write (" " ^ operator ^ " "); - self#write_expr val_expr2; - self#write ")" + self#write_expr left; + self#write " ?? "; + self#write_expr right; + self#write ")"; | _ -> fail self#pos __POS__ (** Writes `instanceof` expression to output buffer (for `php.Syntax.instanceof()`) *) - method write_expr_lang_instanceof args = + method write_expr_syntax_instanceof args = match args with | val_expr :: type_expr :: [] -> self#write "("; @@ -2541,27 +2585,40 @@ class code_writer (ctx:Common.context) hx_type_path php_name = self#write ")" | _ -> fail self#pos __POS__ (** - Writes `foreach` expression to output buffer (for `php.Syntax.foreach()`) + Writes either a "Cls::class" expression (if class is passed directly) or a `$cls->phpClassName` expression + (if class is passed as a variable) to output buffer (for `php.Syntax.nativeClassName()`) *) - method write_expr_lang_foreach args = + method write_expr_syntax_native_class_name args = match args with - | collection_expr :: { eexpr = TFunction fn } :: [] -> - let (key_name, value_name) = match fn.tf_args with - | ({ v_name = key_name }, _) :: ({ v_name = value_name }, _) :: [] -> (key_name, value_name) - | _ -> fail self#pos __POS__ - and add_parentheses = - match collection_expr.eexpr with - | TLocal _ -> false + | cls_expr :: [] -> + (match (reveal_expr cls_expr).eexpr with + | TTypeExpr mtype -> + self#write (self#use_t (type_of_module_type mtype)); + self#write "::class" + | _ -> + self#write_expr cls_expr; + self#write "->phpClassName" + ); + | _ -> fail self#pos __POS__ + (** + Writes `foreach` expression to output buffer (for `php.Syntax.foreach()`) + *) + method write_expr_syntax_foreach body = + match body.eexpr with + | TBlock ({ eexpr = TCall (_, [collection]) } :: { eexpr = TVar (key, _) } :: { eexpr = TVar (value, _) } :: _ :: body_exprs) -> + let add_parentheses = + match collection.eexpr with + | TLocal _ | TField _ | TArray _ -> false | _ -> true in self#write "foreach ("; if add_parentheses then self#write "("; - self#write_expr collection_expr; + self#write_expr collection; if add_parentheses then self#write ")"; - self#write (" as $" ^ key_name ^ " => $" ^ value_name ^ ") "); - self#write_as_block fn.tf_expr + self#write (" as $" ^ key.v_name ^ " => $" ^ value.v_name ^ ") "); + self#write_as_block ~unset_locals:true { body with eexpr = TBlock body_exprs }; | _ -> - error_and_exit self#pos "PHP.foreach() only accepts anonymous function declaration for second argument." + fail self#pos __POS__ (** Writes TCall to output buffer *) @@ -2672,39 +2729,63 @@ class code_writer (ctx:Common.context) hx_type_path php_name = Writes TSwitch to output buffer *) method write_expr_switch switch cases default = - let write_case (conditions, expr) = - List.iter - (fun condition -> + let write_switch = + match switch.eexpr with + | TLocal _ -> + (fun () -> self#write_expr switch) + | TParenthesis ({ eexpr = TLocal _ } as e) -> + (fun () -> self#write_expr e) + | _ -> + self#write "$__hx__switch = "; + self#write_expr switch; + self#write ";\n"; self#write_indentation; - self#write "case "; - self#write_expr condition; - self#write ":\n"; - ) - conditions; - self#indent_more; - self#write_indentation; - self#write_as_block ~inline:true expr; - self#write_statement "break"; - self#indent_less + (fun () -> self#write "$__hx__switch") in - self#write "switch "; - self#write_expr switch; - self#write " {\n"; - self#indent_more; - List.iter write_case cases; - (match default with + let rec write_conditions conditions = + match conditions with + | [] -> () + | condition :: rest -> + if need_boot_equal switch condition then + begin + self#write ((self#use boot_type_path) ^ "::equal("); + write_switch (); + self#write ", "; + self#write_expr condition; + self#write ")" + end + else + begin + write_switch (); + self#write " === "; + self#write_expr condition; + end; + match rest with + | [] -> () + | _ -> + self#write " || "; + write_conditions rest + in + let rec write_cases cases = + match cases with + | [] -> () + | (conditions, expr) :: rest -> + self#write "if ("; + write_conditions conditions; + self#write ") "; + self#write_as_block expr; + match rest with + | [] -> () + | _ -> + self#write " else "; + write_cases rest + in + write_cases cases; + match default with | None -> () | Some expr -> - self#write_line "default:"; - self#indent_more; - self#write_indentation; - self#write_as_block ~inline:true expr; - self#write_statement "break"; - self#indent_less - ); - self#indent_less; - self#write_indentation; - self#write "}" + self#write " else "; + self#write_as_block expr; (** Write TEnumParameter expression to output buffer *) @@ -2739,9 +2820,11 @@ class code_writer (ctx:Common.context) hx_type_path php_name = self#write ("$" ^ arg_name); match default_value with | None -> () - | Some const -> + | Some expr -> self#write " = "; - self#write_expr_const const + match expr.eexpr with + | TConst _ -> self#write_expr expr + | _ -> self#write "null" (** Write an access to a field of dynamic value *) @@ -2784,7 +2867,7 @@ class virtual type_builder ctx (wrapper:type_wrapper) = Get PHP namespace path *) method get_namespace = - match get_php_prefix ctx with + match ctx.pgc_prefix with | [] -> get_real_path wrapper#get_namespace | prefix -> get_real_path (prefix @ wrapper#get_namespace) (** @@ -2850,8 +2933,10 @@ class virtual type_builder ctx (wrapper:type_wrapper) = writer#write_empty_lines; let boot_class = writer#use boot_type_path in (* Boot initialization *) - if boot_type_path = self#get_type_path then - writer#write_statement (boot_class ^ "::__hx__init()"); + if boot_type_path = self#get_type_path then begin + writer#write_statement ("require_once __DIR__.'/" ^ polyfills_file ^ "'"); + writer#write_statement (boot_class ^ "::__hx__init()") + end; let haxe_class = match wrapper#get_type_path with (path, name) -> String.concat "." (path @ [name]) in writer#write_statement (boot_class ^ "::registerClass(" ^ (self#get_name) ^ "::class, '" ^ haxe_class ^ "')"); self#write_rtti_meta; @@ -2880,8 +2965,8 @@ class virtual type_builder ctx (wrapper:type_wrapper) = writer#indent 0; writer#write_line " writer#write_line (" * " ^ s)); - if ctx.debug then writer#write_line (" * Haxe source file: " ^ self#get_source_file); + Codegen.map_source_header ctx.pgc_common (fun s -> writer#write_line (" * " ^ s)); + if ctx.pgc_common.debug then writer#write_line (" * Haxe source file: " ^ self#get_source_file); writer#write_line " */"; writer#write "\n"; let namespace = self#get_namespace in @@ -2950,7 +3035,7 @@ class virtual type_builder ctx (wrapper:type_wrapper) = Writes rtti meta to output buffer *) method write_rtti_meta = - match Codegen.build_metadata ctx wrapper#get_module_type with + match Texpr.build_metadata ctx.pgc_common.basic wrapper#get_module_type with | None -> () | Some meta_expr -> let boot_class = writer#use boot_type_path in @@ -2975,12 +3060,14 @@ class virtual type_builder ctx (wrapper:type_wrapper) = writer#write_statement "$called = true"; writer#write "\n"; writer#reset; + writer#indent 2; (match wrapper#get_magic_init with | None -> () | Some expr -> writer#write_fake_block expr ); writer#write "\n"; writer#reset; + writer#indent 2; self#write_hx_init_body; writer#indent 1; writer#write_line "}" @@ -3002,13 +3089,9 @@ class virtual type_builder ctx (wrapper:type_wrapper) = writer#indent_more; self#write_instance_initialization; let func = inject_defaults ctx func in - begin match func.eexpr with - | TBlock [] -> () - | _ -> writer#write_fake_block func; - end; + writer#write_fake_block func; writer#indent_less; - writer#write_indentation; - writer#write "}" + writer#write_with_indentation "}" (** Writes method declaration (except visibility and `static` keywords) to output buffer *) @@ -3017,7 +3100,49 @@ class virtual type_builder ctx (wrapper:type_wrapper) = writer#write ("function " ^ by_ref ^ name ^ " ("); write_args writer#write writer#write_function_arg func.tf_args; writer#write ") "; - writer#write_expr (inject_defaults ctx func) + if not (self#write_body_if_special_method name) then + writer#write_expr (inject_defaults ctx func) + (** + Writes a body for a special method if `field` represents one. + Returns `true` if `field` is such a method. + *) + method private write_body_if_special_method name = + (* php.Boot.isPhpKeyword(str:String) *) + if self#get_type_path = boot_type_path && name = "isPhpKeyword" then + begin + writer#write "{\n"; + writer#indent_more; + writer#write_line "switch(strtolower($str)) {"; + writer#indent_more; + writer#write_indentation; + let cnt = ref 0 in + List.iter + (fun kwd -> + if !cnt <= 5 then incr cnt + else begin + cnt := 0; + writer#write "\n"; + writer#write_indentation + end; + writer#write ("case '" ^ kwd ^ "': ") + ) + php_keywords_list; + writer#write "\n"; + writer#indent_more; + writer#write_statement "return true"; + writer#indent_less; + writer#write_line "default:"; + writer#indent_more; + writer#write_statement "return false"; + writer#indent_less; + writer#indent_less; + writer#write_line "}"; + writer#indent_less; + writer#write_with_indentation "}"; + true + end + else + false (** Set sourcemap generator *) @@ -3069,22 +3194,29 @@ class enum_builder ctx (enm:tenum) = in writer#indent 1; self#write_doc (DocMethod (args, TEnum (enm, []), field.ef_doc)); - writer#write_indentation; - writer#write ("static public function " ^ name ^ " ("); + writer#write_with_indentation ("static public function " ^ name ^ " ("); write_args writer#write (writer#write_arg true) args; writer#write ") {\n"; writer#indent_more; - writer#write_indentation; - writer#write "return "; let index_str = string_of_int field.ef_index in + let write_construction args = + writer#write ("new " ^ self#get_name ^ "('" ^ name ^ "', " ^ index_str ^", ["); + write_args writer#write (fun (name, _, _) -> writer#write ("$" ^ name)) args; + writer#write "])" + in (match args with - | [] -> writer#write ((writer#use hxenum_type_path) ^ "::singleton(static::class, '" ^ name ^ "', " ^ index_str ^")") + | [] -> + (* writer#write ((writer#use hxenum_type_path) ^ "::singleton(static::class, '" ^ name ^ "', " ^ index_str ^")") *) + writer#write_line "static $inst = null;"; + writer#write_with_indentation "if (!$inst) $inst = "; + write_construction []; + writer#write ";\n"; + writer#write_line "return $inst;" | args -> - writer#write ("new " ^ self#get_name ^ "('" ^ name ^ "', " ^ index_str ^", ["); - write_args writer#write (fun (name, _, _) -> writer#write ("$" ^ name)) args; - writer#write "])" + writer#write_with_indentation "return "; + write_construction args; + writer#write ";\n"; ); - writer#write ";\n"; writer#indent_less; writer#write_line "}" (** @@ -3158,11 +3290,16 @@ class enum_builder ctx (enm:tenum) = class class_builder ctx (cls:tclass) = object (self) inherit type_builder ctx (get_wrapper (TClassDecl cls)) as super + (** + List of methods names uppercased. + Used to check for methods with similar names because PHP function names are case-insensitive. + *) + val mutable used_method_names = [] (** Indicates if type should be declared as `final` *) method is_final = - if not (Meta.has Meta.Final cls.cl_meta) then + if not cls.cl_final then false else begin let hacked = ref false in @@ -3174,17 +3311,17 @@ class class_builder ctx (cls:tclass) = if self#extended_by tcls then hacked := Meta.has Meta.Hack tcls.cl_meta | _ -> () ) - ctx.types; + ctx.pgc_common.types; not !hacked end (** Indicates if `field` should be declared as `final` *) method is_final_field (field:tclass_field) : bool = - Meta.has Meta.Final field.cf_meta + has_class_field_flag field CfFinal (** Check if there is no native php constructor in inheritance chain of this class. - E.g. `StsClass` does have a constructor while still can be called with `new StdClass()`. + E.g. `StdClass` does have a constructor while still can be called with `new StdClass()`. So this method will return true for `MyClass` if `MyClass extends StdClass`. *) method private extends_no_constructor = @@ -3222,8 +3359,8 @@ class class_builder ctx (cls:tclass) = E.g. "class SomeClass extends Another implements IFace" *) method private write_declaration = - if self#is_final then writer#write "final "; self#write_doc (DocClass cls.cl_doc); + if self#is_final then writer#write "final "; writer#write (if cls.cl_interface then "interface " else "class "); writer#write self#get_name; ( @@ -3268,16 +3405,16 @@ class class_builder ctx (cls:tclass) = None else Some { - (mk_field "new" (TFun ([], get_void ctx)) cls.cl_pos cls.cl_pos) with + (mk_field "new" (TFun ([], ctx.pgc_common.basic.tvoid)) cls.cl_pos cls.cl_pos) with cf_kind = Method MethNormal; cf_expr = Some { eexpr = TFunction { tf_args = []; - tf_type = get_void ctx; - tf_expr = { eexpr = TBlock []; epos = cls.cl_pos; etype = get_void ctx; }; + tf_type = ctx.pgc_common.basic.tvoid; + tf_expr = { eexpr = TBlock []; epos = cls.cl_pos; etype = ctx.pgc_common.basic.tvoid; }; }; epos = cls.cl_pos; - etype = get_void ctx; + etype = ctx.pgc_common.basic.tvoid; }; } (** @@ -3355,7 +3492,7 @@ class class_builder ctx (cls:tclass) = Check if this class requires constructor to be generated even if there is no user-defined one *) method private constructor_is_required = - if List.length self#get_namespace > 0 then + if cls.cl_interface || List.length self#get_namespace > 0 then false else begin let required = ref false in @@ -3368,10 +3505,10 @@ class class_builder ctx (cls:tclass) = !required end (** - Writes `--php-prefix` value as class constant PHP_PREFIX + Writes `-D php-prefix` value as class constant PHP_PREFIX *) method private write_php_prefix () = - let prefix = String.concat "\\" (get_php_prefix ctx) in + let prefix = String.concat "\\" ctx.pgc_prefix in let indentation = writer#get_indentation in writer#indent 1; writer#write_statement ("const PHP_PREFIX = \"" ^ (String.escaped prefix) ^ "\""); @@ -3383,8 +3520,7 @@ class class_builder ctx (cls:tclass) = (* `static dynamic function` initialization *) let write_dynamic_method_initialization field = let field_access = "self::$" ^ (field_name field) in - writer#write_indentation; - writer#write (field_access ^ " = "); + writer#write_with_indentation (field_access ^ " = "); (match field.cf_expr with | Some expr -> writer#write_expr expr | None -> fail field.cf_pos __POS__ @@ -3401,15 +3537,14 @@ class class_builder ctx (cls:tclass) = (* `static var` initialization *) let write_var_initialization field = let write_assign expr = - writer#write_indentation; - writer#write ("self::$" ^ (field_name field) ^ " = "); + writer#write_with_indentation ("self::$" ^ (field_name field) ^ " = "); writer#write_expr expr in (* Do not generate fields for RTTI meta, because this generator uses another way to store it. Also skip initialization for `inline var` fields as those are generated as PHP class constants. *) - let is_auto_meta_var = field.cf_name = "__meta__" && (has_rtti_meta ctx wrapper#get_module_type) in + let is_auto_meta_var = field.cf_name = "__meta__" && (has_rtti_meta ctx.pgc_common wrapper#get_module_type) in if (is_var_with_nonconstant_expr field) && (not is_auto_meta_var) && (not (is_inline_var field)) then begin (match field.cf_expr with | None -> () @@ -3440,7 +3575,7 @@ class class_builder ctx (cls:tclass) = | Var { v_read = AccInline; v_write = AccNever } -> self#write_const field | Var _ when is_physical_field field -> (* Do not generate fields for RTTI meta, because this generator uses another way to store it *) - let is_auto_meta_var = is_static && field.cf_name = "__meta__" && (has_rtti_meta ctx wrapper#get_module_type) in + let is_auto_meta_var = is_static && field.cf_name = "__meta__" && (has_rtti_meta ctx.pgc_common wrapper#get_module_type) in if not is_auto_meta_var then self#write_var field is_static; | Var _ -> () | Method MethMacro -> () @@ -3477,14 +3612,14 @@ class class_builder ctx (cls:tclass) = | Some expr -> writer#indent 1; self#write_doc (DocVar (writer#use_t field.cf_type, field.cf_doc)); - writer#write_indentation; - writer#write ("const " ^ (field_name field) ^ " = "); + writer#write_with_indentation ("const " ^ (field_name field) ^ " = "); writer#write_expr expr; writer#write ";\n" (** Writes method to output buffer *) method private write_class_method field is_static = + self#validate_method_name field; writer#reset; writer#indent 1; let (args, return_type) = get_function_signature field in @@ -3510,13 +3645,13 @@ class class_builder ctx (cls:tclass) = Only for non-static methods. Static methods are created as static vars in `__hx__init`. *) method private write_dynamic_method field = + self#validate_method_name field; writer#reset; writer#indent 1; let (args, return_type) = get_function_signature field in List.iter (fun (arg_name, _, _) -> writer#declared_local_var arg_name) args; self#write_doc (DocMethod (args, return_type, field.cf_doc)); - writer#write_indentation; - writer#write ((get_visibility field.cf_meta) ^ " function " ^ (field_name field)); + writer#write_with_indentation ((get_visibility field.cf_meta) ^ " function " ^ (field_name field)); (match field.cf_expr with | None -> (* interface *) writer#write " ("; @@ -3539,6 +3674,15 @@ class class_builder ctx (cls:tclass) = writer#write_statement ("protected $__hx__default__" ^ (field_name field)) | _ -> fail field.cf_pos __POS__ ); + (** + Since PHP function names are case-insensitive we must check for method names clashes. + *) + method private validate_method_name field = + let uppercased_name = StringHelper.uppercase field.cf_name in + if List.exists (fun n -> n = uppercased_name) used_method_names then + ctx.pgc_common.error ("Methods names are case-insensitive in PHP runtime. Cannot redeclare \"" ^ field.cf_name ^ "\".") field.cf_name_pos + else + used_method_names <- uppercased_name :: used_method_names (** Writes initialization code for instances of this class *) @@ -3597,12 +3741,14 @@ class class_builder ctx (cls:tclass) = (** Handles generation process *) -class generator (ctx:context) = +class generator (ctx:php_generator_context) = object (self) val mutable build_dir = "" - val root_dir = ctx.file + val root_dir = ctx.pgc_common.file val mutable init_types = [] val mutable boot : (type_builder * string) option = None + val mutable polyfills_source_path : string option = None + val mutable polyfills_dest_path : string option = None (** Perform required actions before actual php files generation *) @@ -3616,16 +3762,22 @@ class generator (ctx:context) = and name = builder#get_name in let filename = (create_dir_recursive (build_dir :: namespace)) ^ "/" ^ name ^ ".php" in let channel = open_out filename in - if Common.defined ctx Define.SourceMap then + if Common.defined ctx.pgc_common Define.SourceMap then builder#set_sourcemap_generator (new sourcemap_builder filename); output_string channel builder#get_contents; close_out channel; (match builder#get_sourcemap_generator with - | Some smap -> smap#generate ctx + | Some smap -> smap#generate ctx.pgc_common | None -> () ); if builder#get_type_path = boot_type_path then - boot <- Some (builder, filename) + begin + boot <- Some (builder, filename); + let source_dir = Filename.dirname builder#get_source_file in + polyfills_source_path <- Some (Filename.concat source_dir polyfills_file); + let dest_dir = Filename.dirname filename in + polyfills_dest_path <- Some (Filename.concat dest_dir polyfills_file) + end else if builder#has_magic_init then init_types <- (get_full_type_name (namespace, name)) :: init_types (** @@ -3634,6 +3786,9 @@ class generator (ctx:context) = method finalize : unit = self#generate_magic_init; self#generate_entry_point; + match polyfills_source_path, polyfills_dest_path with + | Some src, Some dst -> copy_file src dst + | _ -> fail null_pos __POS__ (** Generates calls to static __init__ methods in Boot.php *) @@ -3642,7 +3797,7 @@ class generator (ctx:context) = | [] -> () | _ -> match boot with - | None -> fail dummy_pos __POS__ + | None -> fail null_pos __POS__ | Some (_, filename) -> let channel = open_out_gen [Open_creat; Open_text; Open_append] 0o644 filename in List.iter @@ -3656,12 +3811,12 @@ class generator (ctx:context) = match self#get_entry_point with | None -> () | Some (uses, entry_point) -> - let filename = Common.defined_value_safe ~default:"index.php" ctx Define.PhpFront in + let filename = Common.defined_value_safe ~default:"index.php" ctx.pgc_common Define.PhpFront in let channel = open_out (root_dir ^ "/" ^ filename) in output_string channel " fail dummy_pos __POS__ + | None -> fail null_pos __POS__ | Some (builder, filename) -> let boot_class = get_full_type_name (add_php_prefix ctx builder#get_type_path) in output_string channel (boot_class ^ "::__hx__init();\n") @@ -3688,13 +3843,13 @@ class generator (ctx:context) = Returns path from `index.php` to directory which will contain all generated classes *) method private get_lib_path : string list = - let path = Common.defined_value_safe ~default:"lib" ctx Define.PhpLib in + let path = Common.defined_value_safe ~default:"lib" ctx.pgc_common Define.PhpLib in (Str.split (Str.regexp "/") path) (** Returns PHP code for entry point *) method private get_entry_point : (string * string) option = - match ctx.main with + match ctx.pgc_common.main with | None -> None | Some expr -> let writer = new code_writer ctx ([], "") "" in @@ -3706,19 +3861,43 @@ class generator (ctx:context) = Some (uses, code) end +(** + @return `tclass` instance for `php.Boot` +*) +let get_boot com : tclass = + let find com_type = + match com_type with + | TClassDecl { cl_path = path } -> path = boot_type_path + | _ -> false + in + try + match List.find find com.types with + | TClassDecl cls -> cls + | _ -> raise Not_found + with + | Not_found -> fail ~msg:"php.Boot not found" null_pos __POS__ + (** Entry point to Genphp7 *) let generate (com:context) = - skip_line_directives := Common.defined com Define.RealPosition; - let gen = new generator com in + let ctx = + { + pgc_common = com; + pgc_skip_line_directives = Common.defined com Define.RealPosition; + pgc_prefix = Str.split (Str.regexp "\\.") (Common.defined_value_safe com Define.PhpPrefix); + pgc_boot = get_boot com; + pgc_namespaces_types_cache = Hashtbl.create 512 + } + in + let gen = new generator ctx in gen#initialize; let rec generate com_type = let wrapper = get_wrapper com_type in if wrapper#needs_generation then (match com_type with - | TClassDecl cls -> gen#generate (new class_builder com cls); - | TEnumDecl enm -> gen#generate (new enum_builder com enm); + | TClassDecl cls -> gen#generate (new class_builder ctx cls); + | TEnumDecl enm -> gen#generate (new enum_builder ctx enm); | TTypeDecl typedef -> (); | TAbstractDecl abstr -> () ); diff --git a/src/generators/genpy.ml b/src/generators/genpy.ml index 0300aa6a236..029239d90eb 100644 --- a/src/generators/genpy.ml +++ b/src/generators/genpy.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,7 +21,7 @@ open Globals open Ast open Type open Common -open Codegen.ExprBuilder +open Texpr.Builder module Utils = struct let class_of_module_type mt = match mt with @@ -68,7 +68,7 @@ module KeywordHandler = struct let kwds = let h = Hashtbl.create 0 in List.iter (fun s -> Hashtbl.add h s ()) [ - "and"; "as"; "assert"; "break"; "class"; "continue"; "def"; "del"; "elif"; "else"; "except"; "exec"; "finally"; "for"; + "and"; "as"; "assert"; "async"; "await"; "break"; "class"; "continue"; "def"; "del"; "elif"; "else"; "except"; "exec"; "finally"; "for"; "from"; "global"; "if"; "import"; "in"; "is"; "lambda"; "not"; "or"; "pass"; " raise"; "return"; "try"; "while"; "with"; "yield"; "None"; "True"; "False"; ]; @@ -174,6 +174,8 @@ module Transformer = struct let lift_expr1 is_value next_id blocks e = lift_expr ~is_value:is_value ~next_id:(Some next_id) ~blocks:blocks e + let alloc_var = Type.alloc_var VGenerated + let to_tvar ?(capture = false) n t p = alloc_var n t p (* { v_name = n; v_type = t; v_id = 0; v_capture = capture; v_extra = None; v_meta = [] } *) @@ -217,6 +219,39 @@ module Transformer = struct e_set_field; ]) e_set_field.etype e_set_field.epos + let dynamic_field_inc_dec next_id e1 s unop unop_flag t p = + let is_post_fix = match unop_flag with + | Postfix -> true + | Prefix -> false + in + let op = match unop with + | Increment -> OpAdd + | Decrement -> OpSub + | _ -> assert false + in + let one = mk (TConst(TInt(Int32.of_int(1)))) t p in + + let temp_var = to_tvar (next_id()) e1.etype e1.epos in + let temp_var_def = mk (TVar(temp_var,Some e1)) e1.etype e1.epos in + let temp_local = mk (TLocal temp_var) e1.etype e1.epos in + + let e_field = dynamic_field_read temp_local s t in + + let prior_val_var = to_tvar (next_id()) t p in + let prior_val_var_def = mk (TVar(prior_val_var, Some e_field )) t p in + let prior_val_local = mk (TLocal prior_val_var) t p in + + let e_value = mk (TBinop(op, prior_val_local, one)) t e1.epos in + let e_ret = if is_post_fix then prior_val_local else e_value in + + let e_set_field = dynamic_field_write temp_local s e_value in + mk (TBlock [ + temp_var_def; + prior_val_var_def; + e_set_field; + e_ret; + ]) e_set_field.etype e_set_field.epos + let add_non_locals_to_func e = match e.eexpr with | TFunction tf -> let cur = ref PMap.empty in @@ -277,13 +312,13 @@ module Transformer = struct let assigns = List.fold_left (fun acc (v,value) -> KeywordHandler.check_var_declaration v; match value with - | None | Some TNull -> + | None | Some {eexpr = TConst TNull} -> acc | Some ct -> let a_local = mk (TLocal v) v.v_type p in let a_null = mk (TConst TNull) v.v_type p in let a_cmp = mk (TBinop(OpEq,a_local,a_null)) !t_bool p in - let a_value = mk (TConst(ct)) v.v_type p in + let a_value = ct in let a_assign = mk (TBinop(OpAssign,a_local,a_value)) v.v_type p in let a_if = mk (TIf(a_cmp,a_assign,None)) !t_void p in a_if :: acc @@ -430,7 +465,7 @@ module Transformer = struct let mk_or e1 e2 = mk (TBinop(OpOr,e1,e2)) !t_bool (punion e1.epos e2.epos) in let mk_if (el,e) eo = let eif = List.fold_left (fun eacc e -> mk_or eacc (mk_eq e1 e)) (mk_eq e1 (List.hd el)) (List.tl el) in - mk (TIf(Codegen.mk_parent eif,e,eo)) e.etype e.epos + mk (TIf(mk_parent eif,e,eo)) e.etype e.epos in let cases = Hashtbl.fold (fun i el acc -> let eint = mk (TConst (TInt (Int32.of_int i))) !t_int e1.epos in @@ -814,15 +849,13 @@ module Transformer = struct | (is_value, TBinop(OpAssignOp op,{eexpr = TField(e1,FAnon cf); etype = t},e2)) when Meta.has Meta.Optional cf.cf_meta -> let e = dynamic_field_read_write ae.a_next_id e1 cf.cf_name op e2 t in transform_expr ~is_value:is_value e - (* TODO we need to deal with Increment, Decrement too! - | (_, TUnop( (Increment | Decrement) as unop, op,{eexpr = TField(e1,FAnon cf)})) when Meta.has Meta.Optional cf.cf_meta -> - let = dynamic_field_read e cf.cf_name in - - let e = dynamic_field_read_write_unop ae.a_next_id e1 cf.cf_name unop op in - Printf.printf "dyn read write\n"; - transform_expr e - *) + | (is_value, TUnop( (Increment | Decrement) as unop, unop_flag,{eexpr = TField(e1, FAnon cf); etype = t; epos = p})) when Meta.has Meta.Optional cf.cf_meta -> + let e = dynamic_field_inc_dec ae.a_next_id e1 cf.cf_name unop unop_flag t p in + transform_expr ~is_value:is_value e + | (is_value, TUnop( (Increment | Decrement) as unop, unop_flag,{eexpr = TField(e1, FDynamic field_name); etype = t; epos = p})) -> + let e = dynamic_field_inc_dec ae.a_next_id e1 field_name unop unop_flag t p in + transform_expr ~is_value:is_value e (* anon field access with non optional members like iterator, length, split must be handled too, we need to Reflect on them too when it's a runtime method *) @@ -1056,7 +1089,7 @@ module Printer = struct | OpInterval | OpArrow | OpIn | OpAssignOp _ -> assert false let print_string s = - Printf.sprintf "\"%s\"" (Ast.s_escape s) + Printf.sprintf "\"%s\"" (StringHelper.s_escape s) let print_constant = function | TThis -> "self" @@ -1089,7 +1122,7 @@ module Printer = struct | TMeta(_,e) -> remove_outer_parens e | _ -> e - let print_args args p = + let rec print_args pctx args p = let had_value = ref false in let had_var_args = ref false in let had_kw_args = ref false in @@ -1112,11 +1145,11 @@ module Printer = struct | None -> "" | Some ct -> had_value := true; - Printf.sprintf " = %s" (print_constant ct) + " = None" ) args in String.concat "," sl - let rec print_op_assign_right pctx e = + and print_op_assign_right pctx e = match e.eexpr with | TIf({eexpr = TParenthesis econd},eif,Some eelse) | TIf(econd,eif,Some eelse) -> @@ -1140,7 +1173,7 @@ module Printer = struct | None -> pctx.pc_next_anon_func() | Some s -> handle_keywords s in - let s_args = print_args tf.tf_args p in + let s_args = print_args pctx tf.tf_args p in let s_expr = print_expr {pctx with pc_indent = " " ^ pctx.pc_indent} tf.tf_expr in Printf.sprintf "def %s(%s):\n%s %s" s_name s_args pctx.pc_indent s_expr @@ -1261,6 +1294,10 @@ module Printer = struct Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (fst ops) (print_expr pctx e2) | x, _ when is_underlying_array x -> Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (fst ops) (print_expr pctx e2) + | TInst({ cl_kind = KTypeParameter(_) }, _), _ -> + Printf.sprintf "%s(%s,%s)" (third ops) (print_expr pctx e1) (print_expr pctx e2) + | _, TInst({ cl_kind = KTypeParameter(_) }, _) -> + Printf.sprintf "%s(%s,%s)" (third ops) (print_expr pctx e1) (print_expr pctx e2) | TDynamic _, TDynamic _ -> Printf.sprintf "%s(%s,%s)" (third ops) (print_expr pctx e1) (print_expr pctx e2) | TDynamic _, x when is_list_or_anon x -> @@ -1426,6 +1463,8 @@ module Printer = struct Printf.sprintf "len(%s)" (print_expr pctx e1) | FInstance(c,_,{cf_name = "length"}) when (is_type "" "str")(TClassDecl c) -> Printf.sprintf "len(%s)" (print_expr pctx e1) + | FAnon({cf_name = "length"}) | FDynamic ("length") -> + Printf.sprintf "HxOverrides.length(%s)" (print_expr pctx e1) | FStatic(c,{cf_name = "fromCharCode"}) when (is_type "" "str")(TClassDecl c) -> Printf.sprintf "HxString.fromCharCode" | FStatic({cl_path = ["python";"internal"],"UBuiltins"},{cf_name = s}) -> @@ -1451,7 +1490,7 @@ module Printer = struct do_default() and print_try pctx e1 catches = - let has_catch_all = List.exists (fun (v,_) -> match v.v_type with + let has_catch_all = List.exists (fun (v,_) -> match follow v.v_type with | TDynamic _ -> true | _ -> false ) catches in @@ -1469,13 +1508,16 @@ module Printer = struct let assign = if is_empty_expr then "" else Printf.sprintf "%s = _hx_e1\n%s" v.v_name indent in let handle_base_type bt = let t = print_base_type bt in + let print_custom_check t_str = + Printf.sprintf "if %s:\n%s %s %s" t_str indent assign (print_expr {pctx with pc_indent = " " ^ pctx.pc_indent} e) + in let print_type_check t_str = - Printf.sprintf "if isinstance(_hx_e1, %s):\n%s %s %s" t_str indent assign (print_expr {pctx with pc_indent = " " ^ pctx.pc_indent} e) + print_custom_check ("isinstance(_hx_e1, " ^ t_str ^ ")") in let res = match t with | "str" -> print_type_check "str" | "Bool" -> print_type_check "bool" - | "Int" -> print_type_check "int" + | "Int" -> print_custom_check "(isinstance(_hx_e1, int) and not isinstance(_hx_e1, bool))" (* for historic reasons bool extends int *) | "Float" -> print_type_check "float" | t -> print_type_check t in @@ -1521,7 +1563,8 @@ module Printer = struct | "super",_ -> let s_el = (print_call_args pctx e1 el) in Printf.sprintf "super().__init__(%s)" s_el - | ("python_Syntax._pythonCode"),[({ eexpr = TConst (TString code) } as ecode); {eexpr = TArrayDecl tl}] -> + | ("python_Syntax._pythonCode"),[({ eexpr = TConst (TString code) } as ecode); {eexpr = TArrayDecl tl}] + | ("python_Syntax.code"),({ eexpr = TConst (TString code) } as ecode) :: tl -> let buf = Buffer.create 0 in let interpolate () = Codegen.interpolate_code pctx.pc_com code tl (Buffer.add_string buf) (fun e -> Buffer.add_string buf (print_expr pctx e)) ecode.epos @@ -1532,6 +1575,12 @@ module Printer = struct Buffer.contents buf | ("python_Syntax._pythonCode"), [e] -> print_expr pctx e + | ("python_Syntax.code"), [e] -> + (match e.eexpr with + | TConst (TString py) -> () + | _ -> pctx.pc_com.error "First argument of python.Syntax.code() must be a constant string." e1.epos + ); + print_expr pctx e | "python_Syntax._callNamedUntyped",el -> let res,fields = match List.rev el with | {eexpr = TObjectDecl fields} :: el -> @@ -1575,8 +1624,14 @@ module Printer = struct Printf.sprintf "%s = %s" (print_expr pctx e0) (print_expr pctx e1) | "python_Syntax.arraySet",[e1;e2;e3] -> Printf.sprintf "%s[%s] = %s" (print_expr pctx e1) (print_expr pctx e2) (print_expr pctx e3) - | "python_Syntax._newInstance", e1 :: [{eexpr = TArrayDecl el}] -> - Printf.sprintf "%s(%s)" (print_expr pctx e1) (print_exprs pctx ", " el) + | "python_Syntax._newInstance", e1 :: [{eexpr = TArrayDecl el}] + | "python_Syntax.construct", e1 :: el -> + let cls = + match e1.eexpr with + | TConst (TString class_name) -> class_name + | _ -> print_expr pctx e1 + in + Printf.sprintf "%s(%s)" cls (print_exprs pctx ", " el) | "python_Syntax.opPow", [e1;e2] -> Printf.sprintf "(%s ** %s)" (print_expr pctx e1) (print_expr pctx e2) | "python_Syntax._foreach",[e1;e2;e3] -> @@ -1616,7 +1671,7 @@ module Printer = struct "print(" ^ (print_expr pctx e) ^ ")" else "print(str(" ^ (print_expr pctx e) ^ "))" - | TField(e1,((FAnon {cf_name = (("join" | "push" | "map" | "filter") as s)}) | FDynamic (("join" | "push" | "map" | "filter") as s))), [x] -> + | TField(e1,((FAnon {cf_name = (("split" | "join" | "push" | "map" | "filter") as s)}) | FDynamic (("split" | "join" | "push" | "map" | "filter") as s))), [x] -> Printf.sprintf "HxOverrides.%s(%s, %s)" s (print_expr pctx e1) (print_expr pctx x) | TField(e1,((FAnon {cf_name = (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s)}) | FDynamic (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s))), [] -> Printf.sprintf "HxOverrides.%s(%s)" s (print_expr pctx e1) @@ -1683,7 +1738,7 @@ module Printer = struct print_exprs pctx sep el and print_exprs_named pctx sep fl = - let args = String.concat sep (List.map (fun ((s,_,_),e) -> Printf.sprintf "'%s': %s" (Ast.s_escape (handle_keywords s)) (print_expr pctx e)) fl) in + let args = String.concat sep (List.map (fun ((s,_,_),e) -> Printf.sprintf "'%s': %s" (StringHelper.s_escape (handle_keywords s)) (print_expr pctx e)) fl) in Printf.sprintf "{%s}" args and print_params_named pctx sep fl = let args = String.concat sep (List.map (fun ((s,_,_),e) -> Printf.sprintf "%s= %s" (handle_keywords s) (print_expr pctx e)) fl) in @@ -1847,7 +1902,7 @@ module Generator = struct | e_last :: el -> let new_last = {e_last with eexpr = TReturn (Some e_last)} in let new_block = {expr2 with eexpr = TBlock (List.rev (new_last :: el))} in - let v_name = alloc_var name (tfun [] e_last.etype) e_last.epos in + let v_name = alloc_var VGenerated name (tfun [] e_last.etype) e_last.epos in let f_name = mk (TLocal v_name) v_name.v_type e_last.epos in let call_f = mk (TCall(f_name,[])) e_last.etype e_last.epos in Some new_block,call_f @@ -1868,7 +1923,7 @@ module Generator = struct | None,e2 -> let expr_string_2 = texpr_str e2 pctx in if field = "" then - spr ctx expr_string_2 + print ctx "%s%s" indent expr_string_2 else print ctx "%s%s = %s" indent field expr_string_2 @@ -1877,7 +1932,7 @@ module Generator = struct let e = match e.eexpr with | TFunction(f) -> let args = if add_self then - let v = alloc_var "self" t_dynamic p in + let v = alloc_var VGenerated "self" t_dynamic p in v.v_meta <- (Meta.This,[],p) :: v.v_meta; (v,None) :: f.tf_args else @@ -2072,6 +2127,10 @@ module Generator = struct use_pass := false; print ctx "\n _hx_class_name = \"%s\"" p_name end; + if has_feature ctx "python._hx_is_interface" then begin + let value = if c.cl_interface then "True" else "False" in + print ctx "\n _hx_is_interface = \"%s\"" value + end; let print_field names field quote = if has_feature ctx ("python." ^ field) then try @@ -2097,7 +2156,6 @@ module Generator = struct ) c.cl_ordered_fields in let field_names = List.map (fun f -> handle_keywords f.cf_name) real_fields in - let field_names = match c.cl_dynamic with Some _ -> "__dict__" :: field_names | None -> field_names in use_pass := false; print ctx "\n __slots__ = ("; (match field_names with @@ -2153,7 +2211,7 @@ module Generator = struct gen_class_init ctx c let gen_enum_metadata ctx en p = - let meta = Codegen.build_metadata ctx.com (TEnumDecl en) in + let meta = Texpr.build_metadata ctx.com.basic (TEnumDecl en) in match meta with | None -> () @@ -2193,10 +2251,14 @@ module Generator = struct List.iter (fun ef -> match follow ef.ef_type with | TFun(args, _) -> + let arg_name hx_name = + let name = handle_keywords hx_name in + if name = p_name then p_name ^ "_" ^ name + else name + in let print_args args = let had_optional = ref false in let sl = List.map (fun (n,o,_) -> - let name = handle_keywords n in let arg_value = if !had_optional then "= None" else if o then begin @@ -2205,17 +2267,21 @@ module Generator = struct end else "" in - Printf.sprintf "%s%s" name arg_value + Printf.sprintf "%s%s" (arg_name n) arg_value ) args in String.concat "," sl in let f = handle_keywords ef.ef_name in let param_str = print_args args in - let args_str = String.concat "," (List.map (fun (n,_,_) -> handle_keywords n) args) in + let args_str = + match args with + | [(n,_,_)] -> (arg_name n) ^ "," + | args -> String.concat "," (List.map (fun (n,_,_) -> arg_name n) args) + in newline ctx; newline ctx; print ctx " @staticmethod\n def %s(%s):\n" f param_str; - print ctx " return %s(\"%s\", %i, [%s])" p ef.ef_name ef.ef_index args_str; + print ctx " return %s(\"%s\", %i, (%s))" p ef.ef_name ef.ef_index args_str; | _ -> assert false ) param_constructors; @@ -2223,7 +2289,7 @@ module Generator = struct (* TODO: haxe source has api.quoteString for ef.ef_name *) let f = handle_keywords ef.ef_name in newline ctx; - print ctx "%s.%s = %s(\"%s\", %i, list())" p f p ef.ef_name ef.ef_index + print ctx "%s.%s = %s(\"%s\", %i, ())" p f p ef.ef_name ef.ef_index ) const_constructors; if has_feature ctx "python._hx_class" then print ctx "\n%s._hx_class = %s" p p; @@ -2283,7 +2349,7 @@ module Generator = struct "," in let k_enc = Codegen.escape_res_name k false in - print ctx "%s\"%s\": open('%%s.%%s'%%(_file,'%s'),'rb').read()" prefix (Ast.s_escape k) k_enc; + print ctx "%s\"%s\": open('%%s.%%s'%%(_file,'%s'),'rb').read()" prefix (StringHelper.s_escape k) k_enc; let f = open_out_bin (ctx.com.file ^ "." ^ k_enc) in output_string f v; @@ -2369,8 +2435,25 @@ module Generator = struct newline ctx; spr ctx "class _hx_AnonObject:\n"; if with_body then begin + spr ctx " _hx_disable_getattr = False\n"; spr ctx " def __init__(self, fields):\n"; - spr ctx " self.__dict__ = fields" + spr ctx " self.__dict__ = fields\n"; + spr ctx " def __repr__(self):\n"; + spr ctx " return repr(self.__dict__)\n"; + spr ctx " def __getattr__(self, name):\n"; + spr ctx " if (self._hx_disable_getattr):\n"; + spr ctx " raise AttributeError('field does not exist')\n"; + spr ctx " else:\n"; + spr ctx " return None\n"; + spr ctx " def _hx_hasattr(self,field):\n"; + spr ctx " self._hx_disable_getattr = True\n"; + spr ctx " try:\n"; + spr ctx " getattr(self, field)\n"; + spr ctx " self._hx_disable_getattr = False\n"; + spr ctx " return True\n"; + spr ctx " except AttributeError:\n"; + spr ctx " self._hx_disable_getattr = False\n"; + spr ctx " return False\n" end else spr ctx " pass"; Hashtbl.add used_paths ([],"_hx_AnonObject") true; @@ -2411,7 +2494,7 @@ module Generator = struct | TBlock el -> List.iter (fun e -> gen_expr ctx e "" ""; newline ctx) el | _ -> - gen_expr ctx e "" "" + gen_expr ctx e "" ""; newline ctx (* Entry point *) @@ -2420,7 +2503,10 @@ module Generator = struct let ctx = mk_context com in Codegen.map_source_header com (fun s -> print ctx "# %s\n# coding: utf-8\n" s); if has_feature ctx "closure_Array" || has_feature ctx "closure_String" then - spr ctx "from functools import partial as _hx_partial"; + spr ctx "from functools import partial as _hx_partial\n"; + spr ctx "import sys\n"; + spr ctx "if sys.stdout.encoding != 'utf-8':\n sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8', buffering=1)\n"; + spr ctx "if sys.stderr.encoding != 'utf-8':\n sys.stderr = open(sys.stderr.fileno(), mode='w', encoding='utf8', buffering=1)\n\n"; gen_imports ctx; gen_resources ctx; gen_types ctx; @@ -2428,7 +2514,7 @@ module Generator = struct gen_static_inits ctx; gen_main ctx; - mkdir_from_path com.file; + Path.mkdir_from_path com.file; let ch = open_out_bin com.file in output_string ch (Buffer.contents ctx.buf); close_out ch diff --git a/src/generators/genswf.ml b/src/generators/genswf.ml index 7216f01b202..aa24fa187fc 100644 --- a/src/generators/genswf.ml +++ b/src/generators/genswf.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -24,6 +24,7 @@ open Type open Common open Ast open Globals +open NativeLibraries let tag ?(ext=false) d = { tid = 0; @@ -74,7 +75,7 @@ let build_dependencies t = (match c.cl_kind with KTypeParameter _ -> () | _ -> add_path c.cl_path DKType); List.iter (add_type_rec (t::l)) pl; | TAbstract (a,pl) -> - if Meta.has Meta.CoreType a.a_meta then + if a.a_path <> ([],"Null") && Meta.has Meta.CoreType a.a_meta then add_path a.a_path DKType; List.iter (add_type_rec (t::l)) pl; | TFun (pl,t2) -> @@ -116,6 +117,9 @@ let build_dependencies t = | None -> () | Some e -> add_expr e end + | TArray ({ eexpr = TIdent "__global__" },{ eexpr = TConst (TString s) }) -> + let path = parse_path s in + add_path path DKExpr; | _ -> Type.iter add_expr e and add_field f = @@ -246,7 +250,7 @@ let build_swf9 com file swc = hls_fields = [|f|]; } ) code in - [tag (TActionScript3 ((if Common.defined com Define.SwfUseDoAbc then Some(1,boot_name) else None), As3hlparse.flatten inits))] + [tag (TActionScript3 ((Some (1,boot_name)), As3hlparse.flatten inits))] ) in let cid = ref 0 in let classes = ref [{ f9_cid = None; f9_classname = boot_name }] in @@ -273,12 +277,14 @@ let build_swf9 com file swc = let ttf = try TTFParser.parse ch with e -> abort ("Error while parsing font " ^ file ^ " : " ^ Printexc.to_string e) p in close_in ch; let get_string e = match fst e with - | EConst (String s) -> Some s + | EConst (String s) -> s | _ -> raise Not_found in let ttf_config = { ttfc_range_str = ""; ttfc_font_name = None; + ttfc_font_weight = TFWRegular; + ttfc_font_posture = TFPNormal; } in begin match args with | (EConst (String str),_) :: _ -> ttf_config.ttfc_range_str <- str; @@ -288,8 +294,19 @@ let build_swf9 com file swc = | _ :: [e] -> begin match fst e with | EObjectDecl fl -> - begin try ttf_config.ttfc_font_name <- get_string (Expr.field_assoc "fontName" fl) - with Not_found -> () end + (try ttf_config.ttfc_font_name <- Some(get_string (Expr.field_assoc "fontName" fl)) with Not_found -> ()); + (try ttf_config.ttfc_font_weight <- ( + match get_string (Expr.field_assoc "fontWeight" fl) with + | "regular" -> TFWRegular + | "bold" -> TFWBold + | _ -> abort "Invalid fontWeight value. Must be `regular` or `bold`." p + ) with Not_found -> ()); + (try ttf_config.ttfc_font_posture <- ( + match get_string (Expr.field_assoc "fontStyle" fl) with + | "normal" -> TFPNormal + | "italic" -> TFPItalic + | _ -> abort "Invalid fontStyle value. Must be `normal` or `italic`." p + ) with Not_found -> ()); | _ -> () end @@ -554,8 +571,8 @@ let generate swf_header com = (* list exports *) let exports = Hashtbl.create 0 in let toremove = ref [] in - List.iter (fun (file,lib,_) -> - let _, tags = lib() in + List.iter (fun swf_lib -> + let _, tags = swf_lib#get_data in List.iter (fun t -> match t.tdata with | TExport l -> List.iter (fun e -> Hashtbl.add exports e.exp_name ()) l @@ -581,7 +598,7 @@ let generate swf_header com = ) el | _ -> () ) tags; - ) com.swf_libs; + ) com.native_libs.swf_libs; (* build haxe swf *) let tags = build_swf9 com file swc in let header, bg = (match swf_header with None -> default_header com | Some h -> convert_header com h) in @@ -622,11 +639,11 @@ let generate swf_header com = let swf = header, fattr @ meta_data @ bg :: scene :: debug @ swf_script_limits @ tags @ [tag TShowFrame] in (* merge swf libraries *) let priority = ref (swf_header = None) in - let swf = List.fold_left (fun swf (file,lib,cl) -> - let swf = merge com file !priority swf (SwfLoader.remove_classes toremove lib cl) in + let swf = List.fold_left (fun swf swf_lib -> + let swf = merge com file !priority swf (SwfLoader.remove_classes toremove swf_lib#get_data swf_lib#list_modules) in priority := false; swf - ) swf com.swf_libs in + ) swf com.native_libs.swf_libs in let swf = match swf with | header,tags when Common.defined com Define.SwfPreloaderFrame -> let rec loop l = @@ -638,7 +655,7 @@ let generate swf_header com = {header with h_frame_count = header.h_frame_count + 1},loop tags | _ -> swf in (* write swf/swc *) - let t = Common.timer ["write";"swf"] in + let t = Timer.timer ["write";"swf"] in let level = (try int_of_string (Common.defined_value com Define.SwfCompressLevel) with Not_found -> 9) in SwfParser.init Extc.input_zip (Extc.output_zip ~level); (match swc with diff --git a/src/generators/genswf9.ml b/src/generators/genswf9.ml index e52c9da7d55..66126c7ff2c 100644 --- a/src/generators/genswf9.ml +++ b/src/generators/genswf9.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -23,6 +23,7 @@ open Type open As3 open As3hl open Common +open FlashProps type read = Read type write = Unused__ | Write @@ -199,7 +200,6 @@ let rec follow_basic t = | TAbstract ({ a_path = ([],"Bool") },[]) | TInst ({ cl_path = (["haxe"],"Int32") },[]) -> t | t -> t) - | TType ({ t_path = ["flash";"utils"],"Object" },[]) | TType ({ t_path = ["flash";"utils"],"Function" },[]) | TType ({ t_path = [],"UInt" },[]) -> t @@ -230,6 +230,8 @@ let rec type_id ctx t = type_path ctx c.cl_path) | TAbstract ({ a_path = [],"Null"},_) -> HMPath ([],"Object") + | TAbstract ({ a_path = ["flash"],"AnyType"},_) -> + HMAny | TAbstract (a,_) when Meta.has Meta.CoreType a.a_meta -> type_path ctx a.a_path | TFun _ | TType ({ t_path = ["flash";"utils"],"Function" },[]) -> @@ -239,12 +241,7 @@ let rec type_id ctx t = | TEnum ({ e_path = ["flash"],"XmlType"; e_extern = true },_) -> HMPath ([],"String") | TEnum (e,_) -> - let rec loop = function - | [] -> type_path ctx e.e_path - | (Meta.FakeEnum,[Ast.EConst (Ast.Ident n),_],_) :: _ -> type_path ctx ([],n) - | _ :: l -> loop l - in - loop e.e_meta + type_path ctx e.e_path | _ -> HMPath ([],"Object") @@ -268,20 +265,12 @@ let classify ctx t = KBool | TAbstract ({ a_path = [],"Void" },_) | TEnum ({ e_path = [],"Void" },_) -> KDynamic + | TAbstract ({ a_path = ["flash"],"AnyType" },_) -> + KDynamic | TEnum ({ e_path = ["flash"],"XmlType"; e_extern = true },_) -> KType (HMPath ([],"String")) | TEnum (e,_) -> - let rec loop = function - | [] -> KType (type_id ctx t) - | (Meta.FakeEnum,[Ast.EConst (Ident n),_],_) :: _ -> - (match n with - | "Int" -> KInt - | "UInt" -> KUInt - | "String" -> KType (HMPath ([],"String")) - | _ -> assert false) - | _ :: l -> loop l - in - loop e.e_meta + KType (type_id ctx t) | TAbstract ({ a_path = [],"UInt" },_) | TType ({ t_path = [],"UInt" },_) -> KUInt | TFun _ | TType ({ t_path = ["flash";"utils"],"Function" },[]) -> @@ -290,7 +279,7 @@ let classify ctx t = (match !(a.a_status) with | Statics _ -> KNone | _ -> KDynamic) - | TType ({ t_path = ["flash";"utils"],"Object" },[]) -> + | TAbstract ({ a_path = ["flash";"utils"],"Object" },[]) -> KType (HMPath ([],"Object")) | TInst _ | TAbstract _ -> KType (type_id ctx t) @@ -313,13 +302,40 @@ let ident i = let as3 p = HMName (p,HNNamespace "http://adobe.com/AS3/2006/builtin") -let property ctx p t = +let make_class_ns c = + match c.cl_path with + | [], n -> n + | p, n -> String.concat "." p ^ ":" ^ n + +let is_cf_protected cf = Meta.has Meta.Protected cf.cf_meta + +let ns_access cf = + try + let (_,params,_) = Meta.get Meta.Ns cf.cf_meta in + match params with + | [(EConst (String ns),_)] -> + Some (HMName (cf.cf_name, HNNamespace ns)) + | [(EConst (String ns),_); (EConst (Ident "internal"),_)] -> + Some (HMName (cf.cf_name, HNInternal (Some ns))) + | _ -> assert false + with Not_found -> + None + +let property ctx fa t = + match Option.map_default ns_access None (extract_field fa) with + | Some n -> n, None, false + | None -> + match fa with + | FStatic (c, cf) when is_cf_protected cf -> + HMName (reserved cf.cf_name, HNStaticProtected (Some (make_class_ns c))), None, false + | _ -> + let p = field_name fa in match follow t with | TInst ({ cl_path = [],"Array" },_) -> (match p with | "length" -> ident p, Some KInt, false (* UInt in the spec *) | "map" | "filter" when Common.defined ctx.com Define.NoFlashOverride -> ident (p ^ "HX"), None, true - | "copy" | "insert" | "remove" | "iterator" | "toString" | "map" | "filter" -> ident p , None, true + | "copy" | "insert" | "remove" | "iterator" | "toString" | "map" | "filter" | "resize" -> ident p , None, true | _ -> as3 p, None, false); | TInst ({ cl_path = ["flash"],"Vector" },_) -> (match p with @@ -364,7 +380,7 @@ let property ctx p t = in (try let c = loop c in - let ns = HMName (reserved p, HNNamespace (match c.cl_path with [],n -> n | l,n -> String.concat "." l ^ ":" ^ n)) in + let ns = HMName (reserved p, HNNamespace (make_class_ns c)) in ns, None, false with Not_found | Exit -> ident p, None, false) @@ -372,6 +388,19 @@ let property ctx p t = | _ -> ident p, None, false +let this_property fa = + match fa with + | FInstance (c,_,cf) | FClosure (Some (c,_),cf) -> + if is_cf_protected cf then + HMName (reserved cf.cf_name, HNProtected (make_class_ns c)) + else begin + match ns_access cf with + | Some n -> n + | None -> ident (field_name fa) + end + | _ -> + ident (field_name fa) + let default_infos() = { ipos = 0; @@ -511,7 +540,7 @@ let rec setvar ctx (acc : write access) kret = set_reg_dup ctx r else set_reg ctx r; - | VGlobal _ | VId _ | VCast _ | VArray | VScope _ when kret <> None -> + | VGlobal _ | VId _ | VCast _ | VArray | VScope _ | VSuper _ when kret <> None -> let r = alloc_reg ctx (match kret with None -> assert false | Some k -> k) in set_reg_dup ctx r; setvar ctx acc None; @@ -672,6 +701,9 @@ let end_fun ctx args dparams tret = hlmt_function = None; } +let gen_expr_ref = ref (fun _ _ _ -> assert false) +let gen_expr ctx e retval = (!gen_expr_ref) ctx e retval + let begin_fun ctx args tret el stat p = let old_locals = ctx.locals in let old_code = ctx.code in @@ -708,18 +740,18 @@ let begin_fun ctx args tret el stat p = let v = (match classify ctx t, c with | _, None -> HVNone | (KInt | KFloat | KUInt | KBool) as kind, Some c -> - (match c with - | TInt i -> if kind = KUInt then HVUInt i else HVInt i - | TFloat s -> HVFloat (float_of_string s) - | TBool b -> HVBool b - | TNull -> abort ("In Flash9, null can't be used as basic type " ^ s_type (print_context()) t) p + (match c.eexpr with + | TConst (TInt i) -> if kind = KUInt then HVUInt i else HVInt i + | TConst (TFloat s) -> HVFloat (float_of_string s) + | TConst (TBool b) -> HVBool b + | TConst TNull -> abort ("In Flash9, null can't be used as basic type " ^ s_type (print_context()) t) p | _ -> assert false) - | _, Some TNull -> HVNone + | _, Some {eexpr = TConst TNull} -> HVNone | k, Some c -> write ctx (HReg r.rid); write ctx HNull; let j = jump ctx J3Neq in - gen_constant ctx c t p; + gen_expr ctx true c; coerce ctx k; write ctx (HSetReg r.rid); j(); @@ -867,18 +899,13 @@ let pop_value ctx retval = branch value *) if retval then ctx.infos.istack <- ctx.infos.istack - 1 -let gen_expr_ref = ref (fun _ _ _ -> assert false) -let gen_expr ctx e retval = (!gen_expr_ref) ctx e retval - let rec gen_access ctx e (forset : 'a) : 'a access = match e.eexpr with | TLocal v -> gen_local_access ctx v e.epos forset - | TField ({ eexpr = TConst TSuper } as e1,f) -> - let f = field_name f in - let id, _, _ = property ctx f e1.etype in + | TField ({ eexpr = TConst TSuper },f) -> write ctx HThis; - VSuper id + VSuper (this_property f) | TEnumParameter (e1,_,i) -> gen_expr ctx true e1; write ctx (HGetProp (ident "params")); @@ -888,13 +915,17 @@ let rec gen_access ctx e (forset : 'a) : 'a access = gen_expr ctx true e1; VId (ident "index") | TField (e1,fa) -> - let f = field_name fa in - let id, k, closure = property ctx f e1.etype in + let id, k, closure = + match e1.eexpr with + | TConst (TThis | TSuper) when not ctx.in_static -> + let id = this_property fa in + write ctx (HFindProp id); + id, None, false + | _ -> + gen_expr ctx true e1; + property ctx fa e1.etype + in if closure && not ctx.for_call then abort "In Flash9, this method cannot be accessed this way : please define a local function" e1.epos; - (match e1.eexpr with - | TConst (TThis|TSuper) when not ctx.in_static -> - write ctx (HFindProp id) - | _ -> gen_expr ctx true e1); (match k with | Some t -> VCast (id,t) | None -> @@ -902,14 +933,17 @@ let rec gen_access ctx e (forset : 'a) : 'a access = | _ , TFun _ when not ctx.for_call -> VCast(id,classify ctx e.etype) | TEnum _, _ -> VId id | TInst (_,tl), et -> - let is_type_parameter_field = match fa with + let requires_cast = match fa with + | FInstance({cl_interface=true},_,{cf_kind = Var _}) -> + (* we have to cast var access on interfaces *) + true | FInstance(_,_,cf) -> + (* if the return type is one of the type-parameters, then we need to cast it *) (match follow cf.cf_type with TInst({cl_kind = KTypeParameter _},_) -> true | _ -> false) | _ -> List.exists (fun t -> follow t == et) tl in - (* if the return type is one of the type-parameters, then we need to cast it *) - if is_type_parameter_field then + if requires_cast then VCast (id, classify ctx e.etype) else if Codegen.is_volatile e.etype then VVolatile (id,None) @@ -1003,6 +1037,8 @@ let rec gen_type ctx t = write ctx (HGetLex t); List.iter (gen_type ctx) tl; write ctx (HApplyType (List.length tl)); + | HMAny -> + write ctx (HNull) | _ -> write ctx (HGetLex t) @@ -1487,6 +1523,9 @@ and gen_call ctx retval e el r = | 2l -> A3OSign16 | _ -> assert false )) + | TIdent "__vector__", [] -> + let t = match r with TAbstract ({a_path = [],"Class"}, [vt]) -> vt | _ -> assert false in + gen_type ctx (type_id ctx t) | TIdent "__vector__", [ep] -> gen_type ctx (type_id ctx r); write ctx HGetGlobalScope; @@ -1503,26 +1542,79 @@ and gen_call ctx retval e el r = write ctx HThis; List.iter (gen_expr ctx true) el; write ctx (HConstructSuper (List.length el)); - | TField ({ eexpr = TConst TSuper },f) , _ -> - let id = ident (field_name f) in + | TField (e1,f) , _ -> + begin + let default () = gen_field_call ctx retval e1 f el r in + let mk_prop_acccess prop_cl prop_tl prop_cf = mk (TField (e1, FInstance (prop_cl, prop_tl, prop_cf))) prop_cf.cf_type e.epos in + let mk_static_acccess cl prop_cf = mk (TField (e1, FStatic (cl, prop_cf))) prop_cf.cf_type e.epos in + match f, el with + | FInstance (cl, tl, cf), [] -> + (match is_extern_instance_accessor ~isget:true cl tl cf with + | Some (prop_cl, prop_tl, prop_cf) -> + let efield = mk_prop_acccess prop_cl prop_tl prop_cf in + getvar ctx (gen_access ctx efield Read) + | None -> + default ()) + + | FInstance (cl, tl, cf), [evalue] -> + (match is_extern_instance_accessor ~isget:false cl tl cf with + | Some (prop_cl, prop_tl, prop_cf) -> + let efield = mk_prop_acccess prop_cl prop_tl prop_cf in + gen_assign ctx efield evalue retval + | None -> + default ()) + + | FStatic (cl, cf), [] -> + (match is_extern_static_accessor ~isget:true cl cf with + | Some prop_cf -> + let efield = mk_static_acccess cl prop_cf in + getvar ctx (gen_access ctx efield Read) + | None -> + default ()) + + | FStatic (cl, cf), [evalue] -> + (match is_extern_static_accessor ~isget:false cl cf with + | Some prop_cf -> + let efield = mk_static_acccess cl prop_cf in + gen_assign ctx efield evalue retval + | None -> + default ()) + + | _ -> + default () + end + | _ -> + gen_expr ctx true e; + write ctx HGetGlobalScope; + List.iter (gen_expr ctx true) el; + write ctx (HCallStack (List.length el)); + coerce ctx (classify ctx r) + +and gen_field_call ctx retval eobj f el r = + match eobj with + | { eexpr = TConst TSuper } -> + let id = this_property f in write ctx (HFindPropStrict id); List.iter (gen_expr ctx true) el; - write ctx (HCallSuper (id,List.length el)); - coerce ctx (classify ctx r); - | TField ({ eexpr = TConst TThis },f) , _ when not ctx.in_static -> - let id = ident (field_name f) in - write ctx (HFindProp id); + if retval then begin + write ctx (HCallSuper (id,List.length el)); + coerce ctx (classify ctx r); + end else + write ctx (HCallSuperVoid (id,List.length el)) + | { eexpr = TConst TThis } when not ctx.in_static -> + let id = this_property f in + write ctx (HFindProp id); (* not sure why we don't use HFindPropStrict here too *) List.iter (gen_expr ctx true) el; if retval then begin write ctx (HCallProperty (id,List.length el)); coerce ctx (classify ctx r); end else write ctx (HCallPropVoid (id,List.length el)) - | TField (e1,f) , _ -> + | _ -> let old = ctx.for_call in ctx.for_call <- true; - gen_expr ctx true e1; - let id , _, _ = property ctx (field_name f) e1.etype in + gen_expr ctx true eobj; + let id , _, _ = property ctx f eobj.etype in ctx.for_call <- old; List.iter (gen_expr ctx true) el; if retval then begin @@ -1530,12 +1622,6 @@ and gen_call ctx retval e el r = coerce ctx (classify ctx r); end else write ctx (HCallPropVoid (id,List.length el)) - | _ -> - gen_expr ctx true e; - write ctx HGetGlobalScope; - List.iter (gen_expr ctx true) el; - write ctx (HCallStack (List.length el)); - coerce ctx (classify ctx r) and gen_unop ctx retval op flag e = let k = classify ctx e.etype in @@ -1587,6 +1673,11 @@ and check_binop ctx e1 e2 = | _ -> false) in if invalid then abort "Comparison of Int and UInt might lead to unexpected results" (punion e1.epos e2.epos); +and gen_assign ctx lhs rhs retval = + let acc = gen_access ctx lhs Write in + gen_expr ctx true rhs; + setvar ctx acc (if retval then Some (classify ctx lhs.etype) else None) + and gen_binop ctx retval op e1 e2 t p = let write_op op = let iop = (match op with @@ -1642,9 +1733,7 @@ and gen_binop ctx retval op e1 e2 t p = in match op with | OpAssign -> - let acc = gen_access ctx e1 Write in - gen_expr ctx true e2; - setvar ctx acc (if retval then Some (classify ctx e1.etype) else None) + gen_assign ctx e1 e2 retval | OpBoolAnd -> write ctx HFalse; let j = jump_expr ctx e1 false in @@ -1777,10 +1866,10 @@ let generate_construct ctx fdata c = let cargs = if not ctx.need_ctor_skip then fdata.tf_args else List.map (fun (v,c) -> let c = (match c with Some _ -> c | None -> Some (match classify ctx v.v_type with - | KInt | KUInt -> TInt 0l - | KFloat -> TFloat "0" - | KBool -> TBool false - | KType _ | KDynamic | KNone -> TNull) + | KInt | KUInt -> mk (TConst (TInt 0l)) ctx.com.basic.tint v.v_pos + | KFloat -> mk (TConst (TFloat "0")) ctx.com.basic.tfloat v.v_pos + | KBool -> mk (TConst (TBool false)) ctx.com.basic.tbool v.v_pos + | KType _ | KDynamic | KNone -> mk (TConst TNull) t_dynamic v.v_pos) ) in v,c ) fdata.tf_args in @@ -1788,7 +1877,7 @@ let generate_construct ctx fdata c = (* if skip_constructor, then returns immediatly *) if ctx.need_ctor_skip then (match c.cl_kind with | KGenericInstance _ -> () - | _ when not (Codegen.constructor_side_effects fdata.tf_expr) -> () + | _ when not (Texpr.constructor_side_effects fdata.tf_expr) -> () | _ -> let id = ident "skip_constructor" in getvar ctx (VGlobal (type_path ctx (["flash"],"Boot"))); @@ -1989,10 +2078,14 @@ let generate_field_kind ctx f c stat = | _ -> let name, kind = method_kind() in let m = generate_method ctx fdata stat f.cf_meta in + let is_override = not stat && ( + if kind = MK3Normal then List.memq f c.cl_overrides + else (loop c name || loop c f.cf_name) + ) in Some (HFMethod { hlm_type = m; - hlm_final = stat || (Meta.has Meta.Final f.cf_meta); - hlm_override = not stat && (loop c name || loop c f.cf_name); + hlm_final = stat || (has_class_field_flag f CfFinal); + hlm_override = is_override; hlm_kind = kind; }) ); @@ -2007,7 +2100,7 @@ let generate_field_kind ctx f c stat = ) args; let dparams = (match !dparams with None -> None | Some l -> Some (List.rev l)) in Some (HFMethod { - hlm_type = end_fun ctx (List.map (fun (a,opt,t) -> alloc_var a t f.cf_pos, (if opt then Some TNull else None)) args) dparams tret; + hlm_type = end_fun ctx (List.map (fun (a,opt,t) -> alloc_var (VUser TVOArgument) a t f.cf_pos, (if opt then Some TNull else None)) args) dparams tret; hlm_final = false; hlm_override = false; hlm_kind = snd (method_kind()); @@ -2047,6 +2140,267 @@ let check_constructor ctx c f = with Exit -> () +let has_protected_meta = Meta.Custom ":has_protected" +let mark_has_protected c = c.cl_meta <- (has_protected_meta,[],null_pos) :: c.cl_meta + +let find_first_nonextern_accessor_implementor cl name = + let rec loop cl cl_found = + match cl.cl_super with + | Some ({ cl_extern = true }, _) | None -> cl_found + | Some (cl_super, _) -> + let has_field = PMap.exists name cl_super.cl_fields in + let cl_found = if has_field then cl_super else cl_found in + loop cl_super cl_found + in + loop cl cl + +let maybe_gen_instance_accessor ctx cl tl accessor_cf acc alloc_slot kind f_impl f_iface = + match find_property_for_accessor ~isget:(kind = MK3Getter) cl tl accessor_cf.cf_name with + | Some (_, _, prop_cf) -> + let accessor_cl = find_first_nonextern_accessor_implementor cl accessor_cf.cf_name in + if accessor_cl == cl then begin + let was_override = ref false in + cl.cl_overrides <- List.filter (fun f2 -> + if f2 == accessor_cf then + (was_override := true; false) + else + true + ) cl.cl_overrides; + + let name, mtype = + if cl.cl_interface then begin + let (args,tret) = f_iface prop_cf in + let mtype = end_fun ctx args None tret in + HMName (reserved prop_cf.cf_name, HNNamespace (make_class_ns cl)), mtype + end else begin + let func = f_impl prop_cf in + let mtype = generate_method ctx func false accessor_cf.cf_meta in + ident prop_cf.cf_name, mtype + end + in + + let getter = { + hlf_name = name; + hlf_slot = alloc_slot (); + hlf_kind = HFMethod { + hlm_type = mtype; + hlm_final = has_class_field_flag accessor_cf CfFinal; + hlm_override = !was_override; + hlm_kind = kind; + }; + hlf_metas = None; + } in + getter :: acc + end else + acc + | None -> + acc + +let mk_instance_getter_func c tl accessor_cl accessor_tl accessor_cf prop_cf = + { + tf_args = []; + tf_type = prop_cf.cf_type; + tf_expr = begin + let ethis = mk (TConst TThis) (TInst (c, tl)) null_pos in + let efield = mk (TField (ethis, FInstance (accessor_cl, accessor_tl, accessor_cf))) accessor_cf.cf_type null_pos in + let ecall = mk (TCall (efield, [])) prop_cf.cf_type null_pos in + mk (TReturn (Some ecall)) t_dynamic null_pos; + end + } + +let maybe_gen_instance_getter ctx c f acc alloc_slot = + let tl = List.map snd c.cl_params in + maybe_gen_instance_accessor ctx c tl f acc alloc_slot MK3Getter + (mk_instance_getter_func c tl c tl f) + (fun prop_cf -> ([],prop_cf.cf_type)) + +let mk_varg t = alloc_var (VUser TVOArgument) "value" t null_pos + +let mk_instance_setter_func com c tl accessor_cl accessor_tl accessor_cf prop_cf = + let varg = mk_varg prop_cf.cf_type in + { + tf_args = [(varg,None)]; + tf_type = com.basic.tvoid; + tf_expr = begin + let ethis = mk (TConst TThis) (TInst (c, tl)) null_pos in + let efield = mk (TField (ethis, FInstance (accessor_cl, accessor_tl, accessor_cf))) accessor_cf.cf_type null_pos in + let earg = mk (TLocal varg) prop_cf.cf_type null_pos in + mk (TCall (efield, [earg])) prop_cf.cf_type null_pos + end + } + +let maybe_gen_instance_setter ctx c f acc alloc_slot = + let tl = List.map snd c.cl_params in + maybe_gen_instance_accessor ctx c tl f acc alloc_slot MK3Setter + (mk_instance_setter_func ctx.com c tl c tl f) + (fun prop_cf -> ([(mk_varg prop_cf.cf_type,None)],ctx.com.basic.tvoid)) + + +let maybe_gen_static_accessor ctx cl accessor_cf acc alloc_slot kind f_impl = + match find_static_property_for_accessor ~isget:(kind = MK3Getter) cl accessor_cf.cf_name with + | Some prop_cf -> + let func = f_impl prop_cf in + let getter = { + hlf_name = ident prop_cf.cf_name; + hlf_slot = alloc_slot (); + hlf_kind = HFMethod { + hlm_type = generate_method ctx func true accessor_cf.cf_meta; + hlm_final = true; + hlm_override = false; + hlm_kind = kind; + }; + hlf_metas = None; + } in + getter :: acc + | None -> + acc + +let maybe_gen_static_getter ctx c f acc alloc_slot = + maybe_gen_static_accessor ctx c f acc alloc_slot MK3Getter (fun prop_cf -> { + tf_args = []; + tf_type = prop_cf.cf_type; + tf_expr = begin + let ethis = Texpr.Builder.make_static_this c null_pos in + let efield = mk (TField (ethis, FStatic (c, f))) f.cf_type null_pos in + let ecall = mk (TCall (efield, [])) prop_cf.cf_type null_pos in + mk (TReturn (Some ecall)) t_dynamic null_pos; + end + }) + +let maybe_gen_static_setter ctx c f acc alloc_slot = + maybe_gen_static_accessor ctx c f acc alloc_slot MK3Setter (fun prop_cf -> + let varg = alloc_var (VUser TVOArgument) "value" prop_cf.cf_type null_pos in + { + tf_args = [(varg,None)]; + tf_type = ctx.com.basic.tvoid; + tf_expr = begin + let ethis = Texpr.Builder.make_static_this c null_pos in + let efield = mk (TField (ethis, FStatic (c, f))) f.cf_type null_pos in + let earg = mk (TLocal varg) prop_cf.cf_type null_pos in + mk (TCall (efield, [earg])) prop_cf.cf_type null_pos + end + } + ) + +let realize_required_accessors ctx cl = + let is_implemented_by_super ci = + Option.map_default (fun (csup,_) -> + (* heavily stripped-down version from Type.unify *) + let rec loop c = + c == ci + || + Option.map_default (fun (cs,_) -> loop cs) false c.cl_super + || + List.exists (fun (cs,_) -> loop cs) c.cl_implements + in + loop csup + ) false cl.cl_super + in + let interface_props = + begin + let h = Hashtbl.create 0 in + let rec collect cl = + let loop (ci,_) = + if not (is_implemented_by_super ci) then begin + List.iter (fun cf -> + match cf.cf_kind with + | Var { v_read = (AccCall | AccNever) as read; v_write = (AccCall | AccNever) as write } -> + begin try + let read', write', native = Hashtbl.find h cf.cf_name in + let read = if read = AccNever then read' else true in + let write = if write = AccNever then write' else true in + Hashtbl.replace h cf.cf_name (read, write, native) + with Not_found -> + Hashtbl.add h cf.cf_name (read = AccCall, write = AccCall, if is_flash_property cf then Some ci else None) + end + | _ -> () + ) ci.cl_ordered_fields; + collect ci; + end + in + List.iter loop cl.cl_implements; + in + collect cl; + h + end + in + + let rec has_nonextern_field cl name = + if PMap.exists name cl.cl_fields then true + else match cl.cl_super with + | Some ({ cl_extern = false } as csup, _) -> has_nonextern_field csup name + | _ -> false + in + + let tl = List.map snd cl.cl_params in + let fields = ref [] in + Hashtbl.iter (fun name (read, write, native) -> + match Type.class_field cl tl name with + | Some (actual_cl, actual_tl), _, cf -> + Option.may (fun iface -> + if not (is_flash_property cf) then + abort (Printf.sprintf "Interface %s requires property %s to be marked with @:flash.property" (s_type_path iface.cl_path) cf.cf_name) cf.cf_pos + ) native; + if actual_cl.cl_extern then begin + let mk_field_access () = + let ethis = mk (TConst TThis) (TInst (cl,tl)) null_pos in + mk (TField (ethis, FInstance (actual_cl, actual_tl, cf))) cf.cf_type null_pos + in + if read then begin + let getter_name = "get_" ^ name in + if not (has_nonextern_field cl getter_name) then begin + let getter_func = { + tf_args = []; + tf_type = cf.cf_type; + tf_expr = mk (TReturn (Some (mk_field_access ()))) t_dynamic null_pos; + } in + let getter = { + hlf_name = ident getter_name; + hlf_slot = 0; + hlf_kind = HFMethod { + hlm_type = generate_method ctx getter_func false []; + hlm_final = false; + hlm_override = false; + hlm_kind = MK3Normal; + }; + hlf_metas = None; + } in + fields := getter :: !fields; + end + end; + if write then begin + let setter_name = "set_" ^ name in + if not (has_nonextern_field cl setter_name) then begin + let varg = alloc_var (VUser TVOArgument) "value" cf.cf_type null_pos in + let setter_func = { + tf_args = [(varg,None)]; + tf_type = cf.cf_type; + tf_expr = begin + let efield = mk_field_access () in + let earg = mk (TLocal varg) varg.v_type null_pos in + let eassign = mk (TBinop (OpAssign, efield, earg)) cf.cf_type null_pos in + mk (TReturn (Some eassign)) t_dynamic null_pos; + end; + } in + let setter = { + hlf_name = ident setter_name; + hlf_slot = 0; + hlf_kind = HFMethod { + hlm_type = generate_method ctx setter_func false []; + hlm_final = false; + hlm_override = false; + hlm_kind = MK3Normal; + }; + hlf_metas = None; + } in + fields := setter :: !fields; + end + end; + end + | _ -> assert false + ) interface_props; + !fields + let generate_class ctx c = let name = type_path ctx c.cl_path in ctx.cur_class <- c; @@ -2088,13 +2442,13 @@ let generate_class ctx c = | Some (c,_) -> find_meta c in let protect() = - let p = (match c.cl_path with [], n -> n | p, n -> String.concat "." p ^ ":" ^ n) in + let p = make_class_ns c in has_protected := Some p; HMName (f.cf_name,HNProtected p) in let rec loop_meta = function | [] -> - if not f.cf_public && ctx.swf_protected then + if not (has_class_field_flag f CfPublic) && ctx.swf_protected then protect() else ident f.cf_name @@ -2106,20 +2460,78 @@ let generate_class ctx c = | _ -> loop_meta l in if c.cl_interface then - HMName (reserved f.cf_name, HNNamespace (match c.cl_path with [],n -> n | l,n -> String.concat "." l ^ ":" ^ n)) + HMName (reserved f.cf_name, HNNamespace (make_class_ns c)) else loop_meta (find_meta c) in - let generate_prop f acc alloc_slot = + let generate_prop stat f acc alloc_slot = match f.cf_kind with - | Method _ -> acc - | Var v -> - (* let p = f.cf_pos in *) - (* let ethis = mk (TConst TThis) (TInst (c,[])) p in *) - acc + | Method _ when is_getter_name f.cf_name -> + if not stat then + maybe_gen_instance_getter ctx c f acc alloc_slot + else + maybe_gen_static_getter ctx c f acc alloc_slot + | Method _ when is_setter_name f.cf_name -> + if not stat then + maybe_gen_instance_setter ctx c f acc alloc_slot + else + maybe_gen_static_setter ctx c f acc alloc_slot + | Var { v_read = (AccCall | AccNever) as read; v_write = (AccCall | AccNever) as write } when not c.cl_interface && not (Meta.has Meta.IsVar f.cf_meta) -> + (* if the accessor methods were defined in super classes, we still need to generate native getter/setter *) + let acc = + if read = AccCall then begin + try + begin + let tl = List.map snd c.cl_params in + match Type.class_field c tl ("get_" ^ f.cf_name) with + | Some (actual_cl, actual_tl), _, getter_cf when actual_cl != c -> + let func = mk_instance_getter_func c tl actual_cl actual_tl getter_cf f in + { + hlf_name = ident f.cf_name; + hlf_slot = alloc_slot (); + hlf_kind = HFMethod { + hlm_type = generate_method ctx func false []; + hlm_final = false; + hlm_override = false; + hlm_kind = MK3Getter; + }; + hlf_metas = None; + } :: acc + | _ -> + acc + end + with Not_found -> + acc + end else acc + in + if write = AccCall then begin + try + begin + let tl = List.map snd c.cl_params in + match Type.class_field c tl ("set_" ^ f.cf_name) with + | Some (actual_cl, actual_tl), _, setter_cf when actual_cl != c -> + let func = mk_instance_setter_func ctx.com c tl actual_cl actual_tl setter_cf f in + { + hlf_name = ident f.cf_name; + hlf_slot = alloc_slot (); + hlf_kind = HFMethod { + hlm_type = generate_method ctx func false []; + hlm_final = false; + hlm_override = false; + hlm_kind = MK3Setter; + }; + hlf_metas = None; + } :: acc + | _ -> + acc + end + with Not_found -> + acc + end else acc + | Method _ | Var _ -> acc in let fields = PMap.fold (fun f acc -> - let acc = generate_prop f acc (fun() -> 0) in + let acc = generate_prop false f acc (fun() -> 0) in match generate_field_kind ctx f c false with | None -> acc | Some k -> @@ -2131,12 +2543,12 @@ let generate_class ctx c = } :: acc ) c.cl_fields [] in let fields = if c.cl_path <> ctx.boot then fields else begin + let cf = { + (mk_field "init" ~public:(ctx.swc && ctx.swf_protected) (TFun ([],t_dynamic)) c.cl_pos null_pos) with + cf_kind = Method MethNormal; + } in { - hlf_name = make_name { - (mk_field "init" (TFun ([],t_dynamic)) c.cl_pos null_pos) with - cf_public = ctx.swc && ctx.swf_protected; - cf_kind = Method MethNormal; - } false; + hlf_name = make_name cf false; hlf_slot = 0; hlf_kind = (HFMethod { hlm_type = generate_inits ctx; @@ -2147,10 +2559,11 @@ let generate_class ctx c = hlf_metas = None; } :: fields end in + let fields = if not c.cl_interface then fields @ realize_required_accessors ctx c else fields in let st_field_count = ref 0 in let st_meth_count = ref 0 in let statics = List.rev (List.fold_left (fun acc f -> - let acc = generate_prop f acc (fun() -> incr st_meth_count; !st_meth_count) in + let acc = generate_prop true f acc (fun() -> incr st_meth_count; !st_meth_count) in match generate_field_kind ctx f c true with | None -> acc | Some k -> @@ -2172,17 +2585,35 @@ let generate_class ctx c = } :: statics in let rec is_dynamic c = - if c.cl_dynamic <> None || c.cl_array_access <> None then true + if c.cl_array_access <> None then true else match c.cl_super with | None -> false | Some (c,_) -> is_dynamic c in + if !has_protected <> None then + mark_has_protected c (* class has its own protected methods - add meta for the child classes *) + else Option.may (fun (csup,_) -> (* child has no own protected methods, check whether parent was marked with the meta *) + if Meta.has has_protected_meta csup.cl_meta then begin + has_protected := Some (make_class_ns c); + mark_has_protected c (* also mark this class with the meta for further child classes *) + end else if csup.cl_extern then begin + let rec loop csup = + if List.exists is_cf_protected csup.cl_ordered_fields then begin + has_protected := Some (make_class_ns c); + mark_has_protected c; (* also mark this class with the meta for further child classes *) + mark_has_protected csup; (* ALSO mark the extern class for faster future checks *) + end else + Option.may (fun (csup,_) -> loop csup) csup.cl_super; + in + loop csup + end + ) c.cl_super; { hlc_index = 0; hlc_name = name; hlc_super = (if c.cl_interface then None else Some (type_path ctx (match c.cl_super with None -> [],"Object" | Some (c,_) -> c.cl_path))); hlc_sealed = not (is_dynamic c); - hlc_final = Meta.has Meta.Final c.cl_meta; + hlc_final = c.cl_final; hlc_interface = c.cl_interface; hlc_namespace = (match !has_protected with None -> None | Some p -> Some (HNProtected p)); hlc_implements = Array.of_list (List.map (fun (c,_) -> @@ -2199,7 +2630,7 @@ let generate_class ctx c = let generate_enum ctx e meta = let name_id = type_path ctx e.e_path in let api = ctx.com.basic in - let f = begin_fun ctx [alloc_var "tag" api.tstring e.e_pos, None;alloc_var "index" api.tint e.e_pos, None;alloc_var "params" (api.tarray (mk_mono())) e.e_pos, None] api.tvoid [ethis] false e.e_pos in + let f = begin_fun ctx [alloc_var VGenerated "tag" api.tstring e.e_pos, None;alloc_var VGenerated "index" api.tint e.e_pos, None;alloc_var VGenerated "params" (api.tarray (mk_mono())) e.e_pos, None] api.tvoid [ethis] false e.e_pos in let tag_id = ident "tag" in let index_id = ident "index" in let params_id = ident "params" in @@ -2230,7 +2661,7 @@ let generate_enum ctx e meta = hlf_slot = !st_count; hlf_kind = (match f.ef_type with | TFun (args,_) -> - let fdata = begin_fun ctx (List.map (fun (a,opt,t) -> alloc_var a t e.e_pos, (if opt then Some TNull else None)) args) (TEnum (e,[])) [] true f.ef_pos in + let fdata = begin_fun ctx (List.map (fun (a,opt,t) -> alloc_var VGenerated a t e.e_pos, (if opt then Some (mk (TConst TNull) t_dynamic null_pos) else None)) args) (TEnum (e,[])) [] true f.ef_pos in write ctx (HFindPropStrict name_id); write ctx (HString f.ef_name); write ctx (HInt f.ef_index); @@ -2327,7 +2758,7 @@ let rec generate_type ctx t = if e.e_extern then None else - let meta = Codegen.build_metadata ctx.com t in + let meta = Texpr.build_metadata ctx.com.basic t in let hlc = generate_enum ctx e meta in let init = begin_fun ctx [] ctx.com.basic.tvoid [ethis] false e.e_pos in generate_enum_init ctx e hlc meta; diff --git a/src/generators/hl2c.ml b/src/generators/hl2c.ml index 44d62a9f580..128b1444672 100644 --- a/src/generators/hl2c.ml +++ b/src/generators/hl2c.ml @@ -1,5 +1,5 @@ (* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -37,12 +37,23 @@ type output_options = | OODecreaseIndent | OOBeginBlock | OOEndBlock + | OOBreak -type function_entry = { +type code_module = { + m_name : string; + mutable m_functions : function_entry list; + mutable m_types : ttype list; +} + +and function_entry = { + fe_index : int; mutable fe_name : string; mutable fe_decl : fundecl option; mutable fe_args : ttype list; mutable fe_ret : ttype; + mutable fe_module : code_module option; + mutable fe_called_by : function_entry list; + mutable fe_calling : function_entry list; } type context = { @@ -50,12 +61,23 @@ type context = { out : Buffer.t; mutable tabs : string; hash_cache : (int, int32) Hashtbl.t; + hash_mem : (int32, bool) Hashtbl.t; + mutable hash_cache_list : int list; hlcode : code; dir : string; mutable curfile : string; mutable cfiles : string list; ftable : function_entry array; - htypes : (ttype, int) PMap.t; + htypes : (ttype, string) PMap.t; + gnames : string array; + bytes_names : string array; + mutable defines : string list; + defined_funs : (int, unit) Hashtbl.t; + hdefines : (string, unit) Hashtbl.t; + mutable defined_types : (ttype, unit) PMap.t; + mutable file_prefix : string; + mutable fun_index : int; + mutable type_module : (ttype, code_module) PMap.t; } let sprintf = Printf.sprintf @@ -93,15 +115,15 @@ let s_comp = function let core_types = let vp = { vfields = [||]; vindex = PMap.empty } in let ep = { ename = ""; eid = 0; eglobal = None; efields = [||] } in - [HVoid;HUI8;HUI16;HI32;HI64;HF32;HF64;HBool;HBytes;HDyn;HFun ([],HVoid);HObj null_proto;HArray;HType;HRef HVoid;HVirtual vp;HDynObj;HAbstract ("",0);HEnum ep;HNull HVoid] + [HVoid;HUI8;HUI16;HI32;HI64;HF32;HF64;HBool;HBytes;HDyn;HFun ([],HVoid);HObj null_proto;HArray;HType;HRef HVoid;HVirtual vp;HDynObj;HAbstract ("",0);HEnum ep;HNull HVoid;HMethod ([],HVoid);HStruct null_proto] let tname str = let n = String.concat "__" (ExtString.String.nsplit str ".") in if Hashtbl.mem keywords ("_" ^ n) then "__" ^ n else n let is_gc_ptr = function - | HVoid | HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64 | HBool | HType | HRef _ -> false - | HBytes | HDyn | HFun _ | HObj _ | HArray | HVirtual _ | HDynObj | HAbstract _ | HEnum _ | HNull _ -> true + | HVoid | HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64 | HBool | HType | HRef _ | HMethod _ -> false + | HBytes | HDyn | HFun _ | HObj _ | HArray | HVirtual _ | HDynObj | HAbstract _ | HEnum _ | HNull _ | HStruct _ -> true let is_ptr = function | HVoid | HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64 | HBool -> false @@ -119,7 +141,7 @@ let rec ctype_no_ptr = function | HBytes -> "vbyte",1 | HDyn -> "vdynamic",1 | HFun _ -> "vclosure",1 - | HObj p -> tname p.pname,0 + | HObj p | HStruct p -> tname p.pname,0 | HArray -> "varray",1 | HType -> "hl_type",1 | HRef t -> let s,i = ctype_no_ptr t in s,i + 1 @@ -128,19 +150,24 @@ let rec ctype_no_ptr = function | HAbstract (name,_) -> name,1 | HEnum _ -> "venum",1 | HNull _ -> "vdynamic",1 + | HMethod _ -> "void",1 let ctype t = let t, nptr = ctype_no_ptr t in if nptr = 0 then t else t ^ String.make nptr '*' +let args_repr args = + if args = [] then "void" else String.concat "," (List.map ctype args) + let cast_fun s args t = - sprintf "((%s (*)(%s))%s)" (ctype t) (String.concat "," (List.map ctype args)) s + sprintf "((%s (*)(%s))%s)" (ctype t) (args_repr args) s let dyn_value_field t = "->v." ^ match t with | HUI8 -> "ui8" | HUI16 -> "ui16" | HI32 -> "i" + | HI64 -> "i64" | HF32 -> "f" | HF64 -> "d" | HBool -> "b" @@ -168,6 +195,8 @@ let type_id t = | HAbstract _ -> "HABSTRACT" | HEnum _ -> "HENUM" | HNull _ -> "HNULL" + | HMethod _ -> "HMETHOD" + | HStruct _ -> "HSTRUCT" let var_type n t = ctype t ^ " " ^ ident n @@ -182,22 +211,55 @@ let hash ctx sid = try Hashtbl.find ctx.hash_cache sid with Not_found -> - let h = hl_hash ctx.hlcode.strings.(sid) in + let rec loop h = + if Hashtbl.mem ctx.hash_mem h then loop (Int32.add h Int32.one) else h + in + let h = loop (hl_hash ctx.hlcode.strings.(sid)) in Hashtbl.add ctx.hash_cache sid h; + Hashtbl.add ctx.hash_mem h true; + ctx.hash_cache_list <- sid :: ctx.hash_cache_list; h +let type_name ctx t = + try PMap.find t ctx.htypes with Not_found -> assert false + +let define ctx s = + if not (Hashtbl.mem ctx.hdefines s) then begin + ctx.defines <- s :: ctx.defines; + Hashtbl.add ctx.hdefines s (); + end + +let rec define_type ctx t = + match t with + | HVoid | HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64 | HBool | HBytes | HDyn | HArray | HType | HDynObj | HNull _ | HRef _ -> () + | HAbstract _ -> + define ctx "#include "; + | HFun (args,ret) | HMethod (args,ret) -> + List.iter (define_type ctx) args; + define_type ctx ret + | HEnum _ | HObj _ | HStruct _ when not (PMap.exists t ctx.defined_types) -> + ctx.defined_types <- PMap.add t () ctx.defined_types; + define ctx (sprintf "#include <%s.h>" (try PMap.find t ctx.type_module with Not_found -> assert false).m_name) + | HVirtual vp when not (PMap.exists t ctx.defined_types) -> + ctx.defined_types <- PMap.add t () ctx.defined_types; + Array.iter (fun (_,_,t) -> define_type ctx t) vp.vfields + | HEnum _ | HObj _ | HStruct _ | HVirtual _ -> + () + let type_value ctx t = - let index = (try PMap.find t ctx.htypes with Not_found -> assert false) in - "&type$" ^ string_of_int index + let n = type_name ctx t in + define ctx (sprintf "extern hl_type %s;" n); + "&" ^ n let enum_constr_type ctx e i = + define_type ctx (HEnum e); let cname,_, tl = e.efields.(i) in if Array.length tl = 0 then "venum" else let name = if e.eid = 0 then - let index = (try PMap.find (HEnum e) ctx.htypes with Not_found -> assert false) in - "Enum$" ^ string_of_int index + let name = (try PMap.find (HEnum e) ctx.htypes with Not_found -> assert false) in + "Enum" ^ name else String.concat "_" (ExtString.String.nsplit e.ename ".") in @@ -222,41 +284,76 @@ let expr ctx str = output ctx str; output ctx ";\n" -let unamed_field fid = "$_f" ^ string_of_int fid +let unamed_field fid = "f$" ^ string_of_int fid let obj_field fid name = if name = "" then unamed_field fid else ident name let close_file ctx = let str = Buffer.contents ctx.out in + let defines = List.rev ctx.defines in + let str = (match defines with [] -> str | l -> String.concat "\n" l ^ "\n\n" ^ str) in + ctx.defines <- []; + ctx.defined_types <- PMap.empty; + Hashtbl.clear ctx.hdefines; + Hashtbl.clear ctx.defined_funs; Buffer.reset ctx.out; let fpath = ctx.dir ^ "/" ^ ctx.curfile in if String.sub ctx.curfile (String.length ctx.curfile - 2) 2 = ".c" then ctx.cfiles <- ctx.curfile :: ctx.cfiles; ctx.curfile <- ""; let fcontent = (try Std.input_file ~bin:true fpath with _ -> "") in if fcontent <> str then begin - Common.mkdir_recursive "" (ExtString.String.nsplit (Filename.dirname fpath) "/"); + Path.mkdir_recursive "" (ExtString.String.nsplit (Filename.dirname fpath) "/"); let ch = open_out_bin fpath in output_string ch str; close_out ch; end +let bom = "\xEF\xBB\xBF" + +let define_global ctx g = + let t = ctx.hlcode.globals.(g) in + define_type ctx t; + define ctx (sprintf "extern %s;" (var_type ctx.gnames.(g) t)) + +let define_function ctx fid = + let ft = ctx.ftable.(fid) in + let fid = if ft.fe_decl = None then -1 else fid in + if not (Hashtbl.mem ctx.defined_funs fid) then begin + Hashtbl.add ctx.defined_funs fid (); + (match ft.fe_decl with + | None -> + define ctx "#include " + | Some f -> + define_type ctx f.ftype; + ctx.defines <- sprintf "%s %s(%s);" (ctype ft.fe_ret) ft.fe_name (args_repr ft.fe_args) :: ctx.defines); + end; + ft.fe_name + +let short_digest str = + String.sub (Digest.to_hex (Digest.string str)) 0 7 + let open_file ctx file = if ctx.curfile <> "" then close_file ctx; let version_major = ctx.version / 1000 in let version_minor = (ctx.version mod 1000) / 100 in let version_revision = (ctx.version mod 100) in - if file <> "hlc.json" then line ctx (sprintf "// Generated by HLC %d.%d.%d (HL v%d)" version_major version_minor version_revision ctx.hlcode.version); - ctx.curfile <- file + if file <> "hlc.json" then define ctx (sprintf "%s// Generated by HLC %d.%d.%d (HL v%d)" bom version_major version_minor version_revision ctx.hlcode.version); + ctx.curfile <- file; + ctx.fun_index <- 0; + ctx.file_prefix <- (short_digest file) ^ "_" let string_data_limit = 64 let string ctx sid = let s = ctx.hlcode.strings.(sid) in if String.length s < string_data_limit then - sprintf "USTR(\"%s\")" (Ast.s_escape ~hex:false s) - else - sprintf "string$%d" sid + sprintf "USTR(\"%s\")" (StringHelper.s_escape s) + else begin + let id = short_digest s in + define ctx (sprintf "extern vbyte string$%s[];" id); + sprintf "string$%s" id + end let generate_reflection ctx = let line = line ctx and expr = expr ctx in @@ -267,7 +364,7 @@ let generate_reflection ctx = match t with | HVoid | HF32 | HF64 | HI64 -> t | HBool | HUI8 | HUI16 | HI32 -> HI32 - | HBytes | HDyn | HFun _ | HObj _ | HArray | HType | HRef _ | HVirtual _ | HDynObj | HAbstract _ | HEnum _ | HNull _ -> HDyn + | _ -> HDyn in let type_kind_id t = match t with @@ -353,6 +450,7 @@ let generate_reflection ctx = | HUI8 | HUI16 | HBool | HI32 -> "i" | HF32 -> "f" | HF64 -> "d" + | HI64 -> "i64" | _ -> "p" in let make_wrap_name args t = @@ -415,18 +513,24 @@ let generate_reflection ctx = let generate_function ctx f = let line = line ctx and expr = expr ctx in let sline fmt = Printf.ksprintf line fmt and sexpr fmt = Printf.ksprintf expr fmt in + let define fmt = Printf.ksprintf (define ctx) fmt in let block() = block ctx and unblock() = unblock ctx in let type_value = type_value ctx in let code = ctx.hlcode in let rid = ref (-1) in + let cl_id = ref 0 in let reg id = "r" ^ string_of_int id in - let label id = "label$" ^ string_of_int f.findex ^ "$" ^ string_of_int id in + let label p = sprintf "label$%s%d_%d" ctx.file_prefix ctx.fun_index p in + ctx.fun_index <- ctx.fun_index + 1; + Hashtbl.add ctx.defined_funs f.findex (); + Array.iter (define_type ctx) f.regs; + define_type ctx f.ftype; let rtype r = f.regs.(r) in - let funname fid = ctx.ftable.(fid).fe_name in + let funname fid = define_function ctx fid in let rcast r t = if tsame (rtype r) t then (reg r) @@ -449,7 +553,7 @@ let generate_function ctx f = let ocall r fid args = let ft = ctx.ftable.(fid) in let rstr = rassign r ft.fe_ret in - sexpr "%s%s(%s)" rstr ft.fe_name (String.concat "," (List.map2 rcast args ft.fe_args)) + sexpr "%s%s(%s)" rstr (funname fid) (String.concat "," (List.map2 rcast args ft.fe_args)) in @@ -457,6 +561,7 @@ let generate_function ctx f = | HUI8 | HUI16 | HI32 | HBool -> "i" | HF32 -> "f" | HF64 -> "d" + | HI64 -> "i64" | _ -> "p" in @@ -489,7 +594,7 @@ let generate_function ctx f = | [] -> assert false | o :: args -> match rtype o with - | HObj _ -> + | HObj _ | HStruct _ -> let vfun = cast_fun (sprintf "%s->$type->vobj_proto[%d]" (reg o) fid) (rtype o :: List.map rtype args) (rtype r) in sexpr "%s%s(%s)" (rassign r (rtype r)) vfun (String.concat "," (List.map reg (o::args))) | HVirtual vp -> @@ -518,30 +623,26 @@ let generate_function ctx f = let set_field obj fid v = match rtype obj with - | HObj o -> + | HObj o | HStruct o -> let name, t = resolve_field o fid in sexpr "%s->%s = %s" (reg obj) (obj_field fid name) (rcast v t) | HVirtual vp -> let name, nid, t = vp.vfields.(fid) in let dset = sprintf "hl_dyn_set%s(%s->value,%ld/*%s*/%s,%s)" (dyn_prefix t) (reg obj) (hash ctx nid) name (type_value_opt (rtype v)) (reg v) in - (match t with - | HFun _ -> expr dset - | _ -> sexpr "if( hl_vfields(%s)[%d] ) *(%s*)(hl_vfields(%s)[%d]) = (%s)%s; else %s" (reg obj) fid (ctype t) (reg obj) fid (ctype t) (reg v) dset) + sexpr "if( hl_vfields(%s)[%d] ) *(%s*)(hl_vfields(%s)[%d]) = (%s)%s; else %s" (reg obj) fid (ctype t) (reg obj) fid (ctype t) (reg v) dset | _ -> assert false in let get_field r obj fid = match rtype obj with - | HObj o -> + | HObj o | HStruct o -> let name, t = resolve_field o fid in sexpr "%s%s->%s" (rassign r t) (reg obj) (obj_field fid name) | HVirtual v -> let name, nid, t = v.vfields.(fid) in let dget = sprintf "(%s)hl_dyn_get%s(%s->value,%ld/*%s*/%s)" (ctype t) (dyn_prefix t) (reg obj) (hash ctx nid) name (type_value_opt t) in - (match t with - | HFun _ -> sexpr "%s%s" (rassign r t) dget - | _ -> sexpr "%shl_vfields(%s)[%d] ? (*(%s*)(hl_vfields(%s)[%d])) : %s" (rassign r t) (reg obj) fid (ctype t) (reg obj) fid dget) + sexpr "%shl_vfields(%s)[%d] ? (*(%s*)(hl_vfields(%s)[%d])) : %s" (rassign r t) (reg obj) fid (ctype t) (reg obj) fid dget | _ -> assert false in @@ -580,12 +681,17 @@ let generate_function ctx f = if !trap_depth > !max_trap_depth then max_trap_depth := !trap_depth | OEndTrap true -> decr trap_depth + | OStaticClosure (_, fid) -> + let ft = ctx.ftable.(fid) in + sexpr "static vclosure cl$%d = { %s, %s, 0 }" (!cl_id) (type_value (HFun (ft.fe_args,ft.fe_ret))) (funname fid); + incr cl_id; | _ -> () ) f.code; for i = 0 to !max_trap_depth - 1 do sexpr "hl_trap_ctx trap$%d" i; done; + cl_id := 0; let flush_options i = match output_options.(i) with @@ -598,6 +704,7 @@ let generate_function ctx f = | OOLabel -> sline "%s:" (label i) | OOCase i -> sline "case %i:" i | OODefault -> line "default:" + | OOBreak -> line "break;"; | OOIncreaseIndent -> block() | OODecreaseIndent -> unblock() | OOBeginBlock -> line "{" @@ -639,20 +746,22 @@ let generate_function ctx f = sexpr "if( %s != %s && (!%s || !%s || %s) ) goto %s" (reg a) (reg b) (reg a) (reg b) pcompare (label d) else sexpr "if( %s && %s && %s ) goto %s" (reg a) (reg b) pcompare (label d) - | HDyn , _ | _, HDyn -> + | (HDyn | HFun _), _ | _, (HDyn | HFun _) -> let inv = if op = CGt || op = CGte then "&& i != hl_invalid_comparison " else "" in sexpr "{ int i = hl_dyn_compare((vdynamic*)%s,(vdynamic*)%s); if( i %s 0 %s) goto %s; }" (reg a) (reg b) (s_comp op) inv (label d) | HObj oa, HObj _ -> (try let fid = PMap.find "__compare" oa.pfunctions in if op = CEq then - sexpr "if( %s == %s || (%s && %s && %s(%s,%s) == 0) ) goto %s" (reg a) (reg b) (reg a) (reg b) (funname fid) (reg a) (reg b) (label d) + sexpr "if( %s == %s || (%s && %s && %s(%s,(vdynamic*)%s) == 0) ) goto %s" (reg a) (reg b) (reg a) (reg b) (funname fid) (reg a) (reg b) (label d) else if op = CNeq then - sexpr "if( %s != %s && (!%s || !%s || %s(%s,%s) != 0) ) goto %s" (reg a) (reg b) (reg a) (reg b) (funname fid) (reg a) (reg b) (label d) + sexpr "if( %s != %s && (!%s || !%s || %s(%s,(vdynamic*)%s) != 0) ) goto %s" (reg a) (reg b) (reg a) (reg b) (funname fid) (reg a) (reg b) (label d) else - sexpr "if( %s && %s && %s(%s,%s) %s 0 ) goto %s" (reg a) (reg b) (funname fid) (reg a) (reg b) (s_comp op) (label d) + sexpr "if( %s && %s && %s(%s,(vdynamic*)%s) %s 0 ) goto %s" (reg a) (reg b) (funname fid) (reg a) (reg b) (s_comp op) (label d) with Not_found -> phys_compare()) + | HStruct _, HStruct _ -> + phys_compare() | HVirtual _, HVirtual _ -> if op = CEq then sexpr "if( %s == %s || (%s && %s && %s->value && %s->value && %s->value == %s->value) ) goto %s" (reg a) (reg b) (reg a) (reg b) (reg a) (reg b) (reg a) (reg b) (label d) @@ -660,7 +769,7 @@ let generate_function ctx f = sexpr "if( %s != %s && (!%s || !%s || !%s->value || !%s->value || %s->value != %s->value) ) goto %s" (reg a) (reg b) (reg a) (reg b) (reg a) (reg b) (reg a) (reg b) (label d) else assert false - | HEnum _, HEnum _ | HDynObj, HDynObj | HFun _, HFun _ | HAbstract _, HAbstract _ -> + | HEnum _, HEnum _ | HDynObj, HDynObj | HAbstract _, HAbstract _ -> phys_compare() | HVirtual _, HObj _-> if op = CEq then @@ -688,7 +797,8 @@ let generate_function ctx f = | OBool (r,b) -> sexpr "%s = %s" (reg r) (if b then "true" else "false") | OBytes (r,idx) -> - sexpr "%s = bytes$%d" (reg r) idx + define "extern vbyte %s[];" ctx.bytes_names.(idx); + sexpr "%s = %s" (reg r) ctx.bytes_names.(idx) | OString (r,idx) -> sexpr "%s = (vbyte*)%s" (reg r) (string ctx idx) | ONull r -> @@ -765,7 +875,8 @@ let generate_function ctx f = | _ -> assert false) | OStaticClosure (r,fid) -> - sexpr "%s = &cl$%d" (reg r) fid + sexpr "%s = &cl$%d" (reg r) (!cl_id); + incr cl_id | OInstanceClosure (r,fid,ptr) -> let ft = ctx.ftable.(fid) in sexpr "%s = hl_alloc_closure_ptr(%s,%s,%s)" (reg r) (type_value (HFun (ft.fe_args,ft.fe_ret))) (funname fid) (reg ptr) @@ -778,9 +889,11 @@ let generate_function ctx f = | _ -> todo()) | OGetGlobal (r,g) -> - sexpr "%s = (%s)global$%d" (reg r) (ctype (rtype r)) g + define_global ctx g; + sexpr "%s = (%s)%s" (reg r) (ctype (rtype r)) ctx.gnames.(g) | OSetGlobal (g,r) -> - sexpr "global$%d = (%s)%s" g (ctype code.globals.(g)) (reg r) + define_global ctx g; + sexpr "%s = (%s)%s" ctx.gnames.(g) (ctype code.globals.(g)) (reg r) | ORet r -> if rtype r = HVoid then expr "return" else sexpr "return %s" (rcast r fret) | OJTrue (r,d) | OJNotNull (r,d) -> @@ -811,6 +924,8 @@ let generate_function ctx f = sexpr "goto %s" (label d) | OLabel _ -> if not (has_label i) then sline "%s:" (label (-1)) + | OToDyn (r,v) when rtype v = HBool -> + sexpr "%s = hl_alloc_dynbool(%s)" (reg r) (reg v) | OToDyn (r,v) -> if is_ptr (rtype v) then begin sline "if( %s == NULL ) %s = NULL; else {" (reg v) (reg r); @@ -820,6 +935,8 @@ let generate_function ctx f = (match rtype v with | HUI8 | HUI16 | HI32 | HBool -> sexpr "%s->v.i = %s" (reg r) (reg v) + | HI64 -> + sexpr "%s->v.i64 = %s" (reg r) (reg v) | HF32 -> sexpr "%s->v.f = %s" (reg r) (reg v) | HF64 -> @@ -838,7 +955,7 @@ let generate_function ctx f = sexpr "%s = (int)%s" (reg r) (reg v) | ONew r -> (match rtype r with - | HObj o -> sexpr "%s = (%s)hl_alloc_obj(%s)" (reg r) (tname o.pname) (tname o.pname ^ "__val") + | HObj o | HStruct o -> sexpr "%s = (%s)hl_alloc_obj(%s)" (reg r) (tname o.pname) (type_value (rtype r)) | HDynObj -> sexpr "%s = hl_alloc_dynobj()" (reg r) | HVirtual _ as t -> sexpr "%s = hl_alloc_virtual(%s)" (reg r) (type_value t) | _ -> assert false) @@ -928,12 +1045,17 @@ let generate_function ctx f = | OSwitch (r,idx,eend) -> sline "switch(%s) {" (reg r); block(); - output_at2 (i + 1) [OODefault;OOIncreaseIndent]; - Array.iteri (fun k delta -> output_at2 (delta + i + 1) [OODecreaseIndent;OOCase k;OOIncreaseIndent]) idx; let pend = i+1+eend in (* insert at end if we have another switch case here *) let old = output_options.(pend) in output_options.(pend) <- []; + (* insert cases *) + output_at2 (i + 1) [OODefault;OOIncreaseIndent]; + Array.iteri (fun k delta -> + output_at2 (delta + i + 1) [OODecreaseIndent;OOCase k;OOIncreaseIndent]; + if delta = eend then output_at pend OOBreak; + ) idx; + (* insert end switch *) output_at2 pend ([OODecreaseIndent;OODecreaseIndent;OOEndBlock] @ List.rev old); | ONullCheck r -> sexpr "if( %s == NULL ) hl_null_access()" (reg r) @@ -961,90 +1083,300 @@ let generate_function ctx f = line "}"; line "" -let write_c com file (code:code) = - - let all_types, htypes = gather_types code in - - let ctx = { - version = com.Common.version; - out = Buffer.create 1024; - tabs = ""; - hlcode = code; - hash_cache = Hashtbl.create 0; - dir = (match Filename.dirname file with "" -> "." | dir -> String.concat "/" (ExtString.String.nsplit dir "\\")); - curfile = ""; - cfiles = []; - ftable = Array.init (Array.length code.functions + Array.length code.natives) (fun _ -> { fe_args = []; fe_ret = HVoid; fe_name = ""; fe_decl = None; }); - htypes = htypes; - } in - - let line = line ctx and expr = expr ctx in - let sline fmt = Printf.ksprintf line fmt and sexpr fmt = Printf.ksprintf expr fmt in +type type_desc = + | DSimple of ttype + | DFun of type_desc list * type_desc * bool + | DNamed of string + | DVirtual of (string * type_desc) array + | DContext of type_desc array - open_file ctx "hl/code.h"; - line "#ifndef HL_CODE_H"; - line "#define HL_CODE_H"; - line ""; - line "#define HLC_BOOT"; - line "#include "; - line "#include \"typedefs.h\""; - line "#include \"types.h\""; - line "#include \"functions.h\""; - line "#include \"globals.h\""; - line "#include \"natives.h\""; - line ""; - line "#endif"; +let valid_ident = + let e = Str.regexp "[^A-Za-z0-9_]+" in + (fun str -> Str.global_replace e "_" str) - let used_closures = Hashtbl.create 0 in - let bytes_strings = Hashtbl.create 0 in +let make_types_idents htypes = + let types_descs = ref PMap.empty in + let rec make_desc t = + match t with + | HVoid | HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64 | HBool | HBytes | HDyn | HArray | HType | HRef _ | HDynObj | HNull _ -> + DSimple t + | HFun (tl,t) -> + DFun (List.map make_desc tl, make_desc t, true) + | HMethod (tl, t) -> + DFun (List.map make_desc tl, make_desc t, false) + | HObj p | HStruct p -> + DNamed p.pname + | HAbstract (n,_) -> + DNamed n + | HEnum e when e.ename = "" -> + let _,_,tl = e.efields.(0) in + DContext (Array.map make_desc tl) + | HEnum e -> + DNamed e.ename + | HVirtual vp -> + try + PMap.find vp (!types_descs) + with Not_found -> + let arr = Array.create (Array.length vp.vfields) ("",DSimple HVoid) in + let td = DVirtual arr in + types_descs := PMap.add vp td (!types_descs); + Array.iteri (fun i (f,_,t) -> arr.(i) <- (f,make_desc t)) vp.vfields; + td + in + let make_sign d = + String.sub (Digest.to_hex (Digest.bytes (Marshal.to_bytes d [Marshal.Compat_32]))) 0 7 + in + let rec desc_string d = + match d with + | DSimple (HNull t) -> + "t$nul_" ^ tstr t + | DSimple (HRef t) -> + "t$ref_" ^ (match make_desc t with DSimple _ -> tstr t | d -> desc_string d) + | DSimple t -> + "t$_" ^ tstr t + | DFun _ -> + "t$fun_" ^ make_sign d + | DNamed n -> + "t$" ^ (String.concat "_" (ExtString.String.nsplit n ".")) + | DVirtual _ -> + "t$vrt_" ^ (make_sign d) + | DContext _ -> + "t$ctx_" ^ (make_sign d) + in + PMap.mapi (fun t _ -> desc_string (make_desc t)) htypes + +let make_global_names code gnames = + let hstrings = Hashtbl.create 0 in + let is_cstr = Hashtbl.create 0 in + Array.iter (fun (g,vl) -> + match code.globals.(g) with + | HObj { pname = "String" } -> + let str = code.strings.(vl.(0)) in + let v = valid_ident str in + Hashtbl.replace hstrings v (Hashtbl.mem hstrings v); + Hashtbl.add is_cstr g (); + gnames.(g) <- str + | _ -> () + ) code.constants; + let gids = Array.mapi (fun i n -> (n,i)) gnames in + Array.sort (fun (n1,g1) (n2,g2) -> let d = compare n1 n2 in if d = 0 then compare g1 g2 else d) gids; + let gnames_used = Hashtbl.create 0 in + let gnames = Hashtbl.create 0 in + Array.iter (fun (str,g) -> + let id = (if Hashtbl.mem is_cstr g then "s$" else "g$") ^ (if String.length str > 32 then short_digest str else let i = valid_ident str in if i = "_" || (try Hashtbl.find hstrings i with Not_found -> false) then short_digest str else i) in + let rec loop id k = + let rid = if k = 0 then id else id ^ "_" ^ string_of_int k in + if Hashtbl.mem gnames_used rid then loop id (k+1) else rid + in + let id = loop id 0 in + Hashtbl.add gnames_used id (); + Hashtbl.add gnames g id; + ) gids; + Array.init (Array.length code.globals) (fun i -> Hashtbl.find gnames i) + +let make_function_table code = + let new_entry i = { fe_index = i; fe_args = []; fe_ret = HVoid; fe_name = ""; fe_module = None; fe_calling = []; fe_called_by = []; fe_decl = None; } in + let ftable = Array.init (Array.length code.functions + Array.length code.natives) new_entry in + Array.iter (fun (lib,name,t,idx) -> + let fname = + let lib = code.strings.(lib) in + let lib = if lib = "std" then "hl" else lib in + lib ^ "_" ^ code.strings.(name) + in + match t with + | HFun (args, t) -> + let ft = ftable.(idx) in + ft.fe_name <- fname; + ft.fe_args <- args; + ft.fe_ret <- t + | _ -> + assert false + ) code.natives; Array.iter (fun f -> - Array.iteri (fun i op -> + let fname = String.concat "_" (ExtString.String.nsplit (fundecl_name f) ".") in + let ft = ftable.(f.findex) in + ft.fe_name <- fname; + (match f.ftype with + | HFun (args,t) -> + ft.fe_args <- args; + ft.fe_ret <- t; + | _ -> + assert false); + ft.fe_decl <- Some f; + Array.iter (fun op -> match op with - | OStaticClosure (_,fid) -> - Hashtbl.replace used_closures fid () - | OBytes (_,sid) -> - Hashtbl.replace bytes_strings sid () + | OCall0 (_,fid) + | OCall1 (_,fid,_) + | OCall2 (_,fid,_,_) + | OCall3 (_,fid,_,_,_) + | OCall4 (_,fid,_,_,_,_) + | OCallN (_,fid,_) + | OStaticClosure (_,fid) + | OInstanceClosure (_,fid,_) -> + let ft2 = ftable.(fid) in + if not (List.memq ft ft2.fe_called_by) then begin + ft2.fe_called_by <- ft :: ft2.fe_called_by; + ft.fe_calling <- ft2 :: ft.fe_calling; + end; | _ -> () - ) f.code + ) f.code; ) code.functions; - - open_file ctx "hl/typedefs.h"; - line "// Types definitions"; + ftable + +let make_modules ctx all_types = + let modules = Hashtbl.create 0 in + let all_modules = ref [] in + let get_module name = + try + Hashtbl.find modules name + with Not_found -> + let m = { + m_name = name; + m_functions = []; + m_types = []; + } in + Hashtbl.add modules name m; + all_modules := m :: !all_modules; + m + in + let add m fid = + let f = ctx.ftable.(fid) in + if f.fe_module <> None then assert false; + f.fe_module <- Some m; + m.m_functions <- f :: m.m_functions; + in + let add_type m t = + m.m_types <- t :: m.m_types; + ctx.type_module <- PMap.add t m ctx.type_module; + in + let mk_name path = + let base_name, path = match List.rev (ExtString.String.nsplit path ".") with + | [] -> "enums", ["hl"] + | name :: acc -> (if name.[0] = '$' then String.sub name 1 (String.length name - 1) else name), List.rev acc + in + let path = path @ [base_name] in + let path = List.map (fun n -> if String.length n > 128 then Digest.to_hex (Digest.string n) else n) path in + let path = (match path with [name] -> ["_std";name] | _ -> path) in + String.concat "/" path + in + let all_contexts = ref [] in Array.iter (fun t -> match t with - | HObj o -> - let name = tname o.pname in - expr ("typedef struct _" ^ name ^ " *" ^ name); - | HAbstract (name,_) -> - expr ("typedef struct _" ^ name ^ " " ^ name); + | HObj o | HStruct o -> + let m = get_module (mk_name o.pname) in + Array.iter (fun p -> add m p.fmethod) o.pproto; + List.iter (fun (_,mid) -> add m mid) o.pbindings; + add_type m t + | HEnum e when e.ename = "" -> + all_contexts := t :: !all_contexts + | HEnum e -> + let m = get_module (mk_name e.ename) in + add_type m t | _ -> () ) all_types; - - line ""; - line "// Types implementation"; - - Array.iter (fun t -> + let ep = ctx.hlcode.entrypoint in + if ep >= 0 then begin + let m = get_module "hl/init" in + add m ep; + ctx.ftable.(ep).fe_name <- "fun$init"; + end; + List.iter (fun m -> + let rec get_deps acc = function + | [] -> acc + | fm :: fl -> + let counter = ref 1 in + let rec loop acc = function + | [] -> acc + | f :: l when f.fe_module = None && List.length f.fe_called_by = 1 && f.fe_decl <> None -> + f.fe_name <- fm.fe_name ^ "__$" ^ (string_of_int !counter); + incr counter; + f.fe_module <- Some m; + loop (append f acc) l + | _ :: l -> + loop acc l + and append f acc = + loop (f :: acc) (List.rev f.fe_calling) + in + get_deps (append fm acc) fl + in + m.m_functions <- get_deps [] m.m_functions + ) !all_modules; + let contexts = ref PMap.empty in + Array.iter (fun f -> + if f.fe_module = None && ExtString.String.starts_with f.fe_name "fun$" then f.fe_name <- "wrap" ^ type_name ctx (match f.fe_decl with None -> assert false | Some f -> f.ftype); + (* assign context to function module *) + match f.fe_args with + | (HEnum e) as t :: _ when e.ename = "" -> + (try + let r = PMap.find t !contexts in + (match r with + | None -> () + | Some m when (match f.fe_module with Some m2 -> m == m2 | _ -> false) -> () + | _ -> contexts := PMap.add t None !contexts) (* multiple contexts *) + with Not_found -> + contexts := PMap.add t f.fe_module !contexts) + | _ -> () + ) ctx.ftable; + List.iter (fun t -> + let m = (try PMap.find t !contexts with Not_found -> None) in + let m = (match m with + | None -> + let tname = PMap.find t ctx.htypes in + get_module ("hl/ctx/" ^ String.sub tname 8 (String.length tname - 8)) + | Some m -> + m + ) in + add_type m t + ) (List.rev !all_contexts); + !all_modules + +let generate_module_types ctx m = + let def_name = "INC_" ^ String.concat "__" (ExtString.String.nsplit m.m_name "/") in + let line = line ctx and expr = expr ctx and sexpr fmt = Printf.ksprintf (expr ctx) fmt in + let type_name t = + match t with + | HObj o | HStruct o -> o.pname + | HEnum e -> e.ename + | _ -> "" + in + let types = List.sort (fun t1 t2 -> compare (type_name t1) (type_name t2)) m.m_types in + define ctx (sprintf "#ifndef %s" def_name); + define ctx (sprintf "#define %s" def_name); + List.iter (fun t -> match t with - | HObj o -> + | HObj o | HStruct o -> let name = tname o.pname in + ctx.defined_types <- PMap.add t () ctx.defined_types; + define ctx (sprintf "typedef struct _%s *%s;" name name); + | _ -> () + ) types; + line ""; + List.iter (fun t -> + match t with + | HObj op | HStruct op -> + let name = tname op.pname in line ("struct _" ^ name ^ " {"); block ctx; let rec loop o = (match o.psuper with - | None -> expr ("hl_type *$type"); - | Some c -> loop c); + | None -> + if not (is_struct t) then expr ("hl_type *$type"); + | Some c -> + define_type ctx (if is_struct t then HStruct c else HObj c); + loop c); Array.iteri (fun i (n,_,t) -> let rec abs_index p v = match p with | None -> v | Some o -> abs_index o.psuper (Array.length o.pfields + v) in + define_type ctx t; expr (var_type (if n = "" then unamed_field (abs_index o.psuper i) else n) t) ) o.pfields; in - loop o; + loop op; unblock ctx; expr "}"; | HEnum e -> @@ -1054,6 +1386,7 @@ let write_c com file (code:code) = block ctx; line "HL__ENUM_CONSTRUCT__"; Array.iteri (fun i t -> + define_type ctx t; expr (var_type ("p" ^ string_of_int i) t) ) pl; unblock ctx; @@ -1062,148 +1395,189 @@ let write_c com file (code:code) = ) e.efields | _ -> () - ) all_types; - - open_file ctx "hl/types.h"; - line "// Types values declaration"; - Array.iteri (fun i t -> - sexpr "extern hl_type type$%d" i; - match t with - | HObj o -> - sline "#define %s__val &type$%d" (tname o.pname) i - | _ -> - () - ) all_types; - line ""; - sexpr "void hl_init_types( hl_module_context *ctx )"; + ) types; + line "#endif"; + line "" - open_file ctx "hl/natives.h"; - line "// Natives functions"; - let native_libs = Hashtbl.create 0 in - Array.iter (fun (lib,name,t,idx) -> - match t with - | HFun (args,t) -> - let fname = - let lib = code.strings.(lib) in - Hashtbl.replace native_libs lib (); - let lib = if lib = "std" then "hl" else lib in - lib ^ "_" ^ code.strings.(name) - in - sexpr "HL_API %s %s(%s)" (ctype t) fname (String.concat "," (List.map ctype args)); - let ft = ctx.ftable.(idx) in - ft.fe_name <- fname; - ft.fe_args <- args; - ft.fe_ret <- t; - | _ -> - assert false - ) code.natives; - - open_file ctx "hl/functions.h"; - line "// Functions declaration"; - Array.iter (fun f -> - match f.ftype with - | HFun (args,t) -> - let fname = String.concat "_" (ExtString.String.nsplit (fundecl_name f) ".") in - sexpr "%s %s(%s)" (ctype t) fname (String.concat "," (List.map ctype args)); - let ft = ctx.ftable.(f.findex) in - ft.fe_name <- fname; - ft.fe_args <- args; - ft.fe_ret <- t; - ft.fe_decl <- Some f; - | _ -> - assert false - ) code.functions; - line ""; - sexpr "extern void *hl_functions_ptrs[]"; - sexpr "extern hl_type *hl_functions_types[]"; +let write_c com file (code:code) gnames = + let all_types, htypes = gather_types code in + let types_ids = make_types_idents htypes in + let gnames = make_global_names code gnames in + let bnames = Array.map (fun b -> "bytes$" ^ short_digest (Digest.to_hex (Digest.bytes b))) code.bytes in - open_file ctx "hl/globals.h"; - line "// Globals"; - Array.iteri (fun i t -> - let name = "global$" ^ string_of_int i in - sexpr "extern %s" (var_type name t) - ) code.globals; + let ctx = { + version = com.Common.version; + out = Buffer.create 1024; + tabs = ""; + hlcode = code; + hash_cache = Hashtbl.create 0; + hash_mem = Hashtbl.create 0; + hash_cache_list = []; + dir = (match Filename.dirname file with "" -> "." | dir -> String.concat "/" (ExtString.String.nsplit dir "\\")); + curfile = ""; + cfiles = []; + ftable = make_function_table code; + htypes = types_ids; + gnames = gnames; + bytes_names = bnames; + defines = []; + hdefines = Hashtbl.create 0; + defined_funs = Hashtbl.create 0; + defined_types = PMap.empty; + file_prefix = ""; + fun_index = 0; + type_module = PMap.empty; + } in + let modules = make_modules ctx all_types in - Array.iteri (fun i str -> - if Hashtbl.mem bytes_strings i then - sexpr "extern vbyte bytes$%d[]" i - else if String.length str >= string_data_limit then - sexpr "vbyte string$%d[]" i - ) code.strings; + let line = line ctx and expr = expr ctx in + let sline fmt = Printf.ksprintf line fmt and sexpr fmt = Printf.ksprintf expr fmt in - Hashtbl.iter (fun fid _ -> sexpr "extern vclosure cl$%d" fid) used_closures; + open_file ctx "hl/natives.h"; + define ctx "#ifndef HL_NATIVES_H"; + define ctx "#define HL_NATIVES_H"; + define ctx "// Abstract decls"; + let rec get_abstracts = function + | [] -> [] + | HAbstract (name,_) :: l -> name :: get_abstracts l + | _ :: l -> get_abstracts l + in + let abstracts = List.sort compare (get_abstracts (Array.to_list all_types)) in + List.iter (fun name -> define ctx (sprintf "typedef struct _%s %s;" name name)) abstracts; + define ctx ""; + line "// Natives functions"; + let native_libs = Hashtbl.create 0 in + let sorted_natives = Array.copy code.natives in + Array.sort (fun n1 n2 -> let mk (lib,name,_,_) = code.strings.(lib), code.strings.(name) in compare (mk n1) (mk n2)) sorted_natives; + Array.iter (fun (lib,_,_,idx) -> + Hashtbl.replace native_libs code.strings.(lib) (); + let ft = ctx.ftable.(idx) in + define_type ctx (HFun (ft.fe_args,ft.fe_ret)); + sexpr "HL_API %s %s(%s)" (ctype ft.fe_ret) ft.fe_name (args_repr ft.fe_args); + ) sorted_natives; + line "#endif"; line ""; - sexpr "void hl_init_roots()"; open_file ctx "hl/globals.c"; - line "#include "; + define ctx "#define HLC_BOOT"; + define ctx "#include "; line "// Globals"; Array.iteri (fun i t -> - let name = "global$" ^ string_of_int i in + let name = gnames.(i) in + define_type ctx t; sexpr "%s = 0" (var_type name t) ) code.globals; + Array.iter (fun (g,fields) -> + let t = code.globals.(g) in + let name = "const_" ^ gnames.(g) in + let field_value t idx = + match t with + | HI32 -> + Int32.to_string code.ints.(idx) + | HBytes -> + "(vbyte*)" ^ string ctx idx + | _ -> + assert false + in + let fields = match t with + | HObj o | HStruct o -> + let fields = List.map2 field_value (List.map (fun (_,_,t) -> t) (Array.to_list o.pfields)) (Array.to_list fields) in + if is_struct t then fields else type_value ctx t :: fields + | _ -> + assert false + in + sexpr "static struct _%s %s = {%s}" (ctype t) name (String.concat "," fields); + ) code.constants; line ""; line "void hl_init_roots() {"; block ctx; + let is_const = Hashtbl.create 0 in + Array.iter (fun (g,fields) -> + sexpr "%s = &const_%s" gnames.(g) gnames.(g); + Hashtbl.add is_const g true; + ) code.constants; Array.iteri (fun i t -> - if is_ptr t then sexpr "hl_add_root((void**)&global$%d)" i; + if is_ptr t && not (Hashtbl.mem is_const i) then sexpr "hl_add_root((void**)&%s)" gnames.(i); ) code.globals; unblock ctx; line "}"; + let output_bytes f str = + for i = 0 to String.length str - 1 do + if (i+1) mod 0x80 = 0 then f "\\\n\t"; + if i > 0 then f ","; + f (string_of_int (int_of_char str.[i])); + done + in Array.iteri (fun i str -> - let rec loop s i = - if i = String.length s then [] else - let c = String.get s i in - string_of_int (int_of_char c) :: loop s (i+1) - in - if Hashtbl.mem bytes_strings i then - sexpr "vbyte bytes$%d[] = {%s}" i (String.concat "," (loop str 0)) - else if String.length str >= string_data_limit then - let s = utf8_to_utf16 str in + if String.length str >= string_data_limit then begin + let s = Common.utf8_to_utf16 str true in sline "// %s..." (String.escaped (String.sub str 0 (string_data_limit-4))); - sexpr "vbyte string$%d[] = {%s}" i (String.concat "," (loop s 0)) + output ctx (Printf.sprintf "vbyte string$%s[] = {" (short_digest str)); + output_bytes (output ctx) s; + sexpr "}"; + end ) code.strings; - - Hashtbl.iter (fun fid _ -> - let ft = ctx.ftable.(fid) in - sexpr "vclosure cl$%d = { %s, %s, 0 }" fid (type_value ctx (HFun (ft.fe_args,ft.fe_ret))) ft.fe_name - ) used_closures; - + Array.iteri (fun i bytes -> + if Bytes.length bytes > 1000 then begin + let bytes_file = "hl/bytes_" ^ (Digest.to_hex (Digest.bytes bytes)) ^ ".h" in + let abs_file = ctx.dir ^ "/" ^ bytes_file in + if not (Sys.file_exists abs_file) then begin + let ch = open_out_bin abs_file in + output_bytes (output_string ch) (Bytes.to_string bytes); + close_out ch; + end; + sline "vbyte %s[] = {" ctx.bytes_names.(i); + output ctx (Printf.sprintf "#%s include \"%s\"\n" ctx.tabs bytes_file); + sexpr "}"; + end else begin + output ctx (Printf.sprintf "vbyte %s[] = {" ctx.bytes_names.(i)); + output_bytes (output ctx) (Bytes.to_string bytes); + sexpr "}"; + end + ) code.bytes; + + let type_value ctx t = "&" ^ type_name ctx t in (* no auto import *) open_file ctx "hl/types.c"; - line "#include "; + define ctx "#define HLC_BOOT"; + define ctx "#include "; line "// Types values"; Array.iteri (fun i t -> - sexpr "hl_type type$%d = { %s } /* %s */" i (type_id t) (tstr t); + match t with + | HMethod _ | HFun _ | HVirtual _ -> + sexpr "hl_type %s = { %s } /* %s */" (type_name ctx t) (type_id t) (tstr t); + | _ -> + sexpr "hl_type %s = { %s }" (type_name ctx t) (type_id t); ) all_types; line ""; line "// Types values data"; - Array.iteri (fun i t -> + Array.iter (fun t -> let field_value (_,name_id,t) = sprintf "{(const uchar*)%s, %s, %ld}" (string ctx name_id) (type_value ctx t) (hash ctx name_id) in match t with - | HObj o -> + | HObj o | HStruct o -> + let name = type_name ctx t in let proto_value p = sprintf "{(const uchar*)%s, %d, %d, %ld}" (string ctx p.fid) p.fmethod (match p.fvirtual with None -> -1 | Some i -> i) (hash ctx p.fid) in let fields = if Array.length o.pfields = 0 then "NULL" else - let name = sprintf "fields$%d" i in + let name = sprintf "fields%s" name in sexpr "static hl_obj_field %s[] = {%s}" name (String.concat "," (List.map field_value (Array.to_list o.pfields))); name in let proto = if Array.length o.pproto = 0 then "NULL" else - let name = sprintf "proto$%d" i in + let name = sprintf "proto%s" name in sexpr "static hl_obj_proto %s[] = {%s}" name (String.concat "," (List.map proto_value (Array.to_list o.pproto))); name in let bindings = if o.pbindings = [] then "NULL" else - let name = sprintf "bindings$%d" i in + let name = sprintf "bindings%s" name in sexpr "static int %s[] = {%s}" name (String.concat "," (List.map (fun (fid,fidx) -> string_of_int fid ^ "," ^ string_of_int fidx) o.pbindings)); name in @@ -1212,40 +1586,45 @@ let write_c com file (code:code) = string_of_int (Array.length o.pproto); string_of_int (List.length o.pbindings); sprintf "(const uchar*)%s" (string ctx o.pid); - (match o.psuper with None -> "NULL" | Some c -> sprintf "%s__val" (tname c.pname)); + (match o.psuper with None -> "NULL" | Some c -> type_value ctx (HObj c)); fields; proto; bindings ] in - sexpr "static hl_type_obj obj$%d = {%s}" i (String.concat "," ofields); + sexpr "static hl_type_obj obj%s = {%s}" name (String.concat "," ofields); | HEnum e -> - let constr_name = sprintf "econstructs$%d" i in + let ename = type_name ctx t in let constr_value cid (name,nid,tl) = let tval = if Array.length tl = 0 then "NULL" else - let name = sprintf "econstruct$%d_%d" i cid in + let name = sprintf "econstruct%s_%d" ename cid in sexpr "static hl_type *%s[] = {%s}" name (String.concat "," (List.map (type_value ctx) (Array.to_list tl))); name in let size = if Array.length tl = 0 then "0" else sprintf "sizeof(%s)" (enum_constr_type ctx e cid) in let offsets = if Array.length tl = 0 then "NULL" else - let name = sprintf "eoffsets$%d_%d" i cid in + let name = sprintf "eoffsets%s_%d" ename cid in sexpr "static int %s[] = {%s}" name (String.concat "," (List.map (fun _ -> "0") (Array.to_list tl))); name in let has_ptr = List.exists is_gc_ptr (Array.to_list tl) in sprintf "{(const uchar*)%s, %d, %s, %s, %s, %s}" (string ctx nid) (Array.length tl) tval size (if has_ptr then "true" else "false") offsets in - sexpr "static hl_enum_construct %s[] = {%s}" constr_name (String.concat "," (Array.to_list (Array.mapi constr_value e.efields))); + let constr_name = if Array.length e.efields = 0 then "NULL" else begin + let name = sprintf "econstruct%s" ename in + sexpr "static hl_enum_construct %s[] = {%s}" name (String.concat "," (Array.to_list (Array.mapi constr_value e.efields))); + name; + end in let efields = [ if e.eid = 0 then "NULL" else sprintf "(const uchar*)%s" (string ctx e.eid); string_of_int (Array.length e.efields); constr_name ] in - sexpr "static hl_type_enum enum$%d = {%s}" i (String.concat "," efields); + sexpr "static hl_type_enum enum%s = {%s}" ename (String.concat "," efields); | HVirtual v -> + let vname = type_name ctx t in let fields_name = if Array.length v.vfields = 0 then "NULL" else - let name = sprintf "vfields$%d" i in + let name = sprintf "vfields%s" vname in sexpr "static hl_obj_field %s[] = {%s}" name (String.concat "," (List.map field_value (Array.to_list v.vfields))); name in @@ -1253,14 +1632,15 @@ let write_c com file (code:code) = fields_name; string_of_int (Array.length v.vfields) ] in - sexpr "static hl_type_virtual virt$%d = {%s}" i (String.concat "," vfields); - | HFun (args,t) -> + sexpr "static hl_type_virtual virt%s = {%s}" vname (String.concat "," vfields); + | HFun (args,ret) | HMethod(args,ret) -> + let fname = type_name ctx t in let aname = if args = [] then "NULL" else - let name = sprintf "fargs$%d" i in + let name = sprintf "fargs%s" fname in sexpr "static hl_type *%s[] = {%s}" name (String.concat "," (List.map (type_value ctx) args)); name in - sexpr "static hl_type_fun tfun$%d = {%s,%s,%d}" i aname (type_value ctx t) (List.length args) + sexpr "static hl_type_fun tfun%s = {%s,%s,%d}" fname aname (type_value ctx ret) (List.length args) | _ -> () ) all_types; @@ -1268,23 +1648,35 @@ let write_c com file (code:code) = line ""; line "void hl_init_types( hl_module_context *ctx ) {"; block ctx; - Array.iteri (fun i t -> + Array.iter (fun t -> match t with - | HObj o -> - sexpr "obj$%d.m = ctx" i; - (match o.pclassglobal with None -> () | Some g -> sexpr "obj$%d.global_value = (void**)&global$%d" i g); - sexpr "type$%d.obj = &obj$%d" i i - | HNull t | HRef t -> - sexpr "type$%d.tparam = %s" i (type_value ctx t) + | HObj o | HStruct o -> + let name = type_name ctx t in + sexpr "obj%s.m = ctx" name; + (match o.pclassglobal with + | None -> () + | Some g -> + define_global ctx g; + sexpr "obj%s.global_value = (void**)&%s" name gnames.(g)); + sexpr "%s.obj = &obj%s" name name + | HNull r | HRef r -> + sexpr "%s.tparam = %s" (type_name ctx t) (type_value ctx r) | HEnum e -> - sexpr "type$%d.tenum = &enum$%d" i i; - (match e.eglobal with None -> () | Some g -> sexpr "enum$%d.global_value = (void**)&global$%d" i g); - sexpr "hl_init_enum(&type$%d,ctx)" i; + let name = type_name ctx t in + sexpr "%s.tenum = &enum%s" name name; + (match e.eglobal with + | None -> () + | Some g -> + define_global ctx g; + sexpr "enum%s.global_value = (void**)&%s" name gnames.(g)); + sexpr "hl_init_enum(&%s,ctx)" name; | HVirtual _ -> - sexpr "type$%d.virt = &virt$%d" i i; - sexpr "hl_init_virtual(&type$%d,ctx)" i; - | HFun _ -> - sexpr "type$%d.fun = &tfun$%d" i i + let name = type_name ctx t in + sexpr "%s.virt = &virt%s" name name; + sexpr "hl_init_virtual(&%s,ctx)" name; + | HFun _ | HMethod _ -> + let name = type_name ctx t in + sexpr "%s.fun = &tfun%s" name name | _ -> () ) all_types; @@ -1292,84 +1684,67 @@ let write_c com file (code:code) = line "}"; open_file ctx "hl/reflect.c"; - line "#include "; + define ctx "#define HLC_BOOT"; + define ctx "#include "; line "// Reflection helpers"; generate_reflection ctx; - let gen_functions = Hashtbl.create 0 in - let all_protos = Hashtbl.create 0 in - Array.iter (fun t -> - match t with - | HObj o -> - Hashtbl.add all_protos o.pname o - | _ -> () - ) all_types; - - Array.iter (fun t -> - match t with - | HObj o when Hashtbl.mem all_protos o.pname -> - let file = ref false in - let base_name, path = match List.rev (ExtString.String.nsplit o.pname ".") with - | [] -> assert false - | name :: acc -> (if name.[0] = '$' then String.sub name 1 (String.length name - 1) else name), List.rev acc - in - let generate fid = - match ctx.ftable.(fid).fe_decl with - | None -> () - | Some f -> - if not !file then begin - file := true; - let path = path @ [base_name] in - let path = List.map (fun n -> if String.length n > 128 then Digest.to_hex (Digest.string n) else n) path in - let path = (match path with [name] -> ["_std";name] | _ -> path) in - open_file ctx (String.concat "/" path ^ ".c"); - line "#include "; - line ""; - end; - Hashtbl.replace gen_functions f.findex (); - generate_function ctx f - in - let gen_proto name = - try - let full_name = String.concat "." (path @ [name]) in - let o = Hashtbl.find all_protos full_name in - Array.iter (fun p -> generate p.fmethod) o.pproto; - List.iter (fun (_,mid) -> generate mid) o.pbindings; - Hashtbl.remove all_protos full_name; - with Not_found -> - () + List.iter (fun m -> + let defined_types = ref PMap.empty in + if m.m_types <> [] then begin + open_file ctx (m.m_name ^ ".h"); + generate_module_types ctx m; + defined_types := ctx.defined_types; + end; + if m.m_functions <> [] then begin + open_file ctx (m.m_name ^ ".c"); + ctx.defined_types <- !defined_types; + define ctx "#define HLC_BOOT"; + define ctx "#include "; + if m.m_types <> [] then define ctx (sprintf "#include <%s.h>" m.m_name); + let file_pos f = + match f.fe_decl with + | Some f when Array.length f.debug > 0 -> + let fid, p = f.debug.(Array.length f.debug - 1) in + (code.strings.(fid), p) + | _ -> + ("",0) in - gen_proto base_name; - gen_proto ("$" ^ base_name); - | _ -> () - ) all_types; + let funcs = List.sort (fun f1 f2 -> compare (file_pos f1) (file_pos f2)) m.m_functions in + List.iter (fun fe -> match fe.fe_decl with None -> () | Some f -> generate_function ctx f) funcs; + end; + ) modules; open_file ctx "hl/functions.c"; - line "#include "; - line ""; - sexpr "void *hl_functions_ptrs[] = {%s}" (String.concat "," (List.map (fun f -> f.fe_name) (Array.to_list ctx.ftable))); + define ctx "#define HLC_BOOT"; + define ctx "#include "; + sexpr "void *hl_functions_ptrs[] = {%s}" (String.concat "," (List.map (fun f -> define_function ctx f.fe_index) (Array.to_list ctx.ftable))); let rec loop i = if i = Array.length ctx.ftable then [] else let ft = ctx.ftable.(i) in - (type_value ctx (HFun (ft.fe_args,ft.fe_ret))) :: loop (i + 1) + let n = type_name ctx (HFun (ft.fe_args,ft.fe_ret)) in + define ctx (sprintf "extern hl_type %s;" n); + ("&" ^ n) :: loop (i + 1) in sexpr "hl_type *hl_functions_types[] = {%s}" (String.concat "," (loop 0)); line ""; Array.iter (fun f -> - if not (Hashtbl.mem gen_functions f.findex) then generate_function ctx f; - ) code.functions; + if f.fe_module = None then (match f.fe_decl with None -> () | Some f -> generate_function ctx f); + ) ctx.ftable; open_file ctx "hl/hashes.c"; - line "#include "; + define ctx "#define HLC_BOOT"; + define ctx "#include "; line ""; line "void hl_init_hashes() {"; block ctx; - Hashtbl.iter (fun i _ -> sexpr "hl_hash((vbyte*)%s)" (string ctx i)) ctx.hash_cache; + List.iter (fun i -> sexpr "hl_hash((vbyte*)%s)" (string ctx i)) (List.rev ctx.hash_cache_list); unblock ctx; line "}"; open_file ctx (Filename.basename file); - line "#include "; + define ctx "#define HLC_BOOT"; + define ctx "#include "; line "#include "; line ""; line "#ifndef HL_MAKE"; @@ -1377,6 +1752,10 @@ let write_c com file (code:code) = line "#endif"; line ""; expr "void hl_init_hashes()"; + expr "void hl_init_roots()"; + expr "void hl_init_types( hl_module_context *ctx )"; + expr "extern void *hl_functions_ptrs[]"; + expr "extern hl_type *hl_functions_types[]"; line ""; line "// Entry point"; line "void hl_entry_point() {"; @@ -1388,7 +1767,7 @@ let write_c com file (code:code) = expr "hl_init_types(&ctx)"; expr "hl_init_hashes()"; expr "hl_init_roots()"; - sexpr "%s()" ctx.ftable.(code.entrypoint).fe_name; + if code.entrypoint >= 0 then sexpr "%s()" (define_function ctx code.entrypoint); unblock ctx; line "}"; line ""; @@ -1399,7 +1778,7 @@ let write_c com file (code:code) = block ctx; sline "\"version\" : %d," ctx.version; sline "\"libs\" : [%s]," (String.concat "," (Hashtbl.fold (fun k _ acc -> sprintf "\"%s\"" k :: acc) native_libs [])); - sline "\"defines\" : {%s\n\t}," (String.concat "," (PMap.foldi (fun k v acc -> sprintf "\n\t\t\"%s\" : \"%s\"" k v :: acc) com.Common.defines.Define.values [])); + sline "\"defines\" : {%s\n\t}," (String.concat "," (PMap.foldi (fun k v acc -> sprintf "\n\t\t\"%s\" : \"%s\"" (String.escaped k) (String.escaped v) :: acc) com.Common.defines.Define.values [])); sline "\"files\" : [%s\n\t]" (String.concat "," (List.map (sprintf "\n\t\t\"%s\"") ctx.cfiles)); unblock ctx; line "}"; diff --git a/src/generators/hlcode.ml b/src/generators/hlcode.ml index 5d02db36d0d..b9cc7a6b184 100644 --- a/src/generators/hlcode.ml +++ b/src/generators/hlcode.ml @@ -1,5 +1,5 @@ (* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -46,6 +46,8 @@ type ttype = | HAbstract of string * string index | HEnum of enum_proto | HNull of ttype + | HMethod of ttype list * ttype + | HStruct of class_proto and class_proto = { pname : string; @@ -206,6 +208,7 @@ type fundecl = { regs : ttype array; code : opcode array; debug : (int * int) array; + assigns : (string index * int) array; } type code = { @@ -214,11 +217,13 @@ type code = { strings : string array; ints : int32 array; floats : float array; + bytes : bytes array; (* types : ttype array // only in bytecode, rebuilt on save() *) globals : ttype array; natives : (string index * string index * ttype * functable index) array; functions : fundecl array; debugfiles : string array; + constants : (global * int array) array; } let null_proto = @@ -250,9 +255,12 @@ let list_mapi f l = *) let is_nullable t = match t with - | HBytes | HDyn | HFun _ | HObj _ | HArray | HVirtual _ | HDynObj | HAbstract _ | HEnum _ | HNull _ | HRef _ -> true - | HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64 | HBool | HVoid | HType -> false + | HBytes | HDyn | HFun _ | HObj _ | HArray | HVirtual _ | HDynObj | HAbstract _ | HEnum _ | HNull _ | HRef _ | HType | HMethod _ | HStruct _ -> true + | HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64 | HBool | HVoid -> false +let is_struct = function + | HStruct _ -> true + | _ -> false let is_int = function | HUI8 | HUI16 | HI32 | HI64 -> true @@ -278,8 +286,10 @@ let rec tsame t1 t2 = if t1 == t2 then true else match t1, t2 with | HFun (args1,ret1), HFun (args2,ret2) when List.length args1 = List.length args2 -> List.for_all2 tsame args1 args2 && tsame ret2 ret1 + | HMethod (args1,ret1), HMethod (args2,ret2) when List.length args1 = List.length args2 -> List.for_all2 tsame args1 args2 && tsame ret2 ret1 | HObj p1, HObj p2 -> p1 == p2 | HEnum e1, HEnum e2 -> e1 == e2 + | HStruct p1, HStruct p2 -> p1 == p2 | HAbstract (_,a1), HAbstract (_,a2) -> a1 == a2 | HVirtual v1, HVirtual v2 -> if v1 == v2 then true else @@ -316,6 +326,12 @@ let rec safe_cast t1 t2 = p.pname = p2.pname || (match p.psuper with None -> false | Some p -> loop p) in loop p1 + | HStruct p1, HStruct p2 -> + (* allow subtyping *) + let rec loop p = + p.pname = p2.pname || (match p.psuper with None -> false | Some p -> loop p) + in + loop p1 | HFun (args1,t1), HFun (args2,t2) when List.length args1 = List.length args2 -> List.for_all2 (fun t1 t2 -> safe_cast t2 t1 || (t1 = HDyn && is_dynamic t2)) args1 args2 && safe_cast t1 t2 | _ -> @@ -333,27 +349,6 @@ let hl_hash b = in loop 0 -let utf16_add buf c = - let add c = - Buffer.add_char buf (char_of_int (c land 0xFF)); - Buffer.add_char buf (char_of_int (c lsr 8)); - in - if c >= 0 && c < 0x10000 then begin - if c >= 0xD800 && c <= 0xDFFF then failwith ("Invalid unicode char " ^ string_of_int c); - add c; - end else if c < 0x110000 then begin - let c = c - 0x10000 in - add ((c asr 10) + 0xD800); - add ((c land 1023) + 0xDC00); - end else - failwith ("Invalid unicode char " ^ string_of_int c) - -let utf8_to_utf16 str = - let b = Buffer.create (String.length str * 2) in - (try UTF8.iter (fun c -> utf16_add b (UChar.code c)) str with Invalid_argument _ | UChar.Out_of_range -> ()); (* if malformed *) - utf16_add b 0; - Buffer.contents b - let rec get_index name p = try PMap.find name p.pindex @@ -393,10 +388,10 @@ let gather_types (code:code) = DynArray.add arr t; types := PMap.add t index !types; match t with - | HFun (args, ret) -> + | HFun (args, ret) | HMethod (args, ret) -> List.iter get_type args; get_type ret - | HObj p -> + | HObj p | HStruct p -> Array.iter (fun (_,n,t) -> get_type t) p.pfields | HNull t | HRef t -> get_type t @@ -439,11 +434,14 @@ let rec tstr ?(stack=[]) ?(detailed=false) t = | HBytes -> "bytes" | HDyn -> "dyn" | HFun (args,ret) -> "(" ^ String.concat "," (List.map (tstr ~stack ~detailed) args) ^ "):" ^ tstr ~stack ~detailed ret - | HObj o when not detailed -> "#" ^ o.pname - | HObj o -> + | HMethod (args,ret) -> "method:(" ^ String.concat "," (List.map (tstr ~stack ~detailed) args) ^ "):" ^ tstr ~stack ~detailed ret + | HObj o when not detailed -> o.pname + | HStruct s when not detailed -> "@" ^ s.pname + | HObj o | HStruct o -> let fields = "{" ^ String.concat "," (List.map (fun(s,_,t) -> s ^ " : " ^ tstr ~detailed:false t) (Array.to_list o.pfields)) ^ "}" in let proto = "{" ^ String.concat "," (List.map (fun p -> (match p.fvirtual with None -> "" | Some _ -> "virtual ") ^ p.fname ^ "@" ^ string_of_int p.fmethod) (Array.to_list o.pproto)) ^ "}" in - "#" ^ o.pname ^ "[" ^ (match o.psuper with None -> "" | Some p -> ">" ^ p.pname ^ " ") ^ "fields=" ^ fields ^ " proto=" ^ proto ^ "]" + let str = o.pname ^ "[" ^ (match o.psuper with None -> "" | Some p -> ">" ^ p.pname ^ " ") ^ "fields=" ^ fields ^ " proto=" ^ proto ^ "]" in + (match t with HObj o -> str | _ -> "@" ^ str) | HArray -> "array" | HType -> @@ -600,6 +598,10 @@ let dump pr code = Array.iteri (fun i s -> pr (" @" ^ string_of_int i ^ " : " ^ String.escaped s); ) code.strings; + pr (string_of_int (Array.length code.bytes) ^ " bytes"); + Array.iteri (fun i s -> + pr (" @" ^ string_of_int i ^ " : " ^ string_of_int (Bytes.length s)); + ) code.bytes; pr (string_of_int (Array.length code.ints) ^ " ints"); Array.iteri (fun i v -> pr (" @" ^ string_of_int i ^ " : " ^ Int32.to_string v); @@ -660,4 +662,8 @@ let dump pr code = List.iter (fun (i,fidx) -> pr (" @" ^ string_of_int i ^ " fun@" ^ string_of_int fidx) ) p.pbindings; - ) protos + ) protos; + pr (string_of_int (Array.length code.constants) ^ " constant values"); + Array.iter (fun (g,fields) -> + pr (Printf.sprintf " @%d %s [%s]" g (tstr code.globals.(g)) (String.concat "," (List.map string_of_int (Array.to_list fields)))); + ) code.constants diff --git a/src/generators/hlinterp.ml b/src/generators/hlinterp.ml index a7bc42ce726..e5750331086 100644 --- a/src/generators/hlinterp.ml +++ b/src/generators/hlinterp.ml @@ -1,5 +1,5 @@ (* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -41,6 +41,7 @@ type value = | VEnum of enum_proto * int * value array | VAbstract of vabstract | VVarArgs of vfunction * value option + | VStruct of vobject and ref_value = | RStack of int @@ -163,6 +164,7 @@ let rec is_compatible v t = | VRef (_,t1), HRef t2 -> tsame t1 t2 | VAbstract _, HAbstract _ -> true | VEnum _, HEnum _ -> true + | VStruct v, HStruct _ -> safe_cast (HStruct v.oproto.pclass) t | _ -> false type cast = @@ -204,6 +206,10 @@ let alloc_obj ctx t = let obj = VObj { oproto = p; ofields = ftable } in List.iter (fun (fid,mk) -> ftable.(fid) <- mk obj) bindings; obj + | HStruct p -> + let p, fields, bindings = get_proto ctx p in + let ftable = Array.map default fields in + VStruct { oproto = p; ofields = ftable } | HVirtual v -> let o = { dfields = Hashtbl.create 0; @@ -286,7 +292,7 @@ let fstr = function | FFun f -> "function@" ^ string_of_int f.findex | FNativeFun (s,_,_) -> "native[" ^ s ^ "]" -let caml_to_hl str = utf8_to_utf16 str +let caml_to_hl str = Common.utf8_to_utf16 str true let hash ctx str = let h = hl_hash str in @@ -311,7 +317,7 @@ let utf16_iter f s = loop 0 let utf16_char buf c = - utf16_add buf (int_of_char c) + Common.utf16_add buf (int_of_char c) let hl_to_caml str = let utf16_eof s = @@ -346,7 +352,7 @@ let rec vstr_d ctx v = | VBool b -> if b then "true" else "false" | VDyn (v,t) -> "dyn(" ^ vstr_d v ^ ":" ^ tstr t ^ ")" | VObj o -> - let p = "#" ^ o.oproto.pclass.pname in + let p = o.oproto.pclass.pname in (match get_to_string ctx o.oproto.pclass with | Some f -> p ^ ":" ^ vstr_d (ctx.fcall f [v]) | None -> p) @@ -364,6 +370,7 @@ let rec vstr_d ctx v = | VEnum (e,i,vals) -> let n, _, _ = e.efields.(i) in if Array.length vals = 0 then n else n ^ "(" ^ String.concat "," (Array.to_list (Array.map vstr_d vals)) ^ ")" | VAbstract _ -> "abstract" | VVarArgs _ -> "varargs" + | VStruct v -> "@" ^ v.oproto.pclass.pname let rec to_virtual ctx v vp = match v with @@ -563,7 +570,7 @@ let rec dyn_get_field ctx obj field rt = get_with d.dvalues.(idx) d.dtypes.(idx) with Not_found -> default rt) - | VObj o -> + | VObj o | VDyn (VStruct o, HStruct _) -> let default rt = match get_method o.oproto.pclass "__get_field" with | None -> default rt @@ -665,6 +672,14 @@ let stack_frame ctx (f,pos) = let file, line = make_stack ctx (f,pos) in Printf.sprintf "%s:%d: Called from fun@%d @x%X" file line f.findex (!pos - 1) +let cached_string ctx idx = + try + Hashtbl.find ctx.cached_strings idx + with Not_found -> + let s = caml_to_hl ctx.code.strings.(idx) in + Hashtbl.add ctx.cached_strings idx s; + s + let virt_make_val v = let hfields = Hashtbl.create 0 in let ftypes = DynArray.create() in @@ -697,7 +712,7 @@ let rec vstr ctx v t = vstr v t | VObj o -> (match get_to_string ctx o.oproto.pclass with - | None -> "#" ^ o.oproto.pclass.pname + | None -> o.oproto.pclass.pname | Some f -> vstr (ctx.fcall f [v]) HBytes) | VBytes b -> (try hl_to_caml b with _ -> "?" ^ String.escaped b) | VClosure (f,_) -> fstr f @@ -730,6 +745,7 @@ let rec vstr ctx v t = in n ^ "(" ^ String.concat "," (loop 0) ^ ")" | VVarArgs _ -> "varargs" + | VStruct s -> "@" ^ s.oproto.pclass.pname let interp ctx f args = let func = get_function ctx in @@ -756,14 +772,6 @@ let interp ctx f args = let check v t id = if ctx.checked && not (is_compatible v t) then error (Printf.sprintf "Can't set %s(%s) with %s" (id()) (tstr t) (vstr_d ctx v)) in - let cached_string idx = - try - Hashtbl.find ctx.cached_strings idx - with Not_found -> - let s = caml_to_hl ctx.code.strings.(idx) in - Hashtbl.add ctx.cached_strings idx s; - s - in let check_obj v o fid = if ctx.checked then match o with | VObj o -> @@ -840,8 +848,8 @@ let interp ctx f args = | OMov (a,b) -> set a (get b) | OInt (r,i) -> set r (VInt ctx.code.ints.(i)) | OFloat (r,i) -> set r (VFloat (Array.unsafe_get ctx.code.floats i)) - | OString (r,s) -> set r (VBytes (cached_string s)) - | OBytes (r,s) -> set r (VBytes (ctx.code.strings.(s) ^ "\x00")) + | OString (r,s) -> set r (VBytes (cached_string ctx s)) + | OBytes (r,s) -> set r (VBytes (Bytes.to_string ctx.code.bytes.(s))) | OBool (r,b) -> set r (VBool b) | ONull r -> set r VNull | OAdd (r,a,b) -> set r (numop Int32.add ( +. ) a b) @@ -897,7 +905,7 @@ let interp ctx f args = set r (alloc_obj ctx (rtype r)) | OField (r,o,fid) -> set r (match get o with - | VObj v -> v.ofields.(fid) + | VObj v | VStruct v -> v.ofields.(fid) | VVirtual v as obj -> (match v.vindexes.(fid) with | VFNone -> dyn_get_field ctx obj (let n,_,_ = v.vtype.vfields.(fid) in n) (rtype r) @@ -908,7 +916,7 @@ let interp ctx f args = let rv = get r in let o = get o in (match o with - | VObj v -> + | VObj v | VStruct v -> check_obj rv o fid; v.ofields.(fid) <- rv | VVirtual v -> @@ -921,10 +929,10 @@ let interp ctx f args = | VNull -> null_access() | _ -> assert false) | OGetThis (r, fid) -> - set r (match get 0 with VObj v -> v.ofields.(fid) | _ -> assert false) + set r (match get 0 with VObj v | VStruct v -> v.ofields.(fid) | _ -> assert false) | OSetThis (fid, r) -> (match get 0 with - | VObj v as o -> + | (VObj v | VStruct v) as o -> let rv = get r in check_obj rv o fid; v.ofields.(fid) <- rv @@ -969,16 +977,6 @@ let interp ctx f args = let m = (match get o with | VObj v as obj -> VClosure (v.oproto.pmethods.(m), Some obj) | VNull -> null_access() - | VVirtual v -> - let name, _, _ = v.vtype.vfields.(m) in - (match v.vvalue with - | VObj o as obj -> - (try - let m = PMap.find name o.oproto.pclass.pfunctions in - VClosure (get_function ctx m, Some obj) - with Not_found -> - VNull) - | _ -> assert false) | _ -> assert false ) in set r (if m = VNull then m else dyn_cast ctx m (match get_type m with None -> assert false | Some v -> v) (rtype r)) @@ -1082,7 +1080,9 @@ let interp ctx f args = | HDynObj -> 16 | HAbstract _ -> 17 | HEnum _ -> 18 - | HNull _ -> 19))) + | HNull _ -> 19 + | HMethod _ -> 20 + | HStruct _ -> 21))) | _ -> assert false); | ORef (r,v) -> set r (VRef (RStack (v + spos),rtype v)) @@ -1196,8 +1196,9 @@ let call_fun ctx f args = throw_msg ctx msg | Sys_exit _ as exc -> raise exc - | e -> +(* | e -> throw_msg ctx (Printexc.to_string e) +*) let call_wrap ?(final=(fun()->())) ctx f args = let old_st = ctx.call_stack in @@ -1351,13 +1352,13 @@ let load_native ctx lib name t = (function | [VBytes str; VInt pos; VInt len] -> (try - VDyn (VInt (Common.parse_int (hl_to_caml_sub str (int pos) (int len))),HI32) + VDyn (VInt (Numeric.parse_int (hl_to_caml_sub str (int pos) (int len))),HI32) with _ -> VNull) | l -> assert false) | "parse_float" -> (function - | [VBytes str; VInt pos; VInt len] -> (try VFloat (Common.parse_float (hl_to_caml_sub str (int pos) (int len))) with _ -> VFloat nan) + | [VBytes str; VInt pos; VInt len] -> (try VFloat (Numeric.parse_float (hl_to_caml_sub str (int pos) (int len))) with _ -> VFloat nan) | _ -> assert false) | "dyn_compare" -> (function @@ -1772,9 +1773,9 @@ let load_native ctx lib name t = if c >= int_of_char 'a' && c <= int_of_char 'z' then c + int_of_char 'A' - int_of_char 'a' else c in - utf16_add buf c + Common.utf16_add buf c ) (String.sub s (int pos) ((int len) lsl 1)); - utf16_add buf 0; + Common.utf16_add buf 0; VBytes (Buffer.contents buf) | _ -> assert false) | "ucs2_lower" -> @@ -1786,9 +1787,9 @@ let load_native ctx lib name t = if c >= int_of_char 'A' && c <= int_of_char 'Z' then c + int_of_char 'a' - int_of_char 'A' else c in - utf16_add buf c + Common.utf16_add buf c ) (String.sub s (int pos) ((int len) lsl 1)); - utf16_add buf 0; + Common.utf16_add buf 0; VBytes (Buffer.contents buf) | _ -> assert false) | "url_encode" -> @@ -1796,18 +1797,8 @@ let load_native ctx lib name t = | [VBytes s; VRef (r, HI32)] -> let s = hl_to_caml s in let buf = Buffer.create 0 in - let hex = "0123456789ABCDEF" in - for i = 0 to String.length s - 1 do - let c = String.unsafe_get s i in - match c with - | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' | '-' | '.' -> - utf16_char buf c - | _ -> - utf16_char buf '%'; - utf16_char buf (String.unsafe_get hex (int_of_char c lsr 4)); - utf16_char buf (String.unsafe_get hex (int_of_char c land 0xF)); - done; - utf16_add buf 0; + Common.url_encode s (utf16_char buf); + Common.utf16_add buf 0; let str = Buffer.contents buf in set_ref r (to_int (String.length str lsr 1 - 1)); VBytes str @@ -2124,11 +2115,13 @@ let create checked = globals = [||]; natives = [||]; strings = [||]; + bytes = [||]; ints = [||]; debugfiles = [||]; floats = [||]; entrypoint = 0; version = 0; + constants = [||]; }; checked = checked; fcall = (fun _ _ -> assert false); @@ -2167,9 +2160,29 @@ let add_code ctx code = functions.(fd.findex) <- FFun fd; loop (i + 1) in - loop (Array.length ctx.code.functions); + loop (Array.length ctx.code.functions); ctx.t_functions <- functions; ctx.code <- code; + Array.iter (fun (g,fields) -> + let t = code.globals.(g) in + let get_const_val t idx = + match t with + | HI32 -> VInt code.ints.(idx) + | HBytes -> VBytes (cached_string ctx idx) + | _ -> assert false + in + let v = (match t with + | HObj o -> + if Array.length o.pfields <> Array.length fields then assert false; + let proto,_,_ = get_proto ctx o in + VObj { + oproto = proto; + ofields = Array.mapi (fun i (_,_,t) -> get_const_val t fields.(i)) o.pfields; + } + | _ -> assert false + ) in + ctx.t_globals.(g) <- v; + ) code.constants; (* call entrypoint *) ignore(call_wrap ctx functions.(code.entrypoint) []) @@ -2247,11 +2260,16 @@ let check code macros = let is_dyn r = if not (is_dynamic (rtype r)) then error (reg_inf r ^ " should be castable to dynamic") in + let get_field r p fid = + try snd (resolve_field p fid) with Not_found -> error (reg_inf r ^ " does not have field " ^ string_of_int fid) + in let tfield o fid proto = if fid < 0 then error (reg_inf o ^ " does not have " ^ (if proto then "proto " else "") ^ "field " ^ string_of_int fid); match rtype o with | HObj p -> - if proto then ftypes.(p.pvirtuals.(fid)) else (try snd (resolve_field p fid) with Not_found -> error (reg_inf o ^ " does not have field " ^ string_of_int fid)) + if proto then ftypes.(p.pvirtuals.(fid)) else get_field o p fid + | HStruct p when not proto -> + get_field o p fid | HVirtual v when not proto -> let _,_, t = v.vfields.(fid) in t @@ -2273,9 +2291,12 @@ let check code macros = if i < 0 || i >= Array.length code.floats then error "float outside range"; | OBool (r,_) -> reg r HBool - | OString (r,i) | OBytes (r,i) -> + | OString (r,i) -> reg r HBytes; if i < 0 || i >= Array.length code.strings then error "string outside range"; + | OBytes (r,i) -> + reg r HBytes; + if i < 0 || i >= Array.length code.bytes then error "bytes outside range"; | ONull r -> let t = rtype r in if not (is_nullable t) then error (tstr t ^ " is not nullable") @@ -2317,16 +2338,24 @@ let check code macros = (match rl with | [] -> assert false | obj :: rl2 -> - let t, rl = (match rtype obj with - | HVirtual v -> - let _, _, t = v.vfields.(m) in - t, rl2 - | _ -> - tfield obj m true, rl - ) in - match t with - | HFun (targs, tret) when List.length targs = List.length rl -> List.iter2 reg rl targs; check tret (rtype r) - | t -> check t (HFun (List.map rtype rl, rtype r))) + let check_args targs tret rl = + if List.length targs <> List.length rl then false else begin + List.iter2 reg rl targs; + check tret (rtype r); + true; + end + in + match rtype obj with + | HVirtual v -> + let _, _, t = v.vfields.(m) in + (match t with + | HMethod (args,ret) when check_args args ret rl2 -> () + | _ -> check t (HMethod (List.map rtype rl, rtype r))) + | _ -> + let t = tfield obj m true in + match t with + | HFun (args, ret) when check_args args ret rl -> () + | _ -> check t (HFun (List.map rtype rl, rtype r))) | OCallClosure (r,f,rl) -> (match rtype f with | HFun (targs,tret) when List.length targs = List.length rl -> List.iter2 reg rl targs; check tret (rtype r) @@ -2342,7 +2371,7 @@ let check code macros = reg r HBool; can_jump delta | OJNull (r,delta) | OJNotNull (r,delta) -> - ignore(rtype r); + if not (is_nullable (rtype r)) then reg r HDyn; can_jump delta | OJUGte (a,b,delta) | OJULt (a,b,delta) | OJSGte (a,b,delta) | OJSLt (a,b,delta) | OJSGt (a,b,delta) | OJSLte (a,b,delta) | OJNotLt (a,b,delta) | OJNotGte (a,b,delta) -> if not (safe_cast (rtype a) (rtype b)) then reg b (rtype a); @@ -2350,6 +2379,7 @@ let check code macros = | OJEq (a,b,delta) | OJNotEq (a,b,delta) -> (match rtype a, rtype b with | (HObj _ | HVirtual _), (HObj _ | HVirtual _) -> () + | (HDyn | HFun _), (HDyn | HFun _) -> () | ta, tb when safe_cast tb ta -> () | _ -> reg a (rtype b)); can_jump delta @@ -2369,7 +2399,7 @@ let check code macros = () | ONew r -> (match rtype r with - | HDynObj | HVirtual _ -> () + | HDynObj | HVirtual _ | HStruct _ -> () | _ -> is_obj r) | OField (r,o,fid) -> check (tfield o fid false) (rtype r) @@ -2390,9 +2420,6 @@ let check code macros = reg r (HFun (tl,tret)); | _ -> assert false) - | HVirtual v -> - let _,_, t = v.vfields.(fid) in - reg r t; | _ -> is_obj o) | OInstanceClosure (r,f,arg) -> @@ -2546,6 +2573,7 @@ type svalue = | SInt of int32 | SFloat of float | SString of string + | SBytes of int | SBool of bool | SNull | SType of ttype @@ -2601,6 +2629,7 @@ let rec svalue_string v = | SInt i -> Int32.to_string i | SFloat f -> string_of_float f | SString s -> "\"" ^ s ^ "\"" + | SBytes i -> "bytes$" ^ string_of_int i | SBool b -> if b then "true" else "false" | SNull -> "null" | SRef _ -> "ref" @@ -2626,7 +2655,7 @@ let rec svalue_string v = | SDelayed (str,_) -> str let svalue_iter f = function - | SUndef | SArg _ | SInt _ | SFloat _ | SString _ | SBool _ | SNull | SType _ | SResult _ + | SUndef | SArg _ | SInt _ | SFloat _ | SBytes _ | SString _ | SBool _ | SNull | SType _ | SResult _ | SFun (_,None) | SGlobal _ | SRef _ | SRefResult _ | SUnreach | SExc | SDelayed _ -> () | SOp (_,a,b) | SMem (a,b,_) -> f a; f b @@ -2807,7 +2836,8 @@ let make_spec (code:code) (f:fundecl) = | OInt (d,i) -> args.(d) <- SInt code.ints.(i) | OFloat (d,f) -> args.(d) <- SFloat code.floats.(f) | OBool (d,b) -> args.(d) <- SBool b - | OBytes (d,s) | OString (d,s) -> args.(d) <- SString code.strings.(s) + | OString (d,s) -> args.(d) <- SString code.strings.(s) + | OBytes (d,s) -> args.(d) <- SBytes s | ONull d -> args.(d) <- SNull | OAdd (d,a,b) -> args.(d) <- SOp ("+",args.(a),args.(b)) | OSub (d,a,b) -> args.(d) <- SOp ("-",args.(a),args.(b)) diff --git a/src/generators/hlopt.ml b/src/generators/hlopt.ml index 7f3b51b6f78..7e18cf384e4 100644 --- a/src/generators/hlopt.ml +++ b/src/generators/hlopt.ml @@ -1,5 +1,5 @@ (* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,7 +22,7 @@ open Hlcode module ISet = Set.Make(struct - let compare = Pervasives.compare + let compare a b = b - a type t = int end) @@ -139,9 +139,13 @@ let opcode_fx frw op = read a; read b; read c | ONew d -> write d - | OArraySize (d, a) | OGetType (d,a) | OGetTID (d,a) | ORef (d, a) | OUnref (d,a) | OSetref (d, a) | OEnumIndex (d, a) | OEnumField (d,a,_,_) -> + | OArraySize (d, a) | OGetType (d,a) | OGetTID (d,a) | OUnref (d,a) | OSetref (d, a) | OEnumIndex (d, a) | OEnumField (d,a,_,_) -> read a; write d + | ORef (d, a) -> + read a; + write a; (* prevent issue with 'a' being reused later - this is not exact as it can be set everytime we pass it to a function *) + write d; | OType (d,_) | OEnumAlloc (d,_) -> write d | OMakeEnum (d,_,rl) -> @@ -488,14 +492,221 @@ let code_graph (f:fundecl) = in blocks_pos, make_block 0 -let optimize dump (f:fundecl) = +type rctx = { + r_root : block; + r_used_regs : int; + r_nop_count : int; + r_blocks_pos : (int, block) Hashtbl.t; + r_reg_moved : (int, (int * int)) Hashtbl.t; + r_live_bits : int array; + r_reg_map : int array; +} + +let remap_fun ctx f dump get_str old_code = + let op index = Array.unsafe_get f.code index in + let nregs = Array.length f.regs in + let reg_remap = ctx.r_used_regs <> nregs in + let assigns = ref f.assigns in + let write str = match dump with None -> () | Some ch -> IO.nwrite ch (Bytes.unsafe_of_string (str ^ "\n")) in + let nargs = (match f.ftype with HFun (args,_) -> List.length args | _ -> assert false) in + + let live_bits = ctx.r_live_bits in + let reg_map = ctx.r_reg_map in + + let bit_regs = 30 in + let stride = (nregs + bit_regs - 1) / bit_regs in + let is_live r i = + let offset = r / bit_regs in + let mask = 1 lsl (r - offset * bit_regs) in + Array.unsafe_get live_bits (i * stride + offset) land mask <> 0 + in + + (* remap assigns *) + if ctx.r_nop_count > 0 then begin + let rec resolve_block p = + try Hashtbl.find ctx.r_blocks_pos p with Not_found -> resolve_block (p - 1) + in + + let new_assigns = List.fold_left (fun acc (i,p) -> + let gmap = Hashtbl.create 0 in + (* + For a given assign at position p, that's been optimized out, + let's try to find where the last assign that maps to the same value + is, and remap the variable name to it + *) + let rec loop p = + if p < 0 || (match op p with ONop _ -> false | _ -> true) then [(i,p)] else + let reg, last_w = try Hashtbl.find ctx.r_reg_moved p with Not_found -> (-1,-1) in + if reg < 0 then [] (* ? *) else + if reg < nargs then [(i,-reg-1)] else + let b = resolve_block p in + if last_w >= b.bstart && last_w < b.bend && last_w < p then loop last_w else + let wp = try PMap.find reg b.bwrite with Not_found -> -1 in + let rec gather b = + if Hashtbl.mem gmap b.bstart then [] else begin + Hashtbl.add gmap b.bstart (); + (* lookup in all parent blocks, recursively, to fetch all last writes *) + List.fold_left (fun acc bp -> + if bp.bstart > b.bstart then acc else + try + let wp = PMap.find reg bp.bwrite in + if wp > p then assert false; + loop wp @ acc + with Not_found -> + gather bp @ acc + ) [] b.bprev; + end + in + if wp < 0 then + gather b + else if wp < p then + loop wp + else + (* lookup in writes between p-1 and block bstart *) + let rec find_w p = + if p < b.bstart then + gather b + else + let found = ref false in + opcode_fx (fun r read -> if r = reg && not read then found := true) (Array.unsafe_get old_code p); + if !found then loop p else find_w (p - 1) + in + find_w (p - 1) + in + loop p @ acc + ) [] (Array.to_list !assigns) in + let new_assigns = List.sort (fun (_,p1) (_,p2) -> p1 - p2) (List.rev new_assigns) in + assigns := Array.of_list new_assigns; + end; + + (* done *) + if dump <> None then begin + let old_assigns = Hashtbl.create 0 in + let new_assigns = Hashtbl.create 0 in + Array.iter (fun (var,pos) -> if pos >= 0 then Hashtbl.replace old_assigns pos var) f.assigns; + Array.iter (fun (var,pos) -> + if pos >= 0 then begin + let f = try Hashtbl.find new_assigns pos with Not_found -> let v = ref [] in Hashtbl.add new_assigns pos v; v in + f := var :: !f; + end + ) !assigns; + let rec loop i block = + if i = Array.length f.code then () else + let block = try + let b = Hashtbl.find ctx.r_blocks_pos i in + write (Printf.sprintf "\t----- [%s] (%X)" + (String.concat "," (List.map (fun b -> Printf.sprintf "%X" b.bstart) b.bnext)) + b.bend + ); + let need = String.concat "," (List.map string_of_int (ISet.elements b.bneed)) in + let wr = String.concat " " (List.rev (PMap.foldi (fun r p acc -> Printf.sprintf "%d@%X" r p :: acc) b.bwrite [])) in + write ("\t" ^ (if b.bloop then "LOOP " else "") ^ "NEED=" ^ need ^ "\tWRITE=" ^ wr); + b + with Not_found -> + block + in + let old = Array.unsafe_get old_code i in + let op = op i in + let rec live_loop r l = + if r = nregs then List.rev l else + live_loop (r + 1) (if is_live r i then r :: l else l) + in + let live = "LIVE=" ^ String.concat "," (List.map string_of_int (live_loop 0 [])) in + let var_set = (try let v = Hashtbl.find old_assigns i in "set " ^ get_str v with Not_found -> "") in + let nvar_set = (try let v = Hashtbl.find new_assigns i in "set " ^ String.concat "," (List.map get_str !v) with Not_found -> "") in + write (Printf.sprintf "\t@%-3X %-20s %-20s %-20s %-20s %s" i (ostr string_of_int old) (if opcode_eq old op then "" else ostr string_of_int op) var_set nvar_set live); + loop (i + 1) block + in + write (Printf.sprintf "%s@%d" (fundecl_name f) f.findex); + let rec loop_arg = function + | [] -> [] + | (_,p) :: _ when p >= 0 -> [] + | (str,p) :: l -> (get_str str ^ ":" ^ string_of_int p) :: loop_arg l + in + write (Printf.sprintf "ARGS = %s\n" (String.concat ", " (loop_arg (Array.to_list f.assigns)))); + if reg_remap then begin + for i=0 to nregs-1 do + write (Printf.sprintf "\tr%-2d %-10s%s" i (tstr f.regs.(i)) (if ctx.r_reg_map.(i) < 0 then " unused" else if ctx.r_reg_map.(i) = i then "" else Printf.sprintf " r%-2d" ctx.r_reg_map.(i))) + done; + end; + loop 0 ctx.r_root; + write ""; + write ""; + (match dump with None -> () | Some ch -> IO.flush ch); + end; + + let code = ref f.code in + let regs = ref f.regs in + let debug = ref f.debug in + + if ctx.r_nop_count > 0 || reg_remap then begin + let new_pos = Array.make (Array.length f.code) 0 in + let jumps = ref [] in + let out_pos = ref 0 in + let out_code = Array.make (Array.length f.code - ctx.r_nop_count) (ONop "") in + let new_debug = Array.make (Array.length f.code - ctx.r_nop_count) (0,0) in + Array.iteri (fun i op -> + Array.unsafe_set new_pos i !out_pos; + match op with + | ONop _ -> () + | _ -> + (match op with + | OJTrue _ | OJFalse _ | OJNull _ | OJNotNull _ | OJSLt _ | OJSGte _ | OJSGt _ | OJSLte _ | OJNotLt _ | OJNotGte _ | OJULt _ | OJUGte _ | OJEq _ | OJNotEq _ | OJAlways _ | OSwitch _ | OTrap _ -> + jumps := i :: !jumps + | _ -> ()); + let op = if reg_remap then opcode_map (fun r -> Array.unsafe_get reg_map r) (fun r -> Array.unsafe_get reg_map r) op else op in + Array.unsafe_set out_code (!out_pos) op; + Array.unsafe_set new_debug (!out_pos) (Array.unsafe_get f.debug i); + incr out_pos + ) f.code; + List.iter (fun j -> + let pos d = + Array.unsafe_get new_pos (j + 1 + d) - Array.unsafe_get new_pos (j + 1) + in + let p = new_pos.(j) in + Array.unsafe_set out_code p (match Array.unsafe_get out_code p with + | OJTrue (r,d) -> OJTrue (r,pos d) + | OJFalse (r,d) -> OJFalse (r,pos d) + | OJNull (r,d) -> OJNull (r, pos d) + | OJNotNull (r,d) -> OJNotNull (r, pos d) + | OJSLt (a,b,d) -> OJSLt (a,b,pos d) + | OJSGte (a,b,d) -> OJSGte (a,b,pos d) + | OJSLte (a,b,d) -> OJSLte (a,b,pos d) + | OJSGt (a,b,d) -> OJSGt (a,b,pos d) + | OJULt (a,b,d) -> OJULt (a,b,pos d) + | OJUGte (a,b,d) -> OJUGte (a,b,pos d) + | OJNotLt (a,b,d) -> OJNotLt (a,b,pos d) + | OJNotGte (a,b,d) -> OJNotGte (a,b,pos d) + | OJEq (a,b,d) -> OJEq (a,b,pos d) + | OJNotEq (a,b,d) -> OJNotEq (a,b,pos d) + | OJAlways d -> OJAlways (pos d) + | OSwitch (r,cases,send) -> OSwitch (r, Array.map pos cases, pos send) + | OTrap (r,d) -> OTrap (r,pos d) + | _ -> assert false) + ) !jumps; + + let assigns = !assigns in + Array.iteri (fun idx (i,p) -> if p >= 0 then Array.unsafe_set assigns idx (i, Array.unsafe_get new_pos p)) assigns; + + code := out_code; + debug := new_debug; + if reg_remap then begin + let new_regs = Array.make ctx.r_used_regs HVoid in + for i=0 to nregs-1 do + let p = Array.unsafe_get reg_map i in + if p >= 0 then Array.unsafe_set new_regs p (Array.unsafe_get f.regs i) + done; + regs := new_regs; + end; + end; + { f with code = !code; regs = !regs; debug = !debug; assigns = !assigns } + +let _optimize (f:fundecl) = let nregs = Array.length f.regs in - let old_code = match dump with None -> f.code | Some _ -> Array.copy f.code in let op index = f.code.(index) in let set_op index op = f.code.(index) <- op in let nop_count = ref 0 in let set_nop index r = f.code.(index) <- (ONop r); incr nop_count in - let write str = match dump with None -> () | Some ch -> IO.nwrite ch (Bytes.unsafe_of_string (str ^ "\n")) in let blocks_pos, root = code_graph f in @@ -507,6 +718,11 @@ let optimize dump (f:fundecl) = let stride = (nregs + bit_regs - 1) / bit_regs in let live_bits = Array.make (Array.length f.code * stride) 0 in + let reg_moved = Hashtbl.create 0 in + let add_reg_moved p w r = + Hashtbl.add reg_moved p (r,last_write.(r)) + in + let set_live r min max = let offset = r / bit_regs in let mask = 1 lsl (r - offset * bit_regs) in @@ -530,7 +746,7 @@ let optimize dump (f:fundecl) = r.ralias <- r; r ) in - +(* let print_state i s = let state_str s = if s.ralias == s && s.rbind == [] then "" else @@ -538,8 +754,7 @@ let optimize dump (f:fundecl) = in write (Printf.sprintf "@%X %s" i (String.concat " " (Array.to_list (Array.map state_str s)))) in - - let dstate = false in +*) let rec propagate b = let state = if b.bloop then @@ -605,7 +820,7 @@ let optimize dump (f:fundecl) = in if i > b.bend then () else let op = op i in - if dstate then print_state i state; + (* print_state i state; (* debug *) *) (match op with | OIncr r | ODecr r | ORef (_,r) -> unalias state.(r) | OCallClosure (_,r,_) when f.regs.(r) = HDyn && (match f.regs.(state.(r).ralias.rindex) with HFun (_,rt) -> not (is_dynamic rt) | HDyn -> false | _ -> true) -> unalias state.(r) (* Issue3218.hx *) @@ -616,7 +831,8 @@ let optimize dump (f:fundecl) = ) (fun w -> w) op in set_op i op; (match op with - | OMov (d, v) when d = v -> + | OMov (d, v) | OToInt (d, v) | OToSFloat (d,v) when d = v -> + add_reg_moved i d v; set_nop i "mov" | OMov (d, v) -> let sv = state.(v) in @@ -632,6 +848,14 @@ let optimize dump (f:fundecl) = | ONullCheck r -> let s = state.(r) in if s.rnullcheck then set_nop i "nullcheck" else begin do_read r; s.rnullcheck <- true; end; + | ONew r -> + let s = state.(r) in + do_write r; + s.rnullcheck <- true; + | OToVirtual (v,o) -> + do_read o; + do_write v; + state.(v).rnullcheck <- state.(o).rnullcheck | _ -> opcode_fx (fun r read -> if read then do_read r else do_write r @@ -723,7 +947,16 @@ let optimize dump (f:fundecl) = let n = read_counts.(r) - 1 in read_counts.(r) <- n; write_counts.(d) <- write_counts.(d) - 1; + add_reg_moved i d r; set_nop i "unused" + | OJAlways d when d >= 0 -> + let rec loop k = + if k = d then set_nop i "nojmp" else + match f.code.(i + k + 1) with + | ONop _ -> loop (k + 1) + | _ -> () + in + loop 0 | _ -> ()); done; @@ -739,108 +972,86 @@ let optimize dump (f:fundecl) = end else reg_map.(i) <- -1; done; - let reg_remap = !used_regs <> nregs in - - (* done *) - if dump <> None then begin - let rec loop i block = - if i = Array.length f.code then () else - let block = try - let b = Hashtbl.find blocks_pos i in - write (Printf.sprintf "\t----- [%s] (%X)" - (String.concat "," (List.map (fun b -> Printf.sprintf "%X" b.bstart) b.bnext)) - b.bend - ); - let need = String.concat "," (List.map string_of_int (ISet.elements b.bneed)) in - let wr = String.concat " " (List.rev (PMap.foldi (fun r p acc -> Printf.sprintf "r%d:%X" r p :: acc) b.bwrite [])) in - write ("\t" ^ (if b.bloop then "LOOP " else "") ^ "NEED=" ^ need ^ "\tWRITE=" ^ wr); - b - with Not_found -> - block - in - let old = old_code.(i) in - let op = op i in - let rec live_loop r l = - if r = nregs then List.rev l else - live_loop (r + 1) (if is_live r i then r :: l else l) - in - let live = "LIVE=" ^ String.concat "," (List.map string_of_int (live_loop 0 [])) in - write (Printf.sprintf "\t@%-3X %-20s %-20s%s" i (ostr string_of_int old) (if opcode_eq old op then "" else ostr string_of_int op) live); - loop (i + 1) block - in - write (Printf.sprintf "%s@%d" (fundecl_name f) f.findex); - if reg_remap then begin - for i=0 to nregs-1 do - write (Printf.sprintf "\tr%-2d %-10s%s" i (tstr f.regs.(i)) (if reg_map.(i) < 0 then " unused" else if reg_map.(i) = i then "" else Printf.sprintf " r%-2d" reg_map.(i))) - done; - end; - loop 0 root; - write ""; - write ""; - (match dump with None -> () | Some ch -> IO.flush ch); - end; + { + r_root = root; + r_blocks_pos = blocks_pos; + r_nop_count = !nop_count; + r_used_regs = !used_regs; + r_live_bits = live_bits; + r_reg_map = reg_map; + r_reg_moved = reg_moved; + } - (* remap *) +type cache_elt = { + c_code : opcode array; + c_rctx : rctx; + c_remap_indexes : int array; + mutable c_last_used : int; +} - let code = ref f.code in - let regs = ref f.regs in - let debug = ref f.debug in +let opt_cache = ref PMap.empty +let used_mark = ref 0 - if !nop_count > 0 || reg_remap then begin - let new_pos = Array.make (Array.length f.code) 0 in - let jumps = ref [] in - let out_pos = ref 0 in - let out_code = Array.make (Array.length f.code - !nop_count) (ONop "") in - let new_debug = Array.make (Array.length f.code - !nop_count) (0,0) in +let optimize dump get_str (f:fundecl) (hxf:Type.tfunc) = + let old_code = match dump with None -> f.code | Some _ -> Array.copy f.code in + try + let c = PMap.find hxf (!opt_cache) in + c.c_last_used <- !used_mark; + if Array.length f.code <> Array.length c.c_code then assert false; + let code = c.c_code in + Array.iter (fun i -> + let op = (match Array.unsafe_get code i, Array.unsafe_get f.code i with + | OInt (r,_), OInt (_,idx) -> OInt (r,idx) + | OFloat (r,_), OFloat (_,idx) -> OFloat (r,idx) + | OBytes (r,_), OBytes (_,idx) -> OBytes (r,idx) + | OString (r,_), OString (_,idx) -> OString (r,idx) + | OCall0 (r,_), OCall0 (_,idx) -> OCall0 (r,idx) + | OCall1 (r,_,a), OCall1 (_,idx,_) -> OCall1 (r,idx,a) + | OCall2 (r,_,a,b), OCall2 (_,idx,_,_) -> OCall2 (r,idx,a,b) + | OCall3 (r,_,a,b,c), OCall3 (_,idx,_,_,_) -> OCall3 (r,idx,a,b,c) + | OCall4 (r,_,a,b,c,d), OCall4 (_,idx,_,_,_,_) -> OCall4 (r,idx,a,b,c,d) + | OCallN (r,_,pl), OCallN (_,idx,_) -> OCallN (r,idx,pl) + | OStaticClosure (r,_), OStaticClosure (_,idx) -> OStaticClosure (r,idx) + | OInstanceClosure (r,_,v), OInstanceClosure (_,idx,_) -> OInstanceClosure (r,idx,v) + | OGetGlobal (r,_), OGetGlobal (_,g) -> OGetGlobal (r,g) + | OSetGlobal (_,v), OSetGlobal (g,_) -> OSetGlobal (g,v) + | ODynGet (r,o,_), ODynGet (_,_,idx) -> ODynGet (r,o,idx) + | ODynSet (o,_,v), ODynSet (_,idx,_) -> ODynSet (o,idx,v) + | OType (r,_), OType (_,t) -> OType (r,t) + | _ -> assert false) in + Array.unsafe_set code i op + ) c.c_remap_indexes; + remap_fun c.c_rctx { f with code = code } dump get_str old_code + with Not_found -> + let rctx = _optimize f in + let old_ops = f.code in + let fopt = remap_fun rctx f dump get_str old_code in + Hashtbl.iter (fun _ b -> + b.bstate <- None; + if dump = None then begin + b.bneed <- ISet.empty; + b.bneed_all <- None; + end; + ) rctx.r_blocks_pos; + let idxs = DynArray.create() in Array.iteri (fun i op -> - Array.unsafe_set new_pos i !out_pos; match op with - | ONop _ -> () - | _ -> - (match op with - | OJTrue _ | OJFalse _ | OJNull _ | OJNotNull _ | OJSLt _ | OJSGte _ | OJSGt _ | OJSLte _ | OJNotLt _ | OJNotGte _ | OJULt _ | OJUGte _ | OJEq _ | OJNotEq _ | OJAlways _ | OSwitch _ | OTrap _ -> - jumps := i :: !jumps - | _ -> ()); - let op = if reg_remap then opcode_map (fun r -> reg_map.(r)) (fun r -> reg_map.(r)) op else op in - out_code.(!out_pos) <- op; - new_debug.(!out_pos) <- f.debug.(i); - incr out_pos - ) f.code; - List.iter (fun j -> - let pos d = - new_pos.(j + 1 + d) - new_pos.(j + 1) - in - let p = new_pos.(j) in - out_code.(p) <- (match out_code.(p) with - | OJTrue (r,d) -> OJTrue (r,pos d) - | OJFalse (r,d) -> OJFalse (r,pos d) - | OJNull (r,d) -> OJNull (r, pos d) - | OJNotNull (r,d) -> OJNotNull (r, pos d) - | OJSLt (a,b,d) -> OJSLt (a,b,pos d) - | OJSGte (a,b,d) -> OJSGte (a,b,pos d) - | OJSLte (a,b,d) -> OJSLte (a,b,pos d) - | OJSGt (a,b,d) -> OJSGt (a,b,pos d) - | OJULt (a,b,d) -> OJULt (a,b,pos d) - | OJUGte (a,b,d) -> OJUGte (a,b,pos d) - | OJNotLt (a,b,d) -> OJNotLt (a,b,pos d) - | OJNotGte (a,b,d) -> OJNotGte (a,b,pos d) - | OJEq (a,b,d) -> OJEq (a,b,pos d) - | OJNotEq (a,b,d) -> OJNotEq (a,b,pos d) - | OJAlways d -> OJAlways (pos d) - | OSwitch (r,cases,send) -> OSwitch (r, Array.map pos cases, pos send) - | OTrap (r,d) -> OTrap (r,pos d) - | _ -> assert false) - ) !jumps; - code := out_code; - debug := new_debug; - if reg_remap then begin - let new_regs = Array.make !used_regs HVoid in - for i=0 to nregs-1 do - let p = reg_map.(i) in - if p >= 0 then new_regs.(p) <- f.regs.(i) - done; - regs := new_regs; - end; - end; + | OInt _ | OFloat _ | OBytes _ | OString _ + | OCall0 _ | OCall1 _ | OCall2 _ | OCall3 _ | OCall4 _ | OCallN _ | OStaticClosure _ + | OInstanceClosure _ | OGetGlobal _ | OSetGlobal _ | ODynGet _ | ODynSet _ | OType _ -> + DynArray.add idxs i + | _ -> () + ) old_ops; + (*opt_cache := PMap.add hxf { + c_code = old_ops; + c_rctx = rctx; + c_last_used = !used_mark; + c_remap_indexes = DynArray.to_array idxs; + } (!opt_cache);*) + fopt - { f with code = !code; regs = !regs; debug = !debug } \ No newline at end of file +let clean_cache() = + PMap.iter (fun k c -> + if !used_mark - c.c_last_used > 3 then opt_cache := PMap.remove k !opt_cache; + ) (!opt_cache); + incr used_mark diff --git a/src/generators/jvm/jvmAttribute.ml b/src/generators/jvm/jvmAttribute.ml new file mode 100644 index 00000000000..be6e512a005 --- /dev/null +++ b/src/generators/jvm/jvmAttribute.ml @@ -0,0 +1,248 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open JvmGlobals +open JvmData +open JvmVerificationTypeInfo +open JvmWriter + +type j_annotation = { + ann_type : int; + ann_elements : (jvm_constant_pool_index * j_annotation_element_value) array; +} + +and j_annotation_element_value = char * j_annotation_value + +and j_annotation_value = + | ValConst of int (* B, C, D, E, F, I, J, S, Z, s *) + | ValEnum of int * int (* e *) + | ValClass of int (* c *) (* V -> Void *) + | ValAnnotation of j_annotation (* @ *) + | ValArray of j_annotation_element_value array (* [ *) + +(* https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.4 *) +type j_stack_map_frame = + | StackSame of int + | Stack1StackItem of int * JvmVerificationTypeInfo.t + | Stack1StackItemExtended of int * JvmVerificationTypeInfo.t + | StackChop1 of int + | StackChop2 of int + | StackChop3 of int + | StackSameExtended of int + | StackAppend1 of int * JvmVerificationTypeInfo.t + | StackAppend2 of int * JvmVerificationTypeInfo.t * JvmVerificationTypeInfo.t + | StackAppend3 of int * JvmVerificationTypeInfo.t * JvmVerificationTypeInfo.t * JvmVerificationTypeInfo.t + | StackFull of int * JvmVerificationTypeInfo.t array * JvmVerificationTypeInfo.t array + +(* https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.13 *) +type jvm_local_debug = { + ld_start_pc : int; + ld_length : int; + ld_name_index : jvm_constant_pool_index; + ld_descriptor_index : jvm_constant_pool_index; + ld_index : int; +} + +type jvm_inner_class = { + ic_inner_class_info_index : int; + ic_outer_class_info_index : int; + ic_inner_name_index : int; + ic_inner_class_access_flags : int; +} + +type j_bootstrap_method = { + bm_method_ref : jvm_constant_pool_index; + bm_arguments : jvm_constant_pool_index array; +} + +(* https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7 *) +type j_attribute = + | AttributeConstantValue of jvm_constant_pool_index + | AttributeCode of jvm_code + | AttributeStackMapTable of j_stack_map_frame array + | AttributeExceptions of jvm_constant_pool_index array + | AttributeSourceFile of jvm_constant_pool_index + | AttributeLineNumberTable of (int * int) array + | AttributeSignature of jvm_constant_pool_index + | AttributeLocalVariableTable of jvm_local_debug array + | AttributeLocalVariableTypeTable of jvm_local_debug array + | AttributeInnerClasses of jvm_inner_class array + | AttributeEnclosingMethod of jvm_constant_pool_index * jvm_constant_pool_index + | AttributeRuntimeVisibleAnnotations of j_annotation array + | AttributeBootstrapMethods of j_bootstrap_method array + +let write_verification_type ch = function + | VTop -> write_byte ch 0 + | VInteger -> write_byte ch 1 + | VFloat -> write_byte ch 2 + | VDouble -> write_byte ch 3 + | VLong -> write_byte ch 4 + | VNull -> write_byte ch 5 + | VUninitializedThis -> write_byte ch 6 + | VObject i -> + write_byte ch 7; + write_ui16 ch i; + | VUninitialized i -> + write_byte ch 8; + write_ui16 ch i + +let write_stack_map_frame ch = function + | StackSame i -> + assert (i < 64); + write_byte ch i + | Stack1StackItem(i,t) -> + assert (i < 64); + write_byte ch (i + 64); + write_verification_type ch t; + | Stack1StackItemExtended(i,t) -> + write_byte ch 247; + write_ui16 ch i; + write_verification_type ch t; + | StackChop1 i1 -> + write_byte ch 250; + write_ui16 ch i1; + | StackChop2 i1 -> + write_byte ch 249; + write_ui16 ch i1; + | StackChop3 i1 -> + write_byte ch 248; + write_ui16 ch i1; + | StackSameExtended i -> + write_byte ch 251; + write_ui16 ch i + | StackAppend1(i1,t1) -> + write_byte ch 252; + write_ui16 ch i1; + write_verification_type ch t1; + | StackAppend2(i1,t1,t2) -> + write_byte ch 253; + write_ui16 ch i1; + write_verification_type ch t1; + write_verification_type ch t2; + | StackAppend3(i1,t1,t2,t3) -> + write_byte ch 254; + write_ui16 ch i1; + write_verification_type ch t1; + write_verification_type ch t2; + write_verification_type ch t3; + | StackFull(i1,tl1,tl2) -> + write_byte ch 255; + write_ui16 ch i1; + write_array16 ch write_verification_type tl1; + write_array16 ch write_verification_type tl2 + +let write_constant pool ch const = + let offset = pool#add const in + write_ui16 ch offset + +let rec write_annotation ch ann = + write_ui16 ch ann.ann_type; + write_array16 ch (fun _ (i,v) -> + write_ui16 ch i; + let rec loop _ (c,v) = + write_byte ch (Char.code c); + match v with + | ValConst i -> + write_ui16 ch i + | ValEnum(i1,i2) -> + write_ui16 ch i1; + write_ui16 ch i2; + | ValClass i -> + write_ui16 ch i + | ValAnnotation a -> + write_annotation ch ann + | ValArray annl -> + write_array16 ch loop annl + in + loop ch v + ) ann.ann_elements + +let write_attribute pool jvma = + let ch = IO.output_bytes () in + let write_local_table table = + write_array16 ch (fun _ d -> + write_ui16 ch d.ld_start_pc; + write_ui16 ch d.ld_length; + write_ui16 ch d.ld_name_index; + write_ui16 ch d.ld_descriptor_index; + write_ui16 ch d.ld_index; + ) table + in + let name = match jvma with + | AttributeConstantValue const -> + write_ui16 ch const; + "ConstantValue"; + | AttributeCode code -> + write_ui16 ch code.code_max_stack; + write_ui16 ch code.code_max_locals; + write_ui32 ch (Bytes.length code.code_code); + write_bytes ch code.code_code; + write_array16 ch write_exception code.code_exceptions; + write_jvm_attributes ch code.code_attributes; + "Code"; + | AttributeStackMapTable stack_map -> + write_array16 ch write_stack_map_frame stack_map; + "StackMapTable" + | AttributeExceptions a -> + write_array16 ch (fun _ offset -> write_ui16 ch offset) a; + "Exceptions" + | AttributeInnerClasses icl -> + write_array16 ch (fun ch ic -> + write_ui16 ch ic.ic_inner_class_info_index; + write_ui16 ch ic.ic_outer_class_info_index; + write_ui16 ch ic.ic_inner_name_index; + write_ui16 ch ic.ic_inner_class_access_flags; + ) icl; + "InnerClasses" + | AttributeEnclosingMethod(i1,i2) -> + write_ui16 ch i1; + write_ui16 ch i2; + "EnclosingMethod" + | AttributeSourceFile offset -> + write_ui16 ch offset; + "SourceFile"; + | AttributeLineNumberTable a -> + write_array16 ch (fun _ (i1,i2) -> + write_ui16 ch i1; + write_ui16 ch i2 + ) a; + "LineNumberTable" + | AttributeSignature offset -> + write_ui16 ch offset; + "Signature" + | AttributeLocalVariableTable table -> + write_local_table table; + "LocalVariableTable" + | AttributeLocalVariableTypeTable table -> + write_local_table table; + "LocalVariableTypeTable" + | AttributeRuntimeVisibleAnnotations al -> + write_array16 ch write_annotation al; + "RuntimeVisibleAnnotations" + | AttributeBootstrapMethods a -> + write_array16 ch (fun _ bm -> + write_ui16 ch bm.bm_method_ref; + write_array16 ch (fun _ i -> write_ui16 ch i) bm.bm_arguments; + ) a; + "BootstrapMethods" + in + { + attr_index = pool#add (ConstUtf8 name); + attr_data = IO.close_out ch + } \ No newline at end of file diff --git a/src/generators/jvm/jvmBuilder.ml b/src/generators/jvm/jvmBuilder.ml new file mode 100644 index 00000000000..0e414bc054d --- /dev/null +++ b/src/generators/jvm/jvmBuilder.ml @@ -0,0 +1,89 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open JvmGlobals +open JvmData +open JvmSignature +open JvmAttribute + +type annotation_kind = + | AInt of Int32.t + | ADouble of float + | AString of string + | ABool of bool + | AEnum of jsignature * string + | AArray of annotation_kind list + +and annotation = (string * annotation_kind) list + +type export_config = { + export_debug : bool; +} + +class base_builder = object(self) + val mutable access_flags = 0 + val attributes = DynArray.create () + val annotations = DynArray.create () + val mutable was_exported = false + + method add_access_flag i = + access_flags <- i lor access_flags + + method add_attribute (a : j_attribute) = + DynArray.add attributes a + + method add_annotation (path : jpath) (a : annotation) = + DynArray.add annotations ((TObject(path,[])),a) + + method private commit_annotations pool = + if DynArray.length annotations > 0 then begin + let open JvmAttribute in + let a = DynArray.to_array annotations in + let a = Array.map (fun (jsig,l) -> + let offset = pool#add_string (generate_signature false jsig) in + let l = List.map (fun (name,ak) -> + let offset = pool#add_string name in + let rec loop ak = match ak with + | AInt i32 -> + 'I',ValConst(pool#add (ConstInt i32)) + | ADouble f -> + 'D',ValConst(pool#add (ConstDouble f)) + | AString s -> + 's',ValConst(pool#add_string s) + | ABool b -> + 'Z',ValConst(pool#add (ConstInt (if b then Int32.one else Int32.zero))) + | AEnum(jsig,name) -> + 'e',ValEnum(pool#add_string (generate_signature false jsig),pool#add_string name) + | AArray l -> + let l = List.map (fun ak -> loop ak) l in + '[',ValArray(Array.of_list l) + in + offset,loop ak + ) l in + { + ann_type = offset; + ann_elements = Array.of_list l; + } + ) a in + self#add_attribute (AttributeRuntimeVisibleAnnotations a) + end + + method export_attributes (pool : JvmConstantPool.constant_pool) = + DynArray.to_array (DynArray.map (write_attribute pool) attributes) +end \ No newline at end of file diff --git a/src/generators/jvm/jvmClass.ml b/src/generators/jvm/jvmClass.ml new file mode 100644 index 00000000000..f8acdb41abc --- /dev/null +++ b/src/generators/jvm/jvmClass.ml @@ -0,0 +1,188 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open JvmGlobals +open JvmData +open JvmSignature +open NativeSignatures +open JvmAttribute +open JvmBuilder + +(* High-level class builder. *) + +class builder path_this path_super = object(self) + inherit base_builder + val pool = new JvmConstantPool.constant_pool + val jsig = TObject(path_this,[]) + val mutable offset_this = 0 + val mutable offset_super = 0 + val mutable interface_offsets = [] + val fields = DynArray.create () + val methods = DynArray.create () + val method_sigs = Hashtbl.create 0 + val inner_classes = Hashtbl.create 0 + val mutable closure_count = 0 + val mutable bootstrap_methods = [] + val mutable num_bootstrap_methods = 0 + val mutable spawned_methods = [] + val mutable field_init_method = None + + method add_interface path = + interface_offsets <- (pool#add_path path) :: interface_offsets + + method add_field (f : jvm_field) = + DynArray.add fields f + + method get_bootstrap_method path name jsig (consts : jvm_constant_pool_index list) = + try + fst (List.assoc (path,name,consts) bootstrap_methods) + with Not_found -> + let offset = pool#add_field path name jsig FKMethod in + let offset = pool#add (ConstMethodHandle(6, offset)) in + let bm = { + bm_method_ref = offset; + bm_arguments = Array.of_list consts; + } in + bootstrap_methods <- ((path,name,consts),(offset,bm)) :: bootstrap_methods; + num_bootstrap_methods <- num_bootstrap_methods + 1; + num_bootstrap_methods - 1 + + method get_pool = pool + + method get_this_path = path_this + method get_super_path = path_super + method get_jsig = jsig + method get_offset_this = offset_this + method get_access_flags = access_flags + + method get_next_closure_name = + let name = Printf.sprintf "hx_closure$%i" closure_count in + closure_count <- closure_count + 1; + name + + method has_method (name : string) (jsig : jsignature) = + Hashtbl.mem method_sigs (name,generate_method_signature false jsig) + + method spawn_inner_class (jm : JvmMethod.builder option) (path_super : jpath) (name : string option) = + let path = match name with + | None -> (fst path_this,Printf.sprintf "%s$%i" (snd path_this) (Hashtbl.length inner_classes)) + | Some name -> (fst path_this,Printf.sprintf "%s$%s" (snd path_this) name) + in + let jc = new builder path path_super in + jc#add_access_flag 0x01; + begin match jm with + | None -> + () + | Some jm -> + let pool = jc#get_pool in + let offset_class = pool#add_path path_this in + let offset_name = pool#add_string jm#get_name in + let offset_desc = pool#add_string (generate_signature false jm#get_jsig) in + let offset_info = pool#add (ConstNameAndType(offset_name,offset_desc)) in + jc#add_attribute (JvmAttribute.AttributeEnclosingMethod(offset_class,offset_info)); + end; + let offset = pool#add_path path in + Hashtbl.add inner_classes offset jc; + jc + + method spawn_method (name : string) (jsig_method : jsignature) (flags : MethodAccessFlags.t list) = + let jm = new JvmMethod.builder self name jsig_method in + let ssig_method = generate_method_signature false jsig_method in + if Hashtbl.mem method_sigs (name,ssig_method) then + jerror (Printf.sprintf "Duplicate field on class %s: %s %s" (Globals.s_type_path path_this) name ssig_method); + Hashtbl.add method_sigs (name,ssig_method) jm; + List.iter (fun flag -> + jm#add_access_flag (MethodAccessFlags.to_int flag) + ) flags; + let pop_scope = jm#push_scope in + if not (jm#has_method_flag MStatic) then ignore(jm#add_local "this" (if jm#get_name = "" then (TUninitialized None) else jsig) VarArgument); + spawned_methods <- (jm,Some pop_scope) :: spawned_methods; + jm + + method spawn_field (name : string) (jsig_method : jsignature) (flags : FieldAccessFlags.t list) = + let jm = new JvmMethod.builder self name jsig_method in + List.iter (fun flag -> + jm#add_access_flag (FieldAccessFlags.to_int flag) + ) flags; + spawned_methods <- (jm,None) :: spawned_methods; + jm + + method private commit_inner_classes = + if Hashtbl.length pool#get_inner_classes > 0 then begin + let open JvmAttribute in + let l = Hashtbl.fold (fun (path,name) offset_class acc -> + (path,name,offset_class) :: acc + ) pool#get_inner_classes [] in + let l = List.map (fun (path,name,offset_class) -> + let offset_name = pool#add_string name in + let flags = try (Hashtbl.find inner_classes offset_class)#get_access_flags with Not_found -> 9 in + let offset_outer = pool#add_path path in + { + ic_inner_class_info_index = offset_class; + ic_outer_class_info_index = offset_outer; + ic_inner_name_index = offset_name; + ic_inner_class_access_flags = flags; + } + ) l in + let a = Array.of_list l in + self#add_attribute (AttributeInnerClasses a) + end + + method private commit_bootstrap_methods = + match bootstrap_methods with + | [] -> + () + | _ -> + let l = List.fold_left (fun acc (_,(_,bm)) -> bm :: acc) [] bootstrap_methods in + self#add_attribute (AttributeBootstrapMethods (Array.of_list l)) + + method export_class (config : export_config) = + assert (not was_exported); + was_exported <- true; + List.iter (fun (jm,pop_scope) -> + begin match pop_scope with + | Some pop_scope -> + pop_scope(); + DynArray.add methods (jm#export_method config); + | None -> + self#add_field jm#export_field + end; + ) (List.rev spawned_methods); + self#commit_bootstrap_methods; + self#commit_inner_classes; + self#commit_annotations pool; + let attributes = self#export_attributes pool in + let pool = pool#close in + { + class_minor_version = 0; + class_major_version = 0x34; + class_constant_pool = pool; + class_access_flags = access_flags; + class_this_class = offset_this; + class_super_class = offset_super; + class_interfaces = Array.of_list interface_offsets; + class_fields = DynArray.to_array fields; + class_methods = DynArray.to_array methods; + class_attributes = attributes; + } + + initializer + offset_this <- pool#add_path path_this; + offset_super <- pool#add_path path_super; +end \ No newline at end of file diff --git a/src/generators/jvm/jvmCode.ml b/src/generators/jvm/jvmCode.ml new file mode 100644 index 00000000000..73c15a20575 --- /dev/null +++ b/src/generators/jvm/jvmCode.ml @@ -0,0 +1,566 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open JvmGlobals +open JvmData +open JvmSignature + +(* Opcode builder with stack management *) + +exception EmptyStack + +class jvm_stack = object(self) + val mutable stack = []; + val mutable stack_size = 0; + val mutable max_stack_size = 0; + + method push js = + stack <- js :: stack; + stack_size <- stack_size + (signature_size js); + if stack_size > max_stack_size then max_stack_size <- stack_size + + method pop = match stack with + | js :: l -> + stack <- l; + stack_size <- stack_size - (signature_size js); + js + | [] -> + raise EmptyStack + + method to_string = + Printf.sprintf "[%s]" (String.concat ", " (List.map (generate_signature false) stack)) + + method save = + (stack,stack_size) + + method top = match stack with + | hd :: _ -> hd + | [] -> raise EmptyStack + + method restore ((stack',stack_size') : (jsignature list * int)) = + stack <- stack'; + stack_size <- stack_size' + + method get_max_stack_size = max_stack_size + method set_max_stack_size value = max_stack_size <- value + + method get_stack = stack + + method get_stack_items i = + let rec loop acc i l = + if i = 0 then List.rev acc + else match l with + | x :: l -> + loop (x :: acc) (i - 1) l + | [] -> + raise EmptyStack + in + loop [] i stack +end + +let s_vt = generate_method_signature true + +let s_vtl l = Printf.sprintf "[%s]" (String.concat ", " (List.map s_vt l)) + +class builder pool = object(self) + val stack = new jvm_stack; + val lines = DynArray.create() + val mutable last_line = -1 + val mutable current_line = -1 + + (* ops *) + val ops = DynArray.create(); + val stack_debug = DynArray.create() + val mutable fp = 0 + + method debug_stack = + let l = DynArray.to_list stack_debug in + let opmax = ref 0 in + let l = List.map (fun (op,_,after,line) -> + let sop = JvmDebug.s_jcode pool op in + if String.length sop > !opmax then opmax := String.length sop; + let safter = s_vtl after in + (line,sop,safter) + ) l in + let s_ops = String.concat "\n\t\t" (List.map (fun (line,sop,safter) -> + Printf.sprintf "%4i %*s %s" line !opmax sop safter + ) l) in + s_ops + + method stack_error opcode expected actual = + let s_ops = self#debug_stack in + jerror + (Printf.sprintf "Stack error\n\tops :\n\t\t%s\n\t line: %i\n\toperation: %s\n\texpected : %s\n\tactual : %s" + s_ops + current_line + (JvmDebug.s_jcode pool opcode) + (s_vtl expected) + (s_vtl actual) + ) + + method op opcode length expect return = + if last_line <> current_line then begin + last_line <- current_line; + DynArray.add lines (fp,current_line) + end; + DynArray.add ops opcode; + fp <- fp + length; + let cur = stack#get_stack in + List.iter (fun js -> + let js' = try + stack#pop + with EmptyStack -> + self#stack_error opcode expect cur; + assert false + in + (* TODO: some unification or something? *) + match js,js' with + | (TObject _ | TTypeParameter _),(TObject _ | TTypeParameter _ | TArray _) -> () (* TODO ??? *) + | TMethod _,TMethod _ -> () + | TMethod _,TObject((["java";"lang";"invoke"],"MethodHandle"),[]) -> () + | TTypeParameter _,TMethod _ -> () + | TObject _,TMethod _ -> () + | TMethod _,TObject _ -> () + | TArray _,TArray _ -> () + | TBool,TInt -> () + | TInt,TBool -> () + | TDouble,TInt -> () + | TInt,(TChar | TShort | TByte) -> () + | (TObject _ | TTypeParameter _),TUninitialized _ -> () + | _ -> + if js <> js' then self#stack_error opcode expect cur + ) expect; + List.iter stack#push (List.rev return); + DynArray.add stack_debug (opcode,cur,stack#get_stack,current_line); + + method op_maybe_wide op opw i tl tr = match get_numeric_range_unsigned i with + | Int8Range -> self#op op 2 tl tr + | Int16Range -> self#op (OpWide opw) 4 tl tr + | Int32Range -> assert false + + (* variables *) + + method iload ?(jsig=TInt) i = match i with + | 0 -> self#op OpIload_0 1 [] [jsig] + | 1 -> self#op OpIload_1 1 [] [jsig] + | 2 -> self#op OpIload_2 1 [] [jsig] + | 3 -> self#op OpIload_3 1 [] [jsig] + | i -> self#op_maybe_wide (OpIload i) (OpWIload i) i [] [jsig] + + method lload i = match i with + | 0 -> self#op OpLload_0 1 [] [TLong] + | 1 -> self#op OpLload_1 1 [] [TLong] + | 2 -> self#op OpLload_2 1 [] [TLong] + | 3 -> self#op OpLload_3 1 [] [TLong] + | i -> self#op_maybe_wide (OpLload i) (OpWLload i) i [] [TLong] + + method fload i = match i with + | 0 -> self#op OpFload_0 1 [] [TFloat] + | 1 -> self#op OpFload_1 1 [] [TFloat] + | 2 -> self#op OpFload_2 1 [] [TFloat] + | 3 -> self#op OpFload_3 1 [] [TFloat] + | i -> self#op_maybe_wide (OpFload i) (OpWFload i) i [] [TFloat] + + method dload i = match i with + | 0 -> self#op OpDload_0 1 [] [TDouble] + | 1 -> self#op OpDload_1 1 [] [TDouble] + | 2 -> self#op OpDload_2 1 [] [TDouble] + | 3 -> self#op OpDload_3 1 [] [TDouble] + | i -> self#op_maybe_wide (OpDload i) (OpWDload i) i [] [TDouble] + + method aload vtt i = match i with + | 0 -> self#op OpAload_0 1 [] [vtt] + | 1 -> self#op OpAload_1 1 [] [vtt] + | 2 -> self#op OpAload_2 1 [] [vtt] + | 3 -> self#op OpAload_3 1 [] [vtt] + | i -> self#op_maybe_wide (OpAload i) (OpWAload i) i [] [vtt] + + method istore i = match i with + | 0 -> self#op OpIstore_0 1 [TInt] [] + | 1 -> self#op OpIstore_1 1 [TInt] [] + | 2 -> self#op OpIstore_2 1 [TInt] [] + | 3 -> self#op OpIstore_3 1 [TInt] [] + | i -> self#op_maybe_wide (OpIstore i) (OpWIstore i) i [TInt] [] + + method lstore i = match i with + | 0 -> self#op OpLstore_0 1 [TLong] [] + | 1 -> self#op OpLstore_1 1 [TLong] [] + | 2 -> self#op OpLstore_2 1 [TLong] [] + | 3 -> self#op OpLstore_3 1 [TLong] [] + | i -> self#op_maybe_wide (OpLstore i) (OpWLstore i) i [TLong] [] + + method fstore i = match i with + | 0 -> self#op OpFstore_0 1 [TFloat] [] + | 1 -> self#op OpFstore_1 1 [TFloat] [] + | 2 -> self#op OpFstore_2 1 [TFloat] [] + | 3 -> self#op OpFstore_3 1 [TFloat] [] + | i -> self#op_maybe_wide (OpFstore i) (OpWFstore i) i [TFloat] [] + + method dstore i = match i with + | 0 -> self#op OpDstore_0 1 [TDouble] [] + | 1 -> self#op OpDstore_1 1 [TDouble] [] + | 2 -> self#op OpDstore_2 1 [TDouble] [] + | 3 -> self#op OpDstore_3 1 [TDouble] [] + | i -> self#op_maybe_wide (OpDstore i) (OpWDstore i) i [TDouble] [] + + method astore vtt i = match i with + | 0 -> self#op OpAstore_0 1 [vtt] [] + | 1 -> self#op OpAstore_1 1 [vtt] [] + | 2 -> self#op OpAstore_2 1 [vtt] [] + | 3 -> self#op OpAstore_3 1 [vtt] [] + | i -> self#op_maybe_wide (OpAstore i) (OpWAstore i) i [vtt] [] + + method iinc index i = match get_numeric_range_unsigned index,get_numeric_range i with + | Int8Range,Int8Range -> + self#op (OpIinc(index,i)) 3 [] [] + | (Int8Range | Int16Range),(Int8Range | Int16Range) -> + self#op (OpWide (OpWIinc(index,i))) 6 [] [] + | _ -> + assert false + + (* conversions *) + + method d2f = self#op OpD2f 1 [TDouble] [TFloat] + method d2i = self#op OpD2i 1 [TDouble] [TInt] + method d2l = self#op OpD2l 1 [TDouble] [TLong] + + method f2d = self#op OpF2d 1 [TFloat] [TDouble] + method f2i = self#op OpF2i 1 [TFloat] [TInt] + method f2l = self#op OpF2l 1 [TFloat] [TLong] + + method i2b jsig = self#op OpI2b 1 [TInt] [jsig] + method i2c = self#op OpI2c 1 [TInt] [TChar] + method i2d = self#op OpI2d 1 [TInt] [TDouble] + method i2f = self#op OpI2f 1 [TInt] [TFloat] + method i2l = self#op OpI2l 1 [TInt] [TLong] + method i2s = self#op OpI2s 1 [TInt] [TShort] + + method l2d = self#op OpL2d 1 [TLong] [TDouble] + method l2f = self#op OpL2f 1 [TLong] [TFloat] + method l2i = self#op OpL2i 1 [TLong] [TInt] + + (* arrays *) + + method newarray ta t = self#op (OpNewarray t) 2 [TInt] [ta] + method anewarray ta offset = self#op (OpAnewarray offset) 3 [TInt] [ta] + + method arraylength ta = self#op OpArraylength 1 [ta] [TInt] + + method aastore ta te = self#op OpAastore 1 [te;TInt;ta] [] + method aaload ta te = self#op OpAaload 1 [TInt;ta] [te] + + method castore ta = self#op OpCastore 1 [TChar;TInt;ta] [] + method caload ta = self#op OpCaload 1 [TInt;ta] [TChar] + + method fastore ta = self#op OpFastore 1 [TFloat;TInt;ta] [] + method faload ta = self#op OpFaload 1 [TInt;ta] [TFloat] + + method lastore ta = self#op OpLastore 1 [TLong;TInt;ta] [] + method laload ta = self#op OpLaload 1 [TInt;ta] [TLong] + + method sastore ta = self#op OpSastore 1 [TShort;TInt;ta] [] + method saload ta = self#op OpSaload 1 [TInt;ta] [TShort] + + method iastore ta = self#op OpIastore 1 [TInt;TInt;ta] [] + method iaload ta = self#op OpIaload 1 [TInt;ta] [TInt] + + method dastore ta = self#op OpDastore 1 [TDouble;TInt;ta] [] + method daload ta = self#op OpDaload 1 [TInt;ta] [TDouble] + + method bastore jsig ta = self#op OpBastore 1 [jsig;TInt;ta] [] + method baload jsig ta = self#op OpBaload 1 [TInt;ta] [jsig] + + (* fields *) + + method getstatic offset t = + self#op (OpGetstatic offset) 3 [] [t] + + method putstatic offset t = + self#op (OpPutstatic offset) 3 [t] [] + + method getfield offset tobj t = + self#op (OpGetfield offset) 3 [tobj] [t] + + method putfield offset tobj t = + self#op (OpPutfield offset) 3 [t;tobj] [] + + (* calls *) + + method invokestatic offset tl tr = + self#op (OpInvokestatic offset) 3 (List.rev tl) tr + + method invokevirtual offset t1 tl tr = + self#op (OpInvokevirtual offset) 3 (List.rev (t1 :: tl)) tr + + method invokeinterface offset t1 tl tr = + let count = List.fold_left (fun count jsig -> count + signature_size jsig) 1 tl in + self#op (OpInvokeinterface(offset,count)) 5 (List.rev (t1 :: tl)) tr + + method invokespecial offset t1 tl tr = + self#op (OpInvokespecial offset) 3 (List.rev (t1 :: tl)) tr + + method invokedynamic offset tl tr = + self#op (OpInvokedynamic(offset)) 5 (List.rev tl) tr + + method new_ offset = + self#op (OpNew offset) 3 [] [TUninitialized (Some fp)] + + (* return *) + + method return_void = + self#op OpReturn 1 [] [] + + method return_value t = + let op = match t with + | TInt | TBool | TByte | TChar | TShort -> OpIreturn + | TLong -> OpLreturn + | TFloat -> OpFreturn + | TDouble -> OpDreturn + | _ -> OpAreturn + in + self#op op 1 [t] [] + + method athrow = + self#op OpAthrow 1 [stack#top] [] + + (* control flow *) + + method if_ cmp r = self#op (OpIf(cmp,r)) 3 [TBool] [] + method if_ref cmp = let r = ref fp in self#if_ cmp r; r + + method if_icmp cmp r = self#op (OpIf_icmp(cmp,r)) 3 [TInt;TInt] [] + method if_icmp_ref cmp = let r = ref fp in self#if_icmp cmp r; r + + method if_acmp_eq t1 t2 r = self#op (OpIf_acmpeq r) 3 [t1;t2] [] + method if_acmp_eq_ref t1 t2 = let r = ref fp in self#if_acmp_eq t1 t2 r; r + + method if_acmp_ne t1 t2 r = self#op (OpIf_acmpne r) 3 [t1;t2] [] + method if_acmp_ne_ref t1 t2 = let r = ref fp in self#if_acmp_ne t1 t2 r; r + + method if_null t r = self#op (OpIfnull r) 3 [t] [] + method if_null_ref t = let r = ref fp in self#if_null t r; r + + method if_nonnull t r = self#op (OpIfnonnull r) 3 [t] [] + method if_nonnull_ref t = let r = ref fp in self#if_nonnull t r; r + + method goto r = self#op (OpGoto r) 3 [] [] + + method lookupswitch offset_def offsets = + let pad = (fp + 1) mod 4 in + let pad = if pad = 0 then pad else 4 - pad in + self#op (OpLookupswitch(pad,offset_def,offsets)) (9 + pad + (Array.length offsets * 8)) [TInt] [] + + method tableswitch offset_def low high offsets = + let pad = (fp + 1) mod 4 in + let pad = if pad = 0 then pad else 4 - pad in + self#op (OpTableswitch(pad,offset_def,low,high,offsets)) (13 + pad + (Array.length offsets * 4)) [TInt] [] + + (* compare *) + + method dcmpg = self#op OpDcmpg 1 [TDouble;TDouble] [TInt] + method dcmpl = self#op OpDcmpl 1 [TDouble;TDouble] [TInt] + + method fcmpg = self#op OpFcmpg 1 [TFloat;TFloat] [TInt] + method fcmpl = self#op OpFcmpl 1 [TFloat;TFloat] [TInt] + + method lcmpl = self#op OpLcmp 1 [TLong;TLong] [TInt] + + (* ops *) + + method iadd = self#op OpIadd 1 [TInt;TInt] [TInt] + method isub = self#op OpIsub 1 [TInt;TInt] [TInt] + method imul = self#op OpImul 1 [TInt;TInt] [TInt] + method iand = self#op OpIand 1 [TInt;TInt] [TInt] + method ior = self#op OpIor 1 [TInt;TInt] [TInt] + method ixor = self#op OpIxor 1 [TInt;TInt] [TInt] + method ishl = self#op OpIshl 1 [TInt;TInt] [TInt] + method ishr = self#op OpIshr 1 [TInt;TInt] [TInt] + method iushr = self#op OpIushr 1 [TInt;TInt] [TInt] + method irem = self#op OpIrem 1 [TInt;TInt] [TInt] + method ineg = self#op OpIneg 1 [TInt] [TInt] + + method ladd = self#op OpLadd 1 [TLong;TLong] [TLong] + method lsub = self#op OpLsub 1 [TLong;TLong] [TLong] + method lmul = self#op OpLmul 1 [TLong;TLong] [TLong] + method ldiv = self#op OpLdiv 1 [TLong;TLong] [TLong] + method land_ = self#op OpLand 1 [TLong;TLong] [TLong] + method lor_ = self#op OpLor 1 [TLong;TLong] [TLong] + method lxor_ = self#op OpLxor 1 [TLong;TLong] [TLong] + method lshl = self#op OpLshl 1 [TInt;TLong] [TLong] + method lshr = self#op OpLshr 1 [TInt;TLong] [TLong] + method lushr = self#op OpLushr 1 [TInt;TLong] [TLong] + method lrem = self#op OpLrem 1 [TLong;TLong] [TLong] + method lneg = self#op OpLneg 1 [TLong] [TLong] + + method fadd = self#op OpFadd 1 [TFloat;TFloat] [TFloat] + method fsub = self#op OpFsub 1 [TFloat;TFloat] [TFloat] + method fmul = self#op OpFmul 1 [TFloat;TFloat] [TFloat] + method fdiv = self#op OpFdiv 1 [TFloat;TFloat] [TFloat] + method frem = self#op OpFrem 1 [TFloat;TFloat] [TFloat] + method fneg = self#op OpFneg 1 [TFloat] [TFloat] + + method dadd = self#op OpDadd 1 [TDouble;TDouble] [TDouble] + method dsub = self#op OpDsub 1 [TDouble;TDouble] [TDouble] + method dmul = self#op OpDmul 1 [TDouble;TDouble] [TDouble] + method ddiv = self#op OpDdiv 1 [TDouble;TDouble] [TDouble] + method drem = self#op OpDrem 1 [TDouble;TDouble] [TDouble] + method dneg = self#op OpDneg 1 [TDouble] [TDouble] + + (* stack *) + + method pop = + let top = stack#top in + self#op (if signature_size top = 1 then OpPop else OpPop2) 1 [top] [] + + method dup = match stack#top with + | TLong | TDouble -> self#op OpDup2 1 [] [stack#top] + | _ -> self#op OpDup 1 [] [stack#top] + + method dup_x1 = + let tl = stack#get_stack_items 2 in + let tl2 = (List.hd tl :: (List.rev tl)) in + match tl with + | (TLong | TDouble) :: _ -> self#op OpDup2_x1 1 tl tl2 + | _ -> self#op OpDup_x1 1 tl tl2 + + method dup_x2 = + let tl = stack#get_stack_items 3 in + let sizes = List.map signature_size tl in + match sizes,tl with + | 2 :: 2 :: _,vt1 :: vt2 :: _ -> self#op OpDup2_x2 1 [vt1;vt2] [vt1;vt2;vt1] + | 1 :: 2 :: _,vt1 :: vt2 :: _ -> self#op OpDup_x2 1 [vt1;vt2] [vt1;vt2;vt1] + | 1 :: 1 :: 1 :: _,vt1 :: vt2 :: vt3 :: _ -> self#op OpDup_x2 1 tl [vt1;vt2;vt3;vt1] + | 2 :: 1 :: 1 :: _,vt1 :: vt2 :: vt3 :: _ -> self#op OpDup2_x2 1 tl [vt1;vt2;vt3;vt1] + | _ -> jerror "???" + + method swap = + let tl = stack#get_stack_items 2 in + self#op OpSwap 1 tl (List.rev tl) + + method checkcast_sig jsig = + let offset = pool#add_type (generate_signature false jsig) in + self#op (OpCheckcast offset) 3 [stack#top] [jsig] + + method checkcast path = + let offset = pool#add_path path in + let jsig = match path with + | [],"Int" -> TInt + | ["haxe" | "java"],"Int64" -> TLong + | _ -> TObject(path,[]) + in + self#op (OpCheckcast offset) 3 [stack#top] [jsig] + + method instanceof path = + let offset = pool#add_path path in + self#op (OpInstanceof offset) 3 [stack#top] [TInt] + + (* monitor *) + + method monitorenter = + self#op OpMonitorenter 1 [stack#top] [] + + method monitorexit = + self#op OpMonitorexit 1 [stack#top] [] + + (* constants *) + + method aconst_null t = self#op OpAconst_null 1 [] [t] + + method ldc offset vt = + if offset < 0xFF then + self#op (OpLdc offset) 2 [] [vt] + else + self#op (OpLdc_w offset) 3 [] [vt] + + method bconst b = + self#op (if b then OpIconst_1 else OpIconst_0) 1 [] [TBool] + + method iconst i32 = + let instr,count = match Int32.to_int i32 with + | -1 -> OpIconst_m1,1 + | 0 -> OpIconst_0,1 + | 1 -> OpIconst_1,1 + | 2 -> OpIconst_2,1 + | 3 -> OpIconst_3,1 + | 4 -> OpIconst_4,1 + | 5 -> OpIconst_5,1 + | i -> + match get_numeric_range i with + | Int8Range -> + OpBipush i,2 + | Int16Range -> + OpSipush i,3 + | Int32Range -> + let offset = pool#add (ConstInt i32) in + if offset < 0xFF then + OpLdc offset,2 + else + OpLdc_w offset,3 + in + self#op instr count [] [TInt] + + method dconst f = + let instr,count = match f with + | 0.0 -> OpDconst_0,1 + | 1.0 -> OpDconst_1,1 + | _ -> + let offset = pool#add (ConstDouble f) in + OpLdc2_w offset,3 + in + self#op instr count [] [TDouble] + + method lconst d = + let instr,count = if d = Int64.zero then + OpLconst_0,1 + else if d = Int64.one then + OpLconst_1,1 + else begin + let offset = pool#add (ConstLong d) in + OpLdc2_w offset,3 + end in + self#op instr count [] [TLong] + + method fconst f = + let instr,count = match f with + | 0.0 -> OpFconst_0,1 + | 1.0 -> OpFconst_1,1 + | 2.0 -> OpFconst_2,1 + | _ -> + let offset = pool#add (ConstFloat f) in + OpLdc_w offset,3 + in + self#op instr count [] [TFloat] + + method sconst t offset = + self#ldc offset t + + method get_pool : JvmConstantPool.constant_pool = pool + method get_fp = fp + method get_ops = ops + method get_stack = stack + method get_max_stack_size = stack#get_max_stack_size + + method get_lines = lines + method set_line line = current_line <- line + + method export_code = + let ch = IO.output_bytes () in + DynArray.iter (JvmWriter.write_opcode ch) ops; + IO.close_out ch +end \ No newline at end of file diff --git a/src/generators/jvm/jvmConstantPool.ml b/src/generators/jvm/jvmConstantPool.ml new file mode 100644 index 00000000000..e1cc1698508 --- /dev/null +++ b/src/generators/jvm/jvmConstantPool.ml @@ -0,0 +1,192 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open IO +open IO.BigEndian +open JvmGlobals +open JvmSignature + +(* High-level constant pool *) + +let utf8jvm (input : string) : bytes = + let channel = IO.output_bytes () in + UTF8.iter (fun c -> + let code = UChar.code c in + match code with + | b when (b > 0 && b <= 0x7F) -> + IO.write_byte channel b + (* includes null byte: *) + | b when (b <= 0x7FF) -> + IO.write_byte channel (0xC0 lor ((b lsr 6) )); + IO.write_byte channel (0x80 lor ((b ) land 0x3F)) + | b when (b <= 0xFFFF) -> + IO.write_byte channel (0xE0 lor ((b lsr 12) )); + IO.write_byte channel (0x80 lor ((b lsr 6) land 0x3F)); + IO.write_byte channel (0x80 lor ((b ) land 0x3F)) + | b -> + IO.write_byte channel 0xED; + IO.write_byte channel (0xA0 lor ((b lsr 16) - 1 )); + IO.write_byte channel (0x80 lor ((b lsr 10) land 0x3F)); + IO.write_byte channel 0xED; + IO.write_byte channel (0xB0 lor ((b lsr 6) land 0x0F)); + IO.write_byte channel (0x80 lor ((b ) land 0x3F)) + ) input; + IO.close_out channel +;; + +class constant_pool = object(self) + val pool = DynArray.create (); + val lut = Hashtbl.create 0; + val luti = Hashtbl.create 0; + val mutable next_index = 1; + val mutable closed = false + val inner_classes = Hashtbl.create 0 + + method add const = + try + Hashtbl.find lut const + with Not_found -> + assert (not closed); + let i = next_index in + next_index <- next_index + 1; + DynArray.add pool const; + Hashtbl.add lut const i; + Hashtbl.add luti i (DynArray.length pool - 1); + match const with + | ConstDouble _ | ConstLong _ -> + next_index <- next_index + 1; + i + | _ -> + i + + method get i = + DynArray.get pool (Hashtbl.find luti i) + + method private s_type_path (p,s) = match p with [] -> s | _ -> String.concat "/" p ^ "/" ^ s + + method add_type s = + let offset = self#add (ConstUtf8 s) in + self#add (ConstClass offset); + + method add_path path = + let s = self#s_type_path path in + let offset = self#add_type s in + if String.contains (snd path) '$' then begin + let name1,name2 = ExtString.String.split (snd path) "$" in + Hashtbl.replace inner_classes ((fst path,name1),name2) offset; + end; + offset + + method add_string s = + self#add (ConstUtf8 s) + + method add_const_string s = + let offset = self#add_string s in + self#add (ConstString offset) + + method add_name_and_type name jsig field_kind = + let offset_name = self#add_string name in + let offset_desc = self#add_string ((if field_kind = FKField then generate_signature else generate_method_signature) false jsig) in + self#add (ConstNameAndType(offset_name,offset_desc)) + + method add_field path name jsig field_kind = + let offset_class = self#add_path path in + let offset_info = self#add_name_and_type name jsig field_kind in + let const = match field_kind with + | FKField -> ConstFieldref(offset_class,offset_info) + | FKMethod -> ConstMethodref(offset_class,offset_info) + | FKInterfaceMethod -> ConstInterfaceMethodref(offset_class,offset_info) + in + self#add const + + method get_inner_classes = inner_classes + + method private write_i64 ch i64 = + write_real_i32 ch (Int64.to_int32 i64); + write_real_i32 ch (Int64.to_int32 (Int64.shift_right_logical i64 32)) + + method private write ch = + write_ui16 ch next_index; + DynArray.iter (function + | ConstUtf8 s -> + write_byte ch 1; + let b = utf8jvm s in + write_ui16 ch (Bytes.length b); + nwrite ch b + | ConstInt i32 -> + write_byte ch 3; + write_real_i32 ch i32; + | ConstFloat f -> + write_byte ch 4; + (match classify_float f with + | FP_normal | FP_subnormal | FP_zero -> + write_real_i32 ch (Int32.bits_of_float f) + | FP_infinite when f > 0.0 -> + write_real_i32 ch 0x7f800000l + | FP_infinite -> + write_real_i32 ch 0xff800000l + | FP_nan -> + write_real_i32 ch 0x7f800001l) + | ConstLong i64 -> + write_byte ch 5; + write_i64 ch i64; + | ConstDouble d -> + write_byte ch 6; + write_double ch d + | ConstClass offset -> + write_byte ch 7; + write_ui16 ch offset; + | ConstString offset -> + write_byte ch 8; + write_ui16 ch offset; + | ConstFieldref (offset1,offset2) -> + write_byte ch 9; + write_ui16 ch offset1; + write_ui16 ch offset2; + | ConstMethodref (offset1,offset2) -> + write_byte ch 10; + write_ui16 ch offset1; + write_ui16 ch offset2; + | ConstInterfaceMethodref (offset1,offset2) -> + write_byte ch 11; + write_ui16 ch offset1; + write_ui16 ch offset2; + | ConstNameAndType (offset1,offset2) -> + write_byte ch 12; + write_ui16 ch offset1; + write_ui16 ch offset2; + | ConstMethodHandle (i,offset) -> + write_byte ch 15; + write_byte ch i; + write_ui16 ch offset; + | ConstMethodType offset -> + write_byte ch 16; + write_ui16 ch offset; + | ConstInvokeDynamic (offset1,offset2) -> + write_byte ch 18; + write_ui16 ch offset1; + write_ui16 ch offset2; + ) pool + + method close = + closed <- true; + let ch = IO.output_bytes () in + self#write ch; + IO.close_out ch +end \ No newline at end of file diff --git a/src/generators/jvm/jvmData.ml b/src/generators/jvm/jvmData.ml new file mode 100644 index 00000000000..acf0d36e790 --- /dev/null +++ b/src/generators/jvm/jvmData.ml @@ -0,0 +1,294 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open JvmGlobals + +(* Low-level data that is written out. *) + +type jvm_attribute = { + attr_index : jvm_constant_pool_index; + attr_data : bytes; +} + +type jvm_field = { + field_access_flags : int; + field_name_index : int; + field_descriptor_index : int; + field_attributes : jvm_attribute array; +} + +type jvm_class = { + class_minor_version : int; + class_major_version : int; + class_constant_pool : bytes; + class_access_flags : int; + class_this_class : int; + class_super_class : int; + class_interfaces : int array; + class_fields : jvm_field array; + class_methods : jvm_field array; + class_attributes : jvm_attribute array; +} + +type jvm_exception = { + exc_start_pc : int; + exc_end_pc : int; + exc_handler_pc : int; + exc_catch_type : jvm_constant_pool_index option; +} + +type jvm_code = { + code_max_stack : int; + code_max_locals : int; + code_code : bytes; + code_exceptions : jvm_exception array; + code_attributes : jvm_attribute array; +} + +(* Opcodes *) + +type jbyte = int +type jshort = int +type jbranchoffset = int + +type jcmp = + | CmpEq + | CmpNe + | CmpLt + | CmpGe + | CmpGt + | CmpLe + +type opwide = + | OpWIinc of jshort * jshort + | OpWIload of jshort + | OpWFload of jshort + | OpWAload of jshort + | OpWLload of jshort + | OpWDload of jshort + | OpWIstore of jshort + | OpWFstore of jshort + | OpWAstore of jshort + | OpWLstore of jshort + | OpWDstore of jshort + +and jopcode = + (* double *) + | OpD2f + | OpD2i + | OpD2l + | OpDadd + | OpDaload + | OpDastore + | OpDcmpg + | OpDcmpl + | OpDdiv + | OpDconst_0 + | OpDconst_1 + | OpDload_0 + | OpDload_1 + | OpDload_2 + | OpDload_3 + | OpDload of jbyte + | OpDmul + | OpDneg + | OpDrem + | OpDreturn + | OpDstore_0 + | OpDstore_1 + | OpDstore_2 + | OpDstore_3 + | OpDstore of jbyte + | OpDsub + (* float *) + | OpF2d + | OpF2i + | OpF2l + | OpFadd + | OpFaload + | OpFastore + | OpFcmpg + | OpFcmpl + | OpFdiv + | OpFconst_0 + | OpFconst_1 + | OpFconst_2 + | OpFload_0 + | OpFload_1 + | OpFload_2 + | OpFload_3 + | OpFload of jbyte + | OpFmul + | OpFneg + | OpFrem + | OpFreturn + | OpFstore_0 + | OpFstore_1 + | OpFstore_2 + | OpFstore_3 + | OpFstore of jbyte + | OpFsub + (* int *) + | OpI2b + | OpI2c + | OpI2d + | OpI2f + | OpI2l + | OpI2s + | OpIadd + | OpIaload + | OpIand + | OpIastore + | OpIconst_m1 + | OpIconst_0 + | OpIconst_1 + | OpIconst_2 + | OpIconst_3 + | OpIconst_4 + | OpIconst_5 + | OpIdiv + | OpIload_0 + | OpIload_1 + | OpIload_2 + | OpIload_3 + | OpIload of jbyte + | OpImul + | OpIneg + | OpIor + | OpIrem + | OpIreturn + | OpIshl + | OpIshr + | OpIstore_0 + | OpIstore_1 + | OpIstore_2 + | OpIstore_3 + | OpIstore of jbyte + | OpIsub + | OpIushr + | OpIxor + (* long *) + | OpL2d + | OpL2f + | OpL2i + | OpLadd + | OpLaload + | OpLand + | OpLastore + | OpLconst_0 + | OpLconst_1 + | OpLcmp + | OpLdiv + | OpLload_0 + | OpLload_1 + | OpLload_2 + | OpLload_3 + | OpLload of jbyte + | OpLmul + | OpLneg + | OpLor + | OpLrem + | OpLreturn + | OpLshl + | OpLshr + | OpLstore_0 + | OpLstore_1 + | OpLstore_2 + | OpLstore_3 + | OpLstore of jbyte + | OpLsub + | OpLushr + | OpLxor + (* short *) + | OpSaload + | OpSastore + | OpSipush of jshort + (* array *) + | OpAaload + | OpAastore + | OpAnewarray of jvm_constant_pool_index + | OpArraylength + | OpBaload + | OpBastore + | OpBipush of jbyte + | OpCaload + | OpCastore + | OpMultianewarray of jvm_constant_pool_index * jbyte + | OpNewarray of jbyte + (* reference *) + | OpAload_0 + | OpAload_1 + | OpAload_2 + | OpAload_3 + | OpAload of jbyte + | OpAreturn + | OpAstore_0 + | OpAstore_1 + | OpAstore_2 + | OpAstore_3 + | OpAstore of jbyte + (* object *) + | OpNew of jvm_constant_pool_index + | OpInstanceof of jvm_constant_pool_index + | OpCheckcast of jvm_constant_pool_index + | OpInvokedynamic of jvm_constant_pool_index + | OpInvokeinterface of jvm_constant_pool_index * jbyte + | OpInvokespecial of jvm_constant_pool_index + | OpInvokestatic of jvm_constant_pool_index + | OpInvokevirtual of jvm_constant_pool_index + | OpGetfield of jvm_constant_pool_index + | OpGetstatic of jvm_constant_pool_index + | OpPutfield of jvm_constant_pool_index + | OpPutstatic of jvm_constant_pool_index + (* branching *) + | OpIf_acmpeq of jbranchoffset ref + | OpIf_acmpne of jbranchoffset ref + | OpIf_icmp of jcmp * jbranchoffset ref + | OpIf of jcmp * jbranchoffset ref + | OpIfnonnull of jbranchoffset ref + | OpIfnull of jbranchoffset ref + | OpGoto of jbranchoffset ref + | OpGoto_w of jbranchoffset ref + | OpJsr of jbranchoffset ref + | OpJsr_w of jbranchoffset ref + (* stack *) + | OpAconst_null + | OpDup + | OpDup_x1 + | OpDup_x2 + | OpDup2 + | OpDup2_x1 + | OpDup2_x2 + | OpLdc of jbyte + | OpLdc_w of jvm_constant_pool_index + | OpLdc2_w of jvm_constant_pool_index + | OpNop + | OpPop + | OpPop2 + | OpSwap + (* other *) + | OpAthrow + | OpIinc of jbyte * jbyte + | OpLookupswitch of int (* num pad bytes *) * jbranchoffset ref (* default *) * (Int32.t * jbranchoffset ref) array + | OpTableswitch of int (* num pad bytes *) * jbranchoffset ref (* default *) * Int32.t (* low *) * Int32.t (* high *) * jbranchoffset ref array + | OpMonitorenter + | OpMonitorexit + | OpRet of jbyte + | OpReturn + | OpWide of opwide \ No newline at end of file diff --git a/src/generators/jvm/jvmDebug.ml b/src/generators/jvm/jvmDebug.ml new file mode 100644 index 00000000000..17c5d2e98ad --- /dev/null +++ b/src/generators/jvm/jvmDebug.ml @@ -0,0 +1,281 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open JvmGlobals +open JvmData + +(* Printing debug functions *) + +let s_const pool const = + let rec loop depth const = + if depth = 3 then + "..." + else begin + let rec_find i = loop (depth + 1) (pool#get i) in + match const with + | ConstUtf8 s -> Printf.sprintf "Utf8 \"%s\"" s + | ConstInt i32 -> Printf.sprintf "Int %i" (Int32.to_int i32) + | ConstFloat f -> Printf.sprintf "Float %f" f + | ConstLong i64 -> Printf.sprintf "Int %i" (Int64.to_int i64) + | ConstDouble f -> Printf.sprintf "Double %f" f + | ConstClass i -> Printf.sprintf "Class(%s)" (rec_find i) + | ConstString i -> Printf.sprintf "String(%s)" (rec_find i) + | ConstFieldref(i1,i2) -> Printf.sprintf "Fieldref(%s, %s)" (rec_find i1) (rec_find i2) + | ConstMethodref(i1,i2) -> Printf.sprintf "Methodref(%s, %s)" (rec_find i1) (rec_find i2) + | ConstInterfaceMethodref(i1,i2) -> Printf.sprintf "InterfaceMethodref(%s, %s)" (rec_find i1) (rec_find i2) + | ConstNameAndType(i1,i2) -> Printf.sprintf "NameAndType(%s, %s)" (rec_find i1) (rec_find i2) + | ConstMethodHandle(i1,i2) -> Printf.sprintf "MethodHandle(%i, %s)" i1 (rec_find i2) + | ConstMethodType i -> Printf.sprintf "MethodType(%s)" (rec_find i) + | ConstInvokeDynamic(i1,i2) -> Printf.sprintf "InvokeDynamic(%i, %s)" i1 (rec_find i2) + end + in + loop 0 const + +let s_const_nice pool const = + let rec loop depth const = + if depth = 3 then + "..." + else begin + let rec_find i = loop (depth + 1) (pool#get i) in + match const with + | ConstUtf8 s -> Printf.sprintf "%s" s + | ConstInt i32 -> Printf.sprintf "%i" (Int32.to_int i32) + | ConstFloat f -> Printf.sprintf "%f" f + | ConstLong i64 -> Printf.sprintf "%i" (Int64.to_int i64) + | ConstDouble f -> Printf.sprintf "%f" f + | ConstClass i -> Printf.sprintf "%s" (rec_find i) + | ConstString i -> Printf.sprintf "%s" (rec_find i) + | ConstFieldref(i1,i2) -> Printf.sprintf "%s.%s" (rec_find i1) (rec_find i2) + | ConstMethodref(i1,i2) -> Printf.sprintf "%s.%s" (rec_find i1) (rec_find i2) + | ConstInterfaceMethodref(i1,i2) -> Printf.sprintf "%s.%s" (rec_find i1) (rec_find i2) + | ConstNameAndType(i1,i2) -> Printf.sprintf "%s:%s" (rec_find i1) (rec_find i2) + | ConstMethodHandle(i1,i2) -> Printf.sprintf "MethodHandle(%i, %s)" i1 (rec_find i2) + | ConstMethodType i -> Printf.sprintf "MethodType(%s)" (rec_find i) + | ConstInvokeDynamic(i1,i2) -> Printf.sprintf "InvokeDynamic(%i, %s)" i1 (rec_find i2) + end + in + loop 0 const + +let s_jcode pool code = + let wi s i = Printf.sprintf "%s %i" s i in + let sc i = s_const_nice pool (pool#get i) in + match code with + (* double *) + | OpD2f -> "d2f" + | OpD2i -> "d2i" + | OpD2l -> "d2l" + | OpDadd -> "dadd" + | OpDaload -> "daload" + | OpDastore -> "dastore" + | OpDcmpg -> "dcmpg" + | OpDcmpl -> "dcmpl" + | OpDdiv -> "ddiv" + | OpDconst_0 -> "dconst_0" + | OpDconst_1 -> "dconst_1" + | OpDload_0 -> "dload_0" + | OpDload_1 -> "dload_1" + | OpDload_2 -> "dload_2" + | OpDload_3 -> "dload_3" + | OpDload i -> wi "dload" i + | OpDmul -> "dmul" + | OpDneg -> "dneg" + | OpDrem -> "drem" + | OpDreturn -> "dreturn" + | OpDstore_0 -> "dstore_0" + | OpDstore_1 -> "dstore_1" + | OpDstore_2 -> "dstore_2" + | OpDstore_3 -> "dstore_3" + | OpDstore i -> wi "dstore" i + | OpDsub -> "dsub" + (* float *) + | OpF2d -> "f2d" + | OpF2i -> "f2i" + | OpF2l -> "f2l" + | OpFadd -> "fadd" + | OpFaload -> "faload" + | OpFastore -> "fastore" + | OpFcmpg -> "fcmpg" + | OpFcmpl -> "fcmpl" + | OpFdiv -> "fdiv" + | OpFconst_0 -> "fconst_0" + | OpFconst_1 -> "fconst_1" + | OpFconst_2 -> "fconst_2" + | OpFload_0 -> "fload_0" + | OpFload_1 -> "fload_1" + | OpFload_2 -> "fload_2" + | OpFload_3 -> "fload_3" + | OpFload i -> wi "fload" i + | OpFmul -> "fmul" + | OpFneg -> "fneg" + | OpFrem -> "frem" + | OpFreturn -> "freturn" + | OpFstore_0 -> "fstore_0" + | OpFstore_1 -> "fstore_1" + | OpFstore_2 -> "fstore_2" + | OpFstore_3 -> "fstore_3" + | OpFstore i -> wi "fstore" i + | OpFsub -> "fsub" + (* int *) + | OpI2b -> "i2b" + | OpI2c -> "i2c" + | OpI2d -> "i2d" + | OpI2f -> "i2f" + | OpI2l -> "i2l" + | OpI2s -> "i2s" + | OpIadd -> "iadd" + | OpIaload -> "iaload" + | OpIand -> "iand" + | OpIastore -> "iastore" + | OpIconst_m1 -> "iconst_m1" + | OpIconst_0 -> "iconst_0" + | OpIconst_1 -> "iconst_1" + | OpIconst_2 -> "iconst_2" + | OpIconst_3 -> "iconst_3" + | OpIconst_4 -> "iconst_4" + | OpIconst_5 -> "iconst_5" + | OpIdiv -> "idiv" + | OpIload_0 -> "iload_0" + | OpIload_1 -> "iload_1" + | OpIload_2 -> "iload_2" + | OpIload_3 -> "iload_3" + | OpIload i -> wi "iload" i + | OpImul -> "imul" + | OpIneg -> "ineg" + | OpIor -> "ior" + | OpIrem -> "irem" + | OpIreturn -> "ireturn" + | OpIshl -> "ishl" + | OpIshr -> "ishr" + | OpIstore_0 -> "istore_0" + | OpIstore_1 -> "istore_1" + | OpIstore_2 -> "istore_2" + | OpIstore_3 -> "istore_3" + | OpIstore i -> wi "istore" i + | OpIsub -> "isub" + | OpIushr -> "iushr" + | OpIxor -> "ixor" + (* long *) + | OpL2d -> "l2d" + | OpL2f -> "l2f" + | OpL2i -> "l2i" + | OpLadd -> "ladd" + | OpLaload -> "laload" + | OpLand -> "land" + | OpLastore -> "lastore" + | OpLconst_0 -> "lconst_0" + | OpLconst_1 -> "lconst_1" + | OpLcmp -> "lcmp" + | OpLdiv -> "ldiv" + | OpLload_0 -> "lload_0" + | OpLload_1 -> "lload_1" + | OpLload_2 -> "lload_2" + | OpLload_3 -> "lload_3" + | OpLload i -> wi "lload" i + | OpLmul -> "lmul" + | OpLneg -> "lneg" + | OpLor -> "lor" + | OpLrem -> "lrem" + | OpLreturn -> "lreturn" + | OpLshl -> "lshl" + | OpLshr -> "lshr" + | OpLstore_0 -> "lstore_0" + | OpLstore_1 -> "lstore_1" + | OpLstore_2 -> "lstore_2" + | OpLstore_3 -> "lstore_3" + | OpLstore i -> wi "lstore" i + | OpLsub -> "lsub" + | OpLushr -> "lushr" + | OpLxor -> "lxor" + (* short *) + | OpSaload -> "saload" + | OpSastore -> "sastore" + | OpSipush i -> wi "sipush" i + (* array *) + | OpAaload -> "aaload" + | OpAastore -> "aastore" + | OpAnewarray offset -> wi "anewarray" offset + | OpArraylength -> "arraylength" + | OpBaload -> "baload" + | OpBastore -> "bastore" + | OpBipush i -> wi "bipush" i + | OpCaload -> "caload" + | OpCastore -> "castore" + | OpMultianewarray(path,i) -> "multinewarray" (* TODO *) + | OpNewarray(jsig) -> "newarray" (* TODO *) + (* reference *) + | OpAload_0 -> "aload_0" + | OpAload_1 -> "aload_1" + | OpAload_2 -> "aload_2" + | OpAload_3 -> "aload_3" + | OpAload i -> wi "aload" i + | OpAreturn -> "areturn" + | OpAstore_0 -> "astore_0" + | OpAstore_1 -> "astore_1" + | OpAstore_2 -> "astore_2" + | OpAstore_3 -> "astore_3" + | OpAstore i -> wi "astore" i + (* object *) + | OpNew offset -> wi "new" offset + | OpInstanceof offset -> wi "instanceof" offset + | OpCheckcast offset -> wi "checkcast" offset + | OpInvokedynamic arg -> "invokedynamic" + | OpInvokeinterface(arg1,arg2) -> "invokeinterface" + | OpInvokespecial arg1 -> Printf.sprintf "invokespecial %s" (sc arg1) + | OpInvokestatic arg1 -> Printf.sprintf "invokestatic %s" (sc arg1) + | OpInvokevirtual arg1 -> Printf.sprintf "invokevirtual %s" (sc arg1) + | OpGetfield arg1 -> Printf.sprintf "getfield %s" (sc arg1) + | OpGetstatic arg1 -> Printf.sprintf "getstatic %s" (sc arg1) + | OpPutfield arg1 -> Printf.sprintf "putfield %s" (sc arg1) + | OpPutstatic arg1 -> Printf.sprintf "putstatic %s" (sc arg1) + (* branching *) + | OpIf_acmpeq i -> wi "acmpeq" !i + | OpIf_acmpne i -> wi "acmpne" !i + | OpIf_icmp(cmp,i) -> wi "if_icmp" !i (* TODO *) + | OpIf(cmp,i) -> wi "if" !i (* TODO *) + | OpIfnonnull i -> wi "ifnotnull" !i + | OpIfnull i -> wi "ifnull" !i + | OpGoto i -> wi "goto" !i + | OpGoto_w i -> wi "goto_w" !i + | OpJsr i -> wi "jsr" !i + | OpJsr_w i -> wi "jsr_w" !i + (* stack *) + | OpAconst_null -> "aconst_null" + | OpDup -> "dup" + | OpDup_x1 -> "dup_x1" + | OpDup_x2 -> "dup_x2" + | OpDup2 -> "dup2" + | OpDup2_x1 -> "dup2_x1" + | OpDup2_x2 -> "dup2_x2" + | OpLdc i -> wi "ldc" i + | OpLdc_w i -> wi "ldc_w" i + | OpLdc2_w i -> wi "ldc2_w" i + | OpNop -> "nop" + | OpPop -> "pop" + | OpPop2 -> "pop2" + | OpSwap -> "swap" + (* other *) + | OpAthrow -> "athrow" + | OpIinc(i1,i2) -> wi "iinc" i1 (* TODO *) + | OpLookupswitch _ -> "lookupswitch" + | OpMonitorenter -> "monitorenter" + | OpMonitorexit -> "monitorexit" + | OpRet i -> wi "ret" i + | OpReturn -> "return" + | OpTableswitch _ -> "tableswitch" + | OpWide _ -> "wide" \ No newline at end of file diff --git a/src/generators/jvm/jvmGlobals.ml b/src/generators/jvm/jvmGlobals.ml new file mode 100644 index 00000000000..5f5a5d4715e --- /dev/null +++ b/src/generators/jvm/jvmGlobals.ml @@ -0,0 +1,166 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +type jvm_constant_pool_index = int + +(* Constants *) + +type jvm_bootstrap_method_index = int + +type jvm_constant = + | ConstUtf8 of string + | ConstInt of int32 + | ConstFloat of float + | ConstLong of int64 + | ConstDouble of float + | ConstClass of jvm_constant_pool_index + | ConstString of jvm_constant_pool_index + | ConstFieldref of jvm_constant_pool_index * jvm_constant_pool_index + | ConstMethodref of jvm_constant_pool_index * jvm_constant_pool_index + | ConstInterfaceMethodref of jvm_constant_pool_index * jvm_constant_pool_index + | ConstNameAndType of jvm_constant_pool_index * jvm_constant_pool_index + | ConstMethodHandle of int * jvm_constant_pool_index + | ConstMethodType of jvm_constant_pool_index + | ConstInvokeDynamic of jvm_bootstrap_method_index * jvm_constant_pool_index + +type field_kind = + | FKField + | FKMethod + | FKInterfaceMethod + +type numeric_range = + | Int8Range + | Int16Range + | Int32Range + +let i320xFF = Int32.of_int 0xFF + +let get_numeric_range i = + if i >= -128 && i <= 127 then Int8Range + else if i >= -32768 && i <= 32767 then Int16Range + else Int32Range + +let get_numeric_range_unsigned i = + if i <= 0xFF then Int8Range + else if i <= 0xFFFF then Int16Range + else Int32Range + +let in_range unsigned range i = match (if unsigned then get_numeric_range_unsigned else get_numeric_range) i,range with + | Int8Range,(Int8Range | Int16Range | Int32Range) -> true + | Int16Range,(Int16Range | Int32Range) -> true + | Int32Range,Int32Range -> true + | _ -> false + +let jerror s = + failwith s + +module ClassAccessFlags = struct + type t = + | CPublic + | CFinal + | CSuper + | CInterface + | CAbstract + | CSynthetic + | CAnnotation + | CEnum + + let to_int = function + | CPublic -> 0x1 + | CFinal -> 0x10 + | CSuper -> 0x20 + | CInterface -> 0x200 + | CAbstract -> 0x400 + | CSynthetic -> 0x1000 + | CAnnotation -> 0x2000 + | CEnum -> 0x4000 + + let has_flag b flag = + b land (to_int flag) <> 0 +end + +module MethodAccessFlags = struct + type t = + | MPublic + | MPrivate + | MProtected + | MStatic + | MFinal + | MSynchronized + | MBridge + | MVarargs + | MNative + | MAbstract + | MStrict + | MSynthetic + + let to_int = function + | MPublic -> 0x1 + | MPrivate -> 0x2 + | MProtected -> 0x4 + | MStatic -> 0x8 + | MFinal -> 0x10 + | MSynchronized -> 0x20 + | MBridge -> 0x40 + | MVarargs -> 0x80 + | MNative -> 0x100 + | MAbstract -> 0x400 + | MStrict -> 0x800 + | MSynthetic -> 0x1000 + + let has_flag b flag = + b land (to_int flag) <> 0 +end + +module FieldAccessFlags = struct + type t = + | FdPublic + | FdPrivate + | FdProtected + | FdStatic + | FdFinal + | FdVolatile + | FdTransient + | FdSynthetic + | FdEnum + + let to_int = function + | FdPublic -> 0x1 + | FdPrivate -> 0x2 + | FdProtected -> 0x4 + | FdStatic -> 0x8 + | FdFinal -> 0x10 + | FdVolatile -> 0x40 + | FdTransient -> 0x80 + | FdSynthetic -> 0x1000 + | FdEnum -> 0x4000 + + let has_flag b flag = + b land (to_int flag) <> 0 +end + +let write_byte ch i = IO.write_byte ch i +let write_bytes ch b = IO.nwrite ch b +let write_ui16 ch i = IO.BigEndian.write_ui16 ch i +let write_ui32 ch i = IO.BigEndian.write_real_i32 ch (Int32.of_int i) +let write_string ch s = IO.nwrite_string ch s + +let write_array16 ch f a = + write_ui16 ch (Array.length a); + Array.iter (f ch) a \ No newline at end of file diff --git a/src/generators/jvm/jvmMethod.ml b/src/generators/jvm/jvmMethod.ml new file mode 100644 index 00000000000..03d7b520c6f --- /dev/null +++ b/src/generators/jvm/jvmMethod.ml @@ -0,0 +1,844 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals +open JvmGlobals +open JvmData +open JvmAttribute +open JvmSignature +open JvmSignature.NativeSignatures +open JvmBuilder + +(* High-level method builder. *) + +type var_init_state = + | VarArgument + | VarWillInit + | VarNeedDefault + +type construction_kind = + | ConstructInitPlusNew + | ConstructInit + +module NativeArray = struct + let read code ja je = match je with + | TBool -> code#baload TBool ja + | TByte -> code#baload TByte ja + | TChar -> code#caload ja + | TDouble -> code#daload ja + | TFloat -> code#faload ja + | TInt -> code#iaload ja + | TLong -> code#laload ja + | TShort -> code#saload ja + | _ -> code#aaload ja je + + let write code ja je = match je with + | TBool -> code#bastore TBool ja + | TByte -> code#bastore TByte ja + | TChar -> code#castore ja + | TDouble -> code#dastore ja + | TFloat -> code#fastore ja + | TInt -> code#iastore ja + | TLong -> code#lastore ja + | TShort -> code#sastore ja + | _ -> code#aastore ja je + + let create code pool je = + let ja = (TArray(je,None)) in + let primitive i = + code#newarray ja i + in + let reference path = + let offset = pool#add_path path in + code#anewarray ja offset; + in + begin match je with + | TBool -> primitive 4 + | TChar -> primitive 5 + | TFloat -> primitive 6 + | TDouble -> primitive 7 + | TByte -> primitive 8 + | TShort -> primitive 9 + | TInt -> primitive 10 + | TLong -> primitive 11 + | TObject(path,_) -> reference path + | TMethod _ -> reference NativeSignatures.method_handle_path + | TTypeParameter _ -> reference NativeSignatures.object_path + | TArray _ -> + let offset = pool#add_type (generate_signature false je) in + code#anewarray ja offset + | TObjectInner _ | TUninitialized _ -> assert false + end; + ja +end + +class builder jc name jsig = object(self) + inherit base_builder + val code = new JvmCode.builder jc#get_pool + + val mutable max_num_locals = 0 + val mutable debug_locals = [] + val mutable stack_frames = [] + val mutable exceptions = [] + val mutable argument_locals = [] + val mutable thrown_exceptions = Hashtbl.create 0 + + (* per-branch *) + val mutable terminated = false + + (* per-frame *) + val mutable locals = [] + val mutable local_offset = 0 + + method has_method_flag flag = + MethodAccessFlags.has_flag access_flags flag + + (** Pushes a new scope onto the stack. Returns a function which when called reverts to the previous state. **) + method push_scope = + let old_locals = locals in + let old_offset = local_offset in + (fun () -> + let delta = local_offset - old_offset in + let fp_end = code#get_fp in + let rec loop i l = + if i = 0 then + () + else begin match l with + | (fpo,name,t) :: l -> + let fp = match !fpo with + | None -> failwith ("Uninitialized local " ^ name); + | Some fp -> fp + in + let ld = { + ld_start_pc = fp; + ld_length = fp_end - fp; + ld_name_index = jc#get_pool#add_string name; + ld_descriptor_index = jc#get_pool#add_string (generate_signature false t); + ld_index = old_offset + i - 1; + } in + debug_locals <- ld :: debug_locals; + loop (i - (signature_size t)) l + | [] -> + assert false + end + in + loop delta locals; + locals <- old_locals; + local_offset <- old_offset; + ) + + method private get_locals_for_stack_frame locals = + List.map (fun (init,_,t) -> + match !init with + | None -> JvmVerificationTypeInfo.VTop + | _ -> JvmVerificationTypeInfo.of_signature jc#get_pool t + ) locals + + (** Adds the current state of locals and stack as a stack frame. This has to be called on every branch target. **) + method add_stack_frame = + let locals = self#get_locals_for_stack_frame locals in + let astack = List.map (JvmVerificationTypeInfo.of_signature jc#get_pool) (code#get_stack#get_stack) in + let r = code#get_fp in + let ff = (r,locals,astack) in + (* If we already have a frame at the same position, overwrite it. This can happen in the case of nested branches. *) + stack_frames <- (match stack_frames with + | (r',_,_) :: stack_frames when r' = r -> ff :: stack_frames + | _ -> ff :: stack_frames) + + (** Adds [exc] as an exception. This will be added to the Code attribute. **) + method add_exception (exc : jvm_exception) = + exceptions <- exc :: exceptions + + (** Adds [path] as a thrown exception for this method. Deals with duplicates. **) + method add_thrown_exception (path : jpath) = + Hashtbl.replace thrown_exceptions (jc#get_pool#add_path path) true + + (* Convenience *) + + (** Adds [s] as a string constant to the constant pool and emits an instruction to load it. **) + method string s = + let offset = jc#get_pool#add_const_string s in + code#sconst (string_sig) offset + + (** Emits an invokevirtual instruction to invoke method [name] on [path] with signature [jsigm]. **) + method invokevirtual (path : jpath) (name : string) (jsigm : jsignature) = match jsigm with + | TMethod(tl,tr) -> + let offset = code#get_pool#add_field path name jsigm FKMethod in + code#invokevirtual offset (object_path_sig path) tl (match tr with None -> [] | Some tr -> [tr]) + | _ -> assert false + + (** Emits an invokeinterface instruction to invoke method [name] on [path] with signature [jsigm]. **) + method invokeinterface (path : jpath) (name : string) (jsigm : jsignature) = match jsigm with + | TMethod(tl,tr) -> + let offset = code#get_pool#add_field path name jsigm FKInterfaceMethod in + code#invokeinterface offset (object_path_sig path) tl (match tr with None -> [] | Some tr -> [tr]) + | _ -> assert false + + (** Emits an invokespecial instruction to invoke method [name] on [path] with signature [jsigm]. **) + method invokespecial (path : jpath) (name : string) (jsigm : jsignature) = match jsigm with + | TMethod(tl,tr) -> + let offset = code#get_pool#add_field path name jsigm FKMethod in + code#invokespecial offset (object_path_sig path) tl (match tr with None -> [] | Some tr -> [tr]) + | _ -> assert false + + (** Emits an invokestatic instruction to invoke method [name] on [path] with signature [jsigm]. **) + method invokestatic (path : jpath) (name : string) (jsigm : jsignature) = match jsigm with + | TMethod(tl,tr) -> + let offset = code#get_pool#add_field path name jsigm FKMethod in + code#invokestatic offset tl (match tr with None -> [] | Some tr -> [tr]) + | _ -> assert false + + (** Emits a getfield instruction to get the value of field [name] on object [path] with signature [jsigf]. **) + method getfield (path : jpath) (name : string) (jsigf : jsignature) = + let offset = code#get_pool#add_field path name jsigf FKField in + code#getfield offset (object_path_sig path) jsigf + + (** Emits a putfield instruction to set the value of field [name] on object [path] with signature [jsigf]. **) + method putfield (path : jpath) (name : string) (jsigf : jsignature) = + let offset = code#get_pool#add_field path name jsigf FKField in + code#putfield offset (object_path_sig path) jsigf + + (** Emits a getstatic instruction to get the value of field [name] on Class [path] with signature [jsigf]. **) + method getstatic (path : jpath) (name : string) (jsigf : jsignature) = + let offset = code#get_pool#add_field path name jsigf FKField in + code#getstatic offset jsigf + + (** Emits a putstatic instruction to set the value of field [name] on Class [path] with signature [jsigf]. **) + method putstatic (path : jpath) (name : string) (jsigf : jsignature) = + let offset = code#get_pool#add_field path name jsigf FKField in + code#putstatic offset jsigf + + (** Loads `this` **) + method load_this = + code#aload self#get_this_sig 0 + + (** Calls the parent constructor with signature [jsig_method] using the specified construction_kind [kind]. **) + method call_super_ctor (kind : construction_kind) (jsig_method : jsignature) = + assert (not (self#has_method_flag MStatic)); + match kind with + | ConstructInitPlusNew -> + self#invokespecial jc#get_super_path "new" jsig_method; + | ConstructInit -> + self#invokespecial jc#get_super_path "" jsig_method; + self#set_this_initialized + + (** Adds a field named [name] with signature [jsig_field] to the enclosing class, and adds an argument with the same name + to this method. The argument value is loaded and stored into the field immediately. **) + method add_argument_and_field (name : string) (jsig_field : jsignature) = + assert (not (self#has_method_flag MStatic)); + let jf = new builder jc name jsig_field in + jf#add_access_flag 1; + jc#add_field jf#export_field; + let _,load,_ = self#add_local name jsig_field VarArgument in + self#load_this; + load(); + self#putfield jc#get_this_path name jsig_field; + + (** Constructs a [path] object using the specified construction_kind [kind]. + + The function [f] is invokved to handle the call arguments. Its returned jsignature list is then used as the + method type of the constructor to invoke. + + If [no_value] is true, this function ensures that the stack is neutral. Otherwise, the created object is pushed + onto the stack. + **) + method construct ?(no_value=false) (kind : construction_kind) (path : jpath) (f : unit -> jsignature list) = + let pool = code#get_pool in + let offset = pool#add_path path in + code#new_ offset; + match kind with + | ConstructInitPlusNew -> + code#dup; + code#aconst_null haxe_empty_constructor_sig; + self#invokespecial path "" (method_sig [haxe_empty_constructor_sig] None); + if not no_value then self#set_top_initialized (object_path_sig path); + if not no_value then code#dup; + let jsigs = f () in + self#invokevirtual path "new" (method_sig jsigs None); + | ConstructInit -> + if not no_value then code#dup; + let jsigs = f () in + self#invokespecial path "" (method_sig jsigs None); + if not no_value then self#set_top_initialized (object_path_sig path) + + (** Loads the default value corresponding to a given signature. **) + method load_default_value = function + | TByte | TBool | TChar | TShort | TInt -> + code#iconst Int32.zero; + | TFloat -> code#fconst 0. + | TDouble -> code#dconst 0. + | TLong -> code#lconst Int64.zero + | jsig -> code#aconst_null jsig + + (** Constructs a new native array with element type [jsig]. + + Iterates over [fl] and invokes the functions to handle the array elements. + **) + method new_native_array (jsig : jsignature) (fl : (unit -> unit) list) = + code#iconst (Int32.of_int (List.length fl)); + let jasig = NativeArray.create code jc#get_pool jsig in + List.iteri (fun i f -> + code#dup; + code#iconst (Int32.of_int i); + f(); + self#cast jsig; + NativeArray.write code jasig jsig + ) fl + + (** Adds a closure to method [name] ob [path] with signature [jsig_method] to the constant pool. + + Also emits an instruction to load the closure. + **) + method read_closure is_static path name jsig_method = + let offset = code#get_pool#add_field path name jsig_method FKMethod in + let offset = code#get_pool#add (ConstMethodHandle((if is_static then 6 else 5), offset)) in + code#ldc offset jsig_method + + (** + Emits a return instruction. + **) + method return = match jsig with + | TMethod(_,tr) -> + begin match tr with + | None -> + code#return_void + | Some jsig -> + code#return_value jsig + end + | _ -> + assert false + + (* casting *) + + (** Checks if the stack top is a basic type and wraps accordingly. **) + method expect_reference_type = + let wrap_null jsig name = + let path = (["java";"lang"],name) in + self#invokestatic path "valueOf" (method_sig [jsig] (Some (object_path_sig path))) + in + match code#get_stack#top with + | TByte as t -> wrap_null t "Byte" + | TChar as t -> wrap_null t "Character" + | TDouble as t -> wrap_null t "Double" + | TFloat as t -> wrap_null t "Float" + | TInt as t -> wrap_null t "Integer" + | TLong as t -> wrap_null t "Long" + | TShort as t -> wrap_null t "Short" + | TBool as t -> wrap_null t "Boolean" + | _ -> () + + method private expect_basic_type ?(not_null=false) jsig = + if not_null then begin + let unwrap_null tname name = + let path = (["java";"lang"],tname) in + self#cast (get_boxed_type jsig); + self#invokevirtual path name (method_sig [] (Some jsig)) + in + match jsig with + | TByte -> unwrap_null "Number" "byteValue" + | TChar -> unwrap_null "Character" "charValue" + | TDouble -> unwrap_null "Number" "doubleValue" + | TFloat -> unwrap_null "Number" "floatValue" + | TInt -> unwrap_null "Number" "intValue" + | TLong -> unwrap_null "Number" "longValue" + | TShort -> unwrap_null "Number" "shortValue" + | TBool -> unwrap_null "Boolean" "booleanValue" + | _ -> () + end else begin + let unwrap_null tname name = + self#invokestatic (["haxe";"jvm"],"Jvm") name (method_sig [object_sig] (Some jsig)) + in + match jsig with + | TByte -> unwrap_null "Byte" "toByte" + | TChar -> unwrap_null "Character" "toChar" + | TDouble -> unwrap_null "Double" "toDouble" + | TFloat -> unwrap_null "Float" "toFloat" + | TInt -> unwrap_null "Integer" "toInt" + | TLong -> unwrap_null "Long" "toLong" + | TShort -> unwrap_null "Short" "toShort" + | TBool -> unwrap_null "Boolean" "toBoolean" + | _ -> () + end + + method adapt_method jsig = + () + (* let offset = code#get_pool#add_string (generate_method_signature false jsig) in + let offset = code#get_pool#add (ConstMethodType offset) in + self#get_code#dup; + self#if_then + (fun () -> self#get_code#if_null_ref jsig) + (fun () -> + code#ldc offset method_type_sig; + self#invokevirtual method_handle_path "asType" (method_sig [method_type_sig] (Some method_handle_sig)) + ); + ignore(code#get_stack#pop); + code#get_stack#push jsig; *) + + (** Casts the top of the stack to [jsig]. If [allow_to_string] is true, Jvm.toString is called. **) + method cast ?(not_null=false) ?(allow_to_string=false) jsig = + let jsig' = code#get_stack#top in + begin match jsig,jsig' with + | TObject((["java";"lang"],"Double"),_),TInt -> + code#i2d; + self#expect_reference_type; + | TObject((["java";"lang"],"Double"),_),TObject((["java";"lang"],"Integer"),_) -> + self#invokestatic (["haxe";"jvm"],"Jvm") "nullIntToNullFloat" (method_sig [integer_sig] (Some double_sig)) + | TObject((["java";"lang"],"Double"),_),TObject((["java";"lang"],"Object"),_) -> + self#invokestatic (["haxe";"jvm"],"Jvm") "dynamicToNullFloat" (method_sig [object_sig] (Some double_sig)) + (* from double *) + | TFloat,TDouble -> + code#d2f + | TInt,TDouble -> + code#d2i; + | TLong,TDouble -> + code#d2l; + (* from float *) + | TDouble,TFloat -> + code#f2d + | TInt,TFloat -> + code#f2i; + | TLong,TFloat -> + code#f2l; + (* from int *) + | TBool,TInt -> + ignore(code#get_stack#pop); + code#get_stack#push TBool; + | TByte,TInt -> + code#i2b TByte + | TChar,TInt -> + code#i2c + | TDouble,TInt -> + code#i2d; + | TFloat,TInt -> + code#i2f + | TLong,TInt -> + code#i2l; + | TShort,TInt -> + code#i2s + (* from long *) + | TDouble,TLong -> + code#l2d; + | TFloat,TLong -> + code#l2f + | TInt,TLong -> + code#l2i; + (* widening *) + | TInt,(TByte | TShort | TChar) -> + (* No cast, but rewrite stack top *) + ignore(code#get_stack#pop); + code#get_stack#push jsig; + | TObject(path1,_),TObject(path2,_) when path1 = path2 -> + () + | TObject((["java";"lang"],"String"),_),_ when allow_to_string -> + self#expect_reference_type; + self#invokestatic (["haxe";"jvm"],"Jvm") "toString" (method_sig [object_sig] (Some string_sig)) + | TObject(path1,_),TObject(path2,_) -> + if path1 = object_path then begin + (* We should never need a checkcast to Object, but we should adjust the stack so stack maps are wide enough *) + ignore(code#get_stack#pop); + code#get_stack#push object_sig + end else + code#checkcast path1; + | TObject(path,_),TTypeParameter _ -> + code#checkcast path + | TMethod _,TMethod _ -> + if jsig <> jsig' then self#adapt_method jsig; + | TMethod _,TObject((["java";"lang";"invoke"],"MethodHandle"),_) -> + self#adapt_method jsig; + | TObject((["java";"lang";"invoke"],"MethodHandle"),_),TMethod _ -> + () + | TMethod _,_ -> + code#checkcast (["java";"lang";"invoke"],"MethodHandle"); + | TArray(jsig1,_),TArray(jsig2,_) when jsig1 = jsig2 -> + () + | TArray _,_ -> + code#checkcast_sig jsig + | t1,t2 -> + match is_unboxed t1,is_unboxed t2 with + | true,false -> self#expect_basic_type ~not_null t1 + | false,true -> self#expect_reference_type + | _ -> () + end + + (* branches *) + + (** Starts a branch. Returns a restore function which reverts the stack and termination status back + to the previous state. The restore function can be called multiple times for multiple branches. + + This function has no effect on locals. Use [push_scope] for them. + **) + method start_branch = + let save = code#get_stack#save in + let old_terminated = terminated in + (fun () -> + code#get_stack#restore save; + terminated <- old_terminated; + ) + + (** Generates code which executes [f_if()] and then branches into [f_then()] and [f_else()]. **) + method if_then_else (f_if : unit -> jbranchoffset ref) (f_then : unit -> unit) (f_else : unit -> unit) = + let jump_then = f_if () in + let restore = self#start_branch in + let pop = self#push_scope in + f_then(); + pop(); + let r_then = ref code#get_fp in + let term_then = self#is_terminated in + if not term_then then code#goto r_then; + jump_then := code#get_fp - !jump_then; + restore(); + self#add_stack_frame; + let pop = self#push_scope in + f_else(); + pop(); + self#set_terminated (term_then && self#is_terminated); + r_then := code#get_fp - !r_then; + if not self#is_terminated then self#add_stack_frame + + (** Generates code which executes [f_if()] and then branches into [f_then()], if the condition holds. **) + method if_then (f_if : unit -> jbranchoffset ref) (f_then : unit -> unit) = + let jump_then = f_if () in + let restore = self#start_branch in + let pop = self#push_scope in + f_then(); + pop(); + restore(); + jump_then := code#get_fp - !jump_then; + self#add_stack_frame + + (** + Returns an instruction offset and emits a goto instruction to it if this method isn't terminated. + **) + method maybe_make_jump = + let r = ref code#get_fp in + if not self#is_terminated then code#goto r; + r + + (** + Closes the list of instruction offsets [rl], effectively making them jump to the current fp. + + Also generates a stack map frame unless [is_exhaustive] is true and all branches terminated. + **) + method close_jumps is_exhaustive rl = + let fp' = code#get_fp in + let term = List.fold_left (fun term (term',r) -> + r := fp' - !r; + term && term' + ) true rl in + let term = is_exhaustive && term in + self#set_terminated term; + if not term then self#add_stack_frame; + + + (** + Emits a tableswitch or lookupswitch instruction, depending on which one makes more sense. + + The switch subject is expected to be on the stack before calling this function. + + If [is_exhaustive] is true and [def] is None, the first case is used as the default case. + **) + method int_switch (is_exhaustive : bool) (cases : (Int32.t list * (unit -> unit)) list) (def : (unit -> unit) option) = + let def,cases = match def,cases with + | None,(_,ec) :: cases when is_exhaustive -> + Some ec,cases + | _ -> + def,cases + in + let flat_cases = DynArray.create () in + let case_lut = ref Int32Map.empty in + let fp = code#get_fp in + let imin = ref Int32.min_int in + let imax = ref Int32.max_int in + let cases = List.map (fun (il,f) -> + let rl = List.map (fun i32 -> + let r = ref fp in + if i32 < !imin then imin := i32; + if i32 > !imax then imax := i32; + DynArray.add flat_cases (i32,r); + case_lut := Int32Map.add i32 r !case_lut; + r + ) il in + (rl,f) + ) cases in + let offset_def = ref fp in + (* No idea what's a good heuristic here... *) + let diff = Int32.sub !imax !imin in + let use_tableswitch = diff < (Int32.of_int (DynArray.length flat_cases + 10)) && diff >= Int32.zero (* #8388 *) in + if use_tableswitch then begin + let offsets = Array.init (Int32.to_int (Int32.sub !imax !imin) + 1) (fun i -> + try Int32Map.find (Int32.add (Int32.of_int i) !imin) !case_lut + with Not_found -> offset_def + ) in + code#tableswitch offset_def !imin !imax offsets + end else begin + let a = DynArray.to_array flat_cases in + Array.sort (fun (i1,_) (i2,_) -> compare i1 i2) a; + code#lookupswitch offset_def a; + end; + let restore = self#start_branch in + let offset_exit = ref code#get_fp in + let def_term,r_def = match def with + | None -> + true,ref 0 + | Some f -> + offset_def := code#get_fp - !offset_def; + self#add_stack_frame; + let pop_scope = self#push_scope in + f(); + pop_scope(); + self#is_terminated,self#maybe_make_jump + in + let rec loop acc cases = match cases with + | (rl,f) :: cases -> + restore(); + self#add_stack_frame; + List.iter (fun r -> r := code#get_fp - !r) rl; + let pop_scope = self#push_scope in + f(); + pop_scope(); + let r = if cases = [] then ref 0 else self#maybe_make_jump in + loop ((self#is_terminated,r) :: acc) cases + | [] -> + List.rev acc + in + let rl = loop [] cases in + self#close_jumps (def <> None) ((def_term,if def = None then offset_def else r_def) :: rl); + if def = None then code#get_fp else !offset_exit + + (** Adds a local with a given [name], signature [jsig] and an [init_state]. + This function returns a tuple consisting of: + + * The slot of the local + * The function to load the value + * The function to store a value + + If [init_state = VarNeedDefault], the local is initialized to a default value matching [jsig]. + If [init_state = VarArgument], the local is considered initialized. + If [init_state = VarWillInit], this function assumes that the returned [store] function will be called appropriately. + **) + method add_local (name : string) (jsig : jsignature) (init_state : var_init_state) = + let slot = local_offset in + let load,store,d = match jsig with + | TInt | TBool | TByte | TShort | TChar -> + if init_state = VarNeedDefault then begin + code#iconst Int32.zero; + code#istore slot + end; + (fun () -> code#iload ~jsig slot),(fun () -> code#istore slot),1 + | TLong -> + if init_state = VarNeedDefault then begin + code#lconst Int64.zero; + code#lstore slot + end; + (fun () -> code#lload slot),(fun () -> code#lstore slot),2 + | TFloat -> + if init_state = VarNeedDefault then begin + code#fconst 0.; + code#fstore slot + end; + (fun () -> code#fload slot),(fun () -> code#fstore slot),1 + | TDouble -> + if init_state = VarNeedDefault then begin + code#dconst 0.; + code#dstore slot + end; + (fun () -> code#dload slot),(fun () -> code#dstore slot),2 + | _ -> + if init_state = VarNeedDefault then begin + code#aconst_null jsig; + code#astore jsig slot + end; + (fun () -> code#aload jsig slot),(fun () -> code#astore jsig slot),1 + in + let init = ref None in + locals <- (init,name,jsig) :: locals; + local_offset <- local_offset + d; + if local_offset > max_num_locals then max_num_locals <- local_offset; + let check_store = + let did_store = ref false in + (fun () -> + if not !did_store then begin + did_store := true; + init := Some (code#get_fp) + end + ) + in + begin match init_state with + | VarArgument | VarNeedDefault -> check_store(); + | _ -> () + end; + slot, + load, + (fun () -> + store(); + check_store(); + ) + + method get_this_sig = + let rec loop locals = match locals with + | [(_,_,jsig)] -> jsig + | _ :: locals -> loop locals + | [] -> assert false + in + loop locals + + method set_this_initialized = + let rec loop acc locals = match locals with + | [(init,name,_)] -> List.rev ((init,name,jc#get_jsig) :: acc) + | [] -> assert false + | l :: locals -> loop (l :: acc) locals + in + locals <- loop [] locals + + method set_top_initialized jsig = + ignore(code#get_stack#pop); + code#get_stack#push jsig + + (** This function has to be called once all arguments are declared. *) + method finalize_arguments = + argument_locals <- locals + + method private get_stack_map_table = + let argument_locals = self#get_locals_for_stack_frame argument_locals in + let stack_map = List.fold_left (fun ((last_offset,last_locals,last_locals_length),acc) (offset,locals,stack) -> + let cur = offset - last_offset - 1 in + let a_locals = Array.of_list (List.rev locals) in + let locals_length = Array.length a_locals in + let default () = + StackFull(cur,a_locals,Array.of_list (List.rev stack)) + in + let entry = match stack,locals_length - last_locals_length with + | [],0 -> + if last_locals = locals then begin + if cur < 64 then StackSame cur + else StackSameExtended cur + end else + default() + | [vt],0 -> + if last_locals = locals then begin + if cur < 64 then Stack1StackItem(cur,vt) + else Stack1StackItemExtended(cur,vt) + end else + default() + | [],1 -> + begin match locals with + | vt1 :: locals when locals = last_locals -> StackAppend1(cur,vt1) + | _ -> default() + end + | [],2 -> + begin match locals with + | vt1 :: vt2 :: locals when locals = last_locals -> StackAppend2(cur,vt2,vt1) + | _ -> default() + end + | [],3 -> + begin match locals with + | vt1 :: vt2 :: vt3 :: locals when locals = last_locals -> StackAppend3(cur,vt3,vt2,vt1) + | _ -> default() + end + | [],-1 -> + begin match last_locals with + | _ :: last_locals when locals = last_locals -> StackChop1 cur + | _ -> default() + end + | [],-2 -> + begin match last_locals with + | _ :: _ :: last_locals when locals = last_locals -> StackChop2 cur + | _ -> default() + end + | [],-3 -> + begin match last_locals with + | _ :: _ :: _ :: last_locals when locals = last_locals -> StackChop3 cur + | _ -> default() + end + | _ -> + default() + in + ((offset,locals,locals_length),entry :: acc) + ) ((-1,argument_locals,List.length argument_locals),[]) (List.rev stack_frames) in + Array.of_list (List.rev (snd stack_map)) + + method get_code = code + method is_terminated = terminated + method get_name = name + method get_jsig = jsig + method set_terminated b = terminated <- b + + method private get_jcode (config : export_config) = + let attributes = DynArray.create () in + let lines = code#get_lines in + if config.export_debug && DynArray.length lines > 0 then + DynArray.add attributes (AttributeLineNumberTable (DynArray.to_array lines)); + let stack_map_table = self#get_stack_map_table in + if Array.length stack_map_table > 0 then + DynArray.add attributes (AttributeStackMapTable stack_map_table); + let exceptions = Array.of_list (List.rev exceptions) in + let attributes = List.map (JvmAttribute.write_attribute jc#get_pool) (DynArray.to_list attributes) in + { + code_max_stack = code#get_max_stack_size; + code_max_locals = max_num_locals; + code_code = code#export_code; + code_exceptions = exceptions; + code_attributes = Array.of_list attributes; + } + + (** Exports the method as a [jvm_field]. No other functions should be called on this object afterwards. *) + method export_method (config : export_config) = + assert (not was_exported); + was_exported <- true; + self#commit_annotations jc#get_pool; + if code#get_fp > 0 then begin + let code = self#get_jcode config in + self#add_attribute (AttributeCode code); + end; + if Hashtbl.length thrown_exceptions > 0 then + self#add_attribute (AttributeExceptions (Array.of_list (Hashtbl.fold (fun k _ c -> k :: c) thrown_exceptions []))); + if config.export_debug then begin match debug_locals with + | [] -> + () + | _ -> + let a = Array.of_list debug_locals in + self#add_attribute (AttributeLocalVariableTable a); + end; + let attributes = self#export_attributes jc#get_pool in + let offset_name = jc#get_pool#add_string name in + let jsig = generate_method_signature false jsig in + let offset_desc = jc#get_pool#add_string jsig in + { + field_access_flags = access_flags; + field_name_index = offset_name; + field_descriptor_index = offset_desc; + field_attributes = attributes; + } + + (** Exports the method as a [jvm_field]. No other functions should be called on this object afterwards. *) + method export_field = + assert (code#get_fp = 0); + assert (not was_exported); + was_exported <- true; + let attributes = self#export_attributes jc#get_pool in + let offset_name = jc#get_pool#add_string name in + let jsig = generate_signature false jsig in + let offset_desc = jc#get_pool#add_string jsig in + { + field_access_flags = access_flags; + field_name_index = offset_name; + field_descriptor_index = offset_desc; + field_attributes = attributes; + } +end \ No newline at end of file diff --git a/src/generators/jvm/jvmSignature.ml b/src/generators/jvm/jvmSignature.ml new file mode 100644 index 00000000000..62c776e8f12 --- /dev/null +++ b/src/generators/jvm/jvmSignature.ml @@ -0,0 +1,294 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open JvmGlobals + +type jpath = (string list) * string + +type jwildcard = + | WExtends (* + *) + | WSuper (* - *) + | WNone + +type jtype_argument = + | TType of jwildcard * jsignature + | TAny (* * *) + +and jsignature = + | TByte (* B *) + | TChar (* C *) + | TDouble (* D *) + | TFloat (* F *) + | TInt (* I *) + | TLong (* J *) + | TShort (* S *) + | TBool (* Z *) + | TObject of jpath * jtype_argument list (* L Classname *) + | TObjectInner of (string list) * (string * jtype_argument list) list (* L Classname ClassTypeSignatureSuffix *) + | TArray of jsignature * int option (* [ *) + | TMethod of jmethod_signature (* ( *) + | TTypeParameter of string (* T *) + | TUninitialized of int option + +(* ( jsignature list ) ReturnDescriptor (| V | jsignature) *) +and jmethod_signature = jsignature list * jsignature option + +let s_wildcard = function + | WExtends -> "WExtends" + | WSuper -> "WSuper" + | WNone -> "WNone" + +let rec s_signature_kind = function + | TByte -> "TByte" + | TChar -> "TChar" + | TDouble -> "TDouble" + | TFloat -> "TFloat" + | TInt -> "TInt" + | TLong -> "TLong" + | TShort -> "TShort" + | TBool -> "TBool" + | TObject(path,params) -> Printf.sprintf "TObject(%s,[%s])" (Globals.s_type_path path) (String.concat "," (List.map s_signature_param_kind params)) + | TObjectInner _ -> "TObjectInner" + | TArray(jsig,io) -> Printf.sprintf "TArray(%s,%s)" (s_signature_kind jsig) (Option.map_default string_of_int "None" io) + | TMethod(jsigs,jsig) -> Printf.sprintf "TMethod([%s],%s)" (String.concat "," (List.map s_signature_kind jsigs)) (Option.map_default s_signature_kind "None" jsig) + | TTypeParameter name -> Printf.sprintf "TTypeParameter(%s)" name + | TUninitialized io -> Printf.sprintf "TUninitilaized(%s)" (Option.map_default string_of_int "None" io) + +and s_signature_param_kind = function + | TAny -> "TAny" + | TType(wc,jsig) -> Printf.sprintf "TType(%s,%s)" (s_wildcard wc) (s_signature_kind jsig) + +let encode_path (pack,name) = + String.concat "/" (pack @ [name]) + +let rec write_param full ch param = match param with + | TAny -> write_byte ch (Char.code '*') + | TType(w, s) -> + begin match w with + | WExtends -> write_byte ch (Char.code '+') + | WSuper -> write_byte ch (Char.code '-') + | WNone -> () + end; + write_signature full ch s + +and write_signature full ch jsig = match jsig with + | TByte -> write_byte ch (Char.code 'B') + | TChar -> write_byte ch (Char.code 'C') + | TDouble -> write_byte ch (Char.code 'D') + | TFloat -> write_byte ch (Char.code 'F') + | TInt -> write_byte ch (Char.code 'I') + | TLong -> write_byte ch (Char.code 'J') + | TShort -> write_byte ch (Char.code 'S') + | TBool -> write_byte ch (Char.code 'Z') + | TObject(path, params) -> + write_byte ch (Char.code 'L'); + write_string ch (encode_path path); + if params <> [] && full then begin + write_byte ch (Char.code '<'); + List.iter (write_param full ch) params; + write_byte ch (Char.code '>') + end; + write_byte ch (Char.code ';') + | TObjectInner(pack, inners) -> + write_byte ch (Char.code 'L'); + List.iter (fun p -> + write_string ch p; + write_byte ch (Char.code '/') + ) pack; + let first = ref true in + List.iter (fun (name,params) -> + (if !first then first := false else write_byte ch (Char.code '.')); + write_string ch name; + if params <> [] then begin + write_byte ch (Char.code '<'); + List.iter (write_param full ch) params; + write_byte ch (Char.code '>') + end; + ) inners; + write_byte ch (Char.code ';') + | TArray(s,size) -> + write_byte ch (Char.code '['); + begin match size with + | Some size -> + write_string ch (string_of_int size); + | None -> () + end; + write_signature full ch s + | TMethod _ -> + write_signature full ch (TObject((["java";"lang";"invoke"],"MethodHandle"),[])) + | TTypeParameter name -> + if full then begin + write_byte ch (Char.code 'T'); + write_string ch name; + write_byte ch (Char.code ';') + end else + write_string ch "Ljava/lang/Object;" + | TUninitialized _ -> + () + +let generate_signature full jsig = + let ch = IO.output_bytes () in + write_signature full ch jsig; + Bytes.unsafe_to_string (IO.close_out ch) + +let generate_method_signature full jsig = + let ch = IO.output_bytes () in + begin match jsig with + | TMethod(args, ret) -> + write_byte ch (Char.code '('); + List.iter (write_signature full ch) args; + write_byte ch (Char.code ')'); + begin match ret with + | None -> write_byte ch (Char.code 'V') + | Some jsig -> write_signature full ch jsig + end + | _ -> + write_signature full ch jsig; + end; + Bytes.unsafe_to_string (IO.close_out ch) + +let signature_size = function + | TDouble | TLong -> 2 + | _ -> 1 + +module NativeSignatures = struct + let object_path = ["java";"lang"],"Object" + let object_sig = TObject(object_path,[]) + + let string_path = ["java";"lang"],"String" + let string_sig = TObject(string_path,[]) + + let boolean_path = ["java";"lang"],"Boolean" + let boolean_sig = TObject(boolean_path,[]) + + let character_path = ["java";"lang"],"Character" + let character_sig = TObject(character_path,[]) + + let method_handle_path = (["java";"lang";"invoke"],"MethodHandle") + let method_handle_sig = TObject(method_handle_path,[]) + + let method_type_path = (["java";"lang";"invoke"],"MethodType") + let method_type_sig = TObject(method_type_path,[]) + + let method_lookup_path = (["java";"lang";"invoke"],"MethodHandles$Lookup") + let method_lookup_sig = TObject(method_lookup_path,[]) + + let call_site_path = (["java";"lang";"invoke"],"CallSite") + let call_site_sig = TObject(call_site_path,[]) + + let java_class_path = ["java";"lang"],"Class" + let java_class_sig = TObject(java_class_path,[TType(WNone,object_sig)]) + + let haxe_jvm_path = ["haxe";"jvm"],"Jvm" + + let haxe_dynamic_object_path = ["haxe";"jvm"],"DynamicObject" + let haxe_dynamic_object_sig = TObject(haxe_dynamic_object_path,[]) + + let haxe_exception_path = ["haxe";"jvm"],"Exception" + let haxe_exception_sig = TObject(haxe_exception_path,[]) + + let haxe_object_path = ["haxe";"jvm"],"Object" + let haxe_object_sig = TObject(haxe_object_path,[]) + + let throwable_path = (["java";"lang"],"Throwable") + let throwable_sig = TObject(throwable_path,[]) + + let exception_path = (["java";"lang"],"Exception") + let exception_sig = TObject(exception_path,[]) + + let retention_path = (["java";"lang";"annotation"],"Retention") + let retention_sig = TObject(retention_path,[]) + + let retention_policy_path = (["java";"lang";"annotation"],"RetentionPolicy") + let retention_policy_sig = TObject(retention_policy_path,[]) + + let java_enum_path = (["java";"lang"],"Enum") + let java_enum_sig jsig = TObject(java_enum_path,[TType(WNone,jsig)]) + + let haxe_enum_path = (["haxe";"jvm"],"Enum") + let haxe_enum_sig jsig = TObject(haxe_enum_path,[TType(WNone,jsig)]) + + let haxe_empty_constructor_path = (["haxe";"jvm"],"EmptyConstructor") + let haxe_empty_constructor_sig = TObject(haxe_empty_constructor_path,[]) + + (* numeric *) + + let byte_path = ["java";"lang"],"Byte" + let byte_sig = TObject(byte_path,[]) + + let short_path = ["java";"lang"],"Short" + let short_sig = TObject(short_path,[]) + + let integer_path = ["java";"lang"],"Integer" + let integer_sig = TObject(integer_path,[]) + + let long_path = ["java";"lang"],"Long" + let long_sig = TObject(long_path,[]) + + let float_path = ["java";"lang"],"Float" + let float_sig = TObject(float_path,[]) + + let double_path = ["java";"lang"],"Double" + let double_sig = TObject(double_path,[]) + + (* compound *) + + let array_sig jsig = TArray(jsig,None) + + let method_sig jsigs jsig = TMethod(jsigs,jsig) + + let object_path_sig path = TObject(path,[]) + + let get_boxed_type jsig = match jsig with + | TBool -> boolean_sig + | TChar -> character_sig + | TByte -> byte_sig + | TShort -> short_sig + | TInt -> integer_sig + | TLong -> long_sig + | TFloat -> float_sig + | TDouble -> double_sig + | _ -> jsig + + let get_unboxed_type jsig = match jsig with + | TObject((["java";"lang"],"Boolean"),_) -> TBool + | TObject((["java";"lang"],"Charcter"),_) -> TChar + | TObject((["java";"lang"],"Byte"),_) -> TByte + | TObject((["java";"lang"],"Short"),_) -> TShort + | TObject((["java";"lang"],"Integer"),_) -> TInt + | TObject((["java";"lang"],"Long"),_) -> TLong + | TObject((["java";"lang"],"Float"),_) -> TFloat + | TObject((["java";"lang"],"Double"),_) -> TDouble + | _ -> jsig + + let is_unboxed jsig = match jsig with + | TBool | TChar + | TByte | TShort | TInt | TLong + | TFloat | TDouble -> + true + | _ -> + false + + let is_dynamic_at_runtime = function + | TObject((["java";"lang"],"Object"),_) + | TTypeParameter _ -> + true + | _ -> + false +end \ No newline at end of file diff --git a/src/generators/jvm/jvmVerificationTypeInfo.ml b/src/generators/jvm/jvmVerificationTypeInfo.ml new file mode 100644 index 00000000000..bfd756db748 --- /dev/null +++ b/src/generators/jvm/jvmVerificationTypeInfo.ml @@ -0,0 +1,56 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open JvmGlobals +open JvmSignature + +type t = + | VTop + | VInteger + | VFloat + | VDouble + | VLong + | VNull + | VUninitializedThis + | VObject of jvm_constant_pool_index + | VUninitialized of int + +let of_signature pool jsig = match jsig with + | TByte | TChar | TBool | TShort | TInt -> VInteger + | TFloat -> VFloat + | TLong -> VLong + | TDouble -> VDouble + | TObject(path,_) -> VObject (pool#add_path path) + | TMethod _ -> VObject (pool#add_path (["java";"lang";"invoke"],"MethodHandle")) + | TArray _ -> VObject (pool#add_path ([],generate_signature false jsig)) + | TTypeParameter _ -> VObject (pool#add_path (["java";"lang"],"Object")) + | TUninitialized (Some i) -> VUninitialized i + | TUninitialized None -> VUninitializedThis + | _ -> assert false + +let to_string vtt = match vtt with + | VTop -> "top" + | VInteger -> "integer" + | VFloat -> "float" + | VLong -> "long" + | VDouble -> "double" + | VNull -> "null" + | VUninitializedThis -> "uninitializedThis" + | VObject i -> "object " ^ (string_of_int i) + | VUninitialized i -> "uninitializedVariable " ^ (string_of_int i) \ No newline at end of file diff --git a/src/generators/jvm/jvmWriter.ml b/src/generators/jvm/jvmWriter.ml new file mode 100644 index 00000000000..954d65b7d90 --- /dev/null +++ b/src/generators/jvm/jvmWriter.ml @@ -0,0 +1,341 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open JvmGlobals +open JvmData + +(* Low-level writing corresponding to jvmData. *) + +let write_jvm_attribute ch jvma = + write_ui16 ch jvma.attr_index; + write_ui32 ch (Bytes.length jvma.attr_data); + write_bytes ch jvma.attr_data + +let write_jvm_attributes ch jvmal = + write_array16 ch write_jvm_attribute jvmal + +let write_jvm_field ch jvmf = + write_ui16 ch jvmf.field_access_flags; + write_ui16 ch jvmf.field_name_index; + write_ui16 ch jvmf.field_descriptor_index; + write_jvm_attributes ch jvmf.field_attributes + +let write_jvm_class ch jvmc = + write_byte ch 0xCA; + write_byte ch 0xFE; + write_byte ch 0xBA; + write_byte ch 0xBE; + write_ui16 ch jvmc.class_minor_version; + write_ui16 ch jvmc.class_major_version; + write_bytes ch jvmc.class_constant_pool; + write_ui16 ch jvmc.class_access_flags; + write_ui16 ch jvmc.class_this_class; + write_ui16 ch jvmc.class_super_class; + write_ui16 ch (Array.length jvmc.class_interfaces); + Array.iter (write_ui16 ch) jvmc.class_interfaces; + write_ui16 ch (Array.length jvmc.class_fields); + Array.iter (write_jvm_field ch) jvmc.class_fields; + write_ui16 ch (Array.length jvmc.class_methods); + Array.iter (write_jvm_field ch) jvmc.class_methods; + write_jvm_attributes ch jvmc.class_attributes + +(* Level 2: Targeting JVM structures *) + +let write_exception ch jvme = + write_ui16 ch jvme.exc_start_pc; + write_ui16 ch jvme.exc_end_pc; + write_ui16 ch jvme.exc_handler_pc; + match jvme.exc_catch_type with + | None -> write_ui16 ch 0 + | Some t -> write_ui16 ch t + +let write_opcode ch code = + let w = write_byte ch in + let wr i32 = write_byte ch (Int32.to_int i32) in + (* TODO: probably don't need these *) + let bp i = + w ((i lsr 8) land 0xFF); + w (i land 0xFF); + in + let b4 i = + w ((i lsr 24) land 0xFF); + w ((i lsr 16) land 0xFF); + w ((i lsr 8) land 0xFF); + w (i land 0xFF); + in + let b4r i32 = + wr (Int32.logand (Int32.shift_right_logical i32 24) i320xFF); + wr (Int32.logand (Int32.shift_right_logical i32 16) i320xFF); + wr (Int32.logand (Int32.shift_right_logical i32 8) i320xFF); + wr (Int32.logand i32 i320xFF); + in + let rec loop code = match code with + (* double *) + | OpD2f -> w 0x90 + | OpD2i -> w 0x8e + | OpD2l -> w 0x8f + | OpDadd -> w 0x63 + | OpDaload -> w 0x31 + | OpDastore -> w 0x52 + | OpDcmpg -> w 0x98 + | OpDcmpl -> w 0x97 + | OpDdiv -> w 0x6f + | OpDconst_0 -> w 0xe + | OpDconst_1 -> w 0xf + | OpDload_0 -> w 0x26 + | OpDload_1 -> w 0x27 + | OpDload_2 -> w 0x28 + | OpDload_3 -> w 0x29 + | OpDload i -> w 0x18; w i + | OpDmul -> w 0x6b + | OpDneg -> w 0x77 + | OpDrem -> w 0x73 + | OpDreturn -> w 0xaf + | OpDstore_0 -> w 0x47 + | OpDstore_1 -> w 0x48 + | OpDstore_2 -> w 0x49 + | OpDstore_3 -> w 0x4a + | OpDstore i -> w 0x39; w i + | OpDsub -> w 0x67 + (* float *) + | OpF2d -> w 0x8d + | OpF2i -> w 0x8b + | OpF2l -> w 0x8c + | OpFadd -> w 0x62 + | OpFaload -> w 0x30 + | OpFastore -> w 0x51 + | OpFcmpg -> w 0x96 + | OpFcmpl -> w 0x95 + | OpFdiv -> w 0x6e + | OpFconst_0 -> w 0xb + | OpFconst_1 -> w 0xc + | OpFconst_2 -> w 0xd + | OpFload_0 -> w 0x22 + | OpFload_1 -> w 0x23 + | OpFload_2 -> w 0x24 + | OpFload_3 -> w 0x25 + | OpFload i -> w 0x17; w i + | OpFmul -> w 0x6a + | OpFneg -> w 0x76 + | OpFrem -> w 0x72 + | OpFreturn -> w 0xae + | OpFstore_0 -> w 0x43 + | OpFstore_1 -> w 0x44 + | OpFstore_2 -> w 0x45 + | OpFstore_3 -> w 0x46 + | OpFstore i -> w 0x38; w i + | OpFsub -> w 0x66 + (* int *) + | OpI2b -> w 0x91 + | OpI2c -> w 0x92 + | OpI2d -> w 0x87 + | OpI2f -> w 0x86 + | OpI2l -> w 0x85 + | OpI2s -> w 0x93 + | OpIadd -> w 0x60 + | OpIaload -> w 0x2e + | OpIand -> w 0x7e + | OpIastore -> w 0x4f + | OpIconst_m1 -> w 0x2 + | OpIconst_0 -> w 0x3 + | OpIconst_1 -> w 0x4 + | OpIconst_2 -> w 0x5 + | OpIconst_3 -> w 0x6 + | OpIconst_4 -> w 0x7 + | OpIconst_5 -> w 0x8 + | OpIdiv -> w 0x6c + | OpIload_0 -> w 0x1a + | OpIload_1 -> w 0x1b + | OpIload_2 -> w 0x1c + | OpIload_3 -> w 0x1d + | OpIload i -> w 0x15; w i + | OpImul -> w 0x68 + | OpIneg -> w 0x74 + | OpIor -> w 0x80 + | OpIrem -> w 0x70 + | OpIreturn -> w 0xac + | OpIshl -> w 0x78 + | OpIshr -> w 0x7a + | OpIstore_0 -> w 0x3b + | OpIstore_1 -> w 0x3c + | OpIstore_2 -> w 0x3d + | OpIstore_3 -> w 0x3e + | OpIstore i -> w 0x36; w i + | OpIsub -> w 0x64 + | OpIushr -> w 0x7c + | OpIxor -> w 0x82 + (* long *) + | OpL2d -> w 0x8a + | OpL2f -> w 0x89 + | OpL2i -> w 0x88 + | OpLadd -> w 0x61 + | OpLaload -> w 0x2f + | OpLand -> w 0x7f + | OpLastore -> w 0x50 + | OpLconst_0 -> w 0x9 + | OpLconst_1 -> w 0xa + | OpLcmp -> w 0x94 + | OpLdiv -> w 0x6d + | OpLload_0 -> w 0x1e + | OpLload_1 -> w 0x1f + | OpLload_2 -> w 0x20 + | OpLload_3 -> w 0x21 + | OpLload i -> w 0x16; w i + | OpLmul -> w 0x69 + | OpLneg -> w 0x75 + | OpLor -> w 0x81 + | OpLrem -> w 0x71 + | OpLreturn -> w 0xad + | OpLshl -> w 0x79 + | OpLshr -> w 0x7b + | OpLstore_0 -> w 0x3f + | OpLstore_1 -> w 0x40 + | OpLstore_2 -> w 0x41 + | OpLstore_3 -> w 0x42 + | OpLstore i -> w 0x37; w i + | OpLsub -> w 0x65 + | OpLushr -> w 0x7d + | OpLxor -> w 0x83 + (* short *) + | OpSaload -> w 0x35 + | OpSastore -> w 0x56 + | OpSipush i -> w 0x11; bp i + (* array *) + | OpAaload -> w 0x32 + | OpAastore -> w 0x53 + | OpAnewarray offset -> w 0xbd; bp offset + | OpArraylength -> w 0xbe + | OpBaload -> w 0x33 + | OpBastore -> w 0x54 + | OpBipush i -> w 0x10; w i + | OpCaload -> w 0x34 + | OpCastore -> w 0x55 + | OpMultianewarray(offset,d) -> w 0xc5; bp offset; w d + | OpNewarray t -> w 0xbc; w t + (* reference *) + | OpAload_0 -> w 0x2a + | OpAload_1 -> w 0x2b + | OpAload_2 -> w 0x2c + | OpAload_3 -> w 0x2d + | OpAload i -> w 0x19; w i + | OpAreturn -> w 0xb0 + | OpAstore_0 -> w 0x4b + | OpAstore_1 -> w 0x4c + | OpAstore_2 -> w 0x4d + | OpAstore_3 -> w 0x4e + | OpAstore i -> w 0x3a; w i + (* object *) + | OpNew offset -> w 0xbb; bp offset + | OpInstanceof offset -> w 0xc1; bp offset + | OpCheckcast offset -> w 0xc0; bp offset + | OpInvokedynamic offset -> w 0xba; bp offset; w 0; w 0 (* ??? *) + | OpInvokeinterface(offset,c) -> w 0xb9; bp offset; w c; w 0 + | OpInvokespecial offset -> w 0xb7; bp offset + | OpInvokestatic offset -> w 0xb8; bp offset + | OpInvokevirtual offset -> w 0xb6; bp offset + | OpGetfield offset -> w 0xb4; bp offset + | OpGetstatic offset -> w 0xb2; bp offset + | OpPutfield offset -> w 0xb5; bp offset + | OpPutstatic offset -> w 0xb3; bp offset + (* branching *) + | OpIf_acmpeq i -> w 0xa5; bp !i + | OpIf_acmpne i -> w 0xa6; bp !i + | OpIf_icmp(cmp,i) -> + begin match cmp with + | CmpEq -> w 0x9f + | CmpNe -> w 0xa0 + | CmpLt -> w 0xa1 + | CmpGe -> w 0xa2 + | CmpGt -> w 0xa3 + | CmpLe -> w 0xa4 + end; + bp !i + | OpIf(cmp,i) -> + begin match cmp with + | CmpEq -> w 0x99 + | CmpNe -> w 0x9a + | CmpLt -> w 0x9b + | CmpGe -> w 0x9c + | CmpGt -> w 0x9d + | CmpLe -> w 0x9e + end; + bp !i + | OpIfnonnull i -> w 0xc7; bp !i + | OpIfnull i -> w 0xc6; bp !i + | OpGoto i -> w 0xa7; bp !i + | OpGoto_w i -> w 0xc8; b4 !i + | OpJsr i -> w 0xa8; bp !i + | OpJsr_w i -> w 0xc9; b4 !i + (* stack *) + | OpAconst_null -> w 0x1 + | OpDup -> w 0x59 + | OpDup_x1 -> w 0x5a + | OpDup_x2 -> w 0x5b + | OpDup2 -> w 0x5c + | OpDup2_x1 -> w 0x5d + | OpDup2_x2 -> w 0x5e + | OpLdc i -> w 0x12; w i + | OpLdc_w i -> w 0x13; bp i + | OpLdc2_w i -> w 0x14; bp i + | OpNop -> w 0x0 + | OpPop -> w 0x57 + | OpPop2 -> w 0x58 + | OpSwap -> w 0x5f + (* other *) + | OpAthrow -> w 0xbf + | OpIinc(i,c) -> w 0x84; w i; w c (* TODO: signed? *) + | OpLookupswitch(pad,def,pairs) -> + w 0xab; + if pad > 0 then for i = 0 to pad -1 do w 0 done; + b4 !def; + b4 (Array.length pairs); + Array.iter (fun (i,offset) -> + b4r i; + b4 !offset + ) pairs; + | OpTableswitch(pad,def,low,high,offsets) -> + w 0xaa; + if pad > 0 then for i = 0 to pad -1 do w 0 done; + b4 !def; + b4r low; + b4r high; + Array.iter (fun offset -> + b4 !offset + ) offsets; + | OpMonitorenter -> w 0xc2 + | OpMonitorexit -> w 0xc3 + | OpRet i -> w 0xa9; w i + | OpReturn -> w 0xb1 + | OpWide op -> + w 0xc4; + begin match op with + | OpWIinc(i1,i2) -> w 0x84; bp i1; bp i2; + | OpWIload i -> w 0x15; bp i + | OpWFload i -> w 0x17; bp i + | OpWAload i -> w 0x19; bp i + | OpWLload i -> w 0x16; bp i + | OpWDload i -> w 0x18; bp i + | OpWIstore i -> w 0x36; bp i + | OpWFstore i -> w 0x38; bp i + | OpWAstore i -> w 0x3a; bp i + | OpWLstore i -> w 0x37; bp i + | OpWDstore i -> w 0x39; bp i + end + in + loop code \ No newline at end of file diff --git a/src/macro/eval/bytes/evalBytesLower.ml b/src/macro/eval/bytes/evalBytesLower.ml new file mode 100644 index 00000000000..4bef53089f9 --- /dev/null +++ b/src/macro/eval/bytes/evalBytesLower.ml @@ -0,0 +1,23 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open EvalBytes_E_L79 +open EvalBytes_L1020 + +let _LOWER = Array.of_list [_E;_L1;_E;_L3;_L4;_L5;_L6;_L7;_L8;_L9;_E;_E;_E;_L13;_L14;_L15;_L16;_L17;_L18;_L19;_L20;_L21;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_L66;_L67;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_L78;_L79;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_L120;_L121;_L122;_L123;_L124;_L125;_L126;_L127;_E;_E;_E;_E;_L132;_L133;_L134;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_L146;_L147;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_L176;_L177;_L178;_L179;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_L665;_L666;_E;_L668;_L669;_L670;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_L1020] \ No newline at end of file diff --git a/src/macro/eval/bytes/evalBytesUpper.ml b/src/macro/eval/bytes/evalBytesUpper.ml new file mode 100644 index 00000000000..d826e2c2743 --- /dev/null +++ b/src/macro/eval/bytes/evalBytesUpper.ml @@ -0,0 +1,24 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open EvalBytes_E_L79 +open EvalBytes_U79 +open EvalBytes_U1021 + +let _UPPER = Array.of_list [_E;_U1;_U2;_U3;_U4;_U5;_U6;_U7;_U8;_U9;_U10;_E;_E;_U13;_U14;_U15;_U16;_U17;_U18;_U19;_U20;_U21;_U22;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_U79;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_U117;_E;_E;_U120;_U121;_U122;_U123;_U124;_U125;_U126;_U127;_E;_E;_E;_E;_E;_U133;_U134;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_U147;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_U176;_U177;_U178;_U179;_U180;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_U665;_U666;_E;_U668;_U669;_U670;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_U685;_U686;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_E;_U1021] \ No newline at end of file diff --git a/src/macro/eval/bytes/evalBytes_E_L79.ml b/src/macro/eval/bytes/evalBytes_E_L79.ml new file mode 100644 index 00000000000..90ee3fc9a92 --- /dev/null +++ b/src/macro/eval/bytes/evalBytes_E_L79.ml @@ -0,0 +1,41 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +let _E = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L1 = Array.of_list [0;97;98;99;100;101;102;103;104;105;106;107;108;109;110;111;112;113;114;115;116;117;118;119;120;121;122;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L3 = Array.of_list [224;225;226;227;228;229;230;231;232;233;234;235;236;237;238;239;240;241;242;243;244;245;246;0;248;249;250;251;252;253;254;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L4 = Array.of_list [257;0;259;0;261;0;263;0;265;0;267;0;269;0;271;0;273;0;275;0;277;0;279;0;281;0;283;0;285;0;287;0;289;0;291;0;293;0;295;0;297;0;299;0;301;0;303;0;105;0;307;0;309;0;311;0;0;314;0;316;0;318;0;320] +let _L5 = Array.of_list [0;322;0;324;0;326;0;328;0;0;331;0;333;0;335;0;337;0;339;0;341;0;343;0;345;0;347;0;349;0;351;0;353;0;355;0;357;0;359;0;361;0;363;0;365;0;367;0;369;0;371;0;373;0;375;0;255;378;0;380;0;382;0;0] +let _L6 = Array.of_list [0;595;387;0;389;0;596;392;0;598;599;396;0;0;477;601;603;402;0;608;611;0;617;616;409;0;0;0;623;626;0;629;417;0;419;0;421;0;640;424;0;643;0;0;429;0;648;432;0;650;651;436;0;438;0;658;441;0;0;0;445;0;0;0] +let _L7 = Array.of_list [0;0;0;0;454;454;0;457;457;0;460;460;0;462;0;464;0;466;0;468;0;470;0;472;0;474;0;476;0;0;479;0;481;0;483;0;485;0;487;0;489;0;491;0;493;0;495;0;0;499;499;0;501;0;405;447;505;0;507;0;509;0;511;0] +let _L8 = Array.of_list [513;0;515;0;517;0;519;0;521;0;523;0;525;0;527;0;529;0;531;0;533;0;535;0;537;0;539;0;541;0;543;0;414;0;547;0;549;0;551;0;553;0;555;0;557;0;559;0;561;0;563;0;0;0;0;0;0;0;11365;572;0;410;11366;0] +let _L9 = Array.of_list [0;578;0;384;649;652;583;0;585;0;587;0;589;0;591;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L13 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;881;0;883;0;0;0;887;0;0;0;0;0;0;0;0;1011] +let _L14 = Array.of_list [0;0;0;0;0;0;940;0;941;942;943;0;972;0;973;974;0;945;946;947;948;949;950;951;952;953;954;955;956;957;958;959;960;961;0;963;964;965;966;967;968;969;970;971;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L15 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;983;0;0;0;0;0;0;0;0;985;0;987;0;989;0;991;0;993;0;995;0;997;0;999;0;1001;0;1003;0;1005;0;1007;0;0;0;0;0;952;0;0;1016;0;1010;1019;0;0;891;892;893] +let _L16 = Array.of_list [1104;1105;1106;1107;1108;1109;1110;1111;1112;1113;1114;1115;1116;1117;1118;1119;1072;1073;1074;1075;1076;1077;1078;1079;1080;1081;1082;1083;1084;1085;1086;1087;1088;1089;1090;1091;1092;1093;1094;1095;1096;1097;1098;1099;1100;1101;1102;1103;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L17 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1121;0;1123;0;1125;0;1127;0;1129;0;1131;0;1133;0;1135;0;1137;0;1139;0;1141;0;1143;0;1145;0;1147;0;1149;0;1151;0] +let _L18 = Array.of_list [1153;0;0;0;0;0;0;0;0;0;1163;0;1165;0;1167;0;1169;0;1171;0;1173;0;1175;0;1177;0;1179;0;1181;0;1183;0;1185;0;1187;0;1189;0;1191;0;1193;0;1195;0;1197;0;1199;0;1201;0;1203;0;1205;0;1207;0;1209;0;1211;0;1213;0;1215;0] +let _L19 = Array.of_list [1231;1218;0;1220;0;1222;0;1224;0;1226;0;1228;0;1230;0;0;1233;0;1235;0;1237;0;1239;0;1241;0;1243;0;1245;0;1247;0;1249;0;1251;0;1253;0;1255;0;1257;0;1259;0;1261;0;1263;0;1265;0;1267;0;1269;0;1271;0;1273;0;1275;0;1277;0;1279;0] +let _L20 = Array.of_list [1281;0;1283;0;1285;0;1287;0;1289;0;1291;0;1293;0;1295;0;1297;0;1299;0;1301;0;1303;0;1305;0;1307;0;1309;0;1311;0;1313;0;1315;0;1317;0;1319;0;1321;0;1323;0;1325;0;1327;0;0;1377;1378;1379;1380;1381;1382;1383;1384;1385;1386;1387;1388;1389;1390;1391] +let _L21 = Array.of_list [1392;1393;1394;1395;1396;1397;1398;1399;1400;1401;1402;1403;1404;1405;1406;1407;1408;1409;1410;1411;1412;1413;1414;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L66 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;11520;11521;11522;11523;11524;11525;11526;11527;11528;11529;11530;11531;11532;11533;11534;11535;11536;11537;11538;11539;11540;11541;11542;11543;11544;11545;11546;11547;11548;11549;11550;11551] +let _L67 = Array.of_list [11552;11553;11554;11555;11556;11557;0;11559;0;0;0;0;0;11565;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L78 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;43888;43889;43890;43891;43892;43893;43894;43895;43896;43897;43898;43899;43900;43901;43902;43903;43904;43905;43906;43907;43908;43909;43910;43911;43912;43913;43914;43915;43916;43917;43918;43919] +let _L79 = Array.of_list [43920;43921;43922;43923;43924;43925;43926;43927;43928;43929;43930;43931;43932;43933;43934;43935;43936;43937;43938;43939;43940;43941;43942;43943;43944;43945;43946;43947;43948;43949;43950;43951;43952;43953;43954;43955;43956;43957;43958;43959;43960;43961;43962;43963;43964;43965;43966;43967;5112;5113;5114;5115;5116;5117;0;0;0;0;0;0;0;0;0;0] \ No newline at end of file diff --git a/src/macro/eval/bytes/evalBytes_L1020.ml b/src/macro/eval/bytes/evalBytes_L1020.ml new file mode 100644 index 00000000000..3a76185154d --- /dev/null +++ b/src/macro/eval/bytes/evalBytes_L1020.ml @@ -0,0 +1,42 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +let _L120 = Array.of_list [7681;0;7683;0;7685;0;7687;0;7689;0;7691;0;7693;0;7695;0;7697;0;7699;0;7701;0;7703;0;7705;0;7707;0;7709;0;7711;0;7713;0;7715;0;7717;0;7719;0;7721;0;7723;0;7725;0;7727;0;7729;0;7731;0;7733;0;7735;0;7737;0;7739;0;7741;0;7743;0] +let _L121 = Array.of_list [7745;0;7747;0;7749;0;7751;0;7753;0;7755;0;7757;0;7759;0;7761;0;7763;0;7765;0;7767;0;7769;0;7771;0;7773;0;7775;0;7777;0;7779;0;7781;0;7783;0;7785;0;7787;0;7789;0;7791;0;7793;0;7795;0;7797;0;7799;0;7801;0;7803;0;7805;0;7807;0] +let _L122 = Array.of_list [7809;0;7811;0;7813;0;7815;0;7817;0;7819;0;7821;0;7823;0;7825;0;7827;0;7829;0;0;0;0;0;0;0;0;0;223;0;7841;0;7843;0;7845;0;7847;0;7849;0;7851;0;7853;0;7855;0;7857;0;7859;0;7861;0;7863;0;7865;0;7867;0;7869;0;7871;0] +let _L123 = Array.of_list [7873;0;7875;0;7877;0;7879;0;7881;0;7883;0;7885;0;7887;0;7889;0;7891;0;7893;0;7895;0;7897;0;7899;0;7901;0;7903;0;7905;0;7907;0;7909;0;7911;0;7913;0;7915;0;7917;0;7919;0;7921;0;7923;0;7925;0;7927;0;7929;0;7931;0;7933;0;7935;0] +let _L124 = Array.of_list [0;0;0;0;0;0;0;0;7936;7937;7938;7939;7940;7941;7942;7943;0;0;0;0;0;0;0;0;7952;7953;7954;7955;7956;7957;0;0;0;0;0;0;0;0;0;0;7968;7969;7970;7971;7972;7973;7974;7975;0;0;0;0;0;0;0;0;7984;7985;7986;7987;7988;7989;7990;7991] +let _L125 = Array.of_list [0;0;0;0;0;0;0;0;8000;8001;8002;8003;8004;8005;0;0;0;0;0;0;0;0;0;0;0;8017;0;8019;0;8021;0;8023;0;0;0;0;0;0;0;0;8032;8033;8034;8035;8036;8037;8038;8039;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L126 = Array.of_list [0;0;0;0;0;0;0;0;8064;8065;8066;8067;8068;8069;8070;8071;0;0;0;0;0;0;0;0;8080;8081;8082;8083;8084;8085;8086;8087;0;0;0;0;0;0;0;0;8096;8097;8098;8099;8100;8101;8102;8103;0;0;0;0;0;0;0;0;8112;8113;8048;8049;8115;0;0;0] +let _L127 = Array.of_list [0;0;0;0;0;0;0;0;8050;8051;8052;8053;8131;0;0;0;0;0;0;0;0;0;0;0;8144;8145;8054;8055;0;0;0;0;0;0;0;0;0;0;0;0;8160;8161;8058;8059;8165;0;0;0;0;0;0;0;0;0;0;0;8056;8057;8060;8061;8179;0;0;0] +let _L132 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;969;0;0;0;107;229;0;0;0;0;0;0;8526;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L133 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;8560;8561;8562;8563;8564;8565;8566;8567;8568;8569;8570;8571;8572;8573;8574;8575;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L134 = Array.of_list [0;0;0;8580;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L146 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;9424;9425;9426;9427;9428;9429;9430;9431;9432;9433] +let _L147 = Array.of_list [9434;9435;9436;9437;9438;9439;9440;9441;9442;9443;9444;9445;9446;9447;9448;9449;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L176 = Array.of_list [11312;11313;11314;11315;11316;11317;11318;11319;11320;11321;11322;11323;11324;11325;11326;11327;11328;11329;11330;11331;11332;11333;11334;11335;11336;11337;11338;11339;11340;11341;11342;11343;11344;11345;11346;11347;11348;11349;11350;11351;11352;11353;11354;11355;11356;11357;11358;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L177 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;11361;0;619;7549;637;0;0;11368;0;11370;0;11372;0;593;625;592;594;0;11379;0;0;11382;0;0;0;0;0;0;0;0;575;576] +let _L178 = Array.of_list [11393;0;11395;0;11397;0;11399;0;11401;0;11403;0;11405;0;11407;0;11409;0;11411;0;11413;0;11415;0;11417;0;11419;0;11421;0;11423;0;11425;0;11427;0;11429;0;11431;0;11433;0;11435;0;11437;0;11439;0;11441;0;11443;0;11445;0;11447;0;11449;0;11451;0;11453;0;11455;0] +let _L179 = Array.of_list [11457;0;11459;0;11461;0;11463;0;11465;0;11467;0;11469;0;11471;0;11473;0;11475;0;11477;0;11479;0;11481;0;11483;0;11485;0;11487;0;11489;0;11491;0;0;0;0;0;0;0;0;11500;0;11502;0;0;0;0;11507;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L665 = Array.of_list [42561;0;42563;0;42565;0;42567;0;42569;0;42571;0;42573;0;42575;0;42577;0;42579;0;42581;0;42583;0;42585;0;42587;0;42589;0;42591;0;42593;0;42595;0;42597;0;42599;0;42601;0;42603;0;42605;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L666 = Array.of_list [42625;0;42627;0;42629;0;42631;0;42633;0;42635;0;42637;0;42639;0;42641;0;42643;0;42645;0;42647;0;42649;0;42651;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _L668 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;42787;0;42789;0;42791;0;42793;0;42795;0;42797;0;42799;0;0;0;42803;0;42805;0;42807;0;42809;0;42811;0;42813;0;42815;0] +let _L669 = Array.of_list [42817;0;42819;0;42821;0;42823;0;42825;0;42827;0;42829;0;42831;0;42833;0;42835;0;42837;0;42839;0;42841;0;42843;0;42845;0;42847;0;42849;0;42851;0;42853;0;42855;0;42857;0;42859;0;42861;0;42863;0;0;0;0;0;0;0;0;0;0;42874;0;42876;0;7545;42879;0] +let _L670 = Array.of_list [42881;0;42883;0;42885;0;42887;0;0;0;0;42892;0;613;0;0;42897;0;42899;0;0;0;42903;0;42905;0;42907;0;42909;0;42911;0;42913;0;42915;0;42917;0;42919;0;42921;0;614;604;609;620;0;0;670;647;669;43859;42933;0;42935;0;0;0;0;0;0;0;0;0] +let _L1020 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;65345;65346;65347;65348;65349;65350;65351;65352;65353;65354;65355;65356;65357;65358;65359;65360;65361;65362;65363;65364;65365;65366;65367;65368;65369;65370;0;0;0;0;0] diff --git a/src/macro/eval/bytes/evalBytes_U1021.ml b/src/macro/eval/bytes/evalBytes_U1021.ml new file mode 100644 index 00000000000..f45db92b879 --- /dev/null +++ b/src/macro/eval/bytes/evalBytes_U1021.ml @@ -0,0 +1,44 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +let _U117 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;42877;0;0;0;11363;0;0] +let _U120 = Array.of_list [0;7680;0;7682;0;7684;0;7686;0;7688;0;7690;0;7692;0;7694;0;7696;0;7698;0;7700;0;7702;0;7704;0;7706;0;7708;0;7710;0;7712;0;7714;0;7716;0;7718;0;7720;0;7722;0;7724;0;7726;0;7728;0;7730;0;7732;0;7734;0;7736;0;7738;0;7740;0;7742] +let _U121 = Array.of_list [0;7744;0;7746;0;7748;0;7750;0;7752;0;7754;0;7756;0;7758;0;7760;0;7762;0;7764;0;7766;0;7768;0;7770;0;7772;0;7774;0;7776;0;7778;0;7780;0;7782;0;7784;0;7786;0;7788;0;7790;0;7792;0;7794;0;7796;0;7798;0;7800;0;7802;0;7804;0;7806] +let _U122 = Array.of_list [0;7808;0;7810;0;7812;0;7814;0;7816;0;7818;0;7820;0;7822;0;7824;0;7826;0;7828;0;0;0;0;0;7776;0;0;0;0;0;7840;0;7842;0;7844;0;7846;0;7848;0;7850;0;7852;0;7854;0;7856;0;7858;0;7860;0;7862;0;7864;0;7866;0;7868;0;7870] +let _U123 = Array.of_list [0;7872;0;7874;0;7876;0;7878;0;7880;0;7882;0;7884;0;7886;0;7888;0;7890;0;7892;0;7894;0;7896;0;7898;0;7900;0;7902;0;7904;0;7906;0;7908;0;7910;0;7912;0;7914;0;7916;0;7918;0;7920;0;7922;0;7924;0;7926;0;7928;0;7930;0;7932;0;7934] +let _U124 = Array.of_list [7944;7945;7946;7947;7948;7949;7950;7951;0;0;0;0;0;0;0;0;7960;7961;7962;7963;7964;7965;0;0;0;0;0;0;0;0;0;0;7976;7977;7978;7979;7980;7981;7982;7983;0;0;0;0;0;0;0;0;7992;7993;7994;7995;7996;7997;7998;7999;0;0;0;0;0;0;0;0] +let _U125 = Array.of_list [8008;8009;8010;8011;8012;8013;0;0;0;0;0;0;0;0;0;0;0;8025;0;8027;0;8029;0;8031;0;0;0;0;0;0;0;0;8040;8041;8042;8043;8044;8045;8046;8047;0;0;0;0;0;0;0;0;8122;8123;8136;8137;8138;8139;8154;8155;8184;8185;8170;8171;8186;8187;0;0] +let _U126 = Array.of_list [8072;8073;8074;8075;8076;8077;8078;8079;0;0;0;0;0;0;0;0;8088;8089;8090;8091;8092;8093;8094;8095;0;0;0;0;0;0;0;0;8104;8105;8106;8107;8108;8109;8110;8111;0;0;0;0;0;0;0;0;8120;8121;0;8124;0;0;0;0;0;0;0;0;0;0;921;0] +let _U127 = Array.of_list [0;0;0;8140;0;0;0;0;0;0;0;0;0;0;0;0;8152;8153;0;0;0;0;0;0;0;0;0;0;0;0;0;0;8168;8169;0;0;0;8172;0;0;0;0;0;0;0;0;0;0;0;0;0;8188;0;0;0;0;0;0;0;0;0;0;0;0] +let _U133 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;8498;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;8544;8545;8546;8547;8548;8549;8550;8551;8552;8553;8554;8555;8556;8557;8558;8559] +let _U134 = Array.of_list [0;0;0;0;8579;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _U147 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;9398;9399;9400;9401;9402;9403;9404;9405;9406;9407;9408;9409;9410;9411;9412;9413;9414;9415;9416;9417;9418;9419;9420;9421;9422;9423;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _U176 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;11264;11265;11266;11267;11268;11269;11270;11271;11272;11273;11274;11275;11276;11277;11278;11279] +let _U177 = Array.of_list [11280;11281;11282;11283;11284;11285;11286;11287;11288;11289;11290;11291;11292;11293;11294;11295;11296;11297;11298;11299;11300;11301;11302;11303;11304;11305;11306;11307;11308;11309;11310;0;0;11360;0;0;0;570;574;0;11367;0;11369;0;11371;0;0;0;0;0;0;11378;0;0;11381;0;0;0;0;0;0;0;0;0] +let _U178 = Array.of_list [0;11392;0;11394;0;11396;0;11398;0;11400;0;11402;0;11404;0;11406;0;11408;0;11410;0;11412;0;11414;0;11416;0;11418;0;11420;0;11422;0;11424;0;11426;0;11428;0;11430;0;11432;0;11434;0;11436;0;11438;0;11440;0;11442;0;11444;0;11446;0;11448;0;11450;0;11452;0;11454] +let _U179 = Array.of_list [0;11456;0;11458;0;11460;0;11462;0;11464;0;11466;0;11468;0;11470;0;11472;0;11474;0;11476;0;11478;0;11480;0;11482;0;11484;0;11486;0;11488;0;11490;0;0;0;0;0;0;0;0;11499;0;11501;0;0;0;0;11506;0;0;0;0;0;0;0;0;0;0;0;0] +let _U180 = Array.of_list [4256;4257;4258;4259;4260;4261;4262;4263;4264;4265;4266;4267;4268;4269;4270;4271;4272;4273;4274;4275;4276;4277;4278;4279;4280;4281;4282;4283;4284;4285;4286;4287;4288;4289;4290;4291;4292;4293;0;4295;0;0;0;0;0;4301;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _U665 = Array.of_list [0;42560;0;42562;0;42564;0;42566;0;42568;0;42570;0;42572;0;42574;0;42576;0;42578;0;42580;0;42582;0;42584;0;42586;0;42588;0;42590;0;42592;0;42594;0;42596;0;42598;0;42600;0;42602;0;42604;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _U666 = Array.of_list [0;42624;0;42626;0;42628;0;42630;0;42632;0;42634;0;42636;0;42638;0;42640;0;42642;0;42644;0;42646;0;42648;0;42650;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _U668 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;42786;0;42788;0;42790;0;42792;0;42794;0;42796;0;42798;0;0;0;42802;0;42804;0;42806;0;42808;0;42810;0;42812;0;42814] +let _U669 = Array.of_list [0;42816;0;42818;0;42820;0;42822;0;42824;0;42826;0;42828;0;42830;0;42832;0;42834;0;42836;0;42838;0;42840;0;42842;0;42844;0;42846;0;42848;0;42850;0;42852;0;42854;0;42856;0;42858;0;42860;0;42862;0;0;0;0;0;0;0;0;0;0;42873;0;42875;0;0;42878] +let _U670 = Array.of_list [0;42880;0;42882;0;42884;0;42886;0;0;0;0;42891;0;0;0;0;42896;0;42898;0;0;0;42902;0;42904;0;42906;0;42908;0;42910;0;42912;0;42914;0;42916;0;42918;0;42920;0;0;0;0;0;0;0;0;0;0;0;42932;0;42934;0;0;0;0;0;0;0;0] +let _U685 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;42931;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;5024;5025;5026;5027;5028;5029;5030;5031;5032;5033;5034;5035;5036;5037;5038;5039] +let _U686 = Array.of_list [5040;5041;5042;5043;5044;5045;5046;5047;5048;5049;5050;5051;5052;5053;5054;5055;5056;5057;5058;5059;5060;5061;5062;5063;5064;5065;5066;5067;5068;5069;5070;5071;5072;5073;5074;5075;5076;5077;5078;5079;5080;5081;5082;5083;5084;5085;5086;5087;5088;5089;5090;5091;5092;5093;5094;5095;5096;5097;5098;5099;5100;5101;5102;5103] +let _U1021 = Array.of_list [0;65313;65314;65315;65316;65317;65318;65319;65320;65321;65322;65323;65324;65325;65326;65327;65328;65329;65330;65331;65332;65333;65334;65335;65336;65337;65338;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] \ No newline at end of file diff --git a/src/macro/eval/bytes/evalBytes_U79.ml b/src/macro/eval/bytes/evalBytes_U79.ml new file mode 100644 index 00000000000..89f8241f273 --- /dev/null +++ b/src/macro/eval/bytes/evalBytes_U79.ml @@ -0,0 +1,40 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +let _U1 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;65;66;67;68;69;70;71;72;73;74;75;76;77;78;79;80;81;82;83;84;85;86;87;88;89;90;0;0;0;0;0] +let _U2 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;924;0;0;0;0;0;0;0;0;0;0] +let _U3 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;192;193;194;195;196;197;198;199;200;201;202;203;204;205;206;207;208;209;210;211;212;213;214;0;216;217;218;219;220;221;222;376] +let _U4 = Array.of_list [0;256;0;258;0;260;0;262;0;264;0;266;0;268;0;270;0;272;0;274;0;276;0;278;0;280;0;282;0;284;0;286;0;288;0;290;0;292;0;294;0;296;0;298;0;300;0;302;0;73;0;306;0;308;0;310;0;0;313;0;315;0;317;0] +let _U5 = Array.of_list [319;0;321;0;323;0;325;0;327;0;0;330;0;332;0;334;0;336;0;338;0;340;0;342;0;344;0;346;0;348;0;350;0;352;0;354;0;356;0;358;0;360;0;362;0;364;0;366;0;368;0;370;0;372;0;374;0;0;377;0;379;0;381;83] +let _U6 = Array.of_list [579;0;0;386;0;388;0;0;391;0;0;0;395;0;0;0;0;0;401;0;0;502;0;0;0;408;573;0;0;0;544;0;0;416;0;418;0;420;0;0;423;0;0;0;0;428;0;0;431;0;0;0;435;0;437;0;0;440;0;0;0;444;0;503] +let _U7 = Array.of_list [0;0;0;0;453;453;453;456;456;456;459;459;459;0;461;0;463;0;465;0;467;0;469;0;471;0;473;0;475;398;0;478;0;480;0;482;0;484;0;486;0;488;0;490;0;492;0;494;0;498;498;498;0;500;0;0;0;504;0;506;0;508;0;510] +let _U8 = Array.of_list [0;512;0;514;0;516;0;518;0;520;0;522;0;524;0;526;0;528;0;530;0;532;0;534;0;536;0;538;0;540;0;542;0;0;0;546;0;548;0;550;0;552;0;554;0;556;0;558;0;560;0;562;0;0;0;0;0;0;0;0;571;0;0;11390] +let _U9 = Array.of_list [11391;0;577;0;0;0;0;582;0;584;0;586;0;588;0;590;11375;11373;11376;385;390;0;393;394;0;399;0;400;42923;0;0;0;403;42924;0;404;0;42893;42922;0;407;406;0;11362;42925;0;0;412;0;11374;413;0;0;415;0;0;0;0;0;0;0;11364;0;0] +let _U10 = Array.of_list [422;0;0;425;0;0;0;42929;430;580;433;434;581;0;0;0;0;0;439;0;0;0;0;0;0;0;0;0;0;42930;42928;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _U13 = Array.of_list [0;0;0;0;0;921;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;880;0;882;0;0;0;886;0;0;0;1021;1022;1023;0;0] +let _U14 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;902;904;905;906;0;913;914;915;916;917;918;919;920;921;922;923;924;925;926;927] +let _U15 = Array.of_list [928;929;931;931;932;933;934;935;936;937;938;939;908;910;911;0;914;920;0;0;0;934;928;975;0;984;0;986;0;988;0;990;0;992;0;994;0;996;0;998;0;1000;0;1002;0;1004;0;1006;922;929;1017;895;0;917;0;0;1015;0;0;1018;0;0;0;0] +let _U16 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1040;1041;1042;1043;1044;1045;1046;1047;1048;1049;1050;1051;1052;1053;1054;1055] +let _U17 = Array.of_list [1056;1057;1058;1059;1060;1061;1062;1063;1064;1065;1066;1067;1068;1069;1070;1071;1024;1025;1026;1027;1028;1029;1030;1031;1032;1033;1034;1035;1036;1037;1038;1039;0;1120;0;1122;0;1124;0;1126;0;1128;0;1130;0;1132;0;1134;0;1136;0;1138;0;1140;0;1142;0;1144;0;1146;0;1148;0;1150] +let _U18 = Array.of_list [0;1152;0;0;0;0;0;0;0;0;0;1162;0;1164;0;1166;0;1168;0;1170;0;1172;0;1174;0;1176;0;1178;0;1180;0;1182;0;1184;0;1186;0;1188;0;1190;0;1192;0;1194;0;1196;0;1198;0;1200;0;1202;0;1204;0;1206;0;1208;0;1210;0;1212;0;1214] +let _U19 = Array.of_list [0;0;1217;0;1219;0;1221;0;1223;0;1225;0;1227;0;1229;1216;0;1232;0;1234;0;1236;0;1238;0;1240;0;1242;0;1244;0;1246;0;1248;0;1250;0;1252;0;1254;0;1256;0;1258;0;1260;0;1262;0;1264;0;1266;0;1268;0;1270;0;1272;0;1274;0;1276;0;1278] +let _U20 = Array.of_list [0;1280;0;1282;0;1284;0;1286;0;1288;0;1290;0;1292;0;1294;0;1296;0;1298;0;1300;0;1302;0;1304;0;1306;0;1308;0;1310;0;1312;0;1314;0;1316;0;1318;0;1320;0;1322;0;1324;0;1326;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _U21 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1329;1330;1331;1332;1333;1334;1335;1336;1337;1338;1339;1340;1341;1342;1343;1344;1345;1346;1347;1348;1349;1350;1351;1352;1353;1354;1355;1356;1357;1358;1359] +let _U22 = Array.of_list [1360;1361;1362;1363;1364;1365;1366;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0] +let _U79 = Array.of_list [0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;5104;5105;5106;5107;5108;5109;0;0] diff --git a/src/macro/eval/evalArray.ml b/src/macro/eval/evalArray.ml index 217d5d69b5f..6e216628689 100644 --- a/src/macro/eval/evalArray.ml +++ b/src/macro/eval/evalArray.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -26,20 +26,19 @@ let create values = { } let array_join a f sep = - let buf = Rope.Buffer.create 0 in - let last = Array.length a - 1 in - Array.iteri (fun i v -> - Rope.Buffer.add_rope buf (f v); - if i <> last then Rope.Buffer.add_rope buf sep; - ) a; - Rope.Buffer.contents buf + let l = Array.map f a in + let l = Array.to_list l in + EvalString.join sep l let to_list a = Array.to_list (Array.sub a.avalues 0 a.alength) +let make len = + try Array.make len vnull with _ -> EvalContext.error_message "Array allocation is too large" + let set_length a l = a.alength <- l; if a.alength > Array.length a.avalues then begin - let values' = Array.make (a.alength * 2) vnull in + let values' = make (a.alength * 2) in Array.blit a.avalues 0 values' 0 (Array.length a.avalues); a.avalues <- values' end @@ -48,7 +47,7 @@ let unsafe_get a i = a.avalues.(i) let unsafe_set a i v = a.avalues.(i) <- v let concat a a2 = - let values' = Array.make (a.alength + a2.alength) vnull in + let values' = make (a.alength + a2.alength) in Array.blit a.avalues 0 values' 0 a.alength; let values2 = (Obj.magic a2.avalues) in Array.blit values2 0 values' a.alength a2.alength; @@ -71,7 +70,7 @@ let rec indexOf a equals x fromIndex = let insert a pos x = if a.alength + 1 >= Array.length a.avalues then begin - let values' = Array.make (Array.length a.avalues * 2 + 5) vnull in + let values' = make (Array.length a.avalues * 2 + 5) in Array.blit a.avalues 0 values' 0 a.alength; a.avalues <- values' end; @@ -115,13 +114,14 @@ let pop a = vnull else begin let v = get a (a.alength - 1) in + unsafe_set a (a.alength - 1) vnull; a.alength <- a.alength - 1; v end let push a v = if a.alength + 1 >= Array.length a.avalues then begin - let values' = Array.make (Array.length a.avalues * 2 + 5) vnull in + let values' = make (Array.length a.avalues * 2 + 5) in Array.blit a.avalues 0 values' 0 a.alength; Array.set values' a.alength v; a.avalues <- values' @@ -147,7 +147,7 @@ let reverse a = let set a i v = if i >= a.alength then begin if i >= Array.length a.avalues then begin - let values' = Array.make (i + 5) vnull in + let values' = make (max (i + 5) (Array.length a.avalues * 2 + 5)) in Array.blit a.avalues 0 values' 0 a.alength; a.avalues <- values'; end; @@ -183,11 +183,20 @@ let splice a pos len end' = let unshift a v = if a.alength + 1 >= Array.length a.avalues then begin - let values' = Array.make (Array.length a.avalues * 2 + 5) vnull in + let values' = make (Array.length a.avalues * 2 + 5) in Array.blit a.avalues 0 values' 1 a.alength; a.avalues <- values' end else begin Array.blit a.avalues 0 a.avalues 1 a.alength; end; Array.set a.avalues 0 v; - a.alength <- a.alength + 1 \ No newline at end of file + a.alength <- a.alength + 1 + +let resize a l = + if a.alength < l then begin + set a (l - 1) vnull; + () + end else if a.alength > l then begin + ignore(splice a l (a.alength - l) a.alength); + () + end else () diff --git a/src/macro/eval/evalBytes.ml b/src/macro/eval/evalBytes.ml new file mode 100644 index 00000000000..ed1d5b84eca --- /dev/null +++ b/src/macro/eval/evalBytes.ml @@ -0,0 +1,160 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +let read_byte this i = int_of_char (Bytes.get this i) + +let read_ui16 this i = + let ch1 = read_byte this i in + let ch2 = read_byte this (i + 1) in + ch1 lor (ch2 lsl 8) + +let read_i32 this i = + let ch1 = read_byte this i in + let ch2 = read_byte this (i + 1) in + let ch3 = read_byte this (i + 2) in + let base = Int32.of_int (ch1 lor (ch2 lsl 8) lor (ch3 lsl 16)) in + let big = Int32.shift_left (Int32.of_int (read_byte this (i + 3))) 24 in + Int32.logor base big + +let read_i64 this i = + let ch1 = read_byte this i in + let ch2 = read_byte this (i + 1) in + let ch3 = read_byte this (i + 2) in + let ch4 = read_byte this (i + 3) in + let base = Int64.of_int (ch1 lor (ch2 lsl 8) lor (ch3 lsl 16)) in + let small = Int64.logor base (Int64.shift_left (Int64.of_int ch4) 24) in + let big = Int64.of_int32 (read_i32 this (i + 4)) in + Int64.logor (Int64.shift_left big 32) small + +let write_byte this i v = + Bytes.set this i (Char.unsafe_chr v) + +let write_ui16 this i v = + write_byte this i v; + write_byte this (i + 1) (v lsr 8) + +let write_i32 this i v = + let base = Int32.to_int v in + let big = Int32.to_int (Int32.shift_right_logical v 24) in + write_byte this i base; + write_byte this (i + 1) (base lsr 8); + write_byte this (i + 2) (base lsr 16); + write_byte this (i + 3) big + +let write_i64 this i v = + write_i32 this i (Int64.to_int32 v); + write_i32 this (i + 4) (Int64.to_int32 (Int64.shift_right_logical v 32)) + + +module Unicase = struct + let _E = EvalBytes_E_L79._E + let _L1 = EvalBytes_E_L79._L1 + let _L3 = EvalBytes_E_L79._L3 + let _L4 = EvalBytes_E_L79._L4 + let _L5 = EvalBytes_E_L79._L5 + let _L6 = EvalBytes_E_L79._L6 + let _L7 = EvalBytes_E_L79._L7 + let _L8 = EvalBytes_E_L79._L8 + let _L9 = EvalBytes_E_L79._L9 + let _L13 = EvalBytes_E_L79._L13 + let _L14 = EvalBytes_E_L79._L14 + let _L15 = EvalBytes_E_L79._L15 + let _L16 = EvalBytes_E_L79._L16 + let _L17 = EvalBytes_E_L79._L17 + let _L18 = EvalBytes_E_L79._L18 + let _L19 = EvalBytes_E_L79._L19 + let _L20 = EvalBytes_E_L79._L20 + let _L21 = EvalBytes_E_L79._L21 + let _L66 = EvalBytes_E_L79._L66 + let _L67 = EvalBytes_E_L79._L67 + let _L78 = EvalBytes_E_L79._L78 + let _L79 = EvalBytes_E_L79._L79 + let _L120 = EvalBytes_L1020._L120 + let _L121 = EvalBytes_L1020._L121 + let _L122 = EvalBytes_L1020._L122 + let _L123 = EvalBytes_L1020._L123 + let _L124 = EvalBytes_L1020._L124 + let _L125 = EvalBytes_L1020._L125 + let _L126 = EvalBytes_L1020._L126 + let _L127 = EvalBytes_L1020._L127 + let _L132 = EvalBytes_L1020._L132 + let _L133 = EvalBytes_L1020._L133 + let _L134 = EvalBytes_L1020._L134 + let _L146 = EvalBytes_L1020._L146 + let _L147 = EvalBytes_L1020._L147 + let _L176 = EvalBytes_L1020._L176 + let _L177 = EvalBytes_L1020._L177 + let _L178 = EvalBytes_L1020._L178 + let _L179 = EvalBytes_L1020._L179 + let _L665 = EvalBytes_L1020._L665 + let _L666 = EvalBytes_L1020._L666 + let _L668 = EvalBytes_L1020._L668 + let _L669 = EvalBytes_L1020._L669 + let _L670 = EvalBytes_L1020._L670 + let _L1020 = EvalBytes_L1020._L1020 + let _U1 = EvalBytes_U79._U1 + let _U2 = EvalBytes_U79._U2 + let _U3 = EvalBytes_U79._U3 + let _U4 = EvalBytes_U79._U4 + let _U5 = EvalBytes_U79._U5 + let _U6 = EvalBytes_U79._U6 + let _U7 = EvalBytes_U79._U7 + let _U8 = EvalBytes_U79._U8 + let _U9 = EvalBytes_U79._U9 + let _U10 = EvalBytes_U79._U10 + let _U13 = EvalBytes_U79._U13 + let _U14 = EvalBytes_U79._U14 + let _U15 = EvalBytes_U79._U15 + let _U16 = EvalBytes_U79._U16 + let _U17 = EvalBytes_U79._U17 + let _U18 = EvalBytes_U79._U18 + let _U19 = EvalBytes_U79._U19 + let _U20 = EvalBytes_U79._U20 + let _U21 = EvalBytes_U79._U21 + let _U22 = EvalBytes_U79._U22 + let _U79 = EvalBytes_U79._U79 + let _U117 = EvalBytes_U1021._U117 + let _U120 = EvalBytes_U1021._U120 + let _U121 = EvalBytes_U1021._U121 + let _U122 = EvalBytes_U1021._U122 + let _U123 = EvalBytes_U1021._U123 + let _U124 = EvalBytes_U1021._U124 + let _U125 = EvalBytes_U1021._U125 + let _U126 = EvalBytes_U1021._U126 + let _U127 = EvalBytes_U1021._U127 + let _U133 = EvalBytes_U1021._U133 + let _U134 = EvalBytes_U1021._U134 + let _U147 = EvalBytes_U1021._U147 + let _U176 = EvalBytes_U1021._U176 + let _U177 = EvalBytes_U1021._U177 + let _U178 = EvalBytes_U1021._U178 + let _U179 = EvalBytes_U1021._U179 + let _U180 = EvalBytes_U1021._U180 + let _U665 = EvalBytes_U1021._U665 + let _U666 = EvalBytes_U1021._U666 + let _U668 = EvalBytes_U1021._U668 + let _U669 = EvalBytes_U1021._U669 + let _U670 = EvalBytes_U1021._U670 + let _U685 = EvalBytes_U1021._U685 + let _U686 = EvalBytes_U1021._U686 + let _U1021 = EvalBytes_U1021._U1021 + + let _LOWER = EvalBytesLower._LOWER + let _UPPER = EvalBytesUpper._UPPER +end \ No newline at end of file diff --git a/src/macro/eval/evalContext.ml b/src/macro/eval/evalContext.ml index c900d7f8b9b..8dfced55d00 100644 --- a/src/macro/eval/evalContext.ml +++ b/src/macro/eval/evalContext.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,74 +21,131 @@ open Globals open Type open EvalValue open EvalHash +open EvalString -type var_info = string +type var_info = { + vi_name : string; + vi_pos : pos; + vi_generated : bool; +} type scope = { + (* The position of the current scope. *) pos : pos; (* The local start offset of the current scope. *) local_offset : int; (* The locals declared in the current scope. Maps variable IDs to local slots. *) - mutable locals : (int,int) Hashtbl.t; + locals : (int,int) Hashtbl.t; (* The name of local variables. Maps local slots to variable names. Only filled in debug mode. *) - mutable local_infos : (int,var_info) Hashtbl.t; + local_infos : (int,var_info) Hashtbl.t; (* The IDs of local variables. Maps variable names to variable IDs. *) - mutable local_ids : (string,int) Hashtbl.t; + local_ids : (string,int) Hashtbl.t; } type env_kind = | EKLocalFunction of int | EKMethod of int * int - | EKDelayed + | EKEntrypoint +(* Compile-time information for environments. This information is static for all + environments of the same kind, e.g. all environments of a specific method. *) type env_info = { + (* If false, the environment has a this-context. *) static : bool; + (* Hash of the source file of this environment. *) pfile : int; + (* Hash of the unique source file of this environment. *) + pfile_unique : int; + (* The environment kind. *) kind : env_kind; + (* The name of capture variables. Maps local slots to variable names. Only filled in debug mode. *) capture_infos : (int,var_info) Hashtbl.t; } +(* Per-environment debug information. These values are only modified while debugging. *) type env_debug = { + (* The timer function to execute when the environment finishes executing *) timer : unit -> unit; + (* The current scope stack. *) mutable scopes : scope list; + (* The current line being executed. This in conjunction with `env_info.pfile` is used to find breakpoints. *) mutable line : int; + (* The current expression being executed *) mutable expr : texpr; } +(* An environment in which code is executed. Environments are created whenever a function is called and when + evaluating static inits. *) type env = { + (* The compile-time information for the current environment *) env_info : env_info; + (* The debug information for the current environment *) env_debug : env_debug; + (* The position at which the current environment was left, e.g. by a call. *) mutable env_leave_pmin : int; + (* The position at which the current environment was left, e.g. by a call. *) mutable env_leave_pmax : int; - mutable env_in_use : bool; + (* The environment's local variables. Indices are determined during compile-time, or can be obtained + through `scope.locals` when debugging. *) env_locals : value array; - env_captures : value ref array; + (* The reference to the environment's captured local variables. Indices are determined during compile-time, + or can be obtained through `env_info.capture_infos`. *) + env_captures : value array; + (* Map of extra variables added while debugging. Keys are hashed variable names. *) + mutable env_extra_locals : value IntMap.t; + (* The parent of the current environment, if exists. *) + env_parent : env option; + (** Exeucution stack depth *) + env_stack_depth : int; + env_eval : eval; } -type breakpoint_state = +and eval = { + mutable env : env option; + thread : vthread; + (* The threads current debug state *) + mutable debug_state : debug_state; + (* The currently active breakpoint. Set to a dummy value initially. *) + mutable breakpoint : breakpoint; + (* Map of all types that are currently being caught. Updated by `emit_try`. *) + caught_types : (int,bool) Hashtbl.t; + (* The most recently caught exception. Used by `debug_loop` to avoid getting stuck. *) + mutable caught_exception : value; + (* The value which was last returned. *) + mutable last_return : value option; + (* The debug channel used to synchronize with the debugger. *) + debug_channel : unit Event.channel; +} + +and debug_state = + | DbgRunning + | DbgWaiting + | DbgStep + | DbgNext of env * pos + | DbgFinish of env (* parent env *) + +and breakpoint_state = | BPEnabled | BPDisabled | BPHit -type breakpoint_column = +and breakpoint_column = | BPAny | BPColumn of int -type breakpoint = { +and breakpoint = { bpid : int; bpfile : int; bpline : int; bpcolumn : breakpoint_column; + bpcondition : Ast.expr option; mutable bpstate : breakpoint_state; } -type debug_state = - | DbgStart - | DbgRunning - | DbgWaiting - | DbgContinue - | DbgNext of int - | DbgFinish of int +type function_breakpoint = { + fbpid : int; + mutable fbpstate : breakpoint_state; +} type builtins = { mutable instance_builtins : (int * value) list IntMap.t; @@ -97,110 +154,184 @@ type builtins = { empty_constructor_builtins : (int,unit -> value) Hashtbl.t; } -type debug_socket = { - addr : Unix.inet_addr; - port : int; - mutable socket : Unix.file_descr option; +type debug_scope_info = { + ds_expr : texpr; + ds_return : value option; } -type debug = { - debug : bool; +type context_reference = + | StackFrame of env + | Scope of scope * env + | CaptureScope of (int,var_info) Hashtbl.t * env + | DebugScope of debug_scope_info * env + | Value of value * env + | Toplevel + | NoSuchReference + +class eval_debug_context = object(self) + val lut = + let d = DynArray.create() in + DynArray.add d Toplevel; + d + + val mutex = Mutex.create() + + method private add reference = + Mutex.lock mutex; + DynArray.add lut reference; + let i = DynArray.length lut - 1 in + Mutex.unlock mutex; + i + + method add_stack_frame env = + self#add (StackFrame env) + + method add_scope scope env = + self#add (Scope(scope,env)) + + method add_capture_scope h env = + self#add (CaptureScope(h,env)) + + method add_value v env = + self#add (Value(v,env)) + + method add_debug_scope scope env = + self#add (DebugScope(scope,env)) + + method get id = + try DynArray.get lut id with _ -> NoSuchReference + +end + +class static_prototypes = object(self) + val mutable prototypes : vprototype IntMap.t = IntMap.empty + val mutable inits : (bool ref * vprototype * (vprototype -> unit) list) IntMap.t = IntMap.empty + + method add proto = + prototypes <- IntMap.add proto.ppath proto prototypes + + method remove path = + inits <- IntMap.remove path inits; + prototypes <- IntMap.remove path prototypes + + method set_needs_reset = + IntMap.iter (fun path (needs_reset, _, _) -> needs_reset := true) inits + + method add_init proto delays = + inits <- IntMap.add proto.ppath (ref false, proto, delays) inits + + method get path = + (try + let (needs_reset, proto, delays) = IntMap.find path inits in + if !needs_reset then begin + needs_reset := false; + List.iter (fun f -> f proto) delays + end + with Not_found -> ()); + IntMap.find path prototypes +end + +type exception_mode = + | CatchAll + | CatchUncaught + | CatchNone + +type debug_connection = { + bp_stop : debug -> unit; + exc_stop : debug -> value -> pos -> unit; + send_thread_event : int -> string -> unit; +} + +and debug_socket = { + socket : Socket.t; + connection : debug_connection; +} + +(* Per-context debug information *) +and debug = { + (* The registered breakpoints *) breakpoints : (int,(int,breakpoint) Hashtbl.t) Hashtbl.t; + (* The registered function breakpoints *) + function_breakpoints : ((int * int),function_breakpoint) Hashtbl.t; + (* Whether or not debugging is supported. Has various effects on the amount of + data being retained at run-time. *) mutable support_debugger : bool; - mutable debug_state : debug_state; - mutable breakpoint : breakpoint; - caught_types : (int,bool) Hashtbl.t; - mutable environment_offset_delta : int; + (* The debugger socket *) mutable debug_socket : debug_socket option; + (* The current exception mode *) + mutable exception_mode : exception_mode; + (* The debug context which manages scopes and variables. *) + mutable debug_context : eval_debug_context; } -type eval = { - environments : env DynArray.t; - mutable environment_offset : int; -} - -type context = { +and context = { ctx_id : int; is_macro : bool; - record_stack : bool; detail_times : bool; builtins : builtins; debug : debug; mutable had_error : bool; mutable curapi : value MacroApi.compiler_api; mutable type_cache : Type.module_type IntMap.t; - overrides : (Type.path * string,bool) Hashtbl.t; + overrides : (Globals.path * string,bool) Hashtbl.t; (* prototypes *) mutable array_prototype : vprototype; mutable string_prototype : vprototype; mutable vector_prototype : vprototype; mutable instance_prototypes : vprototype IntMap.t; - mutable static_prototypes : vprototype IntMap.t; + mutable static_prototypes : static_prototypes; mutable constructors : value Lazy.t IntMap.t; get_object_prototype : 'a . context -> (int * 'a) list -> vprototype * (int * 'a) list; (* eval *) + toplevel : value; eval : eval; + mutable evals : eval IntMap.t; mutable exception_stack : (pos * env_kind) list; + max_stack_depth : int; } let get_ctx_ref : (unit -> context) ref = ref (fun() -> assert false) let get_ctx () = (!get_ctx_ref)() let select ctx = get_ctx_ref := (fun() -> ctx) +let s_debug_state = function + | DbgRunning -> "DbgRunning" + | DbgWaiting -> "DbgWaiting" + | DbgStep -> "DbgStep" + | DbgNext _ -> "DbgNext" + | DbgFinish _ -> "DbgFinish" + (* Misc *) let get_eval ctx = - ctx.eval - -let rec kind_name ctx kind = - let rec loop kind env_id = match kind, env_id with - | EKLocalFunction i, 0 -> - Printf.sprintf "localFunction%i" i - | EKLocalFunction i, env_id -> - let parent_id = env_id - 1 in - let env = DynArray.get ctx.environments parent_id in - Printf.sprintf "%s.localFunction%i" (loop env.env_info.kind parent_id) i - | EKMethod(i1,i2),_ -> Printf.sprintf "%s.%s" (rev_hash_s i1) (rev_hash_s i2) - | EKDelayed,_ -> "delayed" + let id = Thread.id (Thread.self()) in + if id = 0 then ctx.eval else IntMap.find id ctx.evals + +let rec kind_name eval kind = + let rec loop kind env = match kind with + | EKMethod(i1,i2) -> + Printf.sprintf "%s.%s" (rev_hash i1) (rev_hash i2) + | EKLocalFunction i -> + begin match env with + | None -> Printf.sprintf "localFunction%i" i + | Some env -> Printf.sprintf "%s.localFunction%i" (loop env.env_info.kind env.env_parent) i + end + | EKEntrypoint -> + begin match env with + | None -> "entrypoint" + | Some env -> rev_hash env.env_info.pfile + end in - loop kind ctx.environment_offset - -let vstring s = - VString (s,lazy (Rope.to_string s)) - -let vstring_direct (r,s) = - VString(r,s) - -let call_function f vl = match f,vl with - | Fun0 f,_ -> f() - | Fun1 f,[] -> f vnull - | Fun1 f,(a :: _) -> f a - | Fun2 f,[] -> f vnull vnull - | Fun2 f,[a] -> f a vnull - | Fun2 f,(a :: b :: _) -> f a b - | Fun3 f,[] -> f vnull vnull vnull - | Fun3 f,[a] -> f a vnull vnull - | Fun3 f,[a;b] -> f a b vnull - | Fun3 f,(a :: b :: c :: _) -> f a b c - | Fun4 f,[] -> f vnull vnull vnull vnull - | Fun4 f,[a] -> f a vnull vnull vnull - | Fun4 f,[a;b] -> f a b vnull vnull - | Fun4 f,[a;b;c] -> f a b c vnull - | Fun4 f,(a :: b :: c :: d :: _) -> f a b c d - | Fun5 f,[] -> f vnull vnull vnull vnull vnull - | Fun5 f,[a] -> f a vnull vnull vnull vnull - | Fun5 f,[a;b] -> f a b vnull vnull vnull - | Fun5 f,[a;b;c] -> f a b c vnull vnull - | Fun5 f,[a;b;c;d] -> f a b c d vnull - | Fun5 f,(a :: b :: c :: d :: e :: _) -> f a b c d e - | FunN f,_ -> f vl + match eval.env with + | None -> "toplevel" + | Some env -> loop kind (Some env) + +let call_function f vl = f vl let object_fields o = - let fields = IntMap.fold (fun key vvalue acc -> (key,vvalue) :: acc) o.oextra [] in IntMap.fold (fun key index acc -> - if IntMap.mem key o.oremoved then acc - else (key,(o.ofields.(index))) :: acc - ) o.oproto.pinstance_names fields + (key,(o.ofields.(index))) :: acc + ) o.oproto.pinstance_names [] let instance_fields i = IntMap.fold (fun name key acc -> @@ -216,25 +347,33 @@ let proto_fields proto = exception RunTimeException of value * env list * pos -let call_stack ctx = - if not ctx.record_stack then - [] - else - List.rev (DynArray.to_list (DynArray.sub ctx.eval.environments 0 ctx.eval.environment_offset)) +let call_stack eval = + let rec loop acc env = + let acc = env :: acc in + match env.env_parent with + | Some env -> loop acc env + | _ -> List.rev acc + in + match eval.env with + | None -> [] + | Some env -> loop [] env let throw v p = let ctx = get_ctx() in let eval = get_eval ctx in - if ctx.record_stack && eval.environment_offset > 0 then begin - let env = DynArray.get eval.environments (eval.environment_offset - 1) in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - end; - raise (RunTimeException(v,call_stack ctx,p)) + match eval.env with + | Some env -> + if p <> null_pos then begin + env.env_leave_pmin <- p.pmin; + env.env_leave_pmax <- p.pmax; + end; + raise_notrace (RunTimeException(v,call_stack eval,p)) + | None -> + raise_notrace (RunTimeException(v,[],p)) let exc v = throw v null_pos -let exc_string str = exc (vstring (Rope.of_string str)) +let exc_string str = exc (vstring (EvalString.create_ascii str)) let error_message = exc_string @@ -252,89 +391,87 @@ let no_debug = { timer = no_timer; scopes = []; line = 0; - expr = no_expr + expr = no_expr; } let create_env_info static pfile kind capture_infos = let info = { static = static; kind = kind; - pfile = pfile; + pfile = hash pfile; + pfile_unique = hash (Path.unique_full_path pfile); capture_infos = capture_infos; } in info -let push_environment_debug ctx info num_locals num_captures = +let push_environment ctx info num_locals num_captures = let eval = get_eval ctx in let timer = if ctx.detail_times then - Common.timer ["macro";"execution";kind_name eval info.kind] + Timer.timer ["macro";"execution";kind_name eval info.kind] else no_timer in + let debug = if ctx.debug.support_debugger || ctx.detail_times then + { no_debug with timer = timer } + else + no_debug + in + let locals = if num_locals = 0 then + empty_array + else + Array.make num_locals vnull + in + let captures = if num_captures = 0 then + empty_array + else + Array.make num_captures vnull + in + let stack_depth = match eval.env with + | None -> 1; + | Some env -> env.env_stack_depth + 1 + in let env = { env_info = info; env_leave_pmin = 0; env_leave_pmax = 0; - env_in_use = false; - env_debug = { - timer = timer; - scopes = []; - line = 0; - expr = no_expr; - }; - env_locals = Array.make num_locals vnull; - env_captures = Array.make num_captures (ref vnull); + env_debug = debug; + env_locals = locals; + env_captures = captures; + env_extra_locals = IntMap.empty; + env_parent = eval.env; + env_eval = eval; + env_stack_depth = stack_depth; } in - if eval.environment_offset = DynArray.length eval.environments then - DynArray.add eval.environments env - else - DynArray.unsafe_set eval.environments eval.environment_offset env; - eval.environment_offset <- eval.environment_offset + 1; + eval.env <- Some env; + begin match ctx.debug.debug_socket,env.env_info.kind with + | Some socket,EKMethod(key_type,key_field) -> + begin try + let bp = Hashtbl.find ctx.debug.function_breakpoints (key_type,key_field) in + if bp.fbpstate <> BPEnabled then raise Not_found; + socket.connection.bp_stop ctx.debug; + eval.debug_state <- DbgWaiting; + with Not_found -> + () + end + | _ -> + () + end; env -let create_default_environment ctx info num_locals = - { - env_info = info; - env_leave_pmin = 0; - env_leave_pmax = 0; - env_in_use = false; - env_debug = no_debug; - env_locals = Array.make num_locals vnull; - env_captures = empty_array; - } - -let pop_environment_debug ctx env = - let eval = get_eval ctx in - eval.environment_offset <- eval.environment_offset - 1; +let pop_environment ctx env = + let eval = env.env_eval in + eval.env <- env.env_parent; env.env_debug.timer(); () -let push_environment ctx info num_locals num_captures = - if ctx.record_stack then - push_environment_debug ctx info num_locals num_captures - else { - env_info = info; - env_leave_pmin = 0; - env_leave_pmax = 0; - env_in_use = false; - env_debug = no_debug; - env_locals = Array.make num_locals vnull; - env_captures = Array.make num_captures (ref vnull); - } -[@@inline] - -let pop_environment ctx env = - if ctx.record_stack then pop_environment_debug ctx env else () -[@@inline] - (* Prototypes *) let get_static_prototype_raise ctx path = - IntMap.find path ctx.static_prototypes + ctx.static_prototypes#get path let get_static_prototype ctx path p = try get_static_prototype_raise ctx path - with Not_found -> Error.error (Printf.sprintf "[%i] Type not found: %s" ctx.ctx_id (rev_hash_s path)) p + with Not_found -> Error.error (Printf.sprintf "[%i] Type not found: %s" ctx.ctx_id (rev_hash path)) p let get_static_prototype_as_value ctx path p = (get_static_prototype ctx path p).pvalue @@ -344,14 +481,14 @@ let get_instance_prototype_raise ctx path = let get_instance_prototype ctx path p = try get_instance_prototype_raise ctx path - with Not_found -> Error.error (Printf.sprintf "[%i] Instance prototype not found: %s" ctx.ctx_id (rev_hash_s path)) p + with Not_found -> Error.error (Printf.sprintf "[%i] Instance prototype not found: %s" ctx.ctx_id (rev_hash path)) p let get_instance_constructor_raise ctx path = IntMap.find path ctx.constructors let get_instance_constructor ctx path p = try get_instance_constructor_raise ctx path - with Not_found -> Error.error (Printf.sprintf "[%i] Instance constructor not found: %s" ctx.ctx_id (rev_hash_s path)) p + with Not_found -> Error.error (Printf.sprintf "[%i] Instance constructor not found: %s" ctx.ctx_id (rev_hash path)) p let get_special_instance_constructor_raise ctx path = Hashtbl.find (get_ctx()).builtins.constructor_builtins path @@ -361,11 +498,11 @@ let get_proto_field_index_raise proto name = let get_proto_field_index proto name = try get_proto_field_index_raise proto name - with Not_found -> Error.error (Printf.sprintf "Field index for %s not found on prototype %s" (rev_hash_s name) (rev_hash_s proto.ppath)) null_pos + with Not_found -> Error.error (Printf.sprintf "Field index for %s not found on prototype %s" (rev_hash name) (rev_hash proto.ppath)) null_pos let get_instance_field_index_raise proto name = IntMap.find name proto.pinstance_names let get_instance_field_index proto name p = try get_instance_field_index_raise proto name - with Not_found -> Error.error (Printf.sprintf "Field index for %s not found on prototype %s" (rev_hash_s name) (rev_hash_s proto.ppath)) p + with Not_found -> Error.error (Printf.sprintf "Field index for %s not found on prototype %s" (rev_hash name) (rev_hash proto.ppath)) p diff --git a/src/macro/eval/evalDebug.ml b/src/macro/eval/evalDebug.ml index a9545e3ebdc..5c9f222bbbe 100644 --- a/src/macro/eval/evalDebug.ml +++ b/src/macro/eval/evalDebug.ml @@ -13,43 +13,51 @@ open EvalMisc open EvalDebugMisc open MacroApi -let is_caught ctx v = +let is_caught eval v = try - Hashtbl.iter (fun path _ -> if is v path then raise Exit) ctx.debug.caught_types; + Hashtbl.iter (fun path _ -> if is v path then raise Exit) eval.caught_types; false with Exit -> true (* Checks debug state and calls what's needed. *) -let rec run_loop ctx wait run env : value = +let rec run_loop run env : value = + let eval = env.env_eval in let check_breakpoint () = - if ctx.debug.breakpoint.bpstate = BPHit && env.env_debug.line <> ctx.debug.breakpoint.bpline then ctx.debug.breakpoint.bpstate <- BPEnabled + if eval.breakpoint.bpstate = BPHit && env.env_debug.line <> eval.breakpoint.bpline then eval.breakpoint.bpstate <- BPEnabled in - match ctx.debug.debug_state with + match eval.debug_state with | DbgRunning -> check_breakpoint(); run env - | DbgContinue -> - check_breakpoint(); - run env - | DbgNext offset -> - if offset < (get_eval ctx).environment_offset then + | DbgNext(env',p) -> + let b = DisplayPosition.encloses_position (env.env_debug.expr.epos) p in + let rec is_on_stack env = + match env.env_parent with + | Some env -> env == env' || is_on_stack env + | None -> false + in + if is_on_stack env || b then run env else begin - ctx.debug.debug_state <- DbgWaiting; - run_loop ctx wait run env - end - | DbgFinish offset -> - if offset <= (get_eval ctx).environment_offset then + eval.debug_state <- DbgWaiting; + run_loop run env + end; + | DbgFinish env' -> + if env' != env then run env else begin - ctx.debug.debug_state <- DbgWaiting; - run_loop ctx wait run env + eval.debug_state <- DbgWaiting; + run_loop run env end - | DbgWaiting | DbgStart -> - wait ctx run env + | DbgStep -> + eval.debug_state <- DbgWaiting; + run env + | DbgWaiting -> + ignore(Event.sync(Event.receive eval.debug_channel)); + run_loop run env -let debug_loop jit e f = +let debug_loop jit conn e f = let ctx = jit.ctx in let scopes = jit.scopes in let line,col1,_,_ = Lexer.get_pos_coords e.epos in @@ -57,43 +65,58 @@ let debug_loop jit e f = | BPAny -> true | BPColumn i -> i = col1 in - let conn = match ctx.debug.debug_socket with - | Some socket -> EvalDebugSocket.make_connection socket - | None -> EvalDebugCLI.connection + let condition_holds env breakpoint = match breakpoint.bpcondition with + | None -> true + | Some e -> match safe_call env.env_eval (expr_to_value_safe ctx env) e with + | VTrue -> true + | _ -> false + in + let debugger_catches eval v = match ctx.debug.exception_mode with + | CatchAll -> true + | CatchUncaught -> not (is_caught eval v) + | CatchNone -> false in (* Checks if we hit a breakpoint, runs the code if not. *) let rec run_check_breakpoint env = + let eval = env.env_eval in try - let h = Hashtbl.find ctx.debug.breakpoints env.env_info.pfile in + let h = Hashtbl.find ctx.debug.breakpoints env.env_info.pfile_unique in let breakpoint = Hashtbl.find h env.env_debug.line in begin match breakpoint.bpstate with - | BPEnabled when column_matches breakpoint -> + | BPEnabled when column_matches breakpoint && condition_holds env breakpoint -> breakpoint.bpstate <- BPHit; - ctx.debug.breakpoint <- breakpoint; - conn.bp_stop ctx env; - ctx.debug.debug_state <- DbgWaiting; - run_loop ctx conn.wait run_check_breakpoint env + eval.breakpoint <- breakpoint; (* TODO: per-thread... *) + conn.bp_stop ctx.debug; + eval.debug_state <- DbgWaiting; + run_loop run_check_breakpoint env | _ -> raise Not_found end with Not_found -> try f env with - | RunTimeException(v,_,_) when not (is_caught ctx v) -> - conn.exc_stop ctx v e.epos; - ctx.debug.debug_state <- DbgWaiting; - run_loop ctx conn.wait run_check_breakpoint env + | RunTimeException(v,_,_) when debugger_catches env.env_eval v && eval.caught_exception != v -> + eval.caught_exception <- v; + conn.exc_stop ctx.debug v e.epos; + eval.debug_state <- DbgWaiting; + run_loop run_check_breakpoint env | BreakHere -> - conn.bp_stop ctx env; - ctx.debug.debug_state <- DbgWaiting; - run_loop ctx conn.wait run_check_breakpoint env - + conn.bp_stop ctx.debug; + eval.debug_state <- DbgWaiting; + run_loop (fun _ -> vnull) env + | Return v as exc -> + eval.last_return <- Some v; + raise exc + (* | Return _ | Break | Continue | Sys_exit _ | RunTimeException _ as exc -> + raise exc + | exc -> + throw (EvalString.vstring (EvalString.create_ascii (Printexc.to_string exc))) e.epos; *) in (* Sets the environmental debug data, then executes the debug loop. *) let run_set env = env.env_debug.scopes <- scopes; env.env_debug.line <- line; env.env_debug.expr <- e; - run_loop ctx conn.wait run_check_breakpoint env; + run_loop run_check_breakpoint env; in run_set \ No newline at end of file diff --git a/src/macro/eval/evalDebugCLI.ml b/src/macro/eval/evalDebugCLI.ml deleted file mode 100644 index 550c8a16c2d..00000000000 --- a/src/macro/eval/evalDebugCLI.ml +++ /dev/null @@ -1,389 +0,0 @@ -open Gc -open Ast -open Type -open Globals -open MacroApi -open EvalContext -open EvalValue -open EvalExceptions -open EvalHash -open EvalPrinting -open EvalMisc -open EvalDebugMisc - -let get_call_stack_envs ctx kind p = - let envs = match call_stack ctx with - | _ :: envs -> envs - | [] -> [] - in - let rec loop delta envs = match envs with - | _ :: envs when delta < 0 -> loop (delta + 1) envs - | _ -> envs - in - loop ctx.debug.environment_offset_delta envs - -(* Printing *) - -let value_string value = - let rec fields_string depth fields = - let tabs = String.make (depth * 2) ' ' in - let l = List.map (fun (name,value) -> - let s_type,s_value = value_string depth value in - Printf.sprintf "%s%s : %s = %s" tabs (rev_hash_s name) s_type s_value - ) fields in - Printf.sprintf "{\n%s\n%s}" (String.concat "\n" l) tabs - and instance_fields depth vi = - let fields = IntMap.fold (fun name key acc -> - (name,vi.ifields.(key)) :: acc - ) vi.iproto.pinstance_names [] in - fields_string (depth + 1) fields - and value_string depth v = match v with - | VNull -> "NULL","null" - | VTrue -> "Bool","true" - | VFalse -> "Bool","false" - | VInt32 i -> "Int",Int32.to_string i - | VFloat f -> "Float",string_of_float f - | VEnumValue ev -> rev_hash_s ev.epath,Rope.to_string (s_enum_value 0 ev) - | VObject o -> "Anonymous",fields_string (depth + 1) (object_fields o) - | VString(_,s) -> "String","\"" ^ (Ast.s_escape (Lazy.force s)) ^ "\"" - | VArray va -> "Array",Rope.to_string (s_array (depth + 1) va) - | VVector vv -> "Vector",Rope.to_string (s_vector (depth + 1) vv) - | VInstance vi -> rev_hash_s vi.iproto.ppath,instance_fields (depth + 1) vi - | VPrototype proto -> "Anonymous",Rope.to_string (s_proto_kind proto) - | VFunction _ | VFieldClosure _ -> "Function","fun" - in - let s_type,s_value = value_string 0 value in - Printf.sprintf "%s = %s" s_type s_value - -let send_string s = - print_endline s - -let output_info = send_string -let output_error = send_string - -let output_exception_stop ctx v pos = - output_info (uncaught_exception_string v pos "") - -let output_variable_name name = - send_string (Printf.sprintf "%s" name) - -let output_value name value = - send_string (Printf.sprintf "%s : %s" name (value_string value)) - -let output_call_stack_position ctx i kind p = - let line = Lexer.get_error_line p in - send_string (Printf.sprintf "%6i : %s at %s:%i" i (kind_name (get_eval ctx) kind) (Path.get_real_path p.pfile) line) - -let output_call_stack ctx kind p = - let envs = get_call_stack_envs ctx kind p in - let i = ref ((get_eval ctx).environment_offset - 1) in - output_call_stack_position ctx !i kind {p with pfile = Path.unique_full_path p.Globals.pfile}; - List.iter (fun env -> - if env.env_leave_pmin >= 0 then begin - let p = {pmin = env.env_leave_pmin; pmax = env.env_leave_pmax; pfile = rev_file_hash env.env_info.pfile} in - decr i; - output_call_stack_position ctx !i env.env_info.kind p - end - ) envs - -let output_file_path s = send_string (Path.get_real_path s) - -let output_type_name = send_string -let output_breakpoint breakpoint = - let flag = match breakpoint.bpstate with - | BPHit | BPEnabled -> "E" - | BPDisabled -> "d" - in - send_string (Printf.sprintf "%i %s" breakpoint.bpid flag) - -let output_breakpoints ctx = - iter_breakpoints ctx (fun breakpoint -> - output_breakpoint breakpoint - ) - -let output_breakpoint_set breakpoint = - output_info (Printf.sprintf "Breakpoint %i set and enabled" breakpoint.bpid) - -let output_breakpoint_stop ctx env = - output_info (Printf.sprintf "Thread %i stopped in %s at %s:%i." 0 (kind_name (get_eval ctx) env.env_info.kind) (rev_file_hash env.env_info.pfile) env.env_debug.line) - -let output_breakpoint_description breakpoint = - let s_col = match breakpoint.bpcolumn with - | BPAny -> "" - | BPColumn i -> ":" ^ (string_of_int i) - in - send_string (Printf.sprintf "%s:%i%s" ((Path.get_real_path (rev_file_hash breakpoint.bpfile))) breakpoint.bpline s_col) - -let read_line () = - input_line Pervasives.stdin - -let parse_breakpoint_pattern pattern = - (* TODO: more than file:line patterns? *) - try - let split = ExtString.String.nsplit pattern ":" in - let file,line,column = match List.rev split with - | first :: rest -> - let first = int_of_string first in - begin match rest with - | second :: file -> - begin try - file,(int_of_string second),BPColumn first - with _ -> - (second :: file),first,BPAny - end - | file -> - file,first,BPAny - end - | [] -> raise Exit - in - let file = String.concat ":" (List.rev file) in - file,line,column - with _ -> - raise Exit - -let print_variables ctx capture_infos scopes env = - let rec loop scopes = match scopes with - | scope :: scopes -> - Hashtbl.iter (fun _ name -> output_variable_name name) scope.local_infos; - loop scopes - | [] -> - () - in - loop scopes; - Hashtbl.iter (fun slot name -> - if slot < Array.length env.env_captures then - output_variable_name name - ) capture_infos - - -let set_variable ctx scopes name value env = - try - let slot = get_var_slot_by_name scopes name in - env.env_locals.(slot) <- value; - output_value name value; - with Not_found -> - output_error ("No variable found: " ^ name) - -(* Reads input and reacts accordingly. *) -let rec wait ctx run env = - let get_real_env ctx = - ctx.debug.environment_offset_delta <- 0; - DynArray.get (get_eval ctx).environments ((get_eval ctx).environment_offset - 1); - in - let rec move_frame offset : value = - if offset < 0 || offset >= (get_eval ctx).environment_offset then begin - output_error (Printf.sprintf "Frame out of bounds: %i (valid range is %i - %i)" offset 0 ((get_eval ctx).environment_offset - 1)); - loop() - end else begin - ctx.debug.environment_offset_delta <- ((get_eval ctx).environment_offset - offset - 1); - wait ctx run (DynArray.get (get_eval ctx).environments offset); - end - and loop () = - print_string "1> "; - flush stdout; - let line = read_line () in - match ExtString.String.nsplit line " " with - | ["quit" | "exit"] -> - (* TODO: Borrowed from interp.ml *) - if (get_ctx()).curapi.use_cache() then raise (Error.Fatal_error ("",Globals.null_pos)); - raise (Sys_exit 0); - | ["detach"] -> - Hashtbl.iter (fun _ h -> - Hashtbl.clear h - ) ctx.debug.breakpoints; - ctx.debug.debug_state <- DbgRunning; - run env - (* source | history *) - | ["files" | "filespath"] -> - Hashtbl.iter (fun i _ -> - output_file_path (rev_file_hash i); - ) ctx.debug.breakpoints; - loop() - | ["classes"] -> - IntMap.iter (fun i _ -> - output_type_name (rev_hash_s i) - ) ctx.type_cache; - loop() - | ["mem"] -> - output_info (Printf.sprintf "%i" (Gc.stat()).live_words); - loop() - | ["compact"] -> - let before = (Gc.stat()).live_words in - Gc.compact(); - let after = (Gc.stat()).live_words in - output_info (Printf.sprintf "before: %i\nafter: %i" before after); - loop() - | ["collect"] -> - let before = (Gc.stat()).live_words in - Gc.full_major(); - let after = (Gc.stat()).live_words in - output_info (Printf.sprintf "before: %i\nafter: %i" before after); - loop() - | ["break" | "b";pattern] -> - begin try - let file,line,column = parse_breakpoint_pattern pattern in - begin try - let breakpoint = add_breakpoint ctx file line column in - output_breakpoint_set breakpoint; - with Not_found -> - output_error ("Could not find file " ^ file); - end; - with Exit -> - output_error "Unrecognized breakpoint pattern"; - end; - loop() - | ["list" | "l"] -> - (* TODO: other list syntax *) - output_breakpoints ctx; - loop() - | ["describe" | "desc";bpid] -> - (* TODO: range patterns? *) - begin try - let breakpoint = find_breakpoint ctx bpid in - output_breakpoint_description breakpoint; - with Not_found -> - output_error (Printf.sprintf "Unknown breakpoint: %s" bpid); - end; - loop() - | ["disable" | "dis";bpid] -> - (* TODO: range patterns? *) - if bpid = "all" then - iter_breakpoints ctx (fun breakpoint -> breakpoint.bpstate <- BPDisabled) - else begin try - let breakpoint = find_breakpoint ctx bpid in - breakpoint.bpstate <- BPDisabled; - output_info (Printf.sprintf "Breakpoint %s disabled" bpid); - with Not_found -> - output_error (Printf.sprintf "Unknown breakpoint: %s" bpid); - end; - loop() - | ["enable" | "en";bpid] -> - (* TODO: range patterns? *) - if bpid = "all" then - iter_breakpoints ctx (fun breakpoint -> breakpoint.bpstate <- BPEnabled) - else begin try - let breakpoint = find_breakpoint ctx bpid in - breakpoint.bpstate <- BPEnabled; - output_info (Printf.sprintf "Breakpoint %s enabled" bpid); - with Not_found -> - output_error (Printf.sprintf "Unknown breakpoint: %s" bpid); - end; - loop() - | ["delete" | "d";bpid] -> - (* TODO: range patterns? *) - if bpid = "all" then - Hashtbl.iter (fun _ h -> - Hashtbl.clear h - ) ctx.debug.breakpoints - else begin try - let id = try int_of_string bpid with _ -> raise Not_found in - Hashtbl.iter (fun _ h -> - let to_delete = ref [] in - Hashtbl.iter (fun k breakpoint -> if breakpoint.bpid = id then to_delete := k :: !to_delete) h; - List.iter (fun k -> Hashtbl.remove h k) !to_delete; - ) ctx.debug.breakpoints; - output_info (Printf.sprintf "Breakpoint %s deleted" bpid); - with Not_found -> - output_error (Printf.sprintf "Unknown breakpoint: %s" bpid); - end; - loop() - | ["clear";pattern] -> - (* TODO: range patterns? *) - begin try - let file,line,column = parse_breakpoint_pattern pattern in - begin try - delete_breakpoint ctx file line - with Not_found -> - output_info (Printf.sprintf "Could not find breakpoint %s:%i" file line); - end - with Exit -> - output_error ("Unrecognized breakpoint pattern"); - end; - loop() - (* thread | unsafe | safe *) - | ["continue" | "c"] -> - let env = get_real_env ctx in - ctx.debug.debug_state <- (if ctx.debug.debug_state = DbgStart then DbgRunning else DbgContinue); - run env - | ["step" | "s" | ""] -> - let env = get_real_env ctx in - run env - | ["next" | "n"] -> - let env = get_real_env ctx in - ctx.debug.debug_state <- DbgNext (get_eval ctx).environment_offset; - run env - | ["finish" | "f"] -> - let env = get_real_env ctx in - ctx.debug.debug_state <- DbgFinish (get_eval ctx).environment_offset; - run env - | ["where" | "w"] -> - output_call_stack ctx env.env_info.kind env.env_debug.expr.epos; - loop() - | ["up"] -> - let offset = (get_eval ctx).environment_offset - ctx.debug.environment_offset_delta in - move_frame (offset - 2) - | ["down"] -> - let offset = (get_eval ctx).environment_offset - ctx.debug.environment_offset_delta in - move_frame offset - | ["frame";sframe] -> - let frame = try - Some (int_of_string sframe) - with _ -> - None - in - begin match frame with - | Some frame -> move_frame ((get_eval ctx).environment_offset - frame - 1) - | None -> - output_error ("Invalid frame format: " ^ sframe); - loop() - end - | ["variables" | "vars"] -> - print_variables ctx env.env_info.capture_infos env.env_debug.scopes env; - loop() - | ["print" | "p";e] -> - begin try - let e = parse_expr ctx e env.env_debug.expr.epos in - begin try - let name,v = expr_to_value ctx env e in - output_value name v - with Exit -> - output_error ("Don't know how to handle this expression: " ^ (Ast.s_expr e)) - end - with Parse_expr_error e -> - output_error e - end; - loop() - | ["set" | "s";expr_s;"=";value] -> - let parse s = parse_expr ctx s env.env_debug.expr.epos in - begin try - let expr,value = parse expr_s,parse value in - begin try - let _,value = expr_to_value ctx env value in - begin match fst expr with - (* TODO: support setting array elements and enum values *) - | EField(e1,s) -> - let _,v1 = expr_to_value ctx env e1 in - set_field v1 (hash_s s) value; - | EConst (Ident s) -> - set_variable ctx env.env_debug.scopes s value env; - | _ -> - raise Exit - end - with Exit -> - output_error ("Don't know how to handle this expression") - end - with Parse_expr_error e -> - output_error e - end; - loop() - | s -> - output_error (Printf.sprintf "Unknown command: %s" (String.concat " " s)); - loop() - in - loop () - -let connection : debug_connection = { - wait = wait; - bp_stop = output_breakpoint_stop; - exc_stop = output_exception_stop; -} diff --git a/src/macro/eval/evalDebugMisc.ml b/src/macro/eval/evalDebugMisc.ml index 69183e603f3..8cd0a81ce06 100644 --- a/src/macro/eval/evalDebugMisc.ml +++ b/src/macro/eval/evalDebugMisc.ml @@ -5,37 +5,45 @@ open EvalContext open EvalHash open EvalValue open EvalEncode - -type debug_connection = { - wait : context -> (env -> value) -> env -> value; - bp_stop : context -> env -> unit; - exc_stop : context -> value -> pos -> unit; -} +open EvalMisc +open EvalExceptions exception BreakHere +let createInstance_ref : value ref = Obj.magic () + +let declared_before vi p = + vi.vi_pos.pmin < p.pmin + (* Breakpoints *) -let make_breakpoint = - let id = ref (-1) in - (fun file line state column -> - incr id; - { - bpid = !id; - bpfile = file; - bpline = line; - bpstate = state; - bpcolumn = column; - } - ) +let breakpoint_id = ref (-1) + +let make_breakpoint file line state column condition = + incr breakpoint_id; + { + bpid = !breakpoint_id; + bpfile = file; + bpline = line; + bpstate = state; + bpcolumn = column; + bpcondition = condition + } + +let make_function_breakpoint state = + incr breakpoint_id; + { + fbpid = !breakpoint_id; + fbpstate = state; + } let iter_breakpoints ctx f = Hashtbl.iter (fun _ breakpoints -> Hashtbl.iter (fun _ breakpoint -> f breakpoint) breakpoints ) ctx.debug.breakpoints -let add_breakpoint ctx file line column = - let hash = hash_s (Path.unique_full_path (Common.find_file (ctx.curapi.get_com()) file)) in +let add_breakpoint ctx file line column condition = + let hash = hash (Path.unique_full_path (Common.find_file (ctx.curapi.get_com()) file)) in let h = try Hashtbl.find ctx.debug.breakpoints hash with Not_found -> @@ -43,12 +51,12 @@ let add_breakpoint ctx file line column = Hashtbl.add ctx.debug.breakpoints hash h; h in - let breakpoint = make_breakpoint hash line BPEnabled column in + let breakpoint = make_breakpoint hash line BPEnabled column condition in Hashtbl.replace h line breakpoint; breakpoint let delete_breakpoint ctx file line = - let hash = hash_s (Path.unique_full_path (Common.find_file (ctx.curapi.get_com()) file)) in + let hash = hash (Path.unique_full_path (Common.find_file (ctx.curapi.get_com()) file)) in let h = Hashtbl.find ctx.debug.breakpoints hash in Hashtbl.remove h line @@ -66,23 +74,26 @@ let find_breakpoint ctx sid = with Exit -> match !found with None -> assert false | Some breakpoint -> breakpoint - (* Helper *) exception Parse_expr_error of string let parse_expr ctx s p = let error s = raise (Parse_expr_error s) in - ParserEntry.parse_expr_string (ctx.curapi.get_com()).Common.defines s p error false + match ParserEntry.parse_expr_string (ctx.curapi.get_com()).Common.defines s p error true with + | ParseSuccess data | ParseDisplayFile(data,_) -> data + | ParseError(_,(msg,_),_) -> error (Parser.error_msg msg) (* Vars *) -let get_var_slot_by_name scopes name = +let get_var_slot_by_name env is_read scopes name = let rec loop scopes = match scopes with | scope :: scopes -> begin try let id = Hashtbl.find scope.local_ids name in let slot = Hashtbl.find scope.locals id in + let vi = Hashtbl.find scope.local_infos slot in + if is_read && not (declared_before vi env.env_debug.expr.epos) then raise Not_found; slot + scope.local_offset with Not_found -> loop scopes @@ -95,8 +106,8 @@ let get_var_slot_by_name scopes name = let get_capture_slot_by_name capture_infos name = let ret = ref None in try - Hashtbl.iter (fun slot name' -> - if name = name' then begin + Hashtbl.iter (fun slot vi -> + if name = vi.vi_name then begin ret := (Some slot); raise Exit end @@ -105,26 +116,41 @@ let get_capture_slot_by_name capture_infos name = with Exit -> match !ret with None -> assert false | Some name -> name -let get_variable capture_infos scopes name env = +let get_variable env capture_infos scopes name env = try - let slot = get_var_slot_by_name scopes name in + let slot = get_var_slot_by_name env true scopes name in let value = env.env_locals.(slot) in value with Not_found -> let slot = get_capture_slot_by_name capture_infos name in let value = try env.env_captures.(slot) with _ -> raise Not_found in - !value + value (* Expr to value *) let resolve_ident ctx env s = - let key = hash_s s in + let key = hash s in try + (* 0. Extra locals *) + IntMap.find key env.env_extra_locals + with Not_found -> try (* 1. Variable *) - get_variable env.env_info.capture_infos env.env_debug.scopes s env + get_variable ctx env.env_info.capture_infos env.env_debug.scopes s env with Not_found -> try (* 2. Instance *) if env.env_info.static then raise Not_found; + let rec loop env = match env.env_info.kind with + | EKLocalFunction _ -> + begin match env.env_parent with + | None -> assert false + | Some env -> loop env + end + | EKMethod _ -> env + | EKEntrypoint -> + (* This can happen due to threads. Have to check what we can do here... *) + raise Not_found + in + let env = loop env in let v = env.env_locals.(0) in EvalField.field_raise v key with Not_found -> try @@ -138,48 +164,253 @@ let resolve_ident ctx env s = end with Not_found -> try (* 4. Type *) - VPrototype (IntMap.find key ctx.static_prototypes) + VPrototype (get_static_prototype_raise ctx key) + with Not_found -> try + (* 5. Toplevel *) + EvalField.field_raise ctx.toplevel key with Not_found -> - raise Exit + vnull + +let find_enum_field_by_name ve name = + match (get_static_prototype_raise (get_ctx()) ve.epath).pkind with + | PEnum names -> + let fields = snd (List.nth names ve.eindex) in + let rec loop i fields = match fields with + | field :: fields -> + if field = name then i + else loop (i + 1) fields + | [] -> + raise Not_found + in + loop 0 fields + | _ -> + raise Not_found + +let safe_call eval f a = + let old = eval.debug_state in + eval.debug_state <- DbgRunning; + try + let r = f a in + eval.debug_state <- old; + r + with exc -> + eval.debug_state <- old; + raise exc -let expr_to_value ctx env e = +let rec expr_to_value ctx env e = let rec loop e = match fst e with | EConst cst -> begin match cst with - | String s -> "",encode_string s - | Int s -> "",VInt32 (Int32.of_string s) - | Float s -> "",VFloat (float_of_string s) - | Ident "true" -> "",VTrue - | Ident "false" -> "",VFalse - | Ident "null" -> "",VNull + | String s -> EvalString.create_unknown s + | Int s -> VInt32 (Int32.of_string s) + | Float s -> VFloat (float_of_string s) + | Ident "true" -> VTrue + | Ident "false" -> VFalse + | Ident "null" -> VNull | Ident s -> let value = resolve_ident ctx env s in - s,value + value | _ -> raise Exit end | EArray(e1,eidx) -> - let n1,v1 = loop e1 in - let nidx,vidx = loop eidx in + let v1 = loop e1 in + let vidx = loop eidx in let idx = match vidx with VInt32 i -> Int32.to_int i | _ -> raise Exit in - let n = Printf.sprintf "%s[%d]" n1 idx in begin match v1 with - | VArray va -> - let v = EvalArray.get va idx in - (n,v) - | VVector vv -> - let v = Array.get vv idx in - (n,v) - | VEnumValue ev -> - let v = Array.get ev.eargs idx in - (n,v) - | _ -> - raise Exit + | VArray va -> EvalArray.get va idx + | VVector vv -> Array.get vv idx + | VEnumValue ev -> Array.get ev.eargs idx + | _ -> raise Exit end | EField(e1,s) -> - let n1,v1 = loop e1 in - let v = EvalField.field v1 (hash_s s) in - (Printf.sprintf "%s.%s" n1 s),v - | _ -> + let v1 = loop e1 in + let s' = hash s in + begin match v1 with + | VEnumValue ve -> + begin try + let i = find_enum_field_by_name ve s' in + ve.eargs.(i) + with Not_found -> + vnull + end + | _ -> + let v = try + EvalField.field_raise v1 s' + with Not_found -> try + (* Maybe we have a getter? (#8599) *) + let vf = EvalField.field v1 (hash ("get_" ^ s)) in + safe_call env.env_eval (EvalPrinting.call_value_on v1 vf) [] + with _ -> + vnull + in + v + end + | EArrayDecl el -> + let vl = List.map loop el in + encode_array vl + | EObjectDecl fl -> + let fl = List.map (fun ((s,_,_),e) -> s,loop e) fl in + encode_obj_s fl + | EBinop(op,e1,e2) -> + begin match op with + | OpAssign -> + let v2 = loop e2 in + write_expr ctx env e1 v2; + | OpAssignOp op -> + raise Exit (* Nobody does that, right? *) + | OpBoolAnd -> + if is_true (loop e1) then loop e2 + else VFalse + | OpBoolOr -> + if is_true (loop e1) then VTrue + else loop e2 + | _ -> + let v1 = loop e1 in + let v2 = loop e2 in + let p = pos e in + (try get_binop_fun op p with _ -> raise Exit) v1 v2 + end + | EUnop(op,flag,e1) -> + begin match op with + | Not -> + begin match loop e1 with + | VNull | VFalse -> VTrue + | _ -> VFalse + end + | Neg -> + begin match loop e1 with + | VFloat f -> VFloat (-.f) + | VInt32 i -> vint32 (Int32.neg i) + | _ -> raise Exit + end + | NegBits -> + op_sub (pos e) (vint32 (Int32.minus_one)) (loop e1) + | Increment | Decrement -> + raise Exit + end + | ECall(e1,el) -> + begin match fst e1 with + | EField(ethis,s) -> + let vthis = loop ethis in + let v1 = EvalField.field vthis (hash s) in + let vl = List.map loop el in + safe_call env.env_eval (EvalPrinting.call_value_on vthis v1) vl + | _ -> + let v1 = loop e1 in + let vl = List.map loop el in + safe_call env.env_eval (call_value v1) vl + end + | EBlock el -> + let rec loop2 el = match el with + | [] -> VNull + | [e1] -> loop e1 + | e1 :: el -> + ignore(loop e1); + loop2 el + in + loop2 el + | EIf(e1,e2,eo) -> + let v1 = loop e1 in + if is_true v1 then loop e2 + else Option.map_default loop VNull eo + | ETernary(e1,e2,e3) -> + let v1 = loop e1 in + if is_true v1 then loop e2 else loop e3 + | EParenthesis e1 | EMeta(_,e1) | EUntyped e1 | ECast(e1,None) | ECheckType(e1,_) -> + loop e1 + | EReturn e1 -> + let v1 = Option.map_default loop vnull e1 in + raise (Return v1) + | EContinue -> + raise Continue + | EBreak -> + raise Break + | EThrow e1 -> + let v1 = loop e1 in + throw v1 (pos e) + | EVars vl -> + List.iter (fun ((n,_),_,_,eo) -> + match eo with + | Some e -> + env.env_extra_locals <- IntMap.add (hash n) (loop e) env.env_extra_locals + | _ -> + () + ) vl; + vnull + | EWhile(e1,e2,flag) -> + let rec loop2 () = + if is_true (loop e1) then begin + ignore(loop e2); + loop2() + end + in + if flag = DoWhile then ignore(loop e2); + loop2(); + vnull + | ENew((tp,_),el) -> + let rec loop2 v sl = match sl with + | [] -> v + | s :: sl -> + loop2 (EvalField.field v (hash s)) sl + in + let v1 = loop2 ctx.toplevel tp.tpackage in + let v1 = loop2 v1 [match tp.tsub with None -> tp.tname | Some s -> s] in + let vl = List.map loop el in + let vc = loop2 ctx.toplevel ["Type";"createInstance"] in + safe_call env.env_eval (call_value vc) [v1;encode_array vl] + | ETry _ | ESwitch _ | EFunction _ | EFor _ | EDisplay _ + | EDisplayNew _ | ECast(_,Some _) -> raise Exit in loop e + +and write_expr ctx env expr value = + begin match fst expr with + | EField(e1,s) -> + let s' = hash s in + let v1 = expr_to_value ctx env e1 in + begin match v1 with + | VEnumValue ve -> + begin try + let i = find_enum_field_by_name ve s' in + ve.eargs.(i) <- value; + value + with Not_found -> + value + end + | _ -> + try + set_field v1 s' value; + value; + with Not_found -> try + let vf = EvalField.field v1 (hash ("set_" ^ s)) in + safe_call env.env_eval (EvalPrinting.call_value_on v1 vf) [value] + with _ -> + value + end + | EConst (Ident s) -> + begin try + let slot = get_var_slot_by_name env false env.env_debug.scopes s in + env.env_locals.(slot) <- value; + value + with Not_found -> + raise Exit + end + | EArray(e1,e2) -> + let v1 = expr_to_value ctx env e1 in + let vidx = expr_to_value ctx env e2 in + let idx = match vidx with VInt32 i -> Int32.to_int i | _ -> raise Exit in + begin match v1 with + | VArray va -> EvalArray.set va idx value + | VVector vv -> Array.set vv idx value + | VEnumValue ev -> Array.set ev.eargs idx value + | _ -> raise Exit + end; + value + | _ -> + raise Exit + end + +let expr_to_value_safe ctx env e = + try expr_to_value ctx env e + with Exit -> VNull \ No newline at end of file diff --git a/src/macro/eval/evalDebugSocket.ml b/src/macro/eval/evalDebugSocket.ml index 1c2c83be72d..59ff5d2ab8a 100644 --- a/src/macro/eval/evalDebugSocket.ml +++ b/src/macro/eval/evalDebugSocket.ml @@ -3,7 +3,7 @@ open Ast open Type open Globals open MacroApi -open Unix +open JsonRpcSocket open Json open EvalContext open EvalValue @@ -12,128 +12,32 @@ open EvalPrinting open EvalMisc open EvalDebugMisc -module JsonRpc = struct - let jsonrpc_field = "jsonrpc", JString "2.0" +(* Printing *) - let notification method_name params = - let fl = [ - jsonrpc_field; - "method", JString method_name; +let var_to_json name value vio env = + let jv t v num_children = + let id = if num_children = 0 then 0 else (get_ctx()).debug.debug_context#add_value value env in + let fields = [ + "id",JInt id; + "name",JString name; + "type",JString t; + "value",JString v; + "numChildren",JInt num_children; ] in - let fl = Option.map_default (fun params -> ("params",params) :: fl) fl params in - JObject fl - - let result id data = - JObject [ - jsonrpc_field; - "id", id; - "result", data; - ] - - let error id code message = - JObject [ - jsonrpc_field; - "id", id; - "error", JObject [ - "code", JInt code; - "message", JString message; - ]; - ] - - type json_rpc_error = - | Parse_error of string - | Invalid_request of string - | Method_not_found of Json.t * string (* id->methodname *) - | Invalid_params of Json.t - | Custom of Json.t * int * string (* id->code->message *) - - exception JsonRpc_error of json_rpc_error - - let handle_jsonrpc_error f output = - try f () with JsonRpc_error e -> - match e with - | Parse_error s -> output (error JNull (-32700) s) - | Invalid_request s -> output (error JNull (-32600) s) - | Method_not_found (id,meth) -> output (error id (-32601) (Printf.sprintf "Method `%s` not found" meth)) - | Invalid_params id -> output (error id (-32602) "Invalid params") - | Custom (id,code,msg) -> output (error id code msg) - - let process_request input handle output = - let open Json.Reader in - let lexbuf = Sedlexing.Utf8.from_string input in - let json = try read_json lexbuf with Json_error s -> raise (JsonRpc_error (Parse_error s)) in - let fields = match json with JObject fl -> fl | _ -> raise (JsonRpc_error (Invalid_request "not an object")) in - let get_field name map = - let field = try List.find (fun (n,_) -> n = name) fields with Not_found -> raise (JsonRpc_error (Invalid_request ("no `" ^ name ^ "` field"))) in - let value = map (snd field) in - match value with - | None -> raise (JsonRpc_error (Invalid_request (Printf.sprintf "`%s` field has invalid data" name))) - | Some v -> v - in - let id = get_field "id" (fun v -> Some v) in - let meth = get_field "method" (function JString s -> Some s | _ -> None) in - let params = - try - let f = List.find (fun (n,_) -> n = "params") fields in - Some (snd f) - with Not_found -> - None - in - let res = handle id meth params in - output id res -end - -module Transport = struct - let read_byte this i = int_of_char (Bytes.get this i) - - let read_ui16 this i = - let ch1 = read_byte this i in - let ch2 = read_byte this (i + 1) in - ch1 lor (ch2 lsl 8) - - let read_string socket = - match socket.socket with + let fields = match vio with + | Some vi -> + let line,col1,_,_ = Lexer.get_pos_coords vi.vi_pos in + ("generated",JBool vi.vi_generated) :: + ("line",JInt line) :: + ("column",JInt col1) :: + fields | None -> - failwith "no socket" (* TODO: reconnect? *) - | Some socket -> - let buf = Bytes.create 2 in - let _ = recv socket buf 0 2 [] in - let i = read_ui16 buf 0 in - let buf = Bytes.create i in - let _ = recv socket buf 0 i [] in - Bytes.to_string buf - - let send_string socket s = - match socket.socket with - | None -> - failwith "no socket" (* TODO: reconnect? *) - | Some socket -> - let l = String.length s in - assert (l < 0xFFFF); - let buf = Bytes.make 2 ' ' in - Bytes.set buf 0 (Char.unsafe_chr l); - Bytes.set buf 1 (Char.unsafe_chr (l lsr 8)); - ignore(send socket buf 0 2 []); - ignore(send socket (Bytes.unsafe_of_string s) 0 (String.length s) []) -end - -(* Printing *) - - -let print_json socket json = - let b = Buffer.create 0 in - write_json (Buffer.add_string b) json; - Transport.send_string socket (Buffer.contents b) - -let output_event socket event data = - print_json socket (JsonRpc.notification event data) - -let var_to_json name value access = - let jv t v structured = - JObject ["name",JString name;"type",JString t;"value",JString v;"structured",JBool structured;"access",JString access] + fields + in + JObject fields in - let string_repr s = "\"" ^ (Ast.s_escape (Lazy.force s)) ^ "\"" in - let level2_value_repr = function + let string_repr s = "\"" ^ (StringHelper.s_escape s.sstring) ^ "\"" in + let rec level2_value_repr = function | VNull -> "null" | VTrue -> "true" | VFalse -> "false" @@ -146,70 +50,100 @@ let var_to_json name value access = | vl -> name ^ "(...)" end | VObject o -> "{...}" - | VString(_,s) -> string_repr s + | VString s -> string_repr s | VArray _ | VVector _ -> "[...]" - | VInstance vi -> (rev_hash_s vi.iproto.ppath) ^ " {...}" - | VPrototype proto -> Rope.to_string (s_proto_kind proto) + | VInstance vi -> (rev_hash vi.iproto.ppath) ^ " {...}" + | VPrototype proto -> (s_proto_kind proto).sstring | VFunction _ | VFieldClosure _ -> "" + | VLazy f -> level2_value_repr (!f()) in let fields_string fields = - let l = List.map (fun (name, value) -> Printf.sprintf "%s: %s" (rev_hash_s name) (level2_value_repr value)) fields in + let l = List.map (fun (name, value) -> Printf.sprintf "%s: %s" (rev_hash name) (level2_value_repr value)) fields in Printf.sprintf "{%s}" (String.concat ", " l) in let array_elems l = let l = List.map level2_value_repr l in Printf.sprintf "[%s]" (String.concat ", " l) in - let value_string v = match v with - | VNull -> jv "NULL" "null" false - | VTrue -> jv "Bool" "true" false - | VFalse -> jv "Bool" "false" false - | VInt32 i -> jv "Int" (Int32.to_string i) false - | VFloat f -> jv "Float" (string_of_float f) false + let rec value_string v = match v with + | VNull -> jv "NULL" "null" 0 + | VTrue -> jv "Bool" "true" 0 + | VFalse -> jv "Bool" "false" 0 + | VInt32 i -> jv "Int" (Int32.to_string i) 0 + | VFloat f -> jv "Float" (string_of_float f) 0 | VEnumValue ve -> - let type_s = rev_hash_s ve.epath in + let type_s = rev_hash ve.epath in let name = EvalPrinting.s_enum_ctor_name ve in - let value_s,is_structured = match ve.eargs with - | [||] -> name, false + let value_s = match ve.eargs with + | [||] -> name | vl -> let l = Array.to_list (Array.map level2_value_repr vl) in let s = Printf.sprintf "%s(%s)" name (String.concat ", " l) in - s, true + s in - jv type_s value_s is_structured - | VObject o -> jv "Anonymous" (fields_string (object_fields o)) true (* TODO: false for empty structures *) - | VString(_,s) -> jv "String" (string_repr s) false - | VArray va -> jv "Array" (array_elems (EvalArray.to_list va)) true (* TODO: false for empty arrays *) - | VVector vv -> jv "Vector" (array_elems (Array.to_list vv)) true + jv type_s value_s (Array.length ve.eargs) + | VObject o -> + begin try + let e = (get_ctx()).curapi.MacroApi.decode_expr v in + jv "Expr" (Ast.Printer.s_expr e) 2 + with _ -> + let fields = object_fields o in + jv "Anonymous" (fields_string fields) (List.length fields) + end + | VString s -> + jv "String" (string_repr s) 2 + | VArray va -> jv "Array" (array_elems (EvalArray.to_list va)) va.alength + | VVector vv -> jv "Vector" (array_elems (Array.to_list vv)) (Array.length vv) | VInstance vi -> - let class_name = rev_hash_s vi.iproto.ppath in - jv class_name (class_name ^ " " ^ (fields_string (instance_fields vi))) true - | VPrototype proto -> jv "Anonymous" (Rope.to_string (s_proto_kind proto)) false (* TODO: show statics *) - | VFunction _ | VFieldClosure _ -> jv "Function" "" false + let class_name () = EvalDebugMisc.safe_call env.env_eval EvalPrinting.value_string v in + let num_children,class_name = match vi.ikind with + | IMutex _ -> 1,class_name() + | IThread _ -> 1,class_name() + | IBytes bytes -> + let max = 40 in + let s = Bytes.to_string bytes in + let s = (try String.sub s 0 max ^ "..." with Invalid_argument _ -> s) in + List.length (instance_fields vi),s + | _ -> List.length (instance_fields vi),class_name() + in + let num_children = match vi.ikind with + | IMutex _ -> 1 + | IThread _ -> 1 + | _ -> List.length (instance_fields vi) + in + jv class_name (class_name) num_children + | VPrototype proto -> + let fields = proto_fields proto in + jv "Anonymous" (s_proto_kind proto).sstring (List.length fields) + | VFunction _ | VFieldClosure _ -> jv "Function" "" 0 + | VLazy f -> value_string (!f()) in value_string value -let get_call_stack_envs ctx kind p = - let envs = match call_stack ctx with - | _ :: envs -> envs - | [] -> [] - in +let get_call_stack_envs eval p = + let envs = call_stack eval in let rec loop delta envs = match envs with | _ :: envs when delta < 0 -> loop (delta + 1) envs | _ -> envs in - loop ctx.debug.environment_offset_delta envs + loop 0 envs -let output_call_stack ctx kind p = - let envs = get_call_stack_envs ctx kind p in - let id = ref (-1) in - let stack_item kind p artificial = - incr id; +let output_call_stack ctx eval p = + let envs = get_call_stack_envs eval p in + let stack_item env p = + let id = ctx.debug.debug_context#add_stack_frame env in + let kind = env.env_info.kind in let line1,col1,line2,col2 = Lexer.get_pos_coords p in + let path = Path.get_real_path p.pfile in + let artificial,name = match kind with + | EKMethod _ | EKLocalFunction _ -> false,kind_name eval kind + | EKEntrypoint -> true,p.pfile + in + let source = if Sys.file_exists path then JString path else JNull in JObject [ - "id",JInt !id; - "name",JString (kind_name (get_eval ctx) kind); - "source",JString (Path.get_real_path p.pfile); + "id",JInt id; + "name",JString name; + "source",source; "line",JInt line1; "column",JInt col1; "endLine",JInt line2; @@ -217,14 +151,27 @@ let output_call_stack ctx kind p = "artificial",JBool artificial; ] in - let l = [stack_item kind p false] in - let stack = List.fold_left (fun acc env -> - let p = {pmin = env.env_leave_pmin; pmax = env.env_leave_pmax; pfile = rev_file_hash env.env_info.pfile} in - (stack_item env.env_info.kind p (env.env_leave_pmin < 0)) :: acc - ) l envs in + let _,stack = List.fold_left (fun (first,acc) env -> + let p = if first then p else {pmin = env.env_leave_pmin; pmax = env.env_leave_pmax; pfile = rev_hash env.env_info.pfile} in + false,((stack_item env p) :: acc) + ) (true,[]) envs in JArray (List.rev stack) -let output_scopes capture_infos scopes = +let output_threads ctx = + let fold id eval acc = + (JObject [ + "id",JInt id; + "name",JString (Printf.sprintf "Thread %i" (Thread.id eval.thread.tthread)); + ]) :: acc + in + let threads = IntMap.fold fold ctx.evals [] in + JArray threads + +let is_simn = false + +let output_scopes ctx env = + let capture_infos = env.env_info.capture_infos in + let scopes = env.env_debug.scopes in let mk_scope id name pos = let fl = ["id",JInt id; "name",JString name] in let fl = @@ -242,330 +189,608 @@ let output_scopes capture_infos scopes = in JObject fl in - let _,scopes = List.fold_left (fun (id,acc) scope -> + let scopes = List.fold_left (fun acc scope -> if Hashtbl.length scope.local_infos <> 0 then - (id + 1), (mk_scope id "Locals" scope.pos) :: acc + (mk_scope (ctx.debug.debug_context#add_scope scope env) "Locals" scope.pos) :: acc else - (id + 1), acc - ) (1,[]) scopes in + acc + ) [] scopes in + let scopes = if not is_simn then + scopes + else begin + let dbg = { + ds_expr = env.env_debug.expr; + ds_return = env.env_eval.last_return; + } in + (mk_scope (ctx.debug.debug_context#add_debug_scope dbg env) "Eval" null_pos) :: scopes + end in let scopes = List.rev scopes in - let scopes = if Hashtbl.length capture_infos = 0 then scopes else (mk_scope 0 "Captures" null_pos) :: scopes in + let scopes = if Hashtbl.length capture_infos = 0 then scopes else (mk_scope (ctx.debug.debug_context#add_capture_scope capture_infos env) "Captures" null_pos) :: scopes in JArray scopes -let output_capture_vars env = - let infos = env.env_info.capture_infos in - let vars = Hashtbl.fold (fun slot name acc -> - let value = !(env.env_captures.(slot)) in - (var_to_json name value name) :: acc +let output_capture_vars infos env = + let vars = Hashtbl.fold (fun slot vi acc -> + let value = (env.env_captures.(slot)) in + (var_to_json vi.vi_name value (Some vi) env) :: acc ) infos [] in JArray vars +let output_debug_scope dbg env = + let ja = [ + var_to_json "expr" (VString (EvalString.create_ascii (Type.s_expr_pretty true "" false (s_type (print_context())) env.env_debug.expr))) None env; + var_to_json "last return" (match dbg.ds_return with None -> vnull | Some v -> v) None env; + ] in + JArray ja + let output_scope_vars env scope = - let vars = Hashtbl.fold (fun local_slot name acc -> - let slot = local_slot + scope.local_offset in - let value = env.env_locals.(slot) in - (var_to_json name value name) :: acc + let p = env.env_debug.expr.epos in + let vars = Hashtbl.fold (fun local_slot vi acc -> + if declared_before vi p then begin + let slot = local_slot + scope.local_offset in + let value = env.env_locals.(slot) in + (var_to_json vi.vi_name value (Some vi) env) :: acc + end else + acc ) scope.local_infos [] in JArray vars -let output_inner_vars v access = - let children = match v with +let output_inner_vars v env = + let rec loop v = match v with | VNull | VTrue | VFalse | VInt32 _ | VFloat _ | VFunction _ | VFieldClosure _ -> [] | VEnumValue ve -> - begin match ve.eargs with - | [||] -> [] - | vl -> - Array.to_list (Array.mapi (fun i v -> - let n = Printf.sprintf "[%d]" i in - let a = access ^ n in - n, v, a - ) vl) + begin match (get_static_prototype_raise (get_ctx()) ve.epath).pkind with + | PEnum names -> + let fields = snd (List.nth names ve.eindex) in + List.mapi (fun i n -> + let n = rev_hash n in + let v = ve.eargs.(i) in + n, v + ) fields + | _ -> [] end | VObject o -> let fields = object_fields o in List.map (fun (n,v) -> - let n = rev_hash_s n in - let a = access ^ "." ^ n in - n, v, a + let n = rev_hash n in + n, v ) fields - | VString(_,s) -> [] + | VString s -> + let _,l = List.fold_left (fun (i,acc) (cr_index,br_offset) -> + (i + 1),(Printf.sprintf "index%i" i,vint !cr_index) :: + (Printf.sprintf "offset%i" i,vint !br_offset) :: + acc + ) (0,[]) (List.rev s.soffsets) in + ("length",vint s.slength) :: + ("byteLength",vint (String.length s.sstring)) :: + l | VArray va -> let l = EvalArray.to_list va in List.mapi (fun i v -> let n = Printf.sprintf "[%d]" i in - let a = access ^ n in - n, v, a + n, v ) l | VVector vv -> let l = Array.to_list vv in List.mapi (fun i v -> let n = Printf.sprintf "[%d]" i in - let a = access ^ n in - n, v, a + n, v ) l + | VInstance {ikind = IStringMap h} -> + StringHashtbl.fold (fun s (_,v) acc -> + (s,v) :: acc + ) h [] + | VInstance {ikind = IMutex mutex} -> + ["owner",match mutex.mowner with None -> vnull | Some id -> vint id] + | VInstance {ikind = IThread thread} -> + ["id",vint (Thread.id thread.tthread)] | VInstance vi -> let fields = instance_fields vi in List.map (fun (n,v) -> - let n = rev_hash_s n in - let a = access ^ "." ^ n in - n, v, a + let n = rev_hash n in + n, v + ) fields + | VPrototype proto -> + let fields = proto_fields proto in + List.map (fun (n,v) -> + let n = rev_hash n in + n, v ) fields - | VPrototype proto -> [] (* TODO *) + | VLazy f -> loop (!f()) in - let vars = List.map (fun (n,v,a) -> var_to_json n v a) children in + let children = loop v in + let vars = List.map (fun (n,v) -> var_to_json n v None env) children in JArray vars -type command_outcome = - | Loop of Json.t - | Run of Json.t * EvalContext.env - | Wait of Json.t * EvalContext.env +let handle_in_temp_thread ctx env f = + let channel = Event.new_channel () in + let _ = EvalThread.spawn ctx (fun () -> + let eval = get_eval ctx in + eval.env <- Some env; + let v = try + f() + with + | RunTimeException(v,stack,p) -> + prerr_endline (EvalExceptions.get_exc_error_message ctx v stack p); + vnull + | exc -> + prerr_endline (Printexc.to_string exc); + vnull + in + Event.poll (Event.send channel v) + ) in + Event.sync (Event.receive channel) + +module ValueCompletion = struct + let prototype_instance_fields proto = + let rec loop acc proto = + let acc = match proto.pparent with + | None -> acc + | Some proto -> loop acc proto + in + let acc = IntMap.fold (fun name _ acc -> IntMap.add name (name,"field",None) acc) proto.pinstance_names acc in + IntMap.fold (fun name _ acc -> IntMap.add name (name,"method",None) acc) proto.pnames acc + in + loop IntMap.empty proto + let prototype_static_fields proto = + IntMap.fold (fun name _ acc -> IntMap.add name (name,"field",None) acc) proto.pnames IntMap.empty -let make_connection socket = - (* Reads input and reacts accordingly. *) - let rec wait ctx run env = - let get_real_env ctx = - ctx.debug.environment_offset_delta <- 0; - DynArray.get (get_eval ctx).environments ((get_eval ctx).environment_offset - 1); + + let to_json l = + JArray (List.map (fun (n,k,column) -> + let fields = ["label",JString (rev_hash n);"kind",JString k] in + let fields = match column with None -> fields | Some column -> ("start",JInt column) :: fields in + JObject fields + ) l) + + let collect_idents ctx env = + let acc = Hashtbl.create 0 in + let add key = + if not (Hashtbl.mem acc key) then + Hashtbl.add acc key (key,"value",None) in - let rec loop () = - let handle_request id name params = - let error msg = - let open JsonRpc in - raise (JsonRpc_error (Custom (id, 1, msg))) - in - let invalid_params () = - let open JsonRpc in - raise (JsonRpc_error (Invalid_params id)) - in - let rec move_frame offset = - if offset < 0 || offset >= (get_eval ctx).environment_offset then begin - error (Printf.sprintf "Frame out of bounds: %i (valid range is %i - %i)" offset 0 ((get_eval ctx).environment_offset - 1)) - end else begin - ctx.debug.environment_offset_delta <- ((get_eval ctx).environment_offset - offset - 1); - Wait (JNull, (DynArray.get (get_eval ctx).environments offset)) - end - in - match name with - | "continue" -> - let env = get_real_env ctx in - ctx.debug.debug_state <- (if ctx.debug.debug_state = DbgStart then DbgRunning else DbgContinue); - Run (JNull,env) - | "stepIn" -> - let env = get_real_env ctx in - Run (JNull,env) - | "next" -> - let env = get_real_env ctx in - ctx.debug.debug_state <- DbgNext (get_eval ctx).environment_offset; - Run (JNull,env) - | "stepOut" -> - let env = get_real_env ctx in - ctx.debug.debug_state <- DbgFinish (get_eval ctx).environment_offset; - Run (JNull,env) - | "stackTrace" -> - Loop (output_call_stack ctx env.env_info.kind env.env_debug.expr.epos) - | "setBreakpoints" -> - let file, bps = - match params with - | Some (JObject fl) -> - let file = try List.find (fun (n,_) -> n = "file") fl with Not_found -> invalid_params () in - let file = match (snd file) with JString s -> s | _ -> invalid_params () in - let parse_breakpoint = function - | JObject fl -> - let line = try List.find (fun (n,_) -> n = "line") fl with Not_found -> invalid_params () in - let line = match (snd line) with JInt s -> s | _ -> invalid_params () in - let column = try Some (List.find (fun (n,_) -> n = "column") fl) with Not_found -> None in - let column = Option.map_default (fun (_,v) -> match v with JInt i -> BPColumn i | _ -> invalid_params ()) BPAny column in - line,column - | _ -> invalid_params () - in - let bps = try List.find (fun (n,_) -> n = "breakpoints") fl with Not_found -> invalid_params () in - let bps = match (snd bps) with JArray jl -> jl | _ -> invalid_params () in - let bps = List.map parse_breakpoint bps in - file, bps - | _ -> - invalid_params (); - in - let hash = hash_s (Path.unique_full_path (Common.find_file (ctx.curapi.get_com()) file)) in - let h = - try - let h = Hashtbl.find ctx.debug.breakpoints hash in - Hashtbl.clear h; - h - with Not_found -> - let h = Hashtbl.create (List.length bps) in - Hashtbl.add ctx.debug.breakpoints hash h; - h - in - let bps = List.map (fun (line,column) -> - let bp = make_breakpoint hash line BPEnabled column in - Hashtbl.add h line bp; - JObject ["id",JInt bp.bpid] - ) bps in - Loop (JArray bps) - | "setBreakpoint" -> - let file,line,column = - match params with - | Some (JObject fl) -> - let file = try List.find (fun (n,_) -> n = "file") fl with Not_found -> invalid_params () in - let file = match (snd file) with JString s -> s | _ -> invalid_params () in - let line = try List.find (fun (n,_) -> n = "line") fl with Not_found -> invalid_params () in - let line = match (snd line) with JInt s -> s | _ -> invalid_params () in - let column = try Some (List.find (fun (n,_) -> n = "column") fl) with Not_found -> None in - let column = Option.map_default (fun (_,v) -> match v with JInt i -> BPColumn i | _ -> invalid_params ()) BPAny column in - file,line,column - | _ -> - invalid_params (); - in - begin try - let breakpoint = add_breakpoint ctx file line column in - Loop (JObject ["id",JInt breakpoint.bpid]) - with Not_found -> - invalid_params (); - end - | "removeBreakpoint" -> - let id = - match params with - | Some (JObject fl) -> - let id = try List.find (fun (n,_) -> n = "id") fl with Not_found -> invalid_params () in - (match (snd id) with JInt s -> s | _ -> invalid_params ()) - | _ -> invalid_params () - in - begin try - Hashtbl.iter (fun _ h -> - let to_delete = ref [] in - Hashtbl.iter (fun k breakpoint -> if breakpoint.bpid = id then to_delete := k :: !to_delete) h; - List.iter (fun k -> Hashtbl.remove h k) !to_delete; - ) ctx.debug.breakpoints - with Not_found -> - error (Printf.sprintf "Unknown breakpoint: %d" id) - end; - Loop JNull - | "switchFrame" -> - let frame = - match params with - | Some (JObject fl) -> - let id = try List.find (fun (n,_) -> n = "id") fl with Not_found -> invalid_params () in - (match (snd id) with JInt s -> s | _ -> invalid_params ()) - | _ -> invalid_params () - in - move_frame ((get_eval ctx).environment_offset - frame - 1) - | "getScopes" -> - Loop (output_scopes env.env_info.capture_infos env.env_debug.scopes); - | "getScopeVariables" -> - let sid = - match params with - | Some (JObject fl) -> - let id = try List.find (fun (n,_) -> n = "id") fl with Not_found -> invalid_params () in - (match (snd id) with JInt s -> s | _ -> invalid_params ()) - | _ -> invalid_params () - in - begin - let vars = - try - if sid = 0 then begin - output_capture_vars env - end else begin - let scope = try List.nth env.env_debug.scopes (sid - 1) with _ -> raise Exit in - output_scope_vars env scope - end - with Exit -> - error "Invalid scope id" - in - Loop vars - end - | "getStructure" -> - let e = - match params with - | Some (JObject fl) -> - let id = try List.find (fun (n,_) -> n = "expr") fl with Not_found -> invalid_params () in - (match (snd id) with JString s -> s | _ -> invalid_params ()) - | _ -> invalid_params () - in - begin try - let e = parse_expr ctx e env.env_debug.expr.epos in - begin try - let access,v = expr_to_value ctx env e in - Loop (output_inner_vars v access) - with Exit -> - error ("Don't know how to handle this expression: " ^ (Ast.s_expr e)) - end - with Parse_expr_error e -> - error e - end - | "setVariable" -> - let expr_s,value = - match params with - | Some (JObject fl) -> - let expr = try List.find (fun (n,_) -> n = "expr") fl with Not_found -> invalid_params () in - let expr = match (snd expr) with JString s -> s | _ -> invalid_params () in - let value = try List.find (fun (n,_) -> n = "value") fl with Not_found -> invalid_params () in - let value = match (snd value) with JString s -> s | _ -> invalid_params () in - expr,value - | _ -> - invalid_params (); - in - let parse s = parse_expr ctx s env.env_debug.expr.epos in - begin try - let expr,value = parse expr_s,parse value in - begin try - let _,value = expr_to_value ctx env value in - begin match fst expr with - (* TODO: support setting array elements and enum values *) - | EField(e1,s) -> - let _,v1 = expr_to_value ctx env e1 in - set_field v1 (hash_s s) value; - Loop (var_to_json s value expr_s) - | EConst (Ident s) -> - begin try - let slot = get_var_slot_by_name env.env_debug.scopes s in - env.env_locals.(slot) <- value; - Loop (var_to_json name value s) - with Not_found -> - error ("No variable found: " ^ s); - end - | _ -> - raise Exit - end - with Exit -> - error "Don't know how to handle this expression" - end - with Parse_expr_error e -> - error e - end - | meth -> - let open JsonRpc in - raise (JsonRpc_error (Method_not_found (id, meth))) + (* 0. Extra locals *) + IntMap.iter (fun key _ -> add key) env.env_extra_locals; + (* 1. Variables *) + let rec loop scopes = match scopes with + | scope :: scopes -> + Hashtbl.iter (fun key _ -> add (hash key)) scope.local_ids; + loop scopes + | [] -> + () + in + loop env.env_debug.scopes; + (* 2. Captures *) + Hashtbl.iter (fun slot vi -> + add (hash vi.vi_name) + ) env.env_info.capture_infos; + (* 3. Instance *) + if not env.env_info.static then begin + let v = env.env_locals.(0) in + begin match v with + | VInstance vi -> + let fields = prototype_instance_fields vi.iproto in + IntMap.iter (fun key _ -> add key) fields + | _ -> + () + end + end; + (* 4. Static *) + begin match env.env_info.kind with + | EKMethod(i1,_) -> + let proto = get_static_prototype_raise ctx i1 in + let fields = prototype_static_fields proto in + IntMap.iter (fun key _ -> add key) fields + | _ -> + raise Not_found + end; + (* 5. Toplevel *) + begin match ctx.toplevel with + | VObject o -> + let fields = object_fields o in + List.iter (fun (n,_) -> add n) fields + | _ -> + () + end; + to_json (Hashtbl.fold (fun _ v acc -> v :: acc) acc []) + + let output_completion ctx column v = + let field_value_kind v = match v with + | VFunction _ | VFieldClosure _ -> "function" + | _ -> "field" + in + let rec loop v = match v with + | VNull | VTrue | VFalse | VInt32 _ | VFloat _ | VFunction _ | VFieldClosure _ -> + [] + | VObject o -> + let fields = object_fields o in + List.map (fun (n,v) -> + n,(field_value_kind v),None + ) fields + | VInstance vi -> + let fields = prototype_instance_fields vi.iproto in + IntMap.fold (fun _ v acc -> v :: acc) fields [] + | VString _ -> + let fields = prototype_instance_fields ctx.string_prototype in + IntMap.fold (fun _ v acc -> v :: acc) fields [key_length,"field",None] + | VArray _ -> + let fields = prototype_instance_fields ctx.array_prototype in + IntMap.fold (fun _ v acc -> v :: acc) fields [key_length,"field",None] + | VVector _ -> + let fields = prototype_instance_fields ctx.vector_prototype in + IntMap.fold (fun _ v acc -> v :: acc) fields [key_length,"field",None] + | VPrototype proto -> + let fields = prototype_static_fields proto in + IntMap.fold (fun _ v acc -> v :: acc) fields [] + | VLazy f -> + loop (!f()) + | VEnumValue ve -> + begin match (get_static_prototype_raise (get_ctx()) ve.epath).pkind with + | PEnum names -> + let fields = snd (List.nth names ve.eindex) in + List.map (fun n -> n,"value",None) fields + | _ -> [] + end + in + let l = loop v in + to_json l + + exception JsonException of Json.t + + let get_completion ctx text column env = + let p = { pmin = 0; pmax = 0; pfile = "" } in + let save = + let old = !Parser.display_mode,DisplayPosition.display_position#get in + (fun () -> + Parser.display_mode := fst old; + DisplayPosition.display_position#set (snd old); + ) + in + Parser.display_mode := DMDefault; + let offset = column + (String.length "class X{static function main() ") - 1 (* this is retarded *) in + DisplayPosition.display_position#set {p with pmin = offset; pmax = offset}; + begin try + let e = parse_expr ctx text p in + let e = Display.ExprPreprocessing.find_before_pos DMDefault e in + save(); + let rec loop e = match fst e with + | EDisplay(e1,DKDot) -> + let v = handle_in_temp_thread ctx env (fun () -> expr_to_value ctx env e1) in + let json = output_completion ctx column v in + raise (JsonException json) + | EArray(e1,(EDisplay((EConst (Ident "null"),_),DKMarked),_)) -> + let v = handle_in_temp_thread ctx env (fun () -> expr_to_value ctx env e1) in + begin match v with + | VArray va -> + let l = EvalArray.to_list va in + let l = List.mapi (fun i v -> + let n = Printf.sprintf "%d" i in + (hash n),"value",Some column + ) l in + raise (JsonException (to_json l)) + | _ -> + raise Exit + end + | EDisplay(e1,DKMarked) -> + let json = collect_idents ctx env in + raise (JsonException json) + | _ -> + Ast.iter_expr loop e in - let process_outcome id outcome = - let output j = print_json socket (JsonRpc.result id j) in - match outcome with - | Loop result -> - output result; - loop () - | Run (result,env) -> - output result; - run env - | Wait (result,env) -> - output result; - wait ctx run env; + begin try + loop e; + raise Exit + with + | JsonException json -> + json + end + with _ -> + save(); + raise Exit + end; + +end + +type handler_context = { + ctx : context; + jsonrpc : Jsonrpc_handler.jsonrpc_handler; + send_error : 'a . string -> 'a; +} + +let expect_env hctx env = match env with + | Some env -> env + | None -> hctx.send_error "No frame found" + +let handler = + let parse_breakpoint hctx jo = + let j = hctx.jsonrpc in + let obj = j#get_object "breakpoint" jo in + let line = j#get_int_field "line" "line" obj in + let column = j#get_opt_param (fun () -> BPColumn (j#get_int_field "column" "column" obj)) BPAny in + let condition = j#get_opt_param (fun () -> + let s = j#get_string_field "condition" "condition" obj in + Some (parse_expr hctx.ctx s null_pos) + ) None in + (line,column,condition) + in + let select_frame hctx = + let frame_id = hctx.jsonrpc#get_int_param "frameId" in + let env = match hctx.ctx.debug.debug_context#get frame_id with + | StackFrame env -> env + | _ -> hctx.send_error (Printf.sprintf "Bad frame ID: %i" frame_id); + in + env + in + let select_thread hctx = + let id = hctx.jsonrpc#get_opt_param (fun () -> hctx.jsonrpc#get_int_param "threadId") 0 in + let eval = try IntMap.find id hctx.ctx.evals with Not_found -> hctx.send_error "Invalid thread id" in + eval + in + let h = Hashtbl.create 0 in + let l = [ + "pause",(fun hctx -> + let eval = select_thread hctx in + eval.debug_state <- DbgWaiting; + JNull + ); + "continue",(fun hctx -> + let eval = select_thread hctx in + eval.debug_state <- DbgRunning; + ignore(Event.poll (Event.send eval.debug_channel ())); + JNull + ); + "stepIn",(fun hctx -> + let eval = select_thread hctx in + eval.debug_state <- DbgStep; + ignore(Event.poll (Event.send eval.debug_channel ())); + JNull + ); + "next",(fun hctx -> + let eval = select_thread hctx in + let env = expect_env hctx eval.env in + eval.debug_state <- DbgNext(env,env.env_debug.expr.epos); + ignore(Event.poll (Event.send eval.debug_channel ())); + JNull + ); + "stepOut",(fun hctx -> + let eval = select_thread hctx in + let env = expect_env hctx eval.env in + let penv = expect_env hctx env.env_parent in + eval.debug_state <- DbgFinish penv; + ignore(Event.poll (Event.send eval.debug_channel ())); + JNull + ); + "getThreads",(fun hctx -> + output_threads hctx.ctx + ); + "stackTrace",(fun hctx -> + let eval = select_thread hctx in + let env = expect_env hctx eval.env in + output_call_stack hctx.ctx eval env.env_debug.expr.epos + ); + "getScopes",(fun hctx -> + let env = select_frame hctx in + output_scopes hctx.ctx env + ); + "getVariables",(fun hctx -> + let sid = hctx.jsonrpc#get_int_param "id" in + begin + let vars = + try + begin + let scope = hctx.ctx.debug.debug_context#get sid in + match scope with + | Scope(scope,env) -> + output_scope_vars env scope + | CaptureScope(infos,env) -> + output_capture_vars infos env + | DebugScope(dbg,env) -> + output_debug_scope dbg env + | Value(value,env) -> + output_inner_vars value env + | Toplevel | StackFrame _ | NoSuchReference -> + hctx.send_error (Printf.sprintf "Bad ID: %i" sid); + end + with Exit -> + hctx.send_error "Invalid scope id" + in + vars + end + ); + "setBreakpoints",(fun hctx -> + let file = hctx.jsonrpc#get_string_param "file" in + let bps = hctx.jsonrpc#get_array_param "breakpoints" in + let bps = List.map (parse_breakpoint hctx) bps in + let hash = hash (Path.unique_full_path (Common.find_file (hctx.ctx.curapi.get_com()) file)) in + let h = + try + let h = Hashtbl.find hctx.ctx.debug.breakpoints hash in + Hashtbl.clear h; + h + with Not_found -> + let h = Hashtbl.create (List.length bps) in + Hashtbl.add hctx.ctx.debug.breakpoints hash h; + h in - let send_output_and_continue json = - print_json socket json; - loop (); + let bps = List.map (fun (line,column,condition) -> + let bp = make_breakpoint hash line BPEnabled column condition in + Hashtbl.add h line bp; + JObject ["id",JInt bp.bpid] + ) bps in + JArray bps + ); + "setBreakpoint",(fun hctx -> + let line,column,condition = parse_breakpoint hctx (hctx.jsonrpc#get_params) in + let file = hctx.jsonrpc#get_string_param "file" in + let breakpoint = add_breakpoint hctx.ctx file line column condition in + JObject ["id",JInt breakpoint.bpid] + ); + "setFunctionBreakpoints",(fun hctx -> + Hashtbl.clear hctx.ctx.debug.function_breakpoints; + let j = hctx.jsonrpc in + let bps = j#get_array "param" (j#get_params) in + let bps = List.map (fun jo -> + let obj = j#get_object "breakpoint" jo in + let name = j#get_string_field "name" "name" obj in + let i = String.rindex name '.' in + if i < 0 then hctx.send_error "Invalid format, expected Type.field"; + let key_type = String.sub name 0 i in + let key_field = String.sub name (i + 1) (String.length name - i - 1) in + let bp = make_function_breakpoint BPEnabled in + Hashtbl.add hctx.ctx.debug.function_breakpoints (hash key_type,hash key_field) bp; + JObject ["id",JInt bp.fbpid] + ) bps in + JArray bps + ); + "removeBreakpoint",(fun hctx -> + let id = hctx.jsonrpc#get_int_param "id" in + begin try + Hashtbl.iter (fun _ h -> + let to_delete = ref [] in + Hashtbl.iter (fun k breakpoint -> if breakpoint.bpid = id then to_delete := k :: !to_delete) h; + List.iter (fun k -> Hashtbl.remove h k) !to_delete; + ) hctx.ctx.debug.breakpoints; + with Not_found -> + hctx.send_error (Printf.sprintf "Unknown breakpoint: %d" id) + end; + JNull + ); + "setVariable",(fun hctx -> + let id = hctx.jsonrpc#get_int_param "id" in + let name = hctx.jsonrpc#get_string_param "name" in + let value = hctx.jsonrpc#get_string_param "value" in + let get_value env = try + let e = parse_expr hctx.ctx value env.env_debug.expr.epos in + expr_to_value hctx.ctx env e + with Parse_expr_error e -> + hctx.send_error e in - JsonRpc.handle_jsonrpc_error (fun () -> JsonRpc.process_request (Transport.read_string socket) handle_request process_outcome) send_output_and_continue; - in - loop () + begin match hctx.ctx.debug.debug_context#get id with + | Toplevel | NoSuchReference -> + hctx.send_error (Printf.sprintf "Bad ID: %i" id); + | Value(v,env) -> + let value = get_value env in + let name_as_index () = try + (* The name is [1] so we have to extract the number. This is quite stupid but not really our fault... *) + int_of_string (String.sub name 1 (String.length name - 2)) + with _ -> + hctx.send_error "integer expected" + in + begin match v with + | VArray va -> EvalArray.set va (name_as_index()) value + | VVector vv -> Array.set vv (name_as_index()) value + | _ -> + set_field v (hash name) value; + end; + var_to_json "" value None env + | Scope(scope,env) -> + let value = get_value env in + let id = Hashtbl.find scope.local_ids name in + let slot = Hashtbl.find scope.locals id in + env.env_locals.(slot + scope.local_offset) <- value; + var_to_json "" value None env + | CaptureScope(infos,env) -> + let value = get_value env in + let slot = get_capture_slot_by_name infos name in + env.env_captures.(slot) <- value; + var_to_json "" value None env + | DebugScope _ | StackFrame _ -> + JNull + end + ); + "setExceptionOptions",(fun hctx -> + let sl = hctx.jsonrpc#get_array "" hctx.jsonrpc#get_params in + let sl = List.map (hctx.jsonrpc#get_string "") sl in + hctx.ctx.debug.exception_mode <- if List.mem "all" sl then CatchAll + else if List.mem "uncaught" sl then CatchUncaught + else CatchNone; + JNull + ); + "evaluate",(fun hctx -> + let ctx = hctx.ctx in + let env = try select_frame hctx with _ -> expect_env hctx ctx.eval.env in + let s = hctx.jsonrpc#get_string_param "expr" in + begin try + let e = parse_expr ctx s env.env_debug.expr.epos in + let v = handle_in_temp_thread ctx env (fun () -> expr_to_value ctx env e) in + var_to_json "" v None env + with + | Parse_expr_error e -> + hctx.send_error e + | Exit -> + hctx.send_error "Don't know how to handle this expression" + end + ); + "getCompletion",(fun hctx -> + let env = expect_env hctx hctx.ctx.eval.env in + let text = hctx.jsonrpc#get_string_param "text" in + let column = hctx.jsonrpc#get_int_param "column" in + try + ValueCompletion.get_completion hctx.ctx text column env + with Exit -> + hctx.send_error "No completion point found"; + ); + ] in + List.iter (fun (s,f) -> Hashtbl.add h s f) l; + h + +let make_connection socket = + let output_thread_event thread_id reason = + send_event socket "threadEvent" (Some (JObject ["threadId",JInt thread_id;"reason",JString reason])) in - let output_breakpoint_stop _ _ = - output_event socket "breakpointStop" None + let output_breakpoint_stop debug = + (* TODO: this isn't thread-safe. We should only creates these anew if all threads continued *) + debug.debug_context <- new eval_debug_context; + send_event socket "breakpointStop" (Some (JObject ["threadId",JInt (Thread.id (Thread.self()))])) in - let output_exception_stop _ v _ = - output_event socket "exceptionStop" (Some (JObject ["text",JString (value_string v)])) + let output_exception_stop debug v _ = + debug.debug_context <- new eval_debug_context; + send_event socket "exceptionStop" (Some (JObject ["threadId",JInt (Thread.id (Thread.self()));"text",JString (value_string v)])) + in + let rec wait () : unit = + let rec process_outcome id outcome = + let output j = send_json socket (JsonRpc.result id j) in + output outcome; + loop () + and send_output_and_continue json = + send_json socket json; + loop () + and send_output_and_exit json = + send_json socket json; + raise Exit + and loop () = + let input = Socket.read_string socket in + let input = + JsonRpc.handle_jsonrpc_error (fun () -> JsonRpc.parse_request input) send_output_and_exit + in + let jsonrpc = new Jsonrpc_handler.jsonrpc_handler input in + let error msg = + let open JsonRpc in + raise (JsonRpc_error (Custom (jsonrpc#get_id, 1, msg))) + in + let hctx = { + ctx = get_ctx(); + jsonrpc = jsonrpc; + send_error = error; + } in + JsonRpc.handle_jsonrpc_error (fun () -> + let method_name = jsonrpc#get_method_name in + let f = try + Hashtbl.find handler method_name + with Not_found -> + JsonRpc.raise_method_not_found jsonrpc#get_id method_name + in + process_outcome jsonrpc#get_id (f hctx) + ) send_output_and_continue + in + try + loop () + with Exit -> + loop () in + ignore(Thread.create wait ()); { - wait = wait; bp_stop = output_breakpoint_stop; exc_stop = output_exception_stop; + send_thread_event = output_thread_event; } diff --git a/src/macro/eval/evalDecode.ml b/src/macro/eval/evalDecode.ml index 23a0732e9bb..c2caf823de5 100644 --- a/src/macro/eval/evalDecode.ml +++ b/src/macro/eval/evalDecode.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,7 +21,7 @@ open Globals open EvalValue open EvalExceptions -let decode_object v = match v with +let decode_object v = match vresolve v with | VObject o -> o | _ -> unexpected_value v "object" @@ -50,15 +50,11 @@ let decode_varray v = match v with | _ -> unexpected_value v "array" let decode_string v = match v with - | VString(r,s) -> Lazy.force s + | VString s -> s.sstring | _ -> unexpected_value v "string" -let decode_rope v = match v with - | VString(s,_) -> s - | _ -> unexpected_value v "string" - -let decode_rope_string v = match v with - | VString(r,s) -> r,s +let decode_vstring v = match v with + | VString s -> s | _ -> unexpected_value v "string" let decode_bytes v = match v with diff --git a/src/macro/eval/evalEmitter.ml b/src/macro/eval/evalEmitter.ml index 2ebc4ad0967..241f4e7a602 100644 --- a/src/macro/eval/evalEmitter.ml +++ b/src/macro/eval/evalEmitter.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,7 +18,6 @@ *) open Globals -open Ast open EvalHash open EvalValue open EvalEncode @@ -29,30 +28,48 @@ open EvalExceptions open EvalField open EvalMisc -type varacc = - | Local of int - | Env of int - (* Helper *) -let throw_string s p = - throw (encode_string s) p - -let invalid_binop op v1 v2 p = - throw_string (Printf.sprintf "Invalid operation: %s %s %s" (value_string v1) (s_binop op) (value_string v2)) p - let unexpected_value_p v s p = - let str = Printf.sprintf "Unexpected value %s, expected %s" (value_string v) s in + let str = match v with + | VNull -> "Null Access" + | _ -> Printf.sprintf "Unexpected value %s, expected %s" (value_string v) s + in throw_string str p +let as_array p = function + | VArray va -> va + | v -> unexpected_value_p v "Array" p + +let as_bytes p = function + | VInstance {ikind = IBytes s} -> s + | v -> unexpected_value_p v "Bytes" p + +let as_enum_value p = function + | VEnumValue ve -> ve + | v -> unexpected_value_p v "enum value" p + +let as_int p = function + | VInt32 i -> Int32.to_int i + | VFloat f -> int_of_float f + | v -> unexpected_value_p v "int" p + +let as_vector p = function + | VVector vv -> vv + | v -> unexpected_value_p v "Vector" p + let cannot_call v p = - throw (encode_string ("Cannot call " ^ (value_string v))) p + throw (EvalString.create_unknown ("Cannot call " ^ (value_string v))) p let decode_int_p v p = match v with | VInt32 i -> Int32.to_int i | VFloat f -> int_of_float f | _ -> unexpected_value_p v "int" p +let check_stack_depth env = + if env.env_stack_depth > (get_ctx()).max_stack_depth then + exc_string "Stack overflow" + (* Emitter *) let apply env exec = @@ -67,7 +84,7 @@ let emit_local_declaration i exec env = vnull let emit_capture_declaration i exec env = - env.env_captures.(i) <- ref (exec env); + env.env_captures.(i) <- exec env; vnull let emit_const v _ = v @@ -91,8 +108,6 @@ let emit_object_declaration proto fa env = vobject { ofields = a; oproto = proto; - oextra = IntMap.empty; - oremoved = IntMap.empty; } let emit_array_declaration execs env = @@ -107,41 +122,8 @@ let emit_mk_pos exec1 exec2 exec3 env = let max = exec3 env in encode_pos { pfile = decode_string file; pmin = decode_int min; pmax = decode_int max } -let emit_enum_construction0 key i p env = - encode_enum_value key i [||] p - -let emit_enum_construction1 key i exec1 p env = - let v1 = exec1 env in - encode_enum_value key i [|v1|] p - -let emit_enum_construction2 key i exec1 exec2 p env = - let v1 = exec1 env in - let v2 = exec2 env in - encode_enum_value key i [|v1;v2|] p - -let emit_enum_construction3 key i exec1 exec2 exec3 p env = - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - encode_enum_value key i [|v1;v2;v3|] p - -let emit_enum_construction4 key i exec1 exec2 exec3 exec4 p env = - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - let v4 = exec4 env in - encode_enum_value key i [|v1;v2;v3;v4|] p - -let emit_enum_construction5 key i exec1 exec2 exec3 exec4 exec5 p env = - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - let v4 = exec4 env in - let v5 = exec5 env in - encode_enum_value key i [|v1;v2;v3;v4;v5|] p - let emit_enum_construction key i execs p env = - encode_enum_value key i (Array.map (fun exec -> exec env) execs) p + encode_enum_value key i (Array.map (apply env) execs) p (* Branching *) @@ -150,25 +132,43 @@ let emit_if exec_cond exec_then exec_else env = | VTrue -> exec_then env | _ -> exec_else env -let emit_enum_switch_array exec cases exec_def p env = match exec env with - | VEnumValue ev -> - let i = ev.eindex in - if i >= Array.length cases || i < 0 then exec_def env - else (Array.unsafe_get cases i) env - | v -> - unexpected_value_p v "enum value" p +let emit_switch exec execs patterns exec_def env = + let v1 = exec env in + let rec loop v1 i = + if i >= Array.length patterns then exec_def env + else if List.exists (fun exec -> equals v1 (exec env)) patterns.(i) then + execs.(i) env + else + loop v1 (i + 1) + in + loop v1 0 -let emit_int_switch_array exec cases exec_def p env = match exec env with +let emit_int_switch_map exec cases exec_def p env = match exec env with | VInt32 i32 -> let i = Int32.to_int i32 in - if i >= Array.length cases || i < 0 then exec_def env - else (Array.unsafe_get cases i) env + begin try + (IntMap.find i cases) env + with Not_found -> + exec_def env + end | VNull -> exec_def env | v -> unexpected_value_p v "int" p -let emit_int_switch_array_shift shift exec cases exec_def p env = match exec env with +let emit_string_switch_map exec cases exec_def p env = match exec env with + | VString s -> + begin try + (PMap.find s.sstring cases) env + with Not_found -> + exec_def env + end + | VNull -> + exec_def env + | v -> + unexpected_value_p v "string" p + +let emit_int_switch_array shift exec cases exec_def p env = match exec env with | VInt32 i32 -> let i = Int32.to_int i32 + shift in if i >= Array.length cases || i < 0 then exec_def env @@ -178,132 +178,23 @@ let emit_int_switch_array_shift shift exec cases exec_def p env = match exec env | v -> unexpected_value_p v "int" p -let emit_int_switch_map exec cases exec_def p env = match exec env with - | VInt32 i32 -> - let i = Int32.to_int i32 in - begin try - (IntMap.find i cases) env - with Not_found -> - exec_def env - end - | v -> - unexpected_value_p v "int" p - -let emit_constant_switch exec execs constants exec_def env = - let v1 = exec env in - let rec loop v1 i = - if i >= Array.length constants then exec_def env - else if List.exists (fun v2 -> equals v1 v2) (Array.unsafe_get constants i) then - (Array.unsafe_get execs i) env - else - loop v1 (i + 1) - in - loop v1 0 - -let emit_switch exec execs patterns exec_def env = - let v1 = exec env in - let rec loop v1 i = - if i >= Array.length patterns then exec_def env - else if List.exists (fun exec -> equals v1 (exec env)) patterns.(i) then - execs.(i) env - else - loop v1 (i + 1) - in - loop v1 0 - -let emit_int_iterator slot exec1 exec2 p1 p2 env = - let i1 = decode_int_p (env.env_locals.(slot)) p1 in - let i2 = decode_int_p (exec1 env) p2 in - for i = i1 to i2 - 1 do - env.env_locals.(slot) <- vint i; - ignore(exec2 env); - done; - vnull - -let emit_int_iterator_continue slot exec1 exec2 p1 p2 env = - let i1 = decode_int_p (env.env_locals.(slot)) p1 in - let i2 = decode_int_p (exec1 env) p2 in - for i = i1 to i2 - 1 do - env.env_locals.(slot) <- vint i; - (try ignore(exec2 env) with Continue -> ()) - done; - vnull - -let emit_int_iterator_break slot exec1 exec2 p1 p2 env = - let i1 = decode_int_p (env.env_locals.(slot)) p1 in - let i2 = decode_int_p (exec1 env) p2 in - begin try - for i = i1 to i2 - 1 do - env.env_locals.(slot) <- vint i; - ignore(exec2 env); - done; - with Break -> - () - end; - vnull - -let emit_int_iterator_break_continue slot exec1 exec2 p1 p2 env = - let i1 = decode_int_p (env.env_locals.(slot)) p1 in - let i2 = decode_int_p (exec1 env) p1 in - begin try - for i = i1 to i2 - 1 do - env.env_locals.(slot) <- vint i; - (try ignore(exec2 env) with Continue -> ()) - done; - with Break -> - () - end; - vnull - -let emit_while_gte exec1 f exec2 env = - while (num (exec1 env) >= f) do exec2 env done; - vnull - let rec run_while_continue exec_cond exec_body env = try while is_true (exec_cond env) do exec_body env done; with Continue -> run_while_continue exec_cond exec_body env -let emit_while exec_cond exec_body env = - while is_true (exec_cond env) do exec_body env done; - vnull +let rec run_while exec_cond exec_body env = + while is_true (exec_cond env) do exec_body env done let emit_while_break exec_cond exec_body env = - begin try - while is_true (exec_cond env) do exec_body env done; - with Break -> - () - end; - vnull - -let emit_while_continue exec_cond exec_body env = - run_while_continue exec_cond exec_body env; + (try run_while_continue exec_cond exec_body env with Break -> ()); vnull let emit_while_break_continue exec_cond exec_body env = (try run_while_continue exec_cond exec_body env with Break -> ()); vnull -let emit_do_while exec_cond exec_body env = - ignore(exec_body env); - while is_true (exec_cond env) do exec_body env done; - vnull - -let emit_do_while_break exec_cond exec_body env = - begin try - ignore(exec_body env); - while is_true (exec_cond env) do exec_body env done; - with Break -> - () - end; - vnull - -let emit_do_while_continue exec_cond exec_body env = - (try ignore(exec_body env) with Continue -> ()); - run_while_continue exec_cond exec_body env; - vnull - let emit_do_while_break_continue exec_cond exec_body env = begin try ignore(exec_body env); run_while_continue exec_cond exec_body env @@ -315,293 +206,125 @@ let emit_do_while_break_continue exec_cond exec_body env = let emit_try exec catches env = let ctx = get_ctx() in - let eval = get_eval ctx in - let environment_offset = eval.environment_offset in + let eval = env.env_eval in if ctx.debug.support_debugger then begin - List.iter (fun (_,path,_) -> Hashtbl.add ctx.debug.caught_types path true) catches + List.iter (fun (_,path,_) -> Hashtbl.add eval.caught_types path true) catches end; let restore () = - List.iter (fun (_,path,_) -> Hashtbl.remove ctx.debug.caught_types path) catches + List.iter (fun (_,path,_) -> Hashtbl.remove eval.caught_types path) catches in let v = try - let v = exec env in + let v = handle_stack_overflow eval (fun() -> exec env) in restore(); v with RunTimeException(v,_,_) as exc -> + eval.caught_exception <- vnull; restore(); - build_exception_stack ctx environment_offset; - eval.environment_offset <- environment_offset; + build_exception_stack ctx env; + let rec loop () = match eval.env with + | Some env' when env' != env -> + pop_environment ctx env'; + loop(); + | _ -> + () + in + loop(); let exec,_,varacc = try - List.find (fun (_,path,i) -> is v path) catches + List.find (fun (_,path,i) -> path = key_Dynamic || is v path) catches with Not_found -> - raise exc + raise_notrace exc in - begin match varacc with - | Local slot -> env.env_locals.(slot) <- v - | Env slot -> env.env_captures.(slot) <- ref v - end; + varacc (fun _ -> v) env; exec env in v (* Control flow *) -let emit_block1 exec1 env = - exec1 env +let emit_value exec env = + exec env -let emit_block2 exec1 exec2 env = +let emit_seq2 exec1 exec2 env = ignore(exec1 env); exec2 env -let emit_block3 exec1 exec2 exec3 env = - ignore(exec1 env); - ignore(exec2 env); - exec3 env - -let emit_block4 exec1 exec2 exec3 exec4 env = - ignore(exec1 env); - ignore(exec2 env); - ignore(exec3 env); +let emit_seq4 exec1 exec2 exec3 exec4 env = + ignore (exec1 env); + ignore (exec2 env); + ignore (exec3 env); exec4 env -let emit_block5 exec1 exec2 exec3 exec4 exec5 env = - ignore(exec1 env); - ignore(exec2 env); - ignore(exec3 env); - ignore(exec4 env); - exec5 env - -let emit_block execs env = - let l = Array.length execs in - for i = 0 to l - 2 do - ignore((Array.unsafe_get execs i) env) - done; - (Array.unsafe_get execs (l -1)) env - -let emit_value exec env = - exec env +let emit_seq8 exec1 exec2 exec3 exec4 exec5 exec6 exec7 exec8 env = + ignore (exec1 env); + ignore (exec2 env); + ignore (exec3 env); + ignore (exec4 env); + ignore (exec5 env); + ignore (exec6 env); + ignore (exec7 env); + exec8 env -let emit_return_null _ = raise (Return vnull) +let emit_return_null _ = raise_notrace (Return vnull) -let emit_return_value exec env = raise (Return (exec env)) +let emit_return_value exec env = raise_notrace (Return (exec env)) -let emit_break env = raise Break +let emit_break env = raise_notrace Break -let emit_continue env = raise Continue +let emit_continue env = raise_notrace Continue let emit_throw exec p env = throw (exec env) p let emit_safe_cast exec t p env = let v1 = exec env in - if not (is v1 t) then throw_string "Class cast error" p; - v1 + match vresolve v1 with + | VNull -> v1 + | _ -> if not (is v1 t) then throw_string "Class cast error" p else v1 (* Calls *) (* super.call() - immediate *) let emit_super_field_call slot proto i execs p env = + check_stack_depth env; let vthis = env.env_locals.(slot) in let vf = proto.pfields.(i) in - let vl = List.map (fun f -> f env) execs in + let vl = List.map (apply env) execs in call_value_on vthis vf vl (* Type.call() - immediate *) -let call0 v p env = - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - match v with - | VFunction (Fun0 f,_) -> f () - | VFunction (FunN f,_) -> f [] - | VFieldClosure(v0,f) -> call_function f [v0] - | VInstance {ikind = ILazyType(_,get)} -> get() - | _ -> cannot_call v p - -let call1 v v1 p env = - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - match v with - | VFunction (Fun1 f,_) -> f v1 - | VFunction (FunN f,_) -> f [v1] - | VFieldClosure(v0,f) -> call_function f [v0;v1] - | _ -> cannot_call v p - -let call2 v v1 v2 p env = +let emit_proto_field_call v execs p env = + check_stack_depth env; + let f = Lazy.force v in + let vl = List.map (apply env) execs in env.env_leave_pmin <- p.pmin; env.env_leave_pmax <- p.pmax; - match v with - | VFunction (Fun2 f,_) -> f v1 v2 - | VFunction (FunN f,_) -> f [v1;v2] - | VFieldClosure(v0,f) -> call_function f [v0;v1;v2] - | _ -> cannot_call v p + f vl -let call3 v v1 v2 v3 p env = - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - match v with - | VFunction (Fun3 f,_) -> f v1 v2 v3 - | VFunction (FunN f,_) -> f [v1;v2;v3] - | VFieldClosure(v0,f) -> call_function f [v0;v1;v2;v3] - | _ -> cannot_call v p +(* instance.call() where call is overridden - dynamic dispatch *) -let call4 v v1 v2 v3 v4 p env = - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - match v with - | VFunction (Fun4 f,_) -> f v1 v2 v3 v4 - | VFunction (FunN f,_) -> f [v1;v2;v3;v4] - | VFieldClosure(v0,f) -> call_function f [v0;v1;v2;v3;v4] - | _ -> cannot_call v p +let get_prototype v p = match vresolve v with + | VInstance {iproto = proto} | VPrototype proto -> proto + | VString _ -> (get_ctx()).string_prototype + | VArray _ -> (get_ctx()).array_prototype + | VVector _ -> (get_ctx()).vector_prototype + | _ -> unexpected_value_p v "instance" p -let call5 v v1 v2 v3 v4 v5 p env = +let emit_method_call exec name execs p env = + check_stack_depth env; + let vthis = exec env in + let proto = get_prototype vthis p in + let vf = try proto_field_raise proto name with Not_found -> throw_string (Printf.sprintf "Field %s not found on prototype %s" (rev_hash name) (rev_hash proto.ppath)) p in + let vl = List.map (apply env) execs in env.env_leave_pmin <- p.pmin; env.env_leave_pmax <- p.pmax; - match v with - | VFunction (Fun5 f,_) -> f v1 v2 v3 v4 v5 - | VFunction (FunN f,_) -> f [v1;v2;v3;v4;v5] - | VFieldClosure(v0,f) -> call_function f [v0;v1;v2;v3;v4;v5] - | _ -> cannot_call v p - -let emit_proto_field_call proto i execs p = - match execs with - | [] -> - let vf = lazy (match proto.pfields.(i) with VFunction (Fun0 f,_) -> f | v -> cannot_call v p) in - (fun env -> - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - (Lazy.force vf) () - ) - | [exec1] -> - let vf = lazy (match proto.pfields.(i) with VFunction (Fun1 f,_) -> f | v -> cannot_call v p) in - (fun env -> - let f = Lazy.force vf in - let v1 = exec1 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - f v1 - ) - | [exec1;exec2] -> - let vf = lazy (match proto.pfields.(i) with VFunction (Fun2 f,_) -> f | v -> cannot_call v p) in - (fun env -> - let f = Lazy.force vf in - let v1 = exec1 env in - let v2 = exec2 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - f v1 v2 - ) - | [exec1;exec2;exec3] -> - let vf = lazy (match proto.pfields.(i) with VFunction (Fun3 f,_) -> f | v -> cannot_call v p) in - (fun env -> - let f = Lazy.force vf in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - f v1 v2 v3 - ) - | [exec1;exec2;exec3;exec4] -> - let vf = lazy (match proto.pfields.(i) with VFunction (Fun4 f,_) -> f | v -> cannot_call v p) in - (fun env -> - let f = Lazy.force vf in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - let v4 = exec4 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - f v1 v2 v3 v4 - ) - | [exec1;exec2;exec3;exec4;exec5] -> - let vf = lazy (match proto.pfields.(i) with VFunction (Fun5 f,_) -> f | v -> cannot_call v p) in - (fun env -> - let f = Lazy.force vf in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - let v4 = exec4 env in - let v5 = exec5 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - f v1 v2 v3 v4 v5 - ) - | _ -> - let vf = lazy (match proto.pfields.(i) with VFunction (FunN f,_) -> f | v -> cannot_call v p) in - (fun env -> - let f = Lazy.force vf in - let vl = List.map (fun exec -> exec env) execs in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - f vl - ) - -(* instance.call() where call is overridden - dynamic dispatch *) - -let emit_method_call exec name execs p = - let vf vthis = match vthis with - | VInstance {iproto = proto} | VPrototype proto -> proto_field_raise proto name - | VString _ -> proto_field_raise (get_ctx()).string_prototype name - | VArray _ -> proto_field_raise (get_ctx()).array_prototype name - | VVector _ -> proto_field_raise (get_ctx()).vector_prototype name - | _ -> unexpected_value_p vthis "instance" p - in - match execs with - | [] -> - (fun env -> - let vthis = exec env in - let vf = vf vthis in - call1 vf vthis p env - ) - | [exec1] -> - (fun env -> - let vthis = exec env in - let vf = vf vthis in - let v1 = exec1 env in - call2 vf vthis v1 p env - ) - | [exec1;exec2] -> - (fun env -> - let vthis = exec env in - let vf = vf vthis in - let v1 = exec1 env in - let v2 = exec2 env in - call3 vf vthis v1 v2 p env - ) - | [exec1;exec2;exec3] -> - (fun env -> - let vthis = exec env in - let vf = vf vthis in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - call4 vf vthis v1 v2 v3 p env - ) - | [exec1;exec2;exec3;exec4] -> - (fun env -> - let vthis = exec env in - let vf = vf vthis in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - let v4 = exec4 env in - call5 vf vthis v1 v2 v3 v4 p env - ) - | _ -> - (fun env -> - let vthis = exec env in - let vf = vf vthis in - let vl = List.map (apply env) execs in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - call_value_on vthis vf vl - ) + call_value_on vthis vf vl (* instance.call() where call is not a method - lookup + this-binding *) let emit_field_call exec name execs p env = + check_stack_depth env; let vthis = exec env in let vf = field vthis name in env.env_leave_pmin <- p.pmin; @@ -610,146 +333,20 @@ let emit_field_call exec name execs p env = (* new() - immediate + this-binding *) -let emit_constructor_call0 proto vf p env = - let vthis = create_instance_direct proto in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore((Lazy.force vf) vthis); - vthis - -let emit_constructor_call1 proto vf exec1 p env = - let f = Lazy.force vf in - let vthis = create_instance_direct proto in - let v1 = exec1 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore(f vthis v1); - vthis - -let emit_constructor_call2 proto vf exec1 exec2 p env = - let f = Lazy.force vf in - let vthis = create_instance_direct proto in - let v1 = exec1 env in - let v2 = exec2 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore(f vthis v1 v2); - vthis - -let emit_constructor_call3 proto vf exec1 exec2 exec3 p env = - let f = Lazy.force vf in - let vthis = create_instance_direct proto in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore(f vthis v1 v2 v3); - vthis - -let emit_constructor_call4 proto vf exec1 exec2 exec3 exec4 p env = - let f = Lazy.force vf in - let vthis = create_instance_direct proto in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - let v4 = exec4 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore(f vthis v1 v2 v3 v4); - vthis - -let emit_constructor_callN proto vf execs p env = - let f = Lazy.force vf in - let vthis = create_instance_direct proto in - let vl = List.map (fun exec -> exec env) execs in +let emit_constructor_call proto v execs p env = + check_stack_depth env; + let f = Lazy.force v in + let vthis = create_instance_direct proto INormal in + let vl = List.map (apply env) execs in env.env_leave_pmin <- p.pmin; env.env_leave_pmax <- p.pmax; ignore(f (vthis :: vl)); vthis -let emit_constructor_call proto fnew execs p = - match execs with - | [] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun1 f,_) -> f | v -> cannot_call v p) in - emit_constructor_call0 proto vf p - | [exec1] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun2 f,_) -> f | v -> cannot_call v p) in - emit_constructor_call1 proto vf exec1 p - | [exec1;exec2] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun3 f,_) -> f | v -> cannot_call v p) in - emit_constructor_call2 proto vf exec1 exec2 p - | [exec1;exec2;exec3] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun4 f,_) -> f | v -> cannot_call v p) in - emit_constructor_call3 proto vf exec1 exec2 exec3 p - | [exec1;exec2;exec3;exec4] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun5 f,_) -> f | v -> cannot_call v p) in - emit_constructor_call4 proto vf exec1 exec2 exec3 exec4 p - | _ -> - let vf = lazy (match Lazy.force fnew with VFunction (FunN f,_) -> f | v -> cannot_call v p) in - emit_constructor_callN proto vf execs p - (* super() - immediate + this-binding *) -let emit_super_call0 vf p env = - let vthis = env.env_locals.(0) in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore((Lazy.force vf) vthis); - vthis - -let emit_super_call1 vf exec1 p env = - let f = Lazy.force vf in - let vthis = env.env_locals.(0) in - let v1 = exec1 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore(f vthis v1); - vthis - -let emit_super_call2 vf exec1 exec2 p env = - let f = Lazy.force vf in - let vthis = env.env_locals.(0) in - let v1 = exec1 env in - let v2 = exec2 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore(f vthis v1 v2); - vthis - -let emit_super_call3 vf exec1 exec2 exec3 p env = - let f = Lazy.force vf in - let vthis = env.env_locals.(0) in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore(f vthis v1 v2 v3); - vthis - -let emit_super_call4 vf exec1 exec2 exec3 exec4 p env = - let f = Lazy.force vf in - let vthis = env.env_locals.(0) in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - let v4 = exec4 env in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore(f vthis v1 v2 v3 v4); - vthis - -let emit_super_callN vf execs p env = - let f = Lazy.force vf in - let vthis = env.env_locals.(0) in - let vl = List.map (fun exec -> exec env) execs in - env.env_leave_pmin <- p.pmin; - env.env_leave_pmax <- p.pmax; - ignore(f (vthis :: vl)); - vthis - let emit_special_super_call fnew execs env = + check_stack_depth env; let vl = List.map (apply env) execs in let vi' = fnew vl in let vthis = env.env_locals.(0) in @@ -760,68 +357,20 @@ let emit_special_super_call fnew execs env = end; vnull -let emit_super_call fnew execs p = - match execs with - | [] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun1 f,_) -> f | v -> cannot_call v p) in - emit_super_call0 vf p - | [exec1] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun2 f,_) -> f | v -> cannot_call v p) in - emit_super_call1 vf exec1 p - | [exec1;exec2] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun3 f,_) -> f | v -> cannot_call v p) in - emit_super_call2 vf exec1 exec2 p - | [exec1;exec2;exec3] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun4 f,_) -> f | v -> cannot_call v p) in - emit_super_call3 vf exec1 exec2 exec3 p - | [exec1;exec2;exec3;exec4] -> - let vf = lazy (match Lazy.force fnew with VFunction (Fun5 f,_) -> f | v -> cannot_call v p) in - emit_super_call4 vf exec1 exec2 exec3 exec4 p - | _ -> - let vf = lazy (match Lazy.force fnew with VFunction (FunN f,_) -> f | v -> cannot_call v p) in - emit_super_callN vf execs p +let emit_super_call v execs p env = + check_stack_depth env; + let f = Lazy.force v in + let vthis = env.env_locals.(0) in + let vl = List.map (apply env) execs in + env.env_leave_pmin <- p.pmin; + env.env_leave_pmax <- p.pmax; + ignore(f (vthis :: vl)); + vthis (* unknown call - full lookup *) -let emit_call0 exec p env = - call0 (exec env) p env - -let emit_call1 exec exec1 p env = - let v0 = exec env in - let v1 = exec1 env in - call1 v0 v1 p env - -let emit_call2 exec exec1 exec2 p env = - let v0 = exec env in - let v1 = exec1 env in - let v2 = exec2 env in - call2 v0 v1 v2 p env - -let emit_call3 exec exec1 exec2 exec3 p env = - let v0 = exec env in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - call3 v0 v1 v2 v3 p env - -let emit_call4 exec exec1 exec2 exec3 exec4 p env = - let v0 = exec env in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - let v4 = exec4 env in - call4 v0 v1 v2 v3 v4 p env - -let emit_call5 exec exec1 exec2 exec3 exec4 exec5 p env = - let v0 = exec env in - let v1 = exec1 env in - let v2 = exec2 env in - let v3 = exec3 env in - let v4 = exec4 env in - let v5 = exec5 env in - call5 v0 v1 v2 v3 v4 v5 p env - let emit_call exec execs p env = + check_stack_depth env; let v1 = exec env in env.env_leave_pmin <- p.pmin; env.env_leave_pmax <- p.pmax; @@ -831,47 +380,33 @@ let emit_call exec execs p env = let emit_local_read i env = env.env_locals.(i) -let emit_capture_read i env = !(env.env_captures.(i)) +let emit_capture_read i env = env.env_captures.(i) -let emit_array_length_read exec env = match exec env with - | VArray va -> vint (va.alength) - | v -> unexpected_value v "Array" +let emit_array_length_read exec p env = vint (as_array p (exec env)).alength -let emit_vector_length_read exec env = match exec env with - | VVector vv -> vint (Array.length vv) - | v -> unexpected_value v "Vector" +let emit_vector_length_read exec p env = vint (Array.length (as_vector p (exec env))) -let emit_bytes_length_read exec env = match exec env with - | VInstance {ikind = IBytes s} -> vint (Bytes.length s) - | v -> unexpected_value v "Bytes" +let emit_bytes_length_read exec p env = vint (Bytes.length (as_bytes p (exec env))) let emit_proto_field_read proto i env = proto.pfields.(i) -let emit_instance_local_field_read iv i env = match env.env_locals.(iv) with +let emit_instance_field_read exec p i env = match exec env with | VInstance vi -> vi.ifields.(i) - | VString(_,s) -> vint (String.length (Lazy.force s)) - | v -> unexpected_value v "instance" + | VString s -> vint (s.slength) + | VNull -> throw_string "field access on null" p + | v -> unexpected_value_p v "instance" p -let emit_instance_field_read exec i env = match exec env with +let emit_this_field_read iv i env = match env.env_locals.(iv) with | VInstance vi -> vi.ifields.(i) - | VString(_,s) -> vint (String.length (Lazy.force s)) | v -> unexpected_value v "instance" let emit_field_closure exec name env = let v = exec env in dynamic_field v name -let emit_anon_local_field_read iv proto i name p env = - match env.env_locals.(iv) with - | VObject o -> - if proto == o.oproto then o.ofields.(i) - else object_field o name - | VNull -> throw_string "field access on null" p - | v -> field v name - let emit_anon_field_read exec proto i name p env = - match exec env with + match vresolve (exec env) with | VObject o -> if proto == o.oproto then o.ofields.(i) else object_field o name @@ -882,47 +417,29 @@ let emit_field_read exec name p env = match exec env with | VNull -> throw_string "field access on null" p | v -> field v name -let emit_array_local_read i exec2 p env = - let va = env.env_locals.(i) in - let vi = exec2 env in - let i = decode_int_p vi p in - if i < 0 then vnull - else EvalArray.get (decode_varray va) i - -let emit_array_read exec1 exec2 p env = - let va = exec1 env in - let vi = exec2 env in - let i = decode_int_p vi p in - if i < 0 then vnull - else EvalArray.get (decode_varray va) i - -let emit_vector_local_read i exec2 p env = - let vv = env.env_locals.(i) in - let vi = exec2 env in - let i = decode_int_p vi p in +let emit_array_read exec1 p1 exec2 p2 env = + let a = as_array p1 (exec1 env) in + let i = as_int p2 (exec2 env) in if i < 0 then vnull - else Array.unsafe_get (decode_vector vv) i + else EvalArray.get a i -let emit_vector_read exec1 exec2 p env = - let vv = exec1 env in - let vi = exec2 env in - let i = decode_int_p vi p in +let emit_vector_read exec1 p1 exec2 p2 env = + let v = as_vector p1 (exec1 env) in + let i = as_int p2 (exec2 env) in if i < 0 then vnull - else Array.unsafe_get (decode_vector vv) i + else Array.unsafe_get v i -let emit_enum_index exec env = match exec env with - | VEnumValue ev -> vint ev.eindex - | v -> unexpected_value v "enum value" +let emit_enum_index exec p env = vint (as_enum_value p (exec env)).eindex let emit_enum_parameter_read exec i env = match exec env with | VEnumValue ev -> (try ev.eargs.(i) with Not_found -> vnull) | v1 -> unexpected_value v1 "enum value" let emit_string_cca exec1 exec2 p env = - let s = decode_string (exec1 env) in + let s = decode_vstring (exec1 env) in let index = decode_int_p (exec2 env) p in - if index >= String.length s then vnull - else vint (int_of_char s.[index]) + if index < 0 || index >= s.slength then vnull + else vint (EvalString.char_at s index) (* Write *) @@ -939,7 +456,7 @@ let emit_local_write slot exec env = let emit_capture_write slot exec env = let v = exec env in - env.env_captures.(slot) := v; + env.env_captures.(slot) <- v; v let emit_proto_field_write proto i exec2 env = @@ -947,129 +464,82 @@ let emit_proto_field_write proto i exec2 env = proto.pfields.(i) <- v; v -let emit_instance_field_write exec1 i exec2 env = match exec1 env with +let emit_instance_field_write exec1 p i exec2 env = match exec1 env with | VInstance vi -> let v = exec2 env in vi.ifields.(i) <- v; v - | v -> unexpected_value v "instance" + | v -> unexpected_value_p v "instance" p -let emit_anon_field_write exec1 proto i name exec2 env = +let emit_anon_field_write exec1 p proto i name exec2 env = let v1 = exec1 env in let v2 = exec2 env in - begin match v1 with + begin match vresolve v1 with | VObject o -> if proto == o.oproto then begin o.ofields.(i) <- v2; - o.oremoved <- IntMap.remove name o.oremoved; end else set_object_field o name v2 + | VNull -> throw_string "field access on null" p | _ -> set_field v1 name v2; end; v2 -let emit_field_write exec1 name exec2 env = +let emit_field_write exec1 p1 name exec2 env = let v1 = exec1 env in let v2 = exec2 env in - set_field v1 name v2; + (try set_field v1 name v2 with RunTimeException(v,stack,_) -> raise_notrace (RunTimeException(v,stack,p1))); v2 -let emit_array_local_write i exec2 exec3 p env = - let va = env.env_locals.(i) in - let vi = exec2 env in - let v3 = exec3 env in - let i = decode_int_p vi p in - if i < 0 then throw_string (Printf.sprintf "Negative array index: %i" i) p; - EvalArray.set (decode_varray va) i v3; - v3 - -let emit_array_write exec1 exec2 exec3 p env = - let va = exec1 env in - let vi = exec2 env in +let emit_array_write exec1 p1 exec2 p2 exec3 p env = + let a = as_array p1 (exec1 env) in + let i = as_int p2 (exec2 env) in let v3 = exec3 env in - let i = decode_int_p vi p in if i < 0 then throw_string (Printf.sprintf "Negative array index: %i" i) p; - EvalArray.set (decode_varray va) i v3; + EvalArray.set a i v3; v3 -let emit_vector_local_write i exec2 exec3 p env = - let vv = env.env_locals.(i) in - let vi = exec2 env in +let emit_vector_write exec1 p1 exec2 p2 exec3 p env = + let vv = as_vector p1 (exec1 env) in + let i = as_int p2 (exec2 env) in let v3 = exec3 env in - let i = decode_int_p vi p in if i < 0 then throw_string (Printf.sprintf "Negative vector index: %i" i) p; - Array.unsafe_set (decode_vector vv) i v3; - v3 - -let emit_vector_write exec1 exec2 exec3 p env = - let vv = exec1 env in - let vi = exec2 env in - let v3 = exec3 env in - let i = decode_int_p vi p in - if i < 0 then throw_string (Printf.sprintf "Negative vector index: %i" i) p; - Array.unsafe_set (decode_vector vv) i v3; + Array.unsafe_set vv i v3; v3 (* Read + write *) -let emit_local_read_write slot exec fop prefix env = - let v1 = env.env_locals.(slot) in - let v2 = exec env in - let v = fop v1 v2 in - env.env_locals.(slot) <- v; - if prefix then v else v1 - -let emit_local_incr_postfix slot env = - let vi = env.env_locals.(slot) in - env.env_locals.(slot) <- vint32 (Int32.succ (decode_i32 vi)); - vi +let do_incr v p = match v with + | VInt32 i32 -> vint32 (Int32.add i32 Int32.one) + | VFloat f -> vfloat (f +. 1.) + | v -> unexpected_value_p v "number" p -let emit_local_incr_prefix slot env = - let vi = env.env_locals.(slot) in - let v = vint32 (Int32.succ (decode_i32 vi)) in +let emit_local_incr_prefix slot p env = + let v0 = env.env_locals.(slot) in + let v = do_incr v0 p in env.env_locals.(slot) <- v; v -let emit_local_decr_postfix slot env = - let vi = env.env_locals.(slot) in - env.env_locals.(slot) <- vint32 (Int32.pred (decode_i32 vi)); - vi +let emit_local_incr_postfix slot p env = + let v0 = env.env_locals.(slot) in + let v = do_incr v0 p in + env.env_locals.(slot) <- v; + v0 -let emit_local_decr_prefix slot env = - let vi = env.env_locals.(slot) in - let v = vint32 (Int32.pred (decode_i32 vi)) in +let emit_local_read_write slot exec fop prefix env = + let v1 = env.env_locals.(slot) in + let v2 = exec env in + let v = fop v1 v2 in env.env_locals.(slot) <- v; - v + if prefix then v else v1 let emit_capture_read_write slot exec fop prefix env = - let v1 = !(env.env_captures.(slot)) in + let v1 = (env.env_captures.(slot)) in let v2 = exec env in let v = fop v1 v2 in - env.env_captures.(slot) := v; + env.env_captures.(slot) <- v; if prefix then v else v1 -let emit_capture_incr_postfix slot env = - let vi = !(env.env_captures.(slot)) in - env.env_captures.(slot) := vint32 (Int32.succ (decode_i32 vi)); - vi - -let emit_capture_incr_prefix slot env = - let vi = !(env.env_captures.(slot)) in - let v = vint32 (Int32.succ (decode_i32 vi)) in - env.env_captures.(slot) := v; - v - -let emit_capture_decr_postfix slot env = - let vi = !(env.env_captures.(slot)) in - env.env_captures.(slot) := vint32 (Int32.pred (decode_i32 vi)); - vi - -let emit_capture_decr_prefix slot env = - let vi = !(env.env_captures.(slot)) in - let v = vint32 (Int32.pred (decode_i32 vi)) in - env.env_captures.(slot) := v; - v - let emit_proto_field_read_write proto i exec2 fop prefix env = let vf = proto.pfields.(i) in let v2 = exec2 env in @@ -1084,13 +554,13 @@ let instance_field_read_write vi i exec2 fop prefix env = vi.ifields.(i) <- v; if prefix then v else vf -let emit_instance_field_read_write exec1 i exec2 fop prefix env = match exec1 env with +let emit_instance_field_read_write exec1 p1 i exec2 fop prefix env = match exec1 env with | VInstance vi -> instance_field_read_write vi i exec2 fop prefix env - | v -> unexpected_value v "instance" + | v -> unexpected_value_p v "instance" p1 -let emit_field_read_write exec1 name exec2 fop prefix env = +let emit_field_read_write exec1 p1 name exec2 fop prefix env = let v1 = exec1 env in - match v1 with + match vresolve v1 with | VObject o -> let vf = object_field o name in let v2 = exec2 env in @@ -1107,51 +577,23 @@ let emit_field_read_write exec1 name exec2 fop prefix env = let vf = field v1 name in let v2 = exec2 env in let v = fop vf v2 in - set_field v1 name v; + (try set_field v1 name v with RunTimeException(v,stack,_) -> raise_notrace (RunTimeException(v,stack,p1))); if prefix then v else vf -let emit_array_local_read_write i exec2 exec3 fop prefix p env = - let va1 = env.env_locals.(i) in - let va2 = exec2 env in - let va = decode_varray va1 in - let i = decode_int_p va2 p in - if i < 0 then throw_string (Printf.sprintf "Negative array index: %i" i) p; +let emit_array_read_write exec1 p1 exec2 p2 exec3 fop prefix env = + let va = as_array p1 (exec1 env) in + let i = as_int p2 (exec2 env) in + if i < 0 then throw_string (Printf.sprintf "Negative array index: %i" i) p2; let v = EvalArray.get va i in let v2 = exec3 env in let v3 = fop v v2 in EvalArray.set va i v3; if prefix then v3 else v -let emit_array_read_write exec1 exec2 exec3 fop prefix p env = - let va1 = exec1 env in - let va2 = exec2 env in - let va = decode_varray va1 in - let i = decode_int_p va2 p in - if i < 0 then throw_string (Printf.sprintf "Negative array index: %i" i) p; - let v = EvalArray.get va i in - let v2 = exec3 env in - let v3 = fop v v2 in - EvalArray.set va i v3; - if prefix then v3 else v - -let emit_vector_local_read_write i exec2 exec3 fop prefix p env = - let va1 = env.env_locals.(i) in - let va2 = exec2 env in - let va = decode_vector va1 in - let i = decode_int_p va2 p in - if i < 0 then throw_string (Printf.sprintf "Negative vector index: %i" i) p; - let v = Array.unsafe_get va i in - let v2 = exec3 env in - let v3 = fop v v2 in - Array.unsafe_set va i v3; - if prefix then v3 else v - -let emit_vector_read_write exec1 exec2 exec3 fop prefix p env = - let va1 = exec1 env in - let va2 = exec2 env in - let va = decode_vector va1 in - let i = decode_int_p va2 p in - if i < 0 then throw_string (Printf.sprintf "Negative vector index: %i" i) p; +let emit_vector_read_write exec1 p1 exec2 p2 exec3 fop prefix env = + let va = as_vector p1 (exec1 env) in + let i = as_int p2 (exec2 env) in + if i < 0 then throw_string (Printf.sprintf "Negative vector index: %i" i) p2; let v = Array.unsafe_get va i in let v2 = exec3 env in let v3 = fop v v2 in @@ -1168,82 +610,10 @@ let emit_not_eq_null exec env = match exec env with | VNull -> VFalse | _ -> VTrue -let op_add v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.add i1 i2) - | VFloat f1,VFloat f2 -> vfloat (f1 +. f2) - | VInt32 i,VFloat f | VFloat f,VInt32 i -> vfloat ((Int32.to_float i) +. f) - | VString(s1,_),VString(s2,_) -> encode_rope (Rope.concat2 s1 s2) - | VString(s1,_),v2 -> encode_rope (Rope.concat2 s1 (s_value 0 v2)) - | v1,VString(s2,_) -> encode_rope (Rope.concat2 (s_value 0 v1) s2) - | v1,v2 -> encode_rope (Rope.concat2 (s_value 0 v1) (s_value 0 v2)) - -let op_mult p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.mul i1 i2) - | VFloat f1,VFloat f2 -> vfloat (f1 *. f2) - | VInt32 i,VFloat f | VFloat f,VInt32 i -> vfloat ((Int32.to_float i) *. f) - | _ -> invalid_binop OpMult v1 v2 p - -let op_div p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vfloat ((Int32.to_float i1) /. (Int32.to_float i2)) - | VFloat f1,VFloat f2 -> vfloat (f1 /. f2) - | VInt32 i1,VFloat f2 -> vfloat ((Int32.to_float i1) /. f2) - | VFloat f1,VInt32 i2 -> vfloat (f1 /. (Int32.to_float i2)) - | _ -> invalid_binop OpDiv v1 v2 p - -let op_sub p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.sub i1 i2) - | VFloat f1,VFloat f2 -> vfloat (f1 -. f2) - | VInt32 i1,VFloat f2 -> vfloat ((Int32.to_float i1) -. f2) - | VFloat f1,VInt32 i2 -> vfloat (f1 -. (Int32.to_float i2)) - | _ -> invalid_binop OpSub v1 v2 p - -let op_eq v1 v2 = vbool (equals v1 v2) - -let op_not_eq v1 v2 = vbool (not (equals v1 v2)) - -let op_gt v1 v2 = vbool (compare v1 v2 = CSup) - -let op_gte v1 v2 = vbool (match compare v1 v2 with CSup | CEq -> true | _ -> false) - -let op_lt v1 v2 = vbool (compare v1 v2 = CInf) - -let op_lte v1 v2 = vbool (match compare v1 v2 with CInf | CEq -> true | _ -> false) - -let op_and p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.logand i1 i2) - | _ -> invalid_binop OpAnd v1 v2 p - -let op_or p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.logor i1 i2) - | _ -> invalid_binop OpOr v1 v2 p - -let op_xor p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.logxor i1 i2) - | _ -> invalid_binop OpXor v1 v2 p - -let op_shl p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.shift_left i1 (Int32.to_int i2)) - | _ -> invalid_binop OpShl v1 v2 p - -let op_shr p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.shift_right i1 (Int32.to_int i2)) - | _ -> invalid_binop OpShr v1 v2 p - -let op_ushr p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.shift_right_logical i1 (Int32.to_int i2)) - | _ -> invalid_binop OpUShr v1 v2 p - -let op_mod p v1 v2 = match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.rem i1 i2) - | VFloat f1,VFloat f2 -> vfloat (mod_float f1 f2) - | VInt32 i1,VFloat f2 -> vfloat (mod_float (Int32.to_float i1) f2) - | VFloat f1,VInt32 i2 -> vfloat (mod_float f1 (Int32.to_float i2)) - | _ -> invalid_binop OpMod v1 v2 p - -let emit_op_add exec1 exec2 env = +let emit_op_add p exec1 exec2 env = let v1 = exec1 env in let v2 = exec2 env in - op_add v1 v2 + op_add p v1 v2 let emit_op_mult p exec1 exec2 env = let v1 = exec1 env in @@ -1344,161 +714,70 @@ let emit_neg exec p env = match exec env with (* Function *) -let handle_capture_arguments exec varaccs env = - List.iter (fun (slot,i) -> - env.env_captures.(i) <- ref env.env_locals.(slot) - ) varaccs; - exec env - -let run_function ctx exec env = - let v = try - exec env - with - | Return v -> v +type env_creation = { + ec_info : env_info; + ec_num_locals : int; + ec_num_captures : int; +} + +let execute_set_local i env v = + env.env_locals.(i) <- v + +let execute_set_capture i env v = + env.env_captures.(i) <- v + +let process_arguments fl vl env = + let rec loop fl vl = match fl,vl with + | f :: fl,v :: vl -> + f env v; + loop fl vl + | f :: fl,[] -> + f env vnull; + loop fl [] + | [],[] -> + () + | _ -> + exc_string "Something went wrong" in - env.env_in_use <- false; + loop fl vl +[@@inline] + +let create_function_noret ctx eci exec fl vl = + let env = push_environment ctx eci.ec_info eci.ec_num_locals eci.ec_num_captures in + process_arguments fl vl env; + let v = exec env in + pop_environment ctx env; + v + +let create_function ctx eci exec fl vl = + let env = push_environment ctx eci.ec_info eci.ec_num_locals eci.ec_num_captures in + process_arguments fl vl env; + let v = try exec env with Return v -> v in pop_environment ctx env; v -[@@inline] -let run_function_noret ctx exec env = +let create_closure_noret ctx eci refs exec fl vl = + let env = push_environment ctx eci.ec_info eci.ec_num_locals eci.ec_num_captures in + Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs; + process_arguments fl vl env; let v = exec env in - env.env_in_use <- false; pop_environment ctx env; v -[@@inline] -let get_normal_env ctx info num_locals num_captures _ = - push_environment ctx info num_locals num_captures - -let get_closure_env ctx info num_locals num_captures refs = - let env = push_environment ctx info num_locals num_captures in - Array.iteri (fun i vr -> env.env_captures.(i) <- vr) refs; - env - -let get_normal_env_opt ctx default_env info num_locals num_captures _ = - if default_env.env_in_use then begin - push_environment ctx info num_locals num_captures - end else begin - default_env.env_in_use <- true; - default_env - end - -let get_closure_env_opt ctx default_env info num_locals num_captures refs = - let env = if default_env.env_in_use then begin - push_environment ctx info num_locals num_captures - end else begin - default_env.env_in_use <- true; - default_env - end in - Array.iteri (fun i vr -> env.env_captures.(i) <- vr) refs; - env - -let create_function ctx num_args get_env hasret refs exec = - match num_args with - | 0 -> - if hasret then Fun0 (fun () -> - let env = get_env refs in - run_function ctx exec env - ) - else Fun0 (fun () -> - let env = get_env refs in - run_function_noret ctx exec env - ) - | 1 -> - if hasret then Fun1 (fun v1 -> - let env = get_env refs in - env.env_locals.(0) <- v1; - run_function ctx exec env - ) - else Fun1 (fun v1 -> - let env = get_env refs in - env.env_locals.(0) <- v1; - run_function_noret ctx exec env - ) - | 2 -> - let run v1 v2 = - let env = get_env refs in - env.env_locals.(0) <- v1; - env.env_locals.(1) <- v2; - env - in - if hasret then Fun2 (fun v1 v2 -> - let env = run v1 v2 in - run_function ctx exec env - ) - else Fun2 (fun v1 v2 -> - let env = run v1 v2 in - run_function_noret ctx exec env - ) - | 3 -> - let run v1 v2 v3 = - let env = get_env refs in - env.env_locals.(0) <- v1; - env.env_locals.(1) <- v2; - env.env_locals.(2) <- v3; - env - in - if hasret then Fun3 (fun v1 v2 v3 -> - let env = run v1 v2 v3 in - run_function ctx exec env - ) - else Fun3 (fun v1 v2 v3 -> - let env = run v1 v2 v3 in - run_function_noret ctx exec env - ) - | 4 -> - let run v1 v2 v3 v4 = - let env = get_env refs in - env.env_locals.(0) <- v1; - env.env_locals.(1) <- v2; - env.env_locals.(2) <- v3; - env.env_locals.(3) <- v4; - env - in - if hasret then Fun4 (fun v1 v2 v3 v4 -> - let env = run v1 v2 v3 v4 in - run_function ctx exec env - ) - else Fun4 (fun v1 v2 v3 v4 -> - let env = run v1 v2 v3 v4 in - run_function_noret ctx exec env - ) - | 5 -> - let run v1 v2 v3 v4 v5 = - let env = get_env refs in - env.env_locals.(0) <- v1; - env.env_locals.(1) <- v2; - env.env_locals.(2) <- v3; - env.env_locals.(3) <- v4; - env.env_locals.(4) <- v5; - env - in - if hasret then Fun5 (fun v1 v2 v3 v4 v5 -> - let env = run v1 v2 v3 v4 v5 in - run_function ctx exec env - ) - else Fun5 (fun v1 v2 v3 v4 v5 -> - let env = run v1 v2 v3 v4 v5 in - run_function_noret ctx exec env - ) - | _ -> - if hasret then FunN (fun vl -> - let env = get_env refs in - List.iteri (fun i v -> - env.env_locals.(i) <- v - ) vl; - run_function ctx exec env - ) - else FunN (fun vl -> - let env = get_env refs in - List.iteri (fun i v -> - env.env_locals.(i) <- v - ) vl; - run_function_noret ctx exec env - ) - -let emit_closure ctx num_captures num_args get_env hasret exec env = - let refs = Array.sub env.env_captures 0 num_captures in - let f = create_function ctx num_args get_env hasret refs exec in +let create_closure refs ctx eci exec fl vl = + let env = push_environment ctx eci.ec_info eci.ec_num_locals eci.ec_num_captures in + Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs; + process_arguments fl vl env; + let v = try exec env with Return v -> v in + pop_environment ctx env; + v + +let emit_closure ctx mapping eci hasret exec fl env = + let refs = Array.map (fun (i,slot) -> i,emit_capture_read slot env) mapping in + let create = match hasret,eci.ec_num_captures with + | true,0 -> create_function + | false,0 -> create_function_noret + | _ -> create_closure refs + in + let f = create ctx eci exec fl in vstatic_function f \ No newline at end of file diff --git a/src/macro/eval/evalEncode.ml b/src/macro/eval/evalEncode.ml index 63772375613..1031cd007bc 100644 --- a/src/macro/eval/evalEncode.ml +++ b/src/macro/eval/evalEncode.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -22,36 +22,107 @@ open EvalValue open EvalExceptions open EvalContext open EvalHash +open EvalString (* Functions *) -let vifun0 f = vfunction (Fun1 (fun a -> f a)) -let vifun1 f = vfunction (Fun2 (fun a b -> f a b)) -let vifun2 f = vfunction (Fun3 (fun a b c -> f a b c)) -let vifun3 f = vfunction (Fun4 (fun a b c d -> f a b c d)) -let vifun4 f = vfunction (Fun5 (fun a b c d e -> f a b c d e)) - -let vfun0 f = vstatic_function (Fun0 (fun vl -> f ())) -let vfun1 f = vstatic_function (Fun1 (fun a -> f a)) -let vfun2 f = vstatic_function (Fun2 (fun a b -> f a b)) -let vfun3 f = vstatic_function (Fun3 (fun a b c -> f a b c)) -let vfun4 f = vstatic_function (Fun4 (fun a b c d -> f a b c d)) -let vfun5 f = vstatic_function (Fun5 (fun a b c d e -> f a b c d e)) +let vifun0 f = vfunction (fun vl -> match vl with + | [] -> f vnull + | [v0] -> f v0 + | _ -> invalid_call_arg_number 1 (List.length vl +)) + +let vifun1 f = vfunction (fun vl -> match vl with + | [] -> f vnull vnull + | [v0] -> f v0 vnull + | [v0;v1] -> f v0 v1 + | _ -> invalid_call_arg_number 2 (List.length vl +)) + +let vifun2 f = vfunction (fun vl -> match vl with + | [] -> f vnull vnull vnull + | [v0] -> f v0 vnull vnull + | [v0;v1] -> f v0 v1 vnull + | [v0;v1;v2] -> f v0 v1 v2 + | _ -> invalid_call_arg_number 3 (List.length vl +)) + +let vifun3 f = vfunction (fun vl -> match vl with + | [] -> f vnull vnull vnull vnull + | [v0] -> f v0 vnull vnull vnull + | [v0;v1] -> f v0 v1 vnull vnull + | [v0;v1;v2] -> f v0 v1 v2 vnull + | [v0;v1;v2;v3] -> f v0 v1 v2 v3 + | _ -> invalid_call_arg_number 4 (List.length vl +)) + +let vifun4 f = vfunction (fun vl -> match vl with + | [] -> f vnull vnull vnull vnull vnull + | [v0] -> f v0 vnull vnull vnull vnull + | [v0;v1] -> f v0 v1 vnull vnull vnull + | [v0;v1;v2] -> f v0 v1 v2 vnull vnull + | [v0;v1;v2;v3] -> f v0 v1 v2 v3 vnull + | [v0;v1;v2;v3;v4] -> f v0 v1 v2 v3 v4 + | _ -> invalid_call_arg_number 4 (List.length vl +)) + +let vfun0 f = vstatic_function (fun vl -> match vl with + | [] -> f () + | _ -> invalid_call_arg_number 1 (List.length vl +)) + +let vfun1 f = vstatic_function (fun vl -> match vl with + | [] -> f vnull + | [v0] -> f v0 + | _ -> invalid_call_arg_number 1 (List.length vl +)) + +let vfun2 f = vstatic_function (fun vl -> match vl with + | [] -> f vnull vnull + | [v0] -> f v0 vnull + | [v0;v1] -> f v0 v1 + | _ -> invalid_call_arg_number 2 (List.length vl +)) + +let vfun3 f = vstatic_function (fun vl -> match vl with + | [] -> f vnull vnull vnull + | [v0] -> f v0 vnull vnull + | [v0;v1] -> f v0 v1 vnull + | [v0;v1;v2] -> f v0 v1 v2 + | _ -> invalid_call_arg_number 3 (List.length vl +)) + +let vfun4 f = vstatic_function (fun vl -> match vl with + | [] -> f vnull vnull vnull vnull + | [v0] -> f v0 vnull vnull vnull + | [v0;v1] -> f v0 v1 vnull vnull + | [v0;v1;v2] -> f v0 v1 v2 vnull + | [v0;v1;v2;v3] -> f v0 v1 v2 v3 + | _ -> invalid_call_arg_number 4 (List.length vl +)) + +let vfun5 f = vstatic_function (fun vl -> match vl with + | [] -> f vnull vnull vnull vnull vnull + | [v0] -> f v0 vnull vnull vnull vnull + | [v0;v1] -> f v0 v1 vnull vnull vnull + | [v0;v1;v2] -> f v0 v1 v2 vnull vnull + | [v0;v1;v2;v3] -> f v0 v1 v2 v3 vnull + | [v0;v1;v2;v3;v4] -> f v0 v1 v2 v3 v4 + | _ -> invalid_call_arg_number 4 (List.length vl +)) (* Objects *) -let encode_obj _ l = +let encode_obj l = let ctx = get_ctx() in let proto,sorted = ctx.get_object_prototype ctx l in vobject { ofields = Array.of_list (List.map snd sorted); oproto = proto; - oextra = IntMap.empty; - oremoved = IntMap.empty; } -let encode_obj_s k l = - encode_obj k (List.map (fun (s,v) -> (hash_s s),v) l) +let encode_obj_s l = + encode_obj (List.map (fun (s,v) -> (hash s),v) l) (* Enum values *) @@ -86,16 +157,18 @@ let encode_enum i pos index pl = | IAnonStatus -> key_haxe_macro_AnonStatus | IImportMode -> key_haxe_macro_ImportMode | IQuoteStatus -> key_haxe_macro_QuoteStatus + | IDisplayKind -> key_haxe_macro_DisplayKind + | IMessage -> key_haxe_macro_Message in encode_enum_value key index (Array.of_list pl) pos (* Instances *) -let create_instance_direct proto = +let create_instance_direct proto kind = vinstance { ifields = if Array.length proto.pinstance_fields = 0 then proto.pinstance_fields else Array.copy proto.pinstance_fields; iproto = proto; - ikind = INormal; + ikind = kind; } let create_instance ?(kind=INormal) path = @@ -119,26 +192,30 @@ let encode_array l = encode_array_instance (EvalArray.create (Array.of_list l)) let encode_string s = - VString(Rope.of_string s,lazy s) + create_unknown s -let encode_rope s = - vstring s +(* Should only be used for std types that aren't expected to change while the compilation server is running *) +let create_cached_instance path fkind = + let proto = lazy (get_instance_prototype (get_ctx()) path null_pos) in + (fun v -> + create_instance_direct (Lazy.force proto) (fkind v) + ) -let encode_bytes s = - encode_instance key_haxe_io_Bytes ~kind:(IBytes s) +let encode_bytes = + create_cached_instance key_haxe_io_Bytes (fun s -> IBytes s) -let encode_int_map_direct h = - encode_instance key_haxe_ds_IntMap ~kind:(IIntMap h) +let encode_int_map_direct = + create_cached_instance key_haxe_ds_IntMap (fun s -> IIntMap s) -let encode_string_map_direct h = - encode_instance key_haxe_ds_StringMap ~kind:(IStringMap h) +let encode_string_map_direct = + create_cached_instance key_haxe_ds_StringMap (fun s -> IStringMap s) -let encode_object_map_direct h = - encode_instance key_haxe_ds_ObjectMap ~kind:(IObjectMap (Obj.magic h)) +let encode_object_map_direct = + create_cached_instance key_haxe_ds_ObjectMap (fun (s : value ValueHashtbl.t) -> IObjectMap (Obj.magic s)) let encode_string_map convert m = - let h = StringHashtbl.create 0 in - PMap.iter (fun key value -> StringHashtbl.add h (Rope.of_string key,lazy key) (convert value)) m; + let h = StringHashtbl.create () in + PMap.iter (fun key value -> StringHashtbl.add h (create_ascii key) (convert value)) m; encode_string_map_direct h let fake_proto path = @@ -203,3 +280,11 @@ let encode_ref v convert tostr = iproto = ref_proto; ikind = IRef (Obj.repr v); } + +let encode_lazy f = + let rec r = ref (fun () -> + let v = f() in + r := (fun () -> v); + v + ) in + VLazy r diff --git a/src/macro/eval/evalExceptions.ml b/src/macro/eval/evalExceptions.ml index 1cf20ae4fb9..6b17ef1058f 100644 --- a/src/macro/eval/evalExceptions.ml +++ b/src/macro/eval/evalExceptions.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -30,7 +30,9 @@ exception Return of value exception Sys_exit of int let is v path = - path = key_Dynamic || match v with + if path = key_Dynamic then + v <> vnull + else match v with | VInt32 _ -> path = key_Int || path = key_Float | VFloat f -> path = key_Float || (path = key_Int && f = (float_of_int (int_of_float f)) && f <= 2147483647. && f >= -2147483648.) | VTrue | VFalse -> path = key_Bool @@ -73,9 +75,13 @@ let s_value_kind = function | VPrototype _ -> "VPrototype" | VFunction _ -> "VFunction" | VFieldClosure _ -> "VFieldClosure" + | VLazy _ -> "VLazy" let unexpected_value : 'a . value -> string -> 'a = fun v s -> - let str = Printf.sprintf "Unexpected value %s(%s), expected %s" (s_value_kind v) (value_string v) s in + let str = match v with + | VNull -> "Null Access" + | _ -> Printf.sprintf "Unexpected value %s(%s), expected %s" (s_value_kind v) (value_string v) s + in exc_string str let invalid_call_arg_number i i2 = @@ -89,52 +95,70 @@ let uncaught_exception_string v p extra = (Printf.sprintf "%s : Uncaught exception %s%s" (format_pos p) (value_string v) extra) let get_exc_error_message ctx v stack p = - let pl = List.map (fun env -> {pfile = rev_file_hash env.env_info.pfile;pmin = env.env_leave_pmin; pmax = env.env_leave_pmax}) stack in + let pl = List.map (fun env -> {pfile = rev_hash env.env_info.pfile;pmin = env.env_leave_pmin; pmax = env.env_leave_pmax}) stack in let pl = List.filter (fun p -> p <> null_pos) pl in match pl with | [] -> - let extra = if ctx.record_stack then "" else "\nNo stack information available, consider compiling with -D eval-stack" in - uncaught_exception_string v p extra + uncaught_exception_string v p "" | _ -> let sstack = String.concat "\n" (List.map (fun p -> Printf.sprintf "%s : Called from here" (format_pos p)) pl) in - Printf.sprintf "%s : Uncaught exception %s\n%s" (format_pos p) (value_string v) sstack + Printf.sprintf "%sUncaught exception %s\n%s" (if p = null_pos then "" else format_pos p ^ " : ") (value_string v) sstack -let build_exception_stack ctx environment_offset = - let eval = get_eval ctx in - let d = if not ctx.record_stack then [] else DynArray.to_list (DynArray.sub eval.environments environment_offset (eval.environment_offset - environment_offset)) in +let build_exception_stack ctx env = + let eval = env.env_eval in + let rec loop acc env' = + let acc = env' :: acc in + if env == env' then + List.rev acc + else match env'.env_parent with + | Some env -> loop acc env + | None -> assert false + in + let d = match eval.env with + | Some env -> loop [] env + | None -> [] + in ctx.exception_stack <- List.map (fun env -> - env.env_in_use <- false; - env.env_debug.timer(); - {pfile = rev_file_hash env.env_info.pfile;pmin = env.env_leave_pmin; pmax = env.env_leave_pmax},env.env_info.kind + {pfile = rev_hash env.env_info.pfile;pmin = env.env_leave_pmin; pmax = env.env_leave_pmax},env.env_info.kind ) d +let handle_stack_overflow eval f = + try f() + with Stack_overflow -> exc_string "Stack overflow" + let catch_exceptions ctx ?(final=(fun() -> ())) f p = let prev = !get_ctx_ref in select ctx; let eval = get_eval ctx in - let environment_offset = eval.environment_offset in + let env = eval.env in let r = try - let v = f() in + let v = handle_stack_overflow eval f in get_ctx_ref := prev; final(); Some v with | RunTimeException(v,stack,p') -> - build_exception_stack ctx environment_offset; - eval.environment_offset <- environment_offset; + eval.caught_exception <- vnull; + Option.may (build_exception_stack ctx) env; + eval.env <- env; if is v key_haxe_macro_Error then begin let v1 = field v key_message in let v2 = field v key_pos in get_ctx_ref := prev; final(); match v1,v2 with - | VString(_,s),VInstance {ikind = IPos p} -> - raise (Error.Error (Error.Custom (Lazy.force s),p)) + | VString s,VInstance {ikind = IPos p} -> + raise (Error.Error (Error.Custom s.sstring,p)) | _ -> Error.error "Something went wrong" null_pos end else begin (* Careful: We have to get the message before resetting the context because toString() might access it. *) - let msg = get_exc_error_message ctx v (match stack with [] -> [] | _ :: l -> l) (if p' = null_pos then p else p') in + let stack = match stack with + | [] -> [] + | l when p' = null_pos -> l (* If the exception position is null_pos, we're "probably" in a built-in function. *) + | _ :: l -> l (* Otherwise, ignore topmost frame position. *) + in + let msg = get_exc_error_message ctx v stack (if p' = null_pos then p else p') in get_ctx_ref := prev; final(); Error.error msg null_pos diff --git a/src/macro/eval/evalField.ml b/src/macro/eval/evalField.ml index 54da61908b1..b78dbd4578b 100644 --- a/src/macro/eval/evalField.ml +++ b/src/macro/eval/evalField.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -38,14 +38,13 @@ let instance_field vi name = vi.ifields.(get_instance_field_index_raise vi.iproto name) let object_field_raise o name = - try o.ofields.(get_instance_field_index_raise o.oproto name) - with Not_found -> IntMap.find name o.oextra + o.ofields.(get_instance_field_index_raise o.oproto name) let object_field o name = try object_field_raise o name with Not_found -> vnull let field_raise v f = - match v with + match vresolve v with | VObject o -> object_field_raise o f | VInstance {ikind = IBytes s} when f = key_length -> vint (Bytes.length s) | VPrototype proto -> proto_field_raise proto f @@ -55,8 +54,8 @@ let field_raise v f = | VVector vv -> if f = key_length then vint (Array.length vv) else proto_field_direct (get_ctx()).vector_prototype f - | VString (_,s) -> - if f = key_length then vint (String.length (Lazy.force s)) + | VString s -> + if f = key_length then vint (s.slength) else proto_field_direct (get_ctx()).string_prototype f | VInstance vi -> (try instance_field vi f with Not_found -> proto_field_raise vi.iproto f) | _ -> raise Not_found diff --git a/src/macro/eval/evalHash.ml b/src/macro/eval/evalHash.ml index 5d26dbf5f0e..bb3185c3ffa 100644 --- a/src/macro/eval/evalHash.ml +++ b/src/macro/eval/evalHash.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,122 +18,113 @@ *) let reverse_map = Hashtbl.create 0 -let file_map = Hashtbl.create 0 let rev_hash i = Hashtbl.find reverse_map i -let rev_hash_s i = Rope.to_string (rev_hash i) - let hash f = - let i = Hashtbl.hash (Rope.to_string f) in - Hashtbl.replace reverse_map i f; - i - -let hash_s f = let i = Hashtbl.hash f in - Hashtbl.replace reverse_map i (Rope.of_string f); + Hashtbl.replace reverse_map i f; i -let path_hash path = hash_s (Globals.s_type_path path) - -let file_hash file = - let unique_file = Path.unique_full_path file in - Hashtbl.replace file_map unique_file file; - hash_s unique_file - -let rev_file_hash i = - let s = rev_hash_s i in - try Hashtbl.find file_map s with Not_found -> s +let path_hash path = hash (Globals.s_type_path path) -let key_length = hash_s "length" -let key_toString = hash_s "toString" -let key_OutsideBounds = hash_s "OutsideBounds" -let key_low = hash_s "low" -let key_high = hash_s "high" -let key_next = hash_s "next" -let key_hasNext = hash_s "hasNext" -let key___meta__ = hash_s "__meta__" -let key_get = hash_s "get" -let key_pos = hash_s "pos" -let key_len = hash_s "len" -let key_message = hash_s "message" -let key_Array = hash_s "Array" -let key_eval_Vector = hash_s "eval.Vector" -let key_String = hash_s "String" -let key_haxe_ds_StringMap = hash_s "haxe.ds.StringMap" -let key_haxe_ds_IntMap = hash_s "haxe.ds.IntMap" -let key_haxe_ds_ObjectMap = hash_s "haxe.ds.ObjectMap" -let key_haxe_macro_Position = hash_s "haxe.macro.Position" -let key_haxe_macro_LazyType = hash_s "haxe.macro.LazyType" -let key_haxe_macro_TypeDecl = hash_s "haxe.macro.TypeDecl" -let key_haxe_Utf8 = hash_s "haxe.Utf8" -let key_haxe_macro_Ref = hash_s "haxe.macro.Ref" -let key_haxe_io_Error = hash_s "haxe.io.Error" -let key_haxe_io_Bytes = hash_s "haxe.io.Bytes" -let key_Date = hash_s "Date" -let key_Dynamic = hash_s "Dynamic" -let key_ValueType = hash_s "ValueType" -let key_EReg = hash_s "EReg" -let key_haxe_io_BytesBuffer = hash_s "haxe.io.BytesBuffer" -let key_StringBuf = hash_s "StringBuf" -let key_haxe_macro_Error = hash_s "haxe.macro.Error" -let key_Int = hash_s "Int" -let key_Float = hash_s "Float" -let key_Bool = hash_s "Bool" -let key_Class = hash_s "Class" -let key_Enum = hash_s "Enum" -let key_EnumValue = hash_s "EnumValue" -let key_gid = hash_s "gid" -let key_uid = hash_s "uid" -let key_atime = hash_s "atime" -let key_mtime = hash_s "mtime" -let key_ctime = hash_s "ctime" -let key_dev = hash_s "dev" -let key_ino = hash_s "ino" -let key_nlink = hash_s "nlink" -let key_rdev = hash_s "rdev" -let key_size = hash_s "size" -let key_mode = hash_s "mode" -let key_haxe__Int64____Int64 = hash_s "haxe._Int64.___Int64" -let key_haxe_macro_Unsafe = hash_s "haxe.macro.Unsafe" -let key_sys_io__Process_NativeProcess = hash_s "sys.io._Process.NativeProcess" -let key_sys_io_FileOutput = hash_s "sys.io.FileOutput" -let key_sys_io_FileInput = hash_s "sys.io.FileInput" -let key_haxe_io_Eof = hash_s "haxe.io.Eof" -let key_haxe_macro_ExprDef = hash_s "haxe.macro.ExprDef" -let key_haxe_macro_Binop = hash_s "haxe.macro.Binop" -let key_haxe_macro_Unop = hash_s "haxe.macro.Unop" -let key_haxe_macro_Constant = hash_s "haxe.macro.Constant" -let key_haxe_macro_TypeParam = hash_s "haxe.macro.TypeParam" -let key_haxe_macro_ComplexType = hash_s "haxe.macro.ComplexType" -let key_haxe_macro_FieldType = hash_s "haxe.macro.FieldType" -let key_haxe_macro_Type = hash_s "haxe.macro.Type" -let key_haxe_macro_FieldKind = hash_s "haxe.macro.FieldKind" -let key_haxe_macro_MethodKind = hash_s "haxe.macro.MethodKind" -let key_haxe_macro_VarAccess = hash_s "haxe.macro.VarAccess" -let key_haxe_macro_Access = hash_s "haxe.macro.Access" -let key_haxe_macro_ClassKind = hash_s "haxe.macro.ClassKind" -let key_haxe_macro_TypedExprDef = hash_s "haxe.macro.TypedExprDef" -let key_haxe_macro_TConstant = hash_s "haxe.macro.TConstant" -let key_haxe_macro_ModuleType = hash_s "haxe.macro.ModuleType" -let key_haxe_macro_FieldAccess = hash_s "haxe.macro.FieldAccess" -let key_haxe_macro_AnonStatus = hash_s "haxe.macro.AnonStatus" -let key_haxe_macro_ImportMode = hash_s "haxe.macro.ImportMode" -let key_haxe_macro_QuoteStatus = hash_s "haxe.macro.QuoteStatus" -let key_haxe_CallStack = hash_s "haxe.CallStack" -let key___init__ = hash_s "__init__" -let key_new = hash_s "new" -let key_questionmark = hash_s "?" -let key_haxe_StackItem = hash_s "haxe.StackItem" -let key_sys_net__Socket_NativeSocket = hash_s "sys.net._Socket.NativeSocket" -let key_ip = hash_s "ip" -let key_port = hash_s "port" -let key_sys_net_Socket = hash_s "sys.net.Socket" -let key_socket = hash_s "socket" -let key_read = hash_s "read" -let key_write = hash_s "write" -let key_others = hash_s "others" -let key_eval_vm_Thread = hash_s "eval.vm.Thread" -let key_haxe_zip_Compress = hash_s "haxe.zip.Compress" -let key_haxe_zip_Uncompress = hash_s "haxe.zip.Uncompress" -let key_done = hash_s "done" \ No newline at end of file +let key_length = hash "length" +let key_toString = hash "toString" +let key_OutsideBounds = hash "OutsideBounds" +let key_low = hash "low" +let key_high = hash "high" +let key_next = hash "next" +let key_hasNext = hash "hasNext" +let key___meta__ = hash "__meta__" +let key_get = hash "get" +let key_pos = hash "pos" +let key_len = hash "len" +let key_message = hash "message" +let key_Array = hash "Array" +let key_eval_Vector = hash "eval.Vector" +let key_String = hash "String" +let key_haxe_ds_StringMap = hash "haxe.ds.StringMap" +let key_haxe_ds_IntMap = hash "haxe.ds.IntMap" +let key_haxe_ds_ObjectMap = hash "haxe.ds.ObjectMap" +let key_haxe_macro_Position = hash "haxe.macro.Position" +let key_haxe_macro_LazyType = hash "haxe.macro.LazyType" +let key_haxe_macro_TypeDecl = hash "haxe.macro.TypeDecl" +let key_haxe_Utf8 = hash "haxe.Utf8" +let key_haxe_macro_Ref = hash "haxe.macro.Ref" +let key_haxe_io_Error = hash "haxe.io.Error" +let key_haxe_io_Bytes = hash "haxe.io.Bytes" +let key_Date = hash "Date" +let key_Dynamic = hash "Dynamic" +let key_ValueType = hash "ValueType" +let key_EReg = hash "EReg" +let key_haxe_io_BytesBuffer = hash "haxe.io.BytesBuffer" +let key_StringBuf = hash "StringBuf" +let key_haxe_macro_Error = hash "haxe.macro.Error" +let key_Int = hash "Int" +let key_Float = hash "Float" +let key_Bool = hash "Bool" +let key_Class = hash "Class" +let key_Enum = hash "Enum" +let key_EnumValue = hash "EnumValue" +let key_gid = hash "gid" +let key_uid = hash "uid" +let key_atime = hash "atime" +let key_mtime = hash "mtime" +let key_ctime = hash "ctime" +let key_dev = hash "dev" +let key_ino = hash "ino" +let key_nlink = hash "nlink" +let key_rdev = hash "rdev" +let key_size = hash "size" +let key_mode = hash "mode" +let key_haxe__Int64____Int64 = hash "haxe._Int64.___Int64" +let key_haxe_macro_Unsafe = hash "haxe.macro.Unsafe" +let key_sys_io__Process_NativeProcess = hash "sys.io._Process.NativeProcess" +let key_sys_io_FileOutput = hash "sys.io.FileOutput" +let key_sys_io_FileInput = hash "sys.io.FileInput" +let key_haxe_io_Eof = hash "haxe.io.Eof" +let key_haxe_macro_ExprDef = hash "haxe.macro.ExprDef" +let key_haxe_macro_Binop = hash "haxe.macro.Binop" +let key_haxe_macro_Unop = hash "haxe.macro.Unop" +let key_haxe_macro_Constant = hash "haxe.macro.Constant" +let key_haxe_macro_TypeParam = hash "haxe.macro.TypeParam" +let key_haxe_macro_ComplexType = hash "haxe.macro.ComplexType" +let key_haxe_macro_FieldType = hash "haxe.macro.FieldType" +let key_haxe_macro_Type = hash "haxe.macro.Type" +let key_haxe_macro_FieldKind = hash "haxe.macro.FieldKind" +let key_haxe_macro_MethodKind = hash "haxe.macro.MethodKind" +let key_haxe_macro_VarAccess = hash "haxe.macro.VarAccess" +let key_haxe_macro_Access = hash "haxe.macro.Access" +let key_haxe_macro_ClassKind = hash "haxe.macro.ClassKind" +let key_haxe_macro_TypedExprDef = hash "haxe.macro.TypedExprDef" +let key_haxe_macro_TConstant = hash "haxe.macro.TConstant" +let key_haxe_macro_ModuleType = hash "haxe.macro.ModuleType" +let key_haxe_macro_FieldAccess = hash "haxe.macro.FieldAccess" +let key_haxe_macro_AnonStatus = hash "haxe.macro.AnonStatus" +let key_haxe_macro_ImportMode = hash "haxe.macro.ImportMode" +let key_haxe_macro_QuoteStatus = hash "haxe.macro.QuoteStatus" +let key_haxe_macro_DisplayKind = hash "haxe.macro.DisplayKind" +let key_haxe_macro_Message = hash "haxe.macro.Message" +let key_haxe_CallStack = hash "haxe.CallStack" +let key___init__ = hash "__init__" +let key_new = hash "new" +let key_questionmark = hash "?" +let key_haxe_StackItem = hash "haxe.StackItem" +let key_sys_net__Socket_NativeSocket = hash "sys.net._Socket.NativeSocket" +let key_ip = hash "ip" +let key_port = hash "port" +let key_sys_net_Socket = hash "sys.net.Socket" +let key_socket = hash "socket" +let key_read = hash "read" +let key_write = hash "write" +let key_others = hash "others" +let key_eval_vm_Thread = hash "eval.vm.NativeThread" +let key_haxe_zip_Compress = hash "haxe.zip.Compress" +let key_haxe_zip_Uncompress = hash "haxe.zip.Uncompress" +let key_done = hash "done" +let key_eval_toplevel = hash "eval-toplevel" +let key_haxe_iterators_map_key_value_iterator = hash "haxe.iterators.MapKeyValueIterator" +let key_sys_net_Mutex = hash "sys.thread.Mutex" +let key_sys_net_Lock = hash "sys.thread.Lock" +let key_sys_net_Tls = hash "sys.thread.Tls" +let key_sys_net_Deque = hash "sys.thread.Deque" diff --git a/src/macro/eval/evalJit.ml b/src/macro/eval/evalJit.ml index c3e2ff0eff8..d91818bc4cc 100644 --- a/src/macro/eval/evalJit.ml +++ b/src/macro/eval/evalJit.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -24,18 +24,19 @@ open EvalValue open EvalContext open EvalHash open EvalEmitter +open EvalMisc (* Helper *) let rope_path t = match follow t with - | TInst({cl_path=path},_) | TEnum({e_path=path},_) | TAbstract({a_path=path},_) -> Rope.of_string (s_type_path path) - | TDynamic _ -> Rope.of_string "Dynamic" + | TInst({cl_path=path},_) | TEnum({e_path=path},_) | TAbstract({a_path=path},_) -> s_type_path path + | TDynamic _ -> "Dynamic" | TFun _ | TAnon _ | TMono _ | TType _ | TLazy _ -> assert false let eone = mk (TConst(TInt (Int32.one))) t_dynamic null_pos let eval_const = function - | TString s -> vstring (Rope.of_string s) + | TString s -> EvalString.create_unknown s | TInt i32 -> vint32 i32 | TFloat f -> vfloat (float_of_string f) | TBool b -> vbool b @@ -46,86 +47,62 @@ let is_int t = match follow t with | TAbstract({a_path=[],"Int"},_) -> true | _ -> false -let get_binop_fun op p = match op with - | OpAdd -> op_add - | OpMult -> op_mult p - | OpDiv -> op_div p - | OpSub -> op_sub p - | OpEq -> op_eq - | OpNotEq -> op_not_eq - | OpGt -> op_gt - | OpGte -> op_gte - | OpLt -> op_lt - | OpLte -> op_lte - | OpAnd -> op_and p - | OpOr -> op_or p - | OpXor -> op_xor p - | OpShl -> op_shl p - | OpShr -> op_shr p - | OpUShr -> op_ushr p - | OpMod -> op_mod p - | OpAssign | OpBoolAnd | OpBoolOr | OpAssignOp _ | OpInterval | OpArrow | OpIn -> assert false +let is_string t = match follow t with + | TInst({cl_path=[],"String"},_) -> true + | _ -> false + +let is_const_int_pattern (el,_) = + List.for_all (fun e -> match e.eexpr with + | TConst (TInt _) -> true + | _ -> false + ) el open EvalJitContext let rec op_assign ctx jit e1 e2 = match e1.eexpr with | TLocal var -> let exec = jit_expr jit false e2 in - if var.v_capture then emit_capture_write (get_capture_slot jit var.v_id) exec + if var.v_capture then emit_capture_write (get_capture_slot jit var) exec else emit_local_write (get_slot jit var.v_id e1.epos) exec - | TField(e1,fa) -> - let name = hash_s (field_name fa) in - let exec1 = jit_expr jit false e1 in + | TField(ef,fa) -> + let name = hash (field_name fa) in + let exec1 = jit_expr jit false ef in let exec2 = jit_expr jit false e2 in begin match fa with | FInstance({cl_path=(["haxe";"io"],"Bytes")},_,{cf_name="length"}) -> emit_bytes_length_write exec1 exec2 | FStatic({cl_path=path},_) | FEnum({e_path=path},_) -> - let proto = get_static_prototype jit.ctx (path_hash path) e1.epos in + let proto = get_static_prototype jit.ctx (path_hash path) ef.epos in emit_proto_field_write proto (get_proto_field_index proto name) exec2 | FInstance(c,_,_) when not c.cl_interface -> - let proto = get_instance_prototype jit.ctx (path_hash c.cl_path) e1.epos in - let i = get_instance_field_index proto name e1.epos in - emit_instance_field_write exec1 i exec2 + let proto = get_instance_prototype jit.ctx (path_hash c.cl_path) ef.epos in + let i = get_instance_field_index proto name ef.epos in + emit_instance_field_write exec1 ef.epos i exec2 | FAnon cf -> - begin match follow e1.etype with + begin match follow ef.etype with | TAnon an -> - let l = PMap.foldi (fun k _ acc -> (hash_s k,()) :: acc) an.a_fields [] in + let l = PMap.foldi (fun k _ acc -> (hash k,()) :: acc) an.a_fields [] in let proto,_ = ctx.get_object_prototype ctx l in - let i = get_instance_field_index proto name e1.epos in - emit_anon_field_write exec1 proto i name exec2 + let i = get_instance_field_index proto name ef.epos in + emit_anon_field_write exec1 ef.epos proto i name exec2 | _ -> - emit_field_write exec1 name exec2 + emit_field_write exec1 e1.epos name exec2 end | _ -> - emit_field_write exec1 name exec2 + emit_field_write exec1 e1.epos name exec2 end | TArray(ea1,ea2) -> begin match (follow ea1.etype) with | TInst({cl_path=(["eval"],"Vector")}, _) -> - begin match ea1.eexpr with - | TLocal var when not var.v_capture -> - let exec2 = jit_expr jit false ea2 in - let exec3 = jit_expr jit false e2 in - emit_vector_local_write (get_slot jit var.v_id ea1.epos) exec2 exec3 ea2.epos - | _ -> - let exec1 = jit_expr jit false ea1 in - let exec2 = jit_expr jit false ea2 in - let exec3 = jit_expr jit false e2 in - emit_vector_write exec1 exec2 exec3 ea2.epos - end + let exec1 = jit_expr jit false ea1 in + let exec2 = jit_expr jit false ea2 in + let exec3 = jit_expr jit false e2 in + emit_vector_write exec1 ea1.epos exec2 ea2.epos exec3 ea2.epos | _ -> - begin match ea1.eexpr with - | TLocal var when not var.v_capture -> - let exec2 = jit_expr jit false ea2 in - let exec3 = jit_expr jit false e2 in - emit_array_local_write (get_slot jit var.v_id ea1.epos) exec2 exec3 ea2.epos - | _ -> - let exec1 = jit_expr jit false ea1 in - let exec2 = jit_expr jit false ea2 in - let exec3 = jit_expr jit false e2 in - emit_array_write exec1 exec2 exec3 ea2.epos - end + let exec1 = jit_expr jit false ea1 in + let exec2 = jit_expr jit false ea2 in + let exec3 = jit_expr jit false e2 in + emit_array_write exec1 ea1.epos exec2 ea2.epos exec3 ea2.epos end | _ -> @@ -134,74 +111,44 @@ let rec op_assign ctx jit e1 e2 = match e1.eexpr with and op_assign_op jit op e1 e2 prefix = match e1.eexpr with | TLocal var -> let exec = jit_expr jit false e2 in - if var.v_capture then emit_capture_read_write (get_capture_slot jit var.v_id) exec op prefix + if var.v_capture then emit_capture_read_write (get_capture_slot jit var) exec op prefix else emit_local_read_write (get_slot jit var.v_id e1.epos) exec op prefix - | TField(e1,fa) -> - let name = hash_s (field_name fa) in - let exec1 = jit_expr jit false e1 in + | TField(ef,fa) -> + let name = hash (field_name fa) in + let exec1 = jit_expr jit false ef in let exec2 = jit_expr jit false e2 in begin match fa with | FStatic({cl_path=path},_) -> - let proto = get_static_prototype jit.ctx (path_hash path) e1.epos in + let proto = get_static_prototype jit.ctx (path_hash path) ef.epos in emit_proto_field_read_write proto (get_proto_field_index proto name) exec2 op prefix | FInstance(c,_,_) when not c.cl_interface -> - let proto = get_instance_prototype jit.ctx (path_hash c.cl_path) e1.epos in - let i = get_instance_field_index proto name e1.epos in - emit_instance_field_read_write exec1 i exec2 op prefix + let proto = get_instance_prototype jit.ctx (path_hash c.cl_path) ef.epos in + let i = get_instance_field_index proto name ef.epos in + emit_instance_field_read_write exec1 ef.epos i exec2 op prefix | _ -> - emit_field_read_write exec1 name exec2 op prefix + emit_field_read_write exec1 e1.epos name exec2 op prefix end | TArray(ea1,ea2) -> begin match (follow ea1.etype) with | TInst({cl_path=(["eval"],"Vector")}, _) -> - begin match ea1.eexpr with - | TLocal var when not var.v_capture -> - let exec2 = jit_expr jit false ea2 in - let exec3 = jit_expr jit false e2 in - emit_vector_local_read_write (get_slot jit var.v_id ea1.epos) exec2 exec3 op prefix ea2.epos - | _ -> - let exec1 = jit_expr jit false ea1 in - let exec2 = jit_expr jit false ea2 in - let exec3 = jit_expr jit false e2 in - emit_vector_read_write exec1 exec2 exec3 op prefix ea2.epos - end + let exec1 = jit_expr jit false ea1 in + let exec2 = jit_expr jit false ea2 in + let exec3 = jit_expr jit false e2 in + emit_vector_read_write exec1 ea1.epos exec2 ea2.epos exec3 op prefix | _ -> - begin match ea1.eexpr with - | TLocal var when not var.v_capture -> - let exec2 = jit_expr jit false ea2 in - let exec3 = jit_expr jit false e2 in - emit_array_local_read_write (get_slot jit var.v_id ea1.epos) exec2 exec3 op prefix ea2.epos - | _ -> - let exec1 = jit_expr jit false ea1 in - let exec2 = jit_expr jit false ea2 in - let exec3 = jit_expr jit false e2 in - emit_array_read_write exec1 exec2 exec3 op prefix ea2.epos - end + let exec1 = jit_expr jit false ea1 in + let exec2 = jit_expr jit false ea2 in + let exec3 = jit_expr jit false e2 in + emit_array_read_write exec1 ea1.epos exec2 ea2.epos exec3 op prefix end | _ -> assert false -and op_incr jit e1 prefix p = match e1.eexpr with - | TLocal var -> - begin match var.v_capture,prefix with - | true,true -> emit_capture_incr_prefix (get_capture_slot jit var.v_id) - | true,false -> emit_capture_incr_postfix (get_capture_slot jit var.v_id) - | false,true -> emit_local_incr_prefix (get_slot jit var.v_id e1.epos) - | false,false -> emit_local_incr_postfix (get_slot jit var.v_id e1.epos) - end - | _ -> - op_assign_op jit (get_binop_fun OpAdd p) e1 eone prefix +and op_incr jit e1 prefix p = + op_assign_op jit (get_binop_fun OpAdd p) e1 eone prefix -and op_decr jit e1 prefix p = match e1.eexpr with - | TLocal var -> - begin match var.v_capture,prefix with - | true,true -> emit_capture_decr_prefix (get_capture_slot jit var.v_id) - | true,false -> emit_capture_decr_postfix (get_capture_slot jit var.v_id) - | false,true -> emit_local_decr_prefix (get_slot jit var.v_id e1.epos) - | false,false -> emit_local_decr_postfix (get_slot jit var.v_id e1.epos) - end - | _ -> - op_assign_op jit (get_binop_fun OpSub p) e1 eone prefix +and op_decr jit e1 prefix p = + op_assign_op jit (get_binop_fun OpSub p) e1 eone prefix and unop jit op flag e1 p = match op with @@ -215,10 +162,27 @@ and unop jit op flag e1 p = let exec = jit_expr jit false e1 in emit_op_sub p (fun _ -> vint32 (Int32.minus_one)) exec | Increment -> - op_incr jit e1 (flag = Prefix) p + begin match Texpr.skip e1 with + | {eexpr = TLocal v} when not v.v_capture -> + let slot = get_slot jit v.v_id e1.epos in + if flag = Prefix then emit_local_incr_prefix slot e1.epos + else emit_local_incr_postfix slot e1.epos + | _ -> + op_incr jit e1 (flag = Prefix) p + end | Decrement -> op_decr jit e1 (flag = Prefix) p +and jit_default jit return def = + match def with + | None -> + emit_null + | Some e -> + push_scope jit e.epos; + let exec = jit_expr jit return e in + pop_scope jit; + exec + (* This is the main jit function. It turns expression [e] into a function, which can be executed int an environment of type [EvalContext.env]. @@ -242,7 +206,7 @@ and jit_expr jit return e = | TConst ct -> emit_const (eval_const ct) | TObjectDecl fl -> - let fl = List.map (fun ((s,_,_),e) -> hash_s s,jit_expr jit false e) fl in + let fl = List.map (fun ((s,_,_),e) -> hash s,jit_expr jit false e) fl in let proto,_ = ctx.get_object_prototype ctx fl in let fl = List.map (fun (s,exec) -> get_instance_field_index proto s e.epos,exec) fl in let fa = Array.of_list fl in @@ -257,15 +221,20 @@ and jit_expr jit return e = emit_type_expr proto | TFunction tf -> let jit_closure = EvalJitContext.create ctx in - jit_closure.captures <- jit.captures; - jit_closure.capture_infos <- jit.capture_infos; jit.num_closures <- jit.num_closures + 1; - let exec = jit_tfunction jit_closure true e.epos tf in - let num_captures = Hashtbl.length jit.captures in + let fl,exec = jit_tfunction jit_closure true e.epos tf in let hasret = jit_closure.has_nonfinal_return in - let get_env = get_env jit_closure false (file_hash tf.tf_expr.epos.pfile) (EKLocalFunction jit.num_closures) in - let num_args = List.length tf.tf_args in - emit_closure ctx num_captures num_args get_env hasret exec + let eci = get_env_creation jit_closure false tf.tf_expr.epos.pfile (EKLocalFunction jit.num_closures) in + let captures = Hashtbl.fold (fun vid (i,declared) acc -> (i,vid,declared) :: acc) jit_closure.captures [] in + let captures = List.sort (fun (i1,_,_) (i2,_,_) -> Pervasives.compare i1 i2) captures in + (* Check if the out-of-scope var is in the outer scope because otherwise we have to promote outwards. *) + List.iter (fun var -> ignore(get_capture_slot jit var)) jit_closure.captures_outside_scope; + let captures = ExtList.List.filter_map (fun (i,vid,declared) -> + if declared then None + else Some (i,fst (try Hashtbl.find jit.captures vid with Not_found -> Error.error "Something went wrong" e.epos)) + ) captures in + let mapping = Array.of_list captures in + emit_closure ctx mapping eci hasret exec fl (* branching *) | TIf(e1,e2,eo) -> let exec_cond = jit_expr jit false e1 in @@ -275,11 +244,11 @@ and jit_expr jit return e = | Some e -> jit_expr jit return e in emit_if exec_cond exec_then exec_else - | TSwitch(e1,cases,def) when is_int e1.etype -> + | TSwitch(e1,cases,def) when is_int e1.etype && List.for_all is_const_int_pattern cases -> let exec = jit_expr jit false e1 in let h = ref IntMap.empty in let max = ref 0 in - let shift = ref 0 in + let min = ref max_int in List.iter (fun (el,e) -> push_scope jit e.epos; let exec = jit_expr jit return e in @@ -287,128 +256,60 @@ and jit_expr jit return e = | TConst (TInt i32) -> let i = Int32.to_int i32 in h := IntMap.add i exec !h; - if i > !max then max := i - else if i < !shift then shift := i + if i > !max then max := i; + if i < !min then min := i; | _ -> assert false ) el; pop_scope jit; ) cases; - let exec_def = match def with - | None -> emit_null - | Some e -> - push_scope jit e.epos; - let exec = jit_expr jit return e in - pop_scope jit; - exec - in - let l = !max - !shift + 1 in - if l < 256 then begin - let cases = Array.init l (fun i -> try IntMap.find (i + !shift) !h with Not_found -> exec_def) in - if !shift = 0 then begin match (Texpr.skip e1).eexpr with - | TEnumIndex e1 -> - let exec = jit_expr jit false e1 in - emit_enum_switch_array exec cases exec_def e1.epos - | _ -> - emit_int_switch_array exec cases exec_def e1.epos - end else - emit_int_switch_array_shift (- !shift) exec cases exec_def e1.epos + let exec_def = jit_default jit return def in + let l = !max - !min + 1 in + if l > 0 && l < 256 then begin + let cases = Array.init l (fun i -> try IntMap.find (i + !min) !h with Not_found -> exec_def) in + emit_int_switch_array (- !min) exec cases exec_def e1.epos end else emit_int_switch_map exec !h exec_def e1.epos + (* | TSwitch(e1,cases,def) when is_string e1.etype -> + let exec = jit_expr jit false e1 in + let h = ref PMap.empty in + List.iter (fun (el,e) -> + push_scope jit e.epos; + let exec = jit_expr jit return e in + List.iter (fun e -> match e.eexpr with + | TConst (TString s) -> h := PMap.add s exec !h; + | _ -> assert false + ) el; + pop_scope jit; + ) cases; + let exec_def = jit_default jit return def in + emit_string_switch_map exec !h exec_def e1.epos *) | TSwitch(e1,cases,def) -> let exec = jit_expr jit false e1 in let execs = DynArray.create () in - let constants = DynArray.create () in - let patterns = DynArray.create () in - let is_complex = ref false in - (* This is slightly insane... *) - List.iter (fun (el,e) -> + let patterns = List.map (fun (el,e) -> push_scope jit e.epos; - begin try - if !is_complex then raise Exit; - let el = List.map (fun e -> match e.eexpr with - | TConst ct -> eval_const ct - | _ -> raise Exit - ) el in - DynArray.add constants el - with Exit -> - is_complex := true; - let el = List.map (jit_expr jit false) el in - DynArray.add patterns el - end; + let el = List.map (jit_expr jit false) el in DynArray.add execs (jit_expr jit return e); pop_scope jit; - ) cases; - let exec_def = match def with - | None -> - emit_null - | Some e -> - push_scope jit e.epos; - let exec = jit_expr jit return e in - pop_scope jit; - exec - in - if !is_complex then begin - let l = DynArray.length constants in - let all_patterns = Array.init (l + DynArray.length patterns) (fun i -> - if i >= l then DynArray.get patterns (i - l) else (List.map (fun ct -> fun _ -> ct) (DynArray.get constants i)) - ) in - emit_switch exec (DynArray.to_array execs) all_patterns exec_def - end else begin - emit_constant_switch exec (DynArray.to_array execs) (DynArray.to_array constants) exec_def - end + el + ) cases in + let exec_def = jit_default jit return def in + emit_switch exec (DynArray.to_array execs) (Array.of_list patterns) exec_def | TWhile({eexpr = TParenthesis e1},e2,flag) -> loop {e with eexpr = TWhile(e1,e2,flag)} - | TWhile({eexpr = TBinop(OpLt,{eexpr = TLocal v;epos=pv},eto)},e2,NormalWhile) when (Meta.has Meta.ForLoopVariable v.v_meta) -> - let has_break = ref false in - let has_continue = ref false in - let rec loop e = match e.eexpr with - | TUnop(Increment,_,({eexpr = TLocal v'} as e1)) when v == v' -> e1 - | TWhile _ | TFor _ -> e - | TBreak -> has_break := true; e - | TContinue -> has_continue := true; e - | _ -> Type.map_expr loop e - in - let e2 = loop e2 in - let slot = get_slot jit v.v_id pv in - let exec1 = jit_expr jit false eto in - let exec2 = jit_expr jit false e2 in - begin match !has_break,!has_continue with - | false,false -> emit_int_iterator slot exec1 exec2 pv eto.epos - | true,false -> emit_int_iterator_break slot exec1 exec2 pv eto.epos - | false,true -> emit_int_iterator_continue slot exec1 exec2 pv eto.epos - | true,true -> emit_int_iterator_break_continue slot exec1 exec2 pv eto.epos - end | TWhile(e1,e2,flag) -> - let has_break = ref false in - let has_continue = ref false in - let rec loop e = match e.eexpr with - | TContinue -> has_continue := true; if !has_break then raise Exit - | TBreak -> has_break := true; if !has_continue then raise Exit - | TFunction _ | TWhile _ | TFor _ -> () - | _ -> Type.iter loop e + let rec has_continue e = match e.eexpr with + | TContinue -> true + | TWhile _ | TFor _ | TFunction _ -> false + | _ -> check_expr has_continue e in - (try loop e2 with Exit -> ()); - begin match e1.eexpr with - | TBinop(OpGte,e1,{eexpr = TConst (TFloat s)}) when not !has_break && not !has_continue && flag = NormalWhile -> - let f = float_of_string s in - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit false e2 in - emit_while_gte exec1 f exec2 - | _ -> - let exec_cond = jit_expr jit false e1 in - let exec_body = jit_expr jit false e2 in - (* This is a bit moronic, but it does avoid run-time branching and setting up some exception - handlers for break/continue, so it might be worth it... *) - begin match flag,!has_break,!has_continue with - | NormalWhile,false,false -> emit_while exec_cond exec_body - | NormalWhile,true,false -> emit_while_break exec_cond exec_body - | NormalWhile,false,true -> emit_while_continue exec_cond exec_body - | NormalWhile,true,true -> emit_while_break_continue exec_cond exec_body - | DoWhile,false,false -> emit_do_while exec_cond exec_body - | DoWhile,true,false -> emit_do_while_break exec_cond exec_body - | DoWhile,false,true -> emit_do_while_continue exec_cond exec_body - | DoWhile,true,true -> emit_do_while_break_continue exec_cond exec_body - end + let exec_cond = jit_expr jit false e1 in + let exec_body = jit_expr jit false e2 in + begin match flag with + | NormalWhile -> + if has_continue e2 then emit_while_break_continue exec_cond exec_body + else emit_while_break exec_cond exec_body + | DoWhile -> emit_do_while_break_continue exec_cond exec_body end | TTry(e1,catches) -> let exec = jit_expr jit return e1 in @@ -418,106 +319,68 @@ and jit_expr jit return e = let exec = jit_expr jit return e in pop_scope jit; let key = hash (rope_path var.v_type) in - exec,key,varacc + let f = match varacc with + | Local slot -> emit_local_write slot + | Env slot -> emit_capture_write slot + in + exec,key,f ) catches in emit_try exec catches (* control flow *) | TBlock [] -> emit_null - | TBlock el when ctx.debug.support_debugger -> - let e1,el = match List.rev el with - | e1 :: el -> e1,List.rev el - | [] -> assert false - in - push_scope jit e.epos; - let execs = List.map (jit_expr jit false) el in - let exec1 = jit_expr jit return e1 in - pop_scope jit; - emit_block (Array.of_list (execs @ [exec1])) | TBlock [e1] -> push_scope jit e.epos; - let f = loop e1 in - pop_scope jit; - f - | TBlock [e1;e2] -> - push_scope jit e.epos; - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit return e2 in - pop_scope jit; - emit_block2 exec1 exec2 - | TBlock [e1;e2;e3] -> - push_scope jit e.epos; - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit false e2 in - let exec3 = jit_expr jit return e3 in - pop_scope jit; - emit_block3 exec1 exec2 exec3 - | TBlock [e1;e2;e3;e4] -> - push_scope jit e.epos; - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit false e2 in - let exec3 = jit_expr jit false e3 in - let exec4 = jit_expr jit return e4 in - pop_scope jit; - emit_block4 exec1 exec2 exec3 exec4 - | TBlock [e1;e2;e3;e4;e5] -> - push_scope jit e.epos; - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit false e2 in - let exec3 = jit_expr jit false e3 in - let exec4 = jit_expr jit false e4 in - let exec5 = jit_expr jit return e5 in + let exec = jit_expr jit return e1 in pop_scope jit; - emit_block5 exec1 exec2 exec3 exec4 exec5 + exec | TBlock el -> - let d = DynArray.create () in - let add = DynArray.add d in - let rec loop el = match el with - | e1 :: e2 :: e3 :: e4 :: e5 :: el -> - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit false e2 in - let exec3 = jit_expr jit false e3 in - let exec4 = jit_expr jit false e4 in - let exec5 = jit_expr jit (return && el = []) e5 in - add (emit_block5 exec1 exec2 exec3 exec4 exec5); - loop el - | e1 :: e2 :: e3 :: e4 :: el -> - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit false e2 in - let exec3 = jit_expr jit false e3 in - let exec4 = jit_expr jit (return && el = []) e4 in - add (emit_block4 exec1 exec2 exec3 exec4); - loop el - | e1 :: e2 :: e3 :: el -> - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit false e2 in - let exec3 = jit_expr jit (return && el = []) e3 in - add (emit_block3 exec1 exec2 exec3); - loop el - | e1 :: e2 :: el -> - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit (return && el = []) e2 in - add (emit_block2 exec1 exec2); - loop el - | [e1] -> - let exec1 = jit_expr jit return e1 in - add (emit_block1 exec1); + push_scope jit e.epos; + let rec loop acc el = match el with + | [e] -> + List.rev ((jit_expr jit return e) :: acc) + | e :: el -> + loop (jit_expr jit false e :: acc) el | [] -> - () + assert false in - push_scope jit e.epos; - loop el; + let el = loop [] el in pop_scope jit; - emit_block (DynArray.to_array d) + let rec step el = + let a = Array.of_list el in + let rec loop i acc = + if i >= 7 then begin + let f8 = emit_seq8 a.(i - 7) a.(i - 6) a.(i - 5) a.(i - 4) a.(i - 3) a.(i - 2) a.(i - 1) a.(i) in + loop (i - 8) (f8 :: acc) + end else if i >= 3 then begin + let f4 = emit_seq4 a.(i - 3) a.(i - 2) a.(i - 1) a.(i) in + loop (i - 4) (f4 :: acc) + end else if i >= 1 then begin + let f2 = emit_seq2 a.(i - 1) a.(i) in + loop (i - 2) (f2 :: acc) + end else if i = 0 then + ((a.(i)) :: acc) + else + acc + in + let length = Array.length a in + match loop (length - 1) [] with + | [] -> assert false + | [f] -> f + | fl -> step fl + in + step el | TReturn None -> - if return then emit_null + if return && not jit.ctx.debug.support_debugger then + emit_null else begin jit.has_nonfinal_return <- true; emit_return_null end | TReturn (Some e1) -> let exec = jit_expr jit false e1 in - if return then emit_value exec + if return && not jit.ctx.debug.support_debugger then + emit_value exec else begin jit.has_nonfinal_return <- true; emit_return_value exec @@ -538,31 +401,36 @@ and jit_expr jit return e = begin match e1.eexpr with | TField({eexpr = TConst TSuper;epos=pv},FInstance(c,_,cf)) -> let proto = get_instance_prototype ctx (path_hash c.cl_path) e1.epos in - let name = hash_s cf.cf_name in + let name = hash cf.cf_name in let i = get_proto_field_index proto name in let slot = get_slot jit 0 pv in let execs = List.map (jit_expr jit false) el in emit_super_field_call slot proto i execs e.epos | TField(ef,fa) -> - let name = hash_s (field_name fa) in + let name = hash (field_name fa) in let execs = List.map (jit_expr jit false) el in - (* let is_overridden c s_name = - try - Hashtbl.find ctx.overrides (c.cl_path,s_name) - with Not_found -> - false - in *) + let is_final c cf = + c.cl_final || (has_class_field_flag cf CfFinal) || + (* In interp mode we can assume that a field is final if it is not overridden. + We cannot do that in macro mode because overriding fields might be added + after jitting this call. *) + (not ctx.is_macro && not (Hashtbl.mem ctx.overrides (c.cl_path,cf.cf_name))) + in let is_proper_method cf = match cf.cf_kind with | Method MethDynamic -> false | Method _ -> true | Var _ -> false in - (* let instance_call c = + let lazy_proto_field proto = + let i = get_proto_field_index proto name in + lazy (match proto.pfields.(i) with VFunction (f,_) -> f | v -> cannot_call v e.epos) + in + let instance_call c = let exec = jit_expr jit false ef in let proto = get_instance_prototype ctx (path_hash c.cl_path) ef.epos in - let i = get_proto_field_index proto name in - emit_proto_field_call proto i (exec :: execs) e.epos - in *) + let v = lazy_proto_field proto in + emit_proto_field_call v (exec :: execs) e.epos + in let default () = let exec = jit_expr jit false ef in emit_method_call exec name execs e.epos @@ -575,33 +443,25 @@ and jit_expr jit return e = end | FEnum({e_path=path},ef) -> let key = path_hash path in - let pos = Some ef.ef_pos in - begin match execs with - | [] -> emit_enum_construction0 key ef.ef_index pos - | [exec1] -> emit_enum_construction1 key ef.ef_index exec1 pos - | [exec1;exec2] -> emit_enum_construction2 key ef.ef_index exec1 exec2 pos - | [exec1;exec2;exec3] -> emit_enum_construction3 key ef.ef_index exec1 exec2 exec3 pos - | [exec1;exec2;exec3;exec4] -> emit_enum_construction4 key ef.ef_index exec1 exec2 exec3 exec4 pos - | [exec1;exec2;exec3;exec4;exec5] -> emit_enum_construction5 key ef.ef_index exec1 exec2 exec3 exec4 exec5 pos - | _ -> emit_enum_construction key ef.ef_index (Array.of_list execs) pos - end + let pos = Some e.epos in + emit_enum_construction key ef.ef_index (Array.of_list execs) pos | FStatic({cl_path=path},cf) when is_proper_method cf -> let proto = get_static_prototype ctx (path_hash path) ef.epos in - let i = get_proto_field_index proto name in - emit_proto_field_call proto i execs e.epos + let v = lazy_proto_field proto in + emit_proto_field_call v execs e.epos | FInstance(c,_,cf) when is_proper_method cf -> - default(); - (* if is_overridden c cf.cf_name then + if not (is_final c cf) then default() else if not c.cl_interface then instance_call c - else if c.cl_implements = [] && c.cl_super = None then begin match c.cl_descendants with - | [c'] when not c'.cl_interface && not (is_overridden c' cf.cf_name) -> + (* If we have exactly one implementer, use it instead of the super class/interface. *) + else if not ctx.is_macro && c.cl_implements = [] && c.cl_super = None then begin match c.cl_descendants with + | [c'] when not c'.cl_interface && is_final c' cf -> instance_call c' | _ -> default() end else - default() *) + default() | _ -> let exec = jit_expr jit false ef in emit_field_call exec name execs e.epos @@ -616,7 +476,8 @@ and jit_expr jit return e = emit_special_super_call f execs with Not_found -> let fnew = get_instance_constructor jit.ctx key e1.epos in - emit_super_call fnew execs e.epos + let v = lazy (match Lazy.force fnew with VFunction (f,_) -> f | v -> cannot_call v e.epos) in + emit_super_call v execs e.epos end | _ -> assert false end @@ -627,23 +488,10 @@ and jit_expr jit return e = let exec2 = jit_expr jit false min in let exec3 = jit_expr jit false max in emit_mk_pos exec1 exec2 exec3 - | TIdent "$__delayed_call__",[{eexpr = TConst(TInt i)}] -> - let f = ctx.curapi.MacroApi.delayed_macro (Int32.to_int i) in - (fun env -> - let f = f() in - f() - ) | _ -> let exec = jit_expr jit false e1 in let execs = List.map (jit_expr jit false) el in - begin match execs with - | [] -> emit_call0 exec e.epos - | [exec1] -> emit_call1 exec exec1 e.epos - | [exec1;exec2] -> emit_call2 exec exec1 exec2 e.epos - | [exec1;exec2;exec3] -> emit_call3 exec exec1 exec2 exec3 e.epos - | [exec1;exec2;exec3;exec4] -> emit_call4 exec exec1 exec2 exec3 exec4 e.epos - | _ -> emit_call exec execs e.epos - end + emit_call exec execs e.epos end | TNew({cl_path=[],"Array"},_,_) -> emit_new_array @@ -664,38 +512,37 @@ and jit_expr jit return e = with Not_found -> let fnew = get_instance_constructor jit.ctx key e.epos in let proto = get_instance_prototype jit.ctx key e.epos in - emit_constructor_call proto fnew execs e.epos + let v = lazy (match Lazy.force fnew with VFunction (f,_) -> f | v -> cannot_call v e.epos) in + emit_constructor_call proto v execs e.epos end (* read *) | TLocal var -> - if var.v_capture then emit_capture_read (get_capture_slot jit var.v_id) + if var.v_capture then emit_capture_read (get_capture_slot jit var) else emit_local_read (get_slot jit var.v_id e.epos) | TField(e1,fa) -> - let name = hash_s (field_name fa) in + let name = hash (field_name fa) in begin match fa with - | FInstance({cl_path=([],"Array")},_,{cf_name="length"}) -> emit_array_length_read (jit_expr jit false e1) - | FInstance({cl_path=(["eval"],"Vector")},_,{cf_name="length"}) -> emit_vector_length_read (jit_expr jit false e1) - | FInstance({cl_path=(["haxe";"io"],"Bytes")},_,{cf_name="length"}) -> emit_bytes_length_read (jit_expr jit false e1) - | FStatic({cl_path=path},_) | FEnum({e_path=path},_) -> + | FInstance({cl_path=([],"Array")},_,{cf_name="length"}) -> emit_array_length_read (jit_expr jit false e1) e1.epos + | FInstance({cl_path=(["eval"],"Vector")},_,{cf_name="length"}) -> emit_vector_length_read (jit_expr jit false e1) e1.epos + | FInstance({cl_path=(["haxe";"io"],"Bytes")},_,{cf_name="length"}) -> emit_bytes_length_read (jit_expr jit false e1) e1.epos + | FStatic({cl_path=path},_) | FEnum({e_path=path},_) + | FInstance({cl_path=path},_,{cf_kind = Method (MethNormal | MethInline)}) -> let proto = get_static_prototype ctx (path_hash path) e1.epos in emit_proto_field_read proto (get_proto_field_index proto name) | FInstance(c,_,_) when not c.cl_interface -> let proto = get_instance_prototype ctx (path_hash c.cl_path) e1.epos in let i = get_instance_field_index proto name e1.epos in begin match e1.eexpr with - | TLocal var when not var.v_capture -> emit_instance_local_field_read (get_slot jit var.v_id e1.epos) i - | _ -> emit_instance_field_read (jit_expr jit false e1) i + | TConst TThis -> emit_this_field_read (get_slot jit 0 e.epos) i + | _ -> emit_instance_field_read (jit_expr jit false e1) e1.epos i end | FAnon _ -> begin match follow e1.etype with | TAnon an -> - let l = PMap.foldi (fun k _ acc -> (hash_s k,()) :: acc) an.a_fields [] in + let l = PMap.foldi (fun k _ acc -> (hash k,()) :: acc) an.a_fields [] in let proto,_ = ctx.get_object_prototype ctx l in let i = get_instance_field_index proto name e1.epos in - begin match e1.eexpr with - | TLocal var when not var.v_capture -> emit_anon_local_field_read (get_slot jit var.v_id e1.epos) proto i name e1.epos - | _ -> emit_anon_field_read (jit_expr jit false e1) proto i name e1.epos - end + emit_anon_field_read (jit_expr jit false e1) proto i name e1.epos | _ -> emit_field_read (jit_expr jit false e1) name e1.epos end @@ -709,30 +556,20 @@ and jit_expr jit return e = | TArray(e1,e2) -> begin match (follow e1.etype) with | TInst({cl_path=(["eval"],"Vector")}, _) -> - begin match e1.eexpr with - | TLocal var when not var.v_capture -> - emit_vector_local_read (get_slot jit var.v_id e1.epos) (jit_expr jit false e2) e2.epos - | _ -> - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit false e2 in - emit_vector_read exec1 exec2 e2.epos - end + let exec1 = jit_expr jit false e1 in + let exec2 = jit_expr jit false e2 in + emit_vector_read exec1 e1.epos exec2 e2.epos | _ -> - begin match e1.eexpr with - | TLocal var when not var.v_capture -> - emit_array_local_read (get_slot jit var.v_id e1.epos) (jit_expr jit false e2) e2.epos - | _ -> - let exec1 = jit_expr jit false e1 in - let exec2 = jit_expr jit false e2 in - emit_array_read exec1 exec2 e2.epos - end + let exec1 = jit_expr jit false e1 in + let exec2 = jit_expr jit false e2 in + emit_array_read exec1 e1.epos exec2 e2.epos end | TEnumParameter(e1,_,i) -> let exec = jit_expr jit false e1 in emit_enum_parameter_read exec i | TEnumIndex e1 -> let exec = jit_expr jit false e1 in - emit_enum_index exec + emit_enum_index exec e1.epos (* ops *) | TBinop(OpEq,e1,{eexpr = TConst TNull}) | TBinop(OpEq,{eexpr = TConst TNull},e1) -> let exec = jit_expr jit false e1 in @@ -759,7 +596,7 @@ and jit_expr jit return e = let exec1 = jit_expr jit false e1 in let exec2 = jit_expr jit false e2 in begin match op with - | OpAdd -> emit_op_add exec1 exec2 + | OpAdd -> emit_op_add e.epos exec1 exec2 | OpMult -> emit_op_mult e.epos exec1 exec2 | OpDiv -> emit_op_div e.epos exec1 exec2 | OpSub -> emit_op_sub e.epos exec1 exec2 @@ -783,76 +620,92 @@ and jit_expr jit return e = unop jit op flag v1 e.epos (* rewrites/skips *) | TFor(v,e1,e2) -> - loop (Codegen.for_remap (ctx.curapi.MacroApi.get_com()) v e1 e2 e.epos) + loop (Texpr.for_remap (ctx.curapi.MacroApi.get_com()).Common.basic v e1 e2 e.epos) | TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) -> loop e1 | TIdent s -> Error.error ("Unknown identifier: " ^ s) e.epos in let f = loop e in - if ctx.debug.support_debugger then begin match e.eexpr with - | TConst _ | TLocal _ | TTypeExpr _ | TBlock _ | TField _ -> f - | _ -> EvalDebug.debug_loop jit e f - end else - f + begin match ctx.debug.debug_socket with + | None -> + f + | Some socket -> + let wrap () = + EvalDebug.debug_loop jit socket.connection e f + in + begin match e.eexpr with + | TCall _ | TNew _ + | TVar({v_kind = VUser _},_) + | TFor _ | TIf _ | TWhile _ | TSwitch _ | TTry _ + | TReturn _ | TBreak | TContinue | TThrow _ | TCast(_,Some _) -> + wrap() + | TUnop((Increment | Decrement),_,e1) | TBinop((OpAssign | OpAssignOp _),e1,_) -> + begin match (Texpr.skip e1).eexpr with + | TLocal {v_kind = VGenerated | VInlined | VInlinedConstructorVariable | VExtractorVariable} -> + f + | _ -> + wrap() + end + | _ -> + f + end + end and jit_tfunction jit static pos tf = let ctx = jit.ctx in push_scope jit pos; (* Declare `this` (if not static) and function arguments as local variables. *) if not static then ignore(declare_local_this jit); - let varaccs = ExtList.List.filter_map (fun (var,_) -> - let slot = add_local jit var in - if var.v_capture then Some (slot,add_capture jit var) else None + let fl = List.map (fun (var,_) -> + let varacc = declare_local jit var in + match varacc with + | Env slot -> execute_set_capture slot + | Local slot -> execute_set_local slot ) tf.tf_args in + let fl = if static then fl else (execute_set_local 0) :: fl in (* Add conditionals for default values. *) let e = List.fold_left (fun e (v,cto) -> match cto with | None -> e - | Some ct -> concat (Codegen.set_default (ctx.curapi.MacroApi.get_com()) v ct e.epos) e + | Some ct -> concat (Texpr.set_default (ctx.curapi.MacroApi.get_com()).Common.basic v ct e.epos) e ) tf.tf_expr tf.tf_args in + let has_final_return el = match List.rev el with + | {eexpr = TReturn _} :: _ -> true + | _ -> false + in + let e = match e.eexpr with + | TBlock el when ctx.debug.support_debugger && (ExtType.is_void (follow tf.tf_type)) && not (has_final_return el) -> + {e with eexpr = TBlock (el @ [mk (TReturn None) t_dynamic {pos with pmin = pos.pmax}])} + | _ -> + e + in (* Jit the function expression. *) let exec = jit_expr jit true e in - (* Deal with captured arguments, if necessary. *) - let exec = match varaccs with - | [] -> exec - | _ -> handle_capture_arguments exec varaccs - in pop_scope jit; - exec + fl,exec -and get_env jit static file info = - let ctx = jit.ctx in - let num_locals = jit.max_num_locals in - let num_captures = Hashtbl.length jit.captures in - let info = create_env_info static file info jit.capture_infos in - if ctx.record_stack || num_captures > 0 then begin - match info.kind with - | EKLocalFunction _ -> get_closure_env ctx info num_locals num_captures - | _ -> get_normal_env ctx info num_locals num_captures - end else begin - let default_env = create_default_environment ctx info num_locals in - match info.kind with - | EKLocalFunction _ -> get_closure_env_opt ctx default_env info num_locals num_captures - | _ -> get_normal_env_opt ctx default_env info num_locals num_captures - end +and get_env_creation jit static file info = { + ec_info = create_env_info static file info jit.capture_infos; + ec_num_locals = jit.max_num_locals; + ec_num_captures = Hashtbl.length jit.captures; +} (* Creates a [EvalValue.vfunc] of function [tf], which can be [static] or not. *) let jit_tfunction ctx key_type key_field tf static pos = - let t = Common.timer [(if ctx.is_macro then "macro" else "interp");"jit"] in + let t = Timer.timer [(if ctx.is_macro then "macro" else "interp");"jit"] in (* Create a new JitContext with an initial scope *) let jit = EvalJitContext.create ctx in - let exec = jit_tfunction jit static pos tf in + let fl,exec = jit_tfunction jit static pos tf in (* Create the [vfunc] instance depending on the number of arguments. *) let hasret = jit.has_nonfinal_return in - let get_env = get_env jit static (file_hash tf.tf_expr.epos.pfile) (EKMethod(key_type,key_field)) in - let num_args = List.length tf.tf_args + (if not static then 1 else 0) in - let f = create_function ctx num_args get_env hasret empty_array exec in + let eci = get_env_creation jit static tf.tf_expr.epos.pfile (EKMethod(key_type,key_field)) in + let f = if hasret then create_function ctx eci exec fl else create_function_noret ctx eci exec fl in t(); f (* JITs expression [e] to a function. This is used for expressions that are not in a method. *) let jit_expr ctx e = - let t = Common.timer [(if ctx.is_macro then "macro" else "interp");"jit"] in + let t = Timer.timer [(if ctx.is_macro then "macro" else "interp");"jit"] in let jit = EvalJitContext.create ctx in let f = jit_expr jit false (mk_block e) in t(); diff --git a/src/macro/eval/evalJitContext.ml b/src/macro/eval/evalJitContext.ml index 522f2ff0d07..c6870c77676 100644 --- a/src/macro/eval/evalJitContext.ml +++ b/src/macro/eval/evalJitContext.ml @@ -1,6 +1,9 @@ open Type open EvalContext -open EvalEmitter + +type varacc = + | Local of int + | Env of int (* JitContext keeps track of allocated local variables and closures. Scopes can be pushed @@ -14,7 +17,7 @@ type t = { (* The scope stack. *) mutable scopes : scope list; (* The captured variables declared in this context. Maps variable IDs to capture slots. *) - mutable captures : (int,int) Hashtbl.t; + mutable captures : (int,int * bool) Hashtbl.t; (* The current number of locals. *) mutable num_locals : int; (* The maximum number of locals. *) @@ -25,8 +28,17 @@ type t = { mutable has_nonfinal_return : bool; (* The name of capture variables. Maps local slots to variable names. Only filled in debug mode. *) mutable capture_infos : (int,var_info) Hashtbl.t; + (* Variables which are accessed but not declared in this scope. *) + mutable captures_outside_scope : tvar list; } +let var_info_of_var var = + { + vi_name = var.v_name; + vi_pos = var.v_pos; + vi_generated = (match var.v_kind with VUser _ -> false | _ -> true) + } + (* Creates a new context *) let create ctx = { ctx = ctx; @@ -37,6 +49,7 @@ let create ctx = { num_closures = 0; has_nonfinal_return = false; capture_infos = Hashtbl.create 0; + captures_outside_scope = [] } (* Returns the number of locals in [scope]. *) @@ -68,11 +81,11 @@ let increase_num_locals jit = if jit.num_locals > jit.max_num_locals then jit.max_num_locals <- jit.num_locals (* Adds capture variable [var] to context [jit]. *) -let add_capture jit var = +let add_capture jit var declared = let i = Hashtbl.length jit.captures in - Hashtbl.add jit.captures var.v_id i; + Hashtbl.add jit.captures var.v_id (i,declared); if jit.ctx.debug.support_debugger then begin - Hashtbl.replace jit.capture_infos i var.v_name + Hashtbl.replace jit.capture_infos i (var_info_of_var var) end; i @@ -85,8 +98,9 @@ let add_local jit var = match jit.scopes with increase_num_locals jit; let slot = scope.local_offset + i in if jit.ctx.debug.support_debugger then begin + if Typecore.is_gen_local var then var.v_name <- "_g" ^ String.sub var.v_name 1 (String.length var.v_name - 1); Hashtbl.replace scope.local_ids var.v_name var.v_id; - Hashtbl.replace scope.local_infos i var.v_name + Hashtbl.replace scope.local_infos i (var_info_of_var var) end; slot @@ -97,7 +111,7 @@ let add_local jit var = match jit.scopes with Returns either [Env slot] if the variable is captured or [Local slot] otherwise. *) let declare_local jit var = - if var.v_capture then Env (add_capture jit var) + if var.v_capture then Env (add_capture jit var true) else Local (add_local jit var) (* @@ -108,7 +122,7 @@ let declare_local jit var = *) let declare_arg jit var = let varacc = add_local jit var in - if var.v_capture then add_capture jit var,Some varacc else varacc,None + if var.v_capture then add_capture jit var true,Some varacc else varacc,None (* Declares a variable for `this` in context [jit]. *) let declare_local_this jit = match jit.scopes with @@ -119,7 +133,7 @@ let declare_local_this jit = match jit.scopes with increase_num_locals jit; if jit.ctx.debug.support_debugger then begin Hashtbl.replace scope.local_ids "this" 0; - Hashtbl.replace scope.local_infos 0 "this" + Hashtbl.replace scope.local_infos 0 { vi_name = "this"; vi_pos = Globals.null_pos; vi_generated = false } end; Local i @@ -137,8 +151,11 @@ let get_slot_raise jit vid = let get_slot jit vid p = try get_slot_raise jit vid - with Not_found -> throw_string "Unbound variable" p + with Not_found -> EvalMisc.throw_string "Unbound variable" p (* Gets the slot of captured variable id [vid] in context [jit]. *) -let get_capture_slot jit vid = - Hashtbl.find jit.captures vid \ No newline at end of file +let get_capture_slot jit var = + try fst (Hashtbl.find jit.captures var.v_id) + with Not_found -> + jit.captures_outside_scope <- var :: jit.captures_outside_scope; + add_capture jit var false \ No newline at end of file diff --git a/src/macro/eval/evalMain.ml b/src/macro/eval/evalMain.ml index 9f08aae1e8d..dab540c1d96 100644 --- a/src/macro/eval/evalMain.ml +++ b/src/macro/eval/evalMain.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -41,8 +41,10 @@ let sid = ref (-1) let stdlib = ref None let debug = ref None +let debugger_initialized = ref false + let create com api is_macro = - let t = Common.timer [(if is_macro then "macro" else "interp");"create"] in + let t = Timer.timer [(if is_macro then "macro" else "interp");"create"] in incr sid; let builtins = match !stdlib with | None -> @@ -69,25 +71,27 @@ let create com api is_macro = raise Exit in let s = Common.defined_value com Define.EvalDebugger in - if s = "1" then raise Exit; let host,port = try ExtString.String.split s ":" with _ -> fail "Invalid host format, expected host:port" in - let host = try Unix.inet_addr_of_string host with exc -> fail (Printexc.to_string exc) in let port = try int_of_string port with _ -> fail "Invalid port, expected int" in - let socket = try (Unix.socket Unix.PF_INET Unix.SOCK_STREAM) 0 with exc -> fail (Printexc.to_string exc) in - Unix.connect socket (Unix.ADDR_INET (host,port)); - Some {addr = host; port = port; socket = Some socket} + Some (try + let socket = Socket.create host port in + { + socket = socket; + connection = EvalDebugSocket.make_connection socket; + }; + with exc -> + fail (Printexc.to_string exc) + ) with _ -> None in let debug' = { - debug = com.Common.debug || support_debugger; breakpoints = Hashtbl.create 0; + function_breakpoints = Hashtbl.create 0; support_debugger = support_debugger; - debug_state = DbgStart; - breakpoint = EvalDebugMisc.make_breakpoint 0 0 BPDisabled BPAny; - caught_types = Hashtbl.create 0; - environment_offset_delta = 0; debug_socket = socket; + exception_mode = CatchUncaught; + debug_context = new eval_debug_context; } in debug := Some debug'; debug' @@ -95,18 +99,17 @@ let create com api is_macro = debug in let detail_times = Common.defined com Define.EvalTimes in - let record_stack = debug.support_debugger || detail_times || Common.defined com Define.EvalStack in - let evals = DynArray.create () in - let eval = { - environments = DynArray.make 32; - environment_offset = 0; + let thread = { + tthread = Thread.self(); + tstorage = IntMap.empty; + tdeque = EvalThread.Deque.create(); } in - DynArray.add evals eval; + let eval = EvalThread.create_eval thread in + let evals = IntMap.singleton 0 eval in let rec ctx = { ctx_id = !sid; is_macro = is_macro; debug = debug; - record_stack = record_stack; detail_times = detail_times; curapi = api; builtins = builtins; @@ -117,28 +120,35 @@ let create com api is_macro = string_prototype = fake_proto key_String; array_prototype = fake_proto key_Array; vector_prototype = fake_proto key_eval_Vector; - static_prototypes = IntMap.empty; + static_prototypes = new static_prototypes; instance_prototypes = IntMap.empty; constructors = IntMap.empty; get_object_prototype = get_object_prototype; (* eval *) + toplevel = vobject { + ofields = [||]; + oproto = fake_proto key_eval_toplevel; + }; eval = eval; + evals = evals; exception_stack = []; + max_stack_depth = int_of_string (Common.defined_value_safe ~default:"1000" com Define.EvalCallStackDepth); } in + if debug.support_debugger && not !debugger_initialized then begin + (* Let's wait till the debugger says we're good to continue. This allows it to finish configuration. + Note that configuration is shared between macro and interpreter contexts, which is why the check + is governed by a global variable. *) + debugger_initialized := true; + (* There's select_ctx in the json-rpc handling, so let's select this one. It's fine because it's the + first context anyway. *) + select ctx; + ignore(Event.sync(Event.receive eval.debug_channel)); + end; t(); ctx (* API for macroContext.ml *) -let eval_delayed ctx e = - let jit,f = jit_expr ctx e in - let info = create_env_info true (file_hash e.epos.pfile) EKDelayed jit.capture_infos in - fun () -> - let env = push_environment ctx info jit.max_num_locals (Hashtbl.length jit.captures) in - match catch_exceptions ctx (fun () -> Std.finally (fun _ -> pop_environment ctx env) f env) e.epos with - | Some v -> v - | None -> vnull - let call_path ctx path f vl api = if ctx.had_error then None @@ -151,8 +161,15 @@ let call_path ctx path f vl api = in catch_exceptions ctx ~final:(fun () -> ctx.curapi <- old) (fun () -> let vtype = get_static_prototype_as_value ctx (path_hash path) api.pos in - let vfield = field vtype (hash_s f) in - call_value_on vtype vfield vl + let vfield = field vtype (hash f) in + let p = api.pos in + let info = create_env_info true p.pfile EKEntrypoint (Hashtbl.create 0) in + let env = push_environment ctx info 0 0 in + env.env_leave_pmin <- p.pmin; + env.env_leave_pmax <- p.pmax; + let v = call_value_on vtype vfield vl in + pop_environment ctx env; + v ) api.pos end @@ -170,9 +187,9 @@ let value_signature v = Hashtbl.add scache s (Hashtbl.length scache); addc 'y'; let s = EvalStdLib.StdStringTools.url_encode s in - add (string_of_int (Rope.length s)); + add (string_of_int (String.length s)); addc ':'; - add (Rope.to_string s) + add s in let cache = ValueHashtbl.create 0 in let cache_length = ref 0 in @@ -207,7 +224,7 @@ let value_signature v = | VEnumValue ve -> cache v (fun () -> addc 'j'; - adds (rev_hash_s ve.epath); + adds (rev_hash ve.epath); addc ':'; add (string_of_int ve.eindex); addc ':'; @@ -224,13 +241,13 @@ let value_signature v = | VInstance {ikind = IDate f} -> cache v (fun () -> addc 'v'; - add (Rope.to_string (s_date f)) + add ((s_date f).sstring) ) | VInstance {ikind = IStringMap map} -> cache v (fun() -> addc 'b'; - StringHashtbl.iter (fun (_,s) value -> - adds (Lazy.force s); + StringHashtbl.iter (fun s (_,value) -> + adds s; loop value ) map; addc 'h' @@ -271,13 +288,13 @@ let value_signature v = | VInstance i -> cache v (fun () -> addc 'c'; - adds (rev_hash_s i.iproto.ppath); + adds (rev_hash i.iproto.ppath); let fields = instance_fields i in loop_fields fields; addc 'g'; ) - | VString(_,s) -> - adds (Lazy.force s) + | VString s -> + adds s.sstring | VArray {avalues = a} | VVector a -> cache v (fun () -> addc 'a'; @@ -301,10 +318,10 @@ let value_signature v = ) | VPrototype {pkind = PClass _; ppath = path} -> addc 'A'; - adds (rev_hash_s path) + adds (rev_hash path) | VPrototype {pkind = PEnum _; ppath = path} -> addc 'B'; - adds (rev_hash_s path) + adds (rev_hash path) | VPrototype _ -> assert false | VFunction _ | VFieldClosure _ -> @@ -314,9 +331,11 @@ let value_signature v = add (string_of_int !function_count); incr function_count ) + | VLazy f -> + loop (!f()) and loop_fields fields = List.iter (fun (name,v) -> - adds (rev_hash_s name); + adds (rev_hash name); loop v; ) fields in @@ -339,37 +358,36 @@ let setup get_api = let api = get_api (fun() -> (get_ctx()).curapi.get_com()) (fun() -> (get_ctx()).curapi) in List.iter (fun (n,v) -> match v with | VFunction(f,b) -> - let v = match f with - | Fun0 f -> VFunction (Fun0 (fun () -> try f () with Sys_error msg | Failure msg -> exc_string msg),b) - | Fun1 f -> VFunction (Fun1 (fun a -> try f a with Sys_error msg | Failure msg -> exc_string msg),b) - | Fun2 f -> VFunction (Fun2 (fun a b -> try f a b with Sys_error msg | Failure msg -> exc_string msg),b) - | Fun3 f -> VFunction (Fun3 (fun a b c -> try f a b c with Sys_error msg | Failure msg -> exc_string msg),b) - | Fun4 f -> VFunction (Fun4 (fun a b c d -> try f a b c d with Sys_error msg | Failure msg -> exc_string msg),b) - | Fun5 f -> VFunction (Fun5 (fun a b c d e -> try f a b c d e with Sys_error msg | Failure msg -> exc_string msg),b) - | FunN f -> VFunction (FunN (fun vl -> try f vl with Sys_error msg | Failure msg -> exc_string msg),b) + let f vl = try + f vl + with + | Sys_error msg | Failure msg | Invalid_argument msg -> + exc_string msg + | MacroApi.Invalid_expr -> + exc_string "Invalid expression" in + let v = VFunction (f,b) in Hashtbl.replace EvalStdLib.macro_lib n v | _ -> assert false ) api; Globals.macro_platform := Globals.Eval -let can_reuse ctx types = true - let do_reuse ctx api = - ctx.curapi <- api + ctx.curapi <- api; + ctx.static_prototypes#set_needs_reset let set_error ctx b = (* TODO: Have to reset this somewhere if running compilation server. But where... *) ctx.had_error <- b let add_types ctx types ready = - ignore(catch_exceptions ctx (fun () -> ignore(add_types ctx types ready)) null_pos) + if not ctx.had_error then ignore(catch_exceptions ctx (fun () -> ignore(add_types ctx types ready)) null_pos) let compiler_error msg pos = let vi = encode_instance key_haxe_macro_Error in match vi with | VInstance i -> - set_instance_field i key_message (encode_string msg); + set_instance_field i key_message (EvalString.create_unknown msg); set_instance_field i key_pos (encode_pos pos); exc vi | _ -> @@ -389,24 +407,28 @@ let rec value_to_expr v p = in make_path mt in - match v with + match vresolve v with | VNull -> (EConst (Ident "null"),p) | VTrue -> (EConst (Ident "true"),p) | VFalse -> (EConst (Ident "false"),p) | VInt32 i -> (EConst (Int (Int32.to_string i)),p) | VFloat f -> haxe_float f p - | VString(r,s) -> (EConst (String (Lazy.force s)),p) + | VString s -> (EConst (String s.sstring),p) | VArray va -> (EArrayDecl (List.map (fun v -> value_to_expr v p) (EvalArray.to_list va)),p) - | VObject o -> (EObjectDecl (List.map (fun (k,v) -> - let n = rev_hash_s k in - ((n,p,(if Lexer.is_valid_identifier n then NoQuotes else DoubleQuotes)),(value_to_expr v p)) + | VObject o -> (EObjectDecl (ExtList.List.filter_map (fun (k,v) -> + let n = rev_hash k in + (* Workaround for #8261: Ignore generated pos fields *) + begin match v with + | VInstance {ikind = IPos _} when n = "pos" -> None + | _ -> Some ((n,p,(if Lexer.is_valid_identifier n then NoQuotes else DoubleQuotes)),(value_to_expr v p)) + end ) (object_fields o)),p) | VEnumValue e -> let epath = let proto = get_static_prototype_raise (get_ctx()) e.epath in let expr = path e.epath in let name = match proto.pkind with - | PEnum names -> List.nth names e.eindex + | PEnum names -> fst (List.nth names e.eindex) | _ -> assert false in (EField (expr, name), p) @@ -418,15 +440,126 @@ let rec value_to_expr v p = let args = List.map (fun v -> value_to_expr v p) (Array.to_list e.eargs) in (ECall (epath, args), p) end - | _ -> exc_string ("Cannot convert " ^ (value_string v) ^ " to expr") let encode_obj = encode_obj_s -let field v f = field v (EvalHash.hash_s f) +let field v f = field v (EvalHash.hash f) let value_string = value_string let exc_string = exc_string -let eval_expr ctx e = eval_expr ctx key_questionmark key_questionmark e \ No newline at end of file +let eval_expr ctx e = if ctx.had_error then None else eval_expr ctx EKEntrypoint e + +let handle_decoding_error f v t = + let line = ref 1 in + let errors = ref [] in + let error msg v = + errors := (msg,!line) :: !errors; + f (Printf.sprintf "%s <- %s" (value_string v) msg) + in + let rec loop tabs t v = + match t with + | TAnon an -> + f "{"; + PMap.iter (fun _ cf -> + incr line; + f (Printf.sprintf "\n%s%s: " (tabs ^ "\t") cf.cf_name); + try + let vf = field_raise v (EvalHash.hash cf.cf_name) in + begin match vf with + | VNull when not (is_explicit_null cf.cf_type) -> error "expected value" vf + | _ -> loop (tabs ^ "\t") cf.cf_type vf + end + with Not_found -> + if not (is_explicit_null cf.cf_type) then error "expected value" VNull + else f "null" + ) an.a_fields; + incr line; + f (Printf.sprintf "\n%s}" tabs) + | TInst({cl_path=[],"Array"},[t1]) -> + begin match v with + | VArray va -> + f "["; + let _ = List.fold_left (fun first v -> + if not first then f ", "; + loop tabs t1 v; + false + ) true (EvalArray.to_list va) in + f "]" + | _ -> error "expected Array" v + end + | TInst({cl_path=[],"String"},_) -> + begin match v with + | VString _ -> f (value_string v) + | _ -> error "expected String" v + end + | TAbstract({a_path=[],"Null"},[t1]) -> + if v = VNull then f "null" else loop tabs t1 v + | TAbstract({a_path=[],"Bool"},_) -> + begin match v with + | VTrue -> f "true" + | VFalse -> f "false" + | _ -> error "expected Bool" v + end + | TAbstract({a_path=[],("Int" | "Float")},_) -> + begin match v with + | VInt32 _ | VFloat _ -> f (value_string v) + | _ -> error "expected Bool" v + end + | TType(t,tl) -> + loop tabs (apply_params t.t_params tl t.t_type) v + | TAbstract({a_path=["haxe";"macro"],"Position"},_) -> + begin match v with + | VInstance {ikind=IPos _} -> f "#pos" + | _ -> error "expected Position" v + end + | TEnum(en,_) -> + begin match v with + | VEnumValue ev -> + let ef = PMap.find (List.nth en.e_names ev.eindex) en.e_constrs in + f ef.ef_name; + let rec loop2 first tl vl = match tl,vl with + | _,[] -> () + | [],_ -> () + | (_,_,t) :: tl,v :: vl -> + if not first then f ", "; + loop tabs t v; + loop2 false tl vl + in + begin match follow ef.ef_type,Array.to_list ev.eargs with + | _,[] -> + () + | TFun(tl,_),vl -> + f "("; + loop2 true tl vl; + f ")" + | _ -> () + end + | _ -> error "expected enum value" v + end + | TInst _ | TAbstract _ | TFun _ -> + (* TODO: might need some more of these, not sure *) + assert false + | TMono r -> + begin match !r with + | None -> () + | Some t -> loop tabs t v + end + | TLazy r -> + loop tabs (lazy_type r) v + | TDynamic _ -> + () + in + loop "" t v; + !errors + +let get_api_call_pos () = + let eval = get_eval (get_ctx()) in + let env = Option.get eval.env in + let env = match env.env_parent with + | None -> env + | Some env -> env + in + { pfile = rev_hash env.env_info.pfile; pmin = env.env_leave_pmin; pmax = env.env_leave_pmax } \ No newline at end of file diff --git a/src/macro/eval/evalMisc.ml b/src/macro/eval/evalMisc.ml index a3cf0ac7986..86dbf27af84 100644 --- a/src/macro/eval/evalMisc.ml +++ b/src/macro/eval/evalMisc.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,6 +18,7 @@ *) open Globals +open Ast open Type open EvalValue open EvalContext @@ -26,6 +27,19 @@ open EvalDecode open EvalExceptions open EvalPrinting open EvalHash +open EvalString + +let throw_string s p = + throw (create_unknown s) p + +let invalid_binop op v1 v2 p = + throw_string (Printf.sprintf "Invalid operation: %s %s %s" (value_string v1) (s_binop op) (value_string v2)) p + +let update_object_prototype o fields = + let ctx = get_ctx() in + let proto,fields = ctx.get_object_prototype (get_ctx()) fields in + o.ofields <- Array.of_list (List.map snd fields); + o.oproto <- proto (* Calls *) @@ -47,9 +61,10 @@ let set_instance_field vi name v2 = let set_object_field o name v2 = try o.ofields.(get_instance_field_index_raise o.oproto name) <- v2; - o.oremoved <- IntMap.remove name o.oremoved; with Not_found -> - o.oextra <- IntMap.add name v2 o.oextra + let fields = IntMap.fold (fun name i acc -> (name,o.ofields.(i)) :: acc) o.oproto.pinstance_names [] in + let fields = (name,v2) :: fields in + update_object_prototype o fields let set_bytes_length_field v1 v2 = match v1 with @@ -60,7 +75,7 @@ let set_bytes_length_field v1 v2 = vi.ikind <- IBytes b' | _ -> unexpected_value v1 "bytes" -let set_field v1 name v2 = match v1 with +let set_field v1 name v2 = match vresolve v1 with | VObject o -> set_object_field o name v2 | VPrototype proto -> set_proto_field proto name v2 | VArray va -> @@ -89,8 +104,10 @@ let rec compare a b = | VTrue,VTrue | VFalse,VFalse -> CEq | VFalse,VTrue -> CInf | VTrue,VFalse -> CSup - | VString(_,s1),VString(_,s2) -> - let r = String.compare (Lazy.force s1) (Lazy.force s2) in + | VString s1,VString s2 -> + let s1' = s1.sstring in + let s2' = s2.sstring in + let r = String.compare s1' s2' in if r = 0 then CEq else if r < 0 then CInf else CSup | VFunction(a,_), VFunction(b,_) -> if a == b then CEq else CUndef | VArray va1,VArray va2 -> if va1 == va2 then CEq else CUndef @@ -108,15 +125,19 @@ let rec compare a b = | VFieldClosure(v1,f1),VFieldClosure(v2,f2) -> if f1 != f2 then CUndef else compare v1 v2 + | VLazy f1,_ -> + compare (!f1()) b + | _,VLazy f2 -> + compare a (!f2()) | _ -> CUndef -let rec arrays_equal a1 a2 = +let rec arrays_equal cmp a1 a2 = if Array.length a1 <> Array.length a2 then false else begin let rec loop i = if i = Array.length a1 then true - else if not (equals_structurally a1.(i) a2.(i)) then false + else if not (cmp a1.(i) a2.(i)) then false else loop (i + 1) in loop 0 @@ -128,14 +149,108 @@ and equals_structurally a b = | VFloat a,VFloat b -> a = b | VFloat a,VInt32 b -> a = (Int32.to_float b) | VInt32 a,VFloat b -> (Int32.to_float a) = b - | VString(_,s1),VString(_,s2) -> Lazy.force s1 = Lazy.force s2 - | VArray a,VArray b -> a == b || arrays_equal a.avalues b.avalues - | VVector a,VVector b -> a == b || arrays_equal a b - | VObject a,VObject b -> a == b || arrays_equal a.ofields b.ofields && IntMap.equal equals_structurally a.oextra b.oextra - | VEnumValue a,VEnumValue b -> a == b || a.eindex = b.eindex && arrays_equal a.eargs b.eargs && a.epath = b.epath + | VString s1,VString s2 -> s1.sstring = s2.sstring (* STODO *) + | VArray a,VArray b -> a == b || arrays_equal equals_structurally a.avalues b.avalues + | VVector a,VVector b -> a == b || arrays_equal equals_structurally a b + | VObject a,VObject b -> a == b || arrays_equal equals_structurally a.ofields b.ofields + | VEnumValue a,VEnumValue b -> a == b || a.eindex = b.eindex && arrays_equal equals_structurally a.eargs b.eargs && a.epath = b.epath | VPrototype proto1,VPrototype proto2 -> proto1.ppath = proto2.ppath + | VLazy f1,_ -> equals_structurally (!f1()) b + | _,VLazy f2 -> equals_structurally a (!f2()) | _ -> a == b let is_true v = match v with | VTrue -> true - | _ -> false \ No newline at end of file + | _ -> false + +let op_add p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.add i1 i2) + | VFloat f1,VFloat f2 -> vfloat (f1 +. f2) + | VInt32 i,VFloat f | VFloat f,VInt32 i -> vfloat ((Int32.to_float i) +. f) + | VString s1,VString s2 -> vstring (concat s1 s2) + | VString s1,v2 -> vstring (concat s1 (s_value 0 v2)) + | v1,VString s2 -> vstring (concat (s_value 0 v1) s2) + | v1,v2 -> invalid_binop OpAdd v1 v2 p + +let op_mult p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.mul i1 i2) + | VFloat f1,VFloat f2 -> vfloat (f1 *. f2) + | VInt32 i,VFloat f | VFloat f,VInt32 i -> vfloat ((Int32.to_float i) *. f) + | _ -> invalid_binop OpMult v1 v2 p + +let op_div p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vfloat ((Int32.to_float i1) /. (Int32.to_float i2)) + | VFloat f1,VFloat f2 -> vfloat (f1 /. f2) + | VInt32 i1,VFloat f2 -> vfloat ((Int32.to_float i1) /. f2) + | VFloat f1,VInt32 i2 -> vfloat (f1 /. (Int32.to_float i2)) + | _ -> invalid_binop OpDiv v1 v2 p + +let op_sub p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.sub i1 i2) + | VFloat f1,VFloat f2 -> vfloat (f1 -. f2) + | VInt32 i1,VFloat f2 -> vfloat ((Int32.to_float i1) -. f2) + | VFloat f1,VInt32 i2 -> vfloat (f1 -. (Int32.to_float i2)) + | _ -> invalid_binop OpSub v1 v2 p + +let op_eq v1 v2 = vbool (equals v1 v2) + +let op_not_eq v1 v2 = vbool (not (equals v1 v2)) + +let op_gt v1 v2 = vbool (compare v1 v2 = CSup) + +let op_gte v1 v2 = vbool (match compare v1 v2 with CSup | CEq -> true | _ -> false) + +let op_lt v1 v2 = vbool (compare v1 v2 = CInf) + +let op_lte v1 v2 = vbool (match compare v1 v2 with CInf | CEq -> true | _ -> false) + +let op_and p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.logand i1 i2) + | _ -> invalid_binop OpAnd v1 v2 p + +let op_or p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.logor i1 i2) + | _ -> invalid_binop OpOr v1 v2 p + +let op_xor p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.logxor i1 i2) + | _ -> invalid_binop OpXor v1 v2 p + +let op_shl p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.shift_left i1 (Int32.to_int i2)) + | _ -> invalid_binop OpShl v1 v2 p + +let op_shr p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.shift_right i1 (Int32.to_int i2)) + | _ -> invalid_binop OpShr v1 v2 p + +let op_ushr p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.shift_right_logical i1 (Int32.to_int i2)) + | _ -> invalid_binop OpUShr v1 v2 p + +let op_mod p v1 v2 = match v1,v2 with + | VInt32 i1,VInt32 i2 -> (try vint32 (Int32.rem i1 i2) with Division_by_zero -> vfloat nan) + | VFloat f1,VFloat f2 -> vfloat (mod_float f1 f2) + | VInt32 i1,VFloat f2 -> vfloat (mod_float (Int32.to_float i1) f2) + | VFloat f1,VInt32 i2 -> vfloat (mod_float f1 (Int32.to_float i2)) + | _ -> invalid_binop OpMod v1 v2 p + +let get_binop_fun op p = match op with + | OpAdd -> op_add p + | OpMult -> op_mult p + | OpDiv -> op_div p + | OpSub -> op_sub p + | OpEq -> op_eq + | OpNotEq -> op_not_eq + | OpGt -> op_gt + | OpGte -> op_gte + | OpLt -> op_lt + | OpLte -> op_lte + | OpAnd -> op_and p + | OpOr -> op_or p + | OpXor -> op_xor p + | OpShl -> op_shl p + | OpShr -> op_shr p + | OpUShr -> op_ushr p + | OpMod -> op_mod p + | OpAssign | OpBoolAnd | OpBoolOr | OpAssignOp _ | OpInterval | OpArrow | OpIn -> assert false diff --git a/src/macro/eval/evalPrinting.ml b/src/macro/eval/evalPrinting.ml index 5f565f73b4c..3c0ce3cda65 100644 --- a/src/macro/eval/evalPrinting.ml +++ b/src/macro/eval/evalPrinting.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -23,48 +23,64 @@ open EvalValue open EvalContext open EvalField open EvalHash - -open Rope - -let rnull = of_string "null" -let rcomma = of_char ',' -let rtrue = of_string "true" -let rfalse = of_string "false" -let rfun = of_string "#fun" -let rclosure = of_string "#closure" +open EvalString + +let rempty = create_ascii "" +let rbropen = create_ascii "{" +let rbrclose = create_ascii "}" +let rbkopen = create_ascii "[" +let rbkclose = create_ascii "]" +let rpopen = create_ascii "(" +let rpclose = create_ascii ")" +let rcolon = create_ascii ":" +let rgt = create_ascii ">" +let rstop = create_ascii "<...>" +let rnull = create_ascii "null" +let rcomma = create_ascii "," +let rtrue = create_ascii "true" +let rfalse = create_ascii "false" +let rfun = create_ascii "#fun" +let rclosure = create_ascii "#closure" let s_date d = let open Unix in let t = localtime d in - of_string (Printf.sprintf "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" (t.tm_year + 1900) (t.tm_mon + 1) t.tm_mday t.tm_hour t.tm_min t.tm_sec) + create_ascii (Printf.sprintf "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" (t.tm_year + 1900) (t.tm_mon + 1) t.tm_mday t.tm_hour t.tm_min t.tm_sec) + +let s_hash key = create_ascii (EvalHash.rev_hash key) let rec s_object depth o = let fields = object_fields o in - let fields = List.map (fun (key,value) -> (concat empty [EvalHash.rev_hash key; of_string ": "; s_value depth value])) fields in - concat empty [ - of_char '{'; - concat rcomma fields; - of_char '}' - ] + let buf = Buffer.create 0 in + Buffer.add_string buf "{"; + List.iteri (fun i (k,v) -> + if i > 0 then Buffer.add_string buf ", "; + Buffer.add_string buf (rev_hash k); + Buffer.add_string buf ": "; + Buffer.add_string buf (s_value depth v).sstring; + ) fields; + Buffer.add_string buf "}"; + let s = Buffer.contents buf in + create_with_length s (try UTF8.length s with _ -> String.length s) and s_array depth va = - concat empty [ - of_char '['; + join rempty [ + rbkopen; EvalArray.join va (s_value depth) rcomma; - of_char ']'; + rbkclose; ] and s_vector depth vv = - concat empty [ - of_char '['; + join rempty [ + rbkopen; EvalArray.join (EvalArray.create vv) (s_value depth) rcomma; - of_char ']'; + rbkclose; ] and s_enum_ctor_name ve = try begin match (get_static_prototype_raise (get_ctx()) ve.epath).pkind with - | PEnum names -> (try List.nth names ve.eindex with _ -> "#unknown") + | PEnum names -> (try fst (List.nth names ve.eindex) with _ -> "#unknown") | _ -> raise Not_found end with Not_found -> "#unknown" @@ -72,18 +88,18 @@ and s_enum_ctor_name ve = and s_enum_value depth ve = let name = s_enum_ctor_name ve in match ve.eargs with - | [||] -> of_string name + | [||] -> create_ascii name | vl -> - concat empty [ - of_string name; - of_char '('; - concat rcomma (Array.to_list (Array.map (s_value (depth + 1)) vl)); - of_char ')' + join rempty [ + create_ascii name; + rpopen; + join rcomma (Array.to_list (Array.map (s_value (depth + 1)) vl)); + rpclose; ] and s_proto_kind proto = match proto.pkind with - | PClass _ -> concat empty [of_string "Class<"; rev_hash proto.ppath; of_char '>'] - | PEnum _ -> concat empty [of_string "Enum<"; rev_hash proto.ppath; of_char '>'] + | PClass _ -> join rempty [create_ascii "Class<"; s_hash proto.ppath; rgt] + | PEnum _ -> join rempty [create_ascii "Enum<"; s_hash proto.ppath; rgt] | PInstance | PObject -> assert false and s_value depth v = @@ -91,31 +107,28 @@ and s_value depth v = let vf = field_raise v EvalHash.key_toString in s_value (depth + 1) (call_value_on v vf []) in - if depth > 5 then of_string "<...>" + if depth > 5 then rstop else match v with | VNull -> rnull - | VInt32 i32 -> of_string (Int32.to_string i32) + | VInt32 i32 -> create_ascii(Int32.to_string i32) | VTrue -> rtrue | VFalse -> rfalse | VFloat f -> - let s = Common.float_repres f in + let s = Numeric.float_repres f in let len = String.length s in - of_string (if String.unsafe_get s (len - 1) = '.' then String.sub s 0 (len - 1) else s) - | VFunction (f,_) -> - let s = match num_args f with - | -1 -> "" - | i -> string_of_int i - in - concat2 rfun (Rope.of_string (s)) + create_ascii (if String.unsafe_get s (len - 1) = '.' then String.sub s 0 (len - 1) else s) + | VFunction (f,_) -> rfun | VFieldClosure _ -> rclosure | VEnumValue ve -> s_enum_value depth ve - | VString(s,_) -> s + | VString s -> s | VArray va -> s_array (depth + 1) va | VVector vv -> s_vector (depth + 1) vv | VInstance {ikind=IDate d} -> s_date d - | VInstance {ikind=IPos p} -> of_string ("#pos(" ^ Lexer.get_error_pos (Printf.sprintf "%s:%d:") p ^ ")") - | VInstance i -> (try call_to_string () with Not_found -> rev_hash i.iproto.ppath) + | VInstance {ikind=IPos p} -> create_ascii ("#pos(" ^ Lexer.get_error_pos (Printf.sprintf "%s:%d:") p ^ ")") (* STODO: not ascii? *) + | VInstance {ikind=IRegex r} -> r.r_rex_string + | VInstance i -> (try call_to_string () with Not_found -> s_hash i.iproto.ppath) | VObject o -> (try call_to_string () with Not_found -> s_object (depth + 1) o) + | VLazy f -> s_value depth (!f()) | VPrototype proto -> try call_to_string() @@ -130,4 +143,5 @@ and call_value_on vthis v vl = | VFieldClosure(v1,f) -> call_function f (v1 :: vl) | _ -> exc_string ("Cannot call " ^ (value_string v)) -and value_string v = Rope.to_string (s_value 0 v) \ No newline at end of file +and value_string v = + (s_value 0 v).sstring diff --git a/src/macro/eval/evalPrototype.ml b/src/macro/eval/evalPrototype.ml index c175b5d9684..a22c12f7858 100644 --- a/src/macro/eval/evalPrototype.ml +++ b/src/macro/eval/evalPrototype.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -29,11 +29,11 @@ open EvalExceptions open EvalMisc (* JITs expression [e] and executes the result immediately. *) -let eval_expr ctx key name e = +let eval_expr ctx kind e = catch_exceptions ctx (fun () -> let jit,f = jit_expr ctx e in let num_captures = Hashtbl.length jit.captures in - let info = create_env_info true (file_hash e.epos.pfile) (EKMethod(key,name)) jit.capture_infos in + let info = create_env_info true e.epos.pfile kind jit.capture_infos in let env = push_environment ctx info jit.max_num_locals num_captures in Std.finally (fun _ -> pop_environment ctx env) f env ) e.Type.epos @@ -118,7 +118,7 @@ module PrototypeBuilder = struct (* Add metadata field *) begin match pctx.meta with | None -> () - | Some e -> DynArray.add pctx.fields (key___meta__,lazy (match eval_expr ctx pctx.key key___meta__ e with Some e -> e | None -> vnull)) + | Some e -> DynArray.add pctx.fields (key___meta__,lazy (match eval_expr ctx (EKMethod(pctx.key,key___meta__)) e with Some e -> e | None -> vnull)) end; (* Create the mapping from hashed name to field offset for prototype fields. *) let _,pnames = DynArray.fold_left (fun (i,acc) (name,_) -> i + 1,IntMap.add name i acc) (0,IntMap.empty) pctx.fields in @@ -159,7 +159,7 @@ module PrototypeBuilder = struct proto.pvalue <- vprototype proto; (* Register the prototype. *) if pctx.is_static then - ctx.static_prototypes <- IntMap.add pctx.key proto ctx.static_prototypes + ctx.static_prototypes#add proto else begin ctx.instance_prototypes <- IntMap.add pctx.key proto ctx.instance_prototypes; if pctx.key = key_String then ctx.string_prototype <- proto @@ -170,58 +170,71 @@ module PrototypeBuilder = struct end let is_removable_field cf = - Meta.has Meta.Extern cf.cf_meta || Meta.has Meta.Generic cf.cf_meta + has_class_field_flag cf CfExtern || Meta.has Meta.Generic cf.cf_meta + +let is_persistent cf = + Meta.has Meta.Persistent cf.cf_meta let create_static_prototype ctx mt = - let key = path_hash (t_infos mt).mt_path in + let path = (t_infos mt).mt_path in + let key = path_hash path in let com = ctx.curapi.MacroApi.get_com() in - let meta = Codegen.build_metadata com mt in + let meta = Texpr.build_metadata com.Common.basic mt in let o = match mt with | TClassDecl c -> let pparent = match c.cl_super with | None -> None | Some(csup,_) -> Some (get_static_prototype ctx (path_hash csup.cl_path) c.cl_pos) in - let interfaces = List.map (fun (c,_) -> path_hash c.cl_path) c.cl_implements in + let rec collect_interfaces acc (c,_) = + let acc = List.fold_left (fun acc c -> collect_interfaces acc c) acc c.cl_implements in + path_hash c.cl_path :: acc + in + let interfaces = collect_interfaces [] (c,[]) in let pctx = PrototypeBuilder.create ctx key pparent (PClass interfaces) meta in let fields = List.filter (fun cf -> not (is_removable_field cf)) c.cl_ordered_statics in let delays = DynArray.create() in if not c.cl_extern then List.iter (fun cf -> match cf.cf_kind,cf.cf_expr with | Method _,Some {eexpr = TFunction tf; epos = pos} -> - let name = hash_s cf.cf_name in + let name = hash cf.cf_name in PrototypeBuilder.add_proto_field pctx name (lazy (vstatic_function (jit_tfunction ctx key name tf true pos))); | Var _,Some e -> - let name = hash_s cf.cf_name in + let name = hash cf.cf_name in PrototypeBuilder.add_proto_field pctx name (lazy vnull); let i = DynArray.length pctx.PrototypeBuilder.fields - 1 in - DynArray.add delays (fun proto -> proto.pfields.(i) <- (match eval_expr ctx key name e with Some e -> e | None -> vnull)) + let persistent = is_persistent cf in + DynArray.add delays (persistent,(fun proto -> + proto.pfields.(i) <- (match eval_expr ctx (EKMethod(key,name)) e with Some e -> e | None -> vnull) + )) | _,None when is_physical_field cf -> - PrototypeBuilder.add_proto_field pctx (hash_s cf.cf_name) (lazy vnull); + PrototypeBuilder.add_proto_field pctx (hash cf.cf_name) (lazy vnull); | _ -> () ) fields; begin match c.cl_init with | None -> () - | Some e -> DynArray.add delays (fun _ -> ignore(eval_expr ctx key key___init__ e)) + | Some e -> DynArray.add delays (false,(fun _ -> ignore(eval_expr ctx (EKMethod(key,key___init__)) e))) end; PrototypeBuilder.finalize pctx,(DynArray.to_list delays) | TEnumDecl en -> - let pctx = PrototypeBuilder.create ctx key None (PEnum en.e_names) meta in + let names = List.map (fun name -> + let ef = PMap.find name en.e_constrs in + let args = match follow ef.ef_type with + | TFun(args,_) -> + List.map (fun (n,_,_) -> hash n) args + | _ -> + [] + in + name,args + ) en.e_names in + let pctx = PrototypeBuilder.create ctx key None (PEnum names) meta in let enum_field_value ef = match follow ef.ef_type with | TFun(args,_) -> - let f = match args with - | [] -> Fun0 (fun () -> encode_enum_value key ef.ef_index [||] (Some ef.ef_pos)) - | [_] -> Fun1 (fun a -> encode_enum_value key ef.ef_index [|a|] (Some ef.ef_pos)) - | [_;_] -> Fun2 (fun a b -> encode_enum_value key ef.ef_index [|a;b|] (Some ef.ef_pos)) - | [_;_;_] -> Fun3 (fun a b c -> encode_enum_value key ef.ef_index [|a;b;c|] (Some ef.ef_pos)) - | [_;_;_;_] -> Fun4 (fun a b c d -> encode_enum_value key ef.ef_index [|a;b;c;d|] (Some ef.ef_pos)) - | [_;_;_;_;_] -> Fun5 (fun a b c d e -> encode_enum_value key ef.ef_index [|a;b;c;d;e|] (Some ef.ef_pos)) - | _ -> FunN (fun vl -> encode_enum_value key ef.ef_index (Array.of_list vl) (Some ef.ef_pos)) - in + let f = (fun vl -> encode_enum_value key ef.ef_index (Array.of_list vl) (Some ef.ef_pos)) in vstatic_function f | _ -> encode_enum_value key ef.ef_index [||] (Some ef.ef_pos) in - PMap.iter (fun name ef -> PrototypeBuilder.add_proto_field pctx (hash_s name ) (lazy (enum_field_value ef))) en.e_constrs; + PMap.iter (fun name ef -> PrototypeBuilder.add_proto_field pctx (hash name ) (lazy (enum_field_value ef))) en.e_constrs; PrototypeBuilder.finalize pctx,[]; | TAbstractDecl a -> let pctx = PrototypeBuilder.create ctx key None (PClass []) meta in @@ -229,6 +242,21 @@ let create_static_prototype ctx mt = | _ -> assert false in + let rec loop v name path = match path with + | [] -> + set_field v (hash name) (vprototype (fst (fst o))) + | s :: sl -> + let key = hash s in + let v2 = EvalField.field v key in + let v2 = match v2 with + | VNull -> encode_obj [] + | _ -> v2 + in + set_field v key v2; + loop v2 name sl; + in + if ctx.debug.support_debugger then + loop ctx.toplevel (snd path) (fst path); o let create_instance_prototype ctx c = @@ -243,12 +271,12 @@ let create_instance_prototype ctx c = () else List.iter (fun cf -> match cf.cf_kind,cf.cf_expr with | Method meth,Some {eexpr = TFunction tf; epos = pos} -> - let name = hash_s cf.cf_name in + let name = hash cf.cf_name in let v = lazy (vfunction (jit_tfunction ctx key name tf false pos)) in if meth = MethDynamic then PrototypeBuilder.add_instance_field pctx name v; PrototypeBuilder.add_proto_field pctx name v | Var _,_ when is_physical_field cf -> - let name = hash_s cf.cf_name in + let name = hash cf.cf_name in PrototypeBuilder.add_instance_field pctx name (lazy vnull); | _ -> () @@ -257,20 +285,19 @@ let create_instance_prototype ctx c = let get_object_prototype ctx l = let l = List.sort (fun (i1,_) (i2,_) -> if i1 = i2 then 0 else if i1 < i2 then -1 else 1) l in - let sfields = String.concat "," (List.map (fun (i,_) -> rev_hash_s i) l) in - let key = Hashtbl.hash sfields in + let sfields = String.concat "," (List.map (fun (i,_) -> (Printf.sprintf ":%s" (rev_hash i))) l) in + let name = hash (Printf.sprintf "eval.object.Object[%s]" sfields) in try - IntMap.find key ctx.instance_prototypes,l + IntMap.find name ctx.instance_prototypes,l with Not_found -> - let name = hash_s (Printf.sprintf "eval.object.Object[%s]" sfields) in let pctx = PrototypeBuilder.create ctx name None PObject None in List.iter (fun (name,_) -> PrototypeBuilder.add_instance_field pctx name (lazy vnull)) l; let proto = fst (PrototypeBuilder.finalize pctx) in - ctx.instance_prototypes <- IntMap.add key proto ctx.instance_prototypes; + ctx.instance_prototypes <- IntMap.add name proto ctx.instance_prototypes; proto,l let add_types ctx types ready = - let t = Common.timer [(if ctx.is_macro then "macro" else "interp");"add_types"] in + let t = Timer.timer [(if ctx.is_macro then "macro" else "interp");"add_types"] in let new_types = List.filter (fun mt -> let inf = Type.t_infos mt in let key = path_hash inf.mt_path in @@ -280,12 +307,12 @@ let add_types ctx types ready = false with Not_found -> ctx.instance_prototypes <- IntMap.remove key ctx.instance_prototypes; - ctx.static_prototypes <- IntMap.remove key ctx.static_prototypes; + ctx.static_prototypes#remove key; ctx.constructors <- IntMap.remove key ctx.constructors; ready mt; ctx.type_cache <- IntMap.add key mt ctx.type_cache; if ctx.debug.support_debugger then begin - let file_key = hash_s inf.mt_module.m_extra.m_file in + let file_key = hash inf.mt_module.m_extra.m_file in if not (Hashtbl.mem ctx.debug.breakpoints file_key) then begin Hashtbl.add ctx.debug.breakpoints file_key (Hashtbl.create 0) end @@ -325,8 +352,11 @@ let add_types ctx types ready = f proto; match delays with | [] -> () - | _ -> DynArray.add fl_static_init (proto,delays) + | _ -> + DynArray.add fl_static_init (proto,delays); + let non_persistent_delays = ExtList.List.filter_map (fun (persistent,f) -> if not persistent then Some f else None) delays in + ctx.static_prototypes#add_init proto non_persistent_delays; ) fl_static; (* 4. Initialize static fields. *) - DynArray.iter (fun (proto,delays) -> List.iter (fun f -> f proto) delays) fl_static_init; + DynArray.iter (fun (proto,delays) -> List.iter (fun (_,f) -> f proto) delays) fl_static_init; t() \ No newline at end of file diff --git a/src/macro/eval/evalStdLib.ml b/src/macro/eval/evalStdLib.ml index 6a86443a6cb..a67ba25d63f 100644 --- a/src/macro/eval/evalStdLib.ml +++ b/src/macro/eval/evalStdLib.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -27,9 +27,17 @@ open EvalPrinting open EvalMisc open EvalField open EvalHash +open EvalString +open EvalThread let macro_lib = Hashtbl.create 0 +let catch_unix_error f arg = + try + f arg + with Unix.Unix_error(err,cmd,args) -> + exc_string (Printf.sprintf "%s(%s, %s)" (Unix.error_message err) cmd args) + let ptmap_keys h = IntMap.fold (fun k _ acc -> k :: acc) h [] @@ -47,7 +55,6 @@ let encode_i64_direct i64 = let high = Int64.to_int32 (Int64.shift_right_logical i64 32) in encode_i64 low high - module StdEvalVector = struct let this this = match this with | VVector vv -> vv @@ -64,7 +71,8 @@ module StdEvalVector = struct ) let fromArrayCopy = vfun1 (fun arr -> - encode_vector_instance (Array.copy (decode_varray arr).avalues) + let a = decode_varray arr in + encode_vector_instance (Array.sub a.avalues 0 a.alength) ) let copy = vifun0 (fun vthis -> @@ -73,25 +81,17 @@ module StdEvalVector = struct let join = vifun1 (fun vthis sep -> let this = this vthis in - let sep = decode_rope sep in - encode_rope (EvalArray.array_join this (s_value 0) sep) + let sep = decode_vstring sep in + vstring ((EvalArray.array_join this (s_value 0) sep)) ) let map = vifun1 (fun vthis f -> let this = this vthis in let a = match f with | VFunction(f,_) -> - begin match f with - | Fun1 f -> Array.map (fun v -> f v) this - | FunN f -> Array.map (fun v -> f [v]) this - | _ -> invalid_call_arg_number 1 (num_args f) - end + Array.map (fun v -> f [v]) this | VFieldClosure(v1,f) -> - begin match f with - | Fun2 f -> Array.map (fun v -> f v1 v) this - | FunN f -> Array.map (fun v -> f [v1;v]) this - | _ -> invalid_call_arg_number 2 (num_args f) - end + Array.map (fun v -> f (v1 :: [v])) this | _ -> exc_string ("Cannot call " ^ (value_string f)) in encode_vector_instance a @@ -142,16 +142,16 @@ module StdArray = struct let iterator = vifun0 (fun vthis -> let this = this vthis in let f_has_next,f_next = EvalArray.iterator this in - encode_obj None [ + encode_obj [ key_hasNext,vifun0 (fun _ -> vbool (f_has_next())); key_next,vifun0 (fun _ -> f_next()) ] ) let join = vifun1 (fun vthis sep -> - let sep = decode_rope sep in + let sep = decode_vstring sep in let s = EvalArray.join (this vthis) (s_value 0) sep in - encode_rope s + vstring s ) let lastIndexOf = vifun2 (fun vthis x fromIndex -> @@ -167,17 +167,9 @@ module StdArray = struct let this = this vthis in let a = match f with | VFunction(f,_) -> - begin match f with - | Fun1 f -> EvalArray.map this (fun v -> f v) - | FunN f -> EvalArray.map this (fun v -> f [v]) - | _ -> invalid_call_arg_number 1 (num_args f) - end + EvalArray.map this (fun v -> f [v]) | VFieldClosure(v1,f) -> - begin match f with - | Fun2 f -> EvalArray.map this (fun v -> f v1 v) - | FunN f -> EvalArray.map this (fun v -> f [v1;v]) - | _ -> invalid_call_arg_number 2 (num_args f) - end + EvalArray.map this (fun v -> f (v1 :: [v])) | _ -> exc_string ("Cannot call " ^ (value_string f)) in encode_array_instance a @@ -246,7 +238,7 @@ module StdArray = struct ) let toString = vifun0 (fun vthis -> - encode_rope (s_array 0 (this vthis)) + vstring (s_array 0 (this vthis)) ) let unshift = vifun1 (fun vthis v -> @@ -254,6 +246,13 @@ module StdArray = struct EvalArray.unshift this v; vnull ) + + let resize = vifun1 (fun vthis len -> + let this = this vthis in + let len = decode_int len in + EvalArray.resize this len; + vnull + ) end let outside_bounds () = @@ -261,59 +260,21 @@ let outside_bounds () = exc (proto_field_direct haxe_io_Error key_OutsideBounds) module StdBytes = struct + open EvalBytes + let this vthis = match vthis with | VInstance {ikind = IBytes o} -> o | v -> unexpected_value v "bytes" - let read_byte this i = int_of_char (Bytes.get this i) - - let read_ui16 this i = - let ch1 = read_byte this i in - let ch2 = read_byte this (i + 1) in - ch1 lor (ch2 lsl 8) - - let read_i32 this i = - let ch1 = read_byte this i in - let ch2 = read_byte this (i + 1) in - let ch3 = read_byte this (i + 2) in - let base = Int32.of_int (ch1 lor (ch2 lsl 8) lor (ch3 lsl 16)) in - let big = Int32.shift_left (Int32.of_int (read_byte this (i + 3))) 24 in - Int32.logor base big - - let read_i64 this i = - let ch1 = read_byte this i in - let ch2 = read_byte this (i + 1) in - let ch3 = read_byte this (i + 2) in - let ch4 = read_byte this (i + 3) in - let base = Int64.of_int (ch1 lor (ch2 lsl 8) lor (ch3 lsl 16)) in - let small = Int64.logor base (Int64.shift_left (Int64.of_int ch4) 24) in - let big = Int64.of_int32 (read_i32 this (i + 4)) in - Int64.logor (Int64.shift_left big 32) small - - let write_byte this i v = - Bytes.set this i (Char.unsafe_chr v) - - let write_ui16 this i v = - write_byte this i v; - write_byte this (i + 1) (v lsr 8) - - let write_i32 this i v = - let base = Int32.to_int v in - let big = Int32.to_int (Int32.shift_right_logical v 24) in - write_byte this i base; - write_byte this (i + 1) (base lsr 8); - write_byte this (i + 2) (base lsr 16); - write_byte this (i + 3) big - - let write_i64 this i v = - write_i32 this i (Int64.to_int32 v); - write_i32 this (i + 4) (Int64.to_int32 (Int64.shift_right_logical v 32)) - let alloc = vfun1 (fun length -> let length = decode_int length in encode_bytes (Bytes.make length (Char.chr 0)) ) + let encode_native v = match v with + | VEnumValue {eindex = 1} -> true (* haxe.io.Encoding.RawNative *) + | _ -> false + let blit = vifun4 (fun vthis pos src srcpos len -> let s = this vthis in let pos = decode_int pos in @@ -376,11 +337,12 @@ module StdBytes = struct outside_bounds() ) - let getString = vifun2 (fun vthis pos len -> + let getString = vifun3 (fun vthis pos len encoding -> let this = this vthis in let pos = decode_int pos in let len = decode_int len in - encode_string (Bytes.unsafe_to_string ((try Bytes.sub this pos len with _ -> outside_bounds()))); + let s = try Bytes.sub this pos len with _ -> outside_bounds() in + create_unknown (Bytes.unsafe_to_string s) ) let getUInt16 = vifun1 (fun vthis pos -> @@ -389,8 +351,24 @@ module StdBytes = struct let ofData = vfun1 (fun v -> v) - let ofString = vfun1 (fun v -> - encode_bytes (Bytes.of_string (decode_string v)) + let ofString = vfun2 (fun v encoding -> + let s = decode_vstring v in + encode_bytes (Bytes.of_string s.sstring) + ) + + let ofHex = vfun1 (fun v -> + let s = decode_string v in + let len = String.length s in + if (len land 1) <> 0 then exc_string "Not a hex string (odd number of digits)"; + let ret = (Bytes.make (len lsr 1) (Char.chr 0)) in + for i = 0 to Bytes.length ret - 1 do + let high = int_of_char s.[i * 2] in + let low = int_of_char s.[i * 2 + 1] in + let high = (high land 0xF) + ((high land 0x40) lsr 6) * 9 in + let low = (low land 0xF) + ((low land 0x40) lsr 6) * 9 in + Bytes.set ret i (char_of_int (((high lsl 4) lor low) land 0xFF)); + done; + encode_bytes ret ) let set = vifun2 (fun vthis pos v -> @@ -402,7 +380,7 @@ module StdBytes = struct ) let setDouble = vifun2 (fun vthis pos v -> - (try write_i64 (this vthis) (decode_int pos) (Int64.bits_of_float (decode_float v)) with _ -> outside_bounds()); + (try write_i64 (this vthis) (decode_int pos) (Int64.bits_of_float (num v)) with _ -> outside_bounds()); vnull ) @@ -461,7 +439,7 @@ module StdBytes = struct ) let toString = vifun0 (fun vthis -> - encode_string (Bytes.to_string (this vthis)) + (create_unknown (Bytes.to_string (this vthis))) ) end @@ -500,10 +478,10 @@ module StdBytesBuffer = struct vnull ) - let addString = vifun1 (fun vthis src -> + let addString = vifun2 (fun vthis src encoding -> let this = this vthis in - let src = decode_string src in - Buffer.add_string this src; + let src = decode_vstring src in + Buffer.add_string this src.sstring; vnull ) @@ -561,29 +539,29 @@ module StdCallStack = struct let l = DynArray.create () in List.iter (fun (pos,kind) -> let file_pos s = - let line = Lexer.get_error_line pos in - encode_enum_value key_haxe_StackItem 2 [|s;encode_string pos.pfile;vint line|] None + let line1,col1,_,_ = Lexer.get_pos_coords pos in + encode_enum_value key_haxe_StackItem 2 [|s;create_unknown pos.pfile;vint line1;vint col1|] None in match kind with | EKLocalFunction i -> let local_function = encode_enum_value key_haxe_StackItem 4 [|vint i|] None in DynArray.add l (file_pos local_function); | EKMethod(st,sf) -> - let local_function = encode_enum_value key_haxe_StackItem 3 [|encode_string (rev_hash_s st); encode_string (rev_hash_s sf)|] None in + let local_function = encode_enum_value key_haxe_StackItem 3 [|create_unknown (rev_hash st); create_unknown (rev_hash sf)|] None in DynArray.add l (file_pos local_function); - | EKDelayed -> + | EKEntrypoint -> () ) envs; encode_array (DynArray.to_list l) let getCallStack = vfun0 (fun () -> let ctx = get_ctx() in - let envs = call_stack ctx in + let envs = call_stack (get_eval ctx) in let envs = match envs with | _ :: _ :: envs -> envs (* Skip calls to callStack() and getCallStack() *) | _ -> envs in - make_stack (List.map (fun env -> {pfile = rev_file_hash env.env_info.pfile;pmin = env.env_leave_pmin; pmax = env.env_leave_pmax},env.env_info.kind) envs) + make_stack (List.map (fun env -> {pfile = rev_hash env.env_info.pfile;pmin = env.env_leave_pmin; pmax = env.env_leave_pmax},env.env_info.kind) envs) ) let getExceptionStack = vfun0 (fun () -> @@ -609,7 +587,7 @@ module StdCompress = struct let dst = decode_bytes dst in let dstPos = decode_int dstPos in let r = try f this.z (Bytes.unsafe_to_string src) srcPos (Bytes.length src - srcPos) dst dstPos (Bytes.length dst - dstPos) this.z_flush with _ -> exc_string "oops" in - encode_obj None [ + encode_obj [ key_done,vbool r.z_finish; key_read,vint r.z_read; key_write,vint r.z_wrote @@ -654,7 +632,7 @@ module StdContext = struct let file = decode_string file in let line = decode_int line in begin try - ignore(EvalDebugMisc.add_breakpoint (get_ctx()) file line BPAny); + ignore(EvalDebugMisc.add_breakpoint (get_ctx()) file line BPAny None); with Not_found -> exc_string ("Could not find file " ^ file) end; @@ -662,7 +640,8 @@ module StdContext = struct ) let breakHere = vfun0 (fun () -> - raise (EvalDebugMisc.BreakHere) + if not ((get_ctx()).debug.support_debugger) then vnull + else raise (EvalDebugMisc.BreakHere) ) let callMacroApi = vfun1 (fun f -> @@ -682,7 +661,7 @@ module StdContext = struct | None -> vnull | Some l -> - encode_obj_s None l + encode_obj_s l ) end @@ -690,7 +669,7 @@ module StdCrc32 = struct let make = vfun1 (fun data -> let data = decode_bytes data in let crc32 = Extc.zlib_crc32 data (Bytes.length data) in - vint crc32 + vint32 crc32 ) end @@ -711,29 +690,33 @@ module StdDate = struct | 19 -> let r = Str.regexp "^\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\) \\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" in if not (Str.string_match r s 0) then exc_string ("Invalid date format : " ^ s); - let t = Unix.localtime (Unix.time()) in - let t = { t with + let t = { tm_year = int_of_string (Str.matched_group 1 s) - 1900; tm_mon = int_of_string (Str.matched_group 2 s) - 1; tm_mday = int_of_string (Str.matched_group 3 s); tm_hour = int_of_string (Str.matched_group 4 s); tm_min = int_of_string (Str.matched_group 5 s); tm_sec = int_of_string (Str.matched_group 6 s); + tm_wday = 0; + tm_yday = 0; + tm_isdst = false; } in - encode_date (fst (Unix.mktime t)) + encode_date (fst (catch_unix_error mktime t)) | 10 -> let r = Str.regexp "^\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\)$" in if not (Str.string_match r s 0) then exc_string ("Invalid date format : " ^ s); - let t = Unix.localtime (Unix.time()) in - let t = { t with + let t = { tm_year = int_of_string (Str.matched_group 1 s) - 1900; tm_mon = int_of_string (Str.matched_group 2 s) - 1; tm_mday = int_of_string (Str.matched_group 3 s); tm_hour = 0; tm_min = 0; tm_sec = 0; + tm_wday = 0; + tm_yday = 0; + tm_isdst = false; } in - encode_date (fst (Unix.mktime t)) + encode_date (fst (catch_unix_error mktime t)) | 8 -> let r = Str.regexp "^\\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" in if not (Str.string_match r s 0) then exc_string ("Invalid date format : " ^ s); @@ -746,16 +729,56 @@ module StdDate = struct exc_string ("Invalid date format : " ^ s) ) - let getDate = vifun0 (fun vthis -> vint (localtime (this vthis)).tm_mday) - let getDay = vifun0 (fun vthis -> vint (localtime (this vthis)).tm_wday) - let getFullYear = vifun0 (fun vthis -> vint (((localtime (this vthis)).tm_year) + 1900)) - let getHours = vifun0 (fun vthis -> vint (localtime (this vthis)).tm_hour) - let getMinutes = vifun0 (fun vthis -> vint (localtime (this vthis)).tm_min) - let getMonth = vifun0 (fun vthis -> vint (localtime (this vthis)).tm_mon) - let getSeconds = vifun0 (fun vthis -> vint (localtime (this vthis)).tm_sec) + let getDate = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_mday) + let getDay = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_wday) + let getFullYear = vifun0 (fun vthis -> vint (((catch_unix_error localtime (this vthis)).tm_year) + 1900)) + let getHours = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_hour) + let getMinutes = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_min) + let getMonth = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_mon) + let getSeconds = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_sec) + let getUTCDate = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_mday) + let getUTCDay = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_wday) + let getUTCFullYear = vifun0 (fun vthis -> vint (((catch_unix_error gmtime (this vthis)).tm_year) + 1900)) + let getUTCHours = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_hour) + let getUTCMinutes = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_min) + let getUTCMonth = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_mon) + let getUTCSeconds = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_sec) let getTime = vifun0 (fun vthis -> vfloat ((this vthis) *. 1000.)) - let now = vfun0 (fun () -> encode_date (time())) - let toString = vifun0 (fun vthis -> encode_rope (s_date (this vthis))) + let getTimezoneOffset = vifun0 (fun vthis -> + let tmLocal = catch_unix_error localtime (this vthis) in + let tmUTC = catch_unix_error gmtime (this vthis) in + let tsLocal = fst (catch_unix_error mktime tmLocal) in + let tsUTC = fst (catch_unix_error mktime tmUTC) in + vint (int_of_float ((tsUTC -. tsLocal) /. 60.)) + ) + let now = vfun0 (fun () -> encode_date (catch_unix_error time())) + let toString = vifun0 (fun vthis -> vstring (s_date (this vthis))) +end + +module StdDeque = struct + let this vthis = match vthis with + | VInstance {ikind = IDeque d} -> d + | _ -> unexpected_value vthis "Deque" + + let add = vifun1 (fun vthis i -> + let this = this vthis in + Deque.add this i; + vnull + ) + + let pop = vifun1 (fun vthis blocking -> + let this = this vthis in + let blocking = decode_bool blocking in + match Deque.pop this blocking with + | None -> vnull + | Some v -> v + ) + + let push = vifun1 (fun vthis i -> + let this = this vthis in + Deque.push this i; + vnull + ) end module StdEReg = struct @@ -778,13 +801,15 @@ module StdEReg = struct | 'i' -> Some `CASELESS | 's' -> Some `DOTALL | 'm' -> Some `MULTILINE - | 'u' -> Some `UTF8 + | 'u' -> None | 'g' -> global := true; None | c -> failwith ("Unsupported regexp option '" ^ String.make 1 c ^ "'") ) (ExtString.String.explode opt) in - let r = try regexp ~flags r with Error error -> failwith (string_of_pcre_error error) in + let flags = `UTF8 :: `UCP :: flags in + let rex = try regexp ~flags r with Error error -> failwith (string_of_pcre_error error) in let pcre = { - r = r; + r = rex; + r_rex_string = create_ascii (Printf.sprintf "~/%s/%s" r opt); r_global = !global; r_string = ""; r_groups = [||] @@ -803,14 +828,14 @@ module StdEReg = struct let escape = vfun1 (fun s -> let s = decode_string s in - encode_string (Str.quote s) + create_unknown (Str.quote s) ) let map = vifun2 (fun vthis s f -> let this = this vthis in let s = decode_string s in let l = String.length s in - let buf = Rope.Buffer.create 0 in + let buf = Buffer.create 0 in let rec loop pos = if pos >= l then () @@ -818,31 +843,31 @@ module StdEReg = struct let a = exec ~rex:this.r ~pos s in this.r_groups <- [|a|]; let (first,last) = get_substring_ofs a 0 in - Rope.Buffer.add_substring buf s pos (first - pos); - Rope.Buffer.add_rope buf (decode_rope (call_value_on vthis f [vthis])); + Buffer.add_substring buf s pos (first - pos); + Buffer.add_string buf (decode_string (call_value_on vthis f [vthis])); if last = first then begin if last >= l then () else begin if this.r_global then begin - Rope.Buffer.add_substring buf s first 1; + Buffer.add_substring buf s first 1; loop (first + 1) end else - Rope.Buffer.add_substring buf s first (l - first) + Buffer.add_substring buf s first (l - first) end end else if this.r_global then loop last else - Rope.Buffer.add_substring buf s last (l - last) + Buffer.add_substring buf s last (l - last) with Not_found -> - Rope.Buffer.add_substring buf s pos (l - pos) + Buffer.add_substring buf s pos (l - pos) end in this.r_string <- s; loop 0; this.r_string <- ""; this.r_groups <- [||]; - encode_rope (Rope.Buffer.contents buf) + create_unknown (Buffer.contents buf) ) let match' = vifun1 (fun vthis s -> @@ -857,34 +882,47 @@ module StdEReg = struct with Not_found -> this.r_groups <- [||]; vfalse + | Pcre.Error _ -> + exc_string "PCRE Error (invalid unicode string?)" ) let matched = vifun1 (fun vthis n -> let this = this vthis in let n = decode_int n in maybe_run this n (fun (first,last) -> - encode_string (ExtString.String.slice ~first ~last this.r_string) + create_unknown (ExtString.String.slice ~first ~last this.r_string) ) ) let matchedLeft = vifun0 (fun vthis -> let this = this vthis in maybe_run this 0 (fun (first,_) -> - encode_string (ExtString.String.slice ~last:first this.r_string) + create_unknown (ExtString.String.slice ~last:first this.r_string) ) ) let matchedPos = vifun0 (fun vthis -> let this = this vthis in + let rec byte_offset_to_char_offset_lol s i k o = + if i = 0 then + k + else begin + let n = UTF8.next s o in + let d = n - o in + byte_offset_to_char_offset_lol s (i - d) (k + 1) n + end + in maybe_run this 0 (fun (first,last) -> - encode_obj None [key_pos,vint first;key_len,vint (last - first)] + let first = byte_offset_to_char_offset_lol this.r_string first 0 0 in + let last = byte_offset_to_char_offset_lol this.r_string last 0 0 in + encode_obj [key_pos,vint first;key_len,vint (last - first)] ) ) let matchedRight = vifun0 (fun vthis -> let this = this vthis in maybe_run this 0 (fun (_,last) -> - encode_string (ExtString.String.slice ~first:last this.r_string) + create_unknown (ExtString.String.slice ~first:last this.r_string) ) ) @@ -910,7 +948,7 @@ module StdEReg = struct let s = decode_string s in let by = decode_string by in let s = (if this.r_global then Pcre.replace else Pcre.replace_first) ~rex:this.r ~templ:by s in - encode_string s + create_unknown s ) let split = vifun1 (fun vthis s -> @@ -919,8 +957,22 @@ module StdEReg = struct if String.length s = 0 then encode_array [encode_string ""] else begin let max = if this.r_global then -1 else 2 in - let l = Pcre.split ~max ~rex:this.r s in - encode_array (List.map encode_string l) + let l = Pcre.full_split ~max ~rex:this.r s in + let rec loop split cur acc l = match l with + | Text s :: l -> + loop split (cur ^ s) acc l + | Delim s :: l -> + if split then + loop this.r_global "" ((create_unknown cur) :: acc) l + else + loop false (cur ^ s) acc l + | _ :: l -> + loop split cur acc l + | [] -> + List.rev ((create_unknown cur) :: acc) + in + let l = loop true "" [] l in + encode_array l end ) end @@ -935,22 +987,29 @@ module StdFile = struct let perms = 0o666 in let l = Open_creat :: flags in let l = if binary then Open_binary :: l else l in - let ch = open_out_gen l perms path in + let ch = + try open_out_gen l perms path + with Sys_error msg -> exc_string msg + in encode_instance key_sys_io_FileOutput ~kind:(IOutChannel ch) let write_out path content = try - let ch = open_out_bin path in - output_string ch content; - close_out ch; + let ch = open_out_bin path in + output_string ch content; + close_out ch; vnull - with Sys_error _ -> - exc_string ("Could not write file " ^ path) + with Sys_error s -> + exc_string s let append = vfun2 (fun path binary -> create_out path binary [Open_append] ) + let update = vfun2 (fun path binary -> + create_out path binary [Open_rdonly; Open_wronly] + ) + let getBytes = vfun1 (fun path -> let path = decode_string path in try encode_bytes (Bytes.unsafe_of_string (Std.input_file ~bin:true path)) with Sys_error _ -> exc_string ("Could not read file " ^ path) @@ -958,16 +1017,19 @@ module StdFile = struct let getContent = vfun1 (fun path -> let path = decode_string path in - try encode_string (Std.input_file ~bin:true path) with Sys_error _ -> exc_string ("Could not read file " ^ path) + try ((create_unknown (Std.input_file ~bin:true path))) with Sys_error _ -> exc_string ("Could not read file " ^ path) ) let read = vfun2 (fun path binary -> let path = decode_string path in let binary = match binary with - | VTrue -> true + | VTrue | VNull -> true | _ -> false in - let ch = open_in_gen (Open_rdonly :: (if binary then [Open_binary] else [])) 0 path in + let ch = + try open_in_gen (Open_rdonly :: (if binary then [Open_binary] else [])) 0 path + with Sys_error msg -> exc_string msg + in encode_instance key_sys_io_FileInput ~kind:(IInChannel(ch,ref false)) ) @@ -1109,9 +1171,9 @@ module StdFPHelper = struct let low = decode_i32 low in let high = decode_i32 high in let b = Bytes.make 8 '0' in - StdBytes.write_i32 b 0 low; - StdBytes.write_i32 b 4 high; - let i64 = StdBytes.read_i64 b 0 in + EvalBytes.write_i32 b 0 low; + EvalBytes.write_i32 b 4 high; + let i64 = EvalBytes.read_i64 b 0 in vfloat (Int64.float_of_bits i64) ) end @@ -1127,19 +1189,16 @@ module StdFileSystem = struct let patch_path s = if String.length s > 1 && String.length s <= 3 && s.[1] = ':' then Path.add_trailing_slash s + else if s = "/" then "/" else remove_trailing_slash s - let absolutePath = vfun1 (fun relPath -> - encode_string (Path.unique_full_path (decode_string relPath)) - ) - let createDirectory = vfun1 (fun path -> - (try Common.mkdir_from_path (Path.add_trailing_slash (decode_string path)) with Unix.Unix_error (_,cmd,msg) -> exc_string (cmd ^ " " ^ msg)); + catch_unix_error Path.mkdir_from_path (Path.add_trailing_slash (decode_string path)); vnull ) let deleteDirectory = vfun1 (fun path -> - (try Unix.rmdir (decode_string path) with Unix.Unix_error (_,cmd,msg) -> exc_string (cmd ^ " " ^ msg)); + catch_unix_error Unix.rmdir (decode_string path); vnull ) @@ -1154,7 +1213,7 @@ module StdFileSystem = struct ) let fullPath = vfun1 (fun relPath -> - try encode_string (Extc.get_full_path (decode_string relPath)) with exc -> exc_string (Printexc.to_string exc) + try create_unknown (Extc.get_full_path (decode_string relPath)) with exc -> exc_string (Printexc.to_string exc) ) let isDirectory = vfun1 (fun dir -> @@ -1163,8 +1222,14 @@ module StdFileSystem = struct ) let readDirectory = vfun1 (fun dir -> - let d = try Sys.readdir (decode_string dir) with Sys_error s -> exc_string s in - encode_array (Array.to_list (Array.map (fun s -> encode_string s) d)) + let dir = decode_string dir in + let d = try + if not (Sys.is_directory (patch_path dir)) then exc_string "No such directory"; + Sys.readdir dir + with Sys_error s -> + exc_string s + in + encode_array (Array.to_list (Array.map (fun s -> create_unknown s) d)) ) let rename = vfun2 (fun path newPath -> @@ -1173,9 +1238,8 @@ module StdFileSystem = struct ) let stat = vfun1 (fun path -> - let s = try Unix.stat (patch_path (decode_string path)) with Unix.Unix_error (_,cmd,msg) -> exc_string (cmd ^ " " ^ msg) in - let open Unix in - encode_obj None [ + let s = catch_unix_error Unix.stat (patch_path (decode_string path)) in + encode_obj [ key_gid,vint s.st_gid; key_uid,vint s.st_uid; key_atime,StdDate.encode_date s.st_atime; @@ -1193,33 +1257,33 @@ end module StdGc = struct open Gc - let key_minor_heap_size = hash_s "minor_heap_size" - let key_major_heap_increment = hash_s "major_heap_increment" - let key_space_overhead = hash_s "space_overhead" - let key_verbose = hash_s "verbose" - let key_max_overhead = hash_s "max_overhead" - let key_stack_limit = hash_s "stack_limit" - let key_allocation_policy = hash_s "allocation_policy" - let key_minor_words = hash_s "minor_words" - let key_minor_words = hash_s "minor_words" - let key_promoted_words = hash_s "promoted_words" - let key_major_words = hash_s "major_words" - let key_minor_collections = hash_s "minor_collections" - let key_major_collections = hash_s "major_collections" - let key_heap_words = hash_s "heap_words" - let key_heap_chunks = hash_s "heap_chunks" - let key_live_words = hash_s "live_words" - let key_live_blocks = hash_s "live_blocks" - let key_free_words = hash_s "free_words" - let key_free_blocks = hash_s "free_blocks" - let key_largest_free = hash_s "largest_free" - let key_fragments = hash_s "fragments" - let key_compactions = hash_s "compactions" - let key_top_heap_words = hash_s "top_heap_words" - let key_stack_size = hash_s "stack_size" + let key_minor_heap_size = hash "minor_heap_size" + let key_major_heap_increment = hash "major_heap_increment" + let key_space_overhead = hash "space_overhead" + let key_verbose = hash "verbose" + let key_max_overhead = hash "max_overhead" + let key_stack_limit = hash "stack_limit" + let key_allocation_policy = hash "allocation_policy" + let key_minor_words = hash "minor_words" + let key_minor_words = hash "minor_words" + let key_promoted_words = hash "promoted_words" + let key_major_words = hash "major_words" + let key_minor_collections = hash "minor_collections" + let key_major_collections = hash "major_collections" + let key_heap_words = hash "heap_words" + let key_heap_chunks = hash "heap_chunks" + let key_live_words = hash "live_words" + let key_live_blocks = hash "live_blocks" + let key_free_words = hash "free_words" + let key_free_blocks = hash "free_blocks" + let key_largest_free = hash "largest_free" + let key_fragments = hash "fragments" + let key_compactions = hash "compactions" + let key_top_heap_words = hash "top_heap_words" + let key_stack_size = hash "stack_size" let encode_stats stats = - encode_obj None [ + encode_obj [ key_minor_words,vfloat stats.minor_words; key_promoted_words,vfloat stats.promoted_words; key_major_words,vfloat stats.major_words; @@ -1244,7 +1308,7 @@ module StdGc = struct let counters = vfun0 (fun () -> let (minor_words,promoted_words,major_words) = Gc.counters() in - encode_obj None [ + encode_obj [ key_minor_words,vfloat minor_words; key_promoted_words,vfloat promoted_words; key_major_words,vfloat major_words; @@ -1268,7 +1332,7 @@ module StdGc = struct let get = vfun0 (fun () -> let control = Gc.get() in - encode_obj None [ + encode_obj [ key_minor_heap_size,vint control.minor_heap_size; key_major_heap_increment,vint control.major_heap_increment; key_space_overhead,vint control.space_overhead; @@ -1317,58 +1381,103 @@ module StdGc = struct end module StdHost = struct - open Unix - let int32_addr h = let base = Int32.to_int (Int32.logand h 0xFFFFFFl) in let str = Printf.sprintf "%ld.%d.%d.%d" (Int32.shift_right_logical h 24) (base lsr 16) ((base lsr 8) land 0xFF) (base land 0xFF) in - inet_addr_of_string str + catch_unix_error Unix.inet_addr_of_string str let localhost = vfun0 (fun () -> - encode_string (gethostname()) + create_unknown (catch_unix_error Unix.gethostname()) ) let hostReverse = vfun1 (fun ip -> let ip = decode_i32 ip in - try encode_string (gethostbyaddr (int32_addr ip)).h_name with Not_found -> exc_string "Could not reverse host" + try create_unknown (catch_unix_error Unix.gethostbyaddr (int32_addr ip)).h_name with Not_found -> exc_string "Could not reverse host" ) let hostToString = vfun1 (fun ip -> let ip = decode_i32 ip in - encode_string (string_of_inet_addr (int32_addr ip)) + create_unknown (catch_unix_error Unix.string_of_inet_addr (int32_addr ip)) ) let resolve = vfun1 (fun name -> let name = decode_string name in - let h = try gethostbyname name with Not_found -> exc_string ("Could not resolve host " ^ name) in - let addr = string_of_inet_addr h.h_addr_list.(0) in + let h = catch_unix_error Unix.gethostbyname name in + let addr = catch_unix_error Unix.string_of_inet_addr h.h_addr_list.(0) in let a, b, c, d = Scanf.sscanf addr "%d.%d.%d.%d" (fun a b c d -> a,b,c,d) in vint32 (Int32.logor (Int32.shift_left (Int32.of_int a) 24) (Int32.of_int (d lor (c lsl 8) lor (b lsl 16)))) ) end +module StdLock = struct + let this vthis = match vthis with + | VInstance {ikind = ILock lock} -> lock + | v -> unexpected_value v "Lock" + + let release = vifun0 (fun vthis -> + let this = this vthis in + Deque.push this.ldeque vnull; + vnull + ) + + let wait = vifun1 (fun vthis timeout -> + let lock = this vthis in + let rec loop target_time = + match Deque.pop lock.ldeque false with + | None -> + if Sys.time() >= target_time then + vfalse + else begin + Thread.yield(); + loop target_time + end + | Some _ -> + vtrue + in + match Deque.pop lock.ldeque false with + | None -> + begin match timeout with + | VNull -> + ignore(Deque.pop lock.ldeque true); + vtrue + | _ -> + let target_time = (Sys.time()) +. num timeout in + loop target_time + end + | Some _ -> + vtrue + ) +end + +let lineEnd = match Sys.os_type with + | "Win32" | "Cygwin" -> "\r\n" + | _ -> "\n" + module StdLog = struct - let key_fileName = hash_s "fileName" - let key_lineNumber = hash_s "lineNumber" - let key_customParams = hash_s "customParams" + let key_fileName = hash "fileName" + let key_lineNumber = hash "lineNumber" + let key_customParams = hash "customParams" let trace = vfun2 (fun v infos -> let s = value_string v in - let infos = decode_object infos in - let file_name = decode_string (object_field infos key_fileName) in - let line_number = decode_int (object_field infos key_lineNumber) in - let l = match object_field infos key_customParams with - | VArray va -> s :: (List.map value_string (EvalArray.to_list va)) - | _ -> [s] - in - ((get_ctx()).curapi.MacroApi.get_com()).Common.print (Printf.sprintf "%s:%i: %s\n" file_name line_number (String.concat "," l)); + let s = match infos with + | VNull -> (Printf.sprintf "%s" s) ^ lineEnd + | _ -> let infos = decode_object infos in + let file_name = decode_string (object_field infos key_fileName) in + let line_number = decode_int (object_field infos key_lineNumber) in + let l = match object_field infos key_customParams with + | VArray va -> s :: (List.map value_string (EvalArray.to_list va)) + | _ -> [s] + in + (Printf.sprintf "%s:%i: %s" file_name line_number (String.concat "," l)) ^ lineEnd in + ((get_ctx()).curapi.MacroApi.get_com()).Common.print s; vnull ) end let encode_list_iterator l = let l = ref l in - encode_obj None [ + encode_obj [ key_hasNext,vifun0 (fun _ -> match !l with [] -> vfalse | _ -> vtrue ); @@ -1378,46 +1487,174 @@ let encode_list_iterator l = ) ] -module StdMap (Hashtbl : Hashtbl.S) = struct - let map_fields enc dec str enc_inst this = [ - "get",vifun1 (fun vthis vkey -> try Hashtbl.find (this vthis) (dec vkey) with Not_found -> vnull); - "set",vifun2 (fun vthis vkey vvalue -> Hashtbl.replace (this vthis) (dec vkey) vvalue; vnull); - "exists",vifun1 (fun vthis vkey -> vbool (Hashtbl.mem (this vthis) (dec vkey))); - "remove",vifun1 (fun vthis vkey -> - let key = dec vkey in - let b = Hashtbl.mem (this vthis) key in - Hashtbl.remove (this vthis) key; - vbool b - ); - "keys",vifun0 (fun vthis -> - let keys = Hashtbl.fold (fun v _ acc -> (enc v) :: acc) (this vthis) [] in - encode_list_iterator keys - ); - "iterator",vifun0 (fun vthis -> - let keys = Hashtbl.fold (fun _ v acc -> v :: acc) (this vthis) [] in - encode_list_iterator keys - ); - "copy",vifun0 (fun vthis -> - let copied = Hashtbl.copy (this vthis) in - enc_inst copied - ); - "toString",vifun0 (fun vthis -> - let open Rope in - let s = concat empty [ - of_char '{'; - concat rcomma - (Hashtbl.fold (fun key vvalue acc -> (concat empty [str key; of_string " => "; s_value 0 vvalue]) :: acc) (this vthis) []) - ; - of_char '}' - ] in - encode_rope s - ); - ] +let map_key_value_iterator path = vifun0 (fun vthis -> + let ctx = get_ctx() in + let vit = encode_instance path in + let fnew = get_instance_constructor ctx path null_pos in + ignore(call_value_on vit (Lazy.force fnew) [vthis]); + vit +) + +module StdIntMap = struct + let this vthis = match vthis with + | VInstance {ikind = IIntMap h} -> h + | v -> unexpected_value v "int map" + + let copy = vifun0 (fun vthis -> + let copied = IntHashtbl.copy (this vthis) in + encode_int_map_direct copied + ) + + let exists = vifun1 (fun vthis vkey -> + vbool (IntHashtbl.mem (this vthis) (decode_int vkey)) + ) + + let get = vifun1 (fun vthis vkey -> + try IntHashtbl.find (this vthis) (decode_int vkey) + with Not_found -> vnull + ) + + let iterator = vifun0 (fun vthis -> + let keys = IntHashtbl.fold (fun _ v acc -> v :: acc) (this vthis) [] in + encode_list_iterator keys + ) + + let keys = vifun0 (fun vthis -> + let keys = IntHashtbl.fold (fun k _ acc -> vint k :: acc) (this vthis) [] in + encode_list_iterator keys + ) + + let keyValueIterator = map_key_value_iterator key_haxe_iterators_map_key_value_iterator + + let remove = vifun1 (fun vthis vkey -> + let this = this vthis in + let key = decode_int vkey in + let b = IntHashtbl.mem this key in + IntHashtbl.remove this key; + vbool b + ) + + let set = vifun2 (fun vthis vkey vvalue -> + IntHashtbl.add (this vthis) (decode_int vkey) vvalue; + vnull + ) + + let toString = vifun0 (fun vthis -> + let this = this vthis in + let l = IntHashtbl.fold (fun key vvalue acc -> + (join rempty [create_ascii (string_of_int key); create_ascii " => "; s_value 0 vvalue]) :: acc) this [] in + let s = join rcomma l in + let s = join rempty [rbropen;s;rbrclose] in + vstring s + ) end -module StdStringMap = StdMap(StringHashtbl) -module StdIntMap = StdMap(IntHashtbl) -module StdObjectMap = StdMap(ValueHashtbl) +module StdStringMap = struct + let this vthis = match vthis with + | VInstance {ikind = IStringMap h} -> h + | v -> unexpected_value v "string map" + + let copy = vifun0 (fun vthis -> + let copied = StringHashtbl.copy (this vthis) in + encode_string_map_direct copied + ) + + let exists = vifun1 (fun vthis vkey -> + vbool (StringHashtbl.mem (this vthis) (decode_vstring vkey)) + ) + + let get = vifun1 (fun vthis vkey -> + try snd (StringHashtbl.find (this vthis) (decode_vstring vkey)) + with Not_found -> vnull + ) + + let iterator = vifun0 (fun vthis -> + let keys = StringHashtbl.fold (fun _ (_,v) acc -> v :: acc) (this vthis) [] in + encode_list_iterator keys + ) + + let keys = vifun0 (fun vthis -> + let keys = StringHashtbl.fold (fun _ (k,_) acc -> vstring k :: acc) (this vthis) [] in + encode_list_iterator keys + ) + + let keyValueIterator = map_key_value_iterator key_haxe_iterators_map_key_value_iterator + + let remove = vifun1 (fun vthis vkey -> + let this = this vthis in + let key = decode_vstring vkey in + let b = StringHashtbl.mem this key in + StringHashtbl.remove this key; + vbool b + ) + + let set = vifun2 (fun vthis vkey vvalue -> + StringHashtbl.add (this vthis) (decode_vstring vkey) vvalue; + vnull + ) + + let toString = vifun0 (fun vthis -> + let this = this vthis in + let l = StringHashtbl.fold (fun _ (key,vvalue) acc -> + (join rempty [key; create_ascii " => "; s_value 0 vvalue]) :: acc) this [] in + let s = join rcomma l in + let s = join rempty [rbropen;s;rbrclose] in + vstring s + ) +end + +module StdObjectMap = struct + let this vthis = match vthis with + | VInstance {ikind = IObjectMap h} -> Obj.magic h + | v -> unexpected_value v "int map" + + let copy = vifun0 (fun vthis -> + let copied = ValueHashtbl.copy (this vthis) in + encode_object_map_direct copied + ) + + let exists = vifun1 (fun vthis vkey -> + vbool (ValueHashtbl.mem (this vthis) vkey) + ) + + let get = vifun1 (fun vthis vkey -> + try ValueHashtbl.find (this vthis) vkey + with Not_found -> vnull + ) + + let iterator = vifun0 (fun vthis -> + let keys = ValueHashtbl.fold (fun _ v acc -> v :: acc) (this vthis) [] in + encode_list_iterator keys + ) + + let keys = vifun0 (fun vthis -> + let keys = ValueHashtbl.fold (fun k _ acc -> k :: acc) (this vthis) [] in + encode_list_iterator keys + ) + + let keyValueIterator = map_key_value_iterator key_haxe_iterators_map_key_value_iterator + + let remove = vifun1 (fun vthis vkey -> + let this = this vthis in + let b = ValueHashtbl.mem this vkey in + ValueHashtbl.remove this vkey; + vbool b + ) + + let set = vifun2 (fun vthis vkey vvalue -> + ValueHashtbl.replace (this vthis) vkey vvalue; + vnull + ) + + let toString = vifun0 (fun vthis -> + let this = this vthis in + let l = ValueHashtbl.fold (fun key vvalue acc -> + (join rempty [s_value 0 key; create_ascii " => "; s_value 0 vvalue]) :: acc) this [] in + let s = join rcomma l in + let s = join rempty [rbropen;s;rbrclose] in + vstring s + ) +end let random = Random.State.make_self_init() @@ -1488,6 +1725,35 @@ module StdMd5 = struct ) end +module StdMutex = struct + let this vthis = match vthis with + | VInstance {ikind=IMutex mutex} -> mutex + | _ -> unexpected_value vthis "Mutex" + + let acquire = vifun0 (fun vthis -> + let mutex = this vthis in + Mutex.lock mutex.mmutex; + mutex.mowner <- Some (Thread.id (Thread.self())); + vnull + ) + + let release = vifun0 (fun vthis -> + let mutex = this vthis in + mutex.mowner <- None; + Mutex.unlock mutex.mmutex; + vnull + ) + + let tryAcquire = vifun0 (fun vthis -> + let mutex = this vthis in + if Mutex.try_lock mutex.mmutex then begin + mutex.mowner <- Some (Thread.id (Thread.self())); + vtrue + end else + vfalse + ) +end + module StdNativeProcess = struct let this vthis = match vthis with @@ -1543,8 +1809,8 @@ end module StdReflect = struct - let r_get_ = Rope.of_string "get_" - let r_set_ = Rope.of_string "set_" + let r_get_ = create_ascii "get_" + let r_set_ = create_ascii "set_" let callMethod = vfun3 (fun o f args -> call_value_on o f (decode_array args) @@ -1567,7 +1833,8 @@ module StdReflect = struct vbool (loop a b) ) - let copy = vfun1 (fun o -> match o with + let copy = vfun1 (fun o -> match vresolve o with + | VNull -> VNull | VObject o -> VObject { o with ofields = Array.copy o.ofields } | VInstance vi -> vinstance { ifields = Array.copy vi.ifields; @@ -1581,16 +1848,19 @@ module StdReflect = struct ) let deleteField = vfun2 (fun o name -> - let name = hash (decode_rope name) in - match o with + let name = hash (decode_vstring name).sstring in + match vresolve o with | VObject o -> - if IntMap.mem name o.oextra then begin - o.oextra <- IntMap.remove name o.oextra; - vtrue - end else if IntMap.mem name o.oproto.pinstance_names then begin - let i = IntMap.find name o.oproto.pinstance_names in - o.oremoved <- IntMap.add name true o.oremoved; - o.ofields.(i) <- vnull; + let found = ref false in + let fields = IntMap.fold (fun name' i acc -> + if name = name' then begin + found := true; + acc + end else + (name',o.ofields.(i)) :: acc + ) o.oproto.pinstance_names [] in + if !found then begin + update_object_prototype o fields; vtrue end else vfalse @@ -1599,12 +1869,12 @@ module StdReflect = struct ) let field' = vfun2 (fun o name -> - if o = vnull then vnull else dynamic_field o (hash (decode_rope name)) + if o = vnull then vnull else dynamic_field o (hash (decode_vstring name).sstring) ) let fields = vfun1 (fun o -> let proto_fields proto = IntMap.fold (fun name _ acc -> name :: acc) proto.pnames [] in - let fields = match o with + let fields = match vresolve o with | VObject o -> List.map fst (object_fields o) | VInstance vi -> IntMap.fold (fun name _ acc -> name :: acc) vi.iproto.pinstance_names [] | VPrototype proto -> proto_fields proto @@ -1612,20 +1882,25 @@ module StdReflect = struct | VString _ | VArray _ | VVector _ -> [key_length] | _ -> unexpected_value o "object" in - encode_array (List.map (fun i -> encode_rope (rev_hash i)) fields) + encode_array (List.map (fun i -> encode_string (rev_hash i)) fields) ) let getProperty = vfun2 (fun o name -> - let name = decode_rope name in - let vget = field o (hash (Rope.concat Rope.empty [r_get_;name])) in - if vget <> VNull then call_value_on o vget [] - else dynamic_field o (hash name) + if o = VNull then + vnull + else begin + let name = decode_vstring name in + let name_get = hash (concat r_get_ name).sstring in + let vget = field o name_get in + if vget <> VNull then call_value_on o vget [] + else dynamic_field o (hash name.sstring) + end ) let hasField = vfun2 (fun o field -> - let name = hash (decode_rope field) in - let b = match o with - | VObject o -> (IntMap.mem name o.oproto.pinstance_names && not (IntMap.mem name o.oremoved)) || IntMap.mem name o.oextra + let name = hash (decode_vstring field).sstring in + let b = match vresolve o with + | VObject o -> IntMap.mem name o.oproto.pinstance_names | VInstance vi -> IntMap.mem name vi.iproto.pinstance_names || IntMap.mem name vi.iproto.pnames | VPrototype proto -> IntMap.mem name proto.pnames | _ -> unexpected_value o "object" @@ -1644,26 +1919,26 @@ module StdReflect = struct | _ -> vfalse ) - let isObject = vfun1 (fun v -> match v with + let isObject = vfun1 (fun v -> match vresolve v with | VObject _ | VString _ | VArray _ | VVector _ | VInstance _ | VPrototype _ -> vtrue | _ -> vfalse ) let makeVarArgs = vfun1 (fun f -> - vstatic_function (FunN (fun vl -> call_value f [encode_array vl])) + vstatic_function ((fun vl -> call_value f [encode_array vl])) ) let setField = vfun3 (fun o name v -> - set_field o (hash (decode_rope name)) v; vnull + (try set_field o (hash (decode_vstring name).sstring) v with Not_found -> ()); vnull ) let setProperty = vfun3 (fun o name v -> - let name = decode_rope name in - let vset = field o (hash (Rope.concat Rope.empty [r_set_;name])) in - if vset <> VNull then - call_value_on o vset [v] + let name = decode_vstring name in + let name_set = hash (concat r_set_ name).sstring in + let vset = field o name_set in + if vset <> VNull then call_value_on o vset [v] else begin - set_field o (hash name) v; + (try set_field o (hash name.sstring) v with Not_found -> ()); vnull end ) @@ -1673,11 +1948,11 @@ module StdResource = struct open Common let listNames = vfun0 (fun () -> - encode_array (List.map encode_string (hashtbl_keys ((get_ctx()).curapi.MacroApi.get_com()).resources)) + encode_array (List.map create_unknown (hashtbl_keys ((get_ctx()).curapi.MacroApi.get_com()).resources)) ) let getString = vfun1 (fun name -> - try encode_string (Hashtbl.find ((get_ctx()).curapi.MacroApi.get_com()).resources (decode_string name)) with Not_found -> vnull + try ((create_unknown (Hashtbl.find ((get_ctx()).curapi.MacroApi.get_com()).resources (decode_string name)))) with Not_found -> vnull ) let getBytes = vfun1 (fun name -> @@ -1685,11 +1960,21 @@ module StdResource = struct ) end -module StdSocket = struct - open Unix +module StdSha1 = struct + let encode = vfun1 (fun s -> + let s = decode_string s in + encode_string (Sha1.to_hex (Sha1.string s)) + ) + let make = vfun1 (fun b -> + let b = decode_bytes b in + encode_bytes (Bytes.unsafe_of_string (Sha1.to_bin (Sha1.string (Bytes.unsafe_to_string b)))) + ) +end + +module StdSocket = struct let inet_addr_to_int32 addr = - let s = string_of_inet_addr addr in + let s = catch_unix_error Unix.string_of_inet_addr addr in match List.map Int32.of_string (ExtString.String.nsplit s ".") with | [a;b;c;d] -> Int32.add (Int32.add (Int32.add (Int32.shift_left a 24) (Int32.shift_left b 16)) (Int32.shift_left c 8)) d | _ -> assert false @@ -1700,7 +1985,7 @@ module StdSocket = struct let accept = vifun0 (fun vthis -> let this = this vthis in - let socket,_ = Unix.accept this in + let socket,_ = catch_unix_error Unix.accept this in encode_instance key_sys_net__Socket_NativeSocket ~kind:(ISocket socket) ) @@ -1708,12 +1993,12 @@ module StdSocket = struct let this = this vthis in let host = decode_i32 host in let port = decode_int port in - (try Unix.bind this (ADDR_INET (StdHost.int32_addr host,port)) with Unix_error _ -> exc_string (Printf.sprintf "Could not bind port %i" port)); + catch_unix_error Unix.bind this (ADDR_INET (StdHost.int32_addr host,port)); vnull ) let close = vifun0 (fun vthis -> - Unix.close (this vthis); + catch_unix_error Unix.close (this vthis); vnull ) @@ -1721,14 +2006,14 @@ module StdSocket = struct let this = this vthis in let host = decode_i32 host in let port = decode_int port in - Unix.connect this (ADDR_INET (StdHost.int32_addr host,port)); + catch_unix_error (Unix.connect this) (ADDR_INET (StdHost.int32_addr host,port)); vnull ) let host = vifun0 (fun vthis -> - match getsockname (this vthis) with + match catch_unix_error Unix.getsockname (this vthis) with | ADDR_INET (addr,port) -> - encode_obj None [ + encode_obj [ key_ip,vint32 (inet_addr_to_int32 addr); key_port,vint port; ] @@ -1738,14 +2023,14 @@ module StdSocket = struct let listen = vifun1 (fun vthis connections -> let this = this vthis in let connections = decode_int connections in - Unix.listen this connections; + catch_unix_error Unix.listen this connections; vnull ) let peer = vifun0 (fun vthis -> - match getpeername (this vthis) with + match catch_unix_error Unix.getpeername (this vthis) with | ADDR_INET (addr,port) -> - encode_obj None [ + encode_obj [ key_ip,vint32 (inet_addr_to_int32 addr); key_port,vint port; ] @@ -1757,12 +2042,12 @@ module StdSocket = struct let buf = decode_bytes buf in let pos = decode_int pos in let len = decode_int len in - vint (try recv this buf pos len [] with Unix_error(error,msg,_) -> exc_string (Printf.sprintf "%s: %s" msg (error_message error))) + vint (catch_unix_error Unix.recv this buf pos len []) ) let receiveChar = vifun0 (fun vthis -> let buf = Bytes.make 1 '\000' in - ignore(Unix.recv (this vthis) buf 0 1 []); + ignore(catch_unix_error Unix.recv (this vthis) buf 0 1 []); vint (int_of_char (Bytes.unsafe_get buf 0)) ) @@ -1770,18 +2055,23 @@ module StdSocket = struct let proto = get_instance_prototype (get_ctx()) key_sys_net_Socket null_pos in let i = get_instance_field_index proto key_socket null_pos in let pair = function - | VInstance vi as v -> this vi.iproto.pfields.(i),v + | VInstance vi as v -> this vi.ifields.(i),v | v -> unexpected_value v "NativeSocket" in - let read = List.map pair (decode_array read) in - let write = List.map pair (decode_array write) in - let others = List.map pair (decode_array others) in + let decode_optional_array = function + | VNull -> [] + | VArray va -> EvalArray.to_list va + | v -> unexpected_value v "array" + in + let read = List.map pair (decode_optional_array read) in + let write = List.map pair (decode_optional_array write) in + let others = List.map pair (decode_optional_array others) in let timeout = match timeout with VNull -> 0. | VInt32 i -> Int32.to_float i | VFloat f -> f | _ -> unexpected_value timeout "number" in - let read',write',others' = Unix.select (List.map fst read) (List.map fst write) (List.map fst others) timeout in + let read',write',others' = catch_unix_error Unix.select (List.map fst read) (List.map fst write) (List.map fst others) timeout in let read = List.map (fun sock -> List.assq sock read) read' in let write = List.map (fun sock -> List.assq sock write) write' in let others = List.map (fun sock -> List.assq sock others) others' in - encode_obj None [ + encode_obj [ key_read,encode_array read; key_write,encode_array write; key_others,encode_array others; @@ -1793,40 +2083,50 @@ module StdSocket = struct let buf = decode_bytes buf in let pos = decode_int pos in let len = decode_int len in - vint (send this buf pos len []) + vint (catch_unix_error Unix.send this buf pos len []) ) let sendChar = vifun1 (fun vthis char -> let this = this vthis in let char = decode_int char in - ignore(Unix.send this (Bytes.make 1 (char_of_int char)) 0 1 []); + ignore(catch_unix_error Unix.send this (Bytes.make 1 (char_of_int char)) 0 1 []); VNull ) let setFastSend = vifun1 (fun vthis b -> let this = this vthis in let b = decode_bool b in - setsockopt this TCP_NODELAY b; + catch_unix_error Unix.setsockopt this TCP_NODELAY b; + vnull + ) + + let setBroadcast = vifun1 (fun vthis b -> + let this = this vthis in + let b = decode_bool b in + catch_unix_error Unix.setsockopt this SO_BROADCAST b; vnull ) let setTimeout = vifun1 (fun vthis timeout -> let this = this vthis in let timeout = match timeout with VNull -> 0. | VInt32 i -> Int32.to_float i | VFloat f -> f | _ -> unexpected_value timeout "number" in - setsockopt_float this SO_RCVTIMEO timeout; - setsockopt_float this SO_SNDTIMEO timeout; + let timeout = timeout *. 1000. in + catch_unix_error (fun () -> + Unix.setsockopt_float this SO_RCVTIMEO timeout; + Unix.setsockopt_float this SO_SNDTIMEO timeout; + ) (); vnull ) let shutdown = vifun2 (fun vthis read write -> let this = this vthis in let mode = match read,write with - | VTrue,VTrue -> SHUTDOWN_ALL + | VTrue,VTrue -> Unix.SHUTDOWN_ALL | VTrue,_ -> SHUTDOWN_RECEIVE | _,VTrue -> SHUTDOWN_SEND | _ -> exc_string "Nothing to shut down" in - Unix.shutdown this mode; + catch_unix_error Unix.shutdown this mode; vnull ) end @@ -1838,14 +2138,17 @@ module StdStd = struct | _ -> vfalse ) - let instance = vfun2 (fun v t -> match t with + let downcast = vfun2 (fun v t -> match t with | VPrototype proto -> if is v proto.ppath then v else vnull | _ -> vfalse ) - let string = vfun1 (fun v -> - encode_rope (s_value 0 v) + let instance = downcast + + let string = vfun1 (fun v -> match v with + | VString _ -> v + | _ -> vstring (s_value 0 v) ) let int = vfun1 (fun v -> @@ -1853,11 +2156,11 @@ module StdStd = struct ) let parseInt = vfun1 (fun v -> - try vint32 (Common.parse_int (decode_string v)) with _ -> vnull + try vint32 (Numeric.parse_int (decode_string v)) with _ -> vnull ) let parseFloat = vfun1 (fun v -> - try vfloat (Common.parse_float (decode_string v)) with _ -> vnull + try vfloat (Numeric.parse_float (decode_string v)) with _ -> vnull ) let random = vfun1 (fun v -> @@ -1868,232 +2171,283 @@ end module StdString = struct let this vthis = match vthis with - | VString(r,_) -> r - | v -> unexpected_value v "string" - - let this_pair vthis = match vthis with - | VString(r,s) -> r,Lazy.force s - | v -> unexpected_value v "string" - - let this_string vthis = match vthis with - | VString(_,s) -> Lazy.force s + | VString s -> s | v -> unexpected_value v "string" let charAt = vifun1 (fun vthis index -> - let this = this_string vthis in + let this = this vthis in let i = decode_int index in - if i < 0 || i >= String.length this then encode_rope Rope.empty - else encode_rope (Rope.of_char (String.get this i)) + if i < 0 || i >= this.slength then encode_string "" + else vstring (from_char_code (char_at this i)) ) let charCodeAt = vifun1 (fun vthis index -> - let this = this_string vthis in + let this = this vthis in let i = decode_int index in - if i < 0 || i >= String.length this then vnull - else vint (int_of_char (String.get this i)) + if i < 0 || i >= this.slength then vnull + else vint (char_at this i) ) let fromCharCode = vfun1 (fun i -> let i = decode_int i in - if i < 0 || i > 0xFF then vnull - else encode_rope (Rope.of_char (char_of_int i)) + try + vstring (from_char_code i) + with + | Not_found -> + vnull ) let indexOf = vifun2 (fun vthis str startIndex -> + let str = this str in let this = this vthis in - let str = decode_string str in let i = default_int startIndex 0 in try - vint (Rope.search_forward_string str this i) + if str.slength = 0 then + vint (max 0 (min i this.slength)) + else begin + let i = + if i >= this.slength then raise Not_found + else if i < 0 then max (this.slength + i) 0 + else i + in + let b = get_offset this i in + let offset,_,_ = find_substring this str false i b in + vint offset + end with Not_found -> vint (-1) ) let lastIndexOf = vifun2 (fun vthis str startIndex -> - let this = this_string vthis in - let str = decode_string str in - let i = default_int startIndex (String.length this - 1) in + let str = this str in + let this = this vthis in try - if i >= String.length this || i < 0 then raise Not_found; - vint (Str.search_backward (Str.regexp_string str) this i) + if str.slength = 0 then begin + let i = default_int startIndex this.slength in + vint (max 0 (min i this.slength)) + end else begin + let i = default_int startIndex (this.slength - str.slength) in + let i = if i < 0 then raise Not_found else if i >= this.slength - str.slength then this.slength - str.slength else i in + let b = get_offset this i in + let offset,_,_ = find_substring this str true i b in + vint offset + end with Not_found -> vint (-1) ) let split = vifun1 (fun vthis delimiter -> - let this,s = this_pair vthis in - let delimiter = decode_string delimiter in - let l_delimiter = String.length delimiter in - let l_this = Rope.length this in - if l_delimiter = 0 then - encode_array (List.map (fun chr -> encode_string (String.make 1 chr)) (ExtString.String.explode s)) - else if l_delimiter > l_this then - encode_array [encode_rope this] + let this = this vthis in + let s = this.sstring in + let delimiter = decode_vstring delimiter in + let bl_delimiter = String.length delimiter.sstring in + let bl_this = String.length s in + let encode_range pos length clength = + let s = String.sub s pos length in + vstring (create_with_length s clength) + in + if bl_delimiter = 0 then begin + let acc = DynArray.create () in + UTF8.iter (fun uc -> + DynArray.add acc (vstring (create_with_length (UTF8.init 1 (fun _ -> uc)) 1)); + ) s; + encode_array (DynArray.to_list acc) + end else if bl_delimiter > bl_this then + encode_array [encode_range 0 bl_this this.slength] else begin - let chr = delimiter.[0] in let acc = DynArray.create () in - let rec loop k i = + let f = find_substring this delimiter false in + let rec loop c_index b_index = try - if i > l_this - l_delimiter then raise Not_found; - let index = String.index_from s i chr in - let rec loop2 i2 = - if i2 = l_delimiter then true - else if String.unsafe_get s (index + i2) = String.unsafe_get delimiter i2 then loop2 (i2 + 1) - else false - in - if not (loop2 1) then - loop k (index + 1) - else begin - DynArray.add acc (encode_rope (Rope.sub this k (index - k))); - loop (index + l_delimiter) (index + l_delimiter) - end + let c_offset,b_offset,next = f c_index b_index in + DynArray.add acc (encode_range b_index (b_offset - b_index) (c_offset - c_index)); + loop (c_offset + delimiter.slength) next; with Not_found -> - DynArray.add acc (encode_rope (Rope.sub this k (l_this - k))) + DynArray.add acc (encode_range b_index (bl_this - b_index) (this.slength - c_index)) in - let rec loop1 i = - try - if i = l_this then raise Not_found; - let index = String.index_from s i chr in - DynArray.add acc (encode_rope (Rope.sub this i (index - i))); - loop1 (index + l_delimiter) - with Not_found -> - DynArray.add acc (encode_rope (Rope.sub this i (l_this - i))) - in - if l_delimiter = 1 then loop1 0 else loop 0 0; + loop 0 0; encode_array_instance (EvalArray.create (DynArray.to_array acc)) end ) let substr = vifun2 (fun vthis pos len -> let this = this vthis in - let pos = decode_int pos in - if pos >= Rope.length this then - encode_rope Rope.empty + let cl_this = this.slength in + let c_pos = decode_int pos in + if c_pos >= cl_this then + encode_string "" else begin - let pos = if pos < 0 then begin - let pos = Rope.length this + pos in - if pos < 0 then 0 else pos - end else pos in - let len = default_int len (Rope.length this - pos) in - let len = if len < 0 then Rope.length this + len - pos else len in - let s = - if len < 0 then Rope.empty - else if len + pos > Rope.length this then Rope.sub this pos (Rope.length this - pos) - else Rope.sub this pos len - in - encode_rope s + let c_pos = if c_pos < 0 then begin + let c_pos = this.slength + c_pos in + if c_pos < 0 then 0 else c_pos + end else c_pos in + begin + let c_len = match len with + | VNull -> (cl_this - c_pos) + | VInt32 i -> Int32.to_int i + | _ -> unexpected_value len "int" + in + let c_len = + if c_len < 0 then cl_this + c_len - c_pos + else if c_len > cl_this - c_pos then cl_this - c_pos + else c_len + in + vstring (substr this c_pos c_len); + end end ) let substring = vifun2 (fun vthis startIndex endIndex -> let this = this vthis in - let first = decode_int startIndex in - let l = Rope.length this in - let last = default_int endIndex l in - let first = if first < 0 then 0 else first in - let last = if last < 0 then 0 else last in - let first,last = if first > last then last,first else first,last in - let last = if last > l then l else last in - let s = if first > l then - Rope.empty - else - Rope.sub this first (last - first) - in - encode_rope s + let c_first = decode_int startIndex in + let cl_this = this.slength in + let c_last = default_int endIndex cl_this in + let c_first = if c_first < 0 then 0 else c_first in + let c_last = if c_last < 0 then 0 else c_last in + let c_first,c_last = if c_first > c_last then c_last,c_first else c_first,c_last in + let c_last = if c_last > cl_this then cl_this else c_last in + if c_first > cl_this || c_first = c_last then + encode_string "" + else begin + begin + let b_offset1 = get_offset this c_first in + let c_len = c_last - c_first in + let b_len = + if c_last = cl_this then String.length this.sstring - b_offset1 + else (UTF8.move this.sstring b_offset1 c_len) - b_offset1 + in + vstring (create_with_length (String.sub this.sstring b_offset1 b_len) c_len) + end + end ) - let toLowerCase = vifun0 (fun vthis -> encode_rope (Rope.lowercase (this vthis))) + let toLowerCase = vifun0 (fun vthis -> + let this = this vthis in + vstring (case_map this false) + ) let toString = vifun0 (fun vthis -> vthis) - let toUpperCase = vifun0 (fun vthis -> encode_rope (Rope.uppercase (this vthis))) - - let cca = vifun1 (fun vthis i -> - let this = this_string vthis in - let i = decode_int i in - if i < 0 || i >= String.length this then vnull - else vint (int_of_char (String.unsafe_get this i)) + let toUpperCase = vifun0 (fun vthis -> + let this = this vthis in + vstring (case_map this true) ) + + let cca = charCodeAt end module StdStringBuf = struct - module Buffer = Rope.Buffer - let this vthis = match vthis with - | VInstance {ikind = IBuffer buf} -> buf + | VInstance {ikind = IBuffer sb} -> sb | v -> unexpected_value v "string" let add = vifun1 (fun vthis x -> let this = this vthis in - begin match x with - | VString(s,_) -> Buffer.add_rope this s - | _ -> Buffer.add_string this (value_string x) - end; + let s = match x with + | VString s -> s + | _ -> create_ascii (value_string x) + in + VStringBuffer.add_string this s; vnull; ) let addChar = vifun1 (fun vthis c -> let this = this vthis in - let c = decode_int c in - let c = try char_of_int c with _ -> exc_string "char_of_int" in - Buffer.add_char this c; + let i = decode_int c in + Buffer.add_string this.bbuffer (string_of_char_code i); + this.blength <- this.blength + 1; vnull ) let addSub = vifun3 (fun vthis s pos len -> let this = this vthis in - let s = decode_rope s in - let i = decode_int pos in - let len = match len with - | VNull -> Rope.length s - i + let s = decode_vstring s in + let c_pos = decode_int pos in + let c_len = match len with + | VNull -> String.length s.sstring - c_pos | VInt32 i -> Int32.to_int i | _ -> unexpected_value len "int" in - Buffer.add_rope this (Rope.sub s i len); + if c_len > 0 then begin + let b_offset1 = get_offset s c_pos in + let b_offset2 = UTF8.move s.sstring b_offset1 c_len in + VStringBuffer.add_substring this s b_offset1 (b_offset2 - b_offset1) c_len; + end; vnull ) let get_length = vifun0 (fun vthis -> let this = this vthis in - vint (Buffer.length this) + vint this.blength ) let toString = vifun0 (fun vthis -> - encode_rope (Buffer.contents (this vthis)) + let this = this vthis in + let s = VStringBuffer.contents this in + vstring s ) end module StdStringTools = struct let url_encode s = - let b = Rope.Buffer.create 0 in - let hex = "0123456789ABCDEF" in - for i = 0 to String.length s - 1 do - let c = String.unsafe_get s i in - match c with - | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' | '-' | '.' -> - Rope.Buffer.add_char b c - | _ -> - Rope.Buffer.add_char b '%'; - Rope.Buffer.add_char b (String.unsafe_get hex (int_of_char c lsr 4)); - Rope.Buffer.add_char b (String.unsafe_get hex (int_of_char c land 0xF)); - done; - Rope.Buffer.contents b - - let fastCodeAt = vfun2 (fun s index -> - let s = decode_string s in - let index = decode_int index in - if index >= String.length s then vnull - else vint (int_of_char s.[index]) + let b = Buffer.create 0 in + Common.url_encode s (Buffer.add_char b); + Buffer.contents b + + let fastCodeAt = StdString.charCodeAt + + let replace = vfun3 (fun s sub by -> + let by = decode_vstring by in + let sub = decode_vstring sub in + let s' = decode_vstring s in + let bl_s = String.length s'.sstring in + let buf = UTF8.Buf.create bl_s in + let replace_count = ref 0 in + let create () = + vstring (create_with_length (UTF8.Buf.contents buf) (s'.slength + by.slength * !replace_count - sub.slength * !replace_count)) + in + if sub.slength = 0 then begin + if by.slength = 0 then + s + else begin + UTF8.iter (fun uc -> + UTF8.Buf.add_char buf uc; + (* don't add for the final char *) + if !replace_count <> s'.slength - 1 then begin + UTF8.Buf.add_string buf by.sstring; + incr replace_count; + end + ) s'.sstring; + create (); + end + end else begin + let f = find_substring s' sub false in + let rec loop c_index b_index = + try + let c_offset,b_offset,next = f c_index b_index in + UTF8.Buf.add_string buf (String.sub s'.sstring b_index (b_offset - b_index)); + UTF8.Buf.add_string buf by.sstring; + incr replace_count; + loop (c_offset + sub.slength) next; + with Not_found -> + UTF8.Buf.add_string buf (String.sub s'.sstring b_index (bl_s - b_index)); + in + loop 0 0; + create() + end ) let urlEncode = vfun1 (fun s -> let s = decode_string s in - encode_rope (url_encode s) + encode_string (url_encode s) ) let urlDecode = vfun1 (fun s -> let s = decode_string s in - let b = Rope.Buffer.create 0 in + let b = VStringBuffer.create () in + let add s = + VStringBuffer.add_string b s + in let len = String.length s in let decode c = match c with @@ -2102,28 +2456,62 @@ module StdStringTools = struct | 'A'..'F' -> Some (int_of_char c - int_of_char 'A' + 10) | _ -> None in + let decode_hex i = + let p1 = (try decode (String.get s i) with _ -> None) in + let p2 = (try decode (String.get s (i + 1)) with _ -> None) in + match p1, p2 with + | Some c1, Some c2 -> + Some (((c1 lsl 4) lor c2)) + | _ -> + None + in + let expect_hex i = + match String.unsafe_get s i with + | '%' -> + begin match decode_hex (i + 1) with + | None -> exc_string "Malformed" + | Some c -> c + end + | _ -> exc_string "Malformed" + in let rec loop i = if i = len then () else let c = String.unsafe_get s i in match c with | '%' -> - let p1 = (try decode (String.get s (i + 1)) with _ -> None) in - let p2 = (try decode (String.get s (i + 2)) with _ -> None) in - (match p1, p2 with - | Some c1, Some c2 -> - Rope.Buffer.add_char b (char_of_int ((c1 lsl 4) lor c2)); - loop (i + 3) - | _ -> - loop (i + 1)); + begin match decode_hex (i + 1) with + | Some c -> + if c < 0x80 then begin + add (create_ascii (String.make 1 (char_of_int c))); + loop (i + 3) + end else if c < 0xE0 then begin + let c2 = expect_hex (i + 3) in + add (from_char_code (((c land 0x3F) lsl 6) lor (c2 land 0x7F))); + loop (i + 6) + end else if c < 0xF0 then begin + let c2 = expect_hex (i + 3) in + let c3 = expect_hex (i + 6) in + add (from_char_code (((c land 0x1F) lsl 12) lor ((c2 land 0x7F) lsl 6) lor (c3 land 0x7F))); + loop (i + 9) + end else + let c2 = expect_hex (i + 3) in + let c3 = expect_hex (i + 6) in + let c4 = expect_hex (i + 9) in + let k = ((c land 0x0F) lsl 18) lor ((c2 land 0x7F) lsl 12) lor ((c3 land 0x7F) lsl 6) lor (c4 land 0x7F) in + add (from_char_code k); + loop (i + 12) + | None -> + loop (i + 1) + end; | '+' -> - Rope.Buffer.add_char b ' '; + add (create_ascii (String.make 1 ' ')); loop (i + 1) | c -> - Rope.Buffer.add_char b c; + add (create_ascii (String.make 1 c)); loop (i + 1) in loop 0; - encode_rope (Rope.Buffer.contents b) + vstring (VStringBuffer.contents b) ) end @@ -2132,7 +2520,7 @@ module StdSys = struct open Common let args = vfun0 (fun () -> - encode_array (List.map encode_string ((get_ctx()).curapi.MacroApi.get_com()).sys_args) + encode_array (List.map create_unknown ((get_ctx()).curapi.MacroApi.get_com()).sys_args) ) let _command = vfun1 (fun cmd -> @@ -2143,11 +2531,11 @@ module StdSys = struct let cpuTime = vfun0 (fun () -> vfloat (Sys.time())) let environment = vfun0 (fun () -> - let env = Unix.environment() in - let h = StringHashtbl.create 0 in + let env = catch_unix_error Unix.environment() in + let h = StringHashtbl.create () in Array.iter(fun s -> let k, v = ExtString.String.split s "=" in - StringHashtbl.replace h (Rope.of_string k,lazy k) (encode_string v) + StringHashtbl.add h (create_ascii k) (create_unknown v) ) env; encode_string_map_direct h ) @@ -2164,14 +2552,20 @@ module StdSys = struct ) let getCwd = vfun0 (fun () -> - let dir = Unix.getcwd() in + let dir = catch_unix_error Unix.getcwd() in let l = String.length dir in - encode_string (if l = 0 then "./" else match dir.[l - 1] with '/' | '\\' -> dir | _ -> dir ^ "/") + if l = 0 then + encode_string "./" + else match dir.[l - 1] with + | '/' | '\\' -> + create_unknown dir + | _ -> + create_unknown (dir ^ "/") ) let getEnv = vfun1 (fun s -> let s = decode_string s in - try encode_string (Unix.getenv s) with _ -> vnull + try create_unknown (catch_unix_error Unix.getenv s) with _ -> vnull ) let print = vfun1 (fun v -> @@ -2184,7 +2578,7 @@ module StdSys = struct let println = vfun1 (fun v -> let ctx = get_ctx() in let com = ctx.curapi.get_com() in - com.print (value_string v ^ "\n"); + com.print (value_string v ^ lineEnd); vnull ) @@ -2192,28 +2586,34 @@ module StdSys = struct let ctx = get_ctx() in let com = ctx.curapi.get_com() in match com.main_class with - | None -> assert false + | None -> vnull | Some p -> match ctx.curapi.get_type (s_type_path p) with - | Some(Type.TInst (c, _)) -> encode_string (Extc.get_full_path c.Type.cl_pos.Globals.pfile) - | _ -> assert false + | Some(Type.TInst (c, _)) -> create_unknown (Extc.get_full_path c.Type.cl_pos.Globals.pfile) + | _ -> vnull ) let putEnv = vfun2 (fun s v -> let s = decode_string s in let v = decode_string v in - Unix.putenv s v; + catch_unix_error Unix.putenv s v; vnull ) let setCwd = vfun1 (fun s -> - Unix.chdir (decode_string s); + catch_unix_error Unix.chdir (decode_string s); vnull ) let setTimeLocale = vfun1 (fun _ -> vfalse) - let sleep = vfun1 (fun f -> ignore(Unix.select [] [] [] (decode_float f)); vnull) + let sleep = vfun1 (fun f -> + let time = Sys.time() in + Thread.yield(); + let diff = Sys.time() -. time in + Thread.delay ((num f) -. diff); + vnull + ) let stderr = vfun0 (fun () -> encode_instance key_sys_io_FileOutput ~kind:(IOutChannel stderr) @@ -2235,7 +2635,7 @@ module StdSys = struct (match !cached_sys_name with | Some n -> n | None -> - let ic = Unix.open_process_in "uname" in + let ic = catch_unix_error Unix.open_process_in "uname" in let uname = (match input_line ic with | "Darwin" -> "Mac" | n -> n @@ -2249,7 +2649,82 @@ module StdSys = struct encode_string s ) - let time = vfun0 (fun () -> vfloat (Unix.gettimeofday())) + let time = vfun0 (fun () -> vfloat (catch_unix_error Unix.gettimeofday())) +end + +module StdThread = struct + let this vthis = match vthis with + | VInstance {ikind = IThread thread} -> thread + | _ -> unexpected_value vthis "Thread" + + let delay = vfun1 (fun f -> + Thread.delay (num f); + vnull + ) + + let exit = vfun0 (fun () -> + Thread.exit(); + vnull + ) + + let id = vifun0 (fun vthis -> + vint (Thread.id (this vthis).tthread) + ) + + let join = vfun1 (fun thread -> + Thread.join (this thread).tthread; + vnull + ) + + let kill = vifun0 (fun vthis -> + Thread.kill (this vthis).tthread; + vnull + ) + + let self = vfun0 (fun () -> + let eval = get_eval (get_ctx()) in + encode_instance key_eval_vm_Thread ~kind:(IThread eval.thread) + ) + + let readMessage = vfun1 (fun blocking -> + let eval = get_eval (get_ctx()) in + let blocking = decode_bool blocking in + Option.get (Deque.pop eval.thread.tdeque blocking) + ) + + let sendMessage = vifun1 (fun vthis msg -> + let this = this vthis in + Deque.push this.tdeque msg; + vnull + ) + + let yield = vfun0 (fun () -> + Thread.yield(); + vnull + ) +end + +module StdTls = struct + let this vthis = match vthis with + | VInstance {ikind = ITls i} -> i + | _ -> unexpected_value vthis "Thread" + + let get_value = vifun0 (fun vthis -> + let this = this vthis in + try + let id = Thread.id (Thread.self()) in + let eval = IntMap.find id (get_ctx()).evals in + IntMap.find this eval.thread.tstorage + with Not_found -> + vnull + ) + + let set_value = vifun1 (fun vthis v -> + let this = this vthis in + let eval = get_eval (get_ctx()) in + eval.thread.tstorage <- IntMap.add this v eval.thread.tstorage; + v + ) end module StdType = struct @@ -2267,9 +2742,9 @@ module StdType = struct match v with | VPrototype ({pkind = PEnum names} as proto) -> begin try - let l = ExtList.List.filter_map (fun s -> + let l = ExtList.List.filter_map (fun (s,_) -> try - begin match proto_field_direct proto (hash_s s) with + begin match proto_field_direct proto (hash s) with | VEnumValue _ as v -> Some v | _ -> None end @@ -2296,7 +2771,7 @@ module StdType = struct ) let createEnum = vfun3 (fun e constr params -> - let constr = hash (decode_rope constr) in + let constr = hash (decode_vstring constr).sstring in create_enum e constr params ) @@ -2305,7 +2780,7 @@ module StdType = struct match e with | VPrototype {pkind = PEnum names} -> begin try - create_enum e (hash_s (List.nth names index)) params + create_enum e (hash (fst (List.nth names index))) params with Not_found -> vnull end @@ -2334,7 +2809,7 @@ module StdType = struct | VEnumValue ve -> begin try begin match (get_static_prototype_raise (get_ctx()) ve.epath).pkind with - | PEnum names -> encode_string (List.nth names ve.eindex) + | PEnum names -> encode_string (fst (List.nth names ve.eindex)) | _ -> raise Not_found end with Not_found -> @@ -2344,7 +2819,11 @@ module StdType = struct ) let enumEq = vfun2 (fun a b -> - vbool (equals_structurally a b) + let rec weird_eq a b = match a,b with + | VEnumValue a,VEnumValue b -> a == b || a.eindex = b.eindex && arrays_equal weird_eq a.eargs b.eargs && a.epath = b.epath + | _ -> equals a b + in + vbool (weird_eq a b) ) let enumIndex = vfun1 (fun v -> match v with @@ -2371,14 +2850,14 @@ module StdType = struct let getClassFields = vfun1 (fun v -> match v with | VPrototype {pkind = PClass _;pnames = names} -> - encode_array (IntMap.fold (fun name _ acc -> (encode_rope (rev_hash name)) :: acc) names []); + encode_array (IntMap.fold (fun name _ acc -> (encode_string (rev_hash name)) :: acc) names []); | _ -> vnull ) let getClassName = vfun1 (fun v -> match v with - | VPrototype {pkind = PClass _; ppath = path} -> encode_rope (rev_hash path) + | VPrototype {pkind = PClass _; ppath = path} -> encode_string (rev_hash path) | _ -> vnull ) @@ -2392,7 +2871,7 @@ module StdType = struct match v with | VPrototype {pkind = PEnum names} -> begin try - encode_array (List.map encode_string names) + encode_array (List.map (fun (n,_) -> encode_string n) names) with Not_found -> vnull end @@ -2402,7 +2881,7 @@ module StdType = struct let getEnumName = vfun1 (fun v -> match v with - | VPrototype {pkind = PEnum _; ppath = path} -> encode_rope (rev_hash path) + | VPrototype {pkind = PEnum _; ppath = path} -> encode_string (rev_hash path) | _ -> vnull ) @@ -2419,7 +2898,7 @@ module StdType = struct IntMap.fold (fun name _ acc -> IntMap.add name 0 acc) proto.pnames acc in let proto = get_instance_prototype (get_ctx()) proto.ppath null_pos in - encode_array (List.map (fun i -> encode_rope (rev_hash i)) (ptmap_keys (loop IntMap.empty proto))) + encode_array (List.map (fun i -> encode_string (rev_hash i)) (ptmap_keys (loop IntMap.empty proto))) with Not_found -> vnull end @@ -2434,12 +2913,12 @@ module StdType = struct ) let resolveClass = vfun1 (fun v -> - let name = decode_rope v in + let name = (decode_vstring v).sstring in try (get_static_prototype_raise (get_ctx()) (hash name)).pvalue with Not_found -> vnull ) let resolveEnum = vfun1 (fun v -> - let name = decode_rope v in + let name = (decode_vstring v).sstring in try let proto = get_static_prototype_raise (get_ctx()) (hash name) in begin match proto.pkind with @@ -2452,7 +2931,7 @@ module StdType = struct let typeof = vfun1 (fun v -> let ctx = (get_ctx()) in - let i,vl = match v with + let rec loop v = match v with | VNull -> 0,[||] | VInt32 _ -> 1,[||] | VFloat _ -> 2,[||] @@ -2468,7 +2947,10 @@ module StdType = struct 5,[||] | VEnumValue ve -> 7,[|get_static_prototype_as_value ctx ve.epath null_pos|] + | VLazy f -> + loop (!f()) in + let i,vl = loop v in encode_enum_value key_ValueType i vl None ) end @@ -2517,17 +2999,12 @@ module StdUtf8 = struct vnull ) - let charCodeAt = vfun2 (fun s index -> - let s = decode_string s in - let i = decode_int index in - let c = try UTF8.get s i with exc -> exc_string (Printexc.to_string exc) in - vint (UChar.int_of_uchar c) - ) + let charCodeAt = StdString.charCodeAt let compare = vfun2 (fun a b -> let a = decode_string a in let b = decode_string b in - vint (UTF8.compare a b) + vint (Pervasives.compare a b) ) let decode = vfun1 (fun s -> @@ -2538,12 +3015,13 @@ module StdUtf8 = struct Bytes.unsafe_set buf !i (UChar.char_of uc); incr i ) s; - encode_string (Bytes.unsafe_to_string buf) + let s = Bytes.unsafe_to_string buf in + create_unknown s ) let encode = vfun1 (fun s -> let s = decode_string s in - encode_string (UTF8.init (String.length s) (fun i -> UChar.of_char s.[i])) + create_unknown (UTF8.init (String.length s) (fun i -> UChar.of_char s.[i])) ) let iter = vfun2 (fun s f -> @@ -2553,25 +3031,15 @@ module StdUtf8 = struct ) let length = vfun1 (fun s -> - let s = decode_string s in - vint (UTF8.length s) + let s = decode_vstring s in + vint (s.slength) ) - let sub = vfun3 (fun s pos len -> - let s = decode_string s in - let pos = decode_int pos in - let len = decode_int len in - let buf = UTF8.Buf.create 0 in - let i = ref (-1) in - UTF8.iter (fun c -> - incr i; - if !i >= pos && !i < pos + len then UTF8.Buf.add_char buf c; - ) s; - encode_string (UTF8.Buf.contents buf) - ) + let sub = StdString.substr let toString = vifun0 (fun vthis -> - encode_string (UTF8.Buf.contents (this vthis)) + let this = this vthis in + vstring (create_ascii ((UTF8.Buf.contents this))) ) let validate = vfun1 (fun s -> @@ -2585,27 +3053,45 @@ module StdUtf8 = struct end let init_fields builtins path static_fields instance_fields = - let map (name,v) = (hash_s name,v) in + let map (name,v) = (hash name,v) in let path = path_hash path in builtins.static_builtins <- IntMap.add path (List.map map static_fields) builtins.static_builtins; builtins.instance_builtins <- IntMap.add path (List.map map instance_fields) builtins.instance_builtins let init_maps builtins = - let this vthis = match vthis with - | VInstance {ikind = IIntMap h} -> h - | v -> unexpected_value v "int map" - in - init_fields builtins (["haxe";"ds"],"IntMap") [] (StdIntMap.map_fields vint decode_int (fun i -> Rope.of_string (string_of_int i)) encode_int_map_direct this); - let this vthis = match vthis with - | VInstance {ikind = IStringMap h} -> h - | v -> unexpected_value v "string map" - in - init_fields builtins (["haxe";"ds"],"StringMap") [] (StdStringMap.map_fields vstring_direct decode_rope_string (fun (r,_) -> r) encode_string_map_direct this); - let this vthis = match vthis with - | VInstance {ikind = IObjectMap h} -> Obj.magic h - | v -> unexpected_value v "object map" - in - init_fields builtins (["haxe";"ds"],"ObjectMap") [] (StdObjectMap.map_fields (fun v -> v) (fun v -> v) (fun s -> s_value 0 s) encode_object_map_direct this) + init_fields builtins (["haxe";"ds"],"IntMap") [] [ + "copy",StdIntMap.copy; + "exists",StdIntMap.exists; + "get",StdIntMap.get; + "iterator",StdIntMap.iterator; + "keys",StdIntMap.keys; + "keyValueIterator",StdIntMap.keyValueIterator; + "remove",StdIntMap.remove; + "set",StdIntMap.set; + "toString",StdIntMap.toString; + ]; + init_fields builtins (["haxe";"ds"],"ObjectMap") [] [ + "copy",StdObjectMap.copy; + "exists",StdObjectMap.exists; + "get",StdObjectMap.get; + "iterator",StdObjectMap.iterator; + "keys",StdObjectMap.keys; + "keyValueIterator",StdObjectMap.keyValueIterator; + "remove",StdObjectMap.remove; + "set",StdObjectMap.set; + "toString",StdObjectMap.toString; + ]; + init_fields builtins (["haxe";"ds"],"StringMap") [] [ + "copy",StdStringMap.copy; + "exists",StdStringMap.exists; + "get",StdStringMap.get; + "iterator",StdStringMap.iterator; + "keys",StdStringMap.keys; + "keyValueIterator",StdStringMap.keyValueIterator; + "remove",StdStringMap.remove; + "set",StdStringMap.set; + "toString",StdStringMap.toString; + ] let init_constructors builtins = let add = Hashtbl.add builtins.constructor_builtins in @@ -2621,9 +3107,10 @@ let init_constructors builtins = (fun vl -> begin match List.map decode_int vl with | [y;m;d;h;mi;s] -> - let open Unix in - let t = localtime 0. in - let f = mktime {t with tm_sec=s;tm_min=mi;tm_hour=h;tm_mday=d;tm_mon=m;tm_year=y - 1900} in + let f = catch_unix_error (fun () -> + let t = Unix.localtime 0. in + Unix.mktime {t with tm_sec=s;tm_min=mi;tm_hour=h;tm_mday=d;tm_mon=m;tm_year=y - 1900} + ) () in encode_instance key_Date ~kind:(IDate (fst f)) | _ -> assert false end @@ -2638,15 +3125,15 @@ let init_constructors builtins = | [s] -> s | _ -> assert false ); - add key_StringBuf (fun _ -> encode_instance key_StringBuf ~kind:(IBuffer (Rope.Buffer.create 0))); + add key_StringBuf (fun _ -> encode_instance key_StringBuf ~kind:(IBuffer (VStringBuffer.create()))); add key_haxe_Utf8 (fun vl -> match vl with | [size] -> encode_instance key_haxe_Utf8 ~kind:(IUtf8 (UTF8.Buf.create (default_int size 0))) | _ -> assert false ); - add key_haxe_ds_StringMap (fun _ -> encode_instance key_haxe_ds_StringMap ~kind:(IStringMap (StringHashtbl.create 0))); - add key_haxe_ds_IntMap (fun _ -> encode_instance key_haxe_ds_IntMap ~kind:(IIntMap (IntHashtbl.create 0))); - add key_haxe_ds_ObjectMap (fun _ -> encode_instance key_haxe_ds_ObjectMap ~kind:(IObjectMap (Obj.magic (ValueHashtbl.create 0)))); + add key_haxe_ds_StringMap (fun _ -> encode_string_map_direct (StringHashtbl.create ())); + add key_haxe_ds_IntMap (fun _ -> encode_int_map_direct (IntHashtbl.create ())); + add key_haxe_ds_ObjectMap (fun _ -> encode_object_map_direct (Obj.magic (ValueHashtbl.create 0))); add key_haxe_io_BytesBuffer (fun _ -> encode_instance key_haxe_io_BytesBuffer ~kind:(IOutput (Buffer.create 0))); add key_haxe_io_Bytes (fun vl -> match vl with @@ -2666,7 +3153,7 @@ let init_constructors builtins = let cmd = decode_string cmd in let args = match args with | VNull -> None - | VArray va -> Some (Array.map decode_string va.avalues) + | VArray va -> Some (Array.map decode_string (Array.sub va.avalues 0 va.alength)) | _ -> unexpected_value args "array" in encode_instance key_sys_io__Process_NativeProcess ~kind:(IProcess (try Process.run cmd args with Failure msg -> exc_string msg)) @@ -2674,7 +3161,7 @@ let init_constructors builtins = ); add key_sys_net__Socket_NativeSocket (fun _ -> - encode_instance key_sys_net__Socket_NativeSocket ~kind:(ISocket ((Unix.socket Unix.PF_INET Unix.SOCK_STREAM) 0)) + encode_instance key_sys_net__Socket_NativeSocket ~kind:(ISocket ((catch_unix_error Unix.socket Unix.PF_INET Unix.SOCK_STREAM) 0)) ); add key_haxe_zip_Compress (fun vl -> match vl with @@ -2691,6 +3178,40 @@ let init_constructors builtins = let z = Extc.zlib_inflate_init2 windowBits in encode_instance key_haxe_zip_Uncompress ~kind:(IZip { z = z; z_flush = Extc.Z_NO_FLUSH }) | _ -> assert false + ); + add key_eval_vm_Thread + (fun vl -> match vl with + | [f] -> + let ctx = get_ctx() in + if ctx.is_macro then exc_string "Creating threads in macros is not supported"; + let thread = EvalThread.spawn ctx (fun () -> call_value f []) in + encode_instance key_eval_vm_Thread ~kind:(IThread thread) + | _ -> assert false + ); + add key_sys_net_Mutex + (fun _ -> + let mutex = { + mmutex = Mutex.create(); + mowner = None; + } in + encode_instance key_sys_net_Mutex ~kind:(IMutex mutex) + ); + add key_sys_net_Lock + (fun _ -> + let lock = { + ldeque = Deque.create(); + } in + encode_instance key_sys_net_Lock ~kind:(ILock lock) + ); + let tls_counter = ref (-1) in + add key_sys_net_Tls + (fun _ -> + incr tls_counter; + encode_instance key_sys_net_Tls ~kind:(ITls !tls_counter) + ); + add key_sys_net_Deque + (fun _ -> + encode_instance key_sys_net_Deque ~kind:(IDeque (Deque.create())) ) let init_empty_constructors builtins = @@ -2698,11 +3219,10 @@ let init_empty_constructors builtins = Hashtbl.add h key_Array (fun () -> encode_array_instance (EvalArray.create [||])); Hashtbl.add h key_eval_Vector (fun () -> encode_vector_instance (Array.make 0 vnull)); Hashtbl.add h key_Date (fun () -> encode_instance key_Date ~kind:(IDate 0.)); - Hashtbl.add h key_EReg (fun () -> encode_instance key_EReg ~kind:(IRegex {r = Pcre.regexp ""; r_global = false; r_string = ""; r_groups = [||]})); - Hashtbl.add h key_String (fun () -> encode_rope Rope.empty); - Hashtbl.add h key_haxe_Utf8 (fun () -> encode_instance key_haxe_Utf8 ~kind:(IUtf8 (UTF8.Buf.create 0))); - Hashtbl.add h key_haxe_ds_StringMap (fun () -> encode_instance key_haxe_ds_StringMap ~kind:(IStringMap (StringHashtbl.create 0))); - Hashtbl.add h key_haxe_ds_IntMap (fun () -> encode_instance key_haxe_ds_IntMap ~kind:(IIntMap (IntHashtbl.create 0))); + Hashtbl.add h key_EReg (fun () -> encode_instance key_EReg ~kind:(IRegex {r = Pcre.regexp ""; r_rex_string = create_ascii "~//"; r_global = false; r_string = ""; r_groups = [||]})); + Hashtbl.add h key_String (fun () -> encode_string ""); + Hashtbl.add h key_haxe_ds_StringMap (fun () -> encode_instance key_haxe_ds_StringMap ~kind:(IStringMap (StringHashtbl.create ()))); + Hashtbl.add h key_haxe_ds_IntMap (fun () -> encode_instance key_haxe_ds_IntMap ~kind:(IIntMap (IntHashtbl.create ()))); Hashtbl.add h key_haxe_ds_ObjectMap (fun () -> encode_instance key_haxe_ds_ObjectMap ~kind:(IObjectMap (Obj.magic (ValueHashtbl.create 0)))); Hashtbl.add h key_haxe_io_BytesBuffer (fun () -> encode_instance key_haxe_io_BytesBuffer ~kind:(IOutput (Buffer.create 0))) @@ -2723,6 +3243,7 @@ let init_standard_library builtins = "pop",StdArray.pop; "push",StdArray.push; "remove",StdArray.remove; + "resize",StdArray.resize; "reverse",StdArray.reverse; "shift",StdArray.shift; "slice",StdArray.slice; @@ -2745,6 +3266,7 @@ let init_standard_library builtins = "fastGet",StdBytes.fastGet; "ofData",StdBytes.ofData; "ofString",StdBytes.ofString; + "ofHex",StdBytes.ofHex; ] [ "blit",StdBytes.blit; "compare",StdBytes.compare; @@ -2811,9 +3333,22 @@ let init_standard_library builtins = "getMinutes",StdDate.getMinutes; "getMonth",StdDate.getMonth; "getSeconds",StdDate.getSeconds; + "getUTCDate",StdDate.getUTCDate; + "getUTCDay",StdDate.getUTCDay; + "getUTCFullYear",StdDate.getUTCFullYear; + "getUTCHours",StdDate.getUTCHours; + "getUTCMinutes",StdDate.getUTCMinutes; + "getUTCMonth",StdDate.getUTCMonth; + "getUTCSeconds",StdDate.getUTCSeconds; "getTime",StdDate.getTime; + "getTimezoneOffset",StdDate.getTimezoneOffset; "toString",StdDate.toString; ]; + init_fields builtins (["sys";"thread"],"Deque") [] [ + "add",StdDeque.add; + "push",StdDeque.push; + "pop",StdDeque.pop; + ]; init_fields builtins ([],"EReg") [ "escape",StdEReg.escape; ] [ @@ -2834,6 +3369,7 @@ let init_standard_library builtins = "read",StdFile.read; "saveBytes",StdFile.saveBytes; "saveContent",StdFile.saveContent; + "update",StdFile.update; "write",StdFile.write; ] []; init_fields builtins (["sys";"io"],"FileInput") [] [ @@ -2859,7 +3395,6 @@ let init_standard_library builtins = "i64ToDouble",StdFPHelper.i64ToDouble; ] []; init_fields builtins (["sys"],"FileSystem") [ - "absolutePath",StdFileSystem.absolutePath; "createDirectory",StdFileSystem.createDirectory; "deleteFile",StdFileSystem.deleteFile; "deleteDirectory",StdFileSystem.deleteDirectory; @@ -2892,6 +3427,10 @@ let init_standard_library builtins = "hostToString",StdHost.hostToString; "resolve",StdHost.resolve; ] []; + init_fields builtins (["sys";"thread"],"Lock") [] [ + "release",StdLock.release; + "wait",StdLock.wait; + ]; init_fields builtins (["haxe"],"Log") [ "trace",StdLog.trace; ] []; @@ -2928,6 +3467,11 @@ let init_standard_library builtins = "encode",StdMd5.encode; "make",StdMd5.make; ] []; + init_fields builtins (["sys";"thread"],"Mutex") [] [ + "acquire",StdMutex.acquire; + "tryAcquire",StdMutex.tryAcquire; + "release",StdMutex.release; + ]; init_fields builtins (["sys";"io";"_Process"],"NativeProcess") [ ] [ "close",StdNativeProcess.close; "exitCode",StdNativeProcess.exitCode; @@ -2960,6 +3504,10 @@ let init_standard_library builtins = "getString",StdResource.getString; "getBytes",StdResource.getBytes; ] []; + init_fields builtins (["haxe";"crypto"],"Sha1") [ + "encode",StdSha1.encode; + "make",StdSha1.make; + ] []; init_fields builtins (["sys";"net";"_Socket"],"NativeSocket") [ "select",StdSocket.select; ] [ @@ -2975,10 +3523,12 @@ let init_standard_library builtins = "send",StdSocket.send; "sendChar",StdSocket.sendChar; "setFastSend",StdSocket.setFastSend; + "setBroadcast", StdSocket.setBroadcast; "setTimeout",StdSocket.setTimeout; "shutdown",StdSocket.shutdown; ]; init_fields builtins ([],"Std") [ + "downcast",StdStd.downcast; "instance",StdStd.instance; "int",StdStd.int; "is",StdStd.is'; @@ -3011,6 +3561,7 @@ let init_standard_library builtins = ]; init_fields builtins ([],"StringTools") [ "fastCodeAt",StdStringTools.fastCodeAt; + "replace",StdStringTools.replace; "urlEncode",StdStringTools.urlEncode; "urlDecode",StdStringTools.urlDecode; ] []; @@ -3036,6 +3587,22 @@ let init_standard_library builtins = "systemName",StdSys.systemName; "time",StdSys.time; ] []; + init_fields builtins (["eval";"vm"],"NativeThread") [ + "delay",StdThread.delay; + "exit",StdThread.exit; + "join",StdThread.join; + "readMessage",StdThread.readMessage; + "self",StdThread.self; + "yield",StdThread.yield; + ] [ + "id",StdThread.id; + "kill",StdThread.kill; + "sendMessage",StdThread.sendMessage; + ]; + init_fields builtins (["sys";"thread"],"Tls") [] [ + "get_value",StdTls.get_value; + "set_value",StdTls.set_value; + ]; init_fields builtins ([],"Type") [ "allEnums",StdType.allEnums; "createEmptyInstance",StdType.createEmptyInstance; @@ -3077,4 +3644,4 @@ let init_standard_library builtins = ] [ "addChar",StdUtf8.addChar; "toString",StdUtf8.toString; - ] \ No newline at end of file + ] diff --git a/src/macro/eval/evalString.ml b/src/macro/eval/evalString.ml new file mode 100644 index 00000000000..d0aeb6278ac --- /dev/null +++ b/src/macro/eval/evalString.ml @@ -0,0 +1,282 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open EvalValue + +let vstring s = VString s + +let create_ascii s = + { + sstring = s; + slength = String.length s; + soffsets = []; + } + +let create_with_length s length = { + sstring = s; + slength = length; + soffsets = []; +} + +let create_unknown s = + vstring (create_with_length s (try UTF8.length s with _ -> String.length s)) + +let concat s1 s2 = + create_with_length (s1.sstring ^ s2.sstring) (s1.slength + s2.slength) + +let join sep sl = + let l_sep = sep.slength in + let buf = Buffer.create 0 in + let _,length = List.fold_left (fun (first,length) s -> + let length = if first then 0 else length + l_sep in + let length = length + s.slength in + if not first then Buffer.add_string buf sep.sstring; + Buffer.add_string buf s.sstring; + (false,length) + ) (true,0) sl in + create_with_length (Buffer.contents buf) length + +let get_offset' s c_index = + let rec get_b_offset c_len b_offset = + if c_len = 0 then b_offset else + get_b_offset (c_len - 1) (UTF8.next s.sstring b_offset) + in + let rec rget_b_offset c_len b_offset = + if c_len = 0 then b_offset else + rget_b_offset (c_len + 1) (UTF8.prev s.sstring b_offset) + in + match s.soffsets with + | [] -> + let b_offset = get_b_offset c_index 0 in + let r = (ref c_index,ref b_offset) in + s.soffsets <- r :: s.soffsets; + b_offset,r + | [(cr_index1,br_offset1) as r1] -> + let c_index1 = !cr_index1 in + let b_offset1 = !br_offset1 in + let diff = c_index - c_index1 in + let b_offset = match diff with + | 0 -> b_offset1 + | 1 -> UTF8.next s.sstring b_offset1 + | -1 -> UTF8.prev s.sstring b_offset1 + | _ -> + if diff > 0 then + get_b_offset diff b_offset1 + else if c_index + diff < 0 then + (* big step backwards, better to start over *) + get_b_offset c_index 0 + else + rget_b_offset diff b_offset1 + in + (* If our jump is larger than the scientifically determined value 20, upgrade + to two offset pointers. *) + let r = if diff > 20 || diff < -20 then begin + let r2 = (ref c_index,ref b_offset) in + s.soffsets <- r2 :: s.soffsets; + r2 + end else + r1 + in + b_offset,r + | [(cr_index1,br_offset1) as r1;(cr_index2,br_offset2) as r2] -> + let (c_index1,b_offset1) = !cr_index1,!br_offset1 in + let (c_index2,b_offset2) = !cr_index2,!br_offset2 in + let diff1 = c_index - c_index1 in + let diff2 = c_index - c_index2 in + let r,b_offset = match diff1,diff2 with + | 0,_ -> r1,b_offset1 + | _,0 -> r2,b_offset2 + | 1,_ -> r1,UTF8.next s.sstring b_offset1 + | _,1 -> r2,UTF8.next s.sstring b_offset2 + | -1,_ -> r1,UTF8.prev s.sstring b_offset1 + | _,-1 -> r2,UTF8.prev s.sstring b_offset2 + | _ -> + let r,diff,b_offset' = if abs diff1 > abs diff2 then + r2,diff2,b_offset2 + else + r1,diff1,b_offset1 + in + let b_offset = if diff > 0 then + get_b_offset diff b_offset' + else if c_index + diff < 0 then + (* big step backwards, better to start over *) + get_b_offset c_index 0 + else + rget_b_offset diff b_offset' + in + r,b_offset + in + b_offset,r + | _ -> + assert false + +let get_offset s c_index = + let b_offset,(cr_index,br_offset) = get_offset' s c_index in + cr_index := c_index; + br_offset := b_offset; + b_offset + +let char_at s c_index = + let b_offset,(cr_index,br_offset) = get_offset' s c_index in + let i = b_offset in + let s = s.sstring in + let n = Char.code s.[i] in + let char,diff = + if n < 0x80 then n,1 + else if n <= 0xdf then + (n - 0xc0) lsl 6 lor (0x7f land (Char.code s.[i + 1])),2 + else if n <= 0xef then + let n' = n - 0xe0 in + let m0 = Char.code s.[i + 2] in + let m = Char.code (String.unsafe_get s (i + 1)) in + let n' = n' lsl 6 lor (0x7f land m) in + n' lsl 6 lor (0x7f land m0),3 + else if n <= 0xf7 then + let n' = n - 0xf0 in + let m0 = Char.code s.[i + 3] in + let m = Char.code (String.unsafe_get s (i + 1)) in + let n' = n' lsl 6 lor (0x7f land m) in + let m = Char.code (String.unsafe_get s (i + 2)) in + let n' = n' lsl 6 lor (0x7f land m) in + n' lsl 6 lor (0x7f land m0),4 + else if n <= 0xfb then + let n' = n - 0xf8 in + let m0 = Char.code s.[i + 4] in + let m = Char.code (String.unsafe_get s (i + 1)) in + let n' = n' lsl 6 lor (0x7f land m) in + let m = Char.code (String.unsafe_get s (i + 2)) in + let n' = n' lsl 6 lor (0x7f land m) in + let m = Char.code (String.unsafe_get s (i + 3)) in + let n' = n' lsl 6 lor (0x7f land m) in + n' lsl 6 lor (0x7f land m0),5 + else if n <= 0xfd then + let n' = n - 0xfc in + let m0 = Char.code s.[i + 5] in + let m = Char.code (String.unsafe_get s (i + 1)) in + let n' = n' lsl 6 lor (0x7f land m) in + let m = Char.code (String.unsafe_get s (i + 2)) in + let n' = n' lsl 6 lor (0x7f land m) in + let m = Char.code (String.unsafe_get s (i + 3)) in + let n' = n' lsl 6 lor (0x7f land m) in + let m = Char.code (String.unsafe_get s (i + 4)) in + let n' = n' lsl 6 lor (0x7f land m) in + n' lsl 6 lor (0x7f land m0),6 + else invalid_arg "UTF8.look" + in + cr_index := c_index + 1; + br_offset := b_offset + diff; + char + +let string_of_char_code i = + UTF8.init 1 (fun _ -> UChar.uchar_of_int i) + +let from_char_code i = + create_with_length (string_of_char_code i) 1 + +type scan_result = + | ScanHit + | ScanAscii + | ScanOther + +let find_substring this sub reverse = + let cl_this = this.slength in + let cl_sub = sub.slength in + let bl_this = String.length this.sstring in + let bl_sub = String.length sub.sstring in + let s_this = this.sstring in + let s_sub = sub.sstring in + let rec scan b_index b_len = + let c = String.unsafe_get s_this (b_index + b_len) in + if c = String.unsafe_get s_sub b_len then begin + if b_len + 1 = bl_sub then ScanHit + else scan b_index (b_len + 1) + end else if c <= '\127' then + ScanAscii + else + ScanOther + in + if not reverse then begin + let rec loop c_index b_index = + if c_index > cl_this - cl_sub || b_index >= bl_this then raise Not_found; + match scan b_index 0 with + | ScanHit -> + c_index,b_index,b_index + bl_sub + | ScanAscii -> + loop (c_index + 1) (b_index + 1) + | ScanOther -> + loop (c_index + 1) (UTF8.next s_this b_index) + in + loop + end else begin + let rec loop c_index b_index = + if c_index > cl_this - cl_sub || b_index < 0 then raise Not_found; + match scan b_index 0 with + | ScanHit -> + c_index,b_index,b_index + bl_sub + | _ -> + loop (c_index - 1) (UTF8.prev s_this b_index) + in + loop + end + +let case_map this upper = + let buf = UTF8.Buf.create 0 in + let a,m = if upper then EvalBytes.Unicase._UPPER,1022 else EvalBytes.Unicase._LOWER,1021 in + UTF8.iter (fun uc -> + let c = UChar.int_of_uchar uc in + let up = c lsr 6 in + let uc = if up < m then begin + let c = a.(up).(c land ((1 lsl 6) - 1)) in + if c <> 0 then UChar.uchar_of_int c + else uc + end else + uc + in + UTF8.Buf.add_char buf uc + ) this.sstring; + create_with_length (UTF8.Buf.contents buf) this.slength + +let substr this c_index c_length = + if c_length < 0 then + create_with_length "" 0 + else begin + let b_offset1 = get_offset this c_index in + let b_offset2 = UTF8.move this.sstring b_offset1 c_length in + create_with_length (String.sub this.sstring b_offset1 (b_offset2 - b_offset1)) c_length + end + +module VStringBuffer = struct + type t = vstring_buffer + + let create () = { + bbuffer = Buffer.create 0; + blength = 0; + } + + let add_string this s = + Buffer.add_string this.bbuffer s.sstring; + this.blength <- this.blength + s.slength + + let add_substring this s b_pos b_len c_len = + Buffer.add_substring this.bbuffer s.sstring b_pos b_len; + this.blength <- this.blength + c_len + + let contents this = + create_with_length (Buffer.contents this.bbuffer) this.blength +end \ No newline at end of file diff --git a/src/macro/eval/evalThread.ml b/src/macro/eval/evalThread.ml new file mode 100644 index 00000000000..0d948c12a80 --- /dev/null +++ b/src/macro/eval/evalThread.ml @@ -0,0 +1,92 @@ +open Globals +open EvalContext +open EvalDebugMisc +open EvalExceptions +open EvalValue + +module Deque = struct + let create () = { + dvalues = []; + dmutex = Mutex.create(); + } + + let add this i = + Mutex.lock this.dmutex; + this.dvalues <- this.dvalues @ [i]; + Mutex.unlock this.dmutex + + let pop this blocking = + let rec loop () = + Mutex.lock this.dmutex; + match this.dvalues with + | v :: vl -> + this.dvalues <- vl; + Mutex.unlock this.dmutex; + Some v + | [] -> + if not blocking then begin + Mutex.unlock this.dmutex; + None + end else begin + Mutex.unlock this.dmutex; + Thread.yield(); + loop() + end + in + loop() + + let push this i = + Mutex.lock this.dmutex; + this.dvalues <- i :: this.dvalues; + Mutex.unlock this.dmutex +end + +let create_eval thread = { + env = None; + thread = thread; + debug_channel = Event.new_channel (); + debug_state = DbgRunning; + breakpoint = make_breakpoint 0 0 BPDisabled BPAny None; + caught_types = Hashtbl.create 0; + last_return = None; + caught_exception = vnull; +} + +let spawn ctx f = + let f thread = + let id = Thread.id (Thread.self()) in + let maybe_send_thread_event reason = match ctx.debug.debug_socket with + | Some socket -> + socket.connection.send_thread_event id reason + | None -> + () + in + let new_eval = create_eval thread in + ctx.evals <- IntMap.add id new_eval ctx.evals; + let close () = + ctx.evals <- IntMap.remove id ctx.evals; + maybe_send_thread_event "exited"; + in + try + maybe_send_thread_event "started"; + ignore(f ()); + close(); + with + | RunTimeException(v,stack,p) -> + let msg = get_exc_error_message ctx v stack p in + prerr_endline msg; + close(); + | Sys_exit i -> + close(); + exit i; + | exc -> + close(); + raise exc + in + let thread = { + tthread = Obj.magic (); + tstorage = IntMap.empty; + tdeque = Deque.create(); + } in + thread.tthread <- Thread.create f thread; + thread \ No newline at end of file diff --git a/src/macro/eval/evalValue.ml b/src/macro/eval/evalValue.ml index 13f1d31ff0e..ef845e9a71a 100644 --- a/src/macro/eval/evalValue.ml +++ b/src/macro/eval/evalValue.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -26,18 +26,55 @@ type cmp = | CInf | CUndef -type vstring = Rope.t * string Lazy.t +type vstring = { + (* The bytes representation of the string. This is only evaluated if we + need it for something like random access. *) + sstring : UTF8.t; + (* The length of the string. *) + slength : int; + (* The current (character * byte) offsets. *) + mutable soffsets : (int ref * int ref) list; +} -module StringHashtbl = Hashtbl.Make(struct - type t = vstring - let equal (r1,s1) (r2,s2) = r1 == r2 || Lazy.force s1 = Lazy.force s2 - let hash (_,s) = Hashtbl.hash (Lazy.force s) -end) +type vstring_buffer = { + bbuffer : Buffer.t; + mutable blength : int; +} + +let vstring_equal s1 s2 = + s1 == s2 || s1.sstring = s2.sstring -module IntHashtbl = Hashtbl.Make(struct type t = int let equal = (=) let hash = Hashtbl.hash end) +module StringHashtbl = struct + type 'value t = (vstring * 'value) StringMap.t ref + + let add this key v = this := StringMap.add key.sstring (key,v) !this + let copy this = ref !this + let create () = ref StringMap.empty + let find this key = StringMap.find key.sstring !this + let fold f this acc = StringMap.fold f !this acc + let is_empty this = StringMap.is_empty !this + let iter f this = StringMap.iter f !this + let mem this key = StringMap.mem key.sstring !this + let remove this key = this := StringMap.remove key.sstring !this +end + +module IntHashtbl = struct + type 'value t = 'value IntMap.t ref + + let add this key v = this := IntMap.add key v !this + let copy this = ref !this + let create () = ref IntMap.empty + let find this key = IntMap.find key !this + let fold f this acc = IntMap.fold f !this acc + let is_empty this = IntMap.is_empty !this + let iter f this = IntMap.iter f !this + let mem this key = IntMap.mem key !this + let remove this key = this := IntMap.remove key !this +end type vregex = { r : Pcre.regexp; + r_rex_string : vstring; r_global : bool; mutable r_string : string; mutable r_groups : Pcre.substrings array; @@ -50,7 +87,7 @@ type vzlib = { type vprototype_kind = | PClass of int list - | PEnum of string list + | PEnum of (string * int list) list | PInstance | PObject @@ -69,29 +106,19 @@ type value = | VPrototype of vprototype | VFunction of vfunc * bool | VFieldClosure of value * vfunc + | VLazy of (unit -> value) ref -and vfunc = - | Fun0 of (unit -> value) - | Fun1 of (value -> value) - | Fun2 of (value -> value -> value) - | Fun3 of (value -> value -> value -> value) - | Fun4 of (value -> value -> value -> value -> value) - | Fun5 of (value -> value -> value -> value -> value -> value) - | FunN of (value list -> value) +and vfunc = value list -> value and vobject = { (* The fields of the object known when it is created. *) - ofields : value array; + mutable ofields : value array; (* The prototype of the object. *) - oproto : vprototype; - (* Extra fields that were added after the object was created. *) - mutable oextra : value IntMap.t; - (* Map of fields (in ofields) that were deleted via Reflect.deleteField *) - mutable oremoved : bool IntMap.t; + mutable oproto : vprototype; } and vprototype = { - (* The path of the prototype. Using rev_hash_s on this gives the original dot path. *) + (* The path of the prototype. Using rev_hash on this gives the original dot path. *) ppath : int; (* The fields of the prototype itself (static fields). *) pfields : value array; @@ -120,14 +147,18 @@ and vinstance_kind = | IIntMap of value IntHashtbl.t | IObjectMap of (value,value) Hashtbl.t | IOutput of Buffer.t (* BytesBuffer *) - | IBuffer of Rope.Buffer.t (* StringBuf *) + | IBuffer of vstring_buffer(* StringBuf *) | IPos of pos | IUtf8 of UTF8.Buf.buf | IProcess of Process.process | IInChannel of in_channel * bool ref (* FileInput *) | IOutChannel of out_channel (* FileOutput *) | ISocket of Unix.file_descr - | IThread of Thread.t + | IThread of vthread + | IMutex of vmutex + | ILock of vlock + | ITls of int + | IDeque of vdeque | IZip of vzlib (* Compress/Uncompress *) | ITypeDecl of Type.module_type | ILazyType of (Type.tlazy ref) * (unit -> value) @@ -160,7 +191,27 @@ and venum_value = { enpos : pos option; } -let equals a b = match a,b with +and vthread = { + mutable tthread : Thread.t; + tdeque : vdeque; + mutable tstorage : value IntMap.t; +} + +and vdeque = { + mutable dvalues : value list; + dmutex : Mutex.t; +} + +and vmutex = { + mmutex : Mutex.t; + mutable mowner : int option; (* thread ID *) +} + +and vlock = { + ldeque : vdeque; +} + +let rec equals a b = match a,b with | VTrue,VTrue | VFalse,VFalse | VNull,VNull -> true @@ -171,11 +222,13 @@ let equals a b = match a,b with | VEnumValue a,VEnumValue b -> a == b || a.eindex = b.eindex && Array.length a.eargs = 0 && Array.length b.eargs = 0 && a.epath = b.epath | VObject vo1,VObject vo2 -> vo1 == vo2 | VInstance vi1,VInstance vi2 -> vi1 == vi2 - | VString(r1,s1),VString(r2,s2) -> r1 == r2 || Lazy.force s1 = Lazy.force s2 + | VString s1,VString s2 -> vstring_equal s1 s2 | VArray va1,VArray va2 -> va1 == va2 | VVector vv1,VVector vv2 -> vv1 == vv2 | VFunction(vf1,_),VFunction(vf2,_) -> vf1 == vf2 | VPrototype proto1,VPrototype proto2 -> proto1.ppath = proto2.ppath + | VLazy f1,_ -> equals (!f1()) b + | _,VLazy f2 -> equals a (!f2()) | _ -> a == b module ValueHashtbl = Hashtbl.Make(struct @@ -203,11 +256,6 @@ let venum_value e = VEnumValue e let s_expr_pretty e = (Type.s_expr_pretty false "" false (Type.s_type (Type.print_context())) e) -let num_args = function - | Fun0 _ -> 0 - | Fun1 _ -> 1 - | Fun2 _ -> 2 - | Fun3 _ -> 3 - | Fun4 _ -> 4 - | Fun5 _ -> 5 - | FunN _ -> -1 \ No newline at end of file +let rec vresolve v = match v with + | VLazy f -> vresolve (!f()) + | _ -> v \ No newline at end of file diff --git a/src/macro/hlmacro.ml b/src/macro/hlmacro.ml deleted file mode 100644 index 6af29cf0d61..00000000000 --- a/src/macro/hlmacro.ml +++ /dev/null @@ -1,557 +0,0 @@ -(* - The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - *) -open Globals -open Type -open Ast -open Hlcode -open Hlinterp -open MacroApi - -type value = Hlinterp.value - -type context = { - com : Common.context; (* macro one *) - mutable gen : Genhl.context option; - interp : Hlinterp.context; - types : (Type.path,int) Hashtbl.t; - cached_protos : (obj_type, (virtual_proto * vfield array)) Hashtbl.t; - cached_enums : (enum_type, ttype) Hashtbl.t; - mutable curapi : value MacroApi.compiler_api; - mutable has_error : bool; -} - -exception Error of string * Globals.pos list - -let debug = true (* TODO !!! set to false for speed++ ! *) - -let get_ctx_ref = ref (fun() -> assert false) -let get_ctx() : context = (!get_ctx_ref)() -let macro_lib = Hashtbl.create 0 -let interp() = (get_ctx()).interp - -let setup get_api = - let api = get_api (fun() -> (get_ctx()).curapi.get_com()) (fun() -> (get_ctx()).curapi) in - List.iter (fun (n,v) -> Hashtbl.replace macro_lib n (match v with VClosure (FNativeFun (_,v,_),None) -> v | _ -> assert false)) api; - Globals.macro_platform := Globals.Hl - -let select ctx = - get_ctx_ref := (fun() -> ctx) - -let error_handler ctx v stack = - let make_pos st = - let file, line = Hlinterp.make_stack ctx.interp st in - let low = line land 0xFFFFF in - { - Globals.pfile = file; - Globals.pmin = low; - Globals.pmax = low + (line lsr 20); - } - in - (*let rec loop o = - if o == ctx.error_proto then true else match o.oproto with None -> false | Some p -> loop p - in - (match v with - | VObject o when loop o -> - (match get_field o (hash "message"), get_field o (hash "pos") with - | VObject msg, VAbstract (APos pos) -> - (match get_field msg h_s with - | VString msg -> raise (Error.Error (Error.Custom msg,pos)) - | _ -> ()); - | _ -> ()); - | _ -> ());*) - raise (Error (Hlinterp.vstr ctx.interp v Hlcode.HDyn,List.map make_pos stack)) - -let create com api _ = - let ctx = { - com = com; - gen = None; - interp = Hlinterp.create debug; - curapi = api; - types = Hashtbl.create 0; - has_error = false; - cached_protos = Hashtbl.create 0; - cached_enums = Hashtbl.create 0; - } in - select ctx; - Hlinterp.set_error_handler ctx.interp (error_handler ctx); - Hlinterp.set_macro_api ctx.interp (fun name -> try Some (Hashtbl.find macro_lib name) with Not_found -> None); - ctx - -let init ctx = - if ctx.gen = None then ctx.gen <- Some (Genhl.create_context ctx.com true false) - -let set_error ctx e = - ctx.has_error <- e - -let add_types ctx types ready = - let types = List.filter (fun t -> match t with - | TAbstractDecl a when not (Meta.has Meta.CoreType a.a_meta) -> - (* A @:native on an abstract causes the implementation class and the abstract - to have the same path. Let's skip all abstracts so this doesn't matter. *) - false - | _ -> - let path = Type.t_path t in - if Hashtbl.mem ctx.types path then false else begin - Hashtbl.add ctx.types path (Type.t_infos t).mt_module.m_id; - true; - end - ) types in - List.iter ready types; - if ctx.gen = None then init ctx; - match ctx.gen with - | None -> assert false - | Some gen -> - Genhl.add_types gen types; - if debug then Genhl.check gen; - let code = Genhl.build_code gen types None in - if debug then begin - try - Hlinterp.check code true - with Failure _ | Common.Abort _ as exn -> - let ch = open_out_bin "hlcode.txt" in - Hlcode.dump (fun s -> output_string ch (s ^ "\n")) code; - close_out ch; - raise exn - end; - Hlinterp.add_code ctx.interp code - -let do_reuse ctx api = - ctx.curapi <- api - -let can_reuse ctx types = - let has_old_version t = - let inf = Type.t_infos t in - try - Hashtbl.find ctx.types inf.mt_path <> inf.mt_module.m_id - with Not_found -> - false - in - not (List.exists has_old_version types) - -let catch_errors ctx ?(final=(fun() -> ())) f = - let prev = get_ctx() in (* switch context in case we have an older one, see #5676 *) - select ctx; - try - let v = f() in - final(); - select prev; - Some v - with Error _ as e -> - final(); - select prev; - raise e - | Abort -> - final(); - select prev; - None - -let call_path ctx cpath (f:string) args api = - if ctx.has_error then - None - else let old = ctx.curapi in - ctx.curapi <- api; - let gid = Genhl.resolve_class_global (match ctx.gen with None -> assert false | Some ctx -> ctx) (String.concat "." cpath) in - let gval = ctx.interp.Hlinterp.t_globals.(gid) in - let fval = Hlinterp.dyn_get_field ctx.interp gval f Hlcode.HDyn in - match fval with - | Hlinterp.VClosure (f,None) -> - catch_errors ~final:(fun() -> ctx.curapi <- old) ctx (fun() -> call_wrap ctx.interp f args) - | _ -> - prerr_endline (Hlinterp.vstr_d ctx.interp gval); - assert false - -let vnull = VNull -let vbool b = VBool b -let vint i = VInt (Int32.of_int i) -let vint32 i = VInt i -let vfloat f = VFloat f - -let vfun0 f = - let callb args = match args with [] -> f() | _ -> assert false in - VClosure(FNativeFun ("fun0",callb,HVoid), None) - -let vfun1 f = - let callb args = match args with [a] -> f a | _ -> assert false in - VClosure(FNativeFun ("fun1",callb,HVoid), None) - -let vfun2 f = - let callb args = match args with [a;b] -> f a b | _ -> assert false in - VClosure(FNativeFun ("fun2",callb,HVoid), None) - -let vfun3 f = - let callb args = match args with [a;b;c] -> f a b c | _ -> assert false in - VClosure(FNativeFun ("fun3",callb,HVoid), None) - -let vfun4 f = - let callb args = match args with [a;b;c;d] -> f a b c d | _ -> assert false in - VClosure(FNativeFun ("fun4",callb,HVoid), None) - -let vfun5 f = - let callb args = match args with [a;b;c;d;e] -> f a b c d e | _ -> assert false in - VClosure(FNativeFun ("fun5",callb,HVoid), None) - -let exc_string msg = - Hlinterp.throw_msg (interp()) msg - -let compiler_error msg pos = - assert false (* TODO : raise haxe.macro.Error(msg,pos) *) - -let eval_expr ctx (e:texpr) = - assert false - -let eval_delayed _ _ = - assert false (* macro - in - macro *) - -let prepare_callback f n = - assert false - -let encode_pos p = VAbstract (APos p) - -let decode_pos = function - | VAbstract (APos p) -> p - | _ -> raise Invalid_expr - -let last_enum_type = ref IExpr - -let encode_enum t pos tag pl = - last_enum_type := t; - assert false (* todo : list enum prototypes *) - (* - match pos with - | None -> VEnum (tag,Array.of_list pl) - | Some p -> VEnum (tag,Array.of_list (List.rev (encode_pos p :: List.rev pl))) - *) - -let decode_enum = function - | VEnum (_,tag,arr) -> tag, Array.to_list arr - | _ -> raise Invalid_expr - -let decode_enum_with_pos = function - | VEnum (_,tag,arr) when Array.length arr > 0 && (match arr.(Array.length arr - 1) with VAbstract (APos _) -> true | _ -> false) -> - let rec loop i = - if i = Array.length arr - 1 then [] else arr.(i) :: loop (i + 1) - in - (tag, loop 0), decode_pos arr.(Array.length arr - 1) - | e -> - decode_enum e, Globals.null_pos - - -let encode_tdecl t = VAbstract (ATDecl t) -let encode_unsafe o = VAbstract (AUnsafe o) - -let decode_unsafe = function - | VAbstract (AUnsafe v) -> v - | _ -> raise Invalid_expr - -let decode_tdecl = function - | VAbstract (ATDecl t) -> t - | _ -> raise Invalid_expr - -let decode_int = function - | VInt i -> Int32.to_int i - | _ -> raise Invalid_expr - -let decode_i32 = function - | VInt i -> i - | _ -> raise Invalid_expr - -let decode_bool = function - | VBool b -> b - | _ -> raise Invalid_expr - -let field o n = - match o with - | VDynObj _ | VVirtual _ | VObj _ -> Hlinterp.dyn_get_field (interp()) o n HDyn - | _ -> raise Invalid_expr - -let decode_string = function - | VObj { ofields = [|VBytes s;VInt _|] } -> Hlinterp.hl_to_caml s - | _ -> raise Invalid_expr - -let decode_array = function - | VObj { ofields = [|VInt len;VArray (arr,_)|] } -> - let len = Int32.to_int len in - let rec loop i = - if i = len then [] else arr.(i) :: loop (i+1) - in - loop 0 - | v -> - raise Invalid_expr - -let encode_lazytype f t = VAbstract (ALazyType (f,t)) - -let decode_lazytype = function - | VAbstract (ALazyType (t,_)) -> t - | _ -> raise Invalid_expr - -let encode_obj t fields = - match t with - | OMetaAccess -> - let h = Hashtbl.create 0 in - let rec loop i = function - | [] -> () - | (n,_) :: l -> - Hashtbl.add h n i; - loop (i + 1) l - in - loop 0 fields; - let values = Array.of_list (List.map snd fields) in - VDynObj { - dfields = h; - dvalues = values; - dtypes = Array.make (Array.length values) HDyn; - dvirtuals = []; - } - | _ -> - let ctx = get_ctx() in - let to_str (name,f) = - match f with - | None -> name - | Some f -> name ^ "." ^ f - in - let vp, idx = try - Hashtbl.find ctx.cached_protos t - with Not_found -> - let name, field = proto_name t in - let gen = (match ctx.gen with None -> assert false | Some gen -> gen) in - let vt = (try - let t = Hashtbl.find gen.Genhl.macro_typedefs name in - (match t, field with - | _, None -> t - | HVirtual v, Some f -> - let idx = (try PMap.find f v.vindex with Not_found -> failwith (name ^ " has no field definition " ^ f)) in - let _,_, t = v.vfields.(idx) in - (match t with - | HVirtual _ -> t - | _ -> failwith ("Unexpected type " ^ tstr t ^ " for definition " ^ to_str (name,field))) - | _ -> - assert false - ) - with Not_found -> try - let t = PMap.find (["haxe";"macro"],name) gen.Genhl.cached_types in - (match t, field with - | HEnum e, Some f -> - let rec loop i = - if i = Array.length e.efields then raise Not_found; - let n, _, tl = e.efields.(i) in - if n = f then - tl.(0) - else - loop (i + 1) - in - loop 0 - | _ -> - failwith ("Unexpected type " ^ tstr t ^ " for definition " ^ to_str (name,field))) - with Not_found -> - failwith ("Macro definition missing " ^ to_str (name,field)) - ) in - match vt with - | HVirtual vp -> - let vindexes = Array.map (fun (n,_,_) -> - let rec loop i = function - | [] -> VFNone - | (n2,_) :: _ when n = n2 -> VFIndex i - | _ :: l -> loop (i + 1) l - in - loop 0 fields - ) vp.vfields in - Hashtbl.replace ctx.cached_protos t (vp, vindexes); - vp, vindexes - | _ -> - failwith (to_str (name,field) ^ " returned invalid type " ^ tstr vt) - in - if debug then begin - let farr = Array.of_list fields in - Array.iteri (fun i idx -> - let name, _ ,_ = vp.vfields.(i) in - match idx with - | VFNone -> - if List.mem_assoc name fields then failwith ("Field " ^ name ^ " is present in " ^ to_str (proto_name t)) - | VFIndex i when i >= Array.length farr -> - failwith ("Missing field " ^ name ^ " of " ^ to_str (proto_name t)) - | VFIndex i when fst farr.(i) <> name -> - failwith ("Field " ^ name ^ " of " ^ to_str (proto_name t) ^ " is wrongly mapped on " ^ fst farr.(i)) - | _ -> - () - ) idx; - List.iter (fun (n,_) -> - if n <> "name_pos" && not (PMap.mem n vp.vindex) then failwith ("Field " ^ n ^ " has data but is not part of type " ^ to_str (proto_name t)); - ) fields; - end; - VVirtual { - vtype = vp; - vindexes = idx; - vtable = Array.map snd (Array.of_list fields); - vvalue = VNull; - } - -let encode_inst path fields = - let ctx = get_ctx() in - let t = (match ctx.gen with None -> assert false | Some gen -> try Genhl.resolve_type gen path with Not_found -> assert false) in - match t with - | HObj o -> - let proto, _, _ = Hlinterp.get_proto ctx.interp o in - VObj { oproto = proto; ofields = fields } - | _ -> - assert false - -let encode_string s = - encode_inst ([],"String") [|VBytes (caml_to_hl s);VInt (Int32.of_int (String.length s))|] - -let encode_array vl = - let arr = Array.of_list (List.map (fun v -> - match v with - | VNull | VObj _ | VVirtual _ -> v - | VEnum _ -> - let ctx = get_ctx() in - let et = !last_enum_type in - let t = try - Hashtbl.find ctx.cached_enums et - with Not_found -> - let name = enum_name et in - let t = (match ctx.gen with - | None -> assert false - | Some gen -> try PMap.find (["haxe";"macro"],name) gen.Genhl.cached_types with Not_found -> failwith ("Missing enum type " ^ name) - ) in - Hashtbl.replace ctx.cached_enums et t; - t - in - VDyn (v,t) - | _ -> failwith "Invalid array value" - ) vl) in - encode_inst (["hl";"types"],"ArrayObj") [|VInt (Int32.of_int (Array.length arr));VArray (arr,HDyn)|] - -let encode_bytes s = - encode_inst (["haxe";"io"],"Bytes") [|VInt (Int32.of_int (String.length s)); VBytes s|] - -let encode_string_map convert pmap = - let h = Hashtbl.create 0 in - PMap.iter (fun k v -> Hashtbl.add h k (convert v)) pmap; - encode_inst (["haxe";"ds"],"StringMap") [|VAbstract (AHashBytes h)|] - -let decode_bytes = function - | VObj { ofields = [|VInt _;VBytes s|] } -> s - | _ -> raise Invalid_expr - -let encode_ref v convert tostr = - let h = Hashtbl.create 0 in - Hashtbl.add h "get" 0; - Hashtbl.add h "__string" 1; - Hashtbl.add h "toString" 2; - Hashtbl.add h "$" 3; - VDynObj { - dfields = h; - dvalues = [| - vfun0 (fun() -> convert v); - vfun0 (fun() -> VBytes (caml_to_hl (tostr()))); - vfun0 (fun() -> encode_string (tostr())); - VAbstract (AUnsafe (Obj.repr v)) - |]; - dtypes = [| - HFun ([],HDyn); - HFun ([],HBytes); - HFun ([],HDyn); - HDyn; - |]; - dvirtuals = []; - } - -let decode_ref v : 'a = - match field v "$" with - | VAbstract (AUnsafe t) -> Obj.obj t - | _ -> raise Invalid_expr - -let value_string v = - Hlinterp.vstr (get_ctx()).interp v HDyn - -let value_signature v = - failwith "signature() not supported in HL macros" - -let value_to_expr v p = - let ctx = get_ctx() in - let error v = failwith ("Unsupported value " ^ vstr ctx.interp v Hlcode.HDyn) in - (* - let h_enum = hash "__enum__" and h_et = hash "__et__" and h_ct = hash "__ct__" in - let h_tag = hash "tag" and h_args = hash "args" in - let h_length = hash "length" in - let make_path t = - let rec loop = function - | [] -> assert false - | [name] -> (Ast.EConst (Ast.Ident name),p) - | name :: l -> (Ast.EField (loop l,name),p) - in - let t = t_infos t in - loop (List.rev (if t.mt_module.m_path = t.mt_path then fst t.mt_path @ [snd t.mt_path] else fst t.mt_module.m_path @ [snd t.mt_module.m_path;snd t.mt_path])) - in*) - let rec loop = function - | VNull -> (Ast.EConst (Ast.Ident "null"),p) - | VBool b -> (Ast.EConst (Ast.Ident (if b then "true" else "false")),p) - | VInt i -> (Ast.EConst (Ast.Int (Int32.to_string i)),p) - | VFloat f -> - let std = (Ast.EConst (Ast.Ident "std"), p) in - let math = (Ast.EField (std, "Math"), p) in - if (f = infinity) then - (Ast.EField (math, "POSITIVE_INFINITY"), p) - else if (f = neg_infinity) then - (Ast.EField (math, "NEGATIVE_INFINITY"), p) - else if (f <> f) then - (Ast.EField (math, "NaN"), p) - else - (Ast.EConst (Ast.Float (Common.float_repres f)), p) - | VAbstract (APos p) -> - (Ast.EObjectDecl ( - (("fileName",Globals.null_pos,NoQuotes) , (Ast.EConst (Ast.String p.Globals.pfile) , p)) :: - (("lineNumber",Globals.null_pos,NoQuotes) , (Ast.EConst (Ast.Int (string_of_int (Lexer.get_error_line p))),p)) :: - (("className",Globals.null_pos,NoQuotes) , (Ast.EConst (Ast.String ("")),p)) :: - [] - ), p) - | VObj { oproto = { pclass = { pname = "String" } }; ofields = [|VBytes content;VInt _|] } -> - (Ast.EConst (Ast.String (hl_to_caml content)),p) - | v -> - error v - (* - | VObject o as v -> - match o.oproto with - | None -> - (match get_field_opt o h_ct with - | Some (VAbstract (ATDecl t)) -> - make_path t - | _ -> - let fields = List.fold_left (fun acc (fid,v) -> ((field_name ctx fid,Globals.null_pos), loop v) :: acc) [] (Array.to_list o.ofields) in - (Ast.EObjectDecl fields, p)) - | Some proto -> - match get_field_opt proto h_enum, get_field_opt o h_a, get_field_opt o h_s, get_field_opt o h_length with - | _, Some (VArray a), _, Some (VInt len) -> - (Ast.EArrayDecl (List.map loop (Array.to_list (Array.sub a 0 len))),p) - | Some (VObject en), _, _, _ -> - (match get_field en h_et, get_field o h_tag with - | VAbstract (ATDecl t), VString tag -> - let e = (Ast.EField (make_path t,tag),p) in - (match get_field_opt o h_args with - | Some (VArray args) -> - let args = List.map loop (Array.to_list args) in - (Ast.ECall (e,args),p) - | _ -> e) - | _ -> - error v) - | _ -> - error v - *) - in - loop v diff --git a/src/macro/macroApi.ml b/src/macro/macroApi.ml index 87fec9cad19..d920b4a2853 100644 --- a/src/macro/macroApi.ml +++ b/src/macro/macroApi.ml @@ -15,7 +15,7 @@ type 'value compiler_api = { get_type : string -> Type.t option; get_module : string -> Type.t list; after_typing : (module_type list -> unit) -> unit; - on_generate : (Type.t list -> unit) -> unit; + on_generate : (Type.t list -> unit) -> bool -> unit; after_generate : (unit -> unit) -> unit; on_type_not_found : (string -> 'value) -> unit; parse_string : string -> Globals.pos -> bool -> Ast.expr; @@ -25,7 +25,7 @@ type 'value compiler_api = { store_typed_expr : Type.texpr -> Ast.expr; allow_package : string -> unit; type_patch : string -> string -> bool -> string option -> unit; - meta_patch : string -> string -> string option -> bool -> unit; + meta_patch : string -> string -> string option -> bool -> pos -> unit; set_js_generator : (Genjs.ctx -> unit) -> unit; get_local_type : unit -> t option; get_expected_type : unit -> t option; @@ -35,24 +35,22 @@ type 'value compiler_api = { get_local_using : unit -> tclass list; get_local_vars : unit -> (string, Type.tvar) PMap.t; get_build_fields : unit -> 'value; - get_pattern_locals : Ast.expr -> Type.t -> (string,Type.tvar * Globals.pos) PMap.t; define_type : 'value -> string option -> unit; define_module : string -> 'value list -> ((string * Globals.pos) list * Ast.import_mode) list -> Ast.type_path list -> unit; - module_dependency : string -> string -> bool -> unit; + module_dependency : string -> string -> unit; current_module : unit -> module_def; - on_reuse : (unit -> bool) -> unit; mutable current_macro_module : unit -> module_def; - delayed_macro : int -> (unit -> (unit -> 'value)); use_cache : unit -> bool; format_string : string -> Globals.pos -> Ast.expr; cast_or_unify : Type.t -> texpr -> Globals.pos -> bool; - add_global_metadata : string -> string -> (bool * bool * bool) -> unit; + add_global_metadata : string -> string -> (bool * bool * bool) -> pos -> unit; add_module_check_policy : string list -> int list -> bool -> int -> unit; decode_expr : 'value -> Ast.expr; encode_expr : Ast.expr -> 'value; encode_ctype : Ast.type_hint -> 'value; decode_type : 'value -> t; flush_context : (unit -> t) -> t; + typer_ctx : Typecore.typer; } @@ -77,55 +75,8 @@ type enum_type = | IAnonStatus | IQuoteStatus | IImportMode - -type obj_type = - (* make_const *) - | O__Const - (* Expr *) - | OImportExpr - | OImportExpr_path - | OTypePath - | OMetadataEntry - | OField - | OTypeParamDecl - | OFunction - | OFunctionArg - | OExprDef_fields - | OVar - | OCase - | OCatch - | OExpr - (* Type *) - | OMetaAccess - | OTypeParameter - | OClassType - | OAbstractType - | OAnonType - | ODefType - | OEnumType - | OClassField - | OAbstractType_binops - | OAbstractType_unops - | OAbstractType_from - | OAbstractType_to - | OEnumField - | OClassType_superClass - | OClassType_interfaces - | OType_args - | OTVar - | OTVar_extra - | OTFunc - | OTFunc_args - | OFieldAccess_c - | OTypedExprDef - | OTypedExprDef_fields - | OTypedExprDef_cases - | OTypedExprDef_catches - | OJSGenApi - | OContext_getPosInfos - | OCompiler_getDisplayPos - | ORef -(* ---- ^^^^^ please exactly match the name of the typedef or use TypeName_field if it's a anonymous *) + | IDisplayKind + | IMessage (** Our access to the interpreter from the macro api @@ -142,7 +93,8 @@ module type InterpApi = sig val encode_array : value list -> value val encode_string : string -> value - val encode_obj : obj_type -> (string * value) list -> value + val encode_obj : (string * value) list -> value + val encode_lazy : (unit -> value) -> value val vfun0 : (unit -> value) -> value val vfun1 : (value -> value) -> value @@ -192,6 +144,9 @@ module type InterpApi = sig val flush_core_context : (unit -> t) -> t + val handle_decoding_error : (string -> unit) -> value -> Type.t -> (string * int) list + + val get_api_call_pos : unit -> pos end let enum_name = function @@ -215,51 +170,8 @@ let enum_name = function | IAnonStatus -> "AnonStatus" | IImportMode -> "ImportMode" | IQuoteStatus -> "QuoteStatus" - -let proto_name = function - | O__Const -> assert false - | OImportExpr -> "ImportExpr", None - | OImportExpr_path -> "ImportExpr", Some "path" - | OTypePath -> "TypePath", None - | OMetadataEntry -> "MetadataEntry", None - | OField -> "Field", None - | OTypeParamDecl -> "TypeParamDecl", None - | OFunction -> "Function", None - | OFunctionArg -> "FunctionArg", None - | OExprDef_fields -> "ExprDef", Some "fields" - | OVar -> "Var", None - | OCase -> "Case", None - | OCatch -> "Catch", None - | OExpr -> "Expr", None - | OMetaAccess -> "MetaAccess", None - | OTypeParameter -> "TypeParameter", None - | OClassType -> "ClassType", None - | OAbstractType -> "AbstracType", None - | OAnonType -> "AnonType", None - | ODefType -> "DefType", None - | OEnumType -> "EnumType", None - | OClassField -> "ClassField", None - | OAbstractType_binops -> "AbstractType", Some "binops" - | OAbstractType_unops -> "AbstractType", Some "unops" - | OAbstractType_from -> "AbstractType", Some "from" - | OAbstractType_to -> "AbstractType", Some "to" - | OEnumField -> "EnumField", None - | OClassType_superClass -> "ClassType", Some "superClass" - | OClassType_interfaces -> "ClassType", Some "interfaces" - | OType_args -> "Type", Some "args" - | OTVar -> "TVar", None - | OTVar_extra -> "TVar", Some "extra" - | OTFunc -> "TFunc", None - | OTFunc_args -> "TFunc", Some "args" - | OFieldAccess_c -> "FieldAccess", Some "c" - | OTypedExprDef -> "TypedExprDef", None - | OTypedExprDef_fields -> "TypedExprDef", Some "fields" - | OTypedExprDef_cases -> "TypedExprDef", Some "cases" - | OTypedExprDef_catches -> "TypedExprDef", Some "catches" - | OJSGenApi -> "JSGenApi", None - | OContext_getPosInfos -> "Context", Some "getPosInfos" - | OCompiler_getDisplayPos -> "Compiler", Some "getDisplayPos" - | ORef -> "Ref", None + | IDisplayKind -> "DisplayKind" + | IMessage -> "Message" let all_enums = let last = IImportMode in @@ -283,7 +195,7 @@ let haxe_float f p = else if (f <> f) then (Ast.EField (math, "NaN"), p) else - (Ast.EConst (Ast.Float (float_repres f)), p) + (Ast.EConst (Ast.Float (Numeric.float_repres f)), p) (* ------------------------------------------------------------------------------------------------------------- *) (* Our macro api functor *) @@ -354,25 +266,26 @@ let encode_unop op = let encode_import (path,mode) = let tag,pl = match mode with | INormal -> 0, [] - | IAsName s -> 1, [encode_string s] + | IAsName(s,_) -> 1, [encode_string s] | IAll -> 2,[] in let mode = encode_enum IImportMode tag pl in - encode_obj OImportExpr [ - "path", encode_array (List.map (fun (name,p) -> encode_obj OImportExpr_path [ "pos", encode_pos p; "name", encode_string name]) path); + encode_obj [ + "path", encode_array (List.map (fun (name,p) -> encode_obj [ "pos", encode_pos p; "name", encode_string name]) path); "mode", mode ] let encode_placed_name (s,p) = encode_string s -let rec encode_path (t,_) = +let rec encode_path (t,p) = let fields = [ "pack", encode_array (List.map encode_string t.tpackage); "name", encode_string t.tname; "params", encode_array (List.map encode_tparam t.tparams); + "pos", encode_pos p; ] in - encode_obj OTypePath (match t.tsub with + encode_obj (match t.tsub with | None -> fields | Some s -> ("sub", encode_string s) :: fields) @@ -381,7 +294,7 @@ and encode_tparam = function | TPExpr e -> encode_enum ITParam 1 [encode_expr e] and encode_access a = - let tag = match a with + let tag = match fst a with | APublic -> 0 | APrivate -> 1 | AStatic -> 2 @@ -390,11 +303,12 @@ and encode_access a = | AInline -> 5 | AMacro -> 6 | AFinal -> 7 + | AExtern -> 8 in - encode_enum IAccess tag [] + encode_enum ~pos:(Some (pos a)) IAccess tag [] and encode_meta_entry (m,ml,p) = - encode_obj OMetadataEntry [ + encode_obj [ "name", encode_string (Meta.to_string m); "params", encode_array (List.map encode_expr ml); "pos", encode_pos p; @@ -409,7 +323,7 @@ and encode_field (f:class_field) = | FFun f -> 1, [encode_fun f] | FProp (get,set, t, e) -> 2, [encode_placed_name get; encode_placed_name set; null encode_ctype t; null encode_expr e] in - encode_obj OField [ + encode_obj [ "name",encode_placed_name f.cff_name; "name_pos", encode_pos (pos f.cff_name); "doc", null encode_string f.cff_doc; @@ -433,23 +347,29 @@ and encode_ctype t = 4, [encode_array (List.map encode_path tl); encode_array (List.map encode_field fields)] | CTOptional t -> 5, [encode_ctype t] + | CTNamed (n,t) -> + 6, [encode_placed_name n; encode_ctype t] + | CTIntersection tl -> + 7, [(encode_array (List.map encode_ctype tl))] in encode_enum ~pos:(Some (pos t)) ICType tag pl and encode_tparam_decl tp = - encode_obj OTypeParamDecl [ + encode_obj [ "name", encode_placed_name tp.tp_name; "name_pos", encode_pos (pos tp.tp_name); "params", encode_array (List.map encode_tparam_decl tp.tp_params); - "constraints", encode_array (List.map encode_ctype tp.tp_constraints); + "constraints", (match tp.tp_constraints with + | None -> encode_array [] + | Some th -> encode_array [encode_ctype th]); "meta", encode_meta_content tp.tp_meta; ] and encode_fun f = - encode_obj OFunction [ + encode_obj [ "params", encode_array (List.map encode_tparam_decl f.f_params); "args", encode_array (List.map (fun (n,opt,m,t,e) -> - encode_obj OFunctionArg [ + encode_obj [ "name", encode_placed_name n; "name_pos", encode_pos (pos n); "opt", vbool opt; @@ -462,6 +382,24 @@ and encode_fun f = "expr", null encode_expr f.f_expr ] +and encode_display_kind dk = + let tag, pl = match dk with + | DKCall -> 0, [] + | DKDot -> 1, [] + | DKStructure -> 2, [] + | DKMarked -> 3, [] + | DKPattern outermost -> 4, [vbool outermost] + in + encode_enum ~pos:None IDisplayKind tag pl + +and encode_message msg = + let tag, pl = match msg with + | CMInfo(msg,p) -> 0, [(encode_string msg); (encode_pos p)] + | CMWarning(msg,p) -> 1, [(encode_string msg); (encode_pos p)] + | CMError(_,_) -> assert false + in + encode_enum ~pos:None IMessage tag pl + and encode_expr e = let rec loop (e,p) = let tag, pl = match e with @@ -476,7 +414,7 @@ and encode_expr e = | EParenthesis e -> 4, [loop e] | EObjectDecl fl -> - 5, [encode_array (List.map (fun ((f,p,qs),e) -> encode_obj OExprDef_fields [ + 5, [encode_array (List.map (fun ((f,p,qs),e) -> encode_obj [ "field",encode_string f; "name_pos",encode_pos p; "quotes",encode_enum IQuoteStatus (match qs with NoQuotes -> 0 | DoubleQuotes -> 1) []; @@ -491,16 +429,17 @@ and encode_expr e = | EUnop (op,flag,e) -> 9, [encode_unop op; vbool (match flag with Prefix -> false | Postfix -> true); loop e] | EVars vl -> - 10, [encode_array (List.map (fun (v,t,eo) -> - encode_obj OVar [ + 10, [encode_array (List.map (fun (v,final,t,eo) -> + encode_obj [ "name",encode_placed_name v; "name_pos",encode_pos (pos v); + "isFinal",vbool final; "type",null encode_ctype t; "expr",null loop eo; ] ) vl)] | EFunction (name,f) -> - 11, [null encode_string name; encode_fun f] + 11, [null encode_placed_name name; encode_fun f] | EBlock el -> 12, [encode_array (List.map loop el)] | EFor (e,eloop) -> @@ -511,7 +450,7 @@ and encode_expr e = 15, [loop econd;loop e;vbool (match flag with NormalWhile -> true | DoWhile -> false)] | ESwitch (e,cases,eopt) -> 16, [loop e;encode_array (List.map (fun (ecl,eg,e,p) -> - encode_obj OCase [ + encode_obj [ "values",encode_array (List.map loop ecl); "guard",null loop eg; "expr",null loop e; @@ -520,7 +459,7 @@ and encode_expr e = ) cases);null (fun (e,_) -> encode_null_expr e) eopt] | ETry (e,catches) -> 17, [loop e;encode_array (List.map (fun (v,t,e,p) -> - encode_obj OCatch [ + encode_obj [ "name",encode_placed_name v; "name_pos",encode_pos (pos v); "type",encode_ctype t; @@ -540,8 +479,8 @@ and encode_expr e = 22, [loop e] | ECast (e,t) -> 23, [loop e; null encode_ctype t] - | EDisplay (e,flag) -> - 24, [loop e; vbool flag] + | EDisplay (e,dk) -> + 24, [loop e; encode_display_kind dk] | EDisplayNew t -> 25, [encode_path t] | ETernary (econd,e1,e2) -> @@ -551,17 +490,17 @@ and encode_expr e = | EMeta (m,e) -> 28, [encode_meta_entry m;loop e] in - encode_obj OExpr [ + encode_obj [ "pos", encode_pos p; "expr", encode_enum IExpr tag pl; ] in - loop e + encode_lazy (fun () -> loop e) and encode_null_expr e = match e with | None -> - encode_obj OExpr ["pos", vnull;"expr",vnull] + encode_obj ["pos", vnull;"expr",vnull] | Some e -> encode_expr e @@ -627,7 +566,7 @@ let decode_unop op = let decode_import_mode t = match decode_enum t with | 0, [] -> INormal - | 1, [alias] -> IAsName (decode_string alias) + | 1, [alias] -> IAsName (decode_string alias,Globals.null_pos) (* TODO: is it okay to lose the pos here? *) | 2, [] -> IAll | _ -> raise Invalid_expr @@ -635,6 +574,8 @@ let decode_import t = (List.map (fun o -> ((decode_string (field o "name")), (de let maybe_decode_pos p = try decode_pos p with Invalid_expr -> Globals.null_pos +let decode_pos_default p pd = try decode_pos p with Invalid_expr -> pd + let decode_placed_name vp v = decode_string v,maybe_decode_pos vp @@ -642,12 +583,13 @@ let decode_opt_array f v = if v = vnull then [] else List.map f (decode_array v) let rec decode_path t = + let p = field t "pos" in { tpackage = List.map decode_string (decode_array (field t "pack")); tname = decode_string (field t "name"); tparams = decode_opt_array decode_tparam (field t "params"); tsub = opt decode_string (field t "sub"); - },Globals.null_pos + },if p = vnull then Globals.null_pos else decode_pos p and decode_tparam v = match decode_enum v with @@ -659,9 +601,14 @@ and decode_tparams v = decode_opt_array decode_tparam_decl v and decode_tparam_decl v = + let vconstraints = field v "constraints" in { tp_name = decode_placed_name (field v "name_pos") (field v "name"); - tp_constraints = decode_opt_array decode_ctype (field v "constraints"); + tp_constraints = if vconstraints = vnull then None else (match decode_array vconstraints with + | [] -> None + | [t] -> Some (decode_ctype t) + | tl -> Some (CTIntersection (List.map decode_ctype tl),Globals.null_pos) + ); tp_params = decode_tparams (field v "params"); tp_meta = decode_meta_content (field v "meta"); } @@ -681,16 +628,20 @@ and decode_fun v = } and decode_access v = - match decode_enum v with - | 0, [] -> APublic - | 1, [] -> APrivate - | 2, [] -> AStatic - | 3, [] -> AOverride - | 4, [] -> ADynamic - | 5, [] -> AInline - | 6, [] -> AMacro - | 7, [] -> AFinal + let (i,_),p = decode_enum_with_pos v in + let a = match i with + | 0 -> APublic + | 1 -> APrivate + | 2 -> AStatic + | 3 -> AOverride + | 4 -> ADynamic + | 5 -> AInline + | 6 -> AMacro + | 7 -> AFinal + | 8 -> AExtern | _ -> raise Invalid_expr + in + a,p and decode_meta_entry v = Meta.from_string (decode_string (field v "name")), decode_opt_array decode_expr (field v "params"), decode_pos (field v "pos") @@ -708,10 +659,11 @@ and decode_field v = | _ -> raise Invalid_expr in + let pos = decode_pos (field v "pos") in { - cff_name = decode_placed_name (field v "name_pos") (field v "name"); + cff_name = (decode_string (field v "name"),decode_pos_default (field v "name_pos") pos); cff_doc = opt decode_string (field v "doc"); - cff_pos = decode_pos (field v "pos"); + cff_pos = pos; cff_kind = fkind; cff_access = List.map decode_access (opt_list decode_array (field v "access")); cff_meta = opt_list decode_meta_content (field v "meta"); @@ -732,9 +684,21 @@ and decode_ctype t = CTExtend (List.map decode_path (decode_array tl), List.map decode_field (decode_array fl)) | 5, [t] -> CTOptional (decode_ctype t) + | 6, [n;t] -> + CTNamed ((decode_string n,p), decode_ctype t) + | 7, [tl] -> + CTIntersection (List.map decode_ctype (decode_array tl)) | _ -> raise Invalid_expr),p +and decode_display_kind v = match (decode_enum v) with + | 0, [] -> DKCall + | 1, [] -> DKDot + | 2, [] -> DKStructure + | 3, [] -> DKMarked + | 4, [outermost] -> DKPattern (decode_bool outermost) + | _ -> raise Invalid_expr + and decode_expr v = let rec loop v = let p = decode_pos (field v "pos") in @@ -773,10 +737,12 @@ and decode_expr v = EUnop (decode_unop op,(if decode_bool f then Postfix else Prefix),loop e) | 10, [vl] -> EVars (List.map (fun v -> - ((decode_placed_name (field v "name_pos") (field v "name")),opt decode_ctype (field v "type"),opt loop (field v "expr")) + let vfinal = field v "isFinal" in + let final = if vfinal == vnull then false else decode_bool vfinal in + ((decode_placed_name (field v "name_pos") (field v "name")),final,opt decode_ctype (field v "type"),opt loop (field v "expr")) ) (decode_array vl)) | 11, [fname;f] -> - EFunction (opt decode_string fname,decode_fun f) + EFunction (opt (fun v -> decode_string v,Globals.null_pos) fname,decode_fun f) | 12, [el] -> EBlock (List.map loop (decode_array el)) | 13, [e1;e2] -> @@ -807,8 +773,8 @@ and decode_expr v = EThrow (loop e) | 23, [e;t] -> ECast (loop e,opt decode_ctype t) - | 24, [e;f] -> - EDisplay (loop e,decode_bool f) + | 24, [e;dk] -> + EDisplay (loop e,decode_display_kind dk) | 25, [t] -> EDisplayNew (decode_path t) | 26, [e1;e2;e3] -> @@ -844,7 +810,7 @@ let vopt f v = match v with let encode_meta m set = let meta = ref m in - encode_obj OMetaAccess [ + encode_obj [ "get", vfun0 (fun() -> encode_meta_content (!meta) ); @@ -873,9 +839,9 @@ let encode_meta m set = ); ] -let rec encode_mtype ot t fields = +let rec encode_mtype t fields = let i = t_infos t in - encode_obj ot ([ + encode_obj ([ "__t", encode_tdecl t; "pack", encode_array (List.map encode_string (fst i.mt_path)); "name", encode_string (snd i.mt_path); @@ -888,10 +854,10 @@ let rec encode_mtype ot t fields = ] @ fields) and encode_type_params tl = - encode_array (List.map (fun (n,t) -> encode_obj OTypeParameter ["name",encode_string n;"t",encode_type t]) tl) + encode_array (List.map (fun (n,t) -> encode_obj ["name",encode_string n;"t",encode_type t]) tl) and encode_tenum e = - encode_mtype OEnumType (TEnumDecl e) [ + encode_mtype (TEnumDecl e) [ "isExtern", vbool e.e_extern; "exclude", vfun0 (fun() -> e.e_extern <- true; vnull); "constructs", encode_string_map encode_efield e.e_constrs; @@ -899,19 +865,20 @@ and encode_tenum e = ] and encode_tabstract a = - encode_mtype OAbstractType (TAbstractDecl a) [ + encode_mtype (TAbstractDecl a) [ "type", encode_type a.a_this; "impl", (match a.a_impl with None -> vnull | Some c -> encode_clref c); - "binops", encode_array (List.map (fun (op,cf) -> encode_obj OAbstractType_binops [ "op",encode_binop op; "field",encode_cfield cf]) a.a_ops); - "unops", encode_array (List.map (fun (op,postfix,cf) -> encode_obj OAbstractType_unops [ "op",encode_unop op; "isPostfix",vbool (match postfix with Postfix -> true | Prefix -> false); "field",encode_cfield cf]) a.a_unops); - "from", encode_array ((List.map (fun t -> encode_obj OAbstractType_from [ "t",encode_type t; "field",vnull]) a.a_from) @ (List.map (fun (t,cf) -> encode_obj OAbstractType_from [ "t",encode_type t; "field",encode_cfield cf]) a.a_from_field)); - "to", encode_array ((List.map (fun t -> encode_obj OAbstractType_to [ "t",encode_type t; "field",vnull]) a.a_to) @ (List.map (fun (t,cf) -> encode_obj OAbstractType_to [ "t",encode_type t; "field",encode_cfield cf]) a.a_to_field)); + "binops", encode_array (List.map (fun (op,cf) -> encode_obj [ "op",encode_binop op; "field",encode_cfield cf]) a.a_ops); + "unops", encode_array (List.map (fun (op,postfix,cf) -> encode_obj [ "op",encode_unop op; "isPostfix",vbool (match postfix with Postfix -> true | Prefix -> false); "field",encode_cfield cf]) a.a_unops); + "from", encode_array ((List.map (fun t -> encode_obj [ "t",encode_type t; "field",vnull]) a.a_from) @ (List.map (fun (t,cf) -> encode_obj [ "t",encode_type t; "field",encode_cfield cf]) a.a_from_field)); + "to", encode_array ((List.map (fun t -> encode_obj [ "t",encode_type t; "field",vnull]) a.a_to) @ (List.map (fun (t,cf) -> encode_obj [ "t",encode_type t; "field",encode_cfield cf]) a.a_to_field)); "array", encode_array (List.map encode_cfield a.a_array); - "resolve", (match a.a_resolve with None -> vnull | Some cf -> encode_cfref cf) + "resolve", (match a.a_read with None -> vnull | Some cf -> encode_cfref cf); + "resolveWrite", (match a.a_write with None -> vnull | Some cf -> encode_cfref cf) ] and encode_efield f = - encode_obj OEnumField [ + encode_obj [ "name", encode_string f.ef_name; "type", encode_type f.ef_type; "pos", encode_pos f.ef_pos; @@ -923,10 +890,10 @@ and encode_efield f = ] and encode_cfield f = - encode_obj OClassField [ + encode_obj [ "name", encode_string f.cf_name; "type", encode_lazy_type f.cf_type; - "isPublic", vbool f.cf_public; + "isPublic", vbool (has_class_field_flag f CfPublic); "params", encode_type_params f.cf_params; "meta", encode_meta f.cf_meta (fun m -> f.cf_meta <- m); "expr", vfun0 (fun() -> @@ -938,6 +905,8 @@ and encode_cfield f = "namePos",encode_pos f.cf_name_pos; "doc", null encode_string f.cf_doc; "overloads", encode_ref f.cf_overloads (encode_and_map_array encode_cfield) (fun() -> "overloads"); + "isExtern", vbool (has_class_field_flag f CfExtern); + "isFinal", vbool (has_class_field_flag f CfFinal); ] and encode_field_kind k = @@ -985,16 +954,17 @@ and encode_class_kind k = and encode_tclass c = ignore(c.cl_build()); - encode_mtype OClassType (TClassDecl c) [ + encode_mtype (TClassDecl c) [ "kind", encode_class_kind c.cl_kind; "isExtern", vbool c.cl_extern; "exclude", vfun0 (fun() -> c.cl_extern <- true; c.cl_init <- None; vnull); "isInterface", vbool c.cl_interface; + "isFinal", vbool c.cl_final; "superClass", (match c.cl_super with | None -> vnull - | Some (c,pl) -> encode_obj OClassType_superClass ["t",encode_clref c;"params",encode_tparams pl] + | Some (c,pl) -> encode_obj ["t",encode_clref c;"params",encode_tparams pl] ); - "interfaces", encode_array (List.map (fun (c,pl) -> encode_obj OClassType_interfaces ["t",encode_clref c;"params",encode_tparams pl]) c.cl_implements); + "interfaces", encode_array (List.map (fun (c,pl) -> encode_obj ["t",encode_clref c;"params",encode_tparams pl]) c.cl_implements); "fields", encode_ref c.cl_ordered_fields (encode_and_map_array encode_cfield) (fun() -> "class fields"); "statics", encode_ref c.cl_ordered_statics (encode_and_map_array encode_cfield) (fun() -> "class fields"); "constructor", (match c.cl_constructor with None -> vnull | Some cf -> encode_cfref cf); @@ -1003,14 +973,14 @@ and encode_tclass c = ] and encode_ttype t = - encode_mtype ODefType (TTypeDecl t) [ + encode_mtype (TTypeDecl t) [ "isExtern", vbool false; "exclude", vfun0 (fun() -> vnull); "type", encode_type t.t_type; ] and encode_tanon a = - encode_obj OAnonType [ + encode_obj [ "fields", encode_pmap_array encode_cfield a.a_fields; "status", encode_anon_status !(a.a_status); ] @@ -1057,7 +1027,7 @@ and encode_type t = 3 , [encode_ref t encode_ttype (fun() -> s_type_path t.t_path); encode_tparams pl] | TFun (pl,ret) -> let pl = List.map (fun (n,o,t) -> - encode_obj OType_args [ + encode_obj [ "name",encode_string n; "opt",vbool o; "t",encode_type t @@ -1139,12 +1109,12 @@ and encode_tconst c = and encode_tvar v = let f_extra (pl,e) = - encode_obj OTVar_extra [ + encode_obj [ "params",encode_type_params pl; "expr",vopt encode_texpr e ] in - encode_obj OTVar [ + encode_obj [ "id", vint v.v_id; "name", encode_string v.v_name; "t", encode_type v.v_type; @@ -1164,11 +1134,11 @@ and encode_module_type mt = encode_enum IModuleType tag pl and encode_tfunc func = - encode_obj OTFunc [ + encode_obj [ "args",encode_array (List.map (fun (v,c) -> - encode_obj OTFunc_args [ + encode_obj [ "v",encode_tvar v; - "value",match c with None -> vnull | Some c -> encode_tconst c + "value",match c with None -> vnull | Some c -> encode_texpr c ] ) func.tf_args); "t",encode_type func.tf_type; @@ -1177,7 +1147,7 @@ and encode_tfunc func = and encode_field_access fa = let encode_instance c tl = - encode_obj OFieldAccess_c [ + encode_obj [ "c",encode_clref c; "params",encode_tparams tl ] @@ -1203,7 +1173,7 @@ and encode_texpr e = | TTypeExpr mt -> 5,[encode_module_type mt] | TParenthesis e1 -> 6,[loop e1] | TObjectDecl fl -> 7, [encode_array (List.map (fun ((f,_,_),e) -> - encode_obj OTypedExprDef_fields [ + encode_obj [ "name",encode_string f; "expr",loop e; ]) fl)] @@ -1219,13 +1189,13 @@ and encode_texpr e = | TWhile(econd,e1,flag) -> 17,[loop econd;loop e1;vbool (flag = NormalWhile)] | TSwitch(e1,cases,edef) -> 18,[ loop e1; - encode_array (List.map (fun (el,e) -> encode_obj OTypedExprDef_cases ["values",encode_texpr_list el;"expr",loop e]) cases); + encode_array (List.map (fun (el,e) -> encode_obj ["values",encode_texpr_list el;"expr",loop e]) cases); vopt encode_texpr edef ] | TTry(e1,catches) -> 19,[ loop e1; encode_array (List.map (fun (v,e) -> - encode_obj OTypedExprDef_catches [ + encode_obj [ "v",encode_tvar v; "expr",loop e ]) catches @@ -1240,7 +1210,7 @@ and encode_texpr e = | TEnumIndex e1 -> 27,[loop e1] | TIdent s -> 28,[encode_string s] in - encode_obj OTypedExprDef [ + encode_obj [ "pos", encode_pos e.epos; "expr", encode_enum ITypedExpr tag pl; "t", encode_type e.etype @@ -1298,10 +1268,12 @@ let decode_field_kind v = | _ -> raise Invalid_expr let decode_cfield v = - { + let public = decode_bool (field v "isPublic") in + let extern = decode_bool (field v "isExtern") in + let final = decode_bool (field v "isFinal") in + let cf = { cf_name = decode_string (field v "name"); cf_type = decode_type (field v "type"); - cf_public = decode_bool (field v "isPublic"); cf_pos = decode_pos (field v "pos"); cf_name_pos = decode_pos (field v "namePos"); cf_doc = opt decode_string (field v "doc"); @@ -1311,7 +1283,12 @@ let decode_cfield v = cf_expr = None; cf_expr_unoptimized = None; cf_overloads = decode_ref (field v "overloads"); - } + cf_flags = 0; + } in + if public then add_class_field_flag cf CfPublic; + if extern then add_class_field_flag cf CfExtern; + if final then add_class_field_flag cf CfFinal; + cf let decode_efield v = { @@ -1349,7 +1326,7 @@ let decode_module_type v = let rec decode_tfunc v = { - tf_args = List.map (fun v -> decode_tvar (field v "v"),opt decode_tconst (field v "value")) (decode_array (field v "args")); + tf_args = List.map (fun v -> decode_tvar (field v "v"),opt decode_texpr (field v "value")) (decode_array (field v "args")); tf_type = decode_type (field v "t"); tf_expr = decode_texpr (field v "expr") } @@ -1442,9 +1419,10 @@ let decode_type_def v = EEnum (mk (if isExtern then [EExtern] else []) (List.map conv fields)) | 1, [] -> ETypedef (mk (if isExtern then [EExtern] else []) (CTAnonymous fields,Globals.null_pos)) - | 2, [ext;impl;interf] -> + | 2, [ext;impl;interf;final] -> let flags = if isExtern then [HExtern] else [] in let is_interface = decode_opt_bool interf in + let is_final = decode_opt_bool final in let interfaces = (match opt (fun v -> List.map decode_path (decode_array v)) impl with Some l -> l | _ -> [] ) in let flags = (match opt decode_path ext with None -> flags | Some t -> HExtends t :: flags) in let flags = if is_interface then begin @@ -1454,13 +1432,14 @@ let decode_type_def v = List.map (fun t -> HImplements t) interfaces @ flags end in + let flags = if is_final then HFinal :: flags else flags in EClass (mk flags fields) | 3, [t] -> ETypedef (mk (if isExtern then [EExtern] else []) (decode_ctype t)) | 4, [tthis;tfrom;tto] -> - let flags = match opt decode_array tfrom with None -> [] | Some ta -> List.map (fun t -> AFromType (decode_ctype t)) ta in - let flags = match opt decode_array tto with None -> flags | Some ta -> (List.map (fun t -> AToType (decode_ctype t)) ta) @ flags in - let flags = match opt decode_ctype tthis with None -> flags | Some t -> (AIsType t) :: flags in + let flags = match opt decode_array tfrom with None -> [] | Some ta -> List.map (fun t -> AbFrom (decode_ctype t)) ta in + let flags = match opt decode_array tto with None -> flags | Some ta -> (List.map (fun t -> AbTo (decode_ctype t)) ta) @ flags in + let flags = match opt decode_ctype tthis with None -> flags | Some t -> (AbOver t) :: flags in EAbstract(mk flags fields) | _ -> raise Invalid_expr @@ -1488,7 +1467,7 @@ let rec make_const e = | TParenthesis e | TMeta(_,e) | TCast(e,None) -> make_const e | TObjectDecl el -> - encode_obj O__Const (List.map (fun ((f,_,_),e) -> f, make_const e) el) + encode_obj (List.map (fun ((f,_,_),e) -> f, make_const e) el) | TArrayDecl al -> encode_array (List.map make_const al) | _ -> @@ -1527,6 +1506,22 @@ let macro_api ccom get_api = (ccom()).warning msg p; vnull ); + "info", vfun2 (fun msg p -> + let msg = decode_string msg in + let p = decode_pos p in + (ccom()).info msg p; + vnull + ); + "get_messages", vfun0 (fun() -> + encode_array (List.map (fun msg -> encode_message msg) ((ccom()).get_messages())); + ); + "filter_messages", vfun1 (fun predicate -> + let predicate = prepare_callback predicate 2 in + (ccom()).filter_messages (fun msg -> ( + decode_bool (predicate [encode_message msg]) + )); + vnull + ); "class_path", vfun0 (fun() -> encode_array (List.map encode_string (ccom()).class_path); ); @@ -1562,9 +1557,9 @@ let macro_api ccom get_api = (get_api()).after_typing (fun tl -> ignore(f [encode_array (List.map encode_module_type tl)])); vnull ); - "on_generate", vfun1 (fun f -> + "on_generate", vfun2 (fun f b -> let f = prepare_callback f 1 in - (get_api()).on_generate (fun tl -> ignore(f [encode_array (List.map encode_type tl)])); + (get_api()).on_generate (fun tl -> ignore(f [encode_array (List.map encode_type tl)])) (decode_bool b); vnull ); "on_after_generate", vfun1 (fun f -> @@ -1627,18 +1622,19 @@ let macro_api ccom get_api = vnull ); "meta_patch", vfun4 (fun m t f s -> - (get_api()).meta_patch (decode_string m) (decode_string t) (opt decode_string f) (decode_bool s); + (get_api()).meta_patch (decode_string m) (decode_string t) (opt decode_string f) (decode_bool s) (get_api_call_pos ()); vnull ); "add_global_metadata_impl", vfun5 (fun s1 s2 b1 b2 b3 -> - (get_api()).add_global_metadata (decode_string s1) (decode_string s2) (decode_bool b1,decode_bool b2,decode_bool b3); + (get_api()).add_global_metadata (decode_string s1) (decode_string s2) (decode_bool b1,decode_bool b2,decode_bool b3) (get_api_call_pos()); vnull ); "set_custom_js_generator", vfun1 (fun f -> let f = prepare_callback f 1 in (get_api()).set_js_generator (fun js_ctx -> let com = ccom() in - let api = encode_obj OJSGenApi [ + Genjs.setup_kwds com; + let api = encode_obj [ "outputFile", encode_string com.file; "types", encode_array (List.map (fun t -> encode_type (type_of_module_type t)) com.types); "main", (match com.main with None -> vnull | Some e -> encode_texpr e); @@ -1658,10 +1654,10 @@ let macro_api ccom get_api = vnull ); "quoteString", vfun1 (fun v -> - encode_string ("\"" ^ Ast.s_escape (decode_string v) ^ "\"") + encode_string ("\"" ^ StringHelper.s_escape (decode_string v) ^ "\"") ); "buildMetaData", vfun1 (fun t -> - match Codegen.build_metadata com (decode_type_decl t) with + match Texpr.build_metadata com.basic (decode_type_decl t) with | None -> vnull | Some e -> encode_texpr e ); @@ -1686,9 +1682,15 @@ let macro_api ccom get_api = ); vnull ); + "flush_disk_cache", vfun0 (fun () -> + let com = (get_api()).get_com() in + Hashtbl.clear com.file_lookup_cache; + Hashtbl.clear com.readdir_cache; + vnull + ); "get_pos_infos", vfun1 (fun p -> let p = decode_pos p in - encode_obj OContext_getPosInfos ["min",vint p.Globals.pmin;"max",vint p.Globals.pmax;"file",encode_string p.Globals.pfile] + encode_obj ["min",vint p.Globals.pmin;"max",vint p.Globals.pmax;"file",encode_string p.Globals.pfile] ); "make_position", vfun3 (fun min max file -> encode_pos { Globals.pmin = decode_int min; Globals.pmax = decode_int max; Globals.pfile = decode_string file } @@ -1699,7 +1701,7 @@ let macro_api ccom get_api = let data = Bytes.unsafe_to_string data in if name = "" then failwith "Empty resource name"; Hashtbl.replace (ccom()).resources name data; - let m = if name.[0] = '$' then (get_api()).current_macro_module() else (get_api()).current_module() in + let m = if Globals.starts_with name '$' then (get_api()).current_macro_module() else (get_api()).current_module() in m.m_extra.m_binded_res <- PMap.add name data m.m_extra.m_binded_res; vnull ); @@ -1797,24 +1799,13 @@ let macro_api ccom get_api = | None -> ()); Hashtbl.clear com.file_lookup_cache; + Hashtbl.clear com.readdir_cache; vnull ); "add_native_lib", vfun1 (fun file -> let file = decode_string file in let com = ccom() in - (match com.platform with - | Globals.Flash -> SwfLoader.add_swf_lib com file false - | Globals.Java -> Java.add_java_lib com file false - | Globals.Cs -> - let file, is_std = match ExtString.String.nsplit file "@" with - | [file] -> - file,false - | [file;"std"] -> - file,true - | _ -> failwith ("unsupported file@`std` format: " ^ file) - in - Dotnet.add_net_lib com file is_std - | _ -> failwith "Unsupported platform"); + NativeLibraryHandler.add_native_lib com file false (); vnull ); "add_native_arg", vfun1 (fun arg -> @@ -1827,11 +1818,7 @@ let macro_api ccom get_api = vnull ); "register_module_dependency", vfun2 (fun m file -> - (get_api()).module_dependency (decode_string m) (decode_string file) false; - vnull - ); - "register_module_reuse_call", vfun2 (fun m mcall -> - (get_api()).module_dependency (decode_string m) (decode_string mcall) true; + (get_api()).module_dependency (decode_string m) (decode_string file); vnull ); "get_typed_expr", vfun1 (fun e -> @@ -1855,20 +1842,11 @@ let macro_api ccom get_api = vnull ); "get_display_pos", vfun0 (fun() -> - let p = !Parser.resume_display in + let p = DisplayPosition.display_position#get in if p = Globals.null_pos then vnull else - encode_obj OCompiler_getDisplayPos ["file",encode_string p.Globals.pfile;"pos",vint p.Globals.pmin] - ); - "pattern_locals", vfun2 (fun e t -> - let loc = (get_api()).get_pattern_locals (decode_expr e) (decode_type t) in - encode_string_map (fun (v,_) -> encode_type v.v_type) loc - ); - "on_macro_context_reused", vfun1 (fun c -> - let c = prepare_callback c 0 in - (get_api()).on_reuse (fun() -> decode_bool (c [])); - vnull + encode_obj ["file",encode_string p.Globals.pfile;"pos",vint p.Globals.pmin] ); "apply_params", vfun3 (fun tpl tl t -> let tl = List.map decode_type (decode_array tl) in @@ -1918,23 +1896,33 @@ let macro_api ccom get_api = let p = decode_pos p in let l1,c1,l2,c2 = Lexer.get_pos_coords p in let make_pos line character = - encode_obj O__Const [ + encode_obj [ "line",vint line; "character",vint character; ] in let pos_start = make_pos l1 c1 in let pos_end = make_pos l2 c2 in - let range = encode_obj O__Const [ + let range = encode_obj [ "start",pos_start; "end",pos_end; ] in - let location = encode_obj O__Const [ + let location = encode_obj [ "file",encode_string p.Globals.pfile; "range",range ] in location ); + "on_null_safety_report", vfun1 (fun f -> + let f = prepare_callback f 1 in + (ccom()).callbacks#add_null_safety_report (fun (errors:(string*pos) list) -> + let encode_item (msg,pos) = + encode_obj [("msg", encode_string msg); ("pos", encode_pos pos)] + in + ignore(f [encode_array (List.map encode_item errors)]) + ); + vnull + ); ] diff --git a/src/optimization/analyzer.ml b/src/optimization/analyzer.ml index 427425f1990..202d6f8b3e9 100644 --- a/src/optimization/analyzer.ml +++ b/src/optimization/analyzer.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -17,6 +17,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) +open StringHelper open Ast open Type open Common @@ -141,7 +142,7 @@ module Ssa = struct let rec rename_in_block ctx bb = let write_var v is_phi i = update_reaching_def ctx v bb; - let v' = alloc_var (v.v_name) v.v_type v.v_pos in + let v' = alloc_var v.v_kind v.v_name v.v_type v.v_pos in declare_var ctx.graph v' bb; v'.v_meta <- v.v_meta; v'.v_capture <- v.v_capture; @@ -351,6 +352,7 @@ module ConstPropagation = DataFlow(struct | Null of Type.t | Const of tconstant | EnumValue of int * t list + | ModuleType of module_type * Type.t let conditional = true let flag = FlagExecutable @@ -368,6 +370,7 @@ module ConstPropagation = DataFlow(struct | Const ct1,Const ct2 -> ct1 = ct2 | Null t1,Null t2 -> t1 == t2 | EnumValue(i1,_),EnumValue(i2,_) -> i1 = i2 + | ModuleType(mt1,_),ModuleType (mt2,_) -> mt1 == mt2 | _ -> false let transfer ctx bb e = @@ -388,6 +391,8 @@ module ConstPropagation = DataFlow(struct Null e.etype | TConst ct -> Const ct + | TTypeExpr mt -> + ModuleType(mt,e.etype) | TLocal v -> if (follow v.v_type) == t_dynamic || v.v_capture then Bottom @@ -434,7 +439,7 @@ module ConstPropagation = DataFlow(struct begin match follow e1.etype,eval bb e1 with | TEnum _,EnumValue(i,_) -> Const (TInt (Int32.of_int i)) | _,e1 -> - begin match Optimizer.api_inline2 ctx.com c cf.cf_name [wrap e1] e.epos with + begin match Inline.api_inline2 ctx.com c cf.cf_name [wrap e1] e.epos with | None -> raise Exit | Some e -> eval bb e end @@ -442,7 +447,7 @@ module ConstPropagation = DataFlow(struct | TCall ({ eexpr = TField (_,FStatic(c,cf))},el) -> let el = List.map (eval bb) el in let el = List.map wrap el in - begin match Optimizer.api_inline2 ctx.com c cf.cf_name el e.epos with + begin match Inline.api_inline2 ctx.com c cf.cf_name el e.epos with | None -> raise Exit | Some e -> eval bb e end @@ -450,7 +455,8 @@ module ConstPropagation = DataFlow(struct eval bb e1 | _ -> let e1 = match ctx.com.platform,e.eexpr with - | Js,TArray(e1,{eexpr = TConst(TInt i)}) when Int32.to_int i = 1 -> e1 + | Js,TArray(e1,{eexpr = TConst(TInt i)}) when Int32.to_int i = 1 && Define.defined ctx.com.defines Define.JsEnumsAsArrays -> e1 + | Js,TField(e1,FDynamic "_hx_index") when not (Define.defined ctx.com.defines Define.JsEnumsAsArrays) -> e1 | Cpp,TCall({eexpr = TField(e1,FDynamic "__Index")},[]) -> e1 | Neko,TField(e1,FDynamic "index") -> e1 | _ -> raise Exit @@ -473,11 +479,14 @@ module ConstPropagation = DataFlow(struct | Top | Bottom | EnumValue _ | Null _ -> raise Not_found | Const ct -> - let e' = Codegen.type_constant ctx.com (tconst_to_const ct) e.epos in + let e' = Texpr.type_constant ctx.com.basic (tconst_to_const ct) e.epos in if not (type_change_ok ctx.com e'.etype e.etype) then raise Not_found; e' + | ModuleType(mt,t) -> + if not (type_change_ok ctx.com t e.etype) then raise Not_found; + mk (TTypeExpr mt) t e.epos in - let is_special_var v = v.v_capture || is_asvar_type v.v_type in + let is_special_var v = v.v_capture || ExtType.has_variable_semantics v.v_type in let rec commit e = match e.eexpr with | TLocal v when not (is_special_var v) -> begin try @@ -613,6 +622,7 @@ module LocalDce = struct | TCall ({eexpr = TField(_,FEnum _)},_) -> Type.iter loop e | TCall ({eexpr = TConst (TString ("phi" | "fun"))},_) -> () | TCall({eexpr = TField(e1,fa)},el) when PurityState.is_pure_field_access fa -> loop e1; List.iter loop el + | TField(_,fa) when PurityState.is_explicitly_impure fa -> raise Exit | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit | TFor _ -> raise Exit @@ -630,7 +640,7 @@ module LocalDce = struct Meta.has Meta.Used v.v_meta in let keep v = - is_used v || (not (Meta.has Meta.CompilerGenerated v.v_meta) && not ctx.config.local_dce) || is_ref_type v.v_type || v.v_capture || Meta.has Meta.This v.v_meta + is_used v || ((match v.v_kind with VUser _ | VInlined -> true | _ -> false) && not ctx.config.local_dce) || ExtType.has_reference_semantics v.v_type || v.v_capture || Meta.has Meta.This v.v_meta in let rec use v = if not (is_used v) then begin @@ -799,7 +809,7 @@ module Debug = struct ) g.g_var_infos let get_dump_path ctx c cf = - "dump" :: [platform_name ctx.com.platform] @ (fst c.cl_path) @ [Printf.sprintf "%s.%s" (snd c.cl_path) cf.cf_name] + "dump" :: [platform_name_macro ctx.com] @ (fst c.cl_path) @ [Printf.sprintf "%s.%s" (snd c.cl_path) cf.cf_name] let dot_debug ctx c cf = let g = ctx.graph in @@ -896,7 +906,7 @@ module Run = struct open Graph let with_timer detailed s f = - let timer = timer (if detailed then "analyzer" :: s else ["analyzer"]) in + let timer = Timer.timer (if detailed then "analyzer" :: s else ["analyzer"]) in let r = f() in timer(); r @@ -931,9 +941,10 @@ module Run = struct tf,e.etype,true | _ -> (* Wrap expression in a function so we don't have to treat it as a special case throughout. *) + let t = e.etype in let e = mk (TReturn (Some e)) t_dynamic e.epos in - let tf = { tf_args = []; tf_type = e.etype; tf_expr = e; } in - tf,tfun [] e.etype,false + let tf = { tf_args = []; tf_type = t; tf_expr = e; } in + tf,tfun [] t,false in with_timer actx.config.detail_times ["->";"from-texpr"] (fun () -> AnalyzerTexprTransformer.from_tfunction actx tf t e.epos); is_real_function @@ -952,20 +963,49 @@ module Run = struct e else begin (* Get rid of the wrapping function and its return expressions. *) - let rec loop first e = match e.eexpr with - | TReturn (Some e) -> e - | TFunction tf when first -> - begin match loop false tf.tf_expr with - | {eexpr = TBlock _ | TIf _ | TSwitch _ | TTry _} when actx.com.platform = Cpp || actx.com.platform = Hl -> - mk (TCall(e,[])) tf.tf_type e.epos - | e -> + match e.eexpr with + | TFunction tf -> + let get_t t = if ExtType.is_void t then tf.tf_type else t in + let rec loop e = match e.eexpr with + | TBlock [e1] -> + loop e1 + (* If there's a complex expression, keep the function and generate a call to it. *) + | TBlock _ | TIf _ | TSwitch _ | TTry _ when actx.com.platform = Cpp || actx.com.platform = Hl -> + raise Exit + (* Remove generated return *) + | TReturn (Some e) -> + e + | TBlock el -> + begin match List.rev el with + | e1 :: el -> + let e1 = loop e1 in + let e = {e with eexpr = TBlock (List.rev (e1 :: el))} in e - end - | TBlock [e] -> loop first e - | TFunction _ -> e - | _ -> Type.map_expr (loop first) e - in - loop true e + | [] -> + e + end + | TIf(e1,e2,Some e3) -> + let e2 = loop e2 in + let e3 = loop e3 in + {e with eexpr = TIf(e1,e2,Some e3); etype = get_t e.etype} + | TSwitch(e1,cases,edef) -> + let cases = List.map (fun (el,e) -> el,loop e) cases in + let edef = Option.map loop edef in + {e with eexpr = TSwitch(e1,cases,edef); etype = get_t e.etype} + | TTry(e1,catches) -> + let e1 = loop e1 in + let catches = List.map (fun (v,e) -> v,loop e) catches in + {e with eexpr = TTry(e1,catches); etype = get_t e.etype} + | TMeta(m,e1) -> + {e with eexpr = TMeta(m,loop e1)} + | TParenthesis e1 -> + {e with eexpr = TParenthesis (loop e1)} + | _ -> + e + in + (try loop tf.tf_expr with Exit -> mk (TCall(e,[])) tf.tf_type e.epos) + | _ -> + assert false end in e @@ -990,7 +1030,6 @@ module Run = struct let run_on_field ctx config c cf = match cf.cf_expr with | Some e when not (is_ignored cf.cf_meta) && not (Typecore.is_removable_field ctx cf) -> let config = update_config_from_meta ctx.Typecore.com config cf.cf_meta in - (match e.eexpr with TFunction tf -> cf.cf_expr_unoptimized <- Some tf | _ -> ()); let actx = create_analyzer_context ctx.Typecore.com config e in let debug() = print_endline (Printf.sprintf "While analyzing %s.%s" (s_type_path c.cl_path) cf.cf_name); @@ -1005,7 +1044,7 @@ module Run = struct let e = try run_on_expr actx e with - | Error.Error _ | Abort _ as exc -> + | Error.Error _ | Abort _ | Sys.Break as exc -> raise exc | exc -> debug(); diff --git a/src/optimization/analyzerConfig.ml b/src/optimization/analyzerConfig.ml index d93cad09f4e..1c11aeee5c5 100644 --- a/src/optimization/analyzerConfig.ml +++ b/src/optimization/analyzerConfig.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -57,25 +57,7 @@ let all_flags = ) [] [flag_optimize;flag_const_propagation;flag_copy_propagation;flag_local_dce;flag_fusion;flag_ignore;flag_dot_debug;flag_user_var_fusion] let has_analyzer_option meta s = - try - let rec loop ml = match ml with - | (Meta.Analyzer,el,_) :: ml -> - if List.exists (fun (e,p) -> - match e with - | EConst(Ident s2) when s = s2 -> true - | _ -> false - ) el then - true - else - loop ml - | _ :: ml -> - loop ml - | [] -> - false - in - loop meta - with Not_found -> - false + Ast.has_meta_option meta Meta.Analyzer s let is_ignored meta = has_analyzer_option meta flag_ignore @@ -121,7 +103,7 @@ let update_config_from_meta com config meta = config end | _ -> - let s = Ast.s_expr e in + let s = Ast.Printer.s_expr e in com.warning (StringError.string_error s all_flags ("Unrecognized analyzer option: " ^ s)) (pos e); config ) config el diff --git a/src/optimization/analyzerTexpr.ml b/src/optimization/analyzerTexpr.ml index ee34ef47942..db634382c9f 100644 --- a/src/optimization/analyzerTexpr.ml +++ b/src/optimization/analyzerTexpr.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -105,10 +105,9 @@ let target_handles_unops com = match com.platform with | Lua | Python -> false | _ -> true -let target_handles_assign_ops com = match com.platform with - (* Technically PHP can handle assign ops, but unfortunately x += y is not always - equivalent to x = x + y in case y has side-effects. *) - | Lua | Php -> false +let target_handles_assign_ops com e2 = match com.platform with + | Php -> not (has_side_effect e2) + | Lua -> false | Cpp when not (Common.defined com Define.Cppia) -> false | _ -> true @@ -150,30 +149,6 @@ let is_unbound_call_that_might_have_side_effects s el = match s,el with | "__js__",[{eexpr = TConst (TString s)}] when Str.string_match r s 0 -> false | _ -> true -let is_ref_type = function - | TType({t_path = ["cs"],("Ref" | "Out")},_) -> true - | TType({t_path = path},_) when path = Genphp7.ref_type_path -> true - | TType({t_path = ["cpp"],("Reference")},_) -> true - | TAbstract({a_path=["hl";"types"],"Ref"},_) -> true - | _ -> false - -let rec is_asvar_type t = - let check meta = - AnalyzerConfig.has_analyzer_option meta "as_var" - in - match t with - | TInst(c,_) -> check c.cl_meta - | TEnum(en,_) -> check en.e_meta - | TType(t,tl) -> check t.t_meta || (is_asvar_type (apply_params t.t_params tl t.t_type)) - | TAbstract(a,_) -> check a.a_meta - | TLazy f -> is_asvar_type (lazy_type f) - | TMono r -> - (match !r with - | Some t -> is_asvar_type t - | _ -> false) - | _ -> - false - let type_change_ok com t1 t2 = if t1 == t2 then true @@ -225,6 +200,8 @@ module TexprKindMapper = struct | KWrite (* Expression is lhs of =. *) | KReadWrite (* Expression is lhs of += .*) | KStore (* Expression is stored (via =, += or in array/object declaration). *) + | KEq (* Expression is lhs or rhs of == or != *) + | KEqNull (* Expression is lhs or rhs of == null or != null *) | KCalled (* Expression is being called. *) | KCallArgument (* Expression is call argument (leaves context). *) | KReturn (* Expression is returned (leaves context). *) @@ -250,6 +227,26 @@ module TexprKindMapper = struct let e1 = f KReadWrite e1 in let e2 = f KStore e2 in { e with eexpr = TBinop(OpAssignOp op,e1,e2) } + | TBinop((OpEq | OpNotEq) as op,e1,e2) -> + let e1,e2 = match (Texpr.skip e1).eexpr,(Texpr.skip e2).eexpr with + | TConst TNull,TConst TNull -> + let e1 = f KRead e1 in + let e2 = f KRead e2 in + e1,e2 + | TConst TNull,_ -> + let e1 = f KRead e1 in + let e2 = f KEqNull e2 in + e1,e2 + | _,TConst TNull -> + let e1 = f KEqNull e1 in + let e2 = f KRead e2 in + e1,e2 + | _ -> + let e1 = f KEq e1 in + let e2 = f KEq e2 in + e1,e2 + in + {e with eexpr = TBinop(op,e1,e2)} | TBinop(op,e1,e2) -> let e1 = f KRead e1 in let e2 = f KRead e2 in @@ -356,7 +353,7 @@ module TexprFilter = struct | TWhile(e1,e2,flag) when not (is_true_expr e1) -> let p = e.epos in let e_break = mk TBreak t_dynamic p in - let e_not = mk (TUnop(Not,Prefix,Codegen.mk_parent e1)) e1.etype e1.epos in + let e_not = mk (TUnop(Not,Prefix,Texpr.Builder.mk_parent e1)) e1.etype e1.epos in let e_if eo = mk (TIf(e_not,e_break,eo)) com.basic.tvoid p in let rec map_continue e = match e.eexpr with | TContinue -> @@ -370,10 +367,10 @@ module TexprFilter = struct let e_if = e_if None in let e_block = if flag = NormalWhile then Type.concat e_if e2 else Type.concat e2 e_if in let e_true = mk (TConst (TBool true)) com.basic.tbool p in - let e = mk (TWhile(Codegen.mk_parent e_true,e_block,NormalWhile)) e.etype p in + let e = mk (TWhile(Texpr.Builder.mk_parent e_true,e_block,NormalWhile)) e.etype p in loop e | TFor(v,e1,e2) -> - let e = Codegen.for_remap com v e1 e2 e.epos in + let e = Texpr.for_remap com.basic v e1 e2 e.epos in loop e | _ -> Type.map_expr loop e @@ -389,40 +386,40 @@ end *) module InterferenceReport = struct type interference_report = { - ir_var_reads : (int,bool) Hashtbl.t; - ir_var_writes : (int,bool) Hashtbl.t; - ir_field_reads : (string,bool) Hashtbl.t; - ir_field_writes : (string,bool) Hashtbl.t; + mutable ir_var_reads : bool IntMap.t; + mutable ir_var_writes : bool IntMap.t; + mutable ir_field_reads : bool StringMap.t; + mutable ir_field_writes : bool StringMap.t; mutable ir_state_read : bool; mutable ir_state_write : bool; } let create () = { - ir_var_reads = Hashtbl.create 0; - ir_var_writes = Hashtbl.create 0; - ir_field_reads = Hashtbl.create 0; - ir_field_writes = Hashtbl.create 0; + ir_var_reads = IntMap.empty; + ir_var_writes = IntMap.empty; + ir_field_reads = StringMap.empty; + ir_field_writes = StringMap.empty; ir_state_read = false; ir_state_write = false; } - let set_var_read ir v = Hashtbl.replace ir.ir_var_reads v.v_id true - let set_var_write ir v = Hashtbl.replace ir.ir_var_writes v.v_id true - let set_field_read ir s = Hashtbl.replace ir.ir_field_reads s true - let set_field_write ir s = Hashtbl.replace ir.ir_field_writes s true + let set_var_read ir v = ir.ir_var_reads <- IntMap.add v.v_id true ir.ir_var_reads + let set_var_write ir v = ir.ir_var_writes <- IntMap.add v.v_id true ir.ir_var_writes + let set_field_read ir s = ir.ir_field_reads <- StringMap.add s true ir.ir_field_reads + let set_field_write ir s = ir.ir_field_writes <- StringMap.add s true ir.ir_field_writes let set_state_read ir = ir.ir_state_read <- true let set_state_write ir = ir.ir_state_write <- true - let has_var_read ir v = Hashtbl.mem ir.ir_var_reads v.v_id - let has_var_write ir v = Hashtbl.mem ir.ir_var_writes v.v_id - let has_field_read ir s = Hashtbl.mem ir.ir_field_reads s - let has_field_write ir s = Hashtbl.mem ir.ir_field_writes s + let has_var_read ir v = IntMap.mem v.v_id ir.ir_var_reads + let has_var_write ir v = IntMap.mem v.v_id ir.ir_var_writes + let has_field_read ir s = StringMap.mem s ir.ir_field_reads + let has_field_write ir s = StringMap.mem s ir.ir_field_writes let has_state_read ir = ir.ir_state_read let has_state_write ir = ir.ir_state_write - let has_any_field_read ir = Hashtbl.length ir.ir_field_reads > 0 - let has_any_field_write ir = Hashtbl.length ir.ir_field_writes > 0 - let has_any_var_read ir = Hashtbl.length ir.ir_var_reads > 0 - let has_any_var_write ir = Hashtbl.length ir.ir_var_writes > 0 + let has_any_field_read ir = not (StringMap.is_empty ir.ir_field_reads) + let has_any_field_write ir = not (StringMap.is_empty ir.ir_field_writes) + let has_any_var_read ir = not (IntMap.is_empty ir.ir_var_reads) + let has_any_var_write ir = not (IntMap.is_empty ir.ir_var_writes) let from_texpr e = let ir = create () in @@ -528,14 +525,17 @@ module InterferenceReport = struct ir let to_string ir = - let s_hashtbl f h = - String.concat ", " (Hashtbl.fold (fun k _ acc -> (f k) :: acc) h []) + let s_intmap f h = + String.concat ", " (IntMap.fold (fun k _ acc -> (f k) :: acc) h []) in - Type.Printer.s_record_fields "\t" [ - "ir_var_reads",s_hashtbl string_of_int ir.ir_var_reads; - "ir_var_writes",s_hashtbl string_of_int ir.ir_var_writes; - "ir_field_reads",s_hashtbl (fun x -> x) ir.ir_field_reads; - "ir_field_writes",s_hashtbl (fun x -> x) ir.ir_field_writes; + let s_stringmap f h = + String.concat ", " (StringMap.fold (fun k _ acc -> (f k) :: acc) h []) + in + Type.Printer.s_record_fields "" [ + "ir_var_reads",s_intmap string_of_int ir.ir_var_reads; + "ir_var_writes",s_intmap string_of_int ir.ir_var_writes; + "ir_field_reads",s_stringmap (fun x -> x) ir.ir_field_reads; + "ir_field_writes",s_stringmap (fun x -> x) ir.ir_field_writes; "ir_state_read",string_of_bool ir.ir_state_read; "ir_state_write",string_of_bool ir.ir_state_write; ] @@ -623,14 +623,14 @@ module Fusion = struct | OpArrow -> false - let use_assign_op com op e1 e2 = + let use_assign_op com op e1 e2 e3 = let skip e = match com.platform with | Eval -> Texpr.skip e | _ -> e in let e1 = skip e1 in let e2 = skip e2 in - is_assign_op op && target_handles_assign_ops com && Texpr.equal e1 e2 && not (has_side_effect e1) && match com.platform with + is_assign_op op && target_handles_assign_ops com e3 && Texpr.equal e1 e2 && not (has_side_effect e1) && match com.platform with | Cs when is_null e1.etype || is_null e2.etype -> false (* C# hates OpAssignOp on Null *) | _ -> true @@ -647,6 +647,8 @@ module Fusion = struct | {eexpr = TLocal v} :: el -> state#dec_reads v; block_element acc el + | {eexpr = TField (_,fa)} as e1 :: el when PurityState.is_explicitly_impure fa -> + block_element (e1 :: acc) el (* no-side-effect *) | {eexpr = TEnumParameter _ | TEnumIndex _ | TFunction _ | TConst _ | TTypeExpr _} :: el -> block_element acc el @@ -674,7 +676,9 @@ module Fusion = struct block_element acc (el1 @ el2) | {eexpr = TObjectDecl fl} :: el -> block_element acc ((List.map snd fl) @ el) - | {eexpr = TIf(e1,{eexpr = TBlock []},(Some {eexpr = TBlock []} | None))} :: el -> + | {eexpr = TIf(e1,e2,None)} :: el when not (has_side_effect e2) -> + block_element acc (e1 :: el) + | {eexpr = TIf(e1,e2,Some e3)} :: el when not (has_side_effect e2) && not (has_side_effect e3) -> block_element acc (e1 :: el) | {eexpr = TBlock [e1]} :: el -> block_element acc (e1 :: el) @@ -689,18 +693,18 @@ module Fusion = struct let num_uses = state#get_reads v in let num_writes = state#get_writes v in let can_be_used_as_value = can_be_used_as_value com e in - let is_compiler_generated = Meta.has Meta.CompilerGenerated v.v_meta in + let is_compiler_generated = match v.v_kind with VUser _ | VInlined -> false | _ -> true in let has_type_params = match v.v_extra with Some (tl,_) when tl <> [] -> true | _ -> false in let b = num_uses <= 1 && num_writes = 0 && can_be_used_as_value && - not (is_asvar_type v.v_type) && + not (ExtType.has_variable_semantics v.v_type) && (is_compiler_generated || config.optimize && config.fusion && config.user_var_fusion && not has_type_params) in if config.fusion_debug then begin - print_endline (Printf.sprintf "FUSION\n\tvar %s<%i> = %s" v.v_name v.v_id (s_expr_pretty e)); - print_endline (Printf.sprintf "\tcan_be_fused:%b: num_uses:%i <= 1 && num_writes:%i = 0 && can_be_used_as_value:%b && (is_compiler_generated:%b || config.optimize:%b && config.fusion:%b && config.user_var_fusion:%b)" - b num_uses num_writes can_be_used_as_value is_compiler_generated config.optimize config.fusion config.user_var_fusion) + print_endline (Printf.sprintf "\nFUSION: %s\n\tvar %s<%i> = %s" (if b then "true" else "false") v.v_name v.v_id (s_expr_pretty e)); + print_endline (Printf.sprintf "CONDITION:\n\tnum_uses:%i <= 1 && num_writes:%i = 0 && can_be_used_as_value:%b && (is_compiler_generated:%b || config.optimize:%b && config.fusion:%b && config.user_var_fusion:%b)" + num_uses num_writes can_be_used_as_value is_compiler_generated config.optimize config.fusion config.user_var_fusion) end; b in @@ -780,8 +784,8 @@ module Fusion = struct let found = ref false in let blocked = ref false in let ir = InterferenceReport.from_texpr e1 in - if config.fusion_debug then print_endline (Printf.sprintf "\tInterferenceReport: %s\n\t%s" - (InterferenceReport.to_string ir) (Type.s_expr_pretty true "\t" false (s_type (print_context())) (mk (TBlock el) t_dynamic null_pos))); + if config.fusion_debug then print_endline (Printf.sprintf "INTERFERENCE: %s\nINTO: %s" + (InterferenceReport.to_string ir) (Type.s_expr_pretty true "" false (s_type (print_context())) (mk (TBlock el) t_dynamic null_pos))); (* This function walks the AST in order of evaluation and tries to find an occurrence of v1. If successful, that occurrence is replaced with e1. If there's an interference "on the way" the replacement is canceled. *) let rec replace e = @@ -792,7 +796,7 @@ module Fusion = struct blocked := old; e in - let handle_el el = + let handle_el' el = (* This mess deals with the fact that the order of evaluation is undefined for call arguments on these targets. Even if we find a replacement, we pretend that we didn't in order to find possible interferences in later call arguments. *) @@ -807,7 +811,7 @@ module Fusion = struct found := !really_found; el in - let handle_el = if not (target_handles_side_effect_order com) then handle_el else List.map replace in + let handle_el = if not (target_handles_side_effect_order com) then handle_el' else List.map replace in let handle_call e2 el = match com.platform with | Neko -> (* Neko has this reversed at the moment (issue #4787) *) @@ -846,12 +850,15 @@ module Fusion = struct found := true; if type_change_ok com v1.v_type e1.etype then e1 else mk (TCast(e1,None)) v1.v_type e.epos | TLocal v -> - if has_var_write ir v || ((v.v_capture || is_ref_type v.v_type) && (has_state_write ir)) then raise Exit; + if has_var_write ir v || ((v.v_capture || ExtType.has_reference_semantics v.v_type) && (has_state_write ir)) then raise Exit; e | TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) -> let e2 = replace e2 in if not !found && has_var_read ir v then raise Exit; {e with eexpr = TBinop(OpAssign,e1,e2)} + (* Never fuse into write-positions (issue #7298) *) + | TBinop(OpAssignOp _,{eexpr = TLocal v2},_) | TUnop((Increment | Decrement),_,{eexpr = TLocal v2}) when v1 == v2 -> + raise Exit | TBinop(OpAssignOp _ as op,({eexpr = TLocal v} as e1),e2) -> let e2 = replace e2 in if not !found && (has_var_read ir v || has_var_write ir v) then raise Exit; @@ -878,6 +885,27 @@ module Fusion = struct | TUnop((Increment | Decrement),_,{eexpr = TField(e1,fa)}) when has_field_read ir (field_name fa) || has_state_read ir || has_field_write ir (field_name fa) || has_state_write ir -> raise Exit + (* array *) + | TArray(e1,e2) -> + let e1 = replace e1 in + let e2 = replace e2 in + if not !found && has_state_write ir then raise Exit; + {e with eexpr = TArray(e1,e2)} + | TBinop(OpAssign,({eexpr = TArray(e1,e2)} as ef),e3) -> + let e1 = replace e1 in + let e2 = replace e2 in + let e3 = replace e3 in + if not !found && (has_state_read ir) then raise Exit; + {e with eexpr = TBinop(OpAssign,{ef with eexpr = TArray(e1,e2)},e3)} + | TBinop(OpAssignOp _ as op,({eexpr = TArray(e1,e2)} as ef),e3) -> + let e1 = replace e1 in + let e2 = replace e2 in + if not !found && has_state_write ir then raise Exit; + let e3 = replace e3 in + if not !found && has_state_read ir then raise Exit; + {e with eexpr = TBinop(op,{ef with eexpr = TArray(e1,e2)},e3)} + | TUnop((Increment | Decrement),_,{eexpr = TArray _}) when has_state_read ir || has_state_write ir -> + raise Exit (* state *) | TCall({eexpr = TIdent s},el) when not (is_unbound_call_that_might_have_side_effects s el) -> e @@ -904,19 +932,14 @@ module Fusion = struct if not !found && (((has_state_read ir || has_any_field_read ir)) || has_state_write ir || has_any_field_write ir) then raise Exit; {e with eexpr = TCall(e1,el)} | TObjectDecl fl -> - let el = handle_el (List.map snd fl) in + (* The C# generator has trouble with evaluation order in structures (#7531). *) + let el = (match com.platform with Cs -> handle_el' | _ -> handle_el) (List.map snd fl) in if not !found && (has_state_write ir || has_any_field_write ir) then raise Exit; {e with eexpr = TObjectDecl (List.map2 (fun (s,_) e -> s,e) fl el)} | TArrayDecl el -> let el = handle_el el in (*if not !found && (has_state_write ir || has_any_field_write ir) then raise Exit;*) {e with eexpr = TArrayDecl el} - | TBinop(OpAssign,({eexpr = TArray(e1,e2)} as ea),e3) -> - let e1 = replace e1 in - let e2 = replace e2 in - let e3 = replace e3 in - if not !found && has_state_read ir then raise Exit; - {e with eexpr = TBinop(OpAssign,{ea with eexpr = TArray(e1,e2)},e3)} | TBinop(op,e1,e2) when (match com.platform with Cpp -> true | _ -> false) -> let e1 = replace e1 in let temp_found = !found in @@ -924,11 +947,6 @@ module Fusion = struct let e2 = replace e2 in found := !found || temp_found; {e with eexpr = TBinop(op,e1,e2)} - | TArray(e1,e2) -> - let e1 = replace e1 in - let e2 = replace e2 in - if not !found && has_state_write ir then raise Exit; - {e with eexpr = TArray(e1,e2)} | _ -> Type.map_expr replace e in @@ -978,7 +996,8 @@ module Fusion = struct begin try let e2,f = match e2.eexpr with | TReturn (Some e2) -> e2,(fun e -> {e2 with eexpr = TReturn (Some e)}) - | TBinop(OpAssign,e21,e22) -> e22,(fun e -> {e2 with eexpr = TBinop(OpAssign,e21,e)}) + (* This is not sound if e21 contains the variable (issue #7704) *) + (* | TBinop(OpAssign,e21,e22) -> e22,(fun e -> {e2 with eexpr = TBinop(OpAssign,e21,e)}) *) | TVar(v,Some e2) -> e2,(fun e -> {e2 with eexpr = TVar(v,Some e)}) | _ -> raise Exit in @@ -1006,7 +1025,7 @@ module Fusion = struct with Exit -> fuse (e1 :: acc) (e2 :: el) end - | {eexpr = TBinop(OpAssign,e1,{eexpr = TBinop(op,e2,e3)})} as e :: el when use_assign_op com op e1 e2 -> + | {eexpr = TBinop(OpAssign,e1,{eexpr = TBinop(op,e2,e3)})} as e :: el when use_assign_op com op e1 e2 e3 -> let rec loop e = match e.eexpr with | TLocal v -> state#dec_reads v; | _ -> Type.iter loop e @@ -1108,14 +1127,15 @@ module Cleanup = struct | TField({eexpr = TTypeExpr _},_) -> e | TTypeExpr (TClassDecl c) -> - List.iter (fun cf -> if not (Meta.has Meta.MaybeUsed cf.cf_meta) then cf.cf_meta <- (Meta.MaybeUsed,[],cf.cf_pos) :: cf.cf_meta;) c.cl_ordered_statics; e + | TMeta((Meta.Ast,_,_),e1) when (match e1.eexpr with TSwitch _ -> false | _ -> true) -> + loop e1 | _ -> Type.map_expr loop e in let e = loop e in let rec loop kind e = match kind,e.eexpr with - | KRead,TField(e1,FClosure(Some(c,tl),cf)) -> + | KEqNull,TField(e1,FClosure(Some(c,tl),cf)) -> let e1 = loop KAccess e1 in {e with eexpr = TField(e1,FInstance(c,tl,cf))} | _ -> @@ -1188,7 +1208,7 @@ module Purity = struct let rec check_write e1 = begin match e1.eexpr with | TLocal v -> - if is_ref_type v.v_type then taint_raise node; (* Writing to a ref type means impurity. *) + if ExtType.has_reference_semantics v.v_type then taint_raise node; (* Writing to a ref type means impurity. *) () (* Writing to locals does not violate purity. *) | TField({eexpr = TConst TThis},_) when is_ctor -> () (* A constructor can write to its own fields without violating purity. *) @@ -1237,7 +1257,7 @@ module Purity = struct | None -> if not (is_pure c cf) then taint node (* TODO: The function code check shouldn't be here I guess. *) - | Some _ when (Meta.has Meta.Extern cf.cf_meta || Meta.has Meta.FunctionCode cf.cf_meta || Meta.has (Meta.Custom ":hlNative") cf.cf_meta || Meta.has (Meta.Custom ":hlNative") c.cl_meta) -> + | Some _ when (has_class_field_flag cf CfExtern || Meta.has Meta.FunctionCode cf.cf_meta || Meta.has (Meta.HlNative) cf.cf_meta || Meta.has (Meta.HlNative) c.cl_meta) -> if not (is_pure c cf) then taint node | Some e -> try diff --git a/src/optimization/analyzerTexprTransformer.ml b/src/optimization/analyzerTexprTransformer.ml index 6571aeb2e29..b8a67f048b5 100644 --- a/src/optimization/analyzerTexprTransformer.ml +++ b/src/optimization/analyzerTexprTransformer.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -173,8 +173,6 @@ let rec func ctx bb tf t p = close_node g bb; add_cfg_edge bb_func_end bb_next CFGGoto; bb_next,ec - (*| TTypeExpr(TClassDecl {cl_kind = KAbstractImpl a}) when not (Meta.has Meta.RuntimeValue a.a_meta) -> - error "Cannot use abstract as value" e.epos*) | TConst _ | TTypeExpr _ -> bb,e | TThrow _ | TReturn _ | TBreak | TContinue -> @@ -239,11 +237,7 @@ let rec func ctx bb tf t p = | s :: _ -> s | [] -> ctx.temp_var_name in - let v = match v with Some v -> v | None -> alloc_var (loop e) e.etype e.epos in - begin match ctx.com.platform with - | Globals.Cpp when sequential && not (Common.defined ctx.com Define.Cppia) -> () - | _ -> v.v_meta <- [Meta.CompilerGenerated,[],e.epos]; - end; + let v = match v with Some v -> v | None -> alloc_var VGenerated (loop e) e.etype e.epos in let bb = declare_var_and_assign bb v e e.epos in let e = {e with eexpr = TLocal v} in let e = List.fold_left (fun e f -> f e) e fl in @@ -309,12 +303,12 @@ let rec func ctx bb tf t p = and call bb e e1 el = let bb = ref bb in let check e t = match e.eexpr with - | TLocal v when is_ref_type t -> + | TLocal v when ExtType.has_reference_semantics t -> v.v_capture <- true; e | _ -> - if is_asvar_type t then begin - let v = alloc_var "tmp" t e.epos in + if ExtType.has_variable_semantics t then begin + let v = alloc_var VGenerated "tmp" t e.epos in let bb',e = bind_to_temp ~v:(Some v) !bb false e in bb := bb'; e @@ -577,7 +571,7 @@ let rec func ctx bb tf t p = add_texpr bb {e with eexpr = TNew(c,tl,el)}; bb | TCast(e1,Some mt) -> - let b,e1 = value bb e1 in + let bb,e1 = value bb e1 in add_texpr bb {e with eexpr = TCast(e1,Some mt)}; bb | TBinop(OpAssignOp op,({eexpr = TArray(e1,e2)} as ea),e3) -> @@ -605,6 +599,10 @@ let rec func ctx bb tf t p = | TLocal _ when not ctx.config.AnalyzerConfig.local_dce -> add_texpr bb e; bb + | TField (e1,fa) when has_side_effect e -> + let bb,e1 = value bb e1 in + add_texpr bb {e with eexpr = TField(e1,fa)}; + bb (* no-side-effect *) | TEnumParameter _ | TEnumIndex _ | TFunction _ | TConst _ | TTypeExpr _ | TLocal _ | TIdent _ -> bb @@ -722,7 +720,7 @@ and func ctx i = let eo = Option.map loop eo in let v' = get_var_origin ctx.graph v in {e with eexpr = TVar(v',eo)} - | TBinop(OpAssign,e1,({eexpr = TBinop(op,e2,e3)} as e4)) when target_handles_assign_ops ctx.com -> + | TBinop(OpAssign,e1,({eexpr = TBinop(op,e2,e3)} as e4)) when target_handles_assign_ops ctx.com e3 -> let e1 = loop e1 in let e2 = loop e2 in let e3 = loop e3 in @@ -737,8 +735,13 @@ and func ctx i = begin match e1.eexpr,e2.eexpr with | TLocal v1,TLocal v2 when v1 == v2 && not v1.v_capture && is_valid_assign_op op -> begin match op,e3.eexpr with - | OpAdd,TConst (TInt i32) when Int32.to_int i32 = 1 && target_handles_assign_ops ctx.com -> {e with eexpr = TUnop(Increment,Prefix,e1)} - | OpSub,TConst (TInt i32) when Int32.to_int i32 = 1 && target_handles_assign_ops ctx.com -> {e with eexpr = TUnop(Decrement,Prefix,e1)} + | (OpAdd|OpSub) as op,TConst (TInt i32) when Int32.to_int i32 = 1 && ExtType.is_numeric (Abstract.follow_with_abstracts v1.v_type) -> + let op = match op with + | OpAdd -> Increment + | OpSub -> Decrement + | _ -> assert false + in + {e with eexpr = TUnop(op,Prefix,e1)} | _ -> {e with eexpr = TBinop(OpAssignOp op,e1,e3)} end | _ -> diff --git a/src/optimization/analyzerTypes.ml b/src/optimization/analyzerTypes.ml index f77c7c3ca12..7028e59f74d 100644 --- a/src/optimization/analyzerTypes.ml +++ b/src/optimization/analyzerTypes.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/src/optimization/dce.ml b/src/optimization/dce.ml index 26ef137b3f5..d1d8374dfdb 100644 --- a/src/optimization/dce.ml +++ b/src/optimization/dce.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -22,6 +22,11 @@ open Common open Type open Globals +type dce_mode = + | DceNo + | DceStd + | DceFull + type dce = { com : context; full : bool; @@ -38,6 +43,13 @@ type dce = { mutable features : (string,(tclass * tclass_field * bool) list) Hashtbl.t; } +let push_class dce c = + let old = dce.curclass in + dce.curclass <- c; + (fun () -> + dce.curclass <- old + ) + (* checking *) (* check for @:keepSub metadata, which forces @:keep on child classes *) @@ -46,21 +58,31 @@ let rec super_forces_keep c = | Some (csup,_) -> super_forces_keep csup | _ -> false -let rec is_or_overrides_extern_field cf c = - if c.cl_extern then cf.cf_expr = None - else +let overrides_extern_field cf c = + let is_extern c cf = c.cl_extern && cf.cf_expr = None in + let rec loop c cf = match c.cl_super with - | None -> false - | Some (csup,_) -> - try is_or_overrides_extern_field (PMap.find cf.cf_name csup.cl_fields) csup - with Not_found -> false + | None -> false + | Some (c,_) -> + try + let cf = PMap.find cf.cf_name c.cl_fields in + if is_extern c cf then + true + else + loop c cf + with Not_found -> + false + in + loop c cf let is_std_file dce file = List.exists (ExtString.String.starts_with file) dce.std_dirs +let keep_metas = [Meta.Keep;Meta.Expose] + (* check if a class is kept entirely *) let keep_whole_class dce c = - Meta.has Meta.Keep c.cl_meta + Meta.has_one_of keep_metas c.cl_meta || not (dce.full || is_std_file dce c.cl_module.m_extra.m_file || has_meta Meta.Dce c.cl_meta) || super_forces_keep c || (match c with @@ -72,16 +94,38 @@ let keep_whole_class dce c = | _ -> false) let keep_whole_enum dce en = - Meta.has Meta.Keep en.e_meta + Meta.has_one_of keep_metas en.e_meta || not (dce.full || is_std_file dce en.e_module.m_extra.m_file || has_meta Meta.Dce en.e_meta) -(* check if a field is kept *) -let keep_field dce cf c is_static = - Meta.has Meta.Keep cf.cf_meta - || Meta.has Meta.Used cf.cf_meta +(* + Check if a field is kept. + `keep_field` is checked to determine the DCE entry points, i.e. all fields that have `@:keep` or kept for other reasons. + And then it is used at the end to check which fields can be filtered from their classes. +*) +let rec keep_field dce cf c is_static = + Meta.has_one_of (Meta.Used :: keep_metas) cf.cf_meta || cf.cf_name = "__init__" || not (is_physical_field cf) - || (not is_static && is_or_overrides_extern_field cf c) + || (not is_static && overrides_extern_field cf c) + || ( + cf.cf_name = "new" + && match c.cl_super with (* parent class kept constructor *) + | Some ({ cl_constructor = Some ctor } as csup, _) -> keep_field dce ctor csup false + | _ -> false + ) + || begin + let check_accessor prefix = + try + let fields = if is_static then c.cl_statics else c.cl_fields in + let accessor = PMap.find (prefix ^ cf.cf_name) fields in + keep_field dce accessor c is_static + with Not_found -> false + in + match cf.cf_kind with + | Var { v_read = AccCall } -> check_accessor "get_" + | Var { v_write = AccCall } -> check_accessor "set_" + | _ -> false + end (* marking *) @@ -97,6 +141,7 @@ let rec check_feature dce s = and check_and_add_feature dce s = check_feature dce s; + assert (dce.curclass != null_class); Hashtbl.replace dce.curclass.cl_module.m_extra.m_features s true (* mark a field as kept *) @@ -126,10 +171,15 @@ and mark_field dce c cf stat = | None -> add cf | Some (c,_) -> mark_field dce c cf stat end else - add cf + add cf; + if not stat && is_physical_field cf then + match c.cl_constructor with + | None -> () + | Some ctor -> mark_field dce c ctor false end let rec update_marked_class_fields dce c = + let pop = push_class dce c in (* mark all :?used fields as surely :used now *) List.iter (fun cf -> if Meta.has Meta.MaybeUsed cf.cf_meta then mark_field dce c cf true @@ -140,7 +190,8 @@ let rec update_marked_class_fields dce c = (* we always have to keep super classes and implemented interfaces *) (match c.cl_init with None -> () | Some init -> dce.follow_expr dce init); List.iter (fun (c,_) -> mark_class dce c) c.cl_implements; - (match c.cl_super with None -> () | Some (csup,pl) -> mark_class dce csup) + (match c.cl_super with None -> () | Some (csup,pl) -> mark_class dce csup); + pop() (* mark a class as kept. If the class has fields marked as @:?keep, make sure to keep them *) and mark_class dce c = if not (Meta.has Meta.Used c.cl_meta) then begin @@ -151,11 +202,7 @@ end let rec mark_enum dce e = if not (Meta.has Meta.Used e.e_meta) then begin e.e_meta <- (Meta.Used,[],e.e_pos) :: e.e_meta; - - (* do not generate has_enum feature for @:fakeEnum enums since they are not really enums *) - if not (Meta.has Meta.FakeEnum e.e_meta) then - check_and_add_feature dce "has_enum"; - + check_and_add_feature dce "has_enum"; check_feature dce (Printf.sprintf "%s.*" (s_type_path e.e_path)); PMap.iter (fun _ ef -> mark_t dce ef.ef_pos ef.ef_type) e.e_constrs; end @@ -187,7 +234,7 @@ and mark_t dce p t = List.iter (mark_t dce p) pl | TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta -> begin try - mark_t dce p (snd (Typecore.AbstractCast.find_multitype_specialization dce.com a pl p)) + mark_t dce p (snd (AbstractCast.find_multitype_specialization dce.com a pl p)) with Error.Error _ -> () end @@ -330,7 +377,7 @@ and mark_directly_used_t dce p t = List.iter (mark_directly_used_t dce p) pl | TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta -> begin try (* this is copy-pasted from mark_t *) - mark_directly_used_t dce p (snd (Typecore.AbstractCast.find_multitype_specialization dce.com a pl p)) + mark_directly_used_t dce p (snd (AbstractCast.find_multitype_specialization dce.com a pl p)) with Error.Error _ -> () end @@ -391,11 +438,12 @@ and expr_field dce e fa is_call_expr = check_and_add_feature dce "dynamic_read"; check_and_add_feature dce ("dynamic_read." ^ n); | _ -> ()); - begin match follow e.etype with - | TInst(c,_) -> + begin match follow e.etype, fa with + | TInst(c,_), _ + | _, FClosure (Some (c, _), _) -> mark_class dce c; field dce c n false; - | TAnon a -> + | TAnon a, _ -> (match !(a.a_status) with | Statics c -> mark_class dce c; @@ -481,6 +529,12 @@ and expr dce e = check_feature dce ft; expr dce e; + (* keep toString method of T when array.join() is called *) + | TCall ({eexpr = TField(_, FInstance({cl_path = ([],"Array")}, pl, {cf_name="join"}))} as ef, args) -> + List.iter (fun e -> to_string dce e) pl; + expr dce ef; + List.iter (expr dce) args; + (* keep toString method when the class is argument to Std.string or haxe.Log.trace *) | TCall ({eexpr = TField({eexpr = TTypeExpr (TClassDecl ({cl_path = (["haxe"],"Log")} as c))},FStatic (_,{cf_name="trace"}))} as ef, ((e2 :: el) as args)) | TCall ({eexpr = TField({eexpr = TTypeExpr (TClassDecl ({cl_path = ([],"Std")} as c))},FStatic (_,{cf_name="string"}))} as ef, ((e2 :: el) as args)) -> @@ -510,7 +564,7 @@ and expr dce e = check_and_add_feature dce "array_write"; check_and_add_feature dce "array_read"; expr dce e1; - | TBinop(OpAdd,e1,e2) when is_dynamic e1.etype || is_dynamic e2.etype -> + | TBinop((OpAdd | OpAssignOp(OpAdd)),e1,e2) when is_dynamic e1.etype || is_dynamic e2.etype -> check_and_add_feature dce "add_dynamic"; expr dce e1; expr dce e2; @@ -564,7 +618,7 @@ and expr dce e = check_and_add_feature dce "dynamic_binop_=="; expr dce e1; expr dce e2; - | TBinop(OpEq,({ etype = t1} as e1), ({ etype = t2} as e2) ) when is_dynamic t1 || is_dynamic t2 -> + | TBinop(OpNotEq,({ etype = t1} as e1), ({ etype = t2} as e2) ) when is_dynamic t1 || is_dynamic t2 -> check_and_add_feature dce "dynamic_binop_!="; expr dce e1; expr dce e2; @@ -627,36 +681,11 @@ let fix_accessors com = | _ -> () ) com.types -let run com main full = - let dce = { - com = com; - full = full; - dependent_types = Hashtbl.create 0; - std_dirs = if full then [] else List.map Path.unique_full_path com.std_path; - debug = Common.defined com Define.DceDebug; - added_fields = []; - follow_expr = expr; - marked_fields = []; - marked_maybe_fields = []; - t_stack = []; - ts_stack = []; - features = Hashtbl.create 0; - curclass = null_class; - } in - begin match main with - | Some {eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} | Some {eexpr = TBlock ({ eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} :: _)} -> - cf.cf_meta <- (Meta.Keep,[],cf.cf_pos) :: cf.cf_meta - | _ -> - () - end; - List.iter (fun m -> - List.iter (fun (s,v) -> - if Hashtbl.mem dce.features s then Hashtbl.replace dce.features s (v :: Hashtbl.find dce.features s) - else Hashtbl.add dce.features s [v] - ) m.m_extra.m_if_feature; - ) com.modules; - (* first step: get all entry points, which is the main method and all class methods which are marked with @:keep *) - List.iter (fun t -> match t with +let collect_entry_points dce com = + List.iter (fun t -> + let mt = t_infos t in + mt.mt_meta <- Meta.remove Meta.Used mt.mt_meta; + match t with | TClassDecl c -> let keep_class = keep_whole_class dce c && (not c.cl_extern || c.cl_interface) in let loop stat cf = @@ -678,7 +707,9 @@ let run com main full = () end; | TEnumDecl en when keep_whole_enum dce en -> - mark_enum dce en + let pop = push_class dce {null_class with cl_module = en.e_module} in + mark_enum dce en; + pop() | _ -> () ) com.types; @@ -687,8 +718,9 @@ let run com main full = | None -> () | Some _ -> print_endline ("[DCE] Entry point: " ^ (s_type_path c.cl_path) ^ "." ^ cf.cf_name) ) dce.added_fields; - end; - (* second step: initiate DCE passes and keep going until no new fields were added *) + end + +let mark dce = let rec loop () = match dce.added_fields with | [] -> () @@ -698,21 +730,24 @@ let run com main full = List.iter (fun (c,cf,stat) -> mark_dependent_fields dce c cf.cf_name stat) cfl; (* mark fields as used *) List.iter (fun (c,cf,stat) -> + let pop = push_class dce c in if is_physical_field cf then mark_class dce c; mark_field dce c cf stat; - mark_t dce cf.cf_pos cf.cf_type + mark_t dce cf.cf_pos cf.cf_type; + pop() ) cfl; (* follow expressions to new types/fields *) List.iter (fun (c,cf,_) -> - dce.curclass <- c; + let pop = push_class dce c in opt (expr dce) cf.cf_expr; List.iter (fun cf -> if cf.cf_expr <> None then opt (expr dce) cf.cf_expr) cf.cf_overloads; - dce.curclass <- null_class + pop(); ) cfl; loop () in - loop (); - (* third step: filter types *) + loop () + +let sweep dce com = let rec loop acc types = match types with | (TClassDecl c) as mt :: l when keep_whole_class dce c -> @@ -787,7 +822,46 @@ let run com main full = | [] -> acc in - com.types <- loop [] (List.rev com.types); + com.types <- loop [] (List.rev com.types) + +let run com main mode = + let full = mode = DceFull in + let dce = { + com = com; + full = full; + dependent_types = Hashtbl.create 0; + std_dirs = if full then [] else List.map Path.unique_full_path com.std_path; + debug = Common.defined com Define.DceDebug; + added_fields = []; + follow_expr = expr; + marked_fields = []; + marked_maybe_fields = []; + t_stack = []; + ts_stack = []; + features = Hashtbl.create 0; + curclass = null_class; + } in + begin match main with + | Some {eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} | Some {eexpr = TBlock ({ eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} :: _)} -> + cf.cf_meta <- (Meta.Keep,[],cf.cf_pos) :: cf.cf_meta + | _ -> + () + end; + List.iter (fun m -> + List.iter (fun (s,v) -> + if Hashtbl.mem dce.features s then Hashtbl.replace dce.features s (v :: Hashtbl.find dce.features s) + else Hashtbl.add dce.features s [v] + ) m.m_extra.m_if_feature; + ) com.modules; + + (* first step: get all entry points, which is the main method and all class methods which are marked with @:keep *) + collect_entry_points dce com; + + (* second step: initiate DCE passes and keep going until no new fields were added *) + mark dce; + + (* third step: filter types *) + if mode <> DceNo then sweep dce com; (* extra step to adjust properties that had accessors removed (required for Php and Cpp) *) fix_accessors com; @@ -819,10 +893,5 @@ let run com main full = ) com.types; (* cleanup added fields metadata - compatibility with compilation server *) - let rec remove_meta m = function - | [] -> [] - | (m2,_,_) :: l when m = m2 -> l - | x :: l -> x :: remove_meta m l - in - List.iter (fun cf -> cf.cf_meta <- remove_meta Meta.Used cf.cf_meta) dce.marked_fields; - List.iter (fun cf -> cf.cf_meta <- remove_meta Meta.MaybeUsed cf.cf_meta) dce.marked_maybe_fields + List.iter (fun cf -> cf.cf_meta <- Meta.remove Meta.Used cf.cf_meta) dce.marked_fields; + List.iter (fun cf -> cf.cf_meta <- Meta.remove Meta.MaybeUsed cf.cf_meta) dce.marked_maybe_fields diff --git a/src/optimization/inline.ml b/src/optimization/inline.ml new file mode 100644 index 00000000000..cbf2613132e --- /dev/null +++ b/src/optimization/inline.ml @@ -0,0 +1,780 @@ +open Globals +open Ast +open Type +open OptimizerTexpr +open Common +open Typecore +open Error + +let mk_untyped_call name p params = + { + eexpr = TCall({ eexpr = TIdent name; etype = t_dynamic; epos = p }, params); + etype = t_dynamic; + epos = p; + } + +let api_inline2 com c field params p = + match c.cl_path, field, params with + | ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] -> (match com.platform with + | Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) -> + (* We don't want to optimize enums from external sources; as they might change unexpectedly *) + (* and since native C# enums don't have the concept of index - they have rather a value, *) + (* which can't be mapped to a native API - this kind of substitution is dangerous *) + None + | _ -> + Some (mk (TConst (TInt (Int32.of_int f.ef_index))) com.basic.tint p)) + | ([],"Type"),"enumIndex",[{ eexpr = TCall({ eexpr = TField (_,FEnum (en,f)) },pl) }] when List.for_all (fun e -> not (has_side_effect e)) pl -> + (match com.platform with + | Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) -> + (* see comment above *) + None + | _ -> + Some (mk (TConst (TInt (Int32.of_int f.ef_index))) com.basic.tint p)) + | ([],"Std"),"int",[{ eexpr = TConst (TInt _) } as e] -> + Some { e with epos = p } + | ([],"String"),"fromCharCode",[{ eexpr = TConst (TInt i) }] when i > 0l && i < 128l -> + Some (mk (TConst (TString (String.make 1 (char_of_int (Int32.to_int i))))) com.basic.tstring p) + | ([],"Std"),"string",[{ eexpr = TCast ({ eexpr = TConst c } as e, None)}] + | ([],"Std"),"string",[{ eexpr = TConst c } as e] -> + (match c with + | TString s -> + Some { e with epos = p } + | TInt i -> + Some { eexpr = TConst (TString (Int32.to_string i)); epos = p; etype = com.basic.tstring } + | TBool b -> + Some { eexpr = TConst (TString (if b then "true" else "false")); epos = p; etype = com.basic.tstring } + | _ -> + None) + | ([],"Std"),"string",[{ eexpr = TIf (_,{ eexpr = TConst (TString _)},Some { eexpr = TConst (TString _) }) } as e] -> + Some e + | ([],"Std"),"string",[{ eexpr = TLocal v | TField({ eexpr = TLocal v },_) } as ev] when (com.platform = Js || com.platform = Flash) && (match v.v_kind with VUser _ -> true | _ -> false) -> + let pos = ev.epos in + let stringv() = + let to_str = mk (TBinop (Ast.OpAdd, mk (TConst (TString "")) com.basic.tstring pos, ev)) com.basic.tstring pos in + if com.platform = Js || is_nullable ev.etype then + let chk_null = mk (TBinop (Ast.OpEq, ev, mk (TConst TNull) t_dynamic pos)) com.basic.tbool pos in + mk (TIf (chk_null, mk (TConst (TString "null")) com.basic.tstring pos, Some to_str)) com.basic.tstring pos + else + to_str + in + (match follow ev.etype with + | TInst ({ cl_path = [],"String" }, []) -> + Some (stringv()) + | TAbstract ({ a_path = [],"Float" }, []) -> + Some (stringv()) + | TAbstract ({ a_path = [],"Int" }, []) -> + Some (stringv()) + | TAbstract ({ a_path = [],"UInt" }, []) -> + Some (stringv()) + | TAbstract ({ a_path = [],"Bool" }, []) -> + Some (stringv()) + | _ -> + None) + | ([],"Std"),"int",[{ eexpr = TConst (TFloat f) }] -> + let f = float_of_string f in + (match classify_float f with + | FP_infinite | FP_nan -> + None + | _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int +. 1. -> + None (* out range, keep platform-specific behavior *) + | _ -> + Some { eexpr = TConst (TInt (Int32.of_float f)); etype = com.basic.tint; epos = p }) + | ([],"Math"),"ceil",[{ eexpr = TConst (TFloat f) }] -> + let f = float_of_string f in + (match classify_float f with + | FP_infinite | FP_nan -> + None + | _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int -> + None (* out range, keep platform-specific behavior *) + | _ -> + Some { eexpr = TConst (TInt (Int32.of_float (ceil f))); etype = com.basic.tint; epos = p }) + | ([],"Math"),"floor",[{ eexpr = TConst (TFloat f) }] -> + let f = float_of_string f in + (match classify_float f with + | FP_infinite | FP_nan -> + None + | _ when f <= Int32.to_float Int32.min_int || f >= Int32.to_float Int32.max_int +. 1. -> + None (* out range, keep platform-specific behavior *) + | _ -> + Some { eexpr = TConst (TInt (Int32.of_float (floor f))); etype = com.basic.tint; epos = p }) + | (["cs"],"Lib"),("fixed" | "checked" | "unsafe"),[e] -> + Some (mk_untyped_call ("__" ^ field ^ "__") p [e]) + | (["cs"],"Lib"),("lock"),[obj;block] -> + Some (mk_untyped_call ("__lock__") p [obj;mk_block block]) + | (["java"],"Lib"),("lock"),[obj;block] -> + Some (mk_untyped_call ("__lock__") p [obj;mk_block block]) + | _ -> + None + +let api_inline ctx c field params p = + let mk_typeexpr path = + let m = (try Hashtbl.find ctx.g.modules path with Not_found -> assert false) in + add_dependency ctx.m.curmod m; + ExtList.List.find_map (function + | TClassDecl cl when cl.cl_path = path -> Some (make_static_this cl p) + | _ -> None + ) m.m_types + in + + let eJsSyntax () = mk_typeexpr (["js"],"Syntax") in + let eJsBoot () = mk_typeexpr (["js"],"Boot") in + + let tstring = ctx.com.basic.tstring in + let tbool = ctx.com.basic.tbool in + let tint = ctx.com.basic.tint in + + match c.cl_path, field, params with + | ([],"Std"),"is",[o;t] | (["js"],"Boot"),"__instanceof",[o;t] when ctx.com.platform = Js -> + let is_trivial e = + match e.eexpr with + | TConst _ | TLocal _ -> true + | _ -> false + in + + let typeof t = + let tof = Texpr.Builder.fcall (eJsSyntax()) "typeof" [o] tstring p in + mk (TBinop (Ast.OpEq, tof, (mk (TConst (TString t)) tstring p))) tbool p + in + + (match t.eexpr with + (* generate simple typeof checks for basic types *) + | TTypeExpr (TClassDecl ({ cl_path = [],"String" })) -> Some (typeof "string") + | TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) -> Some (typeof "boolean") + | TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) -> Some (typeof "number") + | TTypeExpr (TAbstractDecl ({ a_path = [],"Int" })) when is_trivial o -> + (* generate typeof(o) == "number" && (o|0) === o check *) + let lhs = mk (TBinop (Ast.OpOr, o, mk (TConst (TInt Int32.zero)) tint p)) tint p in + let jscheck = Texpr.Builder.fcall (eJsSyntax()) "strictEq" [lhs;o] tbool p in + Some(mk (TBinop (Ast.OpBoolAnd, typeof "number", jscheck)) tbool p) + | TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) -> + (* generate (o instanceof Array) && o.__enum__ == null check *) + let iof = Texpr.Builder.fcall (eJsSyntax()) "instanceof" [o;t] tbool p in + let enum = mk (TField (o, FDynamic "__enum__")) (mk_mono()) p in + let null = mk (TConst TNull) (mk_mono()) p in + let not_enum = mk (TBinop (Ast.OpEq, enum, null)) tbool p in + Some (mk (TBinop (Ast.OpBoolAnd, iof, not_enum)) tbool p) + | TTypeExpr (TClassDecl cls) -> + if cls.cl_interface then + Some (Texpr.Builder.fcall (eJsBoot()) "__implements" [o;t] tbool p) + else + Some (Texpr.Builder.fcall (eJsSyntax()) "instanceof" [o;t] tbool p) + | _ -> + None) + | (["js"],"Boot"),"__downcastCheck",[o; {eexpr = TTypeExpr (TClassDecl cls) } as t] when ctx.com.platform = Js -> + if cls.cl_interface then + Some (Texpr.Builder.fcall (make_static_this c p) "__implements" [o;t] tbool p) + else + Some (Texpr.Builder.fcall (eJsSyntax()) "instanceof" [o;t] tbool p) + | (["cs" | "java"],"Lib"),("nativeArray"),[{ eexpr = TArrayDecl args } as edecl; _] + | (["haxe";"ds";"_Vector"],"Vector_Impl_"),("fromArrayCopy"),[{ eexpr = TArrayDecl args } as edecl] -> (try + let platf = match ctx.com.platform with + | Cs -> "cs" + | Java -> "java" + | _ -> raise Exit + in + let mpath = if field = "fromArrayCopy" then + (["haxe";"ds"],"Vector") + else + ([platf],"NativeArray") + in + + let m = ctx.g.do_load_module ctx mpath null_pos in + let main = List.find (function | TClassDecl _ | TAbstractDecl _ -> true | _ -> false) m.m_types in + let t = match follow edecl.etype, main with + | TInst({ cl_path = [],"Array" }, [t]), TClassDecl(cl) -> + TInst(cl,[t]) + | TInst({ cl_path = [],"Array" }, [t]), TAbstractDecl(a) -> + TAbstract(a,[t]) + | _ -> assert false + in + Some ({ (mk_untyped_call "__array__" p args) with etype = t }) + with | Exit -> + None) + | _ -> + api_inline2 ctx.com c field params p + +type in_local = { + i_var : tvar; + i_subst : tvar; + i_outside : bool; + i_abstract_this : bool; + mutable i_captured : bool; + mutable i_write : bool; + mutable i_read : int; + mutable i_called : int; + mutable i_force_temp : bool; + mutable i_default_value : texpr option; +} + +type var_inline_kind = + | VIInline + | VIInlineIfCalled + | VIDoNotInline + +let inline_default_config cf t = + (* type substitution on both class and function type parameters *) + let rec get_params c pl = + match c.cl_super with + | None -> c.cl_params, pl + | Some (csup,spl) -> + let spl = (match apply_params c.cl_params pl (TInst (csup,spl)) with + | TInst (_,pl) -> pl + | _ -> assert false + ) in + let ct, cpl = get_params csup spl in + c.cl_params @ ct, pl @ cpl + in + let rec loop t = match follow t with + | TInst({cl_kind = KTypeParameter tl},_) -> List.fold_left (fun (params',tl') (params,tl) -> (params @ params',tl @ tl')) ([],[]) (List.map loop tl) + | TInst (c,pl) -> get_params c pl + | _ -> ([],[]) + in + let tparams = loop t in + let pmonos = List.map (fun _ -> mk_mono()) cf.cf_params in + let tmonos = snd tparams @ pmonos in + let tparams = fst tparams @ cf.cf_params in + tparams <> [], apply_params tparams tmonos + +let inline_metadata e meta = + let inline_meta e meta = match meta with + | (Meta.Deprecated | Meta.Pure),_,_ -> mk (TMeta(meta,e)) e.etype e.epos + | _ -> e + in + List.fold_left inline_meta e meta + +class inline_state ctx ethis params cf f p = object(self) + val locals = Hashtbl.create 0 + val checker = create_affection_checker() + val mutable _inlined_vars = [] + val mutable _in_local_fun = false + val mutable _had_side_effect = false + val mutable _has_return_value = false + + method enter_local_fun = + let old = _in_local_fun in + _in_local_fun <- true; + (fun () -> _in_local_fun <- old) + + method in_local_fun = _in_local_fun + + method inlined_vars = _inlined_vars + + method had_side_effect = _had_side_effect + method set_side_effect = _had_side_effect <- true + + method has_return_value = _has_return_value + method set_return_value = _has_return_value <- true + + method private collect_modified_locals e = (snd checker) e + method might_be_affected e = (fst checker) e + + method declare v = + try + Hashtbl.find locals v.v_id + with Not_found -> + let v' = alloc_var (match v.v_kind with VUser _ -> VInlined | k -> k) v.v_name v.v_type v.v_pos in + v'.v_extra <- v.v_extra; + let i = { + i_var = v; + i_subst = v'; + i_outside = false; + i_abstract_this = Meta.has Meta.This v.v_meta; + i_captured = false; + i_write = false; + i_called = 0; + i_force_temp = false; + i_read = 0; + i_default_value = None; + } in + i.i_subst.v_meta <- List.filter (fun (m,_,_) -> m <> Meta.This) v.v_meta; + Hashtbl.add locals v.v_id i; + Hashtbl.add locals i.i_subst.v_id i; + i + + method read v = + let l = try + Hashtbl.find locals v.v_id + with Not_found -> + { + i_var = v; + i_subst = v; + i_outside = true; + i_abstract_this = Meta.has Meta.This v.v_meta; + i_captured = false; + i_write = false; + i_called = 0; + i_force_temp = false; + i_read = 0; + i_default_value = None; + } + in + if _in_local_fun then l.i_captured <- true; + l + + method private get_substitutions p = + (* + if variables are not written and used with a const value, let's substitute + with the actual value, either create a temp var + *) + let subst = ref PMap.empty in + let is_constant e = + let rec loop e = + match e.eexpr with + | TLocal _ + | TConst TThis (* not really, but should not be move inside a function body *) + -> raise Exit + | TObjectDecl _ | TArrayDecl _ -> raise Exit + | TField (_,FEnum _) + | TTypeExpr _ + | TConst _ -> () + | _ -> + Type.iter loop e + in + try loop e; true with Exit -> false + in + let rec is_writable e = + match e.eexpr with + | TField _ | TEnumParameter _ | TLocal _ | TArray _ -> true + | TCast(e1,None) -> is_writable e1 + | _ -> false + in + let vars = List.fold_left (fun acc (i,e) -> + let accept vik = + subst := PMap.add i.i_subst.v_id (vik,e) !subst; + acc + in + let reject () = + (* mark the replacement local for the analyzer *) + if (i.i_read + i.i_called) <= 1 && not i.i_write then + i.i_subst.v_kind <- VGenerated; + (i.i_subst,Some e) :: acc + in + if i.i_abstract_this && i.i_write then begin + if not (is_writable e) then error "Cannot modify the abstract value, store it into a local first" p; + accept VIInline + end else if i.i_force_temp || (i.i_captured && not (is_constant e)) then + reject() + else begin + let vik = match e.eexpr with + | TLocal _ when i.i_abstract_this -> VIInline + | TLocal _ | TConst _ -> + if not i.i_write then VIInline else VIDoNotInline + | TFunction _ -> + if i.i_write then error "Cannot modify a closure parameter inside inline method" p; + if i.i_read <= 1 then VIInline else VIInlineIfCalled + | _ -> + if not i.i_write && (i.i_read + i.i_called) <= 1 then VIInline else VIDoNotInline + in + match vik with + | VIInline -> accept vik + | VIDoNotInline -> reject() + | VIInlineIfCalled -> + (* "Accept" it so it is added to the substitutions. *) + ignore(accept vik); + if i.i_read > 1 then + (* If it is read more than once, we still have to reject because we need a local. *) + reject() + else + (* Otherwise we don't! *) + acc + end + ) [] _inlined_vars in + vars,!subst + + method initialize = + (* use default values for null/unset arguments *) + let rec loop acc pl al first = + match pl, al with + | _, [] -> + acc + | e :: pl, (v, opt) :: al -> + let l = self#declare v in + (* + if we pass a Null var to an inlined method that needs a T. + we need to force a local var to be created on some platforms. + *) + if ctx.com.config.pf_static && not (is_nullable v.v_type) && is_null e.etype then l.i_force_temp <- true; + (* + if we cast from Dynamic, create a local var as well to do the cast + once and allow DCE to perform properly. + *) + let dynamic_v = follow v.v_type == t_dynamic in + let dynamic_e = follow e.etype == t_dynamic in + let e = if dynamic_v <> dynamic_e then mk (TCast(e,None)) v.v_type e.epos else e in + let e = match e.eexpr, opt with + | TConst TNull , Some c -> c + | _ , Some c when (match c.eexpr with TConst TNull -> false | _ -> true) && (not ctx.com.config.pf_static || is_nullable v.v_type) -> + l.i_force_temp <- true; + l.i_default_value <- Some c; + e + | _ -> e + in + if has_side_effect e then begin + self#collect_modified_locals e; + _had_side_effect <- true; + l.i_force_temp <- true; + end; + (* We use a null expression because we only care about the type (for abstract casts). *) + if l.i_abstract_this then l.i_subst.v_extra <- Some ([],Some {e with eexpr = TConst TNull}); + loop ((l,e) :: acc) pl al false + | [], (v,opt) :: al -> + let l = self#declare v in + let e = match opt with + | None -> mk (TConst TNull) v.v_type v.v_pos + | Some e -> e + in + loop ((l,e) :: acc) [] al false + in + (* + Build the expr/var subst list + *) + let ethis = (match ethis.eexpr with TConst TSuper -> { ethis with eexpr = TConst TThis } | _ -> ethis) in + let vthis = alloc_var VInlined "_this" ethis.etype ethis.epos in + let args1 = (ethis :: params) in + let args2 = ((vthis,None) :: f.tf_args) in + let vars = loop [] args1 args2 true in + _inlined_vars <- vars; (* Order is reversed due to tail-recursion *) + vthis + + method finalize config e tl tret p = + let has_params,map_type = match config with Some config -> config | None -> inline_default_config cf ethis.etype in + if self#had_side_effect then List.iter (fun (l,e) -> + if self#might_be_affected e && not (ExtType.has_value_semantics e.etype) then l.i_force_temp <- true; + ) _inlined_vars; + let vars,subst = self#get_substitutions p in + let rec inline_params in_call in_assignment e = + match e.eexpr with + | TLocal v -> + begin try + let vik,e' = PMap.find v.v_id subst in + begin match vik with + | VIInline -> + begin match e'.eexpr with + (* If we inline a function expression, we have to duplicate its locals. *) + | TFunction _ -> Texpr.duplicate_tvars e' + | TCast(e1,None) when in_assignment -> e1 + | _ -> e' + end + | VIInlineIfCalled when in_call -> + (* We allow inlining function expressions into call-places. However, we have to substitute + their locals to avoid duplicate declarations. *) + Texpr.duplicate_tvars e' + | _ -> e + end + with Not_found -> + e + end + | TCall(e1,el) -> + let e1 = inline_params true false e1 in + let el = List.map (inline_params false false) el in + {e with eexpr = TCall(e1,el)} + | TBinop((OpAssign | OpAssignOp _ as op),e1,e2) -> + let e1 = inline_params false true e1 in + let e2 = inline_params false false e2 in + {e with eexpr = TBinop(op,e1,e2)} + | _ -> Type.map_expr (inline_params false false) e + in + let e = (if PMap.is_empty subst then e else inline_params false false e) in + let init = match vars with [] -> None | l -> Some l in + let md = ctx.curclass.cl_module.m_extra.m_display in + md.m_inline_calls <- (cf.cf_name_pos,{p with pmax = p.pmin + String.length cf.cf_name}) :: md.m_inline_calls; + let wrap e = + (* we can't mute the type of the expression because it is not correct to do so *) + let etype = if has_params then map_type e.etype else e.etype in + (* if the expression is "untyped" and we don't want to unify it accidentally ! *) + try (match follow e.etype with + | TMono _ | TInst ({cl_kind = KTypeParameter _ },_) -> + (match follow tret with + | TAbstract ({ a_path = [],"Void" },_) -> e + | _ -> raise (Unify_error [])) + | _ -> + type_eq (if ctx.com.config.pf_static then EqDoNotFollowNull else EqStrict) etype tret; + e) + with Unify_error _ -> + mk (TCast (e,None)) tret e.epos + in + let e = match init with + | None when not self#has_return_value -> + begin match e.eexpr with + | TBlock _ -> {e with etype = tret} + | _ -> mk (TBlock [e]) tret e.epos + end + | None -> + begin match e.eexpr with + | TBlock [e] -> wrap e + | _ -> wrap e + end + | Some vl -> + let el = DynArray.create () in + let add = DynArray.add el in + List.iter (fun (v,eo) -> + add (mk (TVar (v,eo)) ctx.t.tvoid e.epos); + ) vl; + List.iter (fun (l,e) -> match l.i_default_value with + | None -> () + | Some e -> add (Texpr.set_default ctx.com.basic l.i_subst e e.epos) + ) _inlined_vars; + begin match e.eexpr with + | TBlock el -> List.iter add el + | _ -> add e + end; + mk (TBlock (DynArray.to_list el)) tret e.epos + in + let e = inline_metadata e cf.cf_meta in + let e = Diagnostics.secure_generated_code ctx e in + if has_params then begin + let mt = map_type cf.cf_type in + let unify_func () = unify_raise ctx mt (TFun (tl,tret)) p in + (match follow ethis.etype with + | TAnon a -> (match !(a.a_status) with + | Statics {cl_kind = KAbstractImpl a } when Meta.has Meta.Impl cf.cf_meta -> + if cf.cf_name <> "_new" then begin + (* the first argument must unify with a_this for abstract implementation functions *) + let tb = (TFun(("",false,map_type a.a_this) :: (List.tl tl),tret)) in + unify_raise ctx mt tb p + end + | _ -> unify_func()) + | _ -> unify_func()); + end; + let vars = Hashtbl.create 0 in + let rec map_var v = + if not (Hashtbl.mem vars v.v_id) then begin + Hashtbl.add vars v.v_id (); + if not (self#read v).i_outside then begin + v.v_type <- map_type v.v_type; + match v.v_extra with + | Some(tl,Some e) -> + v.v_extra <- Some(tl,Some (map_expr_type e)); + | _ -> + () + end + end; + v + and map_expr_type e = Type.map_expr_type map_expr_type map_type map_var e in + map_expr_type e +end + +let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=false) force = + (* perform some specific optimization before we inline the call since it's not possible to detect at final optimization time *) + try + let cl = (match follow ethis.etype with + | TInst (c,_) -> c + | TAnon a -> (match !(a.a_status) with Statics c -> c | _ -> raise Exit) + | _ -> raise Exit + ) in + (match api_inline ctx cl cf.cf_name params p with + | None -> raise Exit + | Some e -> Some e) + with Exit -> + let state = new inline_state ctx ethis params cf f p in + let vthis = state#initialize in + let opt f = function + | None -> None + | Some e -> Some (f e) + in + let in_loop = ref false in + let return_type t el = + (* If the function return is Dynamic or Void, stick to it. *) + if follow f.tf_type == t_dynamic || ExtType.is_void (follow f.tf_type) then f.tf_type + (* If the expression is Void, find common type of its branches. *) + else if ExtType.is_void t then unify_min ctx el + else t + in + let map_pos = if self_calling_closure then (fun e -> e) else (fun e -> { e with epos = p }) in + let rec map term in_call e = + let po = e.epos in + let e = map_pos e in + match e.eexpr with + | TLocal v -> + let l = state#read v in + let i = if !in_loop then 2 else 1 in + if in_call then + l.i_called <- l.i_called + i + else + l.i_read <- l.i_read + i; + let e = { e with eexpr = TLocal l.i_subst } in + if l.i_abstract_this then mk (TCast(e,None)) v.v_type e.epos else e + | TConst TThis -> + let l = state#read vthis in + l.i_read <- l.i_read + (if !in_loop then 2 else 1); + { e with eexpr = TLocal l.i_subst } + | TVar (v,eo) -> + { e with eexpr = TVar ((state#declare v).i_subst,opt (map false false) eo)} + | TReturn eo when not state#in_local_fun -> + if not term then error "Cannot inline a not final return" po; + (match eo with + | None -> mk (TConst TNull) f.tf_type p + | Some e -> + state#set_return_value; + map term false e) + | TFor (v,e1,e2) -> + let i = state#declare v in + let e1 = map false false e1 in + let old = !in_loop in + in_loop := true; + let e2 = map false false e2 in + in_loop := old; + { e with eexpr = TFor (i.i_subst,e1,e2) } + | TWhile (cond,eloop,flag) -> + let cond = map false false cond in + let old = !in_loop in + in_loop := true; + let eloop = map false false eloop in + in_loop := old; + { e with eexpr = TWhile (cond,eloop,flag) } + | TSwitch (e1,cases,def) when term -> + let term = term && (def <> None || is_exhaustive e1) in + let cases = List.map (fun (el,e) -> + let el = List.map (map false false) el in + el, map term false e + ) cases in + let def = opt (map term false) def in + let t = return_type e.etype ((List.map snd cases) @ (match def with None -> [] | Some e -> [e])) in + { e with eexpr = TSwitch (map false false e1,cases,def); etype = t } + | TTry (e1,catches) -> + let t = if not term then e.etype else return_type e.etype (e1::List.map snd catches) in + { e with eexpr = TTry (map term false e1,List.map (fun (v,e) -> + let lv = (state#declare v).i_subst in + let e = map term false e in + lv,e + ) catches); etype = t } + | TBlock l -> + let old = save_locals ctx in + let t = ref e.etype in + let rec has_term_return e = + let rec loop e = + let r = match e.eexpr with + | TReturn _ -> true + | TFunction _ -> false + | TIf (_,_,None) | TSwitch (_,_,None) | TFor _ | TWhile (_,_,NormalWhile) -> false (* we might not enter this code at all *) + | TTry (a, catches) -> List.for_all has_term_return (a :: List.map snd catches) + | TIf (cond,a,Some b) -> has_term_return cond || (has_term_return a && has_term_return b) + | TSwitch (cond,cases,Some def) -> has_term_return cond || List.for_all has_term_return (def :: List.map snd cases) + | TBinop (OpBoolAnd,a,b) -> has_term_return a && has_term_return b + | _ -> Type.iter loop e; false + in + if r then raise Exit + in + try loop e; false with Exit -> true + in + let rec loop = function + | [] when term -> + t := mk_mono(); + [mk (TConst TNull) (!t) p] + | [] -> [] + | [e] -> + let e = map term false e in + if term then t := e.etype; + [e] + | ({ eexpr = TIf (cond,e1,None) } as e) :: l when term && has_term_return e1 -> + loop [{ e with eexpr = TIf (cond,e1,Some (mk (TBlock l) e.etype e.epos)); epos = punion e.epos (match List.rev l with e :: _ -> e.epos | [] -> assert false) }] + | e :: l -> + let e = map false false e in + e :: loop l + in + let l = loop l in + old(); + { e with eexpr = TBlock l; etype = !t } + | TIf (econd,eif,Some eelse) when term -> + let econd = map false false econd in + let eif = map term false eif in + let eelse = map term false eelse in + let t = return_type e.etype [eif;eelse] in + { e with eexpr = TIf(econd,eif,Some eelse); etype = t } + | TParenthesis e1 -> + let e1 = map term in_call e1 in + mk (TParenthesis e1) e1.etype e.epos + | TUnop ((Increment|Decrement) as op,flag,({ eexpr = TLocal v } as e1)) -> + state#set_side_effect; + let l = state#read v in + l.i_write <- true; + {e with eexpr = TUnop(op,flag,{e1 with eexpr = TLocal l.i_subst})} + | TBinop ((OpAssign | OpAssignOp _) as op,({ eexpr = TLocal v } as e1),e2) -> + state#set_side_effect; + let l = state#read v in + l.i_write <- true; + let e2 = map false false e2 in + {e with eexpr = TBinop(op,{e1 with eexpr = TLocal l.i_subst},e2)} + | TObjectDecl fl -> + let fl = List.map (fun (s,e) -> s,map false false e) fl in + begin match follow e.etype with + | TAnon an when (match !(an.a_status) with Const -> true | _ -> false) -> + {e with eexpr = TObjectDecl fl; etype = TAnon { an with a_status = ref Closed}} + | _ -> + {e with eexpr = TObjectDecl fl} + end + | TFunction f -> + let old = save_locals ctx in + let args = List.map (function(v,c) -> (state#declare v).i_subst, c) f.tf_args in + let restore = state#enter_local_fun in + let expr = map false false f.tf_expr in + restore(); + old(); + { e with eexpr = TFunction { tf_args = args; tf_expr = expr; tf_type = f.tf_type } } + | TCall({eexpr = TConst TSuper; etype = t},el) -> + state#set_side_effect; + begin match follow t with + | TInst({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction tf})} as cf)} as c,_) -> + begin match type_inline_ctor ctx c cf tf ethis el po with + | Some e -> map term false e + | None -> error "Could not inline super constructor call" po + end + | _ -> error "Cannot inline function containing super" po + end + | TCall(e1,el) -> + state#set_side_effect; + let e1 = map false true e1 in + let el = List.map (map false false) el in + {e with eexpr = TCall(e1,el)} + | TConst TSuper -> + error "Cannot inline function containing super" po + | TMeta((Meta.Ast,_,_) as m,e1) when term -> + (* Special case for @:ast-wrapped TSwitch nodes: If the recursion alters the type of the TSwitch node, we also want + to alter the type of the TMeta node. *) + let e1 = map term in_call e1 in + {e with eexpr = TMeta(m,e1); etype = e1.etype} + | TMeta(m,e1) -> + let e1 = map term in_call e1 in + {e with eexpr = TMeta(m,e1)} + | TNew _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> + state#set_side_effect; + Type.map_expr (map false false) e + | _ -> + Type.map_expr (map false false) e + in + let e = map true false f.tf_expr in + let tl = List.map (fun e -> "",false,e.etype) params in + let e = state#finalize config e tl tret p in + if Meta.has (Meta.Custom ":inlineDebug") ctx.meta then begin + let se t = s_expr_pretty true t true (s_type (print_context())) in + print_endline (Printf.sprintf "Inline %s:\n\tArgs: %s\n\tExpr: %s\n\tResult: %s" + cf.cf_name + (String.concat "" (List.map (fun (i,e) -> Printf.sprintf "\n\t\t%s<%i> = %s" (i.i_subst.v_name) (i.i_subst.v_id) (se "\t\t" e)) state#inlined_vars)) + (se "\t" f.tf_expr) + (se "\t" e) + ); + end; + Some e + +(* Same as type_inline, but modifies the function body to add field inits *) +and type_inline_ctor ctx c cf tf ethis el po = + let field_inits = + let cparams = List.map snd c.cl_params in + let ethis = mk (TConst TThis) (TInst (c,cparams)) c.cl_pos in + let el = List.fold_left (fun acc cf -> + match cf.cf_kind,cf.cf_expr with + | Var _,Some e -> + let lhs = mk (TField(ethis,FInstance (c,cparams,cf))) cf.cf_type e.epos in + let eassign = mk (TBinop(OpAssign,lhs,e)) cf.cf_type e.epos in + eassign :: acc + | _ -> acc + ) [] c.cl_ordered_fields in + List.rev el + in + let tf = + if field_inits = [] then tf + else + let bl = match tf.tf_expr with {eexpr = TBlock b } -> b | x -> [x] in + {tf with tf_expr = mk (TBlock (field_inits @ bl)) ctx.t.tvoid c.cl_pos} + in + type_inline ctx cf tf ethis el ctx.t.tvoid None po true diff --git a/src/optimization/inlineConstructors.ml b/src/optimization/inlineConstructors.ml index b80105b14d4..27f73bff100 100644 --- a/src/optimization/inlineConstructors.ml +++ b/src/optimization/inlineConstructors.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -98,7 +98,7 @@ let inline_constructors ctx e = | IOKCtor(_,isextern,vars) -> List.iter (fun v -> if v.v_id < 0 then cancel_v v p) vars; if isextern then begin - display_error ctx "Extern constructor could not be inlined" io.io_pos; + display_error ctx "Forced inline constructor could not be inlined" io.io_pos; display_error ctx "Cancellation happened here" p; end | _ -> () @@ -150,7 +150,7 @@ let inline_constructors ctx e = PMap.find s io.io_fields in let alloc_io_field_full (io:inline_object) (fname:string) (constexpr_option:texpr option) (t:t) (p:pos) : inline_var = - let v = alloc_var fname t p in + let v = alloc_var VInlined fname t p in let iv = add v (IVKField (io,fname,constexpr_option)) in io.io_fields <- PMap.add fname iv io.io_fields; iv @@ -165,7 +165,7 @@ let inline_constructors ctx e = if i < 0 then "n" ^ (string_of_int (-i)) else (string_of_int i) in - let is_extern_ctor c cf = c.cl_extern || Meta.has Meta.Extern cf.cf_meta in + let is_extern_ctor c cf = c.cl_extern || has_class_field_flag cf CfExtern in let make_expr_for_list (el:texpr list) (t:t) (p:pos): texpr = match el with | [] -> mk (TBlock[]) ctx.t.tvoid p | [e] -> e @@ -174,7 +174,7 @@ let inline_constructors ctx e = let make_expr_for_rev_list (el:texpr list) (t:t) (p:pos) : texpr = make_expr_for_list (List.rev el) t p in let current_io_id = ref 0 in let increment_io_id e = match e.eexpr with - | TObjectDecl _ | TArrayDecl _ | TNew _ -> incr current_io_id + | TObjectDecl _ | TArrayDecl _ | TNew _ | (TMeta((Meta.Inline,_,_),{eexpr = TNew _})) -> incr current_io_id | _ -> () in let rec analyze_aliases (seen_ctors:tclass_field list) (captured:bool) (is_lvalue:bool) (e:texpr) : inline_var option = @@ -221,6 +221,7 @@ let inline_constructors ctx e = in match e.eexpr, e.etype with | TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction tf})} as cf)} as c,tl,pl),_ + | TMeta((Meta.Inline,_,_),{eexpr = TNew({ cl_constructor = Some ({cf_expr = Some ({eexpr = TFunction tf})} as cf)} as c,tl,pl)}),_ when captured && not (List.memq cf seen_ctors) -> begin let io_id = !current_io_id in @@ -229,7 +230,7 @@ let inline_constructors ctx e = begin match e.eexpr with | TConst _ -> loop (vs, decls, e::es) el | _ -> - let v = alloc_var "arg" e.etype e.epos in + let v = alloc_var VGenerated "arg" e.etype e.epos in let decle = mk (TVar(v, Some e)) ctx.t.tvoid e.epos in let io_id_start = !current_io_id in ignore(analyze_aliases true decle); @@ -241,11 +242,12 @@ let inline_constructors ctx e = in let argvs, argvdecls, pl = loop ([],[],[]) pl in let _, cname = c.cl_path in - let v = alloc_var ("inl"^cname) e.etype e.epos in - match Optimizer.type_inline_ctor ctx c cf tf (mk (TLocal v) (TInst (c,tl)) e.epos) pl e.epos with + let v = alloc_var VGenerated ("inl"^cname) e.etype e.epos in + match Inline.type_inline_ctor ctx c cf tf (mk (TLocal v) (TInst (c,tl)) e.epos) pl e.epos with | Some inlined_expr -> let has_untyped = (Meta.has Meta.HasUntyped cf.cf_meta) in - let io = mk_io (IOKCtor(cf,is_extern_ctor c cf,argvs)) io_id inlined_expr ~has_untyped:has_untyped in + let forced = is_extern_ctor c cf || (match e.eexpr with TMeta _ -> true | _ -> false) in + let io = mk_io (IOKCtor(cf,forced,argvs)) io_id inlined_expr ~has_untyped:has_untyped in let rec loop (c:tclass) (tl:t list) = let apply = apply_params c.cl_params tl in List.iter (fun cf -> @@ -273,7 +275,7 @@ let inline_constructors ctx e = | TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some _} as cf)} as c,_,pl),_ when is_extern_ctor c cf -> error "Extern constructor could not be inlined" e.epos; | TObjectDecl fl, _ when captured && fl <> [] && List.for_all (fun((s,_,_),_) -> Lexer.is_valid_identifier s) fl -> - let v = alloc_var "inlobj" e.etype e.epos in + let v = alloc_var VGenerated "inlobj" e.etype e.epos in let ev = mk (TLocal v) v.v_type e.epos in let el = List.map (fun ((s,_,_),e) -> let ef = mk (TField(ev,FDynamic s)) e.etype e.epos in @@ -290,7 +292,7 @@ let inline_constructors ctx e = Some iv | TArrayDecl el, TInst(_, [elemtype]) when captured -> let len = List.length el in - let v = alloc_var "inlarr" e.etype e.epos in + let v = alloc_var VGenerated "inlarr" e.etype e.epos in let ev = mk (TLocal v) v.v_type e.epos in let el = List.mapi (fun i e -> let ef = mk (TArray(ev,(mk (TConst(TInt (Int32.of_int i))) e.etype e.epos))) elemtype e.epos in @@ -387,7 +389,7 @@ let inline_constructors ctx e = ([Type.map_expr f e], None) in match e.eexpr with - | TObjectDecl _ | TArrayDecl _ | TNew _ -> + | TObjectDecl _ | TArrayDecl _ | TNew _ | (TMeta((Meta.Inline,_,_),{eexpr = TNew _})) -> begin try let io = get_io !current_io_id in if io.io_cancelled then begin @@ -509,7 +511,7 @@ let inline_constructors ctx e = let rec get_pretty_name iv = match iv.iv_kind with | IVKField(io,fname,None) -> begin try - let is_user_variable iv = Meta.has Meta.UserVariable iv.iv_var.v_meta in + let is_user_variable iv = match iv.iv_var.v_kind with VUser _ | VInlined -> true | _ -> false in let iv = List.find is_user_variable io.io_aliases in (get_pretty_name iv) ^ "_" ^ fname; with Not_found -> diff --git a/src/optimization/optimizer.ml b/src/optimization/optimizer.ml index 0ffed6b721e..f5a8d703b5d 100644 --- a/src/optimization/optimizer.ml +++ b/src/optimization/optimizer.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -24,875 +24,7 @@ open Typecore open OptimizerTexpr open Error open Globals - -(* ---------------------------------------------------------------------- *) -(* API OPTIMIZATIONS *) - -let mk_untyped_call name p params = - { - eexpr = TCall({ eexpr = TIdent name; etype = t_dynamic; epos = p }, params); - etype = t_dynamic; - epos = p; - } - -let api_inline2 com c field params p = - match c.cl_path, field, params with - | ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] -> (match com.platform with - | Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) -> - (* We don't want to optimize enums from external sources; as they might change unexpectedly *) - (* and since native C# enums don't have the concept of index - they have rather a value, *) - (* which can't be mapped to a native API - this kind of substitution is dangerous *) - None - | _ -> - Some (mk (TConst (TInt (Int32.of_int f.ef_index))) com.basic.tint p)) - | ([],"Type"),"enumIndex",[{ eexpr = TCall({ eexpr = TField (_,FEnum (en,f)) },pl) }] when List.for_all (fun e -> not (has_side_effect e)) pl -> - (match com.platform with - | Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) -> - (* see comment above *) - None - | _ -> - Some (mk (TConst (TInt (Int32.of_int f.ef_index))) com.basic.tint p)) - | ([],"Std"),"int",[{ eexpr = TConst (TInt _) } as e] -> - Some { e with epos = p } - | ([],"String"),"fromCharCode",[{ eexpr = TConst (TInt i) }] when i > 0l && i < 128l -> - Some (mk (TConst (TString (String.make 1 (char_of_int (Int32.to_int i))))) com.basic.tstring p) - | ([],"Std"),"string",[{ eexpr = TCast ({ eexpr = TConst c } as e, None)}] - | ([],"Std"),"string",[{ eexpr = TConst c } as e] -> - (match c with - | TString s -> - Some { e with epos = p } - | TInt i -> - Some { eexpr = TConst (TString (Int32.to_string i)); epos = p; etype = com.basic.tstring } - | TBool b -> - Some { eexpr = TConst (TString (if b then "true" else "false")); epos = p; etype = com.basic.tstring } - | _ -> - None) - | ([],"Std"),"string",[{ eexpr = TIf (_,{ eexpr = TConst (TString _)},Some { eexpr = TConst (TString _) }) } as e] -> - Some e - | ([],"Std"),"string",[{ eexpr = TLocal v | TField({ eexpr = TLocal v },_) } as ev] when (com.platform = Js || com.platform = Flash) && not (Meta.has Meta.CompilerGenerated v.v_meta) -> - let pos = ev.epos in - let stringv() = - let to_str = mk (TBinop (Ast.OpAdd, mk (TConst (TString "")) com.basic.tstring pos, ev)) com.basic.tstring pos in - if com.platform = Js || is_nullable ev.etype then - let chk_null = mk (TBinop (Ast.OpEq, ev, mk (TConst TNull) t_dynamic pos)) com.basic.tbool pos in - mk (TIf (chk_null, mk (TConst (TString "null")) com.basic.tstring pos, Some to_str)) com.basic.tstring pos - else - to_str - in - (match follow ev.etype with - | TInst ({ cl_path = [],"String" }, []) -> - Some (stringv()) - | TAbstract ({ a_path = [],"Float" }, []) -> - Some (stringv()) - | TAbstract ({ a_path = [],"Int" }, []) -> - Some (stringv()) - | TAbstract ({ a_path = [],"UInt" }, []) -> - Some (stringv()) - | TAbstract ({ a_path = [],"Bool" }, []) -> - Some (stringv()) - | _ -> - None) - | ([],"Std"),"int",[{ eexpr = TConst (TFloat f) }] -> - let f = float_of_string f in - (match classify_float f with - | FP_infinite | FP_nan -> - None - | _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int +. 1. -> - None (* out range, keep platform-specific behavior *) - | _ -> - Some { eexpr = TConst (TInt (Int32.of_float f)); etype = com.basic.tint; epos = p }) - | ([],"Math"),"ceil",[{ eexpr = TConst (TFloat f) }] -> - let f = float_of_string f in - (match classify_float f with - | FP_infinite | FP_nan -> - None - | _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int -> - None (* out range, keep platform-specific behavior *) - | _ -> - Some { eexpr = TConst (TInt (Int32.of_float (ceil f))); etype = com.basic.tint; epos = p }) - | ([],"Math"),"floor",[{ eexpr = TConst (TFloat f) }] -> - let f = float_of_string f in - (match classify_float f with - | FP_infinite | FP_nan -> - None - | _ when f <= Int32.to_float Int32.min_int || f >= Int32.to_float Int32.max_int +. 1. -> - None (* out range, keep platform-specific behavior *) - | _ -> - Some { eexpr = TConst (TInt (Int32.of_float (floor f))); etype = com.basic.tint; epos = p }) - | (["cs"],"Lib"),("fixed" | "checked" | "unsafe"),[e] -> - Some (mk_untyped_call ("__" ^ field ^ "__") p [e]) - | (["cs"],"Lib"),("lock"),[obj;block] -> - Some (mk_untyped_call ("__lock__") p [obj;mk_block block]) - | (["java"],"Lib"),("lock"),[obj;block] -> - Some (mk_untyped_call ("__lock__") p [obj;mk_block block]) - | _ -> - None - -let api_inline ctx c field params p = match c.cl_path, field, params with - | ([],"Std"),"is",[o;t] | (["js"],"Boot"),"__instanceof",[o;t] when ctx.com.platform = Js -> - let mk_local ctx n t pos = mk (TIdent n) t pos in - - let tstring = ctx.com.basic.tstring in - let tbool = ctx.com.basic.tbool in - let tint = ctx.com.basic.tint in - - let is_trivial e = - match e.eexpr with - | TConst _ | TLocal _ -> true - | _ -> false - in - - let typeof t = - let tof = mk (TIdent "__typeof__") (tfun [o.etype] tstring) p in - let tof = mk (TCall (tof, [o])) tstring p in - mk (TBinop (Ast.OpEq, tof, (mk (TConst (TString t)) tstring p))) tbool p - in - - (match t.eexpr with - (* generate simple typeof checks for basic types *) - | TTypeExpr (TClassDecl ({ cl_path = [],"String" })) -> Some (typeof "string") - | TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) -> Some (typeof "boolean") - | TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) -> Some (typeof "number") - | TTypeExpr (TAbstractDecl ({ a_path = [],"Int" })) when is_trivial o -> - (* generate typeof(o) == "number" && (o|0) === o check *) - let teq = mk_local ctx "__strict_eq__" (tfun [tint; tint] tbool) p in - let lhs = mk (TBinop (Ast.OpOr, o, mk (TConst (TInt Int32.zero)) tint p)) tint p in - let jscheck = mk (TCall (teq, [lhs; o])) tbool p in - Some(mk (TBinop (Ast.OpBoolAnd, typeof "number", jscheck)) tbool p) - | TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) -> - (* generate (o instanceof Array) && o.__enum__ == null check *) - let iof = mk_local ctx "__instanceof__" (tfun [o.etype;t.etype] tbool) p in - let iof = mk (TCall (iof, [o; t])) tbool p in - let enum = mk (TField (o, FDynamic "__enum__")) (mk_mono()) p in - let null = mk (TConst TNull) (mk_mono()) p in - let not_enum = mk (TBinop (Ast.OpEq, enum, null)) tbool p in - Some (mk (TBinop (Ast.OpBoolAnd, iof, not_enum)) tbool p) - | _ -> - None) - | (["cs" | "java"],"Lib"),("nativeArray"),[{ eexpr = TArrayDecl args } as edecl; _] - | (["haxe";"ds";"_Vector"],"Vector_Impl_"),("fromArrayCopy"),[{ eexpr = TArrayDecl args } as edecl] -> (try - let platf = match ctx.com.platform with - | Cs -> "cs" - | Java -> "java" - | _ -> raise Exit - in - let mpath = if field = "fromArrayCopy" then - (["haxe";"ds"],"Vector") - else - ([platf],"NativeArray") - in - - let m = ctx.g.do_load_module ctx mpath null_pos in - let main = List.find (function | TClassDecl _ | TAbstractDecl _ -> true | _ -> false) m.m_types in - let t = match follow edecl.etype, main with - | TInst({ cl_path = [],"Array" }, [t]), TClassDecl(cl) -> - TInst(cl,[t]) - | TInst({ cl_path = [],"Array" }, [t]), TAbstractDecl(a) -> - TAbstract(a,[t]) - | _ -> assert false - in - Some ({ (mk_untyped_call "__array__" p args) with etype = t }) - with | Exit -> - None) - | _ -> - api_inline2 ctx.com c field params p - -(* ---------------------------------------------------------------------- *) -(* INLINING *) - -type in_local = { - i_var : tvar; - i_subst : tvar; - i_outside : bool; - i_abstract_this : bool; - mutable i_captured : bool; - mutable i_write : bool; - mutable i_read : int; - mutable i_force_temp : bool; -} - -let inline_default_config cf t = - (* type substitution on both class and function type parameters *) - let rec get_params c pl = - match c.cl_super with - | None -> c.cl_params, pl - | Some (csup,spl) -> - let spl = (match apply_params c.cl_params pl (TInst (csup,spl)) with - | TInst (_,pl) -> pl - | _ -> assert false - ) in - let ct, cpl = get_params csup spl in - c.cl_params @ ct, pl @ cpl - in - let tparams = (match follow t with - | TInst (c,pl) -> get_params c pl - | _ -> ([],[])) - in - let pmonos = List.map (fun _ -> mk_mono()) cf.cf_params in - let tmonos = snd tparams @ pmonos in - let tparams = fst tparams @ cf.cf_params in - tparams <> [], apply_params tparams tmonos - -let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=false) force = - (* perform some specific optimization before we inline the call since it's not possible to detect at final optimization time *) - try - let cl = (match follow ethis.etype with - | TInst (c,_) -> c - | TAnon a -> (match !(a.a_status) with Statics c -> c | _ -> raise Exit) - | _ -> raise Exit - ) in - (match api_inline ctx cl cf.cf_name params p with - | None -> raise Exit - | Some e -> Some e) - with Exit -> - let has_params,map_type = match config with Some config -> config | None -> inline_default_config cf ethis.etype in - (* locals substitution *) - let locals = Hashtbl.create 0 in - let local v = - try - Hashtbl.find locals v.v_id - with Not_found -> - let v' = alloc_var v.v_name v.v_type v.v_pos in - v'.v_extra <- v.v_extra; - let i = { - i_var = v; - i_subst = v'; - i_outside = false; - i_abstract_this = Meta.has Meta.This v.v_meta; - i_captured = false; - i_write = false; - i_force_temp = false; - i_read = 0; - } in - i.i_subst.v_meta <- List.filter (fun (m,_,_) -> m <> Meta.This) v.v_meta; - Hashtbl.add locals v.v_id i; - Hashtbl.add locals i.i_subst.v_id i; - i - in - let in_local_fun = ref false in - let read_local v = - let l = try - Hashtbl.find locals v.v_id - with Not_found -> - { - i_var = v; - i_subst = v; - i_outside = true; - i_abstract_this = Meta.has Meta.This v.v_meta; - i_captured = false; - i_write = false; - i_force_temp = false; - i_read = 0; - } - in - if !in_local_fun then l.i_captured <- true; - l - in - (* use default values for null/unset arguments *) - let rec loop pl al first = - match pl, al with - | _, [] -> [] - | e :: pl, (v, opt) :: al -> - (* - if we pass a Null var to an inlined method that needs a T. - we need to force a local var to be created on some platforms. - *) - if ctx.com.config.pf_static && not (is_nullable v.v_type) && is_null e.etype then (local v).i_force_temp <- true; - (* - if we cast from Dynamic, create a local var as well to do the cast - once and allow DCE to perform properly. - *) - let e = if follow v.v_type != t_dynamic && follow e.etype == t_dynamic then mk (TCast(e,None)) v.v_type e.epos else e in - (match e.eexpr, opt with - | TConst TNull , Some c -> mk (TConst c) v.v_type e.epos - (* - This is really weird and should be reviewed again. The problem is that we cannot insert a TCast here because - the abstract `this` value could be written to, which is not possible if it is wrapped in a cast. - - The original problem here is that we do not generate a temporary variable and thus mute the type of the - `this` variable, which leads to unification errors down the line. See issues #2236 and #3713. - *) - (* | _ when first && (Meta.has Meta.Impl cf.cf_meta) -> {e with etype = v.v_type} *) - | _ -> e) :: loop pl al false - | [], (v,opt) :: al -> - (mk (TConst (match opt with None -> TNull | Some c -> c)) v.v_type p) :: loop [] al false - in - (* - Build the expr/var subst list - *) - let ethis = (match ethis.eexpr with TConst TSuper -> { ethis with eexpr = TConst TThis } | _ -> ethis) in - let vthis = alloc_var "_this" ethis.etype ethis.epos in - let might_be_affected,collect_modified_locals = create_affection_checker() in - let had_side_effect = ref false in - let inlined_vars = List.map2 (fun e (v,_) -> - let l = local v in - if has_side_effect e then begin - collect_modified_locals e; - had_side_effect := true; - l.i_force_temp <- true; - end; - if l.i_abstract_this then l.i_subst.v_extra <- Some ([],Some e); - l, e - ) (ethis :: loop params f.tf_args true) ((vthis,None) :: f.tf_args) in - let inlined_vars = List.rev inlined_vars in - (* - here, we try to eliminate final returns from the expression tree. - However, this is not entirely correct since we don't yet correctly propagate - the type of returned expressions upwards ("return" expr itself being Dynamic). - - We also substitute variables with fresh ones that might be renamed at later stage. - *) - let opt f = function - | None -> None - | Some e -> Some (f e) - in - let has_vars = ref false in - let in_loop = ref false in - let cancel_inlining = ref false in - let has_return_value = ref false in - let return_type t el = - (* If the function return is Dynamic or Void, stick to it. *) - if follow f.tf_type == t_dynamic || ExtType.is_void (follow f.tf_type) then f.tf_type - (* If the expression is Void, find common type of its branches. *) - else if ExtType.is_void t then unify_min ctx el - else t - in - let map_pos = if self_calling_closure then (fun e -> e) else (fun e -> { e with epos = p }) in - let rec map term e = - let po = e.epos in - let e = map_pos e in - match e.eexpr with - | TLocal v -> - let l = read_local v in - l.i_read <- l.i_read + (if !in_loop then 2 else 1); - (* never inline a function which contain a delayed macro because its bound - to its variables and not the calling method *) - if v.v_name = "$__delayed_call__" then cancel_inlining := true; - let e = { e with eexpr = TLocal l.i_subst } in - if l.i_abstract_this then mk (TCast(e,None)) v.v_type e.epos else e - | TConst TThis -> - let l = read_local vthis in - l.i_read <- l.i_read + (if !in_loop then 2 else 1); - { e with eexpr = TLocal l.i_subst } - | TVar (v,eo) -> - has_vars := true; - { e with eexpr = TVar ((local v).i_subst,opt (map false) eo)} - | TReturn eo when not !in_local_fun -> - if not term then error "Cannot inline a not final return" po; - (match eo with - | None -> mk (TConst TNull) f.tf_type p - | Some e -> - has_return_value := true; - map term e) - | TFor (v,e1,e2) -> - let i = local v in - let e1 = map false e1 in - let old = !in_loop in - in_loop := true; - let e2 = map false e2 in - in_loop := old; - { e with eexpr = TFor (i.i_subst,e1,e2) } - | TWhile (cond,eloop,flag) -> - let cond = map false cond in - let old = !in_loop in - in_loop := true; - let eloop = map false eloop in - in_loop := old; - { e with eexpr = TWhile (cond,eloop,flag) } - | TSwitch (e1,cases,def) when term -> - let term = term && (def <> None || is_exhaustive e1) in - let cases = List.map (fun (el,e) -> - let el = List.map (map false) el in - el, map term e - ) cases in - let def = opt (map term) def in - let t = return_type e.etype ((List.map snd cases) @ (match def with None -> [] | Some e -> [e])) in - { e with eexpr = TSwitch (map false e1,cases,def); etype = t } - | TTry (e1,catches) -> - let t = if not term then e.etype else return_type e.etype (e1::List.map snd catches) in - { e with eexpr = TTry (map term e1,List.map (fun (v,e) -> - let lv = (local v).i_subst in - let e = map term e in - lv,e - ) catches); etype = t } - | TBlock l -> - let old = save_locals ctx in - let t = ref e.etype in - let rec has_term_return e = - let rec loop e = - let r = match e.eexpr with - | TReturn _ -> true - | TFunction _ -> false - | TIf (_,_,None) | TSwitch (_,_,None) | TFor _ | TWhile (_,_,NormalWhile) -> false (* we might not enter this code at all *) - | TTry (a, catches) -> List.for_all has_term_return (a :: List.map snd catches) - | TIf (cond,a,Some b) -> has_term_return cond || (has_term_return a && has_term_return b) - | TSwitch (cond,cases,Some def) -> has_term_return cond || List.for_all has_term_return (def :: List.map snd cases) - | TBinop (OpBoolAnd,a,b) -> has_term_return a && has_term_return b - | _ -> Type.iter loop e; false - in - if r then raise Exit - in - try loop e; false with Exit -> true - in - let rec loop = function - | [] when term -> - t := mk_mono(); - [mk (TConst TNull) (!t) p] - | [] -> [] - | [e] -> - let e = map term e in - if term then t := e.etype; - [e] - | ({ eexpr = TIf (cond,e1,None) } as e) :: l when term && has_term_return e1 -> - loop [{ e with eexpr = TIf (cond,e1,Some (mk (TBlock l) e.etype e.epos)); epos = punion e.epos (match List.rev l with e :: _ -> e.epos | [] -> assert false) }] - | e :: l -> - let e = map false e in - e :: loop l - in - let l = loop l in - old(); - { e with eexpr = TBlock l; etype = !t } - | TIf (econd,eif,Some eelse) when term -> - let econd = map false econd in - let eif = map term eif in - let eelse = map term eelse in - let t = return_type e.etype [eif;eelse] in - { e with eexpr = TIf(econd,eif,Some eelse); etype = t } - | TParenthesis e1 -> - let e1 = map term e1 in - mk (TParenthesis e1) e1.etype e.epos - | TUnop ((Increment|Decrement) as op,flag,({ eexpr = TLocal v } as e1)) -> - had_side_effect := true; - let l = read_local v in - l.i_write <- true; - {e with eexpr = TUnop(op,flag,{e1 with eexpr = TLocal l.i_subst})} - | TBinop ((OpAssign | OpAssignOp _) as op,({ eexpr = TLocal v } as e1),e2) -> - had_side_effect := true; - let l = read_local v in - l.i_write <- true; - let e2 = map false e2 in - {e with eexpr = TBinop(op,{e1 with eexpr = TLocal l.i_subst},e2)} - | TObjectDecl fl -> - let fl = List.map (fun (s,e) -> s,map false e) fl in - begin match follow e.etype with - | TAnon an when (match !(an.a_status) with Const -> true | _ -> false) -> - {e with eexpr = TObjectDecl fl; etype = TAnon { an with a_status = ref Closed}} - | _ -> - {e with eexpr = TObjectDecl fl} - end - | TFunction f -> - (match f.tf_args with [] -> () | _ -> has_vars := true); - let old = save_locals ctx and old_fun = !in_local_fun in - let args = List.map (function(v,c) -> (local v).i_subst, c) f.tf_args in - in_local_fun := true; - let expr = map false f.tf_expr in - in_local_fun := old_fun; - old(); - { e with eexpr = TFunction { tf_args = args; tf_expr = expr; tf_type = f.tf_type } } - | TCall({eexpr = TConst TSuper; etype = t},el) -> - had_side_effect := true; - begin match follow t with - | TInst({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction tf})} as cf)} as c,_) -> - begin match type_inline_ctor ctx c cf tf ethis el po with - | Some e -> map term e - | None -> error "Could not inline super constructor call" po - end - | _ -> error "Cannot inline function containing super" po - end - | TConst TSuper -> - error "Cannot inline function containing super" po - | TMeta(m,e1) -> - let e1 = map term e1 in - {e with eexpr = TMeta(m,e1)} - | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> - had_side_effect := true; - Type.map_expr (map false) e - | _ -> - Type.map_expr (map false) e - in - let e = map true f.tf_expr in - if !had_side_effect then List.iter (fun (l,e) -> - if might_be_affected e then l.i_force_temp <- true; - ) inlined_vars; - (* - if variables are not written and used with a const value, let's substitute - with the actual value, either create a temp var - *) - let subst = ref PMap.empty in - let is_constant e = - let rec loop e = - match e.eexpr with - | TLocal _ - | TConst TThis (* not really, but should not be move inside a function body *) - -> raise Exit - | TObjectDecl _ | TArrayDecl _ -> raise Exit - | TField (_,FEnum _) - | TTypeExpr _ - | TConst _ -> () - | _ -> - Type.iter loop e - in - try loop e; true with Exit -> false - in - let is_writable e = - match e.eexpr with - | TField _ | TEnumParameter _ | TLocal _ | TArray _ -> true - | _ -> false - in - let force = ref force in - let vars = List.fold_left (fun acc (i,e) -> - let flag = not i.i_force_temp && (match e.eexpr with - | TLocal _ when i.i_abstract_this -> true - | TLocal _ | TConst _ -> not i.i_write - | TFunction _ -> if i.i_write then error "Cannot modify a closure parameter inside inline method" p; true - | _ -> not i.i_write && i.i_read <= 1 - ) in - let flag = flag && (not i.i_captured || is_constant e) in - (* force inlining if we modify 'this' *) - if i.i_write && i.i_abstract_this then force := true; - (* force inlining of 'this' variable if it is written *) - let flag = if not flag && i.i_abstract_this && i.i_write then begin - if not (is_writable e) then error "Cannot modify the abstract value, store it into a local first" p; - true - end else flag in - if flag then begin - subst := PMap.add i.i_subst.v_id e !subst; - acc - end else begin - (* mark the replacement local for the analyzer *) - if i.i_read <= 1 && not i.i_write then - i.i_subst.v_meta <- (Meta.CompilerGenerated,[],p) :: i.i_subst.v_meta; - (i.i_subst,Some e) :: acc - end - ) [] inlined_vars in - let subst = !subst in - let rec inline_params e = - match e.eexpr with - | TLocal v -> (try PMap.find v.v_id subst with Not_found -> e) - | _ -> Type.map_expr inline_params e - in - let e = (if PMap.is_empty subst then e else inline_params e) in - let init = match vars with [] -> None | l -> Some l in - (* - If we have local variables and returning a value, then this will result in - unoptimized JS code, so let's instead skip inlining. - - This could be fixed with better post process code cleanup (planed) - *) - if !cancel_inlining then - None - else - let wrap e = - (* we can't mute the type of the expression because it is not correct to do so *) - let etype = if has_params then map_type e.etype else e.etype in - (* if the expression is "untyped" and we don't want to unify it accidentally ! *) - try (match follow e.etype with - | TMono _ | TInst ({cl_kind = KTypeParameter _ },_) -> - (match follow tret with - | TAbstract ({ a_path = [],"Void" },_) -> e - | _ -> raise (Unify_error [])) - | _ -> - type_eq (if ctx.com.config.pf_static then EqDoNotFollowNull else EqStrict) etype tret; - e) - with Unify_error _ -> - mk (TCast (e,None)) tret e.epos - in - let e = (match e.eexpr, init with - | _, None when not !has_return_value -> - begin match e.eexpr with - | TBlock _ -> {e with etype = tret} - | _ -> mk (TBlock [e]) tret e.epos - end - | TBlock [e] , None -> wrap e - | _ , None -> wrap e - | TBlock l, Some vl -> - let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) ctx.t.tvoid e.epos) vl in - mk (TBlock (el_v @ l)) tret e.epos - | _, Some vl -> - let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) ctx.t.tvoid e.epos) vl in - mk (TBlock (el_v @ [e])) tret e.epos - ) in - let inline_meta e meta = match meta with - | (Meta.Deprecated | Meta.Pure),_,_ -> mk (TMeta(meta,e)) e.etype e.epos - | _ -> e - in - let e = List.fold_left inline_meta e cf.cf_meta in - let e = Display.Diagnostics.secure_generated_code ctx e in - if Meta.has (Meta.Custom ":inlineDebug") ctx.meta then begin - let se t = s_expr_pretty true t true (s_type (print_context())) in - print_endline (Printf.sprintf "Inline %s:\n\tArgs: %s\n\tExpr: %s\n\tResult: %s" - cf.cf_name - (String.concat "" (List.map (fun (i,e) -> Printf.sprintf "\n\t\t%s<%i> = %s" (i.i_subst.v_name) (i.i_subst.v_id) (se "\t\t" e)) inlined_vars)) - (se "\t" f.tf_expr) - (se "\t" e) - ); - end; - (* we need to replace type-parameters that were used in the expression *) - if not has_params then - Some e - else - let mt = map_type cf.cf_type in - let unify_func () = unify_raise ctx mt (TFun (List.map (fun e -> "",false,e.etype) params,tret)) p in - (match follow ethis.etype with - | TAnon a -> (match !(a.a_status) with - | Statics {cl_kind = KAbstractImpl a } when Meta.has Meta.Impl cf.cf_meta -> - if cf.cf_name <> "_new" then begin - (* the first argument must unify with a_this for abstract implementation functions *) - let tb = (TFun(("",false,map_type a.a_this) :: List.map (fun e -> "",false,e.etype) (List.tl params),tret)) in - unify_raise ctx mt tb p - end - | _ -> unify_func()) - | _ -> unify_func()); - (* - this is very expensive since we are building the substitution list for - every expression, but hopefully in such cases the expression size is small - *) - let vars = Hashtbl.create 0 in - let map_var v = - if not (Hashtbl.mem vars v.v_id) then begin - Hashtbl.add vars v.v_id (); - if not (read_local v).i_outside then v.v_type <- map_type v.v_type; - end; - v - in - let rec map_expr_type e = Type.map_expr_type map_expr_type map_type map_var e in - Some (map_expr_type e) - -(* Same as type_inline, but modifies the function body to add field inits *) -and type_inline_ctor ctx c cf tf ethis el po = - let field_inits = - let cparams = List.map snd c.cl_params in - let ethis = mk (TConst TThis) (TInst (c,cparams)) c.cl_pos in - let el = List.fold_left (fun acc cf -> - match cf.cf_kind,cf.cf_expr with - | Var _,Some e -> - let lhs = mk (TField(ethis,FInstance (c,cparams,cf))) cf.cf_type e.epos in - let eassign = mk (TBinop(OpAssign,lhs,e)) cf.cf_type e.epos in - eassign :: acc - | _ -> acc - ) [] c.cl_ordered_fields in - List.rev el - in - let tf = - if field_inits = [] then tf - else - let bl = match tf.tf_expr with {eexpr = TBlock b } -> b | x -> [x] in - {tf with tf_expr = mk (TBlock (field_inits @ bl)) ctx.t.tvoid c.cl_pos} - in - type_inline ctx cf tf ethis el ctx.t.tvoid None po true - - -(* ---------------------------------------------------------------------- *) -(* LOOPS *) - -let rec optimize_for_loop ctx (i,pi) e1 e2 p = - let t_void = ctx.t.tvoid in - let t_int = ctx.t.tint in - let lblock el = Some (mk (TBlock el) t_void p) in - let mk_field e n = - TField (e,try quick_field e.etype n with Not_found -> assert false) - in - let gen_int_iter pt f_get f_length = - let i = add_local ctx i pt pi in - let index = gen_local ctx t_int pi in - index.v_meta <- (Meta.ForLoopVariable,[],null_pos) :: index.v_meta; - let arr, avars = (match e1.eexpr with - | TLocal _ -> e1, None - | _ -> - let atmp = gen_local ctx e1.etype e1.epos in - mk (TLocal atmp) e1.etype e1.epos, (Some (atmp,Some e1)) - ) in - let iexpr = mk (TLocal index) t_int p in - let e2 = type_expr ctx e2 NoValue in - let aget = mk (TVar (i,Some (f_get arr iexpr pt p))) t_void pi in - let incr = mk (TUnop (Increment,Prefix,iexpr)) t_int p in - let block = match e2.eexpr with - | TBlock el -> mk (TBlock (aget :: incr :: el)) t_void e2.epos - | _ -> mk (TBlock [aget;incr;e2]) t_void p - in - let ivar = Some (mk (TConst (TInt 0l)) t_int p) in - let elength = f_length arr p in - let el = [mk (TWhile ( - mk (TBinop (OpLt, iexpr, elength)) ctx.t.tbool p, - block, - NormalWhile - )) t_void p; - ] in - let el = match avars with None -> el | Some (v,eo) -> (mk (TVar (v,eo)) t_void p) :: el in - let el = (mk (TVar (index,ivar)) t_void p) :: el in - lblock el - in - let get_next_array_element arr iexpr pt p = - (mk (TArray (arr,iexpr)) pt p) - in - let get_array_length arr p = - mk (mk_field arr "length") ctx.com.basic.tint p - in - match e1.eexpr, follow e1.etype with - | TNew ({ cl_path = ([],"IntIterator") },[],[i1;i2]) , _ -> - let max = (match i1.eexpr , i2.eexpr with - | TConst (TInt a), TConst (TInt b) when Int32.compare b a < 0 -> error "Range operator can't iterate backwards" p - | _, TConst _ -> None - | _ -> Some (gen_local ctx t_int e1.epos) - ) in - let tmp = gen_local ctx t_int pi in - tmp.v_meta <- (Meta.ForLoopVariable,[],null_pos) :: tmp.v_meta; - let i = add_local ctx i t_int pi in - let rec check e = - match e.eexpr with - | TBinop (OpAssign,{ eexpr = TLocal l },_) - | TBinop (OpAssignOp _,{ eexpr = TLocal l },_) - | TUnop (Increment,_,{ eexpr = TLocal l }) - | TUnop (Decrement,_,{ eexpr = TLocal l }) when l == i -> - error "Loop variable cannot be modified" e.epos - | _ -> - Type.iter check e - in - let e2 = type_expr ctx e2 NoValue in - check e2; - let etmp = mk (TLocal tmp) t_int p in - let incr = mk (TUnop (Increment,Postfix,etmp)) t_int p in - let init = mk (TVar (i,Some incr)) t_void pi in - let block = match e2.eexpr with - | TBlock el -> mk (TBlock (init :: el)) t_void e2.epos - | _ -> mk (TBlock [init;e2]) t_void p - in - (* - force locals to be of Int type (to prevent Int/UInt issues) - *) - let i2 = match follow i2.etype with - | TAbstract ({ a_path = ([],"Int") }, []) -> i2 - | _ -> { i2 with eexpr = TCast(i2, None); etype = t_int } - in - (match max with - | None -> - lblock [ - mk (TVar (tmp,Some i1)) t_void p; - mk (TWhile ( - mk (TBinop (OpLt, etmp, i2)) ctx.t.tbool p, - block, - NormalWhile - )) t_void p; - ] - | Some max -> - lblock [ - mk (TVar (tmp,Some i1)) t_void p; - mk (TVar (max,Some i2)) t_void p; - mk (TWhile ( - mk (TBinop (OpLt, etmp, mk (TLocal max) t_int p)) ctx.t.tbool p, - block, - NormalWhile - )) t_void p; - ]) - | TArrayDecl el, TInst({ cl_path = [],"Array" },[pt]) when false -> - begin try - let num_expr = ref 0 in - let rec loop e = match fst e with - | EContinue | EBreak -> - raise Exit - | _ -> - incr num_expr; - Ast.map_expr loop e - in - ignore(loop e2); - let v = add_local ctx i pt p in - let e2 = type_expr ctx e2 NoValue in - let cost = (List.length el) * !num_expr in - let max_cost = try - int_of_string (Common.defined_value ctx.com Define.LoopUnrollMaxCost) - with Not_found -> - 250 - in - if cost > max_cost then raise Exit; - let eloc = mk (TLocal v) v.v_type p in - let el = List.map (fun e -> - let e_assign = mk (TBinop(OpAssign,eloc,e)) e.etype e.epos in - concat e_assign e2 - ) el in - let ev = mk (TVar(v, None)) ctx.t.tvoid p in - Some (mk (TBlock (ev :: el)) ctx.t.tvoid p) - with Exit -> - gen_int_iter pt get_next_array_element get_array_length - end - | _ , TInst({ cl_path = [],"Array" },[pt]) - | _ , TInst({ cl_path = ["flash"],"Vector" },[pt]) -> - gen_int_iter pt get_next_array_element get_array_length - | _ , TInst({ cl_array_access = Some pt } as c,pl) when (try match follow (PMap.find "length" c.cl_fields).cf_type with TAbstract ({ a_path = [],"Int" },[]) -> true | _ -> false with Not_found -> false) && not (PMap.mem "iterator" c.cl_fields) -> - gen_int_iter (apply_params c.cl_params pl pt) get_next_array_element get_array_length - | _, TAbstract({a_impl = Some c} as a,tl) -> - begin try - let cf_length = PMap.find "get_length" c.cl_statics in - let get_length e p = - make_static_call ctx c cf_length (apply_params a.a_params tl) [e] ctx.com.basic.tint p - in - begin match follow cf_length.cf_type with - | TFun(_,tr) -> - begin match follow tr with - | TAbstract({a_path = [],"Int"},_) -> () - | _ -> raise Not_found - end - | _ -> - raise Not_found - end; - begin try - (* first try: do we have an @:arrayAccess getter field? *) - let todo = mk (TConst TNull) ctx.t.tint p in - let cf,_,r,_,_ = (!find_array_access_raise_ref) ctx a tl todo None p in - let get_next e_base e_index t p = - make_static_call ctx c cf (apply_params a.a_params tl) [e_base;e_index] r p - in - gen_int_iter r get_next get_length - with Not_found -> - (* second try: do we have @:arrayAccess on the abstract itself? *) - if not (Meta.has Meta.ArrayAccess a.a_meta) then raise Not_found; - (* let's allow this only for core-type abstracts *) - if not (Meta.has Meta.CoreType a.a_meta) then raise Not_found; - (* in which case we assume that a singular type parameter is the element type *) - let t = match tl with [t] -> t | _ -> raise Not_found in - gen_int_iter t get_next_array_element get_length - end with Not_found -> - None - end - | _ , TInst ({ cl_kind = KGenericInstance ({ cl_path = ["haxe";"ds"],"GenericStack" },[t]) } as c,[]) -> - let tcell = (try (PMap.find "head" c.cl_fields).cf_type with Not_found -> assert false) in - let i = add_local ctx i t p in - let cell = gen_local ctx tcell p in - let cexpr = mk (TLocal cell) tcell p in - let e2 = type_expr ctx e2 NoValue in - let evar = mk (TVar (i,Some (mk (mk_field cexpr "elt") t p))) t_void pi in - let enext = mk (TBinop (OpAssign,cexpr,mk (mk_field cexpr "next") tcell p)) tcell p in - let block = match e2.eexpr with - | TBlock el -> mk (TBlock (evar :: enext :: el)) t_void e2.epos - | _ -> mk (TBlock [evar;enext;e2]) t_void p - in - lblock [ - mk (TVar (cell,Some (mk (mk_field e1 "head") tcell p))) t_void p; - mk (TWhile ( - mk (TBinop (OpNotEq, cexpr, mk (TConst TNull) tcell p)) ctx.t.tbool p, - block, - NormalWhile - )) t_void p - ] - | _ -> - None - -let optimize_for_loop_iterator ctx v e1 e2 p = - let c,tl = (match follow e1.etype with TInst (c,pl) -> c,pl | _ -> raise Exit) in - let _, _, fhasnext = (try raw_class_field (fun cf -> apply_params c.cl_params tl cf.cf_type) c tl "hasNext" with Not_found -> raise Exit) in - if fhasnext.cf_kind <> Method MethInline then raise Exit; - let tmp = gen_local ctx e1.etype e1.epos in - let eit = mk (TLocal tmp) e1.etype p in - let ehasnext = make_call ctx (mk (TField (eit,FInstance (c, tl, fhasnext))) (TFun([],ctx.t.tbool)) p) [] ctx.t.tbool p in - let enext = mk (TVar (v,Some (make_call ctx (mk (TField (eit,quick_field_dynamic eit.etype "next")) (TFun ([],v.v_type)) p) [] v.v_type p))) ctx.t.tvoid p in - let eblock = (match e2.eexpr with - | TBlock el -> { e2 with eexpr = TBlock (enext :: el) } - | _ -> mk (TBlock [enext;e2]) ctx.t.tvoid p - ) in - mk (TBlock [ - mk (TVar (tmp,Some e1)) ctx.t.tvoid p; - mk (TWhile (ehasnext,eblock,NormalWhile)) ctx.t.tvoid p - ]) ctx.t.tvoid p - +open Inline (* ---------------------------------------------------------------------- *) (* SANITIZE *) @@ -986,6 +118,16 @@ let sanitize_expr com e = | TBinop (op2,_,_) -> if left then not (swap op2 op) else swap op op2 | TIf _ -> if left then not (swap (OpAssignOp OpAssign) op) else swap op (OpAssignOp OpAssign) | TCast (e,None) | TMeta (_,e) -> loop e left + | TConst (TInt i) when not left -> + (match op with + | OpAdd | OpSub -> (Int32.to_int i) < 0 + | _ -> false + ) + | TConst (TFloat flt) when not left -> + (match op with + | OpAdd | OpSub -> String.get flt 0 = '-' + | _ -> false + ) | _ -> false in let e1 = if loop e1 true then parent e1 else e1 in @@ -994,6 +136,8 @@ let sanitize_expr com e = | TUnop (op,mode,e1) -> let rec loop ee = match ee.eexpr with + | TConst (TInt i) when op = Neg && (Int32.to_int i) < 0 -> parent e1 + | TConst (TFloat flt) when op = Neg && String.get flt 0 = '-' -> parent e1 | TBinop _ | TIf _ | TUnop _ -> parent e1 | TCast (e,None) | TMeta (_, e) -> loop e | _ -> e1 @@ -1078,6 +222,12 @@ let rec sanitize com e = (* ---------------------------------------------------------------------- *) (* REDUCE *) +let check_enum_construction_args el i = + let b,_ = List.fold_left (fun (b,i') e -> + (b && (i' = i || not (has_side_effect e))),i' + 1 + ) (true,0) el in + b + let reduce_control_flow ctx e = match e.eexpr with | TIf ({ eexpr = TConst (TBool t) },e1,e2) -> (if t then e1 else match e2 with None -> { e with eexpr = TBlock [] } | Some e -> e) @@ -1110,9 +260,15 @@ let reduce_control_flow ctx e = match e.eexpr with | TCall ({ eexpr = TField (o,FClosure (c,cf)) } as f,el) -> let fmode = (match c with None -> FAnon cf | Some (c,tl) -> FInstance (c,tl,cf)) in { e with eexpr = TCall ({ f with eexpr = TField (o,fmode) },el) } + | TEnumParameter({eexpr = TCall({eexpr = TField(_,FEnum(_,ef1))},el)},ef2,i) + | TEnumParameter({eexpr = TParenthesis {eexpr = TCall({eexpr = TField(_,FEnum(_,ef1))},el)}},ef2,i) + when ef1 == ef2 && check_enum_construction_args el i -> + (try List.nth el i with Failure _ -> e) | _ -> e +let inline_stack = new_rec_stack() + let rec reduce_loop ctx e = let e = Type.map_expr (reduce_loop ctx) e in sanitize_expr ctx.com (match e.eexpr with @@ -1126,6 +282,18 @@ let rec reduce_loop ctx e = (match inl with | None -> reduce_expr ctx e | Some e -> reduce_loop ctx e) + | {eexpr = TField(ef,(FStatic(_,cf) | FInstance(_,_,cf)))} when cf.cf_kind = Method MethInline && not (rec_stack_memq cf inline_stack) -> + begin match cf.cf_expr with + | Some {eexpr = TFunction tf} -> + let rt = (match follow e1.etype with TFun (_,rt) -> rt | _ -> assert false) in + let inl = (try type_inline ctx cf tf ef el rt None e.epos false with Error (Custom _,_) -> None) in + (match inl with + | None -> reduce_expr ctx e + | Some e -> + rec_stack_default inline_stack cf (fun cf' -> cf' == cf) (fun () -> reduce_loop ctx e) e) + | _ -> + reduce_expr ctx e + end | { eexpr = TField ({ eexpr = TTypeExpr (TClassDecl c) },field) } -> (match api_inline ctx c (field_name field) el e.epos with | None -> reduce_expr ctx e @@ -1137,12 +305,18 @@ let rec reduce_loop ctx e = reduce_expr ctx (reduce_control_flow ctx e)) let reduce_expression ctx e = - if ctx.com.foptimize then reduce_loop ctx e else e + if ctx.com.foptimize then + (* We go through rec_stack_default here so that the current field is on inline_stack. This prevents self-recursive + inlining (#7569). *) + rec_stack_default inline_stack ctx.curfield (fun cf' -> cf' == ctx.curfield) (fun () -> reduce_loop ctx e) e + else + e let rec make_constant_expression ctx ?(concat_strings=false) e = let e = reduce_loop ctx e in match e.eexpr with | TConst _ -> Some e + | TField({eexpr = TTypeExpr _},FEnum _) -> Some e | TBinop ((OpAdd|OpSub|OpMult|OpDiv|OpMod|OpShl|OpShr|OpUShr|OpOr|OpAnd|OpXor) as op,e1,e2) -> (match make_constant_expression ctx e1,make_constant_expression ctx e2 with | Some ({eexpr = TConst (TString s1)}), Some ({eexpr = TConst (TString s2)}) when concat_strings -> Some (mk (TConst (TString (s1 ^ s2))) ctx.com.basic.tstring (punion e1.epos e2.epos)) @@ -1238,8 +412,7 @@ let inline_constructors ctx e = in let add_field_var v s t = let ii = IntMap.find v.v_id !vars in - let v' = alloc_var (Printf.sprintf "%s_%s" v.v_name s) t v.v_pos in - v'.v_meta <- (Meta.InlineConstructorVariable,[],v.v_pos) :: v'.v_meta; + let v' = alloc_var VInlinedConstructorVariable (Printf.sprintf "%s_%s" v.v_name s) t v.v_pos in ii.ii_fields <- PMap.add s v' ii.ii_fields; v' in @@ -1247,7 +420,7 @@ let inline_constructors ctx e = if i < 0 then "n" ^ (string_of_int (-i)) else (string_of_int i) in - let is_extern_ctor c cf = c.cl_extern || Meta.has Meta.Extern cf.cf_meta in + let is_extern_ctor c cf = c.cl_extern || has_class_field_flag cf CfExtern in let rec find_locals e = match e.eexpr with | TVar(v,Some e1) -> find_locals e1; @@ -1433,7 +606,7 @@ type compl_locals = { mutable r : (string, (complex_type option * (int * Ast.expr * compl_locals) option)) PMap.t; } -let optimize_completion_expr e = +let optimize_completion_expr e args = let iid = ref 0 in let typing_side_effect = ref false in let locals : compl_locals = { r = PMap.empty } in @@ -1448,6 +621,11 @@ let optimize_completion_expr e = typing_side_effect := true; locals.r <- PMap.add n (t,(match e with Some e when maybe_typed e -> incr iid; Some (!iid,e,{ r = locals.r }) | _ -> None)) locals.r in + let rec hunt_idents e = match fst e with + | EConst (Ident i) -> decl i None None + | _ -> Ast.iter_expr hunt_idents e + in + let e0 = e in let rec loop e = let p = snd e in match fst e with @@ -1468,10 +646,10 @@ let optimize_completion_expr e = ()); map e | EVars vl -> - let vl = List.map (fun ((v,pv),t,e) -> + let vl = List.map (fun ((v,pv),final,t,e) -> let e = (match e with None -> None | Some e -> Some (loop e)) in decl v (Option.map fst t) e; - ((v,pv),t,e) + ((v,pv),final,t,e) ) vl in (EVars vl,p) | EBlock el -> @@ -1480,7 +658,7 @@ let optimize_completion_expr e = let el = List.fold_left (fun acc e -> typing_side_effect := false; let e = loop e in - if !typing_side_effect || Display.is_display_position (pos e) then begin told := true; e :: acc end else acc + if !typing_side_effect || DisplayPosition.display_position#enclosed_in (pos e) then begin told := true; e :: acc end else acc ) [] el in old(); typing_side_effect := !told; @@ -1488,28 +666,65 @@ let optimize_completion_expr e = | EFunction (v,f) -> (match v with | None -> () - | Some name -> + | Some (name,_) -> decl name None (Some e)); let old = save() in List.iter (fun ((n,_),_,_,t,e) -> decl n (Option.map fst t) e) f.f_args; let e = map e in old(); e - | EFor ((EBinop (OpIn,((EConst (Ident n),_) as id),it),p),efor) -> - let it = loop it in - let old = save() in - let etmp = (EConst (Ident "$tmp"),p) in - decl n None (Some (EBlock [ - (EVars [("$tmp",null_pos),None,None],p); - (EFor ((EBinop (OpIn,id,it),p),(EBinop (OpAssign,etmp,(EConst (Ident n),p)),p)),p); - etmp - ],p)); - let efor = loop efor in - old(); - (EFor ((EBinop (OpIn,id,it),p),efor),p) + | EFor (header,body) -> + let idents = ref [] + and has_in = ref false in + let rec collect_idents e = + match e with + | EConst (Ident name), p -> + idents := (name,p) :: !idents; + e + | EBinop (OpIn, e, it), p -> + has_in := true; + (EBinop (OpIn, collect_idents e, loop it), p) + | _ -> + Ast.map_expr collect_idents e + in + let header = collect_idents header in + (match !idents,!has_in with + | [],_ | _,false -> map e + | idents,true -> + let old = save() in + List.iter + (fun (name, pos) -> + let etmp = (EConst (Ident "`tmp"),pos) in + decl name None (Some (EBlock [ + (EVars [("`tmp",null_pos),false,None,None],p); + (EFor(header,(EBinop (OpAssign,etmp,(EConst (Ident name),p)),p)), p); + etmp + ],p)); + ) + idents; + let body = loop body in + old(); + (EFor(header,body),p) + ) | EReturn _ -> typing_side_effect := true; map e + | ESwitch (e1,cases,def) when DisplayPosition.display_position#enclosed_in p -> + let e1 = loop e1 in + hunt_idents e1; + (* Prune all cases that aren't our display case *) + let cases = List.filter (fun (_,_,_,p) -> DisplayPosition.display_position#enclosed_in p) cases in + (* Don't throw away the switch subject when we optimize in a case expression because we might need it *) + let cases = List.map (fun (el,eg,eo,p) -> + List.iter hunt_idents el; + el,eg,(try Option.map loop eo with Return e -> Some e),p + ) cases in + let def = match def with + | None -> None + | Some (None,p) -> Some (None,p) + | Some (Some e,p) -> Some (Some (loop e),p) + in + (ESwitch (e1,cases,def),p) | ESwitch (e,cases,def) -> let e = loop e in let cases = List.map (fun (el,eg,eo,p) -> match eo with @@ -1518,16 +733,7 @@ let optimize_completion_expr e = | Some e -> let el = List.map loop el in let old = save() in - List.iter (fun e -> - match fst e with - | ECall (_,pl) -> - List.iter (fun p -> - match fst p with - | EConst (Ident i) -> decl i None None (* sadly *) - | _ -> () - ) pl - | _ -> () - ) el; + List.iter hunt_idents el; let e = loop e in old(); el, eg, Some e, p @@ -1548,6 +754,29 @@ let optimize_completion_expr e = (n,pn), (t,pt), e, p ) cl in (ETry (et,cl),p) + | ECall(e1,el) when DisplayPosition.display_position#enclosed_in p -> + let e1 = loop e1 in + let el = List.map (fun e -> + if DisplayPosition.display_position#enclosed_in (pos e) then + (try loop e with Return e -> e) + else + (EConst (Ident "null"),(pos e)) + ) el in + (ECall(e1,el),p) + | ECheckType(e1,th) -> + typing_side_effect := true; + let e1 = loop e1 in + (ECheckType(e1,th),p) + | EMeta(m,e1) -> + begin try + let e1 = loop e1 in + (EMeta(m,e1),(pos e)) + with Return e1 -> + let e1 = (EMeta(m,e1),(pos e)) in + raise (Return e1) + end + | EDisplay(_,DKStructure) -> + raise (Return e0) | EDisplay (s,call) -> typing_side_effect := true; let tmp_locals = ref [] in @@ -1564,8 +793,8 @@ let optimize_completion_expr e = PMap.find id (!tmp_hlocals) with Not_found -> let e = subst_locals lc e in - let name = "$tmp_" ^ string_of_int id in - tmp_locals := ((name,null_pos),None,Some e) :: !tmp_locals; + let name = "`tmp_" ^ string_of_int id in + tmp_locals := ((name,null_pos),false,None,Some e) :: !tmp_locals; tmp_hlocals := PMap.add id name !tmp_hlocals; name ) in @@ -1597,6 +826,7 @@ let optimize_completion_expr e = and map e = Ast.map_expr loop e in + List.iter (fun ((n,_),_,_,t,e) -> decl n (Option.map fst t) e) args; (try loop e with Return e -> e) (* ---------------------------------------------------------------------- *) diff --git a/src/optimization/optimizerTexpr.ml b/src/optimization/optimizerTexpr.ml index 97c5a395727..96977ff04e2 100644 --- a/src/optimization/optimizerTexpr.ml +++ b/src/optimization/optimizerTexpr.ml @@ -3,63 +3,6 @@ open Type open Error open Globals -(* - PurityState represents whether or not something has a side-effect. Unless otherwise stated - by using `@:pure` (equivalent to `@:pure(true)`) or `@:pure(false)`, fields are originally - supposed to be "maybe pure". Once all types and fields are known, this is refined by - AnalyzerTexpr.Purity. - - There's a special case for fields that override a parent class field or implement an - interface field: If the overridden/implemented field is explicitly marked as pure, - the type loader marks the overriding/implementing as "expected pure". If during purity - inference this assumption does not hold, an error is shown. -*) -module PurityState = struct - type t = - | Pure - | Impure - | MaybePure - | ExpectPure of pos - - let get_purity_from_meta meta = - try - begin match Meta.get Meta.Pure meta with - | (_,[EConst(Ident s),p],_) -> - begin match s with - | "true" -> Pure - | "false" -> Impure - | "expect" -> ExpectPure p - | _ -> error ("Unsupported purity value " ^ s ^ ", expected true or false") p - end - | (_,[],_) -> - Pure - | (_,_,p) -> - error "Unsupported purity value" p - end - with Not_found -> - MaybePure - - let get_purity c cf = match get_purity_from_meta cf.cf_meta with - | Pure -> Pure - | Impure -> Impure - | ExpectPure p -> ExpectPure p - | _ -> get_purity_from_meta c.cl_meta - - let is_pure c cf = get_purity c cf = Pure - - let is_pure_field_access fa = match fa with - | FInstance(c,_,cf) | FClosure(Some(c,_),cf) | FStatic(c,cf) -> is_pure c cf - | FAnon cf | FClosure(None,cf) -> (get_purity_from_meta cf.cf_meta = Pure) - | FEnum _ -> true - | FDynamic _ -> false - - let to_string = function - | Pure -> "pure" - | Impure -> "impure" - | MaybePure -> "maybe" - | ExpectPure _ -> "expect" -end - (* tells if an expression causes side effects. This does not account for potential null accesses (fields/arrays/ops) *) let has_side_effect e = let rec loop e = @@ -67,6 +10,7 @@ let has_side_effect e = | TConst _ | TLocal _ | TTypeExpr _ | TFunction _ | TIdent _ -> () | TCall({eexpr = TField(e1,fa)},el) when PurityState.is_pure_field_access fa -> loop e1; List.iter loop el | TNew(c,_,el) when (match c.cl_constructor with Some cf when PurityState.is_pure c cf -> true | _ -> false) -> List.iter loop el + | TField(_,fa) when PurityState.is_explicitly_impure fa -> raise Exit | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit | TArray _ | TEnumParameter _ | TEnumIndex _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TFor _ @@ -143,7 +87,7 @@ let optimize_binop e op e1 e2 = in let check_float op f1 f2 = let f = op f1 f2 in - let fstr = Common.float_repres f in + let fstr = Numeric.float_repres f in if (match classify_float f with FP_nan | FP_infinite -> false | _ -> float_of_string fstr = f) then { e with eexpr = TConst (TFloat fstr) } else e in (match e1.eexpr, e2.eexpr with @@ -266,7 +210,7 @@ let optimize_binop e op e1 e2 = (match op with | OpAssign -> e | _ -> - error "You cannot directly compare enums with arguments. Use either 'switch' or 'Type.enumEq'" e.epos) + error "You cannot directly compare enums with arguments. Use either `switch`, `match` or `Type.enumEq`" e.epos) | _ -> e) @@ -298,7 +242,7 @@ let optimize_unop e op flag esub = | NegBits, TConst (TInt i) -> { e with eexpr = TConst (TInt (Int32.lognot i)) } | Neg, TConst (TFloat f) -> let v = 0. -. float_of_string f in - let vstr = Common.float_repres v in + let vstr = Numeric.float_repres v in if float_of_string vstr = v then { e with eexpr = TConst (TFloat vstr) } else diff --git a/src/prebuild/main.ml b/src/prebuild/main.ml new file mode 100644 index 00000000000..39c1c5eb067 --- /dev/null +++ b/src/prebuild/main.ml @@ -0,0 +1,218 @@ +open Json + +exception Prebuild_error of string + +let as_string = function + | JString s -> Some s + | _ -> None + +let as_params = function + | JArray s -> Some (List.map (function + | JString s -> s + | _ -> raise (Prebuild_error "parameter description should be a string") + ) s) + | _ -> None + +let as_platforms = function + | JArray s -> Some (List.map (function + | JString "cross" -> "Cross" + | JString "js" -> "Js" + | JString "lua" -> "Lua" + | JString "neko" -> "Neko" + | JString "flash" -> "Flash" + | JString "php" -> "Php" + | JString "cpp" -> "Cpp" + | JString "cs" -> "Cs" + | JString "java" -> "Java" + | JString "python" -> "Python" + | JString "hl" -> "Hl" + | JString "eval" -> "Eval" + | _ -> raise (Prebuild_error "invalid platform") + ) s) + | _ -> None + +let as_targets = function + | JArray s -> Some (List.map (function + | JString "TClass" -> "TClass" + | JString "TClassField" -> "TClassField" + | JString "TAbstract" -> "TAbstract" + | JString "TAbstractField" -> "TAbstractField" + | JString "TEnum" -> "TEnum" + | JString "TTypedef" -> "TTypedef" + | JString "TAnyField" -> "TAnyField" + | JString "TExpr" -> "TExpr" + | JString "TTypeParameter" -> "TTypeParameter" + | _ -> raise (Prebuild_error "invalid metadata target") + ) s) + | _ -> None + +let as_bool = function + | JBool b -> Some b + | _ -> None + +let as_links = function + | JArray s -> Some (List.map (function + | JString s -> s + | _ -> raise (Prebuild_error "link should be a string") + ) s) + | _ -> None + +let get_optional_field name map default fields = + try + let field = List.find (fun (n, _) -> n = name) fields in + let value = map (snd field) in + match value with + | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data")) + | Some v -> v + with Not_found -> default + +let get_field name map fields = + let field = try List.find (fun (n, _) -> n = name) fields with Not_found -> raise (Prebuild_error ("no `" ^ name ^ "` field")) in + let value = map (snd field) in + match value with + | None -> raise (Prebuild_error ("field `" ^ name ^ "` has invalid data")) + | Some v -> v + +let parse_define json = + let fields = match json with + | JObject fl -> fl + | _ -> raise (Prebuild_error "not an object") + in + (* name *) get_field "name" as_string fields, + (* define *) get_field "define" as_string fields, + (* doc *) get_field "doc" as_string fields, + (* params *) get_optional_field "params" as_params [] fields, + (* platforms *) get_optional_field "platforms" as_platforms [] fields, + (* links *) get_optional_field "links" as_links [] fields + +let parse_meta json = + let fields = match json with + | JObject fl -> fl + | _ -> raise (Prebuild_error "not an object") + in + (* name *) get_field "name" as_string fields, + (* metadata *) get_field "metadata" as_string fields, + (* doc *) get_field "doc" as_string fields, + (* params *) get_optional_field "params" as_params [] fields, + (* platforms *) get_optional_field "platforms" as_platforms [] fields, + (* targets *) get_optional_field "targets" as_targets [] fields, + (* internal *) get_optional_field "internal" as_bool false fields, + (* links *) get_optional_field "links" as_links [] fields + +let parse_file_array path map = + let file = open_in path in + let data = Std.input_all file in + let open Json.Reader in + let lexbuf = Sedlexing.Utf8.from_string data in + let json = read_json lexbuf in + match json with + | JArray s -> List.map map s + | _ -> raise (Prebuild_error "not an array") + +let gen_platforms = function + | [] -> [] + | platforms -> ["Platforms [" ^ (String.concat ";" platforms) ^ "]"] + +let gen_params = List.map (function param -> "HasParam \"" ^ param ^ "\"" ) + +let gen_links = List.map (function link -> "Link \"" ^ link ^ "\"" ) + +let gen_define_type defines = + String.concat "\n" (List.map (function (name, _, _, _, _, _) -> "\t| " ^ name) defines) + +let gen_define_info defines = + let define_str = List.map (function + (name, define, doc, params, platforms, links) -> + let platforms_str = gen_platforms platforms in + let params_str = gen_params params in + let links_str = gen_links links in + "\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str)) ^ "])" + ) defines in + String.concat "\n" define_str + +let gen_meta_type metas = + String.concat "\n" (List.map (function + | ("InlineConstructorArgument", _, _, _, _, _, _, _) -> "\t| InlineConstructorArgument of int * int" + | (name, _, _, _, _, _, _, _) -> "\t| " ^ name + ) metas) + +let gen_meta_info metas = + let meta_str = List.map (function + (name, metadata, doc, params, platforms, targets, internal, links) -> + let platforms_str = gen_platforms platforms in + let params_str = gen_params params in + let targets_str = (match targets with + | [] -> [] + | targets -> ["UsedOn [" ^ (String.concat ";" targets) ^ "]"] + ) in + let internal_str = if internal then ["UsedInternally"] else [] in + let links_str = gen_links links in + let name = (match name with + (* this is a hacky, I know *) + | "InlineConstructorArgument" -> "InlineConstructorArgument _" + | _ -> name + ) in + "\t| " ^ name ^ " -> \"" ^ metadata ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str @ links_str)) ^ "])" + ) metas in + String.concat "\n" meta_str + +let autogen_header = "(* This file is auto-generated using prebuild from files in src-json *) +(* Do not edit manually! *) +" + +let define_header = autogen_header ^ " +open Globals + +type define_parameter = + | HasParam of string + | Platforms of platform list + | Link of string + +" + +let meta_header = autogen_header ^ " +open Globals + +type meta_usage = + | TClass + | TClassField + | TAbstract + | TAbstractField + | TEnum + | TTypedef + | TAnyField + | TExpr + | TTypeParameter + | TVariable + +type meta_parameter = + | HasParam of string + | Platforms of platform list + | UsedOn of meta_usage list + | UsedInternally + | Link of string + +" + +;; + +match Sys.argv with + | [|_; "define"; define_path|] -> + let defines = parse_file_array define_path parse_define in + Printf.printf "%s" define_header; + Printf.printf "type strict_defined =\n"; + Printf.printf "%s" (gen_define_type defines); + Printf.printf "\n\t| Last\n\n"; (* must be last *) + Printf.printf "let infos = function\n"; + Printf.printf "%s" (gen_define_info defines); + Printf.printf "\n\t| Last -> assert false\n" + | [|_; "meta"; meta_path|] -> + let metas = parse_file_array meta_path parse_meta in + Printf.printf "%s" meta_header; + Printf.printf "type strict_meta =\n"; + Printf.printf "%s" (gen_meta_type metas); + Printf.printf "\n\t| Last\n\t| Dollar of string\n\t| Custom of string\n\n"; + Printf.printf "let get_info = function\n"; + Printf.printf "%s" (gen_meta_info metas); + Printf.printf "\n\t| Last -> assert false\n\t| Dollar s -> \"$\" ^ s,(\"\",[])\n\t| Custom s -> s,(\"\",[])\n" + | _ -> () diff --git a/src/syntax/grammar.mly b/src/syntax/grammar.mly index bcaeabc5035..8a55dd6bbc3 100644 --- a/src/syntax/grammar.mly +++ b/src/syntax/grammar.mly @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -20,6 +20,7 @@ open Globals open Ast open Reification open Parser +open DisplayPosition let popt f = parser | [< v = f >] -> Some v @@ -29,15 +30,31 @@ let rec plist f = parser | [< v = f; l = plist f >] -> v :: l | [< >] -> [] -let rec psep sep f = parser +let rec psep_nonempty sep f = parser | [< v = f; s >] -> let rec loop = parser | [< '(sep2,_) when sep2 = sep; v = f; l = loop >] -> v :: l | [< >] -> [] in v :: loop s + +let rec psep sep f = parser + | [< r = psep_nonempty sep f >] -> r | [< >] -> [] +let pignore f = + try + ignore(f()) + with Stream.Error _ | Stream.Failure -> + () + +let expect_unless_resume_p t s = match Stream.peek s with + | Some (t',p) when t' = t -> + Stream.junk s; + p + | _ -> + syntax_error (Expected [s_token t]) s (next_pos s) + let ident = parser | [< '(Const (Ident i),p) >] -> i,p @@ -62,8 +79,21 @@ let property_ident = parser | [< '(Kwd Default,p) >] -> "default",p | [< '(Kwd Null,p) >] -> "null",p -let comma = parser - | [< '(Comma,_) >] -> () +let questionable_dollar_ident s = + let po = match s with parser + | [< '(Question,p) >] -> Some p + | [< >] -> None + in + let name,p = dollar_ident s in + match po with + | None -> + false,(name,p) + | Some p' -> + if p.pmin <> p'.pmax then syntax_error (Custom (Printf.sprintf "Invalid usage of ?, use ?%s instead" name)) s ~pos:(Some p') (); + true,(name,p) + +let question_mark = parser + | [< '(Question,p) >] -> p let semicolon s = if fst (last_token s) = BrClose then @@ -74,8 +104,9 @@ let semicolon s = match s with parser | [< '(Semicolon,p) >] -> p | [< s >] -> - let pos = snd (last_token s) in - if do_resume() then pos else error Missing_semicolon pos + syntax_error Missing_semicolon s (next_pos s) + +let parsing_macro_cond = ref false let rec parse_file s = last_doc := None; @@ -83,43 +114,102 @@ let rec parse_file s = | [< '(Kwd Package,_); pack = parse_package; s >] -> begin match s with parser | [< '(Const(Ident _),p) when pack = [] >] -> error (Custom "Package name must start with a lowercase character") p - | [< _ = semicolon; l = parse_type_decls pack []; '(Eof,_) >] -> pack , l + | [< psem = semicolon; l = parse_type_decls TCAfterImport psem.pmax pack []; '(Eof,_) >] -> pack , l end - | [< l = parse_type_decls [] []; '(Eof,_) >] -> [] , l + | [< l = parse_type_decls TCBeforePackage (-1) [] []; '(Eof,_) >] -> [] , l -and parse_type_decls pack acc s = +and parse_type_decls mode pmax pack acc s = try + check_type_decl_completion mode pmax s; match s with parser - | [< v = parse_type_decl; l = parse_type_decls pack (v :: acc) >] -> l + | [< (v,p) = parse_type_decl mode >] -> + let mode = match v with + | EImport _ | EUsing _ -> TCAfterImport + | _ -> TCAfterType + in + parse_type_decls mode p.pmax pack ((v,p) :: acc) s | [< >] -> List.rev acc - with TypePath ([],Some (name,false),b) -> + with + | TypePath ([],Some (name,false),b,p) -> (* resolve imports *) List.iter (fun d -> match fst d with | EImport (t,_) -> (match List.rev t with - | (n,_) :: path when n = name && List.for_all (fun (i,_) -> is_lower_ident i) path -> raise (TypePath (List.map fst (List.rev path),Some (name,false),b)) + | (n,_) :: path when n = name && List.for_all (fun (i,_) -> is_lower_ident i) path -> raise (TypePath (List.map fst (List.rev path),Some (name,false),b,p)) | _ -> ()) | _ -> () ) acc; - raise (TypePath (pack,Some(name,true),b)) + raise (TypePath (pack,Some(name,true),b,p)) + | Stream.Error msg when !in_display_file -> + handle_stream_error msg s; + ignore(resume false false s); + parse_type_decls mode (last_pos s).pmax pack acc s + +and parse_abstract doc meta flags = parser + | [< '(Kwd Abstract,p1); name = type_name; tl = parse_constraint_params; st = parse_abstract_subtype; sl = plist parse_abstract_relations; s >] -> + let fl,p2 = match s with parser + | [< '(BrOpen,_); fl, p2 = parse_class_fields false p1 >] -> fl,p2 + | [< >] -> syntax_error (Expected ["{"]) s ([],last_pos s) + in + let flags = List.map decl_flag_to_abstract_flag flags in + let flags = (match st with None -> flags | Some t -> AbOver t :: flags) in + ({ + d_name = name; + d_doc = doc; + d_meta = meta; + d_params = tl; + d_flags = flags @ sl; + d_data = fl; + },punion p1 p2) -and parse_type_decl s = +and parse_type_decl mode s = match s with parser | [< '(Kwd Import,p1) >] -> parse_import s p1 | [< '(Kwd Using,p1) >] -> parse_using s p1 | [< doc = get_doc; meta = parse_meta; c = parse_common_flags; s >] -> match s with parser - | [< n , p1 = parse_enum_flags; name = type_name; tl = parse_constraint_params; '(BrOpen,_); l = plist parse_enum; '(BrClose,p2) >] -> - (EEnum { - d_name = name; - d_doc = doc; - d_meta = meta; - d_params = tl; - d_flags = List.map decl_flag_to_enum_flag c @ n; - d_data = l - }, punion p1 p2) - | [< n , p1 = parse_class_flags; name = type_name; tl = parse_constraint_params; hl = plist parse_class_herit; '(BrOpen,_); fl, p2 = parse_class_fields false p1 >] -> + | [< '(Kwd Enum,p1) >] -> + begin match s with parser + | [< a,p = parse_abstract doc ((Meta.Enum,[],null_pos) :: meta) c >] -> + (EAbstract a,p) + | [< name = type_name; tl = parse_constraint_params; '(BrOpen,_); l = plist parse_enum; '(BrClose,p2) >] -> + (EEnum { + d_name = name; + d_doc = doc; + d_meta = meta; + d_params = tl; + d_flags = List.map decl_flag_to_enum_flag c; + d_data = l + }, punion p1 p2) + end + | [< n , p1 = parse_class_flags; name = type_name; tl = parse_constraint_params >] -> + let rec loop had_display p0 acc = + let check_display p1 = + if not had_display && !in_display_file && display_position#enclosed_in p1 then syntax_completion (if List.mem HInterface n then SCInterfaceRelation else SCClassRelation) p0 + in + match s with parser + | [< '(Kwd Extends,p1); t,b = parse_type_path_or_resume p1 >] -> + check_display {p1 with pmin = p0.pmax; pmax = p1.pmin}; + let p0 = pos t in + (* If we don't have type parameters, we have to offset by one so to not complete `extends` + and `implements` after the identifier. *) + let p0 = {p0 with pmax = p0.pmax + (if (fst t).tparams = [] then 1 else 0)} in + loop (had_display || b) p0 ((HExtends t) :: acc) + | [< '(Kwd Implements,p1); t,b = parse_type_path_or_resume p1 >] -> + check_display {p1 with pmin = p0.pmax; pmax = p1.pmin}; + let p0 = pos t in + let p0 = {p0 with pmax = p0.pmax + (if (fst t).tparams = [] then 1 else 0)} in + loop (had_display || b) p0 ((HImplements t) :: acc) + | [< '(BrOpen,p1) >] -> + check_display {p1 with pmin = p0.pmax; pmax = p1.pmin}; + List.rev acc + | [< >] -> + check_display {p1 with pmin = p0.pmax; pmax = (next_pos s).pmax}; + syntax_error (Expected ["extends";"implements";"{"]) s (List.rev acc) + in + let hl = loop false (last_pos s) [] in + let fl, p2 = parse_class_fields false p1 s in (EClass { d_name = name; d_doc = doc; @@ -140,17 +230,11 @@ and parse_type_decl s = d_flags = List.map decl_flag_to_enum_flag c; d_data = t; }, punion p1 (pos t)) - | [< '(Kwd Abstract,p1); name = type_name; tl = parse_constraint_params; st = parse_abstract_subtype; sl = plist parse_abstract_relations; '(BrOpen,_); fl, p2 = parse_class_fields false p1 >] -> - let flags = List.map decl_flag_to_abstract_flag c in - let flags = (match st with None -> flags | Some t -> AIsType t :: flags) in - (EAbstract { - d_name = name; - d_doc = doc; - d_meta = meta; - d_params = tl; - d_flags = flags @ sl; - d_data = fl; - },punion p1 p2) + | [< a,p = parse_abstract doc meta c >] -> + EAbstract a,p + | [< >] -> + check_type_decl_flag_completion mode c s + and parse_class doc meta cflags need_name s = let opt_name = if need_name then type_name else (fun s -> match popt type_name s with None -> "",null_pos | Some n -> n) in @@ -166,70 +250,79 @@ and parse_class doc meta cflags need_name s = }, punion p1 p2) and parse_import s p1 = - let rec loop acc = + let rec loop pn acc = match s with parser | [< '(Dot,p) >] -> let resume() = - type_path (List.map fst acc) true + type_path (List.map fst acc) true (punion pn p) in - if is_resuming p then resume(); - (match s with parser + check_resume p resume (fun () -> ()); + begin match s with parser | [< '(Const (Ident k),p) >] -> - loop ((k,p) :: acc) + loop pn ((k,p) :: acc) | [< '(Kwd Macro,p) >] -> - loop (("macro",p) :: acc) + loop pn (("macro",p) :: acc) | [< '(Kwd Extern,p) >] -> - loop (("extern",p) :: acc) + loop pn (("extern",p) :: acc) | [< '(Binop OpMult,_); '(Semicolon,p2) >] -> p2, List.rev acc, IAll - | [< '(Binop OpOr,_) when do_resume() >] -> - set_resume p; - resume() | [< >] -> - serror()); + ignore(popt semicolon s); + syntax_error (Expected ["identifier"]) s (p,List.rev acc,INormal) + end | [< '(Semicolon,p2) >] -> p2, List.rev acc, INormal - | [< '(Kwd In,_); '(Const (Ident name),_); '(Semicolon,p2) >] -> - p2, List.rev acc, IAsName name - | [< '(Const (Ident "as"),_); '(Const (Ident name),_); '(Semicolon,p2) >] -> - p2, List.rev acc, IAsName name + | [< '(Kwd In,_); '(Const (Ident name),pname); '(Semicolon,p2) >] -> + p2, List.rev acc, IAsName(name,pname) + | [< '(Const (Ident "as"),_); '(Const (Ident name),pname); '(Semicolon,p2) >] -> + p2, List.rev acc, IAsName(name,pname) | [< >] -> - serror() + syntax_error (Expected [".";";";"as"]) s ((last_pos s),List.rev acc,INormal) in let p2, path, mode = (match s with parser - | [< '(Const (Ident name),p) >] -> loop [name,p] - | [< >] -> if would_skip_resume p1 s then p1, [], INormal else serror() + | [< '(Const (Ident name),p) >] -> loop p [name,p] + | [< >] -> syntax_error (Expected ["identifier"]) s (p1,[],INormal) ) in (EImport (path,mode),punion p1 p2) and parse_using s p1 = - let rec loop acc = + let rec loop pn acc = match s with parser | [< '(Dot,p) >] -> + check_resume p (fun () -> type_path (List.map fst acc) false (punion pn p)) (fun () -> ()); begin match s with parser | [< '(Const (Ident k),p) >] -> - loop ((k,p) :: acc) + loop pn ((k,p) :: acc) | [< '(Kwd Macro,p) >] -> - loop (("macro",p) :: acc) + loop pn (("macro",p) :: acc) | [< '(Kwd Extern,p) >] -> - loop (("extern",p) :: acc) + loop pn (("extern",p) :: acc) | [< >] -> - if is_resuming p then type_path (List.map fst acc) false; - serror() + syntax_error (Expected ["identifier"]) s (p,List.rev acc); end | [< '(Semicolon,p2) >] -> p2,List.rev acc + | [< >] -> + syntax_error (Expected [".";";"]) s ((last_pos s),List.rev acc) in let p2, path = (match s with parser - | [< '(Const (Ident name),p) >] -> loop [name,p] - | [< >] -> if would_skip_resume p1 s then p1, [] else serror() + | [< '(Const (Ident name),p) >] -> loop p [name,p] + | [< >] -> syntax_error (Expected ["identifier"]) s (p1,[]) ) in (EUsing path,punion p1 p2) and parse_abstract_relations s = + let check_display p1 (ct,p2) = + if !in_display_file && p1.pmax < (display_position#get).pmin && p2.pmin >= (display_position#get).pmax then + (* This means we skipped the display position between the to/from and the type-hint we parsed. + Very weird case, it was probably a {} like in #7137. Let's discard it and use magic. *) + ((CTPath magic_type_path,p2)) + else + (ct,p2) + in match s with parser - | [< '(Const (Ident "to"),_); t = parse_complex_type >] -> AToType t - | [< '(Const (Ident "from"),_); t = parse_complex_type >] -> AFromType t + | [< '(Const (Ident "to"),p1); t = parse_complex_type_at p1 >] -> (AbTo (check_display p1 t)) + | [< '(Const (Ident "from"),p1); t = parse_complex_type_at p1 >] -> AbFrom (check_display p1 t) and parse_abstract_subtype s = match s with parser @@ -242,119 +335,142 @@ and parse_class_fields tdecl p1 s = let l = parse_class_field_resume tdecl s in let p2 = (match s with parser | [< '(BrClose,p2) >] -> p2 - | [< >] -> if do_resume() then pos (last_token s) else serror() + | [< >] -> + (* We don't want to register this as a syntax error because it's part of the logic in display mode *) + if !in_display then (pos (last_token s)) else error (Expected ["}"]) (next_pos s) ) in l, p2 +and resume tdecl fdecl s = + (* look for next variable/function or next type declaration *) + let rec junk k = + if k <= 0 then () else begin + Stream.junk s; + junk (k - 1); + end + in + (* + walk back tokens which are prefixing a type/field declaration + *) + let rec junk_tokens k = + if k = 0 then + () + else match List.rev_map fst (Stream.npeek k s) with + | Kwd Private :: _ -> junk_tokens (k - 1) + | (Const (Ident _) | Kwd _) :: DblDot :: At :: l + | (Const (Ident _) | Kwd _) :: At :: l -> + junk_tokens (List.length l) + | PClose :: l -> + (* count matching parenthesises for metadata call *) + let rec loop n = function + | [] -> [] + | POpen :: l -> if n = 0 then l else loop (n - 1) l + | PClose :: l -> loop (n + 1) l + | _ :: l -> loop n l + in + (match loop 0 l with + | (Const (Ident _) | Kwd _) :: At :: l + | (Const (Ident _) | Kwd _) :: DblDot :: At :: l -> junk_tokens (List.length l) + | _ -> + junk k) + | _ -> + junk k + in + let rec loop k = + match List.rev_map fst (Stream.npeek k s) with + (* metadata *) + | Kwd _ :: At :: _ | Kwd _ :: DblDot :: At :: _ -> + loop (k + 1) + (* field declaration *) + | Const _ :: Kwd Function :: _ + | Kwd New :: Kwd Function :: _ when fdecl -> + junk_tokens (k - 2); + true + | Kwd Macro :: _ | Kwd Public :: _ | Kwd Static :: _ | Kwd Var :: _ | Kwd Override :: _ | Kwd Dynamic :: _ | Kwd Inline :: _ when fdecl -> + junk_tokens (k - 1); + true + | BrClose :: _ when tdecl -> + junk_tokens (k - 1); + false + (* type declaration *) + | Eof :: _ | Kwd Import :: _ | Kwd Using :: _ | Kwd Extern :: _ | Kwd Class :: _ | Kwd Interface :: _ | Kwd Enum :: _ | Kwd Typedef :: _ | Kwd Abstract :: _-> + junk_tokens (k - 1); + false + | [] -> + false + | _ -> + loop (k + 1) + in + loop 1 + and parse_class_field_resume tdecl s = - if not (do_resume()) then - plist parse_class_field s + if not (!in_display_file) then + plist (parse_class_field tdecl) s else try - let c = parse_class_field s in + let c = parse_class_field tdecl s in c :: parse_class_field_resume tdecl s - with Stream.Error _ | Stream.Failure -> - (* look for next variable/function or next type declaration *) - let rec junk k = - if k <= 0 then () else begin - Stream.junk s; - junk (k - 1); - end - in - (* - walk back tokens which are prefixing a type/field declaration - *) - let rec junk_tokens k = - if k = 0 then - () - else match List.rev_map fst (Stream.npeek k s) with - | Kwd Private :: _ -> junk_tokens (k - 1) - | (Const (Ident _) | Kwd _) :: DblDot :: At :: l - | (Const (Ident _) | Kwd _) :: At :: l -> - junk_tokens (List.length l) - | PClose :: l -> - (* count matching parenthesises for metadata call *) - let rec loop n = function - | [] -> [] - | POpen :: l -> if n = 0 then l else loop (n - 1) l - | PClose :: l -> loop (n + 1) l - | _ :: l -> loop n l - in - (match loop 0 l with - | (Const (Ident _) | Kwd _) :: At :: l - | (Const (Ident _) | Kwd _) :: DblDot :: At :: l -> junk_tokens (List.length l) - | _ -> - junk k) - | _ -> - junk k - in - let rec loop k = - match List.rev_map fst (Stream.npeek k s) with - (* metadata *) - | Kwd _ :: At :: _ | Kwd _ :: DblDot :: At :: _ -> - loop (k + 1) - (* field declaration *) - | Const _ :: Kwd Function :: _ - | Kwd New :: Kwd Function :: _ -> - junk_tokens (k - 2); - parse_class_field_resume tdecl s - | Kwd Macro :: _ | Kwd Public :: _ | Kwd Static :: _ | Kwd Var :: _ | Kwd Final :: _ | Kwd Override :: _ | Kwd Dynamic :: _ | Kwd Inline :: _ -> - junk_tokens (k - 1); - parse_class_field_resume tdecl s - | BrClose :: _ when tdecl -> - junk_tokens (k - 1); - [] - (* type declaration *) - | Eof :: _ | Kwd Import :: _ | Kwd Using :: _ | Kwd Extern :: _ | Kwd Class :: _ | Kwd Interface :: _ | Kwd Enum :: _ | Kwd Typedef :: _ | Kwd Abstract :: _-> - junk_tokens (k - 1); - [] - | [] -> - [] - | _ -> - loop (k + 1) - in - loop 1 + with + | Stream.Error msg -> + handle_stream_error msg s; + if resume tdecl true s then parse_class_field_resume tdecl s else [] + | Stream.Failure -> + if resume tdecl true s then parse_class_field_resume tdecl s else [] and parse_common_flags = parser - | [< '(Kwd Private,_); l = parse_common_flags >] -> DPrivate :: l - | [< '(Kwd Extern,_); l = parse_common_flags >] -> DExtern :: l + | [< '(Kwd Private,p); l = parse_common_flags >] -> (DPrivate,p) :: l + | [< '(Kwd Extern,p); l = parse_common_flags >] -> (DExtern,p) :: l + | [< '(Kwd Final,p); l = parse_common_flags >] -> (DFinal,p) :: l | [< >] -> [] and parse_meta_argument_expr s = - try - expr s - with Display e -> match fst e with - | EDisplay(e,_) -> - begin try - type_path (string_list_of_expr_path_raise e) false - with Exit -> - e - end - | _ -> + let e = expr s in + begin match fst e with + | EDisplay(e1,DKDot) -> + begin try + type_path (string_list_of_expr_path_raise e1) false (pos e1) + with Exit -> e + end + | _ -> + e + end and parse_meta_params pname s = match s with parser - | [< '(POpen,p) when p.pmin = pname.pmax; params = psep Comma parse_meta_argument_expr; '(PClose,_); >] -> params + | [< '(POpen,p) when p.pmin = pname.pmax; params = psep Comma parse_meta_argument_expr; >] -> + ignore(expect_unless_resume_p PClose s); + params | [< >] -> [] and parse_meta_entry = parser [< '(At,p1); s >] -> + let meta = check_resume p1 (fun () -> Some (Meta.Last,[],p1)) (fun () -> None) in match s with parser - | [< name,p = meta_name p1; params = parse_meta_params p; s >] -> (name,params,p) - | [< >] -> - if is_resuming p1 then (Meta.Last,[],p1) else serror() + | [< name,p = parse_meta_name p1; params = parse_meta_params p; s >] -> (name,params,punion p1 p) + | [< >] -> match meta with None -> serror() | Some meta -> meta and parse_meta = parser | [< entry = parse_meta_entry; s >] -> entry :: parse_meta s | [< >] -> [] -and meta_name p1 = parser - | [< '(Const (Ident i),p) when p.pmin = p1.pmax >] -> (Meta.Custom i), p - | [< '(Kwd k,p) when p.pmin = p1.pmax >] -> (Meta.Custom (s_keyword k)),p - | [< '(DblDot,p) when p.pmin = p1.pmax; s >] -> match s with parser - | [< '(Const (Ident i),p1) when p1.pmin = p.pmax >] -> (Meta.parse i),punion p p1 - | [< '(Kwd k,p1) when p1.pmin = p.pmax >] -> (Meta.parse (s_keyword k)),punion p p1 - | [< >] -> if is_resuming p then Meta.Last,p else raise Stream.Failure +and parse_meta_name_2 p1 acc s = + let part,p = match s with parser + | [< '(Const (Ident i),p) when p.pmin = p1.pmax >] -> i,p + | [< '(Kwd k,p) when p.pmin = p1.pmax >] -> s_keyword k,p + in + let acc = part :: acc in + match s with parser + | [< '(Dot,p1); part,p2 = parse_meta_name_2 p1 acc >] -> part,punion p p2 + | [< >] -> acc,punion p1 p + +and parse_meta_name p1 = parser + | [< '(DblDot,p) when p.pmin = p1.pmax; s >] -> + let meta = check_resume p (fun () -> Some (Meta.Last,p)) (fun() -> None) in + begin match s with parser + | [< name,p2 = parse_meta_name_2 p [] >] -> (Meta.parse (rev_concat "." name)),p2 + | [< >] -> match meta with None -> raise Stream.Failure | Some meta -> meta + end + | [< name,p2 = parse_meta_name_2 p1 [] >] -> (Meta.Custom (rev_concat "." name)),p2 and parse_enum_flags = parser | [< '(Kwd Enum,p) >] -> [] , p @@ -365,40 +481,84 @@ and parse_class_flags = parser and parse_complex_type_at p = parser | [< t = parse_complex_type >] -> t - | [< >] -> if is_resuming p then CTPath { tpackage = []; tname = ""; tparams = []; tsub = None },p else serror() + | [< s >] -> if would_skip_display_position p s then CTPath magic_type_path,p else serror() and parse_type_hint = parser - | [< '(DblDot,p1); t = parse_complex_type_at p1 >] -> t - -and parse_type_hint_with_pos s = match s with parser - | [< '(DblDot,p1); t = parse_complex_type_at p1 >] -> t + | [< '(DblDot,p1); s >] -> + let f () = parse_complex_type_at p1 s in + check_resume_range p1 s + (fun p2 -> + let ct = CTPath magic_type_path in + pignore(f); + ct,null_pos + ) + f and parse_type_opt = parser | [< t = parse_type_hint >] -> Some t | [< >] -> None -and parse_complex_type s = - let t = parse_complex_type_inner s in - parse_complex_type_next t s +and parse_complex_type s = parse_complex_type_maybe_named false s + +and parse_complex_type_maybe_named allow_named = parser + | [< '(POpen,p1); tl = psep Comma (parse_complex_type_maybe_named true); '(PClose,p2); s >] -> + begin match tl with + | [] | [(CTNamed _,_)] -> + (* it was () or (a:T) - clearly a new function type syntax, proceed with parsing return type *) + parse_function_type_next tl p1 s + | [t] -> + (* it was some single unnamed type in parenthesis - use old function type syntax *) + let t = CTParent t,punion p1 p2 in + parse_complex_type_next t s + | _ -> + (* it was multiple arguments - clearly a new function type syntax, proceed with parsing return type *) + parse_function_type_next tl p1 s + end + | [< s >] -> + let t = parse_complex_type_inner allow_named s in + parse_complex_type_next t s and parse_structural_extension = parser - | [< '(Binop OpGt,_); t = parse_type_path; '(Comma,_); s >] -> - t - -and parse_complex_type_inner = parser + | [< '(Binop OpGt,p1); s >] -> + match s with parser + | [< t = parse_type_path >] -> + begin match s with parser + | [< '(Comma,_) >] -> t + | [< >] -> syntax_error (Expected [","]) s t + end; + | [< >] -> + if would_skip_display_position p1 s then begin + begin match s with parser + | [< '(Comma,_) >] -> () + | [< >] -> () + end; + magic_type_path,null_pos + end else raise Stream.Failure + +and parse_complex_type_inner allow_named = parser | [< '(POpen,p1); t = parse_complex_type; '(PClose,p2) >] -> CTParent t,punion p1 p2 | [< '(BrOpen,p1); s >] -> (match s with parser - | [< l,p2 = parse_type_anonymous false false >] -> CTAnonymous l,punion p1 p2 + | [< l,p2 = parse_type_anonymous >] -> CTAnonymous l,punion p1 p2 | [< t = parse_structural_extension; s>] -> let tl = t :: plist parse_structural_extension s in (match s with parser - | [< l,p2 = parse_type_anonymous false false >] -> CTExtend (tl,l),punion p1 p2 + | [< l,p2 = parse_type_anonymous >] -> CTExtend (tl,l),punion p1 p2 | [< l,p2 = parse_class_fields true p1 >] -> CTExtend (tl,l),punion p1 p2) | [< l,p2 = parse_class_fields true p1 >] -> CTAnonymous l,punion p1 p2 | [< >] -> serror()) - | [< '(Question,p1); t,p2 = parse_complex_type_inner >] -> + | [< '(Question,p1); t,p2 = parse_complex_type_inner allow_named >] -> CTOptional (t,p2),punion p1 p2 + | [< n = dollar_ident; s >] -> + (match s with parser + | [< '(DblDot,_) when allow_named; t = parse_complex_type >] -> + let p1 = snd n in + let p2 = snd t in + CTNamed (n,t),punion p1 p2 + | [< s >] -> + let n,p = n in + let t,p = parse_type_path2 None [] n p s in + CTPath t,p) | [< t,p = parse_type_path >] -> CTPath t,p @@ -406,71 +566,123 @@ and parse_type_path s = parse_type_path1 None [] s and parse_type_path1 p0 pack = parser | [< name, p1 = dollar_ident_macro pack; s >] -> - if is_lower_ident name then - (match s with parser - | [< '(Dot,p) >] -> - if is_resuming p then - raise (TypePath (List.rev (name :: pack),None,false)) - else - parse_type_path1 (match p0 with None -> Some p1 | Some _ -> p0) (name :: pack) s - | [< '(Semicolon,_) >] -> - error (Custom "Type name should start with an uppercase letter") p1 - | [< >] -> serror()) - else - let sub,p2 = (match s with parser - | [< '(Dot,p); s >] -> - (if is_resuming p then - raise (TypePath (List.rev pack,Some (name,false),false)) - else match s with parser - | [< '(Const (Ident name),p2) when not (is_lower_ident name) >] -> Some name,p2 - | [< '(Binop OpOr,_) when do_resume() >] -> - set_resume p; - raise (TypePath (List.rev pack,Some (name,false),false)) - | [< >] -> serror()) - | [< >] -> None,p1 - ) in - let params,p2 = (match s with parser - | [< '(Binop OpLt,_); l = psep Comma parse_type_path_or_const; '(Binop OpGt,p2) >] -> l,p2 - | [< >] -> [],p2 - ) in - { - tpackage = List.rev pack; - tname = name; - tparams = params; - tsub = sub; - },punion (match p0 with None -> p1 | Some p -> p) p2 - | [< '(Binop OpOr,_) when do_resume() >] -> - raise (TypePath (List.rev pack,None,false)) + parse_type_path2 p0 pack name p1 s + +and parse_type_path2 p0 pack name p1 s = + if is_lower_ident name then + (match s with parser + | [< '(Dot,p) >] -> + check_resume p + (fun () -> raise (TypePath (List.rev (name :: pack),None,false,punion (match p0 with None -> p1 | Some p0 -> p0) p))) + (fun () -> parse_type_path1 (match p0 with None -> Some p1 | Some _ -> p0) (name :: pack) s) + | [< '(Semicolon,_) >] -> + error (Custom "Type name should start with an uppercase letter") p1 + | [< >] -> serror()) + else + let sub,p2 = (match s with parser + | [< '(Dot,p); s >] -> + (check_resume p + (fun () -> raise (TypePath (List.rev pack,Some (name,false),false,punion (match p0 with None -> p1 | Some p0 -> p0) p))) + (fun () -> match s with parser + | [< '(Const (Ident name),p2) when not (is_lower_ident name) >] -> Some name,p2 + | [< >] -> serror())) + | [< >] -> None,p1 + ) in + let params,p2 = (match s with parser + | [< '(Binop OpLt,plt); l = psep Comma (parse_type_path_or_const plt) >] -> + begin match s with parser + | [<'(Binop OpGt,p2) >] -> l,p2 + | [< >] -> + syntax_error (Expected [">"]) s (l,pos (last_token s)) + end + | [< >] -> [],p2 + ) in + { + tpackage = List.rev pack; + tname = name; + tparams = params; + tsub = sub; + },punion (match p0 with None -> p1 | Some p -> p) p2 and type_name = parser - | [< '(Const (Ident name),p) >] -> + | [< '(Const (Ident name),p); s >] -> if is_lower_ident name then - error (Custom "Type name should start with an uppercase letter") p + syntax_error (Custom "Type name should start with an uppercase letter") ~pos:(Some p) s (name,p) else name,p | [< '(Dollar name,p) >] -> "$" ^ name,p -and parse_type_path_or_const = parser +and parse_type_path_or_const plt = parser (* we can't allow (expr) here *) - | [< '(BkOpen,p1); l = parse_array_decl; '(BkClose,p2); s >] -> TPExpr (EArrayDecl l, punion p1 p2) + | [< '(BkOpen,p1); e = parse_array_decl p1 >] -> TPExpr (e) | [< t = parse_complex_type >] -> TPType t | [< '(Const c,p) >] -> TPExpr (EConst c,p) + | [< '(Kwd True,p) >] -> TPExpr (EConst (Ident "true"),p) + | [< '(Kwd False,p) >] -> TPExpr (EConst (Ident "false"),p) | [< e = expr >] -> TPExpr e - | [< >] -> serror() + | [< s >] -> + if !in_display_file then begin + if would_skip_display_position plt s then begin + let ct = CTPath magic_type_path in + TPType (ct,plt) + end else + raise Stream.Failure + end else + serror() -and parse_complex_type_next (t : type_hint) = parser - | [< '(Arrow,_); t2,p2 = parse_complex_type >] -> - (match t2 with +and parse_complex_type_next (t : type_hint) s = + let make_fun t2 p2 = match t2 with | CTFunction (args,r) -> CTFunction (t :: args,r),punion (pos t) p2 | _ -> - CTFunction ([t] , (t2,p2)),punion (pos t) p2) + CTFunction ([t] , (t2,p2)),punion (pos t) p2 + in + let make_intersection t2 p2 = match t2 with + | CTIntersection tl -> + CTIntersection (t :: tl),punion (pos t) p2 + | _ -> + CTIntersection ([t;t2,p2]),punion (pos t) p2 + in + match s with parser + | [< '(Arrow,pa); s >] -> + begin match s with parser + | [< t2,p2 = parse_complex_type >] -> make_fun t2 p2 + | [< >] -> + if would_skip_display_position pa s then begin + let ct = CTPath magic_type_path in + make_fun ct null_pos + end else serror() + end + | [< '(Binop OpAnd,pa); s >] -> + begin match s with parser + | [< t2,p2 = parse_complex_type >] -> make_intersection t2 p2 + | [< >] -> + if would_skip_display_position pa s then begin + let ct = CTPath magic_type_path in + make_intersection ct null_pos + end else serror() + end | [< >] -> t -and parse_type_anonymous opt final = parser - | [< '(Question,_) when not opt; s >] -> parse_type_anonymous true final s - | [< '(Kwd Final,_) when not opt && not final; s >] -> parse_type_anonymous opt true s - | [< name, p1 = ident; t = parse_type_hint_with_pos; s >] -> +and parse_function_type_next tl p1 = parser + | [< '(Arrow,pa); s >] -> + begin match s with parser + | [< tret = parse_complex_type_inner false >] -> CTFunction (tl,tret), punion p1 (snd tret) + | [< >] -> if would_skip_display_position pa s then begin + let ct = (CTPath magic_type_path),null_pos in + CTFunction (tl,ct), punion p1 pa + end else serror() + end + | [< >] -> serror () + +and parse_type_anonymous s = + let p0 = popt question_mark s in + match s with parser + | [< name, p1 = ident; t = parse_type_hint; s >] -> + let opt,p1 = match p0 with + | Some p -> true,p + | None -> false,p1 + in let p2 = pos (last_token s) in let next acc = { @@ -478,18 +690,22 @@ and parse_type_anonymous opt final = parser cff_meta = if opt then [Meta.Optional,[],null_pos] else []; cff_access = []; cff_doc = None; - cff_kind = if final then FProp(("default",null_pos),("never",null_pos),Some t,None) else FVar (Some t,None); + cff_kind = FVar (Some t,None); cff_pos = punion p1 p2; } :: acc in - match s with parser + begin match s with parser | [< '(BrClose,p2) >] -> next [],p2 | [< '(Comma,p2) >] -> (match s with parser | [< '(BrClose,p2) >] -> next [],p2 - | [< l,p2 = parse_type_anonymous false false >] -> next l,punion p1 p2 + | [< l,p2 = parse_type_anonymous >] -> next l,punion p1 p2 | [< >] -> serror()); - | [< >] -> serror() + | [< >] -> + syntax_error (Expected [",";"}"]) s (next [],p2) + end + | [< >] -> + if p0 = None then raise Stream.Failure else serror() and parse_enum s = let doc = get_doc s in @@ -500,7 +716,7 @@ and parse_enum s = | [< '(POpen,_); l = psep Comma parse_enum_param; '(PClose,_) >] -> l | [< >] -> [] ) in - let t = popt parse_type_hint_with_pos s in + let t = popt parse_type_hint s in let p2 = (match s with parser | [< p = semicolon >] -> p | [< >] -> serror() @@ -516,14 +732,14 @@ and parse_enum s = } and parse_enum_param = parser - | [< '(Question,_); name, _ = ident; t = parse_type_hint_with_pos >] -> (name,true,t) - | [< name, _ = ident; t = parse_type_hint_with_pos >] -> (name,false,t) + | [< '(Question,_); name, _ = ident; t = parse_type_hint >] -> (name,true,t) + | [< name, _ = ident; t = parse_type_hint >] -> (name,false,t) and parse_function_field doc meta al = parser - | [< '(Kwd Function,p1); name = parse_fun_name; pl = parse_constraint_params; '(POpen,_); args = psep Comma parse_fun_param; '(PClose,_); t = popt parse_type_hint_with_pos; s >] -> + | [< '(Kwd Function,p1); name = parse_fun_name; pl = parse_constraint_params; '(POpen,_); args = psep Comma parse_fun_param; '(PClose,_); t = popt parse_type_hint; s >] -> let e, p2 = (match s with parser - | [< e = toplevel_expr; s >] -> - (try ignore(semicolon s) with Error (Missing_semicolon,p) -> !display_error Missing_semicolon p); + | [< e = expr; s >] -> + ignore(semicolon s); Some e, pos e | [< p = semicolon >] -> None, p | [< >] -> serror() @@ -534,33 +750,55 @@ and parse_function_field doc meta al = parser f_type = t; f_expr = e; } in - name, punion p1 p2, FFun f, al + name,punion p1 p2,FFun f,al,meta and parse_var_field_assignment = parser - | [< '(Binop OpAssign,_); e = toplevel_expr; p2 = semicolon >] -> Some e , p2 + | [< '(Binop OpAssign,_); s >] -> + begin match s with parser + | [< '(Binop OpLt,p1); s >] -> + let e = handle_xml_literal p1 in + (* accept but don't expect semicolon *) + let p2 = match s with parser + | [< '(Semicolon,p) >] -> p + | [< >] -> pos e + in + Some e,p2 + | [< e = expr; p2 = semicolon >] -> Some e , p2 + | [< >] -> serror() + end | [< p2 = semicolon >] -> None , p2 | [< >] -> serror() -and parse_class_field s = +and parse_class_field tdecl s = let doc = get_doc s in + let meta = parse_meta s in match s with parser - | [< meta = parse_meta; al = parse_cf_rights true []; s >] -> - let name, pos, k, al = (match s with parser - | [< '(Kwd Var,p1); name = dollar_ident; s >] -> + | [< al = plist parse_cf_rights; s >] -> + let check_optional opt name = + if opt then begin + if not tdecl then syntax_error (Custom "?var syntax is only allowed in structures") ~pos:(Some (pos name)) s (); + (Meta.Optional,[],null_pos) :: meta + end else + meta + in + let name,pos,k,al,meta = (match s with parser + | [< '(Kwd Var,p1); opt,name = questionable_dollar_ident; s >] -> + let meta = check_optional opt name in begin match s with parser | [< '(POpen,_); i1 = property_ident; '(Comma,_); i2 = property_ident; '(PClose,_) >] -> - let t = popt parse_type_hint_with_pos s in + let t = popt parse_type_hint s in let e,p2 = parse_var_field_assignment s in - name, punion p1 p2, FProp (i1,i2,t, e), al - | [< t = popt parse_type_hint_with_pos; s >] -> + name,punion p1 p2,FProp (i1,i2,t,e),al,meta + | [< t = popt parse_type_hint; s >] -> let e,p2 = parse_var_field_assignment s in - name, punion p1 p2, FVar (t,e), al + name,punion p1 p2,FVar (t,e),al,meta end | [< '(Kwd Final,p1) >] -> begin match s with parser - | [< name = dollar_ident; t = popt parse_type_hint_with_pos; e,p2 = parse_var_field_assignment >] -> - name,punion p1 p2,FVar(t,e),(AFinal :: al) - | [< al = parse_cf_rights (not (List.mem AStatic al)) (AFinal :: al); f = parse_function_field doc meta al >] -> + | [< opt,name = questionable_dollar_ident; t = popt parse_type_hint; e,p2 = parse_var_field_assignment >] -> + let meta = check_optional opt name in + name,punion p1 p2,FVar(t,e),(al @ [AFinal,p1]),meta + | [< al2 = plist parse_cf_rights; f = parse_function_field doc meta (al @ ((AFinal,p1) :: al2)) >] -> f | [< >] -> serror() @@ -568,8 +806,34 @@ and parse_class_field s = | [< f = parse_function_field doc meta al >] -> f | [< >] -> - if al = [] then raise Stream.Failure else serror() + let check_override_completion po = + (* If there's an identifier in the stream, it must be a unfinished filter for + an override completion, e.g. `override toStr|`. In that case we simply ignore + the identifier. *) + begin match Stream.peek s with + | Some (Const (Ident _),_) -> Stream.junk s + | _ -> () + end; + would_skip_display_position po s + in + begin match List.rev al with + | [] -> raise Stream.Failure + | (AOverride,po) :: _ when check_override_completion po -> + let f = { + f_params = []; + f_args = []; + f_type = None; + f_expr = None + } in + let _,p2 = next_token s in + (magic_display_field_name,p2),punion po p2,FFun f,al,meta + | _ -> serror() + end ) in + let pos = match al with + | [] -> pos + | (_,p) :: _ -> punion p pos + in { cff_name = name; cff_doc = doc; @@ -579,15 +843,15 @@ and parse_class_field s = cff_kind = k; } -and parse_cf_rights allow_static l = parser - | [< '(Kwd Static,_) when allow_static; l = parse_cf_rights false (AStatic :: l) >] -> l - | [< '(Kwd Macro,_) when not(List.mem AMacro l); l = parse_cf_rights allow_static (AMacro :: l) >] -> l - | [< '(Kwd Public,_) when not(List.mem APublic l || List.mem APrivate l); l = parse_cf_rights allow_static (APublic :: l) >] -> l - | [< '(Kwd Private,_) when not(List.mem APublic l || List.mem APrivate l); l = parse_cf_rights allow_static (APrivate :: l) >] -> l - | [< '(Kwd Override,_) when not (List.mem AOverride l); l = parse_cf_rights false (AOverride :: l) >] -> l - | [< '(Kwd Dynamic,_) when not (List.mem ADynamic l); l = parse_cf_rights allow_static (ADynamic :: l) >] -> l - | [< '(Kwd Inline,_); l = parse_cf_rights allow_static (AInline :: l) >] -> l - | [< >] -> l +and parse_cf_rights = parser + | [< '(Kwd Static,p) >] -> AStatic,p + | [< '(Kwd Macro,p) >] -> AMacro,p + | [< '(Kwd Public,p) >] -> APublic,p + | [< '(Kwd Private,p) >] -> APrivate,p + | [< '(Kwd Override,p) >] -> AOverride,p + | [< '(Kwd Dynamic,p) >] -> ADynamic,p + | [< '(Kwd Inline,p) >] -> AInline,p + | [< '(Kwd Extern,p) >] -> AExtern,p and parse_fun_name = parser | [< name,p = dollar_ident >] -> name,p @@ -596,11 +860,11 @@ and parse_fun_name = parser and parse_fun_param s = let meta = parse_meta s in match s with parser - | [< '(Question,_); name, pn = dollar_ident; t = popt parse_type_hint_with_pos; c = parse_fun_param_value >] -> ((name,pn),true,meta,t,c) - | [< name, pn = dollar_ident; t = popt parse_type_hint_with_pos; c = parse_fun_param_value >] -> ((name,pn),false,meta,t,c) + | [< '(Question,_); name, pn = dollar_ident; t = popt parse_type_hint; c = parse_fun_param_value >] -> ((name,pn),true,meta,t,c) + | [< name, pn = dollar_ident; t = popt parse_type_hint; c = parse_fun_param_value >] -> ((name,pn),false,meta,t,c) and parse_fun_param_value = parser - | [< '(Binop OpAssign,_); e = toplevel_expr >] -> Some e + | [< '(Binop OpAssign,_); e = expr >] -> Some e | [< >] -> None and parse_fun_param_type = parser @@ -608,36 +872,59 @@ and parse_fun_param_type = parser | [< name = ident; t = parse_type_hint >] -> (name,false,t) and parse_constraint_params = parser - | [< '(Binop OpLt,_); l = psep Comma parse_constraint_param; '(Binop OpGt,_) >] -> l + | [< '(Binop OpLt,p); s >] -> + begin match s with parser + | [< l = psep_nonempty Comma parse_constraint_param; '(Binop OpGt,_) >] -> l + | [< >] -> + let pos = match s with parser + | [< '(Binop OpGt,p) >] -> Some p (* junk > so we don't get weird follow-up errors *) + | [< >] -> None + in + syntax_error (Expected ["type parameter"]) ~pos s []; + end | [< >] -> [] -and parse_constraint_param = parser - | [< meta = parse_meta; name = type_name; s >] -> +and parse_constraint_param s = + let meta = parse_meta s in + match s with parser + | [< name = type_name; s >] -> let params = (match s with parser | [< >] -> [] ) in - let ctl = (match s with parser + let cto = (match s with parser | [< '(DblDot,_); s >] -> (match s with parser - | [< '(POpen,_); l = psep Comma parse_complex_type; '(PClose,_) >] -> l - | [< t = parse_complex_type >] -> [t] + | [< t = parse_complex_type >] -> Some t | [< >] -> serror()) - | [< >] -> [] + | [< >] -> None ) in { tp_name = name; tp_params = params; - tp_constraints = ctl; + tp_constraints = cto; tp_meta = meta; } - -and parse_type_path_or_resume p1 s = match s with parser - | [< t = parse_type_path >] -> t - | [< >] -> if would_skip_resume p1 s then { tpackage = []; tname = ""; tparams = []; tsub = None },null_pos else raise Stream.Failure + | [< >] -> + (* If we have a metadata but no name afterwards, we have to fail hard. *) + if meta <> [] then syntax_error (Expected ["type name"]) s (); + raise Stream.Failure; + +and parse_type_path_or_resume p1 s = + let pnext = next_pos s in + let check_resume exc = + if !in_display_file && display_position#enclosed_in (punion p1 pnext) then + (magic_type_path,punion_next p1 s),true + else + raise exc + in + try + let t = parse_type_path s in + t,false + with Stream.Failure | Stream.Error _ as exc -> check_resume exc and parse_class_herit = parser - | [< '(Kwd Extends,p1); t = parse_type_path_or_resume p1 >] -> HExtends t - | [< '(Kwd Implements,p1); t = parse_type_path_or_resume p1 >] -> HImplements t + | [< '(Kwd Extends,p1); t,_ = parse_type_path_or_resume p1 >] -> HExtends t + | [< '(Kwd Implements,p1); t,_ = parse_type_path_or_resume p1 >] -> HImplements t and block1 = parser | [< name,p = dollar_ident; s >] -> block2 (name,p,NoQuotes) (Ident name) p s @@ -646,94 +933,140 @@ and block1 = parser and block2 name ident p s = match s with parser - | [< '(DblDot,_); e = expr; l = parse_obj_decl >] -> EObjectDecl ((name,e) :: l) + | [< '(DblDot,_) >] -> + let e = secure_expr s in + fst (parse_obj_decl name e p s) | [< >] -> - let e = expr_next (EConst ident,p) s in - try + let f s = + let e = expr_next (EConst ident,p) s in let _ = semicolon s in - let b = block [e] s in - EBlock b - with - | Error (err,p) -> - (!display_error) err p; - EBlock (block [e] s) + e + in + let el,_ = block_with_pos' [] f p s in + EBlock el and block acc s = fst (block_with_pos acc null_pos s) -and block_with_pos acc p s = +and block_with_pos' acc f p s = try (* because of inner recursion, we can't put Display handling in errors below *) - let e = try parse_block_elt s with Display e -> display (EBlock (List.rev (e :: acc)),snd e) in + let e = f s in block_with_pos (e :: acc) (pos e) s with | Stream.Failure -> List.rev acc,p - | Stream.Error _ -> - let tk , pos = next_token s in - (!display_error) (Unexpected tk) pos; - block_with_pos acc pos s - | Error (e,p) -> - (!display_error) e p; + | Stream.Error msg when !in_display_file -> + handle_stream_error msg s; + (block_with_pos acc (next_pos s) s) + | Error (e,p) when !in_display_file -> block_with_pos acc p s +and block_with_pos acc p s = + block_with_pos' acc parse_block_elt p s + and parse_block_elt = parser - | [< '(Kwd Var,p1); vl = parse_var_decls p1; p2 = semicolon >] -> + | [< '(Kwd Var,p1); vl = parse_var_decls false p1; p2 = semicolon >] -> + (EVars vl,punion p1 p2) + | [< '(Kwd Final,p1); vl = parse_var_decls true p1; p2 = semicolon >] -> (EVars vl,punion p1 p2) - | [< '(Kwd Inline,p1); '(Kwd Function,_); e = parse_function p1 true; _ = semicolon >] -> e + | [< '(Kwd Inline,p1); s >] -> + begin match s with parser + | [< '(Kwd Function,_); e = parse_function p1 true; _ = semicolon >] -> e + | [< e = secure_expr; _ = semicolon >] -> make_meta Meta.Inline [] e p1 + | [< >] -> serror() + end + | [< '(Binop OpLt,p1); s >] -> + let e = handle_xml_literal p1 in + (* accept but don't expect semicolon *) + begin match s with parser + | [< '(Semicolon,_) >] -> () + | [< >] -> () + end; + e | [< e = expr; _ = semicolon >] -> e -and parse_obj_decl = parser - | [< '(Comma,_); s >] -> - (match s with parser - | [< name,p = ident; '(DblDot,_); e = expr; l = parse_obj_decl >] -> ((name,p,NoQuotes),e) :: l - | [< '(Const (String name),p); '(DblDot,_); e = expr; l = parse_obj_decl >] -> ((name,p,DoubleQuotes),e) :: l - | [< >] -> []) - | [< >] -> [] - -and parse_array_decl = parser - | [< e = expr; s >] -> - (match s with parser - | [< '(Comma,_); l = parse_array_decl >] -> e :: l - | [< >] -> [e]) - | [< >] -> - [] +and parse_obj_decl name e p0 s = + let make_obj_decl el p1 = + EObjectDecl (List.rev el),punion p0 p1 + in + let rec loop p_end acc = match s with parser + | [< '(Comma,p1); s >] -> + let next_expr key = + let e = secure_expr s in + loop (pos e) ((key,e) :: acc) + in + let next key = match s with parser + | [< '(DblDot,_) >] -> + next_expr key + | [< >] -> + syntax_error (Expected [":"]) s (next_expr key) + in + begin match s with parser + | [< name,p = ident >] -> next (name,p,NoQuotes) + | [< '(Const (String name),p) >] -> next (name,p,DoubleQuotes) + | [< >] -> acc,p_end + end + | [< >] -> acc,p_end + in + let el,p_end = loop p0 [name,e] in + let e = make_obj_decl el p_end in + e + +and parse_array_decl p1 s = + let resume_or_fail p1 = + syntax_error (Expected ["expr";"]"]) s ( + let p = punion_next p1 s in + [mk_null_expr p],p + ) + in + let el,p2 = match s with parser + | [< '(BkClose,p2) >] -> [],p2 + | [< e0 = secure_expr >] -> + let rec loop acc = match s with parser + | [< '(Comma,pk) >] -> + begin match s with parser + | [< '(BkClose,p2) >] -> acc,p2 + | [< e = secure_expr >] -> loop (e :: acc) + | [< >] -> + syntax_error (Expected ["expr";"]"]) s (acc,pk) + end + | [< '(BkClose,p2) >] -> acc,p2 + | [< >] -> + syntax_error (Expected [",";"]"]) s (acc,next_pos s) + in + loop [e0] + | [< >] -> resume_or_fail p1 + in + EArrayDecl (List.rev el),punion p1 p2 -and parse_var_decl_head = parser - | [< name, p = dollar_ident; t = popt parse_type_hint_with_pos >] -> (name,t,p) +and parse_var_decl_head final = parser + | [< name, p = dollar_ident; t = popt parse_type_hint >] -> (name,final,t,p) and parse_var_assignment = parser | [< '(Binop OpAssign,p1); s >] -> - begin match s with parser - | [< e = expr >] -> Some e - | [< >] -> error (Custom "expression expected after =") p1 - end + Some (secure_expr s) | [< >] -> None -and parse_var_assignment_resume vl name pn t s = - try - let eo = parse_var_assignment s in - ((name,pn),t,eo) - with Display e -> - let v = ((name,pn),t,Some e) in - let e = (EVars(List.rev (v :: vl)),punion pn (pos e)) in - display e - -and parse_var_decls_next vl = parser - | [< '(Comma,p1); name,t,pn = parse_var_decl_head; s >] -> - let v_decl = parse_var_assignment_resume vl name pn t s in - parse_var_decls_next (v_decl :: vl) s +and parse_var_assignment_resume final vl name pn t s = + let eo = parse_var_assignment s in + ((name,pn),final,t,eo) + +and parse_var_decls_next final vl = parser + | [< '(Comma,p1); name,final,t,pn = parse_var_decl_head final; s >] -> + let v_decl = parse_var_assignment_resume final vl name pn t s in + parse_var_decls_next final (v_decl :: vl) s | [< >] -> vl -and parse_var_decls p1 = parser - | [< name,t,pn = parse_var_decl_head; s >] -> - let v_decl = parse_var_assignment_resume [] name pn t s in - List.rev (parse_var_decls_next [v_decl] s) +and parse_var_decls final p1 = parser + | [< name,final,t,pn = parse_var_decl_head final; s >] -> + let v_decl = parse_var_assignment_resume final [] name pn t s in + List.rev (parse_var_decls_next final [v_decl] s) | [< s >] -> error (Custom "Missing variable identifier") p1 -and parse_var_decl = parser - | [< name,t,pn = parse_var_decl_head; v_decl = parse_var_assignment_resume [] name pn t >] -> v_decl +and parse_var_decl final = parser + | [< name,final,t,pn = parse_var_decl_head final; v_decl = parse_var_assignment_resume final [] name pn t >] -> v_decl and inline_function = parser | [< '(Kwd Inline,_); '(Kwd Function,p1) >] -> true, p1 @@ -744,7 +1077,9 @@ and parse_macro_expr p = parser let _, to_type, _ = reify !in_macro in let t = to_type t p in (ECheckType (t,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some "ComplexType"; tparams = [] },null_pos)),p) - | [< '(Kwd Var,p1); vl = psep Comma parse_var_decl >] -> + | [< '(Kwd Var,p1); vl = psep Comma (parse_var_decl false) >] -> + reify_expr (EVars vl,p1) !in_macro + | [< '(Kwd Final,p1); vl = psep Comma (parse_var_decl true) >] -> reify_expr (EVars vl,p1) !in_macro | [< d = parse_class None [] [] false >] -> let _,_,to_type = reify !in_macro in @@ -753,7 +1088,7 @@ and parse_macro_expr p = parser reify_expr e !in_macro and parse_function p1 inl = parser - | [< name = popt dollar_ident; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = popt parse_type_hint_with_pos; s >] -> + | [< name = popt dollar_ident; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = popt parse_type_hint; s >] -> let make e = let f = { f_params = pl; @@ -761,31 +1096,37 @@ and parse_function p1 inl = parser f_args = al; f_expr = Some e; } in - EFunction ((match name with None -> None | Some (name,_) -> Some (if inl then "inline_" ^ name else name)),f), punion p1 (pos e) + let e = EFunction ((match name with None -> None | Some (name,pn) -> Some (name,pn)),f), punion p1 (pos e) in + if inl then make_meta Meta.Inline [] e p1 + else e in - (try - expr_next (make (secure_expr s)) s - with - Display e -> display (make e)) + make (secure_expr s) and arrow_expr = parser - | [< '(Arrow,_); s >] -> try let e = expr s in e,false with Display e -> e,true - | _ -> serror() + | [< '(Arrow,_); e = expr >] -> e + | [< >] -> serror() -and arrow_function p1 al er = +and arrow_function p1 al er s = let make e = - EFunction(None, { f_params = []; f_type = None; f_args = al; f_expr = Some (EReturn(Some e), (snd e)); }), punion p1 (pos e) + let p = pos e in + let return = (EMeta((Meta.ImplicitReturn, [], null_pos), (EReturn(Some e), p)), p) in + EFunction(None, { f_params = []; f_type = None; f_args = al; f_expr = Some return; }), punion p1 p in - let e,display_error = er in - if display_error then display (make e) else make e + List.iter (fun (_,_,ml,_,_) -> match ml with + | (_,_,p) :: _ -> syntax_error (Custom "Metadata on arrow function arguments is not allowed") ~pos:(Some p) s () + | [] -> () + ) al; + make er and arrow_ident_checktype e = (match e with | EConst(Ident n),p -> (n,p),None | ECheckType((EConst(Ident n),p),(t,pt)),_ -> (n,p),(Some (t,pt)) | _ -> serror()) -and arrow_first_param e = +and arrow_first_param e s = (match fst e with + | EConst(Ident ("true" | "false" | "null" | "this" | "super")) -> + syntax_error (Custom "Invalid argument name") ~pos:(Some (pos e)) s (("",null_pos),false,[],None,None) | EConst(Ident n) -> (n,snd e),false,[],None,None | EBinop(OpAssign,e1,e2) @@ -801,32 +1142,38 @@ and expr = parser begin try make_meta name params (secure_expr s) p with - | Display e -> - display (make_meta name params e p) - | Stream.Failure | Stream.Error _ when Path.unique_full_path p.pfile = (!resume_display).pfile -> - let e = EConst (Ident "null"),p in - display (make_meta name params e p) + | Stream.Failure | Stream.Error _ when !in_display_file -> + let e = EConst (Ident "null"),null_pos in + make_meta name params e p end + | [< '(Binop OpLt,p1) >] -> + handle_xml_literal p1 | [< '(BrOpen,p1); s >] -> - if is_resuming p1 then display (EDisplay ((EObjectDecl [],p1),false),p1); (match s with parser - | [< '(Binop OpOr,p2) when do_resume() >] -> - set_resume p1; - display (EDisplay ((EObjectDecl [],p1),false),p1); | [< b = block1; s >] -> let p2 = match s with parser | [< '(BrClose,p2) >] -> p2 | [< >] -> (* Ignore missing } if we are resuming and "guess" the last position. *) - if do_resume() then pos (next_token s) else serror() + syntax_error (Expected ["}"]) s (pos (next_token s)) in let e = (b,punion p1 p2) in (match b with | EObjectDecl _ -> expr_next e s - | _ -> e)) + | _ -> e) + | [< >] -> + check_resume p1 (fun() -> (EDisplay ((EObjectDecl [],p1),DKStructure),p1)) serror; + ) + | [< '(Kwd k,p) when !parsing_macro_cond; s >] -> + expr_next (EConst (Ident (s_keyword k)), p) s | [< '(Kwd Macro,p); s >] -> - parse_macro_expr p s - | [< '(Kwd Var,p1); v = parse_var_decl >] -> (EVars [v],p1) + begin match s with parser + | [< '(Dot,pd); e = parse_field (EConst (Ident "macro"),p) pd >] -> e + | [< e = parse_macro_expr p >] -> e + | [< >] -> serror() + end + | [< '(Kwd Var,p1); v = parse_var_decl false >] -> (EVars [v],p1) + | [< '(Kwd Final,p1); v = parse_var_decl true >] -> (EVars [v],p1) | [< '(Const c,p); s >] -> expr_next (EConst c,p) s | [< '(Kwd This,p); s >] -> expr_next (EConst (Ident "this"),p) s | [< '(Kwd True,p); s >] -> expr_next (EConst (Ident "true"),p) s @@ -837,7 +1184,7 @@ and expr = parser | [< '(POpen,pp); e = expr; s >] -> (match s with parser | [< '(Comma,pc); t = parse_complex_type; '(PClose,p2); s >] -> expr_next (ECast (e,Some t),punion p1 p2) s - | [< t,pt = parse_type_hint_with_pos; '(PClose,p2); s >] -> + | [< t,pt = parse_type_hint; '(PClose,p2); s >] -> let ep = EParenthesis (ECheckType(e,(t,pt)),punion p1 p2), punion p1 p2 in expr_next (ECast (ep,None),punion p1 (pos ep)) s | [< '(Const (Ident "is"),p_is); t = parse_type_path; '(PClose,p2); >] -> @@ -849,32 +1196,31 @@ and expr = parser | [< >] -> serror()) | [< e = secure_expr >] -> expr_next (ECast (e,None),punion p1 (pos e)) s) | [< '(Kwd Throw,p); e = expr >] -> (EThrow e,p) - | [< '(Kwd New,p1); t = parse_type_path; s >] -> + | [< '(Kwd New,p1); t,_ = parse_type_path_or_resume p1; s >] -> begin match s with parser | [< '(POpen,po); e = parse_call_params (fun el p2 -> (ENew(t,el)),punion p1 p2) po >] -> expr_next e s | [< >] -> - if do_resume() then (ENew(t,[]),punion p1 (pos t)) - else serror() + syntax_error (Expected ["("]) s (ENew(t,[]),punion p1 (pos t)) end | [< '(POpen,p1); s >] -> (match s with parser | [< '(PClose,p2); er = arrow_expr; >] -> - arrow_function p1 [] er + arrow_function p1 [] er s | [< '(Question,p2); al = psep Comma parse_fun_param; '(PClose,_); er = arrow_expr; >] -> let al = (match al with | (np,_,_,topt,e) :: al -> (np,true,[],topt,e) :: al | _ -> assert false ) in - arrow_function p1 al er + arrow_function p1 al er s | [< e = expr; s >] -> (match s with parser | [< '(PClose,p2); s >] -> expr_next (EParenthesis e, punion p1 p2) s | [< '(Comma,pc); al = psep Comma parse_fun_param; '(PClose,_); er = arrow_expr; >] -> - arrow_function p1 ((arrow_first_param e) :: al) er - | [< t,pt = parse_type_hint_with_pos; s >] -> (match s with parser + arrow_function p1 ((arrow_first_param e s) :: al) er s + | [< t,pt = parse_type_hint; s >] -> (match s with parser | [< '(PClose,p2); s >] -> expr_next (EParenthesis (ECheckType(e,(t,pt)),punion p1 p2), punion p1 p2) s | [< '(Comma,pc); al = psep Comma parse_fun_param; '(PClose,_); er = arrow_expr; >] -> let (np,_) = arrow_ident_checktype e in - arrow_function p1 ((np,false,[],(Some(t,pt)),None) :: al) er + arrow_function p1 ((np,false,[],(Some(t,pt)),None) :: al) er s | [< '((Binop OpAssign),p2); ea1 = expr; s >] -> let with_args al er = (match fst e with | EConst(Ident n) -> - arrow_function p1 (((n,snd e),true,[],(Some(t,pt)),(Some ea1)) :: al) er + arrow_function p1 (((n,snd e),true,[],(Some(t,pt)),(Some ea1)) :: al) er s | _ -> serror()) in (match s with parser @@ -885,9 +1231,10 @@ and expr = parser | [< >] -> serror()) | [< >] -> serror()) | [< '(Const (Ident "is"),p_is); t = parse_type_path; '(PClose,p2); >] -> expr_next (make_is e t (punion p1 p2) p_is) s - | [< >] -> serror()) + | [< >] -> + syntax_error (Expected [")";",";":";"is"]) s (expr_next (EParenthesis e, punion p1 (pos e)) s)) ) - | [< '(BkOpen,p1); l = parse_array_decl; '(BkClose,p2); s >] -> expr_next (EArrayDecl l, punion p1 p2) s + | [< '(BkOpen,p1); e = parse_array_decl p1; s >] -> expr_next e s | [< '(Kwd Function,p1); e = parse_function p1 false; >] -> e | [< '(Unop op,p1) when is_prefix op; e = expr >] -> make_unop op e p1 | [< '(Binop OpSub,p1); e = expr >] -> @@ -899,68 +1246,101 @@ and expr = parser | [< '(Const (Int i),p); e = expr_next (EConst (Int i),p) >] -> e | [< '(Const (Float f),p); e = expr_next (EConst (Float f),p) >] -> e | [< >] -> serror()) */*) - | [< '(Kwd For,p); '(POpen,_); it = expr; '(PClose,_); s >] -> - (try - let e = secure_expr s in - (EFor (it,e),punion p (pos e)) - with - Display e -> display (EFor (it,e),punion p (pos e))) - | [< '(Kwd If,p); '(POpen,_); cond = expr; '(PClose,_); e1 = expr; s >] -> + | [< '(Kwd For,p); '(POpen,_); it = secure_expr; s >] -> + let e = match s with parser + | [< '(PClose,_); e = secure_expr >] -> e + | [< >] -> + syntax_error (Expected [")"]) s (mk_null_expr (pos it)) + in + (EFor (it,e),punion p (pos e)) + | [< '(Kwd If,p); '(POpen,_); cond = secure_expr; s >] -> + let e1 = match s with parser + | [< '(PClose,_); e1 = secure_expr >] -> e1 + | [< >] -> + syntax_error (Expected [")"]) s (mk_null_expr (pos cond)) + in let e2 = (match s with parser - | [< '(Kwd Else,_); e2 = expr; s >] -> Some e2 + | [< '(Kwd Else,_); e2 = secure_expr; s >] -> Some e2 | [< >] -> - match Stream.npeek 2 s with - | [(Semicolon,_); (Kwd Else,_)] -> - Stream.junk s; - Stream.junk s; - Some (secure_expr s) + (* We check this in two steps to avoid the lexer missing tokens (#8565). *) + match Stream.npeek 1 s with + | [(Semicolon,_)] -> + begin match Stream.npeek 2 s with + | [(Semicolon,_);(Kwd Else,_)] -> + Stream.junk s; + Stream.junk s; + Some (secure_expr s) + | _ -> + None + end | _ -> None ) in (EIf (cond,e1,e2), punion p (match e2 with None -> pos e1 | Some e -> pos e)) - | [< '(Kwd Return,p); e = popt expr >] -> (EReturn e, match e with None -> p | Some e -> punion p (pos e)) + | [< '(Kwd Return,p); s >] -> + begin match s with parser + | [< e = expr >] -> (EReturn (Some e),punion p (pos e)) + | [< >] -> + if would_skip_display_position p s then (EReturn (Some (mk_null_expr (punion_next p s))),p) + else (EReturn None,p) + end | [< '(Kwd Break,p) >] -> (EBreak,p) | [< '(Kwd Continue,p) >] -> (EContinue,p) - | [< '(Kwd While,p1); '(POpen,_); cond = expr; '(PClose,_); s >] -> - (try - let e = secure_expr s in - (EWhile (cond,e,NormalWhile),punion p1 (pos e)) - with - Display e -> display (EWhile (cond,e,NormalWhile),punion p1 (pos e))) - | [< '(Kwd Do,p1); e = expr; '(Kwd While,_); '(POpen,_); cond = expr; '(PClose,_); s >] -> (EWhile (cond,e,DoWhile),punion p1 (pos e)) - | [< '(Kwd Switch,p1); e = expr; '(BrOpen,_); cases , def = parse_switch_cases e []; '(BrClose,p2); s >] -> (ESwitch (e,cases,def),punion p1 p2) - | [< '(Kwd Try,p1); e = expr; cl,p2 = parse_catches e [] (pos e) >] -> (ETry (e,cl),punion p1 p2) + | [< '(Kwd While,p1); '(POpen,_); cond = secure_expr; s >] -> + let e = match s with parser + | [< '(PClose,_); e = secure_expr >] -> e + | [< >] -> + syntax_error (Expected [")"]) s (mk_null_expr (pos cond)) + in + (EWhile (cond,e,NormalWhile),punion p1 (pos e)) + | [< '(Kwd Do,p1); e = secure_expr; s >] -> + begin match s with parser + | [< '(Kwd While,_); '(POpen,_); cond = secure_expr; s >] -> + let p2 = expect_unless_resume_p PClose s in + (EWhile (cond,e,DoWhile),punion p1 p2) + | [< >] -> + syntax_error (Expected ["while"]) s e (* ignore do *) + end + | [< '(Kwd Switch,p1); e = secure_expr; s >] -> + begin match s with parser + | [< '(BrOpen,_); cases , def = parse_switch_cases e [] >] -> + let p2 = match s with parser + | [< '(BrClose,p2) >] -> p2 + | [< >] -> + (* Ignore missing } if we are resuming and "guess" the last position. *) + syntax_error (Expected ["}"]) s (pos (next_token s)) + in + (ESwitch (e,cases,def),punion p1 p2) + | [< >] -> + syntax_error (Expected ["{"]) s (ESwitch(e,[],None),punion p1 (pos e)) + end + | [< '(Kwd Try,p1); e = secure_expr; cl,p2 = parse_catches e [] (pos e) >] -> (ETry (e,cl),punion p1 p2) | [< '(IntInterval i,p1); e2 = expr >] -> make_binop OpInterval (EConst (Int i),p1) e2 - | [< '(Kwd Untyped,p1); e = expr >] -> (EUntyped e,punion p1 (pos e)) + | [< '(Kwd Untyped,p1); e = secure_expr >] -> (EUntyped e,punion p1 (pos e)) | [< '(Dollar v,p); s >] -> expr_next (EConst (Ident ("$"^v)),p) s + | [< '(Kwd Inline,p); e = secure_expr >] -> make_meta Meta.Inline [] e p -and expr_next e1 = parser +and expr_next e1 s = + try + expr_next' e1 s + with Stream.Error msg when !in_display -> + handle_stream_error msg s; + e1 + +and expr_next' e1 = parser | [< '(BrOpen,p1) when is_dollar_ident e1; eparam = expr; '(BrClose,p2); s >] -> (match fst e1 with | EConst(Ident n) -> expr_next (EMeta((Meta.from_string n,[],snd e1),eparam), punion p1 p2) s | _ -> assert false) - | [< '(Dot,p); s >] -> - if is_resuming p then display (EDisplay (e1,false),p); - (match s with parser - | [< '(Kwd Macro,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"macro") , punion (pos e1) p2) s - | [< '(Kwd Extern,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"extern") , punion (pos e1) p2) s - | [< '(Kwd New,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"new") , punion (pos e1) p2) s - | [< '(Const (Ident f),p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,f) , punion (pos e1) p2) s - | [< '(Dollar v,p2); s >] -> expr_next (EField (e1,"$"^v) , punion (pos e1) p2) s - | [< '(Binop OpOr,p2) when do_resume() >] -> - set_resume p; - display (EDisplay (e1,false),p) (* help for debug display mode *) - | [< >] -> - (* turn an integer followed by a dot into a float *) - match e1 with - | (EConst (Int v),p2) when p2.pmax = p.pmin -> expr_next (EConst (Float (v ^ ".")),punion p p2) s - | _ -> serror()) + | [< '(Dot,p); e = parse_field e1 p >] -> e | [< '(POpen,p1); e = parse_call_params (fun el p2 -> (ECall(e1,el)),punion (pos e1) p2) p1; s >] -> expr_next e s - | [< '(BkOpen,_); e2 = expr; '(BkClose,p2); s >] -> + | [< '(BkOpen,p1); e2 = secure_expr; s >] -> + let p2 = expect_unless_resume_p BkClose s in + let e2 = check_signature_mark e2 p1 p2 in expr_next (EArray (e1,e2), punion (pos e1) p2) s | [< '(Arrow,pa); s >] -> - let er = try let e = expr s in e,false with Display e -> e,true - in arrow_function (snd e1) [arrow_first_param e1] er + let er = expr s in + arrow_function (snd e1) [arrow_first_param e1 s] er s | [< '(Binop OpGt,p1); s >] -> (match s with parser | [< '(Binop OpGt,p2) when p1.pmax = p2.pmin; s >] -> @@ -975,48 +1355,63 @@ and expr_next e1 = parser make_binop OpGte e1 (secure_expr s) | [< e2 = secure_expr >] -> make_binop OpGt e1 e2) - | [< '(Binop op,_); s >] -> - (try - (match s with parser - | [< e2 = expr >] -> make_binop op e1 e2 - | [< >] -> serror()) - with Display e2 -> - raise (Display (make_binop op e1 e2))) + | [< '(Binop op,_); e2 = secure_expr >] -> make_binop op e1 e2 | [< '(Unop op,p) when is_postfix e1 op; s >] -> expr_next (EUnop (op,Postfix,e1), punion (pos e1) p) s - | [< '(Question,_); e2 = expr; '(DblDot,_); e3 = expr >] -> - (ETernary (e1,e2,e3),punion (pos e1) (pos e3)) + | [< '(Question,_); e2 = expr; s >] -> + begin match s with parser + | [< '(DblDot,_); e3 = expr >] -> (ETernary (e1,e2,e3),punion (pos e1) (pos e3)) + | [< >] -> syntax_error (Expected [":"]) s e2 + end | [< '(Kwd In,_); e2 = expr >] -> make_binop OpIn e1 e2 | [< >] -> e1 +and parse_field e1 p s = + check_resume p (fun () -> (EDisplay (e1,DKDot),p)) (fun () -> + begin match s with parser + | [< '(Kwd Macro,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"macro") , punion (pos e1) p2) s + | [< '(Kwd Extern,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"extern") , punion (pos e1) p2) s + | [< '(Kwd New,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"new") , punion (pos e1) p2) s + | [< '(Kwd k,p2) when !parsing_macro_cond && p.pmax = p2.pmin; s >] -> expr_next (EField (e1,s_keyword k) , punion (pos e1) p2) s + | [< '(Const (Ident f),p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,f) , punion (pos e1) p2) s + | [< '(Dollar v,p2); s >] -> expr_next (EField (e1,"$"^v) , punion (pos e1) p2) s + | [< >] -> + (* turn an integer followed by a dot into a float *) + match e1 with + | (EConst (Int v),p2) when p2.pmax = p.pmin -> expr_next (EConst (Float (v ^ ".")),punion p p2) s + | _ -> serror() + end + ) + and parse_guard = parser | [< '(Kwd If,p1); '(POpen,_); e = expr; '(PClose,_); >] -> e and expr_or_var = parser - | [< '(Kwd Var,p1); name,p2 = dollar_ident; >] -> EVars [(name,p2),None,None],punion p1 p2 - | [< e = expr >] -> e + | [< '(Kwd Var,p1); name,p2 = dollar_ident; >] -> EVars [(name,p2),false,None,None],punion p1 p2 + | [< '(Kwd Final,p1); name,p2 = dollar_ident; >] -> EVars [(name,p2),true,None,None],punion p1 p2 + | [< e = secure_expr >] -> e and parse_switch_cases eswitch cases = parser - | [< '(Kwd Default,p1); '(DblDot,_); s >] -> - let b,p2 = (try block_with_pos [] p1 s with Display e -> display (ESwitch (eswitch,cases,Some (Some e,punion p1 (pos e))),punion (pos eswitch) (pos e))) in + | [< '(Kwd Default,p1); '(DblDot,pdot); s >] -> + let b,p2 = (block_with_pos [] p1 s) in let b = match b with - | [] -> None,p1 + | [] -> None,pdot | _ -> let p = punion p1 p2 in Some ((EBlock b,p)),p in let l , def = parse_switch_cases eswitch cases s in - (match def with None -> () | Some _ -> error Duplicate_default p1); + (match def with None -> () | Some _ -> syntax_error Duplicate_default ~pos:(Some p1) s ()); l , Some b - | [< '(Kwd Case,p1); el = psep Comma expr_or_var; eg = popt parse_guard; '(DblDot,_); s >] -> + | [< '(Kwd Case,p1); el = psep Comma expr_or_var; eg = popt parse_guard; s >] -> + let pdot = expect_unless_resume_p DblDot s in + if !was_auto_triggered then check_resume pdot (fun () -> ()) (fun () -> ()); (match el with - | [] -> error (Custom "case without a pattern is not allowed") p1 + | [] -> syntax_error (Custom "case without a pattern is not allowed") ~pos:(Some p1) s ([],None) | _ -> - let b,p2 = (try block_with_pos [] p1 s with Display e -> display (ESwitch (eswitch,List.rev ((el,eg,Some e,punion p1 (pos e)) :: cases),None),punion (pos eswitch) (pos e))) in + let b,p2 = (block_with_pos [] p1 s) in let b,p = match b with - | [] -> - let p2 = match eg with Some e -> pos e | None -> match List.rev el with (_,p) :: _ -> p | [] -> p1 in - None,punion p1 p2 + | [] -> None,punion p1 pdot | _ -> let p = punion p1 p2 in Some ((EBlock b,p)),p in parse_switch_cases eswitch ((el,eg,b,p) :: cases) s @@ -1027,12 +1422,7 @@ and parse_switch_cases eswitch cases = parser and parse_catch etry = parser | [< '(Kwd Catch,p); '(POpen,_); name, pn = dollar_ident; s >] -> match s with parser - | [< t,pt = parse_type_hint_with_pos; '(PClose,_); s >] -> - (try - let e = secure_expr s in - ((name,pn),(t,pt),e,punion p (pos e)),(pos e) - with - Display e -> display (ETry (etry,[(name,pn),(t,pt),e,(pos e)]),punion (pos etry) (pos e))) + | [< t,pt = parse_type_hint; '(PClose,_); e = secure_expr >] -> ((name,pn),(t,pt),e,punion p (pos e)),(pos e) | [< '(_,p) >] -> error Missing_type p and parse_catches etry catches pmax = parser @@ -1040,85 +1430,99 @@ and parse_catches etry catches pmax = parser | [< >] -> List.rev catches,pmax and parse_call_params f p1 s = - let make_display_call el p2 = - let e = f el p2 in - display (EDisplay(e,true),pos e) - in - if is_resuming p1 then make_display_call [] p1; - let rec parse_next_param acc p1 = - let e = try - expr s - with - | Stream.Error _ | Stream.Failure as exc -> - let p2 = pos (next_token s) in - if encloses_resume (punion p1 p2) then make_display_call (List.rev acc) p2 - else raise exc - | Display e -> - display (f (List.rev (e :: acc)) (pos e)) - in + if not !in_display_file then begin + let el = psep Comma expr s in match s with parser - | [< '(PClose,p2) >] -> f (List.rev (e :: acc)) p2 - | [< '(Comma,p2) >] -> parse_next_param (e :: acc) p2 - | [< '(Semicolon,p2) >] -> if encloses_resume (punion p1 p2) then make_display_call (List.rev acc) p2 else serror() + | [< '(PClose,p2) >] -> f el p2 | [< >] -> - let p2 = pos (next_token s) in - if encloses_resume (punion p1 p2) then make_display_call (List.rev (e :: acc)) p2 else serror() - in - match s with parser - | [< '(PClose,p2) >] -> f [] p2 - | [< '(Binop OpOr,p2) when do_resume() >] -> - set_resume p1; - make_display_call [] p2 - | [< >] -> parse_next_param [] p1 + let expected = if el = [] then ["expression";")"] else [",";")"] in + syntax_error (Expected expected) s (f el (last_pos s)) + end else begin + let rec parse_next_param acc p1 = + let e = try + expr s + with + | Stream.Failure -> + let expected = "expression" :: (if acc = [] then [")"] else []) in + syntax_error (Expected expected) s (); + mk_null_expr (punion_next p1 s) + | Stream.Error msg -> + handle_stream_error msg s; + mk_null_expr (punion_next p1 s) + in + match s with parser + | [< '(PClose,p2) >] -> + let e = check_signature_mark e p1 p2 in + f (List.rev (e :: acc)) p2 + | [< '(Comma,p2) >] -> + let e = check_signature_mark e p1 p2 in + parse_next_param (e :: acc) p2 + | [< >] -> + let p2 = next_pos s in + syntax_error (Expected [",";")"]) s (); + let e = check_signature_mark e p1 p2 in + f (List.rev (e :: acc)) p2 + in + match s with parser + | [< '(PClose,p2) >] -> f [] p2 + | [< >] -> parse_next_param [] p1 + end + +(* Tries to parse a toplevel expression and defaults to a null expression when in display mode. + This function always accepts in display mode and should only be used for expected expressions, + not accepted ones! *) +and secure_expr = parser + | [< e = expr >] -> e + | [< s >] -> + syntax_error (Expected ["expression"]) s ( + let last = last_token s in + let plast = pos last in + let offset = match fst last with + | Const _ | Kwd _ | Dollar _ -> 1 + | _ -> 0 + in + let plast = {plast with pmin = plast.pmax + offset} in + mk_null_expr (punion_next plast s) + ) -and parse_macro_cond allow_op s = - match s with parser - | [< '(Const (Ident t),p) >] -> - parse_macro_ident allow_op t p s - | [< '(Const (String s),p) >] -> - None, (EConst (String s),p) - | [< '(Const (Int i),p) >] -> - None, (EConst (Int i),p) - | [< '(Const (Float f),p) >] -> - None, (EConst (Float f),p) - | [< '(Kwd k,p) >] -> - parse_macro_ident allow_op (s_keyword k) p s - | [< '(POpen, p1); _,e = parse_macro_cond true; '(PClose, p2) >] -> - let e = (EParenthesis e,punion p1 p2) in - if allow_op then parse_macro_op e s else None, e - | [< '(Unop op,p); tk, e = parse_macro_cond allow_op >] -> - tk, make_unop op e p - -and parse_macro_ident allow_op t p s = +let rec validate_macro_cond s e = match fst e with + | EConst (Ident _) + | EConst (String _) + | EConst (Int _) + | EConst (Float _) + -> e + | EUnop (op,p,e1) -> (EUnop (op, p, validate_macro_cond s e1), snd e) + | EBinop (op,e1,e2) -> (EBinop(op, (validate_macro_cond s e1), (validate_macro_cond s e2)), snd e) + | EParenthesis (e1) -> (EParenthesis (validate_macro_cond s e1), snd e) + | EField(e1,name) -> (EField(validate_macro_cond s e1,name), snd e) + | ECall ((EConst (Ident _),_) as i, args) -> (ECall (i,List.map (validate_macro_cond s) args),snd e) + | _ -> syntax_error (Custom ("Invalid conditional expression")) ~pos:(Some (pos e)) s ((EConst (Ident "false"),(pos e))) + +let parse_macro_ident t p s = if t = "display" then Hashtbl.replace special_identifier_files (Path.unique_full_path p.pfile) t; let e = (EConst (Ident t),p) in - if not allow_op then - None, e - else - parse_macro_op e s - -and parse_macro_op e s = - match Stream.peek s with - | Some (Binop op,_) -> - Stream.junk s; - let op = match Stream.peek s with - | Some (Binop OpAssign,_) when op = OpGt -> - Stream.junk s; - OpGte - | _ -> op - in - let tk, e2 = (try parse_macro_cond true s with Stream.Failure -> serror()) in - tk, make_binop op e e2 - | tk -> - tk, e + None, e -and toplevel_expr s = +let rec parse_macro_cond s = + parsing_macro_cond := true; try - expr s - with - Display e -> e - -and secure_expr s = - match s with parser - | [< e = expr >] -> e - | [< >] -> serror() \ No newline at end of file + let cond = (match s with parser + | [< '(Const (Ident t),p) >] -> + parse_macro_ident t p s + | [< '(Const (String s),p) >] -> + None, (EConst (String s),p) + | [< '(Const (Int i),p) >] -> + None, (EConst (Int i),p) + | [< '(Const (Float f),p) >] -> + None, (EConst (Float f),p) + | [< '(Kwd k,p) >] -> + parse_macro_ident (s_keyword k) p s + | [< '(Unop op,p); tk, e = parse_macro_cond >] -> + tk, make_unop op e p + | [< '(POpen,p1); (e,p) = expr; '(PClose,_) >] -> + None, (EParenthesis(validate_macro_cond s (e,p)),p1)) in + parsing_macro_cond := false; + cond + with e -> + parsing_macro_cond := false; + raise e \ No newline at end of file diff --git a/src/syntax/lexer.ml b/src/syntax/lexer.ml index eacd3e60dba..72947fdbc91 100644 --- a/src/syntax/lexer.ml +++ b/src/syntax/lexer.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -28,11 +28,18 @@ type error_msg = | Unterminated_regexp | Unclosed_comment | Unclosed_code - | Invalid_escape of char + | Invalid_escape of char * (string option) | Invalid_option + | Unterminated_markup exception Error of error_msg * pos +type xml_lexing_context = { + open_tag : string; + close_tag : string; + lexbuf : Sedlexing.lexbuf; +} + let error_msg = function | Invalid_character c when c > 32 && c < 128 -> Printf.sprintf "Invalid character '%c'" (char_of_int c) | Invalid_character c -> Printf.sprintf "Invalid character 0x%.2X" c @@ -40,8 +47,10 @@ let error_msg = function | Unterminated_regexp -> "Unterminated regular expression" | Unclosed_comment -> "Unclosed comment" | Unclosed_code -> "Unclosed code string" - | Invalid_escape c -> Printf.sprintf "Invalid escape sequence \\%s" (Char.escaped c) + | Invalid_escape (c,None) -> Printf.sprintf "Invalid escape sequence \\%s" (Char.escaped c) + | Invalid_escape (c,Some msg) -> Printf.sprintf "Invalid escape sequence \\%s. %s" (Char.escaped c) msg | Invalid_option -> "Invalid regular expression option" + | Unterminated_markup -> "Unterminated markup literal" type lexer_file = { lfile : string; @@ -84,7 +93,8 @@ let keywords = Switch;Case;Default;Public;Private;Try;Untyped; Catch;New;This;Throw;Extern;Enum;In;Interface; Cast;Override;Dynamic;Typedef;Package; - Inline;Using;Null;True;False;Abstract;Macro;Final]; + Inline;Using;Null;True;False;Abstract;Macro;Final; + Operator;Overload]; h let is_valid_identifier s = try @@ -188,7 +198,20 @@ let resolve_pos file = | '\r' -> ignore(input_char ch); inc 2 - | _ -> fun () -> 1 + | c -> (fun () -> + let rec skip n = + if n > 0 then begin + ignore(input_char ch); + skip (n - 1) + end + in + let code = int_of_char c in + if code < 0xC0 then () + else if code < 0xE0 then skip 1 + else if code < 0xF0 then skip 2 + else skip 3; + 1 + ) in loop (p + i()) in @@ -243,12 +266,14 @@ let mk lexbuf t = let mk_ident lexbuf = let s = lexeme lexbuf in - mk lexbuf (try Kwd (Hashtbl.find keywords s) with Not_found -> Const (Ident s)) + mk lexbuf (Const (Ident s)) + +let mk_keyword lexbuf kwd = + mk lexbuf (Kwd kwd) let invalid_char lexbuf = error (Invalid_character (lexeme_char lexbuf 0)) (lexeme_start lexbuf) - let ident = [%sedlex.regexp? ( Star '_', @@ -265,10 +290,27 @@ let ident = [%sedlex.regexp? ) ] +let sharp_ident = [%sedlex.regexp? + ( + ('a'..'z' | 'A'..'Z' | '_'), + Star ('a'..'z' | 'A'..'Z' | '0'..'9' | '_'), + Star ( + '.', + ('a'..'z' | 'A'..'Z' | '_'), + Star ('a'..'z' | 'A'..'Z' | '0'..'9' | '_') + ) + ) +] + let idtype = [%sedlex.regexp? Star '_', 'A'..'Z', Star ('_' | 'a'..'z' | 'A'..'Z' | '0'..'9')] let integer = [%sedlex.regexp? ('1'..'9', Star ('0'..'9')) | '0'] +(* https://www.w3.org/TR/xml/#sec-common-syn plus '$' for JSX *) +let xml_name_start_char = [%sedlex.regexp? '$' | ':' | 'A'..'Z' | '_' | 'a'..'z' | 0xC0 .. 0xD6 | 0xD8 .. 0xF6 | 0xF8 .. 0x2FF | 0x370 .. 0x37D | 0x37F .. 0x1FFF | 0x200C .. 0x200D | 0x2070 .. 0x218F | 0x2C00 .. 0x2FEF | 0x3001 .. 0xD7FF | 0xF900 .. 0xFDCF | 0xFDF0 .. 0xFFFD | 0x10000 .. 0xEFFFF] +let xml_name_char = [%sedlex.regexp? xml_name_start_char | '-' | '.' | '0'..'9' | 0xB7 | 0x0300 .. 0x036F | 0x203F .. 0x2040] +let xml_name = [%sedlex.regexp? Opt(xml_name_start_char, Star xml_name_char)] + let rec skip_header lexbuf = match%sedlex lexbuf with | 0xfeff -> skip_header lexbuf @@ -354,13 +396,13 @@ let rec token lexbuf = reset(); let pmin = lexeme_start lexbuf in let pmax = (try string lexbuf with Exit -> error Unterminated_string pmin) in - let str = (try unescape (contents()) with Invalid_escape_sequence(c,i) -> error (Invalid_escape c) (pmin + i)) in + let str = (try unescape (contents()) with Invalid_escape_sequence(c,i,msg) -> error (Invalid_escape (c,msg)) (pmin + i)) in mk_tok (Const (String str)) pmin pmax; | "'" -> reset(); let pmin = lexeme_start lexbuf in let pmax = (try string2 lexbuf with Exit -> error Unterminated_string pmin) in - let str = (try unescape (contents()) with Invalid_escape_sequence(c,i) -> error (Invalid_escape c) (pmin + i)) in + let str = (try unescape (contents()) with Invalid_escape_sequence(c,i,msg) -> error (Invalid_escape (c,msg)) (pmin + i)) in let t = mk_tok (Const (String str)) pmin pmax in fast_add_fmt_string (snd t); t @@ -378,6 +420,57 @@ let rec token lexbuf = let v = lexeme lexbuf in let v = String.sub v 1 (String.length v - 1) in mk lexbuf (Dollar v) + (* type decl *) + | "package" -> mk_keyword lexbuf Package + | "import" -> mk_keyword lexbuf Import + | "using" -> mk_keyword lexbuf Using + | "class" -> mk_keyword lexbuf Class + | "interface" -> mk_keyword lexbuf Interface + | "enum" -> mk_keyword lexbuf Enum + | "abstract" -> mk_keyword lexbuf Abstract + | "typedef" -> mk_keyword lexbuf Typedef + (* relations *) + | "extends" -> mk_keyword lexbuf Extends + | "implements" -> mk_keyword lexbuf Implements + (* modifier *) + | "extern" -> mk_keyword lexbuf Extern + | "static" -> mk_keyword lexbuf Static + | "public" -> mk_keyword lexbuf Public + | "private" -> mk_keyword lexbuf Private + | "override" -> mk_keyword lexbuf Override + | "dynamic" -> mk_keyword lexbuf Dynamic + | "inline" -> mk_keyword lexbuf Inline + | "macro" -> mk_keyword lexbuf Macro + | "final" -> mk_keyword lexbuf Final + | "operator" -> mk_keyword lexbuf Operator + | "overload" -> mk_keyword lexbuf Overload + (* fields *) + | "function" -> mk_keyword lexbuf Function + | "var" -> mk_keyword lexbuf Var + (* values *) + | "null" -> mk_keyword lexbuf Null + | "true" -> mk_keyword lexbuf True + | "false" -> mk_keyword lexbuf False + | "this" -> mk_keyword lexbuf This + (* expr *) + | "if" -> mk_keyword lexbuf If + | "else" -> mk_keyword lexbuf Else + | "while" -> mk_keyword lexbuf While + | "do" -> mk_keyword lexbuf Do + | "for" -> mk_keyword lexbuf For + | "break" -> mk_keyword lexbuf Break + | "continue" -> mk_keyword lexbuf Continue + | "return" -> mk_keyword lexbuf Return + | "switch" -> mk_keyword lexbuf Switch + | "case" -> mk_keyword lexbuf Case + | "default" -> mk_keyword lexbuf Default + | "throw" -> mk_keyword lexbuf Throw + | "try" -> mk_keyword lexbuf Try + | "catch" -> mk_keyword lexbuf Catch + | "untyped" -> mk_keyword lexbuf Untyped + | "new" -> mk_keyword lexbuf New + | "in" -> mk_keyword lexbuf In + | "cast" -> mk_keyword lexbuf Cast | ident -> mk_ident lexbuf | idtype -> mk lexbuf (Const (Ident (lexeme lexbuf))) | _ -> invalid_char lexbuf @@ -443,7 +536,11 @@ and code_string lexbuf open_braces = code_string lexbuf open_braces | "/*" -> let pmin = lexeme_start lexbuf in + let save = contents() in + reset(); (try ignore(comment lexbuf) with Exit -> error Unclosed_comment pmin); + reset(); + Buffer.add_string buf save; code_string lexbuf open_braces | "//", Star (Compl ('\n' | '\r')) -> store lexbuf; code_string lexbuf open_braces | Plus (Compl ('/' | '"' | '\'' | '{' | '}' | '\n' | '\r')) -> store lexbuf; code_string lexbuf open_braces @@ -472,3 +569,74 @@ and regexp_options lexbuf = | 'a'..'z' -> error Invalid_option (lexeme_start lexbuf) | "" -> "" | _ -> assert false + +and not_xml ctx depth in_open = + let lexbuf = ctx.lexbuf in + match%sedlex lexbuf with + | eof -> + raise Exit + | '\n' | '\r' | "\r\n" -> + newline lexbuf; + store lexbuf; + not_xml ctx depth in_open + (* closing tag *) + | '<','/',xml_name,'>' -> + let s = lexeme lexbuf in + Buffer.add_string buf s; + (* If it matches our document close tag, finish or decrease depth. *) + if s = ctx.close_tag then begin + if depth = 0 then lexeme_end lexbuf + else not_xml ctx (depth - 1) false + end else + not_xml ctx depth false + (* opening tag *) + | '<',xml_name -> + let s = lexeme lexbuf in + Buffer.add_string buf s; + (* If it matches our document open tag, increase depth and set in_open to true. *) + let depth,in_open = if s = ctx.open_tag then depth + 1,true else depth,false in + not_xml ctx depth in_open + (* /> *) + | '/','>' -> + let s = lexeme lexbuf in + Buffer.add_string buf s; + (* We only care about this if we are still in the opening tag, i.e. if it wasn't closed yet. + In that case, decrease depth and finish if it's 0. *) + let depth = if in_open then depth - 1 else depth in + if depth < 0 then lexeme_end lexbuf + else not_xml ctx depth false + | '<' | '/' | '>' -> + store lexbuf; + not_xml ctx depth in_open + | Plus (Compl ('<' | '/' | '>' | '\n' | '\r')) -> + store lexbuf; + not_xml ctx depth in_open + | _ -> + assert false + +let rec sharp_token lexbuf = + match%sedlex lexbuf with + | sharp_ident -> mk_ident lexbuf + | Plus (Chars " \t") -> sharp_token lexbuf + | "\r\n" -> newline lexbuf; sharp_token lexbuf + | '\n' | '\r' -> newline lexbuf; sharp_token lexbuf + | _ -> token lexbuf + +let lex_xml p lexbuf = + let name,pmin = match%sedlex lexbuf with + | xml_name -> lexeme lexbuf,lexeme_start lexbuf + | _ -> invalid_char lexbuf + in + if p + 1 <> pmin then invalid_char lexbuf; + Buffer.add_string buf ("<" ^ name); + let open_tag = "<" ^ name in + let close_tag = "" in + let ctx = { + open_tag = open_tag; + close_tag = close_tag; + lexbuf = lexbuf; + } in + try + not_xml ctx 0 (name <> "") (* don't allow self-closing fragments *) + with Exit -> + error Unterminated_markup p \ No newline at end of file diff --git a/src/syntax/parser.ml b/src/syntax/parser.ml index 5e0b98f78a2..2138c71c806 100644 --- a/src/syntax/parser.ml +++ b/src/syntax/parser.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -20,49 +20,85 @@ open Ast open Globals open Reification +open DisplayTypes.DisplayMode +open DisplayPosition type error_msg = | Unexpected of token | Duplicate_default | Missing_semicolon - | Unclosed_macro + | Unclosed_conditional | Unimplemented | Missing_type + | Expected of string list + | StreamError of string | Custom of string +type decl_flag = + | DPrivate + | DExtern + | DFinal + +type type_decl_completion_mode = + | TCBeforePackage + | TCAfterImport + | TCAfterType + +type syntax_completion = + | SCComment + | SCClassRelation + | SCInterfaceRelation + | SCTypeDecl of type_decl_completion_mode + | SCAfterTypeFlag of decl_flag list + exception Error of error_msg * pos -exception TypePath of string list * (string * bool) option * bool (* in import *) -exception Display of expr +exception TypePath of string list * (string * bool) option * bool (* in import *) * pos +exception SyntaxCompletion of syntax_completion * pos let error_msg = function | Unexpected t -> "Unexpected "^(s_token t) | Duplicate_default -> "Duplicate default" | Missing_semicolon -> "Missing ;" - | Unclosed_macro -> "Unclosed macro" + | Unclosed_conditional -> "Unclosed conditional compilation block" | Unimplemented -> "Not implemented for current platform" | Missing_type -> "Missing type declaration" + | Expected sl -> "Expected " ^ (String.concat " or " sl) + | StreamError s -> s | Custom s -> s +type parse_data = string list * (type_def * pos) list + +type parse_error = (error_msg * pos) + +type 'a parse_result = + (* Parsed display file. There can be errors. *) + | ParseDisplayFile of 'a * parse_error list + (* Parsed non-display-file without errors. *) + | ParseSuccess of 'a + (* Parsed non-display file with errors *) + | ParseError of 'a * parse_error * parse_error list + +let syntax_completion kind p = + raise (SyntaxCompletion(kind,p)) + let error m p = raise (Error (m,p)) -let display_error : (error_msg -> pos -> unit) ref = ref (fun _ _ -> assert false) let special_identifier_files : (string,string) Hashtbl.t = Hashtbl.create 0 -type decl_flag = - | DPrivate - | DExtern - -let decl_flag_to_class_flag = function +let decl_flag_to_class_flag (flag,p) = match flag with | DPrivate -> HPrivate | DExtern -> HExtern + | DFinal -> HFinal -let decl_flag_to_enum_flag = function +let decl_flag_to_enum_flag (flag,p) = match flag with | DPrivate -> EPrivate | DExtern -> EExtern + | DFinal -> error (Custom "final on enums is not allowed") p -let decl_flag_to_abstract_flag = function - | DPrivate -> APrivAbstract - | DExtern -> AExtern +let decl_flag_to_abstract_flag (flag,p) = match flag with + | DPrivate -> AbPrivate + | DExtern -> AbExtern + | DFinal -> error (Custom "final on abstracts is not allowed") p module TokenCache = struct let cache = ref (DynArray.create ()) @@ -74,15 +110,64 @@ module TokenCache = struct (fun () -> cache := old_cache) end -let last_doc : (string * int) option ref = ref None -let use_doc = ref false -let resume_display = ref null_pos -let in_macro = ref false - let last_token s = let n = Stream.count s in TokenCache.get (if n = 0 then 0 else n - 1) +let last_pos s = pos (last_token s) + +let next_token s = match Stream.peek s with + | Some (Eof,p) -> + (Eof,p) + | Some tk -> tk + | None -> + let last_pos = pos (last_token s) in + (Eof,last_pos) + +let next_pos s = pos (next_token s) + +(* Global state *) + +let in_display = ref false +let was_auto_triggered = ref false +let display_mode = ref DMNone +let in_macro = ref false +let had_resume = ref false +let code_ref = ref (Sedlexing.Utf8.from_string "") +let delayed_syntax_completion : (syntax_completion * pos) option ref = ref None + +let reset_state () = + in_display := false; + was_auto_triggered := false; + display_mode := DMNone; + display_position#reset; + in_macro := false; + had_resume := false; + code_ref := Sedlexing.Utf8.from_string ""; + delayed_syntax_completion := None + +(* Per-file state *) + +let in_display_file = ref false +let last_doc : (string * int) option ref = ref None +let syntax_errors = ref [] + +let syntax_error error_msg ?(pos=None) s v = + let p = (match pos with Some p -> p | None -> next_pos s) in + let p = if p.pmax = max_int then {p with pmax = p.pmin + 1} else p in + if not !in_display then error error_msg p; + syntax_errors := (error_msg,p) :: !syntax_errors; + v + +let handle_stream_error msg s = + let err,pos = if msg = "" then begin + let tk,pos = next_token s in + (Unexpected tk),Some pos + end else + (StreamError msg),None + in + syntax_error err ~pos s () + let get_doc s = (* do the peek first to make sure we fetch the doc *) match Stream.peek s with @@ -96,40 +181,32 @@ let get_doc s = let serror() = raise (Stream.Error "") -let do_resume() = !resume_display <> null_pos +let magic_display_field_name = " - display - " +let magic_type_path = { tpackage = []; tname = ""; tparams = []; tsub = None } -let display e = raise (Display e) +let delay_syntax_completion kind p = + delayed_syntax_completion := Some(kind,p) -let type_path sl in_import = match sl with - | n :: l when n.[0] >= 'A' && n.[0] <= 'Z' -> raise (TypePath (List.rev l,Some (n,false),in_import)); - | _ -> raise (TypePath (List.rev sl,None,in_import)) +let type_path sl in_import p = match sl with + | n :: l when n.[0] >= 'A' && n.[0] <= 'Z' -> raise (TypePath (List.rev l,Some (n,false),in_import,p)); + | _ -> raise (TypePath (List.rev sl,None,in_import,p)) -let is_resuming_file file = - Path.unique_full_path file = !resume_display.pfile +let would_skip_display_position p1 s = + if !in_display_file then match Stream.npeek 1 s with + | [ (_,p2) ] -> display_position#enclosed_in (punion p1 p2) + | _ -> false + else false -let is_resuming p = - let p2 = !resume_display in - p.pmax = p2.pmin && is_resuming_file p.pfile - -let set_resume p = - resume_display := { p with pfile = Path.unique_full_path p.pfile } - -let encloses_resume p = - p.pmin <= !resume_display.pmin && p.pmax >= !resume_display.pmax - -let would_skip_resume p1 s = - match Stream.npeek 1 s with - | [ (_,p2) ] -> - is_resuming_file p2.pfile && encloses_resume (punion p1 p2) - | _ -> - false +let cut_pos_at_display p = display_position#cut p let is_dollar_ident e = match fst e with - | EConst (Ident n) when n.[0] = '$' -> + | EConst (Ident n) when starts_with n '$' -> true | _ -> false +let rev_concat s sl = String.concat s (List.rev sl) + let precedence op = let left = true and right = false in match op with @@ -189,6 +266,87 @@ let make_is e (t,p_t) p p_is = let e2 = expr_of_type_path (t.tpackage,t.tname) p_t in ECall(e_is,[e;e2]),p -let next_token s = match Stream.peek s with - | Some tk -> tk - | _ -> last_token s \ No newline at end of file +let handle_xml_literal p1 = + Lexer.reset(); + let i = Lexer.lex_xml p1.pmin !code_ref in + let xml = Lexer.contents() in + let e = EConst (String xml),{p1 with pmax = i} in + let e = make_meta Meta.Markup [] e p1 in + e + +let punion_next p1 s = + let _,p2 = next_token s in + { + pfile = p1.pfile; + pmin = p1.pmin; + pmax = p2.pmax - 1; + } + +let mk_null_expr p = (EConst(Ident "null"),p) + +let mk_display_expr e dk = (EDisplay(e,dk),(pos e)) + +let is_completion () = + !display_mode = DMDefault + +let is_signature_display () = + !display_mode = DMSignature + +let check_resume p fyes fno = + if is_completion () && !in_display_file && p.pmax = (display_position#get).pmin then begin + had_resume := true; + fyes() + end else + fno() + +let check_resume_range p s fyes fno = + if is_completion () && !in_display_file then begin + let pnext = next_pos s in + if p.pmin < (display_position#get).pmin && pnext.pmin >= (display_position#get).pmax then + fyes pnext + else + fno() + end else + fno() + +let check_type_decl_flag_completion mode flags s = + if not !in_display_file || not (is_completion()) then raise Stream.Failure; + let check_type_completion () = match Stream.peek s with + (* If there's an identifier coming up, it's probably an incomplete type + declaration. Let's just raise syntax completion in that case because + the parser would fail otherwise anyway. *) + | Some((Const(Ident _),p)) -> syntax_completion (SCTypeDecl mode) p + | _ -> raise Stream.Failure + in + match flags with + | [] -> check_type_completion() + | (_,p) :: _ -> + if would_skip_display_position p s then begin + let flags = List.map fst flags in + syntax_completion (SCAfterTypeFlag flags) p + end; + check_type_completion() + +let check_type_decl_completion mode pmax s = + if !in_display_file && is_completion() then begin + let pmin = match Stream.peek s with + | Some (Eof,_) | None -> max_int + | Some tk -> (pos tk).pmin + in + (* print_endline (Printf.sprintf "(%i <= %i) (%i >= %i)" pmax !display_position.pmin pmin !display_position.pmax); *) + if pmax <= (display_position#get).pmin && pmin >= (display_position#get).pmax then + delay_syntax_completion (SCTypeDecl mode) display_position#get + end + +let check_signature_mark e p1 p2 = + if not (is_signature_display()) then e + else begin + let p = punion p1 p2 in + if true || not !was_auto_triggered then begin (* TODO: #6383 *) + if encloses_position_gt display_position#get p then (mk_display_expr e DKMarked) + else e + end else begin + if (display_position#get).pmin = p1.pmax then (mk_display_expr e DKMarked) + else e + end + end \ No newline at end of file diff --git a/src/syntax/parserEntry.ml b/src/syntax/parserEntry.ml index 8749e24c41b..e135e607def 100644 --- a/src/syntax/parserEntry.ml +++ b/src/syntax/parserEntry.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -19,7 +19,9 @@ open Globals open Ast open Parser +open Semver open Grammar +open DisplayPosition (* eval *) type small_type = @@ -27,19 +29,35 @@ type small_type = | TBool of bool | TFloat of float | TString of string + | TVersion of (version * version * version) * (version list option) let is_true = function | TBool false | TNull | TFloat 0. | TString "" -> false | _ -> true +let s_small_type v = + match v with + | TNull -> "null" + | TBool _ -> "boolean" + | TFloat _ -> "float" + | TString _ -> "string" + | TVersion _ -> "version" + +let parse_version s p = + try match parse_version s with release,pre -> TVersion (release,pre) + with Invalid_argument msg -> error (Custom msg) p + let cmp v1 v2 = match v1, v2 with - | TNull, TNull -> 0 + | TNull, _ | _, TNull -> raise Exit | TFloat a, TFloat b -> compare a b | TString a, TString b -> compare a b | TBool a, TBool b -> compare a b | TString a, TFloat b -> compare (float_of_string a) b | TFloat a, TString b -> compare a (float_of_string b) + | TVersion (release1,pre1), TVersion (release2,pre2) -> compare_version (release1,pre1) (release2,pre2) + | _, TVersion _ + | TVersion _, _ -> raise (Invalid_argument ("Cannot compare " ^ (s_small_type v1) ^ " and " ^ (s_small_type v2))) | _ -> raise Exit (* always false *) let rec eval ctx (e,p) = @@ -49,15 +67,16 @@ let rec eval ctx (e,p) = | EConst (String s) -> TString s | EConst (Int i) -> TFloat (float_of_string i) | EConst (Float f) -> TFloat (float_of_string f) + | ECall ((EConst (Ident "version"),_),[(EConst (String s), p)]) -> parse_version s p | EBinop (OpBoolAnd, e1, e2) -> TBool (is_true (eval ctx e1) && is_true (eval ctx e2)) | EBinop (OpBoolOr, e1, e2) -> TBool (is_true (eval ctx e1) || is_true(eval ctx e2)) | EUnop (Not, _, e) -> TBool (not (is_true (eval ctx e))) | EParenthesis e -> eval ctx e | EBinop (op, e1, e2) -> - let v1 = eval ctx e1 in - let v2 = eval ctx e2 in + let v1, v2 = eval_binop_exprs ctx e1 e2 in let compare op = - TBool (try op (cmp v1 v2) 0 with _ -> false) + try TBool (try op (cmp v1 v2) 0 with Exit -> false) + with Invalid_argument msg -> error (Custom msg) p in (match op with | OpEq -> compare (=) @@ -67,31 +86,68 @@ let rec eval ctx (e,p) = | OpLt -> compare (<) | OpLte -> compare (<=) | _ -> error (Custom "Unsupported operation") p) + | EField _ -> + begin try + let sl = string_list_of_expr_path_raise (e,p) in + let i = String.concat "." (List.rev sl) in + (try TString (Define.raw_defined_value ctx i) with Not_found -> TNull) + with Exit -> + error (Custom "Invalid condition expression") p + end | _ -> error (Custom "Invalid condition expression") p +and eval_binop_exprs ctx e1 e2 = + match eval ctx e1, eval ctx e2 with + | (TVersion _ as v1), (TVersion _ as v2) -> (v1, v2) + | (TVersion _ as v1), TString s -> (v1, parse_version s (snd e2)) + | TString s, (TVersion _ as v2) -> (parse_version s (snd e1), v2) + | v1, v2 -> (v1, v2) + (* parse main *) -let parse ctx code = +let parse ctx code file = let old = Lexer.save() in let restore_cache = TokenCache.clear () in + let was_display = !in_display in + let was_display_file = !in_display_file in + let old_code = !code_ref in + let old_macro = !in_macro in + code_ref := code; + in_display := display_position#get <> null_pos; + in_display_file := !in_display && Path.unique_full_path file = (display_position#get).pfile; + syntax_errors := []; + let restore = + (fun () -> + restore_cache (); + in_display := was_display; + in_macro := old_macro; + in_display_file := was_display_file; + code_ref := old_code; + ) + in let mstack = ref [] in last_doc := None; in_macro := Define.defined ctx Define.Macro; Lexer.skip_header code; - let sraw = Stream.from (fun _ -> Some (Lexer.token code)) in + let sharp_error s p = + let line = StringError.string_error ("#" ^ s) ["#if";"#elseif";"#else";"#end";"#error";"#line"] "Unknown token" in + error (Custom line) p + in + + let sraw = Stream.from (fun _ -> Some (Lexer.sharp_token code)) in let rec next_token() = process_token (Lexer.token code) and process_token tk = match fst tk with | Comment s -> + (* if encloses_resume (pos tk) then syntax_completion SCComment (pos tk); *) let tk = next_token() in - if !use_doc then begin - let l = String.length s in - if l > 0 && s.[0] = '*' then last_doc := Some (String.sub s 1 (l - (if l > 1 && s.[l-1] = '*' then 2 else 1)), (snd tk).pmin); - end; + let l = String.length s in + if l > 0 && s.[0] = '*' then last_doc := Some (String.sub s 1 (l - (if l > 1 && s.[l-1] = '*' then 2 else 1)), (snd tk).pmin); tk | CommentLine s -> + if !in_display_file && display_position#enclosed_in (pos tk) then syntax_completion SCComment (pos tk); next_token() | Sharp "end" -> (match !mstack with @@ -118,13 +174,15 @@ let parse ctx code = ) in !(Lexer.cur).Lexer.lline <- line - 1; next_token(); + | Sharp s -> + sharp_error s (pos tk) | _ -> tk and enter_macro p = - let tk, e = parse_macro_cond false sraw in + let tk, e = parse_macro_cond sraw in let tk = (match tk with None -> Lexer.token code | Some tk -> tk) in - if is_true (eval ctx e) || (match fst e with EConst (Ident "macro") when Path.unique_full_path p.pfile = (!resume_display).pfile -> true | _ -> false) then begin + if is_true (eval ctx e) then begin mstack := p :: !mstack; tk end else @@ -143,8 +201,12 @@ let parse ctx code = enter_macro (snd tk) | Sharp "if" -> skip_tokens_loop p test (skip_tokens p false) + | Sharp ("error" | "line") -> + skip_tokens p test + | Sharp s -> + sharp_error s (pos tk) | Eof -> - if do_resume() then tk else error Unclosed_macro p + syntax_error Unclosed_conditional ~pos:(Some p) sraw tk | _ -> skip_tokens p test @@ -158,40 +220,53 @@ let parse ctx code = ) in try let l = parse_file s in - (match !mstack with p :: _ when not (do_resume()) -> error Unclosed_macro p | _ -> ()); - restore_cache (); + (match !mstack with p :: _ -> syntax_error Unclosed_conditional ~pos:(Some p) sraw () | _ -> ()); + let was_display_file = !in_display_file in + restore(); Lexer.restore old; - l + if was_display_file then + ParseDisplayFile(l,List.rev !syntax_errors) + else begin match List.rev !syntax_errors with + | [] -> ParseSuccess l + | error :: errors -> ParseError(l,error,errors) + end with | Stream.Error _ | Stream.Failure -> let last = (match Stream.peek s with None -> last_token s | Some t -> t) in Lexer.restore old; - restore_cache (); + restore(); error (Unexpected (fst last)) (pos last) | e -> Lexer.restore old; - restore_cache (); + restore(); raise e let parse_string com s p error inlined = let old = Lexer.save() in let old_file = (try Some (Hashtbl.find Lexer.all_files p.pfile) with Not_found -> None) in - let old_display = !resume_display in - let old_de = !display_error in + let old_display = display_position#get in + let old_in_display_file = !in_display_file in + let old_syntax_errors = !syntax_errors in + syntax_errors := []; let restore() = (match old_file with | None -> () | Some f -> Hashtbl.replace Lexer.all_files p.pfile f); - if not inlined then resume_display := old_display; - Lexer.restore old; - display_error := old_de + if not inlined then begin + display_position#set old_display; + in_display_file := old_in_display_file; + end; + syntax_errors := old_syntax_errors; + Lexer.restore old in Lexer.init p.pfile true; - display_error := (fun e p -> raise (Error (e,p))); - if not inlined then resume_display := null_pos; - let pack, decls = try - parse com (Sedlexing.Utf8.from_string s) + if not inlined then begin + display_position#reset; + in_display_file := false; + end; + let result = try + parse com (Sedlexing.Utf8.from_string s) p.pfile with Error (e,pe) -> restore(); error (error_msg e) (if inlined then pe else p) @@ -200,12 +275,17 @@ let parse_string com s p error inlined = error (Lexer.error_msg e) (if inlined then pe else p) in restore(); - pack,decls + result let parse_expr_string com s p error inl = let head = "class X{static function main() " in let head = (if p.pmin > String.length head then head ^ String.make (p.pmin - String.length head) ' ' else head) in let rec loop e = let e = Ast.map_expr loop e in (fst e,p) in + let extract_expr (_,decls) = match decls with + | [EClass { d_data = [{ cff_name = "main",null_pos; cff_kind = FFun { f_expr = Some e } }]},_] -> (if inl then e else loop e) + | _ -> raise Exit + in match parse_string com (head ^ s ^ ";}") p error inl with - | _,[EClass { d_data = [{ cff_name = "main",null_pos; cff_kind = FFun { f_expr = Some e } }]},_] -> if inl then e else loop e - | _ -> raise Exit + | ParseSuccess data -> ParseSuccess(extract_expr data) + | ParseError(data,error,errors) -> ParseError(extract_expr data,error,errors) + | ParseDisplayFile(data,errors) -> ParseDisplayFile(extract_expr data,errors) diff --git a/src/syntax/reification.ml b/src/syntax/reification.ml index 52c4ad45c9b..a4178c67e52 100644 --- a/src/syntax/reification.ml +++ b/src/syntax/reification.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -136,9 +136,12 @@ let reify in_macro = | CTParent t -> ct "TParent" [to_type_hint t p] | CTExtend (tl,fields) -> ct "TExtend" [to_array to_tpath tl p; to_array to_cfield fields p] | CTOptional t -> ct "TOptional" [to_type_hint t p] + | CTNamed (n,t) -> ct "TNamed" [to_placed_name n; to_type_hint t p] + | CTIntersection tl -> ct "TIntersection" (List.map (fun t -> to_ctype t p) tl) and to_type_hint (t,p) _ = (* to_obj ["type",to_ctype t p;"pos",to_pos p] p *) to_ctype (t,p) p + and to_display_kind dk p = mk_enum "DisplayKind" (s_display_kind dk) [] p and to_fun f p = let p = {p with pmax = p.pmin} in let farg ((n,_),o,_,t,e) p = @@ -152,7 +155,7 @@ let reify in_macro = let rec fparam t p = let fields = [ "name", to_placed_name t.tp_name; - "constraints", to_array to_ctype t.tp_constraints p; + "constraints", (match t.tp_constraints with None -> to_null p | Some ct -> to_array to_ctype [ct] p); "params", to_array fparam t.tp_params p; ] in to_obj fields p @@ -167,7 +170,7 @@ let reify in_macro = and to_cfield f p = let p = f.cff_pos in let to_access a p = - let n = (match a with + let n = (match fst a with | APublic -> "APublic" | APrivate -> "APrivate" | AStatic -> "AStatic" @@ -176,6 +179,7 @@ let reify in_macro = | AInline -> "AInline" | AMacro -> "AMacro" | AFinal -> "AFinal" + | AExtern -> "AExtern" ) in mk_enum "Access" n [] p in @@ -245,8 +249,8 @@ let reify in_macro = | EObjectDecl fl -> let quote_kind kk p = let n = match kk with - | NoQuotes -> "NoQuotes" - | DoubleQuotes -> "DoubleQuotes" + | NoQuotes -> "Unquoted" + | DoubleQuotes -> "Quoted" in mk_enum "QuoteStatus" n [] p in @@ -267,12 +271,12 @@ let reify in_macro = ) [] p in expr "EUnop" [op;to_bool (flag = Postfix) p;loop e] | EVars vl -> - expr "EVars" [to_array (fun ((n,pn),th,e) p -> + expr "EVars" [to_array (fun ((n,pn),final,th,e) p -> let fields = [ - (* "name", to_obj ["name",to_string n pn;"pos",to_pos pn] p; *) "name", to_string n pn; "type", to_opt to_type_hint th p; "expr", to_opt to_expr e p; + "isFinal",to_bool final p; ] in to_obj fields p ) vl p] @@ -280,15 +284,15 @@ let reify in_macro = let name = match name with | None -> to_null null_pos - | Some name -> + | Some (name,pn) -> if ExtString.String.starts_with name "inline_$" then begin let real_name = (String.sub name 7 (String.length name - 7)) in - let e_name = to_string real_name p in + let e_name = to_string real_name pn in let e_inline = to_string "inline_" p in let e_add = (EBinop(OpAdd,e_inline,e_name),p) in e_add end else - to_string name p + to_string name pn in expr "EFunction" [name; to_fun f p] | EBlock el -> @@ -321,8 +325,8 @@ let reify in_macro = expr "EThrow" [loop e] | ECast (e,ct) -> expr "ECast" [loop e; to_opt to_type_hint ct p] - | EDisplay (e,flag) -> - expr "EDisplay" [loop e; to_bool flag p] + | EDisplay (e,dk) -> + expr "EDisplay" [loop e; to_display_kind dk p] | EDisplayNew t -> expr "EDisplayNew" [to_tpath t p] | ETernary (e1,e2,e3) -> @@ -361,12 +365,12 @@ let reify in_macro = to_obj [ "name", to_placed_name t.tp_name; "params", (EArrayDecl (List.map (to_tparam_decl p) t.tp_params),p); - "constraints", (EArrayDecl (List.map (fun t -> to_ctype t p) t.tp_constraints),p) + "constraints", (EArrayDecl (match t.tp_constraints with None -> [] | Some th -> [to_ctype th p]),p) ] p and to_type_def (t,p) = match t with | EClass d -> - let ext = ref None and impl = ref [] and interf = ref false in + let ext = ref None and impl = ref [] and interf = ref false and final = ref false in List.iter (function | HExtern | HPrivate -> () | HInterface -> interf := true; @@ -377,6 +381,7 @@ let reify in_macro = !ext end) | HImplements i-> impl := (to_tpath i p) :: !impl + | HFinal -> final := true ) d.d_flags; to_obj [ "pack", (EArrayDecl [],p); @@ -385,7 +390,7 @@ let reify in_macro = "meta", to_meta d.d_meta p; "params", (EArrayDecl (List.map (to_tparam_decl p) d.d_params),p); "isExtern", to_bool (List.mem HExtern d.d_flags) p; - "kind", mk_enum "TypeDefKind" "TDClass" [(match !ext with None -> (EConst (Ident "null"),p) | Some t -> t);(EArrayDecl (List.rev !impl),p);to_bool !interf p] p; + "kind", mk_enum "TypeDefKind" "TDClass" [(match !ext with None -> (EConst (Ident "null"),p) | Some t -> t);(EArrayDecl (List.rev !impl),p);to_bool !interf p;to_bool !final p] p; "fields", (EArrayDecl (List.map (fun f -> to_cfield f p) d.d_data),p) ] p | _ -> assert false diff --git a/src/syntax/semver.ml b/src/syntax/semver.ml new file mode 100644 index 00000000000..1756c815d59 --- /dev/null +++ b/src/syntax/semver.ml @@ -0,0 +1,114 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(** + A single version within semver string (e.g major or minor or patch) +*) +type version = + | SVNum of int + | SVStr of string (* `alpha`, `pre`, `rc` etc. *) + +let s_version = function + | SVNum n -> "SVNum " ^ (string_of_int n) + | SVStr s -> "SVStr " ^ s + +let to_string ((major,minor,patch),pre) = + let str v = + match v with + | SVNum n -> string_of_int n + | SVStr s -> s + in + (String.concat "." (List.map str [major;minor;patch])) + ^ match pre with + | None -> "" + | Some pre -> "-" ^ (String.concat "." (List.map str pre)) + + +(** + Parse SemVer string +*) +let parse_version s = + let error () = + raise (Invalid_argument ("Invalid version string \"" ^ s ^ "\". Should follow SemVer.")) + in + let parse dotted_str = + List.map + (fun s -> + try SVNum (int_of_string s) + with _ -> SVStr s + ) + (ExtString.String.nsplit dotted_str ".") + in + let parse_release dotted_str = + match parse dotted_str with + | [SVNum _ as major; SVNum _ as minor; SVNum _ as patch] -> (major, minor, patch) + | _ -> error() + in + let index = try Some (String.index s '-') with Not_found -> None in + match index with + (* 1.2.3 *) + | None -> (parse_release s), None + (* 1.2.3- *) + | Some index when index + 1 = String.length s -> error() + (* 1.2.3-alpha.1+23 *) + | Some index -> + let release = parse_release (String.sub s 0 index) + and pre = + let pre_str = String.sub s (index + 1) (String.length s - (index + 1)) in + (* remove build meta *) + let pre_str = + try String.sub pre_str 0 (String.index pre_str '+') + with Not_found -> pre_str + in + parse pre_str + in + release, Some pre + +(** + @see https://semver.org/#spec-item-11 +*) +let compare_version a b = + let compare_v v1 v2 = + match v1,v2 with + | SVNum n1, SVNum n2 -> compare n1 n2 + | SVStr s1, SVStr s2 -> compare s1 s2 + | SVStr _, SVNum _ -> 1 + | SVNum _, SVStr _ -> -1 + in + let rec compare_lists version_list1 version_list2 = + match version_list1, version_list2 with + | [], [] -> 0 + | [], _ -> -1 + | _, [] -> 1 + | v1 :: rest1, v2 :: rest2 -> + let diff = compare_v v1 v2 in + if diff <> 0 then diff + else compare_lists rest1 rest2 + in + match a, b with + | ((major1,minor1,patch1), pre1), ((major2,minor2,patch2), pre2) -> + let diff = compare_lists [major1;minor1;patch1] [major2;minor2;patch2] in + if diff <> 0 then + diff + else + match pre1, pre2 with + | None, None -> 0 + | None, _ -> 1 + | _, None -> -1 + | Some pre1, Some pre2 -> compare_lists pre1 pre2 \ No newline at end of file diff --git a/src/typing/calls.ml b/src/typing/calls.ml new file mode 100644 index 00000000000..af3440c7319 --- /dev/null +++ b/src/typing/calls.ml @@ -0,0 +1,794 @@ +open Globals +open DisplayTypes.DisplayMode +open Common +open Ast +open Type +open Typecore +open TyperBase +open Fields +open Error + +let is_forced_inline c cf = + match c with + | Some { cl_extern = true } -> true + | Some { cl_kind = KAbstractImpl _ } -> true + | _ when has_class_field_flag cf CfExtern -> true + | _ -> false + +let make_call ctx e params t ?(force_inline=false) p = + try + let ethis,cl,f = match e.eexpr with + | TField (ethis,fa) -> + let co,cf = match fa with + | FInstance(c,_,cf) | FStatic(c,cf) -> Some c,cf + | FAnon cf -> None,cf + | _ -> raise Exit + in + ethis,co,cf + | _ -> + raise Exit + in + if not force_inline then begin + if f.cf_kind <> Method MethInline then raise Exit; + end else begin + delay ctx PFinal (fun () -> + if has_class_field_flag f CfOverridden then error (Printf.sprintf "Cannot force inline-call to %s because it is overridden" f.cf_name) p + ); + end; + let config = match cl with + | Some ({cl_kind = KAbstractImpl _}) when Meta.has Meta.Impl f.cf_meta -> + let t = if f.cf_name = "_new" then + t + else if params = [] then + error "Invalid abstract implementation function" f.cf_pos + else + follow (List.hd params).etype + in + begin match t with + | TAbstract(a,pl) -> + let has_params = a.a_params <> [] || f.cf_params <> [] in + let monos = List.map (fun _ -> mk_mono()) f.cf_params in + let map_type = fun t -> apply_params a.a_params pl (apply_params f.cf_params monos t) in + Some (has_params,map_type) + | _ -> + None + end + | _ -> + None + in + ignore(follow f.cf_type); (* force evaluation *) + (match cl, ctx.curclass.cl_kind, params with + | Some c, KAbstractImpl _, { eexpr = TLocal { v_meta = v_meta } } :: _ when c == ctx.curclass -> + if + f.cf_name <> "_new" + && has_meta Meta.This v_meta + && not (assign_to_this_is_allowed ctx) + && has_class_field_flag f CfModifiesThis + then + error ("Abstract 'this' value can only be modified inside an inline function. '" ^ f.cf_name ^ "' modifies 'this'") p; + | _ -> () + ); + let params = List.map (ctx.g.do_optimize ctx) params in + let force_inline = is_forced_inline cl f in + (match f.cf_expr_unoptimized,f.cf_expr with + | Some fd,_ + | None,Some { eexpr = TFunction fd } -> + (match Inline.type_inline ctx f fd ethis params t config p force_inline with + | None -> + if force_inline then error "Inline could not be done" p; + raise Exit; + | Some e -> e) + | _ -> + (* + we can't inline because there is most likely a loop in the typing. + this can be caused by mutually recursive vars/functions, some of them + being inlined or not. In that case simply ignore inlining. + *) + raise Exit) + with Exit -> + mk (TCall (e,params)) t p + +let mk_array_get_call ctx (cf,tf,r,e1,e2o) c ebase p = match cf.cf_expr with + | None -> + if not (Meta.has Meta.NoExpr cf.cf_meta) then display_error ctx "Recursive array get method" p; + mk (TArray(ebase,e1)) r p + | Some _ -> + let et = type_module_type ctx (TClassDecl c) None p in + let ef = mk (TField(et,(FStatic(c,cf)))) tf p in + make_call ctx ef [ebase;e1] r p + +let mk_array_set_call ctx (cf,tf,r,e1,e2o) c ebase p = + let evalue = match e2o with None -> assert false | Some e -> e in + match cf.cf_expr with + | None -> + if not (Meta.has Meta.NoExpr cf.cf_meta) then display_error ctx "Recursive array set method" p; + let ea = mk (TArray(ebase,e1)) r p in + mk (TBinop(OpAssign,ea,evalue)) r p + | Some _ -> + let et = type_module_type ctx (TClassDecl c) None p in + let ef = mk (TField(et,(FStatic(c,cf)))) tf p in + make_call ctx ef [ebase;e1;evalue] r p + +let call_to_string ctx ?(resume=false) e = + (* Ignore visibility of the toString field. *) + ctx.meta <- (Meta.PrivateAccess,[],e.epos) :: ctx.meta; + let acc = type_field (TypeFieldConfig.create resume) ctx e "toString" e.epos MCall in + ctx.meta <- List.tl ctx.meta; + !build_call_ref ctx acc [] (WithType.with_type ctx.t.tstring) e.epos + +let rec unify_call_args' ctx el args r callp inline force_inline = + let in_call_args = ctx.in_call_args in + ctx.in_call_args <- true; + let call_error err p = + raise (Error (Call_error err,p)) + in + let arg_error ul name opt p = + let err = Stack (ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")) in + call_error (Could_not_unify err) p + in + let mk_pos_infos t = + let infos = mk_infos ctx callp [] in + type_expr ctx infos (WithType.with_type t) + in + let rec default_value name t = + if is_pos_infos t then + mk_pos_infos t + else + null (ctx.t.tnull t) callp + in + let skipped = ref [] in + let invalid_skips = ref [] in + let skip name ul t p = + if not ctx.com.config.pf_can_skip_non_nullable_argument && not (is_nullable t) then + invalid_skips := name :: !invalid_skips; + skipped := (name,ul,p) :: !skipped; + default_value name t + in + (* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, c.cl_extern | _ -> false, false in *) + let type_against name t e = + try + let e = type_expr ctx e (WithType.with_argument t name) in + AbstractCast.cast_or_unify_raise ctx t e e.epos + with Error(l,p) when (match l with Call_error _ | Module_not_found _ -> false | _ -> true) -> + raise (WithTypeError (l,p)) + in + let rec loop el args = match el,args with + | [],[] -> + begin match List.rev !invalid_skips with + | [] -> () + | name :: _ -> call_error (Cannot_skip_non_nullable name) callp; + end; + [] + | _,[name,false,t] when (match follow t with TAbstract({a_path = ["haxe";"extern"],"Rest"},_) -> true | _ -> false) -> + begin match follow t with + | TAbstract({a_path=(["haxe";"extern"],"Rest")},[t]) -> + (try List.map (fun e -> type_against name t e,false) el with WithTypeError(ul,p) -> arg_error ul name false p) + | _ -> + assert false + end + | [],(_,false,_) :: _ -> + call_error (Not_enough_arguments args) callp + | [],(name,true,t) :: args -> + begin match loop [] args with + | [] when not (inline && (ctx.g.doinline || force_inline)) && not ctx.com.config.pf_pad_nulls -> + if is_pos_infos t then [mk_pos_infos t,true] + else [] + | args -> + let e_def = default_value name t in + (e_def,true) :: args + end + | (e,p) :: el, [] -> + begin match List.rev !skipped with + | [] -> + if ctx.in_display then begin + let e = type_expr ctx (e,p) WithType.value in + (e,false) :: loop el [] + end else call_error Too_many_arguments p + | (s,ul,p) :: _ -> arg_error ul s true p + end + | e :: el,(name,opt,t) :: args -> + begin try + let e = type_against name t e in + (e,opt) :: loop el args + with + WithTypeError (ul,p)-> + if opt && List.length el < List.length args then + let e_def = skip name ul t p in + (e_def,true) :: loop (e :: el) args + else + match List.rev !skipped with + | [] -> arg_error ul name opt p + | (s,ul,p) :: _ -> arg_error ul s true p + end + in + let el = try loop el args with exc -> ctx.in_call_args <- in_call_args; raise exc; in + ctx.in_call_args <- in_call_args; + el,TFun(args,r) + +let unify_call_args ctx el args r p inline force_inline = + let el,tf = unify_call_args' ctx el args r p inline force_inline in + List.map fst el,tf + +let unify_field_call ctx fa el args ret p inline = + let map_cf cf0 map cf = + let t = map (monomorphs cf.cf_params cf.cf_type) in + begin match cf.cf_expr,cf.cf_kind with + | None,Method MethInline when not ctx.com.config.pf_overload -> + (* This is really awkward and shouldn't be here. We'll keep it for + 3.2 in order to not break code that relied on the quirky behavior + in 3.1.3, but it should really be reviewed afterwards. + Related issue: https://github.com/HaxeFoundation/haxe/issues/3846 + *) + cf.cf_expr <- cf0.cf_expr; + cf.cf_kind <- cf0.cf_kind; + | _ -> + () + end; + t,cf + in + let expand_overloads map cf = + (TFun(args,ret),cf) :: (List.map (map_cf cf map) cf.cf_overloads) + in + let candidates,co,cf,mk_fa = match fa with + | FStatic(c,cf) -> + expand_overloads (fun t -> t) cf,Some c,cf,(fun cf -> FStatic(c,cf)) + | FAnon cf -> + expand_overloads (fun t -> t) cf,None,cf,(fun cf -> FAnon cf) + | FInstance(c,tl,cf) -> + let map = apply_params c.cl_params tl in + let cfl = if cf.cf_name = "new" || not (Meta.has Meta.Overload cf.cf_meta && ctx.com.config.pf_overload) then + List.map (map_cf cf map) cf.cf_overloads + else + List.map (fun (t,cf) -> map (monomorphs cf.cf_params t),cf) (Overloads.get_overloads c cf.cf_name) + in + (TFun(args,ret),cf) :: cfl,Some c,cf,(fun cf -> FInstance(c,tl,cf)) + | FClosure(co,cf) -> + let c = match co with None -> None | Some (c,_) -> Some c in + expand_overloads (fun t -> t) cf,c,cf,(fun cf -> match co with None -> FAnon cf | Some (c,tl) -> FInstance(c,tl,cf)) + | _ -> + error "Invalid field call" p + in + let is_forced_inline = is_forced_inline co cf in + let is_overload = Meta.has Meta.Overload cf.cf_meta in + let attempt_call t cf = match follow t with + | TFun(args,ret) -> + let el,tf = unify_call_args' ctx el args ret p inline is_forced_inline in + let mk_call ethis p_field inline = + let ef = mk (TField(ethis,mk_fa cf)) t p_field in + make_call ctx ef (List.map fst el) ret ~force_inline:inline p + in + el,tf,mk_call + | _ -> + assert false + in + let maybe_raise_unknown_ident cerr p = + let rec loop err = + match err with + | Unknown_ident _ -> error (error_msg err) p + | Stack (e1,e2) -> (loop e1; loop e2) + | _ -> () + in + match cerr with Could_not_unify err -> loop err | _ -> () + in + let rec loop candidates = match candidates with + | [] -> [],[] + | (t,cf) :: candidates -> + begin try + let candidate = attempt_call t cf in + if ctx.com.config.pf_overload && is_overload then begin + let candidates,failures = loop candidates in + candidate :: candidates,failures + end else + [candidate],[] + with Error ((Call_error cerr as err),p) -> + maybe_raise_unknown_ident cerr p; + let candidates,failures = loop candidates in + candidates,(cf,err,p) :: failures + end + in + let fail_fun () = + let tf = TFun(args,ret) in + [],tf,(fun ethis p_field _ -> + let e1 = mk (TField(ethis,mk_fa cf)) tf p_field in + mk (TCall(e1,[])) ret p) + in + match candidates with + | [t,cf] -> + begin try + let el,tf,mk_call = attempt_call t cf in + List.map fst el,tf,mk_call + with Error _ when ctx.com.display.dms_error_policy = EPIgnore -> + fail_fun(); + end + | _ -> + let candidates,failures = loop candidates in + let fail () = + let failures = List.map (fun (cf,err,p) -> cf,error_msg err,p) failures in + let failures = remove_duplicates (fun (_,msg1,_) (_,msg2,_) -> msg1 <> msg2) failures in + begin match failures with + | [_,msg,p] -> + error msg p + | _ -> + display_error ctx "Could not find a suitable overload, reasons follow" p; + List.iter (fun (cf,msg,p2) -> + display_error ctx ("Overload resolution failed for " ^ (s_type (print_context()) cf.cf_type)) p; + display_error ctx msg p2; + ) failures; + error "End of overload failure reasons" p + end + in + if is_overload && ctx.com.config.pf_overload then begin match Overloads.Resolution.reduce_compatible candidates with + | [] -> fail() + | [el,tf,mk_call] -> List.map fst el,tf,mk_call + | _ -> error "Ambiguous overload" p + end else begin match List.rev candidates with + | [] -> fail() + | (el,tf,mk_call) :: _ -> List.map fst el,tf,mk_call + end + +let type_generic_function ctx (e,fa) el ?(using_param=None) with_type p = + let c,tl,cf,stat = match fa with + | FInstance(c,tl,cf) -> c,tl,cf,false + | FStatic(c,cf) -> c,[],cf,true + | _ -> assert false + in + if cf.cf_params = [] then error "Function has no type parameters and cannot be generic" p; + let monos = List.map (fun _ -> mk_mono()) cf.cf_params in + let map_monos t = apply_params cf.cf_params monos t in + let map t = if stat then map_monos t else apply_params c.cl_params tl (map_monos t) in + let t = map cf.cf_type in + let args,ret = match t,using_param with + | TFun((_,_,ta) :: args,ret),Some e -> + let ta = if not (Meta.has Meta.Impl cf.cf_meta) then ta + else match follow ta with TAbstract(a,tl) -> Abstract.get_underlying_type a tl | _ -> assert false + in + (* manually unify first argument *) + unify ctx e.etype ta p; + args,ret + | TFun(args,ret),None -> args,ret + | _ -> error "Invalid field type for generic call" p + in + begin match with_type with + | WithType.WithType(t,_) -> unify ctx ret t p + | _ -> () + end; + let el,_ = unify_call_args ctx el args ret p false false in + begin try + check_constraints ctx cf.cf_name cf.cf_params monos map false p + with Unify_error l -> + display_error ctx (error_msg (Unify l)) p + end; + let el = match using_param with None -> el | Some e -> e :: el in + (try + let gctx = Generic.make_generic ctx cf.cf_params monos p in + let name = cf.cf_name ^ "_" ^ gctx.Generic.name in + let unify_existing_field tcf pcf = try + unify_raise ctx tcf t p + with Error(Unify _,_) as err -> + display_error ctx ("Cannot create field " ^ name ^ " due to type mismatch") p; + display_error ctx "Conflicting field was defined here" pcf; + raise err + in + let cf2 = try + let cf2 = if stat then + let cf2 = PMap.find name c.cl_statics in + unify_existing_field cf2.cf_type cf2.cf_pos; + cf2 + else + let cf2 = PMap.find name c.cl_fields in + unify_existing_field cf2.cf_type cf2.cf_pos; + cf2 + in + cf2 + (* + java.Lib.array() relies on the ability to shadow @:generic function for certain types + see https://github.com/HaxeFoundation/haxe/issues/8393#issuecomment-508685760 + *) + (* if cf.cf_name_pos = cf2.cf_name_pos then + cf2 + else + error ("Cannot specialize @:generic because the generated function name is already used: " ^ name) p *) + with Not_found -> + let cf2 = mk_field name (map_monos cf.cf_type) cf.cf_pos cf.cf_name_pos in + if stat then begin + c.cl_statics <- PMap.add name cf2 c.cl_statics; + c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics + end else begin + if List.memq cf c.cl_overrides then c.cl_overrides <- cf2 :: c.cl_overrides; + c.cl_fields <- PMap.add name cf2 c.cl_fields; + c.cl_ordered_fields <- cf2 :: c.cl_ordered_fields + end; + ignore(follow cf.cf_type); + let rec check e = match e.eexpr with + | TNew({cl_kind = KTypeParameter _} as c,_,_) when not (TypeloadCheck.is_generic_parameter ctx c) -> + display_error ctx "Only generic type parameters can be constructed" e.epos; + display_error ctx "While specializing this call" p; + | _ -> + Type.iter check e + in + cf2.cf_expr <- (match cf.cf_expr with + | None -> + display_error ctx "Recursive @:generic function" p; None; + | Some e -> + let e = Generic.generic_substitute_expr gctx e in + check e; + Some e + ); + cf2.cf_kind <- cf.cf_kind; + if not (has_class_field_flag cf CfPublic) then remove_class_field_flag cf2 CfPublic; + let metadata = List.filter (fun (m,_,_) -> match m with + | Meta.Generic -> false + | _ -> true + ) cf.cf_meta in + cf2.cf_meta <- (Meta.NoCompletion,[],p) :: (Meta.NoUsing,[],p) :: (Meta.GenericInstance,[],p) :: metadata; + cf2 + in + let e = match c.cl_kind with + | KAbstractImpl(a) -> + type_type ctx a.a_path p + | _ -> e + in + let fa = if stat then FStatic (c,cf2) else FInstance (c,tl,cf2) in + let e = mk (TField(e,fa)) cf2.cf_type p in + make_call ctx e el ret p + with Generic.Generic_Exception (msg,p) -> + error msg p) + +let rec acc_get ctx g p = + match g with + | AKNo f -> error ("Field " ^ f ^ " cannot be accessed for reading") p + | AKExpr e -> e + | AKSet _ | AKAccess _ | AKFieldSet _ -> assert false + | AKUsing (et,c,cf,e,_) when ctx.in_display -> + (* Generate a TField node so we can easily match it for position/usage completion (issue #1968) *) + let ec = type_module_type ctx (TClassDecl c) None p in + let ec = {ec with eexpr = (TMeta((Meta.StaticExtension,[],null_pos),ec))} in + let t = match follow et.etype with + | TFun (_ :: args,ret) -> TFun(args,ret) + | _ -> et.etype + in + mk (TField(ec,FStatic(c,cf))) t et.epos + | AKUsing (et,_,cf,e,_) -> + (* build a closure with first parameter applied *) + (match follow et.etype with + | TFun (_ :: args,ret) -> + let tcallb = TFun (args,ret) in + let twrap = TFun ([("_e",false,e.etype)],tcallb) in + (* arguments might not have names in case of variable fields of function types, so we generate one (issue #2495) *) + let args = List.map (fun (n,o,t) -> + let t = if o then ctx.t.tnull t else t in + o,if n = "" then gen_local ctx t e.epos else alloc_var VGenerated n t e.epos (* TODO: var pos *) + ) args in + let ve = alloc_var VGenerated "_e" e.etype e.epos in + let ecall = make_call ctx et (List.map (fun v -> mk (TLocal v) v.v_type p) (ve :: List.map snd args)) ret p in + let ecallb = mk (TFunction { + tf_args = List.map (fun (o,v) -> v,if o then Some (Texpr.Builder.make_null v.v_type v.v_pos) else None) args; + tf_type = ret; + tf_expr = (match follow ret with | TAbstract ({a_path = [],"Void"},_) -> ecall | _ -> mk (TReturn (Some ecall)) t_dynamic p); + }) tcallb p in + let ewrap = mk (TFunction { + tf_args = [ve,None]; + tf_type = tcallb; + tf_expr = mk (TReturn (Some ecallb)) t_dynamic p; + }) twrap p in + make_call ctx ewrap [e] tcallb p + | _ -> assert false) + | AKInline (e,f,fmode,t) -> + (* do not create a closure for static calls *) + let cmode = (match fmode with FStatic _ -> fmode | FInstance (c,tl,f) -> FClosure (Some (c,tl),f) | _ -> assert false) in + ignore(follow f.cf_type); (* force computing *) + begin match f.cf_kind,f.cf_expr with + | _ when not (ctx.com.display.dms_inline) -> + mk (TField (e,cmode)) t p + | Method _,_-> + let chk_class c = (c.cl_extern || has_class_field_flag f CfExtern) && not (Meta.has Meta.Runtime f.cf_meta) in + let wrap_extern c = + let c2 = + let m = c.cl_module in + let mpath = (fst m.m_path @ ["_" ^ snd m.m_path],(snd m.m_path) ^ "_Impl_") in + try + let rec loop mtl = match mtl with + | (TClassDecl c) :: _ when c.cl_path = mpath -> c + | _ :: mtl -> loop mtl + | [] -> raise Not_found + in + loop c.cl_module.m_types + with Not_found -> + let c2 = mk_class c.cl_module mpath c.cl_pos null_pos in + c.cl_module.m_types <- (TClassDecl c2) :: c.cl_module.m_types; + c2 + in + let cf = try + PMap.find f.cf_name c2.cl_statics + with Not_found -> + let cf = {f with cf_kind = Method MethNormal} in + c2.cl_statics <- PMap.add cf.cf_name cf c2.cl_statics; + c2.cl_ordered_statics <- cf :: c2.cl_ordered_statics; + cf + in + let e_t = type_module_type ctx (TClassDecl c2) None p in + mk (TField(e_t,FStatic(c2,cf))) t p + in + let e_def = mk (TField (e,cmode)) t p in + begin match follow e.etype with + | TInst (c,_) when chk_class c -> + display_error ctx "Can't create closure on an extern inline member method" p; + e_def + | TAnon a -> + begin match !(a.a_status) with + | Statics {cl_extern = false} when has_class_field_flag f CfExtern -> + display_error ctx "Cannot create closure on @:extern inline method" p; + e_def + | Statics c when chk_class c -> wrap_extern c + | _ -> e_def + end + | _ -> e_def + end + | Var _,Some e -> + let rec loop e = Type.map_expr loop { e with epos = p } in + let e = loop e in + let e = Inline.inline_metadata e f.cf_meta in + if not (type_iseq f.cf_type e.etype) then mk (TCast(e,None)) f.cf_type e.epos + else e + | Var _,None when ctx.com.display.dms_display -> + mk (TField (e,cmode)) t p + | Var _,None -> + error "Recursive inline is not supported" p + end + | AKMacro _ -> + assert false + +let rec build_call ?(mode=MGet) ctx acc el (with_type:WithType.t) p = + let check_assign () = if mode = MSet then invalid_assign p in + match acc with + | AKInline (ethis,f,fmode,t) when Meta.has Meta.Generic f.cf_meta -> + check_assign(); + type_generic_function ctx (ethis,fmode) el with_type p + | AKInline (ethis,f,fmode,t) -> + check_assign(); + (match follow t with + | TFun (args,r) -> + let _,_,mk_call = unify_field_call ctx fmode el args r p true in + mk_call ethis p true + | _ -> + error (s_type (print_context()) t ^ " cannot be called") p + ) + | AKUsing (et,cl,ef,eparam,forced_inline (* TOOD? *)) when Meta.has Meta.Generic ef.cf_meta -> + check_assign(); + (match et.eexpr with + | TField(ec,fa) -> + type_generic_function ctx (ec,fa) el ~using_param:(Some eparam) with_type p + | _ -> assert false) + | AKUsing (et,cl,ef,eparam,force_inline) -> + begin match ef.cf_kind with + | Method MethMacro -> + let ethis = type_module_type ctx (TClassDecl cl) None p in + let eparam,f = push_this ctx eparam in + let e = build_call ~mode ctx (AKMacro (ethis,ef)) (eparam :: el) with_type p in + f(); + e + | _ -> + check_assign(); + let t = follow (field_type ctx cl [] ef p) in + (* for abstracts we have to apply their parameters to the static function *) + let t,tthis = match follow eparam.etype with + | TAbstract(a,tl) when Meta.has Meta.Impl ef.cf_meta -> apply_params a.a_params tl t,apply_params a.a_params tl a.a_this + | te -> t,te + in + let params,args,r,eparam = match t with + | TFun ((_,_,t1) :: args,r) -> + unify ctx tthis t1 eparam.epos; + let ef = prepare_using_field ef in + begin match unify_call_args ctx el args r p (ef.cf_kind = Method MethInline) (is_forced_inline (Some cl) ef) with + | el,TFun(args,r) -> el,args,r,eparam + | _ -> assert false + end + | _ -> assert false + in + make_call ctx ~force_inline et (eparam :: params) r p + end + | AKMacro (ethis,cf) -> + if ctx.macro_depth > 300 then error "Stack overflow" p; + ctx.macro_depth <- ctx.macro_depth + 1; + ctx.with_type_stack <- with_type :: ctx.with_type_stack; + let ethis_f = ref (fun () -> ()) in + let f = (match ethis.eexpr with + | TTypeExpr (TClassDecl c) -> + (match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with + | None -> (fun() -> type_expr ~mode ctx (EConst (Ident "null"),p) WithType.value) + | Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = (!type_block_ref) ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos) + | Some e -> (fun() -> type_expr ~mode ctx e with_type)) + | _ -> + (* member-macro call : since we will make a static call, let's find the actual class and not its subclass *) + (match follow ethis.etype with + | TInst (c,_) -> + let rec loop c = + if PMap.mem cf.cf_name c.cl_fields then + let eparam,f = push_this ctx ethis in + ethis_f := f; + let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with + | None -> (fun() -> type_expr ~mode ctx (EConst (Ident "null"),p) WithType.value) + | Some e -> (fun() -> type_expr ~mode ctx e WithType.value) + in + e + else + match c.cl_super with + | None -> assert false + | Some (csup,_) -> loop csup + in + loop c + | _ -> assert false)) + in + ctx.macro_depth <- ctx.macro_depth - 1; + ctx.with_type_stack <- List.tl ctx.with_type_stack; + let old = ctx.on_error in + ctx.on_error <- (fun ctx msg ep -> + (* display additional info in the case the error is not part of our original call *) + if ep.pfile <> p.pfile || ep.pmax < p.pmin || ep.pmin > p.pmax then begin + TypeloadFields.locate_macro_error := false; + old ctx msg ep; + TypeloadFields.locate_macro_error := true; + ctx.com.error "Called from macro here" p; + end else + old ctx msg ep; + ); + let e = try + f() + with exc -> + ctx.on_error <- old; + !ethis_f(); + raise exc + in + let e = Diagnostics.secure_generated_code ctx e in + ctx.on_error <- old; + !ethis_f(); + e + | AKNo _ | AKSet _ | AKAccess _ | AKFieldSet _ -> + ignore(acc_get ctx acc p); + assert false + | AKExpr e -> + let rec loop t = match follow t with + | TFun (args,r) -> + begin match e.eexpr with + | TField(e1,fa) when not (match fa with FEnum _ | FDynamic _ -> true | _ -> false) -> + begin match fa with + | FInstance(_,_,cf) | FStatic(_,cf) when Meta.has Meta.Generic cf.cf_meta -> + type_generic_function ctx (e1,fa) el with_type p + | _ -> + let _,_,mk_call = unify_field_call ctx fa el args r p false in + mk_call e1 e.epos false + end + | _ -> + let el, tfunc = unify_call_args ctx el args r p false false in + let r = match tfunc with TFun(_,r) -> r | _ -> assert false in + mk (TCall (e,el)) r p + end + | TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta -> + loop (Abstract.get_underlying_type a tl) + | TMono _ -> + let t = mk_mono() in + let el = List.map (fun e -> type_expr ctx e WithType.value) el in + unify ctx (tfun (List.map (fun e -> e.etype) el) t) e.etype e.epos; + mk (TCall (e,el)) t p + | t -> + let el = List.map (fun e -> type_expr ctx e WithType.value) el in + let t = if t == t_dynamic then + t_dynamic + else if ctx.untyped then + mk_mono() + else + error (s_type (print_context()) e.etype ^ " cannot be called") e.epos + in + mk (TCall (e,el)) t p + in + loop e.etype + +let type_bind ctx (e : texpr) (args,ret) params p = + let vexpr v = mk (TLocal v) v.v_type p in + let acount = ref 0 in + let alloc_name n = + if n = "" && not ctx.is_display_file then begin + incr acount; + "a" ^ string_of_int !acount; + end else + n + in + let rec loop args params given_args missing_args ordered_args = match args, params with + | [], [] -> given_args,missing_args,ordered_args + | [], _ -> error "Too many callback arguments" p + | (n,o,t) :: args , [] when o -> + let a = if is_pos_infos t then + let infos = mk_infos ctx p [] in + ordered_args @ [type_expr ctx infos (WithType.with_argument t n)] + else if ctx.com.config.pf_pad_nulls then + (ordered_args @ [(mk (TConst TNull) t_dynamic p)]) + else + ordered_args + in + loop args [] given_args missing_args a + | (n,o,t) :: _ , (EConst(Ident "_"),p) :: _ when not ctx.com.config.pf_can_skip_non_nullable_argument && o && not (is_nullable t) -> + error "Usage of _ is not supported for optional non-nullable arguments" p + | (n,o,t) :: args , ([] as params) + | (n,o,t) :: args , (EConst(Ident "_"),_) :: params -> + let v = alloc_var VGenerated (alloc_name n) (if o then ctx.t.tnull t else t) p in + loop args params given_args (missing_args @ [v,o]) (ordered_args @ [vexpr v]) + | (n,o,t) :: args , param :: params -> + let e = type_expr ctx param (WithType.with_argument t n) in + let e = AbstractCast.cast_or_unify ctx t e p in + let v = alloc_var VGenerated (alloc_name n) t (pos param) in + loop args params (given_args @ [v,o,Some e]) missing_args (ordered_args @ [vexpr v]) + in + let given_args,missing_args,ordered_args = loop args params [] [] [] in + let rec gen_loc_name n = + let name = if n = 0 then "f" else "f" ^ (string_of_int n) in + if List.exists (fun (n,_,_) -> name = n) args then gen_loc_name (n + 1) else name + in + let loc = alloc_var VGenerated (gen_loc_name 0) e.etype e.epos in + let given_args = (loc,false,Some e) :: given_args in + let inner_fun_args l = List.map (fun (v,o) -> v.v_name, o, v.v_type) l in + let t_inner = TFun(inner_fun_args missing_args, ret) in + let call = make_call ctx (vexpr loc) ordered_args ret p in + let e_ret = match follow ret with + | TAbstract ({a_path = [],"Void"},_) -> + call + | TMono _ -> + mk (TReturn (Some call)) t_dynamic p; + | _ -> + mk (TReturn (Some call)) t_dynamic p; + in + let func = mk (TFunction { + tf_args = List.map (fun (v,o) -> v, if o then Some (Texpr.Builder.make_null v.v_type null_pos) else None) missing_args; + tf_type = ret; + tf_expr = e_ret; + }) t_inner p in + let outer_fun_args l = List.map (fun (v,o,_) -> v.v_name, o, v.v_type) l in + let func = mk (TFunction { + tf_args = List.map (fun (v,_,_) -> v,None) given_args; + tf_type = t_inner; + tf_expr = mk (TReturn (Some func)) t_inner p; + }) (TFun(outer_fun_args given_args, t_inner)) p in + make_call ctx func (List.map (fun (_,_,e) -> (match e with Some e -> e | None -> assert false)) given_args) t_inner p + +let array_access ctx e1 e2 mode p = + let has_abstract_array_access = ref false in + try + (match follow e1.etype with + | TAbstract ({a_impl = Some c} as a,pl) when a.a_array <> [] -> + begin match mode with + | MSet -> + (* resolve later *) + AKAccess (a,pl,c,e1,e2) + | _ -> + has_abstract_array_access := true; + let e = mk_array_get_call ctx (AbstractCast.find_array_access ctx a pl e2 None p) c e1 p in + AKExpr e + end + | _ -> raise Not_found) + with Not_found -> + unify ctx e2.etype ctx.t.tint e2.epos; + let rec loop ?(skip_abstract=false) et = + match skip_abstract,follow et with + | _, TInst ({ cl_array_access = Some t; cl_params = pl },tl) -> + apply_params pl tl t + | _, TInst ({ cl_super = Some (c,stl); cl_params = pl },tl) -> + apply_params pl tl (loop (TInst (c,stl))) + | _, TInst ({ cl_path = [],"ArrayAccess" },[t]) -> + t + | _, TInst ({ cl_path = [],"Array"},[t]) when t == t_dynamic -> + t_dynamic + | false, TAbstract(a,tl) when Meta.has Meta.ArrayAccess a.a_meta -> + let at = apply_params a.a_params tl a.a_this in + let skip_abstract = fast_eq et at in + loop ~skip_abstract at + | _, _ -> + let pt = mk_mono() in + let t = ctx.t.tarray pt in + (try unify_raise ctx et t p + with Error(Unify _,_) -> if not ctx.untyped then begin + if !has_abstract_array_access then error ("No @:arrayAccess function accepts an argument of " ^ (s_type (print_context()) e2.etype)) e1.epos + else error ("Array access is not allowed on " ^ (s_type (print_context()) e1.etype)) e1.epos + end); + pt + in + let pt = loop e1.etype in + AKExpr (mk (TArray (e1,e2)) pt p) \ No newline at end of file diff --git a/src/typing/fields.ml b/src/typing/fields.ml new file mode 100644 index 00000000000..c34deead667 --- /dev/null +++ b/src/typing/fields.ml @@ -0,0 +1,623 @@ +open Globals +open Common +open Ast +open Type +open TyperBase +open Error +open Typecore + +module TypeFieldConfig = struct + type t = { + allow_resolve : bool; + do_resume : bool; + } + + let allow_resolve cfg = cfg.allow_resolve + + let do_resume cfg = cfg.do_resume + + let default = { + allow_resolve = true; + do_resume = false; + } + + let create resume = { + allow_resolve = true; + do_resume = resume; + } + + let with_resume cfg = {cfg with do_resume = true} +end + +(* + temporally remove the constant flag from structures to allow larger unification +*) +let remove_constant_flag t callb = + let tmp = ref [] in + let rec loop t = + match follow t with + | TAnon a -> + if !(a.a_status) = Const then begin + a.a_status := Closed; + tmp := a :: !tmp; + end; + PMap.iter (fun _ f -> loop f.cf_type) a.a_fields; + | _ -> + () + in + let restore() = + List.iter (fun a -> a.a_status := Const) (!tmp) + in + try + loop t; + let ret = callb (!tmp <> []) in + restore(); + ret + with e -> + restore(); + raise e + +let check_constraints ctx tname tpl tl map delayed p = + List.iter2 (fun m (name,t) -> + match follow t with + | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> + let f = (fun() -> + List.iter (fun ct -> + try + Type.unify (map m) (map ct) + with Unify_error l -> + let l = Constraint_failure (tname ^ "." ^ name) :: l in + raise (Unify_error l) + ) constr + ) in + if delayed then + delay ctx PCheckConstraint (fun () -> try f() with Unify_error l -> display_error ctx (error_msg (Unify l)) p) + else + f() + | _ -> + () + ) tl tpl + +let enum_field_type ctx en ef tl_en tl_ef p = + let map t = apply_params en.e_params tl_en (apply_params ef.ef_params tl_ef t) in + begin try + check_constraints ctx (s_type_path en.e_path) en.e_params 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 + +let add_constraint_checks ctx ctypes pl f tl p = + List.iter2 (fun m (name,t) -> + match follow t with + | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> + let constr = List.map (fun t -> + let t = apply_params f.cf_params tl t in + (* only apply params if not static : in that case no param is passed *) + let t = (if pl = [] then t else apply_params ctypes pl t) in + t + ) constr in + delay ctx PCheckConstraint (fun() -> + List.iter (fun ct -> + try + (* if has_mono m then raise (Unify_error [Unify_custom "Could not resolve full type for constraint checks"; Unify_custom ("Type was " ^ (s_type (print_context()) m))]); *) + Type.unify m ct + with Unify_error l -> + display_error ctx (error_msg (Unify (Constraint_failure (f.cf_name ^ "." ^ name) :: l))) p; + ) constr + ); + | _ -> () + ) tl f.cf_params + +let field_type ctx c pl f p = + match f.cf_params with + | [] -> f.cf_type + | l -> + let monos = List.map (fun _ -> mk_mono()) l in + if not (Meta.has Meta.Generic f.cf_meta) then add_constraint_checks ctx c.cl_params pl f monos p; + apply_params l monos f.cf_type + +let fast_enum_field e ef p = + let et = mk (TTypeExpr (TEnumDecl e)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }) p in + TField (et,FEnum (e,ef)) + +let get_constructor ctx c params p = + match c.cl_kind with + | KAbstractImpl a -> + let f = (try PMap.find "_new" c.cl_statics with Not_found -> raise_error (No_constructor (TAbstractDecl a)) p) in + let ct = field_type ctx c params f p in + apply_params a.a_params params ct, f + | _ -> + let ct, f = (try Type.get_constructor (fun f -> field_type ctx c params f p) c with Not_found -> raise_error (No_constructor (TClassDecl c)) p) in + apply_params c.cl_params params ct, f + +let check_constructor_access ctx c f p = + if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx (error_msg (No_constructor (TClassDecl c))) p; + if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx (Printf.sprintf "Cannot access private constructor of %s" (s_class_path c)) p + +let check_no_closure_meta ctx fa mode p = + if mode <> MCall && not (DisplayPosition.display_position#enclosed_in p) then begin + let check_field f cl_meta = + match f.cf_kind with + | Method _ -> + if + Meta.has Meta.NoClosure cl_meta + || Meta.has Meta.NoClosure f.cf_meta + then + error ("Method " ^ f.cf_name ^ " cannot be used as a value") p + | _ -> () + in + match fa with + | FStatic (c, ({ cf_kind = Method _} as f)) -> check_field f c.cl_meta + | FInstance (c, _, ({ cf_kind = Method _} as f)) -> check_field f c.cl_meta + | FClosure (Some (c, _), ({ cf_kind = Method _} as f)) -> check_field f c.cl_meta + | FClosure (None, ({ cf_kind = Method _} as f)) -> check_field f [] + | FAnon ({ cf_kind = Method _} as f) -> check_field f [] + | _ -> () + end + +let field_access ctx mode f fmode t e p = + check_no_closure_meta ctx fmode mode p; + let bypass_accessor = if ctx.bypass_accessor > 0 then (ctx.bypass_accessor <- ctx.bypass_accessor - 1; true) else false in + let fnormal() = AKExpr (mk (TField (e,fmode)) t p) in + let normal() = + match follow e.etype with + | TAnon a -> + (match !(a.a_status) with + | EnumStatics en -> + let c = (try PMap.find f.cf_name en.e_constrs with Not_found -> assert false) in + let fmode = FEnum (en,c) in + AKExpr (mk (TField (e,fmode)) t p) + | _ -> fnormal()) + | _ -> fnormal() + in + match f.cf_kind with + | Method m -> + if mode = MSet && m <> MethDynamic && not ctx.untyped then error "Cannot rebind this method : please use 'dynamic' before method declaration" p; + begin match ctx.curfun,e.eexpr with + | (FunMemberAbstract | FunMemberAbstractLocal),TTypeExpr(TClassDecl ({cl_kind = KAbstractImpl a} as c)) when c == ctx.curclass && Meta.has Meta.Impl f.cf_meta -> + let e = mk (TField(e,fmode)) t p in + let ethis = get_this ctx p in + let ethis = {ethis with etype = TAbstract(a,List.map snd a.a_params)} in + AKUsing(e,ctx.curclass,f,ethis,false) + | _ -> + (match m, mode with + | MethInline, _ -> AKInline (e,f,fmode,t) + | MethMacro, MGet -> display_error ctx "Macro functions must be called immediately" p; normal() + | MethMacro, MCall -> AKMacro (e,f) + | _ , MGet -> + let cmode = (match fmode with + | FInstance(_, _, cf) | FStatic(_, cf) when Meta.has Meta.Generic cf.cf_meta -> display_error ctx "Cannot create closure on generic function" p; fmode + | FInstance (c,tl,cf) -> FClosure (Some (c,tl),cf) + | FStatic _ | FEnum _ -> fmode + | FAnon f -> FClosure (None, f) + | FDynamic _ | FClosure _ -> assert false + ) in + AKExpr (mk (TField (e,cmode)) t p) + | _ -> normal()) + end + | Var v -> + match (match mode with MGet | MCall -> v.v_read | MSet -> v.v_write) with + | AccNo when not (Meta.has Meta.PrivateAccess ctx.meta) -> + (match follow e.etype with + | TInst (c,_) when is_parent c ctx.curclass || can_access ctx c { f with cf_flags = unset_flag f.cf_flags (int_of_class_field_flag CfPublic) } false -> normal() + | TAnon a -> + (match !(a.a_status) with + | Opened when mode = MSet -> + f.cf_kind <- Var { v with v_write = AccNormal }; + normal() + | Statics c2 when ctx.curclass == c2 || can_access ctx c2 { f with cf_flags = unset_flag f.cf_flags (int_of_class_field_flag CfPublic) } true -> normal() + | _ -> if ctx.untyped then normal() else AKNo f.cf_name) + | _ -> + if ctx.untyped then normal() else AKNo f.cf_name) + | AccNormal | AccNo -> + (* + if we are reading from a read-only variable on an anonymous object, it might actually be a method, so make sure to create a closure + *) + let is_maybe_method() = + match v.v_write, follow t, follow e.etype with + | (AccNo | AccNever), TFun _, TAnon a -> + (match !(a.a_status) with + | Statics _ | EnumStatics _ -> false + | _ -> true) + | _ -> false + in + if mode = MGet && is_maybe_method() then + AKExpr (mk (TField (e,FClosure (None,f))) t p) + else + normal() + | AccCall | AccInline when ctx.in_display -> + normal() + | AccCall -> + let m = (match mode with MSet -> "set_" | _ -> "get_") ^ f.cf_name in + let is_abstract_this_access () = match e.eexpr,ctx.curfun with + | TTypeExpr (TClassDecl ({cl_kind = KAbstractImpl _} as c)),(FunMemberAbstract | FunMemberAbstractLocal) -> + c == ctx.curclass + | _ -> + false + in + let bypass_accessor = + bypass_accessor + || + ( + m = ctx.curfield.cf_name + && + match e.eexpr with + | TConst TThis -> true + | TLocal v -> Option.map_default (fun vthis -> v == vthis) false ctx.vthis + | TTypeExpr (TClassDecl c) when c == ctx.curclass -> true + | _ -> false + ) + in + if bypass_accessor then + let prefix = (match ctx.com.platform with Flash when Common.defined ctx.com Define.As3 -> "$" | _ -> "") in + (match e.eexpr with TLocal _ when Common.defined ctx.com Define.Haxe3Compat -> ctx.com.warning "Field set has changed here in Haxe 4: call setter explicitly to keep Haxe 3.x behaviour" p | _ -> ()); + if not (is_physical_field f) then begin + display_error ctx "This field cannot be accessed because it is not a real variable" p; + display_error ctx "Add @:isVar here to enable it" f.cf_pos; + end; + AKExpr (mk (TField (e,if prefix = "" then fmode else FDynamic (prefix ^ f.cf_name))) t p) + else if is_abstract_this_access() then begin + let this = get_this ctx p in + if mode = MSet then begin + let c,a = match ctx.curclass with {cl_kind = KAbstractImpl a} as c -> c,a | _ -> assert false in + let f = PMap.find m c.cl_statics in + (* we don't have access to the type parameters here, right? *) + (* let t = apply_params a.a_params pl (field_type ctx c [] f p) in *) + let t = (field_type ctx c [] f p) in + let ef = mk (TField (e,FStatic (c,f))) t p in + AKUsing (ef,c,f,this,false) + end else + AKExpr (make_call ctx (mk (TField (e,quick_field_dynamic e.etype m)) (tfun [this.etype] t) p) [this] t p) + end else if mode = MSet then + AKSet (e,t,f) + else + AKExpr (make_call ctx (mk (TField (e,quick_field_dynamic e.etype m)) (tfun [] t) p) [] t p) + | AccResolve -> + let fstring = mk (TConst (TString f.cf_name)) ctx.t.tstring p in + let tresolve = tfun [ctx.t.tstring] t in + AKExpr (make_call ctx (mk (TField (e,FDynamic "resolve")) tresolve p) [fstring] t p) + | AccNever -> + if ctx.untyped then normal() else AKNo f.cf_name + | AccInline -> + AKInline (e,f,fmode,t) + | AccCtor -> + if ctx.curfun = FunConstructor then normal() else AKNo f.cf_name + | AccRequire (r,msg) -> + match msg with + | None -> error_require r p + | Some msg -> error msg p + +let class_field ctx c tl name p = + raw_class_field (fun f -> field_type ctx c tl f p) c tl name + +let rec using_field ctx mode e i p = + if mode = MSet then raise Not_found; + (* do not try to find using fields if the type is a monomorph, which could lead to side-effects *) + let is_dynamic = match follow e.etype with + | TMono _ -> raise Not_found + | t -> t == t_dynamic + in + let check_constant_struct = ref false in + let rec loop = function + | [] -> + raise Not_found + | (c,pc) :: l -> + try + let cf = PMap.find i c.cl_statics in + if Meta.has Meta.NoUsing cf.cf_meta || not (can_access ctx c cf true) || (Meta.has Meta.Impl cf.cf_meta) then raise Not_found; + let monos = List.map (fun _ -> mk_mono()) cf.cf_params in + let map = apply_params cf.cf_params monos in + let t = map cf.cf_type in + begin match follow t with + | TFun((_,_,(TType({t_path = ["haxe";"macro"],"ExprOf"},[t0]) | t0)) :: args,r) -> + if is_dynamic && follow t0 != t_dynamic then raise Not_found; + let e = unify_static_extension ctx e t0 p in + (* early constraints check is possible because e.etype has no monomorphs *) + List.iter2 (fun m (name,t) -> match follow t with + | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] && not (has_mono m) -> + List.iter (fun tc -> Type.unify m (map tc)) constr + | _ -> () + ) monos cf.cf_params; + let et = type_module_type ctx (TClassDecl c) None p in + ImportHandling.maybe_mark_import_position ctx pc; + AKUsing (mk (TField (et,FStatic (c,cf))) t p,c,cf,e,false) + | _ -> + raise Not_found + end + with Not_found -> + loop l + | Unify_error el | Error (Unify el,_) -> + if List.exists (function Has_extra_field _ -> true | _ -> false) el then check_constant_struct := true; + loop l + in + try + (* module using from `using Path` *) + loop ctx.m.module_using + with Not_found -> try + (* type using from `@:using(Path)` *) + let mt = module_type_of_type e.etype in + loop (t_infos mt).mt_using + with Not_found | Exit -> try + (* global using *) + let acc = loop ctx.g.global_using in + (match acc with + | AKUsing (_,c,_,_,_) -> add_dependency ctx.m.curmod c.cl_module + | _ -> assert false); + acc + with Not_found -> + if not !check_constant_struct then raise Not_found; + remove_constant_flag e.etype (fun ok -> if ok then using_field ctx mode e i p else raise Not_found) + +(* Resolves field [i] on typed expression [e] using the given [mode]. *) +let rec type_field cfg ctx e i p mode = + let pfield = if (e.epos = p) then p else {p with pmin = p.pmax - (String.length i)} in + let no_field() = + if TypeFieldConfig.do_resume cfg then raise Not_found; + let t = match follow e.etype with + | TAnon a -> (match !(a.a_status) with + | Statics {cl_kind = KAbstractImpl a} -> TAbstract(a,[]) + | _ -> e.etype) + | TInst({cl_kind = KAbstractImpl a},_) -> TAbstract(a,[]) + | _ -> e.etype + in + let has_special_field a = + List.exists (fun (_,cf) -> cf.cf_name = i) a.a_ops + || List.exists (fun (_,_,cf) -> cf.cf_name = i) a.a_unops + || List.exists (fun cf -> cf.cf_name = i) a.a_array + in + if not ctx.untyped then begin + match t with + | TAbstract(a,_) when has_special_field a -> + (* the abstract field is not part of the field list, which is only true when it has no expression (issue #2344) *) + display_error ctx ("Field " ^ i ^ " cannot be called directly because it has no expression") pfield; + | _ -> + display_error ctx (StringError.string_error i (string_source t) (s_type (print_context()) t ^ " has no field " ^ i)) pfield; + end; + AKExpr (mk (TField (e,FDynamic i)) (mk_mono()) p) + in + let does_forward a stat = + try + let _,el,_ = Meta.get (if stat then Meta.ForwardStatics else Meta.Forward) a.a_meta in + match el with + | [] -> + true + | _ -> + List.exists (fun e -> match fst e with + | EConst(Ident s | String s) -> s = i + | _ -> error "Identifier or string expected as argument to @:forward" (pos e) + ) el + with Not_found -> + false + in + match follow e.etype with + | TInst (c,params) -> + let rec loop_dyn c params = + match c.cl_dynamic with + | Some t -> + let t = apply_params c.cl_params params t in + if (mode = MGet || mode = MCall) && PMap.mem "resolve" c.cl_fields then begin + let f = PMap.find "resolve" c.cl_fields in + begin match f.cf_kind with + | Method MethMacro -> display_error ctx "The macro accessor is not allowed for field resolve" f.cf_pos + | _ -> () + end; + let texpect = tfun [ctx.t.tstring] t in + let tfield = apply_params c.cl_params params (monomorphs f.cf_params f.cf_type) in + (try Type.unify tfield texpect + with Unify_error l -> + display_error ctx "Field resolve has an invalid type" f.cf_pos; + display_error ctx (error_msg (Unify [Cannot_unify(tfield,texpect)])) f.cf_pos); + AKExpr (make_call ctx (mk (TField (e,FInstance (c,params,f))) tfield p) [Texpr.type_constant ctx.com.basic (String i) p] t p) + end else + AKExpr (mk (TField (e,FDynamic i)) t p) + | None -> + match c.cl_super with + | None -> raise Not_found + | Some (c,params) -> loop_dyn c params + in + (try + let c2, t , f = class_field ctx c params i p in + if e.eexpr = TConst TSuper then (match mode,f.cf_kind with + | MGet,Var {v_read = AccCall } + | MSet,Var {v_write = AccCall } + | MCall,Var {v_read = AccCall } -> + () + | MCall, Var _ -> + display_error ctx "Cannot access superclass variable for calling: needs to be a proper method" pfield + | MCall, _ -> + () + | MGet,Var _ + | MSet,Var _ when ctx.com.platform = Flash && (match c2 with Some ({ cl_extern = true }, _) -> true | _ -> false) -> + () + | _, Method _ -> + display_error ctx "Cannot create closure on super method" p + | _ -> + display_error ctx "Normal variables cannot be accessed with 'super', use 'this' instead" pfield); + if not (can_access ctx c f false) && not ctx.untyped then display_error ctx ("Cannot access private field " ^ i) pfield; + field_access ctx mode f (match c2 with None -> FAnon f | Some (c,tl) -> FInstance (c,tl,f)) (apply_params c.cl_params params t) e p + with Not_found -> try + begin match e.eexpr with + | TConst TSuper -> raise Not_found + | _ -> using_field ctx mode e i p + end + with Not_found -> try + loop_dyn c params + with Not_found -> try + (* if we have an abstract constraint we have to check its static fields and recurse (issue #2343) *) + begin match c.cl_kind with + | KTypeParameter tl -> + let rec loop tl = match tl with + | t :: tl -> + begin match follow t with + | TAbstract({a_impl = Some c},tl) when PMap.mem i c.cl_statics -> + let e = mk_cast e t p in + type_field cfg ctx e i p mode; + | _ -> + loop tl + end + | [] -> + raise Not_found + in + loop tl + | _ -> + raise Not_found + end + with Not_found -> + if PMap.mem i c.cl_statics then error ("Cannot access static field " ^ i ^ " from a class instance") pfield; + no_field()) + | TDynamic t -> + (try + using_field ctx mode e i p + with Not_found -> + AKExpr (mk (TField (e,FDynamic i)) t p)) + | TAnon a -> + (try + let f = PMap.find i a.a_fields in + if Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Enum f.cf_meta) then display_error ctx "Cannot access non-static abstract field statically" pfield; + if not (has_class_field_flag f CfPublic) && not ctx.untyped then begin + match !(a.a_status) with + | Closed | Extend _ -> () (* always allow anon private fields access *) + | Statics c when can_access ctx c f true -> () + | _ -> display_error ctx ("Cannot access private field " ^ i) pfield + end; + let fmode, ft = (match !(a.a_status) with + | Statics c -> FStatic (c,f), field_type ctx c [] f p + | EnumStatics e -> FEnum (e,try PMap.find f.cf_name e.e_constrs with Not_found -> assert false), Type.field_type f + | _ -> + match f.cf_params with + | [] -> + FAnon f, Type.field_type f + | l -> + (* handle possible constraints *) + let monos = List.map (fun _ -> mk_mono()) l in + let t = apply_params f.cf_params monos f.cf_type in + add_constraint_checks ctx [] [] f monos p; + FAnon f, t + ) in + field_access ctx mode f fmode ft e p + with Not_found -> try + match !(a.a_status) with + | Statics {cl_kind = KAbstractImpl a} when does_forward a true -> + let mt = try module_type_of_type a.a_this with Exit -> raise Not_found in + let et = type_module_type ctx mt None p in + type_field cfg ctx et i p mode; + | _ -> + raise Not_found + with Not_found -> + if is_closed a then try + using_field ctx mode e i p + with Not_found -> + no_field() + else + let f = { + (mk_field i (mk_mono()) p null_pos) with + cf_kind = Var { v_read = AccNormal; v_write = (match mode with MSet -> AccNormal | MGet | MCall -> AccNo) }; + } in + a.a_fields <- PMap.add i f a.a_fields; + field_access ctx mode f (FAnon f) (Type.field_type f) e p + ) + | TMono r -> + let f = { + (mk_field i (mk_mono()) p null_pos) with + cf_kind = Var { v_read = AccNormal; v_write = (match mode with MSet -> AccNormal | MGet | MCall -> AccNo) }; + } in + let x = ref Opened in + let t = TAnon { a_fields = PMap.add i f PMap.empty; a_status = x } in + ctx.opened <- x :: ctx.opened; + r := Some t; + field_access ctx mode f (FAnon f) (Type.field_type f) e p + | TAbstract (a,pl) -> + let static_abstract_access_through_instance = ref false in + (try + let c = (match a.a_impl with None -> raise Not_found | Some c -> c) in + let f = PMap.find i c.cl_statics in + if not (can_access ctx c f true) && not ctx.untyped then display_error ctx ("Cannot access private field " ^ i) pfield; + let field_type f = + if not (Meta.has Meta.Impl f.cf_meta) then begin + static_abstract_access_through_instance := true; + raise Not_found; + end; + let t = field_type ctx c [] f p in + apply_params a.a_params pl t + in + let et = type_module_type ctx (TClassDecl c) None p in + let field_expr f t = mk (TField (et,FStatic (c,f))) t p in + (match mode, f.cf_kind with + | (MGet | MCall), Var {v_read = AccCall } -> + (* getter call *) + let getter = PMap.find ("get_" ^ f.cf_name) c.cl_statics in + let t = field_type getter in + let r = match follow t with TFun(_,_) -> field_type f | _ -> raise Not_found in + let ef = field_expr getter t in + AKExpr(make_call ctx ef [e] r p) + | MSet, Var {v_write = AccCall } -> + let f = PMap.find ("set_" ^ f.cf_name) c.cl_statics in + let t = field_type f in + let ef = field_expr f t in + AKUsing (ef,c,f,e,false) + | (MGet | MCall), Var {v_read = AccNever} -> + AKNo f.cf_name + | (MGet | MCall), _ -> + let rec loop cfl = match cfl with + | [] -> error (Printf.sprintf "Field %s cannot be called on %s" f.cf_name (s_type (print_context()) e.etype)) pfield + | cf :: cfl -> + match follow (apply_params a.a_params pl (monomorphs cf.cf_params cf.cf_type)) with + | TFun((_,_,t1) :: _,_) when type_iseq t1 (Abstract.get_underlying_type a pl) -> + cf + | _ -> + loop cfl + in + let f = match f.cf_overloads with + | [] -> f + | cfl -> loop (f :: cfl) + in + let t = field_type f in + begin match follow t with + | TFun((_,_,t1) :: _,_) -> () + | _ -> error ("Invalid call to static function " ^ i ^ " through abstract instance") pfield + end; + let ef = field_expr f t in + AKUsing (ef,c,f,e,false) + | MSet, _ -> + error "This operation is unsupported" p) + with Not_found -> try + if does_forward a false then + let underlying_type = Abstract.get_underlying_type ~return_first:true a pl in + type_field (TypeFieldConfig.with_resume cfg) ctx {e with etype = underlying_type} i p mode + else + raise Not_found + with Not_found -> try + using_field ctx mode e i p + with Not_found -> try + (match ctx.curfun, e.eexpr with + | FunMemberAbstract, TConst (TThis) -> type_field cfg ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode; + | _ -> raise Not_found) + with Not_found -> try + let get_resolve is_write = + let c,cf = match a.a_impl,(if is_write then a.a_write else a.a_read) with + | Some c,Some cf -> c,cf + | _ -> raise Not_found + in + let et = type_module_type ctx (TClassDecl c) None p in + let t = apply_params a.a_params pl (field_type ctx c [] cf p) in + let ef = mk (TField (et,FStatic (c,cf))) t p in + let r = match follow t with + | TFun(_,r) -> r + | _ -> assert false + in + if is_write then + AKFieldSet(e,ef,i,r) + else + AKExpr ((!build_call_ref) ctx (AKUsing(ef,c,cf,e,false)) [EConst (String i),p] NoValue p) + in + if not (TypeFieldConfig.allow_resolve cfg) then raise Not_found; + get_resolve (mode = MSet) + with Not_found -> + if !static_abstract_access_through_instance then error ("Invalid call to static function " ^ i ^ " through abstract instance") pfield + else no_field()) + | _ -> + try using_field ctx mode e i p with Not_found -> no_field() + +let type_field_default_cfg = type_field TypeFieldConfig.default diff --git a/src/typing/finalization.ml b/src/typing/finalization.ml new file mode 100644 index 00000000000..98af5a36a6a --- /dev/null +++ b/src/typing/finalization.ml @@ -0,0 +1,166 @@ +open Globals +open Ast +open Common +open Type +open Error +open TyperBase +open Typecore + +(* ---------------------------------------------------------------------- *) +(* FINALIZATION *) + +let get_main ctx types = + match ctx.com.main_class with + | None -> None + | Some cl -> + let t = Typeload.load_type_def ctx null_pos { tpackage = fst cl; tname = snd cl; tparams = []; tsub = None } in + let fmode, ft, r = (match t with + | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ -> + error ("Invalid -main : " ^ s_type_path cl ^ " is not a class") null_pos + | TClassDecl c -> + try + let f = PMap.find "main" c.cl_statics in + let t = Type.field_type f in + (match follow t with + | TFun ([],r) -> FStatic (c,f), t, r + | _ -> error ("Invalid -main : " ^ s_type_path cl ^ " has invalid main function") c.cl_pos); + with + Not_found -> error ("Invalid -main : " ^ s_type_path cl ^ " does not have static function main") c.cl_pos + ) in + let emain = type_type ctx cl null_pos in + let main = mk (TCall (mk (TField (emain,fmode)) ft null_pos,[])) r null_pos in + (* add haxe.EntryPoint.run() call *) + let main = (try + let et = List.find (fun t -> t_path t = (["haxe"],"EntryPoint")) types in + let ec = (match et with TClassDecl c -> c | _ -> assert false) in + let ef = PMap.find "run" ec.cl_statics in + let p = null_pos in + let et = mk (TTypeExpr et) (TAnon { a_fields = PMap.empty; a_status = ref (Statics ec) }) p in + let call = mk (TCall (mk (TField (et,FStatic (ec,ef))) ef.cf_type p,[])) ctx.t.tvoid p in + mk (TBlock [main;call]) ctx.t.tvoid p + with Not_found -> + main + ) in + Some main + +let finalize ctx = + flush_pass ctx PFinal "final"; + match ctx.com.callbacks#get_after_typing with + | [] -> + () + | fl -> + let rec loop handled_types = + let all_types = Hashtbl.fold (fun _ m acc -> m.m_types @ acc) ctx.g.modules [] in + match (List.filter (fun mt -> not (List.memq mt handled_types)) all_types) with + | [] -> + () + | new_types -> + List.iter (fun f -> f new_types) fl; + flush_pass ctx PFinal "final"; + loop all_types + in + loop [] + +type state = + | Generating + | Done + | NotYet + +let sort_types com modules = + let types = ref [] in + let states = Hashtbl.create 0 in + let state p = try Hashtbl.find states p with Not_found -> NotYet in + let statics = ref PMap.empty in + + let rec loop t = + let p = t_path t in + match state p with + | Done -> () + | Generating -> + com.warning ("Warning : maybe loop in static generation of " ^ s_type_path p) (t_infos t).mt_pos; + | NotYet -> + Hashtbl.add states p Generating; + let t = (match t with + | TClassDecl c -> + walk_class p c; + t + | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ -> + t + ) in + Hashtbl.replace states p Done; + types := t :: !types + + and loop_class p c = + if c.cl_path <> p then loop (TClassDecl c) + + and loop_enum p e = + if e.e_path <> p then loop (TEnumDecl e) + + and loop_abstract p a = + if a.a_path <> p then loop (TAbstractDecl a) + + and walk_static_field p c cf = + match cf.cf_expr with + | None -> () + | Some e -> + if PMap.mem (c.cl_path,cf.cf_name) (!statics) then + () + else begin + statics := PMap.add (c.cl_path,cf.cf_name) () (!statics); + walk_expr p e; + end + + and walk_expr p e = + match e.eexpr with + | TTypeExpr t -> + (match t with + | TClassDecl c -> loop_class p c + | TEnumDecl e -> loop_enum p e + | TAbstractDecl a -> loop_abstract p a + | TTypeDecl _ -> assert false) + | TNew (c,_,_) -> + iter (walk_expr p) e; + loop_class p c; + let rec loop c = + if PMap.mem (c.cl_path,"new") (!statics) then + () + else begin + statics := PMap.add (c.cl_path,"new") () !statics; + (match c.cl_constructor with + | Some { cf_expr = Some e } -> walk_expr p e + | _ -> ()); + match c.cl_super with + | None -> () + | Some (csup,_) -> loop csup + end + in + loop c + | TField(e1,FStatic(c,cf)) -> + walk_expr p e1; + walk_static_field p c cf; + | _ -> + iter (walk_expr p) e + + and walk_class p c = + (match c.cl_super with None -> () | Some (c,_) -> loop_class p c); + List.iter (fun (c,_) -> loop_class p c) c.cl_implements; + (match c.cl_init with + | None -> () + | Some e -> walk_expr p e); + PMap.iter (fun _ f -> + match f.cf_expr with + | None -> () + | Some e -> + match e.eexpr with + | TFunction _ -> () + | _ -> walk_expr p e + ) c.cl_statics + + in + let sorted_modules = List.sort (fun m1 m2 -> compare m1.m_path m2.m_path) (Hashtbl.fold (fun _ m acc -> m :: acc) modules []) in + List.iter (fun m -> List.iter loop m.m_types) sorted_modules; + List.rev !types, sorted_modules + +let generate ctx = + let types,modules = sort_types ctx.com ctx.g.modules in + get_main ctx types,types,modules diff --git a/src/typing/forLoop.ml b/src/typing/forLoop.ml new file mode 100644 index 00000000000..e84b9722f88 --- /dev/null +++ b/src/typing/forLoop.ml @@ -0,0 +1,506 @@ +open Globals +open Ast +open Type +open Common +open Typecore +open TyperBase +open Fields +open Error +open Texpr.Builder + +let optimize_for_loop_iterator ctx v e1 e2 p = + let c,tl = (match follow e1.etype with TInst (c,pl) -> c,pl | _ -> raise Exit) in + let _, _, fhasnext = (try raw_class_field (fun cf -> apply_params c.cl_params tl cf.cf_type) c tl "hasNext" with Not_found -> raise Exit) in + if fhasnext.cf_kind <> Method MethInline then raise Exit; + let tmp = gen_local ctx e1.etype e1.epos in + let eit = mk (TLocal tmp) e1.etype p in + let ehasnext = make_call ctx (mk (TField (eit,FInstance (c, tl, fhasnext))) (TFun([],ctx.t.tbool)) p) [] ctx.t.tbool p in + let enext = mk (TVar (v,Some (make_call ctx (mk (TField (eit,quick_field_dynamic eit.etype "next")) (TFun ([],v.v_type)) p) [] v.v_type p))) ctx.t.tvoid p in + let eblock = (match e2.eexpr with + | TBlock el -> { e2 with eexpr = TBlock (enext :: el) } + | _ -> mk (TBlock [enext;e2]) ctx.t.tvoid p + ) in + mk (TBlock [ + mk (TVar (tmp,Some e1)) ctx.t.tvoid p; + mk (TWhile (ehasnext,eblock,NormalWhile)) ctx.t.tvoid p + ]) ctx.t.tvoid p + +module IterationKind = struct + type t_kind = + | IteratorIntConst of texpr * texpr * bool (* ascending? *) + | IteratorIntUnroll of int * int * bool + | IteratorInt of texpr * texpr + | IteratorArrayDecl of texpr list + | IteratorArray + | IteratorArrayAccess + | IteratorGenericStack of tclass + | IteratorIterator + | IteratorCustom of (texpr -> texpr -> Type.t -> pos -> texpr) * (texpr -> pos -> texpr) + | IteratorAbstract of tvar * texpr * texpr + | IteratorDynamic + + type t = { + it_kind : t_kind; + it_type : Type.t; + it_expr : texpr; + } + + let type_field_config = { + Fields.TypeFieldConfig.do_resume = true; + allow_resolve = false; + } + + let get_next_array_element arr iexpr pt p = + (mk (TArray (arr,iexpr)) pt p) + + let check_iterator ?(resume=false) ?last_resort ctx s e p = + let t,pt = Typeload.t_iterator ctx in + let dynamic_iterator = ref None in + let e1 = try + let e = AbstractCast.cast_or_unify_raise ctx t e p in + match Abstract.follow_with_abstracts e.etype with + | TDynamic _ | TMono _ -> + (* try to find something better than a dynamic value to iterate on *) + dynamic_iterator := Some e; + raise (Error (Unify [Unify_custom "Avoid iterating on a dynamic value"], p)) + | _ -> e + with Error (Unify _,_) -> + let try_last_resort after = + try + match last_resort with + | Some fn -> fn() + | None -> raise Not_found + with Not_found -> + after() + in + let try_acc acc = + let acc_expr = !build_call_ref ctx acc [] WithType.value e.epos in + try + unify_raise ctx acc_expr.etype t acc_expr.epos; + acc_expr + with Error (Unify(l),p) -> + try_last_resort (fun () -> + match !dynamic_iterator with + | Some e -> e + | None -> + if resume then raise Not_found; + display_error ctx "Field iterator has an invalid type" acc_expr.epos; + display_error ctx (error_msg (Unify l)) p; + mk (TConst TNull) t_dynamic p + ) + in + try + let acc = type_field ({do_resume = true;allow_resolve = false}) ctx e s e.epos MCall in + try_acc acc; + with Not_found -> + try_last_resort (fun () -> + match !dynamic_iterator with + | Some e -> e + | None -> + let acc = type_field ({do_resume = resume;allow_resolve = false}) ctx e s e.epos MCall in + try_acc acc + ) + in + e1,pt + + let of_texpr_by_array_access ctx e p = + match follow e.etype with + | TInst({ cl_array_access = Some pt } as c,pl) when (try match follow (PMap.find "length" c.cl_fields).cf_type with TAbstract ({ a_path = [],"Int" },[]) -> true | _ -> false with Not_found -> false) && not (PMap.mem "iterator" c.cl_fields) -> + IteratorArrayAccess,e,apply_params c.cl_params pl pt + | TAbstract({a_impl = Some c} as a,tl) -> + let cf_length = PMap.find "get_length" c.cl_statics in + let get_length e p = + make_static_call ctx c cf_length (apply_params a.a_params tl) [e] ctx.com.basic.tint p + in + (match follow cf_length.cf_type with + | TFun(_,tr) -> + (match follow tr with + | TAbstract({a_path = [],"Int"},_) -> () + | _ -> raise Not_found + ) + | _ -> + raise Not_found + ); + (try + (* first try: do we have an @:arrayAccess getter field? *) + let todo = mk (TConst TNull) ctx.t.tint p in + let cf,_,r,_,_ = AbstractCast.find_array_access_raise ctx a tl todo None p in + let get_next e_base e_index t p = + make_static_call ctx c cf (apply_params a.a_params tl) [e_base;e_index] r p + in + IteratorCustom(get_next,get_length),e,r + with Not_found -> + (* second try: do we have @:arrayAccess on the abstract itself? *) + if not (Meta.has Meta.ArrayAccess a.a_meta) then raise Not_found; + (* let's allow this only for core-type abstracts *) + if not (Meta.has Meta.CoreType a.a_meta) then raise Not_found; + (* in which case we assume that a singular type parameter is the element type *) + let t = match tl with [t] -> t | _ -> raise Not_found in + IteratorCustom(get_next_array_element,get_length),e,t + ) + | _ -> raise Not_found + + let of_texpr ?(resume=false) ctx e unroll p = + let dynamic_iterator e = + display_error ctx "You can't iterate on a Dynamic value, please specify Iterator or Iterable" e.epos; + IteratorDynamic,e,t_dynamic + in + let check_iterator () = + let array_access_result = ref None in + let last_resort () = + array_access_result := Some (of_texpr_by_array_access ctx e p); + mk (TConst TNull) t_dynamic p + in + let e1,pt = check_iterator ~resume ~last_resort ctx "iterator" e p in + match !array_access_result with + | Some result -> result + | None -> + match Abstract.follow_with_abstracts e1.etype with + | (TMono _ | TDynamic _) -> dynamic_iterator e1; + | _ -> (IteratorIterator,e1,pt) + in + let try_forward_array_iterator () = + match follow e.etype with + | TAbstract ({ a_this = (TInst ({ cl_path = [],"Array" }, [_]) as array_type)} as abstr, params) -> + let forwards_iterator = + match Meta.get Meta.Forward abstr.a_meta with + | (_, [], _) -> true + | (_, args, _) -> + List.exists (fun (arg,_) -> match arg with EConst (Ident"iterator") -> true | _ -> false ) args + in + if forwards_iterator then + match apply_params abstr.a_params params array_type with + | TInst({ cl_path = [],"Array" },[pt]) as t -> IteratorArray,(mk_cast e t e.epos),pt + | _ -> raise Not_found + else + raise Not_found + | _ -> raise Not_found + in + let it,e1,pt = match e.eexpr,follow e.etype with + | TNew ({ cl_path = ([],"IntIterator") },[],[efrom;eto]),_ -> + let it = match efrom.eexpr,eto.eexpr with + | TConst (TInt a),TConst (TInt b) -> + let diff = Int32.to_int (Int32.sub a b) in + let unroll = unroll (abs diff) in + if unroll then IteratorIntUnroll(Int32.to_int a,abs(diff),diff <= 0) + else IteratorIntConst(efrom,eto,diff <= 0) + | _ -> + let eto = match follow eto.etype with + | TAbstract ({ a_path = ([],"Int") }, []) -> eto + | _ -> { eto with eexpr = TCast(eto, None); etype = ctx.t.tint } + in + IteratorInt(efrom,eto) + in + it,e,ctx.t.tint + | TArrayDecl el,TInst({ cl_path = [],"Array" },[pt]) -> + let it = if unroll (List.length el) then IteratorArrayDecl el + else IteratorArray in + (it,e,pt) + | _,TInst({ cl_path = [],"Array" },[pt]) + | _,TInst({ cl_path = ["flash"],"Vector" },[pt]) -> + IteratorArray,e,pt + | _,TAbstract({ a_impl = Some c },_) -> + (try + let v_tmp = gen_local ctx e.etype e.epos in + let e_tmp = make_local v_tmp v_tmp.v_pos in + let acc_next = type_field type_field_config ctx e_tmp "next" p MCall in + let acc_hasNext = type_field type_field_config ctx e_tmp "hasNext" p MCall in + (match acc_next, acc_hasNext with + | AKExpr({ eexpr = TField(_, FDynamic _)}), _ + | _, AKExpr({ eexpr = TField(_, FDynamic _)}) -> raise Not_found + | _ -> () + ); + let e_next = !build_call_ref ctx acc_next [] WithType.value e.epos in + let e_hasNext = !build_call_ref ctx acc_hasNext [] WithType.value e.epos in + IteratorAbstract(v_tmp,e_next,e_hasNext),e,e_next.etype + with Not_found -> + (try try_forward_array_iterator () + with Not_found -> check_iterator ()) + ) + | _, TAbstract _ -> + (try try_forward_array_iterator () + with Not_found -> check_iterator ()) + | _,TInst ({ cl_kind = KGenericInstance ({ cl_path = ["haxe";"ds"],"GenericStack" },[pt]) } as c,[]) -> + IteratorGenericStack c,e,pt + | _,(TMono _ | TDynamic _) -> + dynamic_iterator e + | _ -> + check_iterator () + in + { + it_kind = it; + it_type = pt; + it_expr = e1; + } + + let to_texpr ctx v iterator e2 p = + let e1,pt = iterator.it_expr,iterator.it_type in + let t_void = ctx.t.tvoid in + let t_int = ctx.t.tint in + let mk_field e n = + TField (e,try quick_field e.etype n with Not_found -> assert false) + in + let get_array_length arr p = + mk (mk_field arr "length") ctx.com.basic.tint p + in + let check_loop_var_modification vl e = + let rec loop e = + match e.eexpr with + | TBinop (OpAssign,{ eexpr = TLocal l },_) + | TBinop (OpAssignOp _,{ eexpr = TLocal l },_) + | TUnop (Increment,_,{ eexpr = TLocal l }) + | TUnop (Decrement,_,{ eexpr = TLocal l }) when List.memq l vl -> + error "Loop variable cannot be modified" e.epos + | _ -> + Type.iter loop e + in + loop e + in + let gen_int_iter e1 pt f_get f_length = + let index = gen_local ctx t_int v.v_pos in + index.v_meta <- (Meta.ForLoopVariable,[],null_pos) :: index.v_meta; + let arr, avars = (match e1.eexpr with + | TLocal _ -> e1, None + | _ -> + let atmp = gen_local ctx e1.etype e1.epos in + mk (TLocal atmp) e1.etype e1.epos, (Some (atmp,Some e1)) + ) in + let iexpr = mk (TLocal index) t_int p in + let aget = mk (TVar (v,Some (f_get arr iexpr pt p))) t_void v.v_pos in + let incr = mk (TUnop (Increment,Prefix,iexpr)) t_int p in + let block = match e2.eexpr with + | TBlock el -> mk (TBlock (aget :: incr :: el)) t_void e2.epos + | _ -> mk (TBlock [aget;incr;e2]) t_void p + in + let ivar = Some (mk (TConst (TInt 0l)) t_int p) in + let elength = f_length arr p in + let el = [mk (TWhile ( + mk (TBinop (OpLt, iexpr, elength)) ctx.t.tbool p, + block, + NormalWhile + )) t_void p; + ] in + let el = match avars with None -> el | Some (v,eo) -> (mk (TVar (v,eo)) t_void p) :: el in + let el = (mk (TVar (index,ivar)) t_void p) :: el in + mk (TBlock el) t_void p + in + match iterator.it_kind with + | IteratorIntUnroll(offset,length,ascending) -> + check_loop_var_modification [v] e2; + if not ascending then error "Cannot iterate backwards" p; + let el = ExtList.List.init length (fun i -> + let ei = make_int ctx.t (if ascending then i + offset else offset - i) p in + let rec loop e = match e.eexpr with + | TLocal v' when v == v' -> {ei with epos = e.epos} + | _ -> map_expr loop e + in + let e2 = loop e2 in + Texpr.duplicate_tvars e2 + ) in + mk (TBlock el) t_void p + | IteratorIntConst(a,b,ascending) -> + check_loop_var_modification [v] e2; + if not ascending then error "Cannot iterate backwards" p; + let v_index = gen_local ctx t_int p in + let evar_index = mk (TVar(v_index,Some a)) t_void p in + let ev_index = make_local v_index p in + let op1,op2 = if ascending then (OpLt,Increment) else (OpGt,Decrement) in + let econd = binop op1 ev_index b ctx.t.tbool p in + let ev_incr = mk (TUnop(op2,Postfix,ev_index)) t_int p in + let evar = mk (TVar(v,Some ev_incr)) t_void p in + let e2 = concat evar e2 in + let ewhile = mk (TWhile(econd,e2,NormalWhile)) t_void p in + mk (TBlock [ + evar_index; + ewhile; + ]) t_void p + | IteratorInt(a,b) -> + check_loop_var_modification [v] e2; + let v_index = gen_local ctx t_int p in + let evar_index = mk (TVar(v_index,Some a)) t_void p in + let ev_index = make_local v_index p in + let v_b = gen_local ctx b.etype b.epos in + let evar_b = mk (TVar (v_b,Some b)) t_void p in + let ev_b = make_local v_b b.epos in + let econd = binop OpLt ev_index ev_b ctx.t.tbool p in + let ev_incr = mk (TUnop(Increment,Postfix,ev_index)) t_int p in + let evar = mk (TVar(v,Some ev_incr)) t_void p in + let e2 = concat evar e2 in + let ewhile = mk (TWhile(econd,e2,NormalWhile)) t_void p in + mk (TBlock [ + evar_index; + evar_b; + ewhile; + ]) t_void p + | IteratorArrayDecl el -> + let el = List.map (fun e -> + let ev = mk (TVar(v,Some e)) t_void e.epos in + let e = concat ev e2 in + Texpr.duplicate_tvars e + ) el in + mk (TBlock el) t_void p + | IteratorArray | IteratorArrayAccess -> + gen_int_iter e1 pt get_next_array_element get_array_length + | IteratorCustom(f_next,f_length) -> + gen_int_iter e1 pt f_next f_length + | IteratorIterator -> + begin try optimize_for_loop_iterator ctx v e1 e2 p + with Exit -> mk (TFor(v,e1,e2)) t_void p end + | IteratorGenericStack c -> + let tcell = (try (PMap.find "head" c.cl_fields).cf_type with Not_found -> assert false) in + let cell = gen_local ctx tcell p in + let cexpr = mk (TLocal cell) tcell p in + let evar = mk (TVar (v,Some (mk (mk_field cexpr "elt") pt p))) t_void v.v_pos in + let enext = mk (TBinop (OpAssign,cexpr,mk (mk_field cexpr "next") tcell p)) tcell p in + let block = match e2.eexpr with + | TBlock el -> mk (TBlock (evar :: enext :: el)) t_void e2.epos + | _ -> mk (TBlock [evar;enext;e2]) t_void p + in + mk (TBlock [ + mk (TVar (cell,Some (mk (mk_field e1 "head") tcell p))) t_void p; + mk (TWhile ( + mk (TBinop (OpNotEq, cexpr, mk (TConst TNull) tcell p)) ctx.t.tbool p, + block, + NormalWhile + )) t_void p + ]) t_void p + | IteratorAbstract(v_tmp,e_next,e_hasNext) -> + let evar = mk (TVar(v,Some e_next)) t_void p in + let e2 = concat evar e2 in + let ewhile = mk (TWhile(e_hasNext,e2,NormalWhile)) t_void p in + mk (TBlock [ + mk (TVar(v_tmp,Some e1)) t_void p; + ewhile; + ]) t_void p + | IteratorDynamic -> + mk (TFor(v,e1,e2)) t_void p +end + +let is_cheap_enough ctx e2 i = + let num_expr = ref 0 in + let rec loop e = match fst e with + | EContinue | EBreak -> + raise Exit + | _ -> + incr num_expr; + Ast.map_expr loop e + in + try + if ctx.com.display.dms_kind <> DMNone then raise Exit; + ignore(loop e2); + let cost = i * !num_expr in + let max_cost = try + int_of_string (Common.defined_value ctx.com Define.LoopUnrollMaxCost) + with Not_found -> + 250 + in + cost <= max_cost + with Exit -> + false + +let is_cheap_enough_t ctx e2 i = + let num_expr = ref 0 in + let rec loop e = match e.eexpr with + | TContinue | TBreak -> + raise Exit + | _ -> + incr num_expr; + Type.map_expr loop e + in + try + if ctx.com.display.dms_kind <> DMNone then raise Exit; + ignore(loop e2); + let cost = i * !num_expr in + let max_cost = try + int_of_string (Common.defined_value ctx.com Define.LoopUnrollMaxCost) + with Not_found -> + 250 + in + cost <= max_cost + with Exit -> + false + +type iteration_ident = string * pos * display_kind option + +type iteration_kind = + | IKNormal of iteration_ident + | IKKeyValue of iteration_ident * iteration_ident + +let type_for_loop ctx handle_display it e2 p = + let rec loop_ident dko e1 = match e1 with + | EConst(Ident i),p -> i,p,dko + | EDisplay(e1,dk),_ -> loop_ident (Some dk) e1 + | _ -> error "Identifier expected" (pos e1) + in + let rec loop dko e1 = match fst e1 with + | EBinop(OpIn,e1,e2) -> + begin match fst e1 with + | EBinop(OpArrow,ei1,ei2) -> IKKeyValue(loop_ident None ei1,loop_ident None ei2),e2 + | _ -> IKNormal (loop_ident dko e1),e2 + end + | EDisplay(e1,dk) -> loop (Some dk) e1 + | EBinop(OpArrow,ei1,(EBinop(OpIn,ei2,e2),_)) -> IKKeyValue(loop_ident None ei1,loop_ident None ei2),e2 + | _ -> + begin match dko with + | Some dk -> ignore(handle_display ctx e1 dk WithType.value); + | None -> () + end; + error "For expression should be 'v in expr'" (snd it) + in + let ik,e1 = loop None it in + let e1 = type_expr ctx e1 WithType.value in + let old_loop = ctx.in_loop in + let old_locals = save_locals ctx in + ctx.in_loop <- true; + let e2 = Expr.ensure_block e2 in + let check_display (i,pi,dko) = match dko with + | None -> () + | Some dk -> ignore(handle_display ctx (EConst(Ident i.v_name),i.v_pos) dk (WithType.with_type i.v_type)) + in + match ik with + | IKNormal(i,pi,dko) -> + let iterator = IterationKind.of_texpr ctx e1 (is_cheap_enough ctx e2) p in + let i = add_local_with_origin ctx TVOForVariable i iterator.it_type pi in + let e2 = type_expr ctx e2 NoValue in + check_display (i,pi,dko); + ctx.in_loop <- old_loop; + old_locals(); + begin try + IterationKind.to_texpr ctx i iterator e2 p + with Exit -> + mk (TFor (i,iterator.it_expr,e2)) ctx.t.tvoid p + end + | IKKeyValue((ikey,pkey,dkokey),(ivalue,pvalue,dkovalue)) -> + let e1,pt = IterationKind.check_iterator ctx "keyValueIterator" e1 e1.epos in + begin match follow e1.etype with + | TDynamic _ | TMono _ -> display_error ctx "You can't iterate on a Dynamic value, please specify KeyValueIterator or KeyValueIterable" e1.epos; + | _ -> () + end; + let vtmp = gen_local ctx e1.etype e1.epos in + let etmp = make_local vtmp vtmp.v_pos in + let ehasnext = !build_call_ref ctx (type_field_default_cfg ctx etmp "hasNext" etmp.epos MCall) [] WithType.value etmp.epos in + let enext = !build_call_ref ctx (type_field_default_cfg ctx etmp "next" etmp.epos MCall) [] WithType.value etmp.epos in + let v = gen_local ctx pt e1.epos in + let ev = make_local v v.v_pos in + let ekey = Calls.acc_get ctx (type_field_default_cfg ctx ev "key" ev.epos MGet) ev.epos in + let evalue = Calls.acc_get ctx (type_field_default_cfg ctx ev "value" ev.epos MGet) ev.epos in + let vkey = add_local_with_origin ctx TVOForVariable ikey ekey.etype pkey in + let vvalue = add_local_with_origin ctx TVOForVariable ivalue evalue.etype pvalue in + let e2 = type_expr ctx e2 NoValue in + check_display (vkey,pkey,dkokey); + check_display (vvalue,pvalue,dkovalue); + let ebody = mk (TBlock [ + mk (TVar(v,Some enext)) ctx.t.tvoid enext.epos; + mk (TVar(vkey,Some ekey)) ctx.t.tvoid ekey.epos; + mk (TVar(vvalue,Some evalue)) ctx.t.tvoid evalue.epos; + e2; + ]) ctx.t.tvoid e2.epos in + let e = mk (TBlock [ + mk (TVar(vtmp,Some e1)) ctx.t.tvoid e1.epos; + mk (TWhile(ehasnext,ebody,NormalWhile)) ctx.t.tvoid p; + ]) ctx.t.tvoid p in + ctx.in_loop <- old_loop; + old_locals(); + e + + diff --git a/src/typing/generic.ml b/src/typing/generic.ml new file mode 100644 index 00000000000..c9be52da93e --- /dev/null +++ b/src/typing/generic.ml @@ -0,0 +1,309 @@ +open Globals +open DisplayTypes.DisplayMode +open Common +open Ast +open Type +open Typecore +open Error + +exception Generic_Exception of string * pos + +type generic_context = { + ctx : typer; + subst : (t * (t * texpr option)) list; + name : string; + p : pos; + mutable mg : module_def option; +} + +let generic_check_const_expr ctx t = + match follow t with + | TInst({cl_kind = KExpr e},_) -> + let e = type_expr {ctx with locals = PMap.empty} e WithType.value in + e.etype,Some e + | _ -> t,None + +let make_generic ctx ps pt p = + let rec loop l1 l2 = + match l1, l2 with + | [] , [] -> [] + | (x,TLazy f) :: l1, _ -> loop ((x,lazy_type f) :: l1) l2 + | (_,t1) :: l1 , t2 :: l2 -> + let t,eo = generic_check_const_expr ctx t2 in + (t1,(t,eo)) :: loop l1 l2 + | _ -> assert false + in + let name = + String.concat "_" (List.map2 (fun (s,_) t -> + let rec subst s = "_" ^ string_of_int (Char.code (String.get (Str.matched_string s) 0)) ^ "_" in + let ident_safe = Str.global_substitute (Str.regexp "[^a-zA-Z0-9_]") subst in + let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in + let rec loop top t = match follow t with + | TInst(c,tl) -> (match c.cl_kind with + | KExpr e -> ident_safe (Ast.Printer.s_expr e) + | _ -> (ident_safe (s_type_path_underscore c.cl_path)) ^ (loop_tl tl)) + | TEnum(en,tl) -> (s_type_path_underscore en.e_path) ^ (loop_tl tl) + | TAnon(a) -> "anon_" ^ String.concat "_" (PMap.foldi (fun s f acc -> (s ^ "_" ^ (loop false (follow f.cf_type))) :: acc) a.a_fields []) + | TFun(args, return_type) -> "func_" ^ (String.concat "_" (List.map (fun (_, _, t) -> loop false t) args)) ^ "_" ^ (loop false return_type) + | TAbstract(a,tl) -> (s_type_path_underscore a.a_path) ^ (loop_tl tl) + | _ when not top -> "_" (* allow unknown/incompatible types as type parameters to retain old behavior *) + | TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p)) + | TDynamic _ -> "Dynamic" + | t -> raise (Generic_Exception (("Unsupported type parameter: " ^ (s_type (print_context()) t) ^ ")"), p)) + and loop_tl tl = match tl with + | [] -> "" + | tl -> "_" ^ String.concat "_" (List.map (loop false) tl) + in + loop true t + ) ps pt) + in + { + ctx = ctx; + subst = loop ps pt; + name = name; + p = p; + mg = None; + } + +let rec generic_substitute_type gctx t = + match t with + | TInst ({ cl_kind = KGeneric } as c2,tl2) -> + (* maybe loop, or generate cascading generics *) + let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in + let t = f (List.map (generic_substitute_type gctx) tl2) in + (match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ()); + t + | _ -> + try + let t,_ = List.assq t gctx.subst in + generic_substitute_type gctx t + with Not_found -> + Type.map (generic_substitute_type gctx) t + +let generic_substitute_expr gctx e = + let vars = Hashtbl.create 0 in + let build_var v = + try + Hashtbl.find vars v.v_id + with Not_found -> + let v2 = alloc_var v.v_kind v.v_name (generic_substitute_type gctx v.v_type) v.v_pos in + v2.v_meta <- v.v_meta; + Hashtbl.add vars v.v_id v2; + v2 + in + let rec build_expr e = + match e.eexpr with + | TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) -> + let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c) gctx.p in + let t = f (List.map (generic_substitute_type gctx) tl) in + begin match follow t with + | TInst(c',_) when c == c' -> + (* The @:generic class wasn't expanded, let's not recurse to avoid infinite loop (#6430) *) + map_expr_type build_expr (generic_substitute_type gctx) build_var e + | _ -> + let fa = try + quick_field t cf.cf_name + with Not_found -> + error (Printf.sprintf "Type %s has no field %s (possible typing order issue)" (s_type (print_context()) t) cf.cf_name) e.epos + in + build_expr {e with eexpr = TField(e1,fa)} + end; + | TTypeExpr (TClassDecl ({cl_kind = KTypeParameter _;} as c)) when Meta.has Meta.Const c.cl_meta -> + let rec loop subst = match subst with + | (t1,(_,eo)) :: subst -> + begin match follow t1 with + | TInst(c2,_) when c == c2 -> eo + | _ -> loop subst + end + | [] -> raise Not_found + in + begin try + let eo = loop gctx.subst in + begin match eo with + | Some e -> e + | None -> error "Only Const type parameters can be used as value" e.epos + end + with Not_found -> + e + end + | _ -> + map_expr_type build_expr (generic_substitute_type gctx) build_var e + in + build_expr e + +let get_short_name = + let i = ref (-1) in + (fun () -> + incr i; + Printf.sprintf "Hx___short___hx_type_%i" !i + ) + +let rec build_generic ctx c p tl = + let pack = fst c.cl_path in + let recurse = ref false in + let rec check_recursive t = + match follow t with + | TInst (c2,tl) -> + (match c2.cl_kind with + | KTypeParameter tl -> + if not (TypeloadCheck.is_generic_parameter ctx c2) && has_ctor_constraint c2 then + error "Type parameters with a constructor cannot be used non-generically" p; + recurse := true + | _ -> ()); + List.iter check_recursive tl; + | _ -> + () + in + List.iter check_recursive tl; + if !recurse || not (ctx.com.display.dms_full_typing) then begin + TInst (c,tl) (* build a normal instance *) + end else begin + let gctx = make_generic ctx c.cl_params tl p in + let name = (snd c.cl_path) ^ "_" ^ gctx.name in + try + let t = Typeload.load_instance ctx ({ tpackage = pack; tname = name; tparams = []; tsub = None },p) false in + match t with + | TInst({ cl_kind = KGenericInstance (csup,_) },_) when c == csup -> t + | _ -> error ("Cannot specialize @:generic because the generated type name is already used: " ^ name) p + with Error(Module_not_found path,_) when path = (pack,name) -> + let m = (try Hashtbl.find ctx.g.modules (Hashtbl.find ctx.g.types_module c.cl_path) with Not_found -> assert false) in + (* let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in *) + ignore(c.cl_build()); (* make sure the super class is already setup *) + let mg = { + m_id = alloc_mid(); + m_path = (pack,name); + m_types = []; + m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake m.m_extra.m_check_policy; + } in + gctx.mg <- Some mg; + let cg = mk_class mg (pack,name) c.cl_pos null_pos in + mg.m_types <- [TClassDecl cg]; + Hashtbl.add ctx.g.modules mg.m_path mg; + add_dependency mg m; + add_dependency ctx.m.curmod mg; + (* ensure that type parameters are set in dependencies *) + let dep_stack = ref [] in + let rec loop t = + if not (List.memq t !dep_stack) then begin + dep_stack := t :: !dep_stack; + match t with + | TInst (c,tl) -> add_dep c.cl_module tl + | TEnum (e,tl) -> add_dep e.e_module tl + | TType (t,tl) -> add_dep t.t_module tl + | TAbstract (a,tl) -> add_dep a.a_module tl + | TMono r -> + (match !r with + | None -> () + | Some t -> loop t) + | TLazy f -> + loop (lazy_type f); + | TDynamic t2 -> + if t == t2 then () else loop t2 + | TAnon a -> + PMap.iter (fun _ f -> loop f.cf_type) a.a_fields + | TFun (args,ret) -> + List.iter (fun (_,_,t) -> loop t) args; + loop ret + end + and add_dep m tl = + add_dependency mg m; + List.iter loop tl + in + List.iter loop tl; + let build_field cf_old = + (* We have to clone the type parameters (issue #4672). We cannot substitute the constraints immediately because + we need the full substitution list first. *) + let param_subst,params = List.fold_left (fun (subst,params) (s,t) -> match follow t with + | TInst(c,tl) as t -> + let t2 = TInst({c with cl_module = mg;},tl) in + (t,(t2,None)) :: subst,(s,t2) :: params + | _ -> assert false + ) ([],[]) cf_old.cf_params in + let gctx = {gctx with subst = param_subst @ gctx.subst} in + let cf_new = {cf_old with cf_pos = cf_old.cf_pos} in (* copy *) + (* Type parameter constraints are substituted here. *) + cf_new.cf_params <- List.rev_map (fun (s,t) -> match follow t with + | TInst({cl_kind = KTypeParameter tl1} as c,_) -> + let tl1 = List.map (generic_substitute_type gctx) tl1 in + c.cl_kind <- KTypeParameter tl1; + s,t + | _ -> assert false + ) params; + let f () = + let t = generic_substitute_type gctx cf_old.cf_type in + ignore (follow t); + begin try (match cf_old.cf_expr with + | None -> + begin match cf_old.cf_kind with + | Method _ when not c.cl_interface && not c.cl_extern -> + display_error ctx (Printf.sprintf "Field %s has no expression (possible typing order issue)" cf_new.cf_name) cf_new.cf_pos; + display_error ctx (Printf.sprintf "While building %s" (s_type_path cg.cl_path)) p; + | _ -> + () + end + | Some e -> + cf_new.cf_expr <- Some (generic_substitute_expr gctx e) + ) with Unify_error l -> + error (error_msg (Unify l)) cf_new.cf_pos + end; + t + in + let r = exc_protect ctx (fun r -> + let t = mk_mono() in + r := lazy_processing (fun() -> t); + let t0 = f() in + unify_raise ctx t0 t p; + link_dynamic t0 t; + t + ) "build_generic" in + cf_new.cf_type <- TLazy r; + cf_new + in + if c.cl_init <> None then error "This class can't be generic" p; + List.iter (fun cf -> match cf.cf_kind with + | Method MethMacro when not ctx.in_macro -> () + | _ -> error "A generic class can't have static fields" cf.cf_pos + ) c.cl_ordered_statics; + cg.cl_super <- (match c.cl_super with + | None -> None + | Some (cs,pl) -> + let ts = follow (apply_params c.cl_params tl (TInst(cs,pl))) in + let cs,pl = TypeloadCheck.Inheritance.check_extends ctx c ts p in + match cs.cl_kind with + | KGeneric -> + (match build_generic ctx cs p pl with + | TInst (cs,pl) -> Some (cs,pl) + | _ -> assert false) + | _ -> Some(cs,pl) + ); + TypeloadFunction.add_constructor ctx cg false p; + cg.cl_kind <- KGenericInstance (c,tl); + cg.cl_meta <- (Meta.NoDoc,[],null_pos) :: cg.cl_meta; + if has_meta Meta.Keep c.cl_meta then cg.cl_meta <- (Meta.Keep,[],null_pos) :: cg.cl_meta; + cg.cl_interface <- c.cl_interface; + cg.cl_constructor <- (match cg.cl_constructor, c.cl_constructor, c.cl_super with + | _, Some cf, _ -> Some (build_field cf) + | Some ctor, _, _ -> Some ctor + | None, None, None -> None + | _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos + ); + cg.cl_implements <- List.map (fun (i,tl) -> + (match follow (generic_substitute_type gctx (TInst (i, List.map (generic_substitute_type gctx) tl))) with + | TInst (i,tl) -> i, tl + | _ -> assert false) + ) c.cl_implements; + cg.cl_ordered_fields <- List.map (fun f -> + let f = build_field f in + cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields; + f + ) c.cl_ordered_fields; + cg.cl_overrides <- List.map (fun f -> + try PMap.find f.cf_name cg.cl_fields with Not_found -> assert false + ) c.cl_overrides; + (* In rare cases the class name can become too long, so let's shorten it (issue #3090). *) + if String.length (snd cg.cl_path) > 254 then begin + let n = get_short_name () in + cg.cl_meta <- (Meta.Native,[EConst(String (n)),p],null_pos) :: cg.cl_meta; + end; + TInst (cg,[]) + end diff --git a/src/typing/instanceBuilder.ml b/src/typing/instanceBuilder.ml new file mode 100644 index 00000000000..a999fdc130b --- /dev/null +++ b/src/typing/instanceBuilder.ml @@ -0,0 +1,103 @@ +open Globals +open Ast +open Typecore +open Type +open Error + +let get_macro_path ctx e args p = + let rec loop e = + match fst e with + | EField (e,f) -> f :: loop e + | EConst (Ident i) -> [i] + | _ -> error "Invalid macro call" p + in + let path = match e with + | (EConst(Ident i)),_ -> + let path = try + if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found; + ctx.curclass.cl_path + with Not_found -> try + (t_infos (let path,_,_ = PMap.find i ctx.m.module_globals in path)).mt_path + with Not_found -> + error "Invalid macro call" p + in + i :: (snd path) :: (fst path) + | _ -> + loop e + in + (match path with + | meth :: cl :: path -> (List.rev path,cl), meth, args + | _ -> error "Invalid macro call" p) + +let build_macro_type ctx pl p = + let path, field, args = (match pl with + | [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)] + | [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] -> + get_macro_path ctx e args p + | _ -> + error "MacroType requires a single expression call parameter" p + ) in + let old = ctx.ret in + let t = (match ctx.g.do_macro ctx MMacroType path field args p with + | None -> mk_mono() + | Some _ -> ctx.ret + ) in + ctx.ret <- old; + t + +let build_macro_build ctx c pl cfl p = + let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with + | _,[ECall(e,args),_],_ -> get_macro_path ctx e args p + | _ -> error "genericBuild requires a single expression call parameter" p + in + let old = ctx.ret,ctx.get_build_infos in + ctx.get_build_infos <- (fun() -> Some (TClassDecl c, pl, cfl)); + let t = (match ctx.g.do_macro ctx MMacroType path field args p with + | None -> mk_mono() + | Some _ -> ctx.ret + ) in + ctx.ret <- fst old; + ctx.get_build_infos <- snd old; + t + +(* -------------------------------------------------------------------------- *) +(* API EVENTS *) + +let build_instance ctx mtype p = + match mtype with + | TClassDecl c -> + if ctx.pass > PBuildClass then ignore(c.cl_build()); + let build f s = + let r = exc_protect ctx (fun r -> + let t = mk_mono() in + r := lazy_processing (fun() -> t); + let tf = (f()) in + unify_raise ctx tf t p; + link_dynamic t tf; + (match tf with + | TInst (c, _) -> ignore(c.cl_build()) + | TAbstract (a, _) -> Abstract.build_abstract a + | _ -> () + ); + t + ) s in + TLazy r + in + let ft = (fun pl -> + match c.cl_kind with + | KGeneric -> + build (fun () -> Generic.build_generic ctx c p pl) "build_generic" + | KMacroType -> + build (fun () -> build_macro_type ctx pl p) "macro_type" + | KGenericBuild cfl -> + build (fun () -> build_macro_build ctx c pl cfl p) "generic_build" + | _ -> + TInst (c,pl) + ) in + c.cl_params , c.cl_path , ft + | TEnumDecl e -> + e.e_params , e.e_path , (fun t -> TEnum (e,t)) + | TTypeDecl t -> + t.t_params , t.t_path , (fun tl -> TType(t,tl)) + | TAbstractDecl a -> + a.a_params, a.a_path, (fun tl -> TAbstract(a,tl)) diff --git a/src/typing/macroContext.ml b/src/typing/macroContext.ml index 5ef00d3a642..387470d9d6f 100644 --- a/src/typing/macroContext.ml +++ b/src/typing/macroContext.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,7 +18,7 @@ *) open Ast -open Common.DisplayMode +open DisplayTypes.DisplayMode open Common open Type open Typecore @@ -43,12 +43,17 @@ end let macro_enable_cache = ref false let macro_interp_cache = ref None -let macro_interp_on_reuse = ref [] -let macro_interp_reused = ref false -let delayed_macro_result = ref ((fun() -> assert false) : unit -> unit -> Interp.value) -let unify_call_args_ref = ref (fun _ _ _ _ _ _ _-> assert false) -let unify_call_args a b c d e f g : (texpr list * t) = !unify_call_args_ref a b c d e f g +let safe_decode v expected t p f = + try + f () + with MacroApi.Invalid_expr | EvalContext.RunTimeException _ -> + let path = ["dump";"decoding_error"] in + let ch = Path.create_file false ".txt" [] path in + let errors = Interp.handle_decoding_error (output_string ch) v t in + List.iter (fun (s,i) -> Printf.fprintf ch "\nline %i: %s" i s) (List.rev errors); + close_out ch; + error (Printf.sprintf "Expected %s but got %s (see %s.txt for details)" expected (Interp.value_string v) (String.concat "/" path)) p let get_next_stored_typed_expr_id = let uid = ref 0 in @@ -82,10 +87,10 @@ let get_type_patch ctx t sub = tp let macro_timer ctx l = - Common.timer (if Common.defined ctx.com Define.MacroTimes then ("macro" :: l) else ["macro"]) + Timer.timer (if Common.defined ctx.com Define.MacroTimes then ("macro" :: l) else ["macro"]) let typing_timer ctx need_type f = - let t = Common.timer ["typing"] in + let t = Timer.timer ["typing"] in let old = ctx.com.error and oldp = ctx.pass and oldlocals = ctx.locals in (* disable resumable errors... unless we are in display mode (we want to reach point of completion) @@ -120,7 +125,26 @@ let load_macro_ref : (typer -> bool -> path -> string -> pos -> (typer * ((strin let make_macro_api ctx p = let parse_expr_string s p inl = - typing_timer ctx false (fun() -> try ParserEntry.parse_expr_string ctx.com.defines s p error inl with Exit -> raise MacroApi.Invalid_expr) + typing_timer ctx false (fun() -> + try + begin match ParserEntry.parse_expr_string ctx.com.defines s p error inl with + | ParseSuccess data -> data + | ParseDisplayFile(data,_) when inl -> data (* ignore errors when inline-parsing in display file *) + | ParseDisplayFile _ -> assert false (* cannot happen because ParserEntry.parse_string sets `display_position := null_pos;` *) + | ParseError _ -> raise MacroApi.Invalid_expr + end + with Exit -> + raise MacroApi.Invalid_expr) + in + let parse_metadata s p = + try + match ParserEntry.parse_string ctx.com.defines (s ^ " typedef T = T") null_pos error false with + | ParseSuccess(_,[ETypedef t,_]) -> t.d_meta + | ParseDisplayFile _ -> assert false (* cannot happen because null_pos is used *) + | ParseError(_,_,_) -> error "Malformed metadata string" p + | _ -> assert false + with _ -> + error "Malformed metadata string" p in { MacroApi.pos = p; @@ -135,59 +159,59 @@ let make_macro_api ctx p = { tpackage = fst path; tname = snd path; tparams = []; tsub = None } in try - let m = Some (Typeload.load_instance ctx (tp,null_pos) true p) in + let m = Some (Typeload.load_instance ctx (tp,p) true) in m with Error (Module_not_found _,p2) when p == p2 -> None ) ); MacroApi.resolve_type = (fun t p -> - typing_timer ctx false (fun() -> Typeload.load_complex_type ctx false p (t,null_pos)) + typing_timer ctx false (fun() -> Typeload.load_complex_type ctx false (t,p)) ); MacroApi.get_module = (fun s -> typing_timer ctx false (fun() -> let path = parse_path s in - let m = List.map type_of_module_type (Typeload.load_module ctx path p).m_types in + let m = List.map type_of_module_type (TypeloadModule.load_module ctx path p).m_types in m ) ); MacroApi.after_typing = (fun f -> - Common.add_typing_filter ctx.com (fun tl -> + ctx.com.callbacks#add_after_typing (fun tl -> let t = macro_timer ctx ["afterTyping"] in f tl; t() ) ); - MacroApi.on_generate = (fun f -> - Common.add_filter ctx.com (fun() -> + MacroApi.on_generate = (fun f b -> + (if b then ctx.com.callbacks#add_before_save else ctx.com.callbacks#add_after_save) (fun() -> let t = macro_timer ctx ["onGenerate"] in f (List.map type_of_module_type ctx.com.types); t() ) ); MacroApi.after_generate = (fun f -> - Common.add_final_filter ctx.com (fun() -> + ctx.com.callbacks#add_after_generation (fun() -> let t = macro_timer ctx ["afterGenerate"] in f(); t() ) ); MacroApi.on_type_not_found = (fun f -> - ctx.com.load_extern_type <- ctx.com.load_extern_type @ [fun path p -> + ctx.com.load_extern_type <- ctx.com.load_extern_type @ ["onTypeNotFound",fun path p -> let td = f (s_type_path path) in if td = Interp.vnull then None else let (pack,name),tdef,p = Interp.decode_type_def td in - Some (name,(pack,[tdef,p])) + Some (pack,[tdef,p]) ]; ); MacroApi.parse_string = parse_expr_string; MacroApi.type_expr = (fun e -> - typing_timer ctx true (fun() -> type_expr ctx e Value) + typing_timer ctx true (fun() -> type_expr ctx e WithType.value) ); MacroApi.type_macro_expr = (fun e -> - let e = typing_timer ctx true (fun() -> type_expr ctx e Value) in + let e = typing_timer ctx true (fun() -> type_expr ctx e WithType.value) in let rec loop e = match e.eexpr with | TField(_,FStatic(c,({cf_kind = Method _} as cf))) -> ignore(!load_macro_ref ctx false c.cl_path cf.cf_name e.epos) | _ -> Type.iter loop e @@ -210,7 +234,9 @@ let make_macro_api ctx p = typing_timer ctx false (fun() -> let v = (match v with None -> None | Some s -> match ParserEntry.parse_string ctx.com.defines ("typedef T = " ^ s) null_pos error false with - | _,[ETypedef { d_data = ct },_] -> Some ct + | ParseSuccess(_,[ETypedef { d_data = ct },_]) -> Some ct + | ParseDisplayFile _ -> assert false (* cannot happen because null_pos is used *) + | ParseError(_,(msg,p),_) -> Parser.error msg p (* p is null_pos, but we don't have anything else here... *) | _ -> assert false ) in let tp = get_type_patch ctx t (Some (f,s)) in @@ -219,17 +245,14 @@ let make_macro_api ctx p = | Some _ -> tp.tp_type <- Option.map fst v ); ); - MacroApi.meta_patch = (fun m t f s -> - let m = (match ParserEntry.parse_string ctx.com.defines (m ^ " typedef T = T") null_pos error false with - | _,[ETypedef t,_] -> t.d_meta - | _ -> assert false - ) in + MacroApi.meta_patch = (fun m t f s p -> + let ml = parse_metadata m p in let tp = get_type_patch ctx t (match f with None -> None | Some f -> Some (f,s)) in - tp.tp_meta <- tp.tp_meta @ m; + tp.tp_meta <- tp.tp_meta @ (List.map (fun (m,el,_) -> (m,el,p)) ml); ); MacroApi.set_js_generator = (fun gen -> - Common.mkdir_from_path ctx.com.file; - let js_ctx = Genjs.alloc_ctx ctx.com in + Path.mkdir_from_path ctx.com.file; + let js_ctx = Genjs.alloc_ctx ctx.com (get_es_version ctx.com) in ctx.com.js_gen <- Some (fun() -> let t = macro_timer ctx ["jsGenerator"] in gen js_ctx; @@ -237,14 +260,15 @@ let make_macro_api ctx p = ); ); MacroApi.get_local_type = (fun() -> - match ctx.g.get_build_infos() with + match ctx.get_build_infos() with | Some (mt,tl,_) -> Some (match mt with | TClassDecl c -> TInst (c,tl) | TEnumDecl e -> TEnum (e,tl) | TTypeDecl t -> TType (t,tl) - | TAbstractDecl a -> TAbstract(a,tl)) - | None -> + | TAbstractDecl a -> TAbstract(a,tl) + ) + | _ -> if ctx.curclass == null_class then None else @@ -252,7 +276,7 @@ let make_macro_api ctx p = ); MacroApi.get_expected_type = (fun() -> match ctx.with_type_stack with - | (WithType t) :: _ -> Some t + | (WithType.WithType(t,_)) :: _ -> Some t | _ -> None ); MacroApi.get_call_arguments = (fun() -> @@ -273,25 +297,26 @@ let make_macro_api ctx p = ctx.locals; ); MacroApi.get_build_fields = (fun() -> - match ctx.g.get_build_infos() with + match ctx.get_build_infos() with | None -> Interp.vnull | Some (_,_,fields) -> Interp.encode_array (List.map Interp.encode_field fields) ); - MacroApi.get_pattern_locals = (fun e t -> - !get_pattern_locals_ref ctx e t - ); MacroApi.define_type = (fun v mdep -> - let m, tdef, pos = (try Interp.decode_type_def v with MacroApi.Invalid_expr -> Interp.exc_string "Invalid type definition") in + let cttype = { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = Some ("TypeDefinition") } in + let mctx = (match ctx.g.macros with None -> assert false | Some (_,mctx) -> mctx) in + let ttype = Typeload.load_instance mctx (cttype,p) false in + let f () = Interp.decode_type_def v in + let m, tdef, pos = safe_decode v "TypeDefinition" ttype p f in let add is_macro ctx = - let mdep = Option.map_default (fun s -> Typeload.load_module ctx (parse_path s) pos) ctx.m.curmod mdep in - let mnew = Typeload.type_module ctx m mdep.m_extra.m_file [tdef,pos] pos in + let mdep = Option.map_default (fun s -> TypeloadModule.load_module ctx (parse_path s) pos) ctx.m.curmod mdep in + let mnew = TypeloadModule.type_module ctx m mdep.m_extra.m_file [tdef,pos] pos in mnew.m_extra.m_kind <- if is_macro then MMacro else MFake; add_dependency mnew mdep; in add false ctx; (* if we are adding a class which has a macro field, we also have to add it to the macro context (issue #1497) *) - if not ctx.in_macro then match tdef,ctx.g.macros with - | EClass c,Some (_,mctx) when List.exists (fun cff -> (Meta.has Meta.Macro cff.cff_meta || List.mem AMacro cff.cff_access)) c.d_data -> + if not ctx.in_macro then match tdef with + | EClass c when List.exists (fun cff -> (Meta.has Meta.Macro cff.cff_meta || List.mem_assoc AMacro cff.cff_access)) c.d_data -> add true mctx | _ -> () @@ -311,32 +336,26 @@ let make_macro_api ctx p = let mpath = Ast.parse_path m in begin try let m = Hashtbl.find ctx.g.modules mpath in - ignore(Typeload.type_types_into_module ctx m types pos) + ignore(TypeloadModule.type_types_into_module ctx m types pos) with Not_found -> - let mnew = Typeload.type_module ctx mpath ctx.m.curmod.m_extra.m_file types pos in + let mnew = TypeloadModule.type_module ctx mpath ctx.m.curmod.m_extra.m_file types pos in mnew.m_extra.m_kind <- MFake; add_dependency mnew ctx.m.curmod; end ); - MacroApi.module_dependency = (fun mpath file ismacro -> - let m = typing_timer ctx false (fun() -> Typeload.load_module ctx (parse_path mpath) p) in - if ismacro then - m.m_extra.m_macro_calls <- file :: List.filter ((<>) file) m.m_extra.m_macro_calls - else - add_dependency m (create_fake_module ctx file); + MacroApi.module_dependency = (fun mpath file -> + let m = typing_timer ctx false (fun() -> + let old_deps = ctx.m.curmod.m_extra.m_deps in + let m = TypeloadModule.load_module ctx (parse_path mpath) p in + ctx.m.curmod.m_extra.m_deps <- old_deps; + m + ) in + add_dependency m (create_fake_module ctx file); ); MacroApi.current_module = (fun() -> ctx.m.curmod ); MacroApi.current_macro_module = (fun () -> assert false); - MacroApi.delayed_macro = (fun i -> - let mctx = (match ctx.g.macros with None -> assert false | Some (_,mctx) -> mctx) in - let f = (try DynArray.get mctx.g.delayed_macros i with _ -> failwith "Delayed macro retrieve failure") in - f(); - let ret = !delayed_macro_result in - delayed_macro_result := (fun() -> assert false); - ret - ); MacroApi.use_cache = (fun() -> !macro_enable_cache ); @@ -352,19 +371,17 @@ let make_macro_api ctx p = false ) ); - MacroApi.add_global_metadata = (fun s1 s2 config -> - let meta = (match ParserEntry.parse_string ctx.com.defines (s2 ^ " typedef T = T") null_pos error false with - | _,[ETypedef t,_] -> t.d_meta - | _ -> assert false - ) in - List.iter (fun m -> + MacroApi.add_global_metadata = (fun s1 s2 config p -> + let meta = parse_metadata s2 p in + List.iter (fun (m,el,_) -> + let m = (m,el,p) in ctx.g.global_metadata <- (ExtString.String.nsplit s1 ".",m,config) :: ctx.g.global_metadata; ) meta; ); MacroApi.add_module_check_policy = (fun sl il b i -> let add ctx = ctx.g.module_check_policies <- (List.fold_left (fun acc s -> (ExtString.String.nsplit s ".",List.map Obj.magic il,b) :: acc) ctx.g.module_check_policies sl); - Hashtbl.iter (fun _ m -> m.m_extra.m_check_policy <- Typeload.get_policy ctx m.m_path) ctx.g.modules; + Hashtbl.iter (fun _ m -> m.m_extra.m_check_policy <- TypeloadModule.get_policy ctx m.m_path) ctx.g.modules; in let add_macro ctx = match ctx.g.macros with | None -> () @@ -375,25 +392,21 @@ let make_macro_api ctx p = | CompilationServer.MacroContext -> add_macro ctx | CompilationServer.NormalAndMacroContext -> add ctx; add_macro ctx; ); - MacroApi.on_reuse = (fun f -> - macro_interp_on_reuse := f :: !macro_interp_on_reuse - ); MacroApi.decode_expr = Interp.decode_expr; MacroApi.encode_expr = Interp.encode_expr; MacroApi.encode_ctype = Interp.encode_ctype; MacroApi.decode_type = Interp.decode_type; + MacroApi.typer_ctx = ctx; } let rec init_macro_interp ctx mctx mint = let p = null_pos in - ignore(Typeload.load_module mctx (["haxe";"macro"],"Expr") p); - ignore(Typeload.load_module mctx (["haxe";"macro"],"Type") p); + ignore(TypeloadModule.load_module mctx (["haxe";"macro"],"Expr") p); + ignore(TypeloadModule.load_module mctx (["haxe";"macro"],"Type") p); flush_macro_context mint ctx; Interp.init mint; if !macro_enable_cache && not (Common.defined mctx.com Define.NoMacroCache) then begin macro_interp_cache := Some mint; - macro_interp_on_reuse := []; - macro_interp_reused := true; end and flush_macro_context mint ctx = @@ -403,26 +416,6 @@ and flush_macro_context mint ctx = let _, types, modules = ctx.g.do_generate mctx in mctx.com.types <- types; mctx.com.Common.modules <- modules; - let check_reuse() = - if !macro_interp_reused then - true - else if not (List.for_all (fun f -> f()) !macro_interp_on_reuse) then - false - else begin - macro_interp_reused := true; - true; - end - in - (* if one of the type we are using has been modified, we need to create a new macro context from scratch *) - let mint = if not (Interp.can_reuse mint types && check_reuse()) then begin - let com2 = mctx.com in - let mint = Interp.create com2 (make_macro_api ctx Globals.null_pos) true in - let macro = ((fun() -> Interp.select mint), mctx) in - ctx.g.macros <- Some macro; - mctx.g.macros <- Some macro; - init_macro_interp ctx mctx mint; - mint - end else mint in (* we should maybe ensure that all filters in Main are applied. Not urgent atm *) let expr_filters = [VarLazifier.apply mctx.com;AbstractCast.handle_abstract_casts mctx; CapturedVars.captured_vars mctx.com;] in @@ -461,7 +454,6 @@ let create_macro_interp ctx mctx = Interp.select mint; mint, (fun() -> init_macro_interp ctx mctx mint) | Some mint -> - macro_interp_reused := false; Interp.do_reuse mint (make_macro_api ctx null_pos); mint, (fun() -> ()) ) in @@ -488,7 +480,8 @@ let get_macro_context ctx p = ctx.com.get_macros <- (fun() -> Some com2); com2.package_rules <- PMap.empty; com2.main_class <- None; - com2.display <- DisplayMode.create DMNone; + (* Inherit most display settings, but require normal typing. *) + com2.display <- {ctx.com.display with dms_kind = DMNone; dms_display = false; dms_full_typing = true; dms_force_macro_typing = true; dms_inline = true; }; List.iter (fun p -> com2.defines.Define.values <- PMap.remove (Globals.platform_name p) com2.defines.Define.values) Globals.platforms; com2.defines.Define.defines_signature <- None; com2.class_path <- List.filter (fun s -> not (ExtString.String.exists s "/_std/")) com2.class_path; @@ -500,10 +493,29 @@ let get_macro_context ctx p = Common.define com2 Define.Macro; Common.init_platform com2 !Globals.macro_platform; let mctx = ctx.g.do_create com2 in - mctx.is_display_file <- ctx.is_display_file; + mctx.is_display_file <- false; create_macro_interp ctx mctx; + Option.may (fun cs -> CompilationServer.maybe_add_context_sign cs com2 "get_macro_context") (CompilationServer.get()); api, mctx +let load_macro_module ctx cpath display p = + let api, mctx = get_macro_context ctx p in + let m = (try Hashtbl.find ctx.g.types_module cpath with Not_found -> cpath) in + (* Temporarily enter display mode while typing the macro. *) + let old = mctx.com.display in + if display then mctx.com.display <- ctx.com.display; + let mloaded = TypeloadModule.load_module mctx m p in + api.MacroApi.current_macro_module <- (fun() -> mloaded); + mctx.m <- { + curmod = mloaded; + module_types = []; + module_using = []; + module_globals = PMap.empty; + wildcard_packages = []; + module_imports = []; + }; + mloaded,(fun () -> mctx.com.display <- old) + let load_macro ctx display cpath f p = let api, mctx = get_macro_context ctx p in let mint = Interp.get_ctx() in @@ -511,22 +523,9 @@ let load_macro ctx display cpath f p = | name :: pack when name.[0] >= 'A' && name.[0] <= 'Z' -> (List.rev pack,name), Some (snd cpath) | _ -> cpath, None ) in - let meth = try Hashtbl.find mctx.com.cached_macros (cpath,f) with Not_found -> + let (meth,mloaded) = try Hashtbl.find mctx.com.cached_macros (cpath,f) with Not_found -> let t = macro_timer ctx ["typing";s_type_path cpath ^ "." ^ f] in - (* Temporarily enter display mode while typing the macro. *) - if display then mctx.com.display <- ctx.com.display; - let m = (try Hashtbl.find ctx.g.types_module cpath with Not_found -> cpath) in - let mloaded = Typeload.load_module mctx m p in - api.MacroApi.current_macro_module <- (fun() -> mloaded); - mctx.m <- { - curmod = mloaded; - module_types = []; - module_using = []; - module_globals = PMap.empty; - wildcard_packages = []; - module_imports = []; - }; - add_dependency ctx.m.curmod mloaded; + let mloaded,restore = load_macro_module ctx cpath display p in let mt = Typeload.load_type_def mctx p { tpackage = fst cpath; tname = snd cpath; tparams = []; tsub = sub } in let cl, meth = (match mt with | TClassDecl c -> @@ -534,10 +533,11 @@ let load_macro ctx display cpath f p = c, (try PMap.find f c.cl_statics with Not_found -> error ("Method " ^ f ^ " not found on class " ^ s_type_path cpath) p) | _ -> error "Macro should be called on a class" p ) in + api.MacroApi.current_macro_module <- (fun() -> mloaded); if not (Common.defined ctx.com Define.NoDeprecationWarnings) then - Display.DeprecationCheck.check_cf mctx.com meth p; - let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret,cl,meth | _ -> error "Macro call should be a method" p) in - mctx.com.display <- DisplayMode.create DMNone; + DeprecationCheck.check_cf mctx.com meth p; + let meth = (match follow meth.cf_type with TFun (args,ret) -> (args,ret,cl,meth),mloaded | _ -> error "Macro call should be a method" p) in + restore(); if not ctx.in_macro then flush_macro_context mint ctx; Hashtbl.add mctx.com.cached_macros (cpath,f) meth; mctx.m <- { @@ -551,6 +551,7 @@ let load_macro ctx display cpath f p = t(); meth in + add_dependency ctx.m.curmod mloaded; let call args = if ctx.com.verbose then Common.log ctx.com ("Calling macro " ^ s_type_path cpath ^ "." ^ f ^ " (" ^ p.pfile ^ ":" ^ string_of_int (Lexer.get_error_line p) ^ ")"); let t = macro_timer ctx ["execution";s_type_path cpath ^ "." ^ f] in @@ -571,7 +572,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p = let mctx, (margs,mret,mclass,mfield), call_macro = load_macro ctx (mode = MDisplay) cpath f p in let mpos = mfield.cf_pos in let ctexpr = { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = None } in - let expr = Typeload.load_instance mctx (ctexpr,null_pos) false p in + let expr = Typeload.load_instance mctx (ctexpr,p) false in (match mode with | MDisplay -> raise Exit (* We don't have to actually call the macro. *) @@ -579,18 +580,18 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p = unify mctx mret expr mpos; | MBuild -> let ctfields = { tpackage = []; tname = "Array"; tparams = [TPType (CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = Some "Field" },null_pos)]; tsub = None } in - let tfields = Typeload.load_instance mctx (ctfields,null_pos) false p in + let tfields = Typeload.load_instance mctx (ctfields,p) false in unify mctx mret tfields mpos | MMacroType -> let cttype = { tpackage = ["haxe";"macro"]; tname = "Type"; tparams = []; tsub = None } in - let ttype = Typeload.load_instance mctx (cttype,null_pos) false p in + let ttype = Typeload.load_instance mctx (cttype,p) false in try unify_raise mctx mret ttype mpos; (* TODO: enable this again in the future *) (* ctx.com.warning "Returning Type from @:genericBuild macros is deprecated, consider returning ComplexType instead" p; *) with Error (Unify _,_) -> let cttype = { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = Some ("ComplexType") } in - let ttype = Typeload.load_instance mctx (cttype,null_pos) false p in + let ttype = Typeload.load_instance mctx (cttype,p) false in unify_raise mctx mret ttype mpos; ); (* @@ -638,16 +639,19 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p = let constants = List.map (fun e -> let p = snd e in let e = (try - (match Codegen.type_constant_value ctx.com e with - | { eexpr = TConst (TString _); epos = p } when Lexer.is_fmt_string p -> - Lexer.remove_fmt_string p; - todo := (fun() -> Lexer.add_fmt_string p) :: !todo; - | _ -> ()); + let e' = Texpr.type_constant_value ctx.com.basic e in + let rec loop e = match e with + | { eexpr = TConst (TString _); epos = p } when Lexer.is_fmt_string p -> + Lexer.remove_fmt_string p; + todo := (fun() -> Lexer.add_fmt_string p) :: !todo; + | _ -> Type.iter loop e + in + loop e'; e with Error (Custom _,_) -> (* if it's not a constant, let's make something that is typed as haxe.macro.Expr - for nice error reporting *) (EBlock [ - (EVars [("__tmp",null_pos),Some (CTPath ctexpr,p),Some (EConst (Ident "null"),p)],p); + (EVars [("__tmp",null_pos),false,Some (CTPath ctexpr,p),Some (EConst (Ident "null"),p)],p); (EConst (Ident "__tmp"),p); ],p) ) in @@ -655,7 +659,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p = incr index; (EArray ((EArrayDecl [e],p),(EConst (Int (string_of_int (!index))),p)),p) ) el in - let elt, _ = unify_call_args mctx constants (List.map fst eargs) t_dynamic p false false in + let elt, _ = try Calls.unify_call_args mctx constants (List.map fst eargs) t_dynamic p false false with e -> List.iter (fun f -> f()) (!todo); raise e; in List.iter (fun f -> f()) (!todo); List.map2 (fun (_,mct) e -> let e, et = (match e.eexpr with @@ -676,7 +680,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p = | None -> Interp.vnull end | MAOther -> match Interp.eval_expr ictx et with - | None -> assert false + | None -> Interp.vnull | Some v -> v ) eargs elt in @@ -688,76 +692,56 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p = match call_macro args with | None -> None | Some v -> - try - Some (match mode with - | MExpr | MDisplay -> Interp.decode_expr v + let expected,process = match mode with + | MExpr | MDisplay -> + "Expr",(fun () -> Some (Interp.decode_expr v)) | MBuild -> - let fields = if v = Interp.vnull then - (match ctx.g.get_build_infos() with - | None -> assert false - | Some (_,_,fields) -> fields) - else - List.map Interp.decode_field (Interp.decode_array v) - in - (EVars [("fields",null_pos),Some (CTAnonymous fields,p),None],p) + "Array",(fun () -> + let fields = if v = Interp.vnull then + (match ctx.get_build_infos() with + | None -> assert false + | Some (_,_,fields) -> fields) + else + List.map Interp.decode_field (Interp.decode_array v) + in + Some (EVars [("fields",null_pos),false,Some (CTAnonymous fields,p),None],p) + ) | MMacroType -> - let t = if v = Interp.vnull then - mk_mono() - else try - let ct = Interp.decode_ctype v in - Typeload.load_complex_type ctx false p ct; - with MacroApi.Invalid_expr | EvalContext.RunTimeException _ -> - Interp.decode_type v - in - ctx.ret <- t; - (EBlock [],p) - ) - with MacroApi.Invalid_expr -> - if v = Interp.vnull then - error "Unexpected null value returned from macro" p - else - error "The macro didn't return a valid result" p + "ComplexType",(fun () -> + let t = if v = Interp.vnull then + mk_mono() + else try + let ct = Interp.decode_ctype v in + Typeload.load_complex_type ctx false ct; + with MacroApi.Invalid_expr | EvalContext.RunTimeException _ -> + Interp.decode_type v + in + ctx.ret <- t; + Some (EBlock [],p) + ) + in + safe_decode v expected mret p process in - let e = (if ctx.in_macro then begin - (* - this is super-tricky : we can't evaluate a macro inside a macro because we might trigger some cycles. - So instead, we generate a haxe.macro.Context.delayedCalled(i) expression that will only evaluate the - macro if/when it is called. - - The tricky part is that the whole delayed-evaluation process has to use the same contextual information - as if it was evaluated now. - *) - let ctx = { - ctx with locals = ctx.locals; - } in - let pos = DynArray.length mctx.g.delayed_macros in - DynArray.add mctx.g.delayed_macros (fun() -> - delayed_macro_result := (fun() -> - let mint = Interp.get_ctx() in - match call() with - | None -> (fun() -> raise MacroApi.Abort) - | Some e -> Interp.eval_delayed mint (type_expr ctx e Value) - ); - ); - ctx.m.curmod.m_extra.m_time <- -1.; (* disable caching for modules having macro-in-macro *) - if Common.defined ctx.com Define.MacroDebug then - ctx.com.warning "Macro-in-macro call detected" p; - let e = (EConst (Ident "$__delayed_call__"),p) in - Some (EUntyped (ECall (e,[EConst (Int (string_of_int pos)),p]),p),p) - end else + let e = if ctx.in_macro then + Some (EThrow((EConst(String "macro-in-macro")),p),p) + else call() - ) in + in e let call_macro ctx path meth args p = let mctx, (margs,_,mclass,mfield), call = load_macro ctx false path meth p in - let el, _ = unify_call_args mctx args margs t_dynamic p false false in + let el, _ = Calls.unify_call_args mctx args margs t_dynamic p false false in call (List.map (fun e -> try Interp.make_const e with Exit -> error "Parameter should be a constant" e.epos) el) let call_init_macro ctx e = - let p = { pfile = "--macro"; pmin = 0; pmax = 0 } in + let p = { pfile = "--macro " ^ e; pmin = -1; pmax = -1 } in let e = try - ParserEntry.parse_expr_string ctx.com.defines e p error false + begin match ParserEntry.parse_expr_string ctx.com.defines e p error false with + | ParseSuccess data -> data + | ParseError(_,(msg,p),_) -> (Parser.error msg p) + | ParseDisplayFile _ -> assert false (* cannot happen *) + end with err -> display_error ctx ("Could not parse `" ^ e ^ "`") p; raise err @@ -789,5 +773,9 @@ let interpret ctx = let setup() = Interp.setup Interp.macro_api +let type_stored_expr ctx e1 = + let id = match e1 with (EConst (Int s),_) -> int_of_string s | _ -> assert false in + get_stored_typed_expr ctx.com id + ;; load_macro_ref := load_macro; diff --git a/src/typing/magicTypes.ml b/src/typing/magicTypes.ml index 25df45f50f5..cec5c007cda 100644 --- a/src/typing/magicTypes.ml +++ b/src/typing/magicTypes.ml @@ -4,6 +4,7 @@ open Common open Type open Typecore open Typeload +open TypeloadModule open Error (* -------------------------------------------------------------------------- *) @@ -25,21 +26,21 @@ let extend_remoting ctx c t p async prot = (* build it *) Common.log ctx.com ("Building proxy for " ^ s_type_path path); let file, decls = (try - parse_module ctx path p + TypeloadParse.parse_module ctx path p with | Not_found -> ctx.com.package_rules <- rules; error ("Could not load proxy module " ^ s_type_path path ^ (if fst path = [] then " (try using absolute path)" else "")) p | e -> ctx.com.package_rules <- rules; raise e) in ctx.com.package_rules <- rules; let base_fields = [ { cff_name = "__cnx",null_pos; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = []; cff_kind = FVar (Some (CTPath { tpackage = ["haxe";"remoting"]; tname = if async then "AsyncConnection" else "Connection"; tparams = []; tsub = None },null_pos),None) }; - { cff_name = "new",null_pos; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun { f_args = [("c",null_pos),false,[],None,None]; f_type = None; f_expr = Some (EBinop (OpAssign,(EConst (Ident "__cnx"),p),(EConst (Ident "c"),p)),p); f_params = [] } }; + { cff_name = "new",null_pos; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic,null_pos]; cff_kind = FFun { f_args = [("c",null_pos),false,[],None,None]; f_type = None; f_expr = Some (EBinop (OpAssign,(EConst (Ident "__cnx"),p),(EConst (Ident "c"),p)),p); f_params = [] } }; ] in let tvoid = CTPath { tpackage = []; tname = "Void"; tparams = []; tsub = None } in let build_field is_public acc f = if fst f.cff_name = "new" then acc else match f.cff_kind with - | FFun fd when (is_public || List.mem APublic f.cff_access) && not (List.mem AStatic f.cff_access) -> + | FFun fd when (is_public || List.mem_assoc APublic f.cff_access) && not (List.mem_assoc AStatic f.cff_access) -> if List.exists (fun (_,_,_,t,_) -> t = None) fd.f_args then error ("Field " ^ fst f.cff_name ^ " type is not complete and cannot be used by RemotingProxy") p; let eargs = [EArrayDecl (List.map (fun ((a,_),_,_,_,_) -> (EConst (Ident a),p)) fd.f_args),p] in let ftype = (match fd.f_type with Some (CTPath { tpackage = []; tname = "Void" },_) -> None | _ -> fd.f_type) in @@ -64,7 +65,7 @@ let extend_remoting ctx c t p async prot = f_type = if async then None else ftype; f_expr = Some (EBlock [expr],p); } in - { cff_name = f.cff_name; cff_pos = f.cff_pos; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun fd } :: acc + { cff_name = f.cff_name; cff_pos = f.cff_pos; cff_doc = None; cff_meta = []; cff_access = [APublic,null_pos]; cff_kind = FFun fd } :: acc | _ -> acc in let decls = List.map (fun d -> @@ -90,7 +91,7 @@ let extend_remoting ctx c t p async prot = (* HAXE.XML.PROXY *) let extend_xml_proxy ctx c t file p = - let t = load_complex_type ctx false p (t,p) in + let t = load_complex_type ctx false (t,p) in let file = (try Common.find_file ctx.com file with Not_found -> file) in add_dependency c.cl_module (create_fake_module ctx file); let used = ref PMap.empty in diff --git a/src/typing/matcher.ml b/src/typing/matcher.ml index 04ed97559c0..a5bcf749bf8 100644 --- a/src/typing/matcher.ml +++ b/src/typing/matcher.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,7 +21,9 @@ open Globals open Ast open Type open Common +open Texpr.Builder open Error +open DisplayTypes exception Internal_match_failure @@ -37,7 +39,7 @@ let make_offset_list left right middle other = (ExtList.List.make left other) @ [middle] @ (ExtList.List.make right other) let type_field_access ctx ?(resume=false) e name = - Typer.acc_get ctx (Typer.type_field ~resume ctx e name e.epos Typer.MGet) e.epos + Calls.acc_get ctx (Fields.type_field (Fields.TypeFieldConfig.create resume) ctx e name e.epos MGet) e.epos let unapply_type_parameters params monos = List.iter2 (fun (_,t1) t2 -> match t2,follow t2 with TMono m1,TMono m2 when m1 == m2 -> Type.unify t1 t2 | _ -> ()) params monos @@ -56,10 +58,10 @@ let get_general_module_type ctx mt p = end | _ -> error "Cannot use this type as a value" p in - Typeload.load_instance ctx ({tname=loop mt;tpackage=[];tsub=None;tparams=[]},null_pos) true p + Typeload.load_instance ctx ({tname=loop mt;tpackage=[];tsub=None;tparams=[]},p) true module Constructor = struct - type t = + type t_kind = | ConConst of tconstant | ConEnum of tenum * tenum_field | ConStatic of tclass * tclass_field @@ -67,7 +69,9 @@ module Constructor = struct | ConFields of string list | ConArray of int - let to_string con = match con with + type t = t_kind * pos + + let to_string con = match fst con with | ConConst ct -> s_const ct | ConEnum(en,ef) -> ef.ef_name | ConStatic(c,cf) -> Printf.sprintf "%s.%s" (s_type_path (match c.cl_kind with KAbstractImpl a -> a.a_path | _ -> c.cl_path)) cf.cf_name @@ -75,7 +79,7 @@ module Constructor = struct | ConFields fields -> Printf.sprintf "{ %s }" (String.concat ", " fields) | ConArray i -> Printf.sprintf "" i - let equal con1 con2 = match con1,con2 with + let equal con1 con2 = match fst con1,fst con2 with | ConConst ct1,ConConst ct2 -> ct1 = ct2 | ConEnum(en1,ef1),ConEnum(en2,ef2) -> en1 == en2 && ef1 == ef2 | ConStatic(c1,cf1),ConStatic(c2,cf2) -> c1 == c2 && cf1 == cf2 @@ -84,7 +88,7 @@ module Constructor = struct | ConArray i1,ConArray i2 -> i1 = i2 | _ -> false - let arity con = match con with + let arity con = match fst con with | ConEnum (_,{ef_type = TFun(args,_)}) -> List.length args | ConEnum _ -> 0 | ConConst _ -> 0 @@ -93,7 +97,7 @@ module Constructor = struct | ConTypeExpr _ -> 0 | ConStatic _ -> 0 - let compare con1 con2 = match con1,con2 with + let compare con1 con2 = match fst con1,fst con2 with | ConConst ct1,ConConst ct2 -> compare ct1 ct2 | ConEnum(en1,ef1),ConEnum(en2,ef2) -> compare ef1.ef_index ef2.ef_index | ConStatic(c1,cf1),ConStatic(c2,cf2) -> compare cf1.cf_name cf2.cf_name @@ -104,20 +108,19 @@ module Constructor = struct open Typecore - let to_texpr ctx match_debug p con = match con with + let to_texpr ctx match_debug con = + let p = pos con in + match fst con with | ConEnum(en,ef) -> - if Meta.has Meta.FakeEnum en.e_meta then begin - let e_mt = !type_module_type_ref ctx (TEnumDecl en) None p in - mk (TField(e_mt,FEnum(en,ef))) ef.ef_type p - end else if match_debug then mk (TConst (TString ef.ef_name)) ctx.t.tstring p + if match_debug then mk (TConst (TString ef.ef_name)) ctx.t.tstring p else mk (TConst (TInt (Int32.of_int ef.ef_index))) ctx.t.tint p - | ConConst ct -> Codegen.ExprBuilder.make_const_texpr ctx.com ct p - | ConArray i -> Codegen.ExprBuilder.make_int ctx.com i p - | ConTypeExpr mt -> Typer.type_module_type ctx mt None p - | ConStatic(c,cf) -> Codegen.ExprBuilder.make_static_field c cf p + | ConConst ct -> make_const_texpr ctx.com.basic ct p + | ConArray i -> make_int ctx.com.basic i p + | ConTypeExpr mt -> TyperBase.type_module_type ctx mt None p + | ConStatic(c,cf) -> make_static_field c cf p | ConFields _ -> error "Something went wrong" p - let hash = Hashtbl.hash + let hash con = Hashtbl.hash (fst con) end module Pattern = struct @@ -141,6 +144,7 @@ module Pattern = struct ctx_locals : (string, tvar) PMap.t; mutable current_locals : (string, tvar * pos) PMap.t; mutable in_reification : bool; + is_postfix_match : bool; } exception Bad_pattern of string @@ -164,7 +168,7 @@ module Pattern = struct let ctx = pctx.ctx in let p = pos e in let fail () = - error ("Unrecognized pattern: " ^ (Ast.s_expr e)) p + error ("Unrecognized pattern: " ^ (Ast.Printer.s_expr e)) p in let unify_expected t' = unify ctx t' t p @@ -172,8 +176,9 @@ module Pattern = struct let verror name p = error (Printf.sprintf "Variable %s must appear exactly once in each sub-pattern" name) p in - let add_local name p = + let add_local final name p = let is_wildcard_local = name = "_" in + if not is_wildcard_local && pctx.is_postfix_match then error "Capture variables are not allowed in .match patterns" p; if not is_wildcard_local && PMap.mem name pctx.current_locals then error (Printf.sprintf "Variable %s is bound multiple times" name) p; match pctx.or_locals with | Some map when not is_wildcard_local -> @@ -182,16 +187,24 @@ module Pattern = struct pctx.current_locals <- PMap.add name (v,p) pctx.current_locals; v | _ -> - let v = alloc_var name t p in + let v = alloc_var (VUser TVOPatternVariable) name t p in + if final then v.v_final <- true; pctx.current_locals <- PMap.add name (v,p) pctx.current_locals; ctx.locals <- PMap.add name v ctx.locals; v in let con_enum en ef p = - Display.DeprecationCheck.check_enum pctx.ctx.com en p; - Display.DeprecationCheck.check_ef pctx.ctx.com ef p; - ConEnum(en,ef) + if not (Common.defined ctx.com Define.NoDeprecationWarnings) then begin + DeprecationCheck.check_enum pctx.ctx.com en p; + DeprecationCheck.check_ef pctx.ctx.com ef p; + end; + ConEnum(en,ef),p in + let con_static c cf p = ConStatic(c,cf),p in + let con_const ct p = ConConst ct,p in + let con_type_expr mt p = ConTypeExpr mt,p in + let con_array i p = ConArray i,p in + let con_fields fl p = ConFields fl,p in let check_expr e = let rec loop e = match e.eexpr with | TField(_,FEnum(en,ef)) -> @@ -199,9 +212,9 @@ module Pattern = struct (* (match follow ef.ef_type with TFun _ -> raise Exit | _ -> ()); *) PatConstructor(con_enum en ef e.epos,[]) | TField(_,FStatic(c,({cf_kind = Var {v_write = AccNever}} as cf))) -> - PatConstructor(ConStatic(c,cf),[]) + PatConstructor(con_static c cf e.epos,[]) | TConst ct -> - PatConstructor(ConConst ct,[]) + PatConstructor(con_const ct e.epos,[]) | TCast(e1,None) -> loop e1 | TField _ -> @@ -211,51 +224,45 @@ module Pattern = struct in loop e in + let display_mode () = + if pctx.is_postfix_match then DKMarked else DKPattern toplevel + in let try_typing e = let old = ctx.untyped in ctx.untyped <- true; - let e = try type_expr ctx e (WithType t) with exc -> ctx.untyped <- old; raise exc in + let e = try type_expr ctx e (WithType.with_type t) with exc -> ctx.untyped <- old; raise exc in ctx.untyped <- old; match e.eexpr with | TTypeExpr mt -> unify_type_pattern ctx mt t e.epos; - PatConstructor(ConTypeExpr mt,[]) + PatConstructor(con_type_expr mt e.epos,[]) | _ -> let pat = check_expr e in - begin try - Type.unify e.etype t - with (Unify_error l) -> - (* Hack: Allow matching the underlying type against its abstract. *) - begin match follow e.etype with - | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) && type_iseq t (Abstract.get_underlying_type a tl) -> () - | _ -> raise_or_display ctx l p - end - end; + unify ctx e.etype t p; pat in let handle_ident s p = - let save = - let old = ctx.locals in - ctx.locals <- (try PMap.add "this" (PMap.find "this" old) PMap.empty with Not_found -> PMap.empty); - (fun () -> - ctx.locals <- old; - ) - in try - let pat = try_typing (EConst (Ident s),p) in - save(); - pat + try_typing (EConst (Ident s),p) with | Exit | Bad_pattern _ -> + let restore = + let old = ctx.on_error in + ctx.on_error <- (fun _ _ _ -> + raise Exit + ); + (fun () -> + ctx.on_error <- old + ) + in begin try let mt = module_type_of_type t in - let e_mt = Typer.type_module_type ctx mt None p in + let e_mt = TyperBase.type_module_type ctx mt None p in let e = type_field_access ctx ~resume:true e_mt s in - let pat = check_expr e in - save(); - pat + restore(); + check_expr e with _ -> - save(); + restore(); if not (is_lower_ident s) && (match s.[0] with '`' | '_' -> false | _ -> true) then begin display_error ctx "Capture variables must be lower-case" p; end; @@ -276,12 +283,9 @@ module Pattern = struct pctx.ctx.com.warning (Printf.sprintf "`case %s` has been deprecated, use `case var %s` instead" s s) p *) | l -> pctx.ctx.com.warning ("Potential typo detected (expected similar values are " ^ (String.concat ", " l) ^ "). Consider using `var " ^ s ^ "` instead") p end; - let v = add_local s p in + let v = add_local false s p in PatVariable v end - | exc -> - save(); - raise exc in let rec loop e = match fst e with | EParenthesis e1 | ECast(e1,None) -> @@ -293,27 +297,25 @@ module Pattern = struct pctx.in_reification <- old; e | EConst((Ident ("false" | "true") | Int _ | String _ | Float _) as ct) -> - let e = Codegen.type_constant ctx.com ct p in + let p = pos e in + let e = Texpr.type_constant ctx.com.basic ct p in unify_expected e.etype; let ct = match e.eexpr with TConst ct -> ct | _ -> assert false in - PatConstructor(ConConst ct,[]) + PatConstructor(con_const ct p,[]) | EConst (Ident i) -> - begin match i with - | "_" -> - begin match follow t with - | TFun(ta,tr) when tr == fake_tuple_type -> - PatTuple(List.map (fun (_,_,t) -> (PatAny,pos e)) ta) - | _ -> - PatAny - end + begin match follow t with + | TFun(ta,tr) when tr == fake_tuple_type -> + if i = "_" then PatTuple(List.map (fun (_,_,t) -> (PatAny,pos e)) ta) + else error "Cannot bind matched tuple to variable, use _ instead" p | _ -> - handle_ident i (pos e) + if i = "_" then PatAny + else handle_ident i (pos e) end - | EVars([(s,p),None,None]) -> - let v = add_local s p in + | EVars([(s,p),final,None,None]) -> + let v = add_local final s p in PatVariable v | ECall(e1,el) -> - let e1 = type_expr ctx e1 (WithType t) in + let e1 = type_expr ctx e1 (WithType.with_type t) in begin match e1.eexpr,follow e1.etype with | TField(_, FEnum(en,ef)),TFun(_,TEnum(_,tl)) -> let monos = List.map (fun _ -> mk_mono()) ef.ef_params in @@ -356,7 +358,7 @@ module Pattern = struct | Bad_pattern s -> error s p end | EArrayDecl el -> - begin match follow t with + let rec pattern t = match follow t with | TFun(tl,tr) when tr == fake_tuple_type -> let rec loop el tl = match el,tl with | e :: el,(_,_,t) :: tl -> @@ -372,10 +374,16 @@ module Pattern = struct let patterns = ExtList.List.mapi (fun i e -> make pctx false t2 e ) el in - PatConstructor(ConArray (List.length patterns),patterns) + PatConstructor(con_array (List.length patterns) (pos e),patterns) + | TAbstract(a,tl) -> + begin match TyperBase.get_abstract_froms a tl with + | [t2] -> pattern t2 + | _ -> fail() + end | _ -> fail() - end + in + pattern t | EObjectDecl fl -> let rec known_fields t = match follow t with | TAnon an -> @@ -383,7 +391,7 @@ module Pattern = struct | TInst(c,tl) -> let rec loop fields c tl = let fields = List.fold_left (fun acc cf -> - if Typer.can_access ctx c cf false then (cf,apply_params c.cl_params tl cf.cf_type) :: acc + if Typecore.can_access ctx c cf false then (cf,apply_params c.cl_params tl cf.cf_type) :: acc else acc ) fields c.cl_ordered_fields in match c.cl_super with @@ -429,56 +437,78 @@ module Pattern = struct patterns,fields ) ([],[]) known_fields in List.iter (fun ((s,_,_),e) -> if not (List.mem s fields) then error (Printf.sprintf "%s has no field %s" (s_type t) s) (pos e)) fl; - PatConstructor(ConFields fields,patterns) + PatConstructor(con_fields fields (pos e),patterns) | EBinop(OpOr,e1,e2) -> let pctx1 = {pctx with current_locals = PMap.empty} in let pat1 = make pctx1 toplevel t e1 in let pctx2 = {pctx with current_locals = PMap.empty; or_locals = Some (pctx1.current_locals)} in let pat2 = make pctx2 toplevel t e2 in PMap.iter (fun name (v,p) -> - if not (PMap.mem name pctx2.current_locals) then verror name p; + if not (PMap.mem name pctx2.current_locals) && name <> "_" then verror name p; pctx.current_locals <- PMap.add name (v,p) pctx.current_locals ) pctx1.current_locals; PatOr(pat1,pat2) | EBinop(OpAssign,e1,e2) -> - let rec loop in_display e = match e with + let rec loop dko e = match e with | (EConst (Ident s),p) -> - let v = add_local s p in - if in_display then ignore(Typer.display_expr ctx e (mk (TLocal v) v.v_type p) (WithType t) p); + let v = add_local false s p in + begin match dko with + | None -> () + | Some dk -> ignore(TyperDisplay.display_expr ctx e (mk (TLocal v) v.v_type p) dk (WithType.with_type t) p); + end; let pat = make pctx false t e2 in PatBind(v,pat) - | (EParenthesis e1,_) -> loop in_display e1 - | (EDisplay(e1,_),_) -> loop true e1 + | (EParenthesis e1,_) -> loop dko e1 + | (EDisplay(e1,dk),_) -> loop (Some dk) e1 | _ -> fail() in - loop false e1 + loop None e1 | EBinop(OpArrow,e1,e2) -> let restore = save_locals ctx in ctx.locals <- pctx.ctx_locals; - let v = add_local "_" null_pos in - let e1 = type_expr ctx e1 Value in + let v = add_local false "_" null_pos in + let e1 = type_expr ctx e1 WithType.value in v.v_name <- "tmp"; restore(); let pat = make pctx toplevel e1.etype e2 in PatExtractor(v,e1,pat) - | EDisplay(e,iscall) -> + (* Special case for completion on a pattern local: We don't want to add the local to the context + while displaying (#7319) *) + | EDisplay((EConst (Ident _),_ as e),dk) when pctx.ctx.com.display.dms_kind = DMDefault -> + let locals = ctx.locals in let pat = loop e in - let _ = if iscall then Typer.handle_signature_display ctx e (WithType t) - else Typer.handle_display ctx e (WithType t) in + let locals' = ctx.locals in + ctx.locals <- locals; + ignore(TyperDisplay.handle_edisplay ctx e (display_mode()) (WithType.with_type t)); + ctx.locals <- locals'; pat + (* For signature completion, we don't want to recurse into the inner pattern because there's probably + a EDisplay(_,DMMarked) in there. We can handle display immediately because inner patterns should not + matter (#7326) *) + | EDisplay(e1,DKCall) -> + ignore(TyperDisplay.handle_edisplay ctx e (display_mode()) (WithType.with_type t)); + loop e1 + | EDisplay(e,dk) -> + let pat = loop e in + ignore(TyperDisplay.handle_edisplay ctx e (display_mode()) (WithType.with_type t)); + pat + | EMeta((Meta.StoredTypedExpr,_,_),e1) -> + let e1 = MacroContext.type_stored_expr ctx e1 in + loop (TExprToExpr.convert_expr e1) | _ -> fail() in let pat = loop e in pat,p - let make ctx t e = + let make ctx t e postfix_match = let pctx = { ctx = ctx; current_locals = PMap.empty; ctx_locals = ctx.locals; or_locals = None; in_reification = false; + is_postfix_match = postfix_match; } in make pctx true t e end @@ -492,7 +522,7 @@ module Case = struct case_pos : pos; } - let make ctx t el eg eo_ast with_type p = + let make ctx t el eg eo_ast with_type postfix_match p = let rec collapse_case el = match el with | e :: [] -> e @@ -513,20 +543,20 @@ module Case = struct ) ctx.locals [] in let old_ret = ctx.ret in ctx.ret <- map ctx.ret; - let pat = Pattern.make ctx (map t) e in + let pat = Pattern.make ctx (map t) e postfix_match in unapply_type_parameters ctx.type_params monos; let eg = match eg with | None -> None - | Some e -> Some (type_expr ctx e Value) + | Some e -> Some (type_expr ctx e WithType.value) in let eo = match eo_ast,with_type with - | None,WithType t -> + | None,WithType.WithType(t,_) -> unify ctx ctx.t.tvoid t (pos e); None | None,_ -> None - | Some e,WithType t -> - let e = type_expr ctx e (WithType (map t)) in + | Some e,WithType.WithType(t,_) -> + let e = type_expr ctx e (WithType.with_type (map t)) in let e = AbstractCast.cast_or_unify ctx (map t) e e.epos in Some e | Some e,_ -> @@ -536,11 +566,6 @@ module Case = struct ctx.ret <- old_ret; List.iter (fun (v,t) -> v.v_type <- t) old_types; save(); - if ctx.is_display_file && Display.is_display_position p then begin match eo,eo_ast with - | Some e,Some e_ast -> ignore(Typer.display_expr ctx e_ast e with_type p) - | None,None -> ignore(Typer.display_expr ctx (EBlock [],p) (mk (TBlock []) ctx.t.tvoid p) with_type p) - | _ -> assert false - end; { case_guard = eg; case_expr = eo; @@ -571,6 +596,7 @@ module Decision_tree = struct dt_i : int; dt_pos : pos; mutable dt_goto_target : bool; + mutable dt_texpr : texpr option; } let s_case_expr tabs case = match case.case_expr with @@ -582,32 +608,34 @@ module Decision_tree = struct s_case_expr tabs case | Switch(e,cases,dt) -> let s_case (con,b,dt) = - Printf.sprintf "\n\t%scase %s%s: %s" tabs (Constructor.to_string con) (if b then "(unguarded) " else "") (to_string (tabs ^ "\t") dt) + Printf.sprintf "\n%2i\t%scase %s%s: %s" dt.dt_i tabs (Constructor.to_string con) (if b then "(unguarded) " else "") (to_string (tabs ^ "\t") dt) in let s_cases = String.concat "" (List.map s_case cases) in let s_default = to_string (tabs ^ "\t") dt in - Printf.sprintf "switch (%s) {%s\n%s\tdefault: %s\n%s}" (Type.s_expr_pretty false tabs false s_type e) s_cases tabs s_default tabs + Printf.sprintf "switch (%s) {%s\n%2i%s\tdefault: %s\n%s}" (Type.s_expr_pretty false tabs false s_type e) s_cases dt.dt_i tabs s_default tabs | Bind(bl,dt) -> (String.concat "" (List.map (fun (v,_,e) -> if v.v_name = "_" then "" else Printf.sprintf "%s<%i> = %s; " v.v_name v.v_id (s_expr_pretty e)) bl)) ^ to_string tabs dt | Guard(e,dt1,dt2) -> - Printf.sprintf "if (%s) {\n\t%s%s\n%s} else {\n\t%s%s\n%s}" (s_expr_pretty e) tabs (to_string (tabs ^ "\t") dt1) tabs tabs (to_string (tabs ^ "\t") dt2) tabs + Printf.sprintf "if (%s) {\n%2i\t%s%s\n%s} else {\n%2i\t%s%s\n%s}" (s_expr_pretty e) dt1.dt_i tabs (to_string (tabs ^ "\t") dt1) tabs dt2.dt_i tabs (to_string (tabs ^ "\t") dt2) tabs | GuardNull(e,dt1,dt2) -> - Printf.sprintf "if (%s == null) {\n\t%s%s\n%s} else {\n\t%s%s\n%s}" (s_expr_pretty e) tabs (to_string (tabs ^ "\t") dt1) tabs tabs (to_string (tabs ^ "\t") dt2) tabs + Printf.sprintf "if (%s == null) {\n%2i\t%s%s\n%s} else {\n%2i\t%s%s\n%s}" (s_expr_pretty e) dt1.dt_i tabs (to_string (tabs ^ "\t") dt1) tabs dt2.dt_i tabs (to_string (tabs ^ "\t") dt2) tabs | Fail -> "" + let to_string tabs dt = Printf.sprintf "%2i %s" dt.dt_i (to_string tabs dt) + let equal_dt dt1 dt2 = dt1.dt_i = dt2.dt_i let equal dt1 dt2 = match dt1,dt2 with | Leaf case1,Leaf case2 -> case1 == case2 | Switch(subject1,cases1,dt1),Switch(subject2,cases2,dt2) -> - subject1 == subject2 && + Texpr.equal subject1 subject2 && safe_for_all2 (fun (con1,b1,dt1) (con2,b2,dt2) -> Constructor.equal con1 con2 && b1 = b2 && equal_dt dt1 dt2) cases1 cases2 && equal_dt dt1 dt2 | Bind(l1,dt1),Bind(l2,dt2) -> - safe_for_all2 (fun (v1,_,e1) (v2,_,e2) -> v1 == v2 && e1 == e2) l1 l2 && + safe_for_all2 (fun (v1,_,e1) (v2,_,e2) -> v1 == v2 && Texpr.equal e1 e2) l1 l2 && equal_dt dt1 dt2 | Fail,Fail -> true @@ -683,7 +711,7 @@ module Useless = struct let s = specialize false con pM in u s (patterns @ ql) | PatTuple patterns -> - let s = specialize true (ConConst TNull) pM in + let s = specialize true (ConConst TNull,pos pat) pM in u s (patterns @ ql) | (PatVariable _ | PatAny) -> let d = default pM in @@ -783,7 +811,7 @@ module Useless = struct let pM,qM,rM = specialize' false con pM qM rM in u' pM qM rM (patterns @ pl) q r | PatTuple patterns -> - let pM,qM,rM = specialize' true (ConConst TNull) pM qM rM in + let pM,qM,rM = specialize' true (ConConst TNull,pos pat) pM qM rM in u' pM qM rM (patterns @ pl) q r | PatAny | PatVariable _ -> let pM,qM = transfer_column pM qM in @@ -837,7 +865,7 @@ module Compile = struct try DtTable.find mctx.dt_table dt with Not_found -> - let dti = {dt_t = dt; dt_i = mctx.dt_count; dt_pos = p; dt_goto_target = false } in + let dti = {dt_t = dt; dt_i = mctx.dt_count; dt_pos = p; dt_goto_target = false; dt_texpr = None } in DtTable.add mctx.dt_table dt dti; mctx.dt_count <- mctx.dt_count + 1; dti @@ -849,15 +877,27 @@ module Compile = struct let guard mctx e dt1 dt2 = hashcons mctx (Guard(e,dt1,dt2)) (punion dt1.dt_pos dt2.dt_pos) let guard_null mctx e dt1 dt2 = hashcons mctx (GuardNull(e,dt1,dt2)) (punion dt1.dt_pos dt2.dt_pos) - let rec get_sub_subjects mctx e con = - match con with + let rec get_sub_subjects mctx e con arg_positions = + match fst con with | ConEnum(en,ef) -> let tl = List.map (fun _ -> mk_mono()) en.e_params in let t_en = TEnum(en,tl) in let e = if not (type_iseq t_en e.etype) then mk (TCast(e,None)) t_en e.epos else e in begin match follow ef.ef_type with | TFun(args,_) -> - ExtList.List.mapi (fun i (_,_,t) -> mk (TEnumParameter(e,ef,i)) (apply_params en.e_params tl (monomorphs ef.ef_params t)) e.epos) args + let rec combine args positions = + match (args, positions) with + | (a :: args, p :: positions) -> (a, p) :: combine args positions + | (a :: args, []) -> (a, e.epos) :: combine args positions + | _ -> [] + in + let arg_and_pos = combine args arg_positions in + ExtList.List.mapi + (fun i ((_,_,t), p) -> + let params = apply_params en.e_params tl (monomorphs ef.ef_params t) in + mk (TEnumParameter({ e with epos = p },ef,i)) params p + ) + arg_and_pos | _ -> [] end @@ -865,10 +905,9 @@ module Compile = struct List.map (type_field_access mctx.ctx e) sl | ConArray 0 -> [] | ConArray i -> - let t = match follow e.etype with TInst({cl_path=[],"Array"},[t]) -> t | TDynamic _ as t -> t | _ -> assert false in ExtList.List.init i (fun i -> - let ei = Codegen.ExprBuilder.make_int mctx.ctx.com i e.epos in - mk (TArray(e,ei)) t e.epos + let ei = make_int mctx.ctx.com.basic i e.epos in + Calls.acc_get mctx.ctx (Calls.array_access mctx.ctx e ei MGet e.epos) e.epos ) | ConConst _ | ConTypeExpr _ | ConStatic _ -> [] @@ -1030,28 +1069,39 @@ module Compile = struct let unguarded = ConTable.create 0 in let null = ref [] in List.iter (fun (case,bindings,patterns) -> - let rec loop pat = match fst pat with - | PatConstructor(ConConst TNull,_) -> + let rec loop bindings pat = match fst pat with + | PatConstructor((ConConst TNull,_),_) -> null := (case,bindings,List.tl patterns) :: !null; - | PatConstructor(con,_) -> + | PatConstructor(con,patterns) -> if case.case_guard = None then ConTable.replace unguarded con true; - ConTable.replace sigma con true; - | PatBind(_,pat) -> loop pat + let arg_positions = snd (List.split patterns) in + ConTable.replace sigma con arg_positions; + | PatBind(v,pat) -> loop ((v,pos pat,subject) :: bindings) pat | PatVariable _ | PatAny -> () | PatExtractor _ -> raise Extractor | _ -> error ("Unexpected pattern: " ^ (Pattern.to_string pat)) case.case_pos; in - loop (List.hd patterns) + loop bindings (List.hd patterns) ) cases; - let sigma = ConTable.fold (fun con _ acc -> (con,ConTable.mem unguarded con) :: acc) sigma [] in + let sigma = ConTable.fold (fun con arg_positions acc -> (con,ConTable.mem unguarded con,arg_positions) :: acc) sigma [] in sigma,List.rev !null in let sigma,null = get_column_sigma cases in if mctx.match_debug then print_endline (Printf.sprintf "compile_switch:\n\tsubject: %s\n\ttsubjects: %s\n\tcases: %s" (s_expr_pretty subject) (s_subjects subjects) (s_cases cases)); - let switch_cases = List.map (fun (con,unguarded) -> - let subjects = get_sub_subjects mctx subject con @ subjects in + let switch_cases = List.map (fun (con,unguarded,arg_positions) -> + let sub_subjects = get_sub_subjects mctx subject con arg_positions in + let rec loop bindings locals sub_subjects = match sub_subjects with + | e :: sub_subjects -> + let v = gen_local mctx.ctx e.etype e.epos in + loop ((v,v.v_pos,e) :: bindings) ((mk (TLocal v) v.v_type v.v_pos) :: locals) sub_subjects + | [] -> + List.rev bindings,List.rev locals + in + let bindings,sub_subjects = loop [] [] sub_subjects in + let subjects = sub_subjects @ subjects in let spec = specialize subject con cases in let dt = compile mctx subjects spec in + let dt = bind mctx bindings dt in con,unguarded,dt ) sigma in let default = default subject cases in @@ -1096,8 +1146,7 @@ module Compile = struct let patterns = make_offset_list (left2 + 1) (right2 - 1) pat pat_any @ patterns in (left + 1, right - 1,ev :: subjects,((case,bindings,patterns) :: cases),ex_bindings) with Not_found -> - let v = alloc_var "_hx_tmp" e1.etype e1.epos in - v.v_meta <- (Meta.Custom ":extractorVariable",[],v.v_pos) :: v.v_meta; + let v = alloc_var VExtractorVariable "_hx_tmp" e1.etype e1.epos in let ex_bindings = (v,e1.epos,e1,left,right) :: ex_bindings in let patterns = make_offset_list (left + 1) (right - 1) pat pat_any @ patterns in let ev = mk (TLocal v) v.v_type e1.epos in @@ -1129,11 +1178,17 @@ module Compile = struct let ev = mk (TLocal v) e.etype e.epos in (ev :: subjects,(v,e.epos,e) :: vars) ) ([],[]) subjects in - let dt = compile mctx subjects cases in - Useless.check mctx.ctx.com cases; - match vars with - | [] -> dt - | _ -> bind mctx vars dt + begin match cases,subjects with + | [],(subject :: _) -> + let dt_fail = fail mctx subject.epos in + switch mctx subject [] dt_fail + | _ -> + let dt = compile mctx subjects cases in + Useless.check mctx.ctx.com cases; + match vars with + | [] -> dt + | _ -> bind mctx vars dt + end end module TexprConverter = struct @@ -1145,32 +1200,39 @@ module TexprConverter = struct type match_kind = | SKValue | SKEnum - | SKFakeEnum | SKLength exception Not_exhaustive - let s_subject s e = - let rec loop s e = match e.eexpr with + let s_subject v_lookup s e = + let rec loop top s e = match e.eexpr with + | TField(_,FEnum(en,ef)) -> + s | TField(e1,fa) -> - loop (Printf.sprintf "{ %s: %s }" (field_name fa) s) e1 + if top then loop false s e1 + else loop false (Printf.sprintf "{ %s: %s }" (field_name fa) s) e1 | TEnumParameter(e1,ef,i) -> let arity = match follow ef.ef_type with TFun(args,_) -> List.length args | _ -> assert false in let l = make_offset_list i (arity - i - 1) s "_" in - loop (Printf.sprintf "%s(%s)" ef.ef_name (String.concat ", " l)) e1 + loop false (Printf.sprintf "%s(%s)" ef.ef_name (String.concat ", " l)) e1 + | TLocal v -> + begin try + loop top s (IntMap.find v.v_id v_lookup) + with Not_found -> + s + end | _ -> s in - loop s e + loop true s e let s_match_kind = function | SKValue -> "value" | SKEnum -> "enum" - | SKFakeEnum -> "fakeEnum" | SKLength -> "length" let unify_constructor ctx params t con = - match con with + match fst con with | ConEnum(en,ef) -> let t_ef = match follow ef.ef_type with TFun(_,t) -> t | _ -> ef.ef_type in let t_ef = apply_params ctx.type_params params (monomorphs en.e_params (monomorphs ef.ef_params t_ef)) in @@ -1192,6 +1254,11 @@ module TexprConverter = struct | _ -> Some(con,params) + let rec extract_const e = match e.eexpr with + | TConst ct -> Some ct + | TCast(e1,None) -> extract_const e1 + | _ -> None + let all_ctors ctx e cases = let infer_type() = match cases with | [] -> e,e.etype,false @@ -1200,7 +1267,7 @@ module TexprConverter = struct (* error "Could not determine switch kind, make sure the type is known" e.epos; *) t_dynamic in - let t = match con with + let t = match fst con with | ConEnum(en,_) -> TEnum(en,List.map snd en.e_params) | ConArray _ -> ctx.t.tarray t_dynamic | ConConst ct -> @@ -1215,7 +1282,7 @@ module TexprConverter = struct | ConTypeExpr mt -> get_general_module_type ctx mt e.epos | ConFields _ | ConStatic _ -> fail() in - mk (TCast(e,None)) t e.epos,t,true + e,t,true in let e,t,inferred = match follow e.etype with | TDynamic _ | TMono _ -> @@ -1229,16 +1296,19 @@ module TexprConverter = struct in let rec loop t = match follow t with | TAbstract({a_path = [],"Bool"},_) -> - add (ConConst(TBool true)); - add (ConConst(TBool false)); + add (ConConst(TBool true),null_pos); + add (ConConst(TBool false),null_pos); SKValue,RunTimeFinite | TAbstract({a_impl = Some c} as a,pl) when Meta.has Meta.Enum a.a_meta -> List.iter (fun cf -> ignore(follow cf.cf_type); if Meta.has Meta.Impl cf.cf_meta && Meta.has Meta.Enum cf.cf_meta then match cf.cf_expr with - | Some {eexpr = TConst ct | TCast ({eexpr = TConst ct},None)} -> - if ct != TNull then add (ConConst ct) - | _ -> add (ConStatic(c,cf)) + | Some e -> + begin match extract_const e with + | Some ct -> if ct <> TNull then add (ConConst ct,null_pos) + | None -> add (ConStatic(c,cf),null_pos) + end; + | _ -> add (ConStatic(c,cf),null_pos) ) c.cl_ordered_statics; SKValue,CompileTimeFinite | TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> @@ -1249,21 +1319,18 @@ module TexprConverter = struct | TInst({cl_path=[],"Array"},_) -> SKLength,Infinite | TEnum(en,pl) -> - PMap.iter (fun _ ef -> add (ConEnum(en,ef))) en.e_constrs; - if Meta.has Meta.FakeEnum en.e_meta then - SKFakeEnum,CompileTimeFinite - else - SKEnum,RunTimeFinite + PMap.iter (fun _ ef -> add (ConEnum(en,ef),null_pos)) en.e_constrs; + SKEnum,RunTimeFinite | TAnon _ -> - SKValue,CompileTimeFinite + SKValue,Infinite | TInst(_,_) -> - SKValue,CompileTimeFinite + SKValue,Infinite | _ -> SKValue,Infinite in let kind,finiteness = loop t in - let compatible_kind con = match con with - | ConEnum _ -> kind = SKEnum || kind = SKFakeEnum + let compatible_kind con = match fst con with + | ConEnum _ -> kind = SKEnum | ConArray _ -> kind = SKLength | _ -> kind = SKValue in @@ -1274,14 +1341,18 @@ module TexprConverter = struct let unmatched = ConTable.fold (fun con _ acc -> con :: acc) h [] in e,unmatched,kind,finiteness - let report_not_exhaustive e_subject unmatched = + let report_not_exhaustive v_lookup e_subject unmatched = let sl = match follow e_subject.etype with | TAbstract({a_impl = Some c} as a,tl) when Meta.has Meta.Enum a.a_meta -> - List.map (fun (con,_) -> match con with + List.map (fun (con,_) -> match fst con with | ConConst ct1 -> let cf = List.find (fun cf -> match cf.cf_expr with - | Some ({eexpr = TConst ct2 | TCast({eexpr = TConst ct2},None)}) -> ct1 = ct2 + | Some e -> + begin match extract_const e with + | Some ct2 -> ct1 = ct2 + | None -> false + end | _ -> false ) c.cl_ordered_statics in cf.cf_name @@ -1295,12 +1366,13 @@ module TexprConverter = struct | [] -> "_" | _ -> String.concat " | " (List.sort Pervasives.compare sl) in - error (Printf.sprintf "Unmatched patterns: %s" (s_subject s e_subject)) e_subject.epos + error (Printf.sprintf "Unmatched patterns: %s" (s_subject v_lookup s e_subject)) e_subject.epos let to_texpr ctx t_switch match_debug with_type dt = + let v_lookup = ref IntMap.empty in let com = ctx.com in let p = dt.dt_pos in - let c_type = match follow (Typeload.load_instance ctx ({ tpackage = ["std"]; tname="Type"; tparams=[]; tsub = None},null_pos) true p) with TInst(c,_) -> c | t -> assert false in + let c_type = match follow (Typeload.load_instance ctx ({ tpackage = ["std"]; tname="Type"; tparams=[]; tsub = None},p) true) with TInst(c,_) -> c | t -> assert false in let mk_index_call e = if not ctx.in_macro && not ctx.com.display.DisplayMode.dms_full_typing then (* If we are in display mode there's a chance that these fields don't exist. Let's just use a @@ -1316,107 +1388,131 @@ module TexprConverter = struct let cf = PMap.find "enumConstructor" c_type.cl_statics in make_static_call ctx c_type cf (fun t -> t) [e] com.basic.tstring e.epos in - let rec loop toplevel params dt = match dt.dt_t with - | Leaf case -> - begin match case.case_expr with - | Some e -> e - | None -> mk (TBlock []) ctx.t.tvoid case.case_pos - end - | Switch(_,[ConFields _,_,dt],_) -> (* TODO: Can we improve this by making it more general? *) - loop false params dt - | Switch(e_subject,cases,default) -> - let e_subject,unmatched,kind,finiteness = all_ctors ctx e_subject cases in - let unmatched = ExtList.List.filter_map (unify_constructor ctx params e_subject.etype) unmatched in - let loop toplevel params dt = - try Some (loop toplevel params dt) - with Not_exhaustive -> match with_type,finiteness with - | NoValue,Infinite -> None - | _,CompileTimeFinite when unmatched = [] -> None - | _ when ctx.com.display.DisplayMode.dms_error_policy = DisplayMode.EPIgnore -> None - | _ -> report_not_exhaustive e_subject unmatched - in - let cases = ExtList.List.filter_map (fun (con,_,dt) -> match unify_constructor ctx params e_subject.etype con with - | Some(_,params) -> Some (con,dt,params) - | None -> None - ) cases in - let group cases = - let h = DtTable.create 0 in - List.iter (fun (con,dt,params) -> - let l,_,_ = try DtTable.find h dt.dt_t with Not_found -> [],dt,params in - DtTable.replace h dt.dt_t (con :: l,dt,params) - ) cases; - DtTable.fold (fun _ (cons,dt,params) acc -> (cons,dt,params) :: acc) h [] - in - let cases = group cases in - let cases = List.sort (fun (cons1,_,_) (cons2,_,_) -> match cons1,cons2 with - | (con1 :: _),con2 :: _ -> Constructor.compare con1 con2 - | _ -> -1 - ) cases in - let e_default = match unmatched,finiteness with - | [],RunTimeFinite -> - None - | _ -> - loop false params default - in - let cases = ExtList.List.filter_map (fun (cons,dt,params) -> - let eo = loop false params dt in - begin match eo with - | None -> None - | Some e -> Some (List.map (Constructor.to_texpr ctx match_debug dt.dt_pos) (List.sort Constructor.compare cons),e) - end - ) cases in - let e_subject = match kind with - | SKValue | SKFakeEnum -> e_subject - | SKEnum -> if match_debug then mk_name_call e_subject else mk_index_call e_subject - | SKLength -> type_field_access ctx e_subject "length" - in - begin match cases with - | [_,e2] when e_default = None && (match finiteness with RunTimeFinite -> true | _ -> false) -> - {e2 with etype = t_switch} - | [[e1],e2] when (with_type = NoValue || e_default <> None) && ctx.com.platform <> Java (* TODO: problem with TestJava.hx:285 *) -> - let e_op = mk (TBinop(OpEq,e_subject,e1)) ctx.t.tbool e_subject.epos in - mk (TIf(e_op,e2,e_default)) t_switch dt.dt_pos - | _ -> - let e_subject = match finiteness with - | RunTimeFinite | CompileTimeFinite when e_default = None -> - let meta = (Meta.Exhaustive,[],dt.dt_pos) in - mk (TMeta(meta,e_subject)) e_subject.etype e_subject.epos + let rec loop toplevel params dt = match dt.dt_texpr with + | Some e -> + e + | None -> + let e = match dt.dt_t with + | Leaf case -> + begin match case.case_expr with + | Some e -> e + | None -> mk (TBlock []) ctx.t.tvoid case.case_pos + end + | Switch(_,[(ConFields _,_),_,dt],_) -> (* TODO: Can we improve this by making it more general? *) + loop false params dt + | Switch(e_subject,cases,default) -> + let e_subject,unmatched,kind,finiteness = all_ctors ctx e_subject cases in + let unmatched = ExtList.List.filter_map (unify_constructor ctx params e_subject.etype) unmatched in + let loop toplevel params dt = + try Some (loop false params dt) + with Not_exhaustive -> match with_type,finiteness with + | WithType.NoValue,Infinite when toplevel -> None + | _,CompileTimeFinite when unmatched = [] -> None + | _ when ctx.com.display.DisplayMode.dms_error_policy = DisplayMode.EPIgnore -> None + | _ -> report_not_exhaustive !v_lookup e_subject unmatched + in + let cases = ExtList.List.filter_map (fun (con,_,dt) -> match unify_constructor ctx params e_subject.etype con with + | Some(_,params) -> Some (con,dt,params) + | None -> None + ) cases in + let group cases = + let h = DtTable.create 0 in + List.iter (fun (con,dt,params) -> + let l,_,_ = try DtTable.find h dt.dt_t with Not_found -> [],dt,params in + DtTable.replace h dt.dt_t (con :: l,dt,params) + ) cases; + DtTable.fold (fun _ (cons,dt,params) acc -> (cons,dt,params) :: acc) h [] + in + let cases = group cases in + let cases = List.sort (fun (cons1,_,_) (cons2,_,_) -> match cons1,cons2 with + | (con1 :: _),con2 :: _ -> Constructor.compare con1 con2 + | _ -> -1 + ) cases in + let e_default = match unmatched,finiteness with + | [],RunTimeFinite -> + None | _ -> - e_subject + loop toplevel params default in - mk (TSwitch(e_subject,cases,e_default)) t_switch dt.dt_pos - end - | Guard(e,dt1,dt2) -> - let e_then = loop false params dt1 in - begin try - let e_else = loop false params dt2 in - mk (TIf(e,e_then,Some e_else)) t_switch (punion e_then.epos e_else.epos) - with Not_exhaustive when with_type = NoValue -> - mk (TIf(e,e_then,None)) ctx.t.tvoid (punion e.epos e_then.epos) - end - | GuardNull(e,dt1,dt2) -> - let e_null = Codegen.ExprBuilder.make_null e.etype e.epos in - let f = try - let e_then = loop false params dt1 in - (fun () -> - let e_else = loop false params dt2 in - let e_op = mk (TBinop(OpEq,e,e_null)) ctx.t.tbool e.epos in - mk (TIf(e_op,e_then,Some e_else)) t_switch (punion e_then.epos e_else.epos) - ) - with Not_exhaustive -> - if toplevel then (fun () -> loop false params dt2) - else if ctx.com.display.DisplayMode.dms_error_policy = DisplayMode.EPIgnore then (fun () -> mk (TConst TNull) (mk_mono()) dt2.dt_pos) - else report_not_exhaustive e [ConConst TNull,dt.dt_pos] + let cases = ExtList.List.filter_map (fun (cons,dt,params) -> + let eo = loop toplevel params dt in + begin match eo with + | None -> None + | Some e -> Some (List.map (Constructor.to_texpr ctx match_debug) (List.sort Constructor.compare cons),e) + end + ) cases in + let e_subject = match kind with + | SKValue -> e_subject + | SKEnum -> if match_debug then mk_name_call e_subject else mk_index_call e_subject + | SKLength -> type_field_access ctx e_subject "length" + in + begin match cases with + | [_,e2] when e_default = None && (match finiteness with RunTimeFinite -> true | _ -> false) -> + {e2 with etype = t_switch} + | [[e1],e2] when (with_type = NoValue || e_default <> None) && ctx.com.platform <> Java (* TODO: problem with TestJava.hx:285 *) -> + let e_op = mk (TBinop(OpEq,e_subject,e1)) ctx.t.tbool e_subject.epos in + begin match e2.eexpr with + | TIf(e_op2,e3,e_default2) when (match e_default,e_default2 with Some(e1),Some(e2) when e1 == e2 -> true | _ -> false) -> + let eand = binop OpBoolAnd e_op e_op2 ctx.t.tbool (punion e_op.epos e_op2.epos) in + mk (TIf(eand,e3,e_default)) t_switch dt.dt_pos + | _ -> + mk (TIf(e_op,e2,e_default)) t_switch dt.dt_pos + end + | _ -> + let e_subject = match finiteness with + | RunTimeFinite | CompileTimeFinite when e_default = None -> + let meta = (Meta.Exhaustive,[],dt.dt_pos) in + mk (TMeta(meta,e_subject)) e_subject.etype e_subject.epos + | _ -> + e_subject + in + mk (TSwitch(e_subject,cases,e_default)) t_switch dt.dt_pos + end + | Guard(e,dt1,dt2) -> + let e_then = loop false params dt1 in + begin try + let e_else = loop false params dt2 in + mk (TIf(e,e_then,Some e_else)) t_switch (punion e_then.epos e_else.epos) + with Not_exhaustive when with_type = NoValue -> + mk (TIf(e,e_then,None)) ctx.t.tvoid (punion e.epos e_then.epos) + end + | GuardNull(e,dt1,dt2) -> + let e_null = make_null e.etype e.epos in + let f_op e = mk (TBinop(OpEq,e,e_null)) ctx.t.tbool e.epos in + let f = try + let rec loop2 acc dt = match dt.dt_t with + | GuardNull(e,dt1,dt3) when Decision_tree.equal_dt dt2 dt3 -> + loop2 ((f_op e) :: acc) dt1 + | Guard(e,dt1,dt3) when Decision_tree.equal_dt dt2 dt3 -> + loop2 (e :: acc) dt1 + | _ -> + List.rev acc,dt + in + let conds,dt1 = loop2 [] dt1 in + let e_then = loop toplevel params dt1 in + (fun () -> + let e_else = loop toplevel params dt2 in + let e_cond = List.fold_left (fun e1 e2 -> binop OpBoolAnd e1 e2 ctx.t.tbool (punion e1.epos e2.epos)) (f_op e) conds in + mk (TIf(e_cond,e_then,Some e_else)) t_switch (punion e_then.epos e_else.epos) + ) + with Not_exhaustive -> + if toplevel then (fun () -> loop toplevel params dt2) + else if ctx.com.display.DisplayMode.dms_error_policy = DisplayMode.EPIgnore then (fun () -> mk (TConst TNull) (mk_mono()) dt2.dt_pos) + else report_not_exhaustive !v_lookup e [(ConConst TNull,dt.dt_pos),dt.dt_pos] + in + f() + | Bind(bl,dt) -> + let el = List.rev_map (fun (v,p,e) -> + v_lookup := IntMap.add v.v_id e !v_lookup; + mk (TVar(v,Some e)) com.basic.tvoid p + ) bl in + let e = loop toplevel params dt in + mk (TBlock (el @ [e])) e.etype dt.dt_pos + | Fail -> + raise Not_exhaustive in - f() - | Bind(bl,dt) -> - let el = List.rev_map (fun (v,p,e) -> - mk (TVar(v,Some e)) com.basic.tvoid p - ) bl in - let e = loop toplevel params dt in - mk (TBlock (el @ [e])) e.etype dt.dt_pos - | Fail -> - raise Not_exhaustive + dt.dt_texpr <- Some e; + e in let params = List.map snd ctx.type_params in let e = loop true params dt in @@ -1426,17 +1522,17 @@ end module Match = struct open Typecore - let match_expr ctx e cases def with_type p = + let match_expr ctx e cases def with_type postfix_match p = let match_debug = Meta.has (Meta.Custom ":matchDebug") ctx.curfield.cf_meta in let rec loop e = match fst e with | EArrayDecl el when (match el with [(EFor _ | EWhile _),_] -> false | _ -> true) -> - let el = List.map (fun e -> type_expr ctx e Value) el in + let el = List.map (fun e -> type_expr ctx e WithType.value) el in let t = tuple_type (List.map (fun e -> e.etype) el) in t,el | EParenthesis e1 -> loop e1 | _ -> - let e = type_expr ctx e Value in + let e = type_expr ctx e WithType.value in e.etype,[e] in let t,subjects = loop e in @@ -1445,22 +1541,45 @@ module Match = struct | None -> cases | Some (eo,p) -> cases @ [[EConst (Ident "_"),p],None,eo,p] in - let tmono,with_type = match with_type with - | WithType t -> (match follow t with TMono _ -> Some t,Value | _ -> None,with_type) - | _ -> None,with_type + let tmono,with_type,allow_min_void = match with_type with + | WithType.WithType(t,src) -> + (match follow t, src with + | TMono _, Some ImplicitReturn -> Some t, WithType.Value src, true + | TMono _, _ -> Some t,WithType.value,false + | _ -> None,with_type,false) + | _ -> None,with_type,false in let cases = List.map (fun (el,eg,eo,p) -> let p = match eo with Some e when p = null_pos -> pos e | _ -> p in - let case,bindings,pat = Case.make ctx t el eg eo with_type p in + let case,bindings,pat = Case.make ctx t el eg eo with_type postfix_match p in case,bindings,[pat] ) cases in let infer_switch_type () = match with_type with - | NoValue -> mk_mono() - | Value -> - let el = List.map (fun (case,_,_) -> match case.Case.case_expr with Some e -> e | None -> mk (TBlock []) ctx.t.tvoid p) cases in - unify_min ctx el - | WithType t -> t + | WithType.NoValue -> ctx.t.tvoid + | WithType.Value(_) -> + begin match cases with + | [] -> + (* If there are no cases we assume Void. This then causes a "Cannot use Void as value" error. + Note that we cannot rely on an exhaustiveness error because the switch could be over an empty enum. *) + ctx.t.tvoid + | _ -> + let el = List.map (fun (case,_,_) -> + match case.Case.case_expr with + | Some e -> + (* If we have a block, use the position of the last element. *) + begin match e.eexpr with + | TBlock el when el <> [] -> List.hd (List.rev el) + | _ -> e + end + | None -> + (* If we have no block we have to use the `case pattern` position because that's all we have. *) + mk (TBlock []) ctx.t.tvoid case.Case.case_pos + ) cases in + if allow_min_void then unify_min_for_type_source ctx el (Some WithType.ImplicitReturn) + else unify_min ctx el + end + | WithType.WithType(t,_) -> t in if match_debug then begin print_endline "CASES BEGIN"; @@ -1488,6 +1607,10 @@ module Match = struct print_endline "TEXPR END"; end; {e with epos = p} -end -;; -Typecore.match_expr_ref := Match.match_expr \ No newline at end of file + + let match_expr ctx e cases def with_type postfix_match p = match cases,def with + | [],None when (match with_type with WithType.NoValue -> true | _ -> false) -> + type_expr ctx e WithType.value + | _ -> + match_expr ctx e cases def with_type postfix_match p +end \ No newline at end of file diff --git a/src/typing/nullSafety.ml b/src/typing/nullSafety.ml new file mode 100644 index 00000000000..e106d806251 --- /dev/null +++ b/src/typing/nullSafety.ml @@ -0,0 +1,1516 @@ +open Globals +open Ast +open Type + +type safety_message = { + sm_msg : string; + sm_pos : pos; +} + +type safety_report = { + mutable sr_errors : safety_message list; +} + +let add_error report msg pos = + report.sr_errors <- { sm_msg = ("Null safety: " ^ msg); sm_pos = pos; } :: report.sr_errors; + +type scope_type = + | STNormal + | STLoop + | STClosure + (* A closure which gets executed along the "normal" program flow without being delayed or stored somewhere *) + | STImmediateClosure + +type safety_unify_error = + | NullSafetyError + +exception Safety_error of safety_unify_error + +let safety_error () : unit = raise (Safety_error NullSafetyError) + +type safety_mode = + | SMOff + | SMLoose + | SMStrict + +(** + Terminates compiler process and prints user-friendly instructions about filing an issue in compiler repo. +*) +let fail ?msg hxpos mlpos = + let msg = + (Lexer.get_error_pos (Printf.sprintf "%s:%d:") hxpos) ^ ": " + ^ "Null safety: " ^ (match msg with Some msg -> msg | _ -> "unexpected expression.") ^ "\n" + ^ "Submit an issue to https://github.com/HaxeFoundation/haxe/issues with expression example and following information:" + in + match mlpos with + | (file, line, _, _) -> + Printf.eprintf "%s\n" msg; + Printf.eprintf "%s:%d\n" file line; + assert false + +(** + Returns human-readable string representation of specified type +*) +let str_type t = s_type (print_context()) t + +let is_string_type t = + match t with + | TInst ({ cl_path = ([], "String")}, _) + | TAbstract ({ a_path = ([],"Null") },[TInst ({ cl_path = ([], "String")}, _)]) -> true + | _ -> false + +(** + Check for explicit `Null<>` typing +*) +let rec is_nullable_type = function + | TMono r -> + (match !r with None -> false | Some t -> is_nullable_type t) + | TAbstract ({ a_path = ([],"Null") },[t]) -> + true + | TAbstract (a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> + is_nullable_type (apply_params a.a_params tl a.a_this) + | TLazy f -> + is_nullable_type (lazy_type f) + | TType (t,tl) -> + is_nullable_type (apply_params t.t_params tl t.t_type) + | _ -> + false + +(** + If `expr` is a TCast or TMeta, returns underlying expression (recursively bypassing nested casts). + Otherwise returns `expr` as is. +*) +let rec reveal_expr expr = + match expr.eexpr with + | TCast (e, _) -> reveal_expr e + | TMeta (_, e) -> reveal_expr e + | _ -> expr + +(** + Try to get a human-readable representation of an `expr` +*) +let symbol_name expr = + match (reveal_expr expr).eexpr with + | TField (_, access) -> field_name access + | TIdent name -> name + | TLocal { v_name = name } -> name + | TNew _ -> "new" + | _ -> "" + +type safety_subject = + (* + Fields accessed through a static access are identified by the class path and the field name. + E.g. + `pack.MyClass.field` is `((["pack"], "MyClass"), ["field"])` + `pack.MyClass.field.sub` is `((["pack"], "MyClass"), ["field"; "sub"])` + *) + | SFieldOfClass of (path * (string list)) + (* + Fields accessed through a local variable are identified by the var id and the field name. + E.g. + `v.field` is `(v.v_id, ["field"])` + `v.field.sub` is `(v.v_id, ["field"; "sub"])` + *) + | SFieldOfLocalVar of (int * (string list)) + (* + Fields accessed through `this` are identified by their names. + E.g. + `this.field` is `["field"]` + `this.field.sub` is `["field"; "sub"]` + *) + | SFieldOfThis of (string list) + (* + Local variables - by tvar.v_id + *) + | SLocalVar of int + (* + For expressions, which cannot be checked agains `null` to become safe + *) + | SNotSuitable + +let rec get_subject loose_safety expr = + match expr.eexpr with + | TLocal v -> + SLocalVar v.v_id + | TField ({ eexpr = TTypeExpr _ }, FStatic (cls, field)) when loose_safety || (has_class_field_flag field CfFinal) -> + SFieldOfClass (cls.cl_path, [field.cf_name]) + | TField ({ eexpr = TConst TThis }, (FInstance (_, _, field) | FAnon field)) when loose_safety || (has_class_field_flag field CfFinal) -> + SFieldOfThis [field.cf_name] + | TField ({ eexpr = TLocal v }, (FInstance (_, _, field) | FAnon field)) when loose_safety || (has_class_field_flag field CfFinal) -> + SFieldOfLocalVar (v.v_id, [field.cf_name]) + | TField (e, (FInstance (_, _, field) | FAnon field)) when loose_safety -> + (match get_subject loose_safety e with + | SFieldOfClass (path, fields) -> SFieldOfClass (path, field.cf_name :: fields) + | SFieldOfThis fields -> SFieldOfThis (field.cf_name :: fields) + | SFieldOfLocalVar (var_id, fields) -> SFieldOfLocalVar (var_id, field.cf_name :: fields) + |_ -> SNotSuitable + ) + |_ -> SNotSuitable + +let rec is_suitable loose_safety expr = + match expr.eexpr with + | TField ({ eexpr = TConst TThis }, FInstance _) + | TField ({ eexpr = TLocal _ }, (FInstance _ | FAnon _)) + | TField ({ eexpr = TTypeExpr _ }, FStatic _) + | TLocal _ -> true + | TField (target, (FInstance _ | FStatic _ | FAnon _)) when loose_safety -> is_suitable loose_safety target + |_ -> false + +class unificator = + object(self) + val stack = new_rec_stack() + (** + Check if it's possible to pass a value of type `a` to a place where a value of type `b` is expected. + Raises `Safety_error` exception if it's not. + *) + method unify a b = + if a == b then + () + else + match a, b with + (* if `b` is nullable, no more checks needed *) + | _, TAbstract ({ a_path = ([],"Null") },[t]) -> + () + | TAbstract ({ a_path = ([],"Null") },[t]), _ when not (is_nullable_type b) -> + safety_error() + | TInst (_, a_params), TInst(_, b_params) when (List.length a_params) = (List.length b_params) -> + List.iter2 self#unify a_params b_params + | TAnon a_anon, TAnon b_anon -> + self#unify_anon_to_anon a_anon b_anon + | TInst (a_cls, a_params), TAnon b_anon -> + self#unify_class_to_anon a_cls a_params b_anon + | TFun a_signature, TFun b_signature -> + self#unify_functions a_signature b_signature + (* patterns below are used to reveal real type *) + | TLazy f, _ -> + self#unify (lazy_type f) b + | _, TLazy f -> self#unify a (lazy_type f) + | TMono t, _ -> + (match !t with None -> () | Some t -> self#unify t b) + | _, TMono t -> + (match !t with None -> () | Some t -> self#unify a t) + | TType (t,tl), _ -> + self#unify_rec a b (fun() -> self#unify (apply_params t.t_params tl t.t_type) b) + | _, TType (t,tl) -> + self#unify_rec a b (fun() -> self#unify a (apply_params t.t_params tl t.t_type)) + | TAbstract (abstr,tl), _ when not (Meta.has Meta.CoreType abstr.a_meta) -> + self#unify (apply_params abstr.a_params tl abstr.a_this) b + | _, TAbstract (abstr,tl) when not (Meta.has Meta.CoreType abstr.a_meta) -> + self#unify a (apply_params abstr.a_params tl abstr.a_this) + | _ -> + () + + method unify_rec (a:t) (b:t) (frun:unit->unit) = + let checked = + rec_stack_exists + (fun(a2,b2) -> fast_eq a a2 && fast_eq b b2) + stack + in + if not checked then begin + try + stack.rec_stack <- (a, b) :: stack.rec_stack; + frun(); + stack.rec_stack <- List.tl stack.rec_stack + with + | e -> + stack.rec_stack <- List.tl stack.rec_stack; + raise e + end + + method private unify_anon_to_anon (a:tanon) (b:tanon) = + PMap.iter + (fun name b_field -> + let a_field = + try Some (PMap.find name a.a_fields) + with Not_found -> None + in + match a_field with + | None -> () + | Some a_field -> self#unify a_field.cf_type b_field.cf_type + ) + b.a_fields + + method private unify_class_to_anon (a:tclass) (a_params:tparams) (b:tanon) = + PMap.iter + (fun name b_field -> + let a_field = + try Some (PMap.find name a.cl_fields) + with Not_found -> None + in + match a_field with + | None -> () + | Some a_field -> + let a_type = apply_params a.cl_params a_params a_field.cf_type in + self#unify a_type b_field.cf_type + ) + b.a_fields + + method private unify_functions (a_args, a_result) (b_args, b_result) = + (* check return type *) + (match b_result with + | TAbstract ({ a_path = ([], "Void") }, []) -> () + | _ -> self#unify a_result b_result; + ); + (* check arguments *) + let rec traverse a_args b_args = + match a_args, b_args with + | [], _ | _, [] -> () + | (_, _, a_arg) :: a_rest, (_, _, b_arg) :: b_rest -> + self#unify b_arg a_arg; + traverse a_rest b_rest + in + traverse a_args b_args + end + +(** + Checks if execution of provided expression is guaranteed to be terminated with `return`, `throw`, `break` or `continue`. +*) +let rec is_dead_end e = + match e.eexpr with + | TThrow _ -> true + | TReturn _ -> true + | TBreak -> true + | TContinue -> true + | TWhile (_, body, DoWhile) -> is_dead_end body + | TIf (_, if_body, Some else_body) -> is_dead_end if_body && is_dead_end else_body + | TBlock exprs -> List.exists is_dead_end exprs + | TMeta (_, e) -> is_dead_end e + | TCast (e, _) -> is_dead_end e + | _ -> false + +(** + If `t` represents `Null` this function returns `SomeType`. +*) +let rec unfold_null t = + match t with + | TMono r -> (match !r with None -> t | Some t -> unfold_null t) + | TAbstract ({ a_path = ([],"Null") }, [t]) -> unfold_null t + | TLazy f -> unfold_null (lazy_type f) + | TType (t,tl) -> unfold_null (apply_params t.t_params tl t.t_type) + | _ -> t + +(** + Shadow Type.error to avoid raising unification errors, which should not be raised from null-safety checks +*) +let safety_error () : unit = raise (Safety_error NullSafetyError) + +let accessed_field_name access = + match access with + | FInstance (_, _, { cf_name = name }) -> name + | FStatic (_, { cf_name = name }) -> name + | FAnon { cf_name = name } -> name + | FDynamic name -> name + | FClosure (_, { cf_name = name }) -> name + | FEnum (_, { ef_name = name }) -> name + +let rec can_pass_type src dst = + if is_nullable_type src && not (is_nullable_type dst) then + false + else + (* TODO *) + match dst with + | TMono r -> (match !r with None -> true | Some t -> can_pass_type src t) + | TEnum (_, params) -> true + | TInst _ -> true + | TType (t, tl) -> can_pass_type src (apply_params t.t_params tl t.t_type) + | TFun _ -> true + | TAnon _ -> true + | TDynamic _ -> true + | TLazy _ -> true + | TAbstract ({ a_path = ([],"Null") }, [t]) -> true + | TAbstract _ -> true + +(** + Collect nullable local vars which are checked against `null`. + Returns a tuple of (vars_checked_to_be_null * vars_checked_to_be_not_null) in case `condition` evaluates to `true`. +*) +let rec process_condition loose_safety condition (is_nullable_expr:texpr->bool) callback = + let nulls = ref [] + and not_nulls = ref [] in + let add to_nulls expr = + if to_nulls then nulls := expr :: !nulls + else not_nulls := expr :: !not_nulls + in + let rec traverse positive e = + match e.eexpr with + | TUnop (Not, Prefix, e) -> traverse (not positive) e + | TBinop (OpEq, { eexpr = TConst TNull }, checked_expr) when is_suitable loose_safety checked_expr -> + add positive checked_expr + | TBinop (OpEq, checked_expr, { eexpr = TConst TNull }) when is_suitable loose_safety checked_expr -> + add positive checked_expr + | TBinop (OpNotEq, { eexpr = TConst TNull }, checked_expr) when is_suitable loose_safety checked_expr -> + add (not positive) checked_expr + | TBinop (OpNotEq, checked_expr, { eexpr = TConst TNull }) when is_suitable loose_safety checked_expr -> + add (not positive) checked_expr + | TBinop (OpEq, e, checked_expr) when is_suitable loose_safety checked_expr && not (is_nullable_expr e) -> + if positive then not_nulls := checked_expr :: !not_nulls + | TBinop (OpEq, checked_expr, e) when is_suitable loose_safety checked_expr && not (is_nullable_expr e) -> + if positive then not_nulls := checked_expr :: !not_nulls + | TBinop (OpBoolAnd, left_expr, right_expr) when positive -> + traverse positive left_expr; + traverse positive right_expr + | TBinop (OpBoolAnd, left_expr, right_expr) when not positive -> + List.iter + (fun e -> + let _, not_nulls = process_condition loose_safety left_expr is_nullable_expr callback in + List.iter (add true) not_nulls + ) + [left_expr; right_expr] + | TBinop (OpBoolOr, left_expr, right_expr) when not positive -> + traverse positive left_expr; + traverse positive right_expr + | TBinop (OpBoolOr, left_expr, right_expr) when positive -> + List.iter + (fun e -> + let nulls, _ = process_condition loose_safety left_expr is_nullable_expr callback in + List.iter (add true) nulls + ) + [left_expr; right_expr] + | TParenthesis e -> traverse positive e + | _ -> callback e + in + traverse true condition; + (!nulls, !not_nulls) + +(** + Check if metadata contains @:nullSafety(Off) meta +**) +let rec contains_unsafe_meta metadata = + match metadata with + | [] -> false + | (Meta.NullSafety, [(EConst (Ident "Off"), _)], _) :: _ -> true + | _ :: rest -> contains_unsafe_meta rest + +(** + Check if metadata contains @:nullSafety or @:nullSafety(true) meta +**) +let rec contains_safe_meta metadata = + match metadata with + | [] -> false + | (Meta.NullSafety, [], _) :: _ + | (Meta.NullSafety, [(EConst (Ident ("Loose" | "Strict")), _)], _) :: _ -> true + | _ :: rest -> contains_safe_meta rest + +let safety_enabled meta = + (contains_safe_meta meta) && not (contains_unsafe_meta meta) + +let safety_mode (metadata:Ast.metadata) = + let rec traverse mode meta = + match mode, meta with + | Some SMOff, _ + | _, [] -> mode + | _, (Meta.NullSafety, [(EConst (Ident "Off"), _)], _) :: _ -> + Some SMOff + | None, (Meta.NullSafety, ([] | [(EConst (Ident "Loose"), _)]), _) :: rest -> + traverse (Some SMLoose) rest + | _, (Meta.NullSafety, [(EConst (Ident "Strict"), _)], _) :: rest -> + traverse (Some SMStrict) rest + | _, _ :: rest -> + traverse mode rest + in + match traverse None metadata with + | Some mode -> mode + | None -> SMOff + +let rec validate_safety_meta error (metadata:Ast.metadata) = + match metadata with + | [] -> () + | (Meta.NullSafety, args, pos) :: rest -> + (match args with + | ([] | [(EConst (Ident ("Off" | "Loose" | "Strict")), _)]) -> () + | _ -> error "Invalid argument for @:nullSafety meta" pos + ); + validate_safety_meta error rest + | _ :: rest -> validate_safety_meta error rest + +(** + Check if specified `field` represents a `var` field which will exist at runtime. +*) +let should_be_initialized field = + match field.cf_kind with + | Var { v_read = AccNormal | AccInline | AccNo } | Var { v_write = AccNormal | AccNo } -> true + | Var _ -> Meta.has Meta.IsVar field.cf_meta + | _ -> false + +(** + Check if `field` is overridden in subclasses +*) +let is_overridden cls field = + let rec loop_inheritance c = + (PMap.mem field.cf_name c.cl_fields) + || List.exists (fun d -> loop_inheritance d) c.cl_descendants; + in + List.exists (fun d -> loop_inheritance d) cls.cl_descendants + +(** + Check if all items of the `needle` list exist in the same order in the beginning of the `haystack` list. +*) +let rec list_starts_with_list (haystack:string list) (needle:string list) = + match haystack, needle with + | _, [] -> true + | [], _ -> false + | current_haystack :: rest_haystack, current_needle :: rest_needle -> + current_haystack = current_needle && list_starts_with_list rest_haystack rest_needle + +(** + A class which is used to check if an anonymous function passed to a method will be executed + before that method execution is finished. +*) +class immediate_execution = + object(self) + val cache = Hashtbl.create 500 + (** + Get cached results of the previous checks for the specified `field` + *) + method private get_cache field = + try + Hashtbl.find cache field + with + | Not_found -> + let field_cache = Hashtbl.create 5 in + Hashtbl.add cache field field_cache; + field_cache + (** + Check if a lambda passed to `arg_num`th argument of the `callee` function will be executed immediately without + delaying it or storing it somewhere else. + *) + method check callee arg_num = + match (reveal_expr callee).eexpr with + | TField (_, FClosure (Some (cls, _), ({ cf_kind = Method (MethNormal | MethInline) } as field))) + | TField (_, FStatic (cls, ({ cf_kind = Method (MethNormal | MethInline) } as field))) + | TField (_, FInstance (cls, _, ({ cf_kind = Method (MethNormal | MethInline) } as field))) -> + if PurityState.is_pure cls field then + true + else + (match cls, field with + (* known to be pure *) + | { cl_path = ([], "Array") }, _ -> true + (* try to analyze function code *) + | _, ({ cf_expr = (Some { eexpr = TFunction fn }) } as field) when (has_class_field_flag field CfFinal) || not (is_overridden cls field) -> + if arg_num < 0 || arg_num >= List.length fn.tf_args then + false + else begin + let cache = self#get_cache field in + if Hashtbl.mem cache arg_num then + Hashtbl.find cache arg_num + else begin + Hashtbl.add cache arg_num true; + let (arg_var, _) = List.nth fn.tf_args arg_num in + let result = not (self#is_stored arg_var fn.tf_expr) in + Hashtbl.replace cache arg_num result; + result + end + end + | _ -> + false + ) + | _ -> false + (** + Check if `fn_var` is passed somewhere else in `expr` (stored to a var/field, captured by a closure etc.) + *) + method private is_stored fn_var expr = + match expr.eexpr with + | TThrow { eexpr = TLocal v } + | TReturn (Some { eexpr = TLocal v }) + | TCast ({ eexpr = TLocal v }, _) + | TMeta (_, { eexpr = TLocal v }) + | TBinop (OpAssign, _, { eexpr = TLocal v }) when v.v_id = fn_var.v_id -> + true + | TFunction fn -> + let rec captured e = + match e.eexpr with + | TLocal v -> v.v_id = fn_var.v_id + | _ -> check_expr captured e + in + captured fn.tf_expr + | TCall (callee, args) -> + if self#is_stored fn_var callee then + true + else begin + let arg_num = ref 0 in + List.exists + (fun arg -> + let result = + match arg.eexpr with + | TLocal v when v.v_id = fn_var.v_id -> not (self#check callee !arg_num) + | _ -> self#is_stored fn_var arg + in + incr arg_num; + result + ) + args + end + | _ -> check_expr (self#is_stored fn_var) expr + end + +(** + Each loop or function should have its own safety scope. +*) +class safety_scope (mode:safety_mode) (scope_type:scope_type) (safe_locals:(safety_subject,texpr) Hashtbl.t) (never_safe:(safety_subject,texpr) Hashtbl.t) = + object (self) + (** Local vars declared in current scope *) + val declarations = Hashtbl.create 100 + method get_safe_locals = safe_locals + method get_never_safe = never_safe + method get_type = scope_type + (** + Reset local vars safety to the specified state + *) + method reset_to (state:(safety_subject,texpr) Hashtbl.t) = + Hashtbl.clear safe_locals; + Hashtbl.iter (Hashtbl.add safe_locals) state + (** + Should be called for each local var declared + *) + method declare_var v = + Hashtbl.add declarations v.v_id v + (** + Check if local var was declared in this scope + *) + method owns_var v = + Hashtbl.mem declarations v.v_id + (** + Check if local variable declared in this scope is guaranteed to not have a `null` value. + *) + method is_safe (expr:texpr) = + not (is_nullable_type expr.etype) + || match self#get_subject expr with + | SNotSuitable -> + false + | subj -> + not (Hashtbl.mem never_safe subj) + && Hashtbl.mem safe_locals subj + (* not (Hashtbl.mem never_safe local_var.v_id) + && ( + Hashtbl.mem safe_locals local_var.v_id + || not (is_nullable_type local_var.v_type) + ) *) + (** + Add variable to the list of safe locals. + *) + method add_to_safety expr = + match self#get_subject expr with + | SNotSuitable -> () + | subj -> Hashtbl.replace safe_locals subj expr + (** + Remove variable from the list of safe locals. + *) + method remove_from_safety ?(forever=false) expr = + match self#get_subject expr with + | SNotSuitable -> () + | subj -> + Hashtbl.remove safe_locals subj; + if forever then + Hashtbl.replace never_safe subj expr + (** + Remove locals, which don't exist in `sample`, from safety. + *) + method filter_safety (sample:(safety_subject,texpr) Hashtbl.t) = + Hashtbl.iter + (fun subj expr -> + if not (Hashtbl.mem sample subj) then + Hashtbl.remove safe_locals subj + ) + (Hashtbl.copy safe_locals); + (** + Should be called upon assigning a value to `expr`. + Removes subjects like `expr.subField` from safety. + *) + method reassigned (expr:texpr) = + match self#get_subject expr with + | SNotSuitable -> () + | subj -> + let remove safe_subj safe_fields fields = + if list_starts_with_list (List.rev safe_fields) (List.rev fields) then + Hashtbl.remove safe_locals safe_subj + in + Hashtbl.iter + (fun safe_subj safe_expr -> + match safe_subj, subj with + | SFieldOfLocalVar (safe_id, _), SLocalVar v_id when safe_id = v_id -> + Hashtbl.remove safe_locals safe_subj + | SFieldOfLocalVar (safe_id, safe_fields), SFieldOfLocalVar (v_id, fields) when safe_id = v_id -> + remove safe_subj safe_fields fields + | SFieldOfClass (safe_path, safe_fields), SFieldOfClass (path, fields) when safe_path = path -> + remove safe_subj safe_fields fields + | SFieldOfClass (safe_path, safe_fields), SFieldOfClass (path, fields) when safe_path = path -> + remove safe_subj safe_fields fields + | SFieldOfThis safe_fields, SFieldOfThis fields -> + remove safe_subj safe_fields fields + | _ -> () + ) + (Hashtbl.copy safe_locals) + (** + Wrapper for `get_subject` function + *) + method private get_subject = + get_subject (mode <> SMStrict) + end + +(** + Class to simplify collecting lists of local vars, fields and other symbols checked against `null`. +*) +class local_safety (mode:safety_mode) = + object (self) + val mutable scopes = [new safety_scope mode STNormal (Hashtbl.create 100) (Hashtbl.create 100)] + (** + Drop collected data + *) + method clear = + scopes <- [new safety_scope mode STNormal (Hashtbl.create 100) (Hashtbl.create 100)] + (** + Get the latest created scope. + *) + method private get_current_scope = + match scopes with + | current :: _-> current + | [] -> fail ~msg:"List of scopes should never end." null_pos __POS__ + (** + Get a copy of hashtable, which stores currently safe locals + *) + method get_safe_locals_copy = + Hashtbl.copy (self#get_current_scope#get_safe_locals) + (** + Should be called upon local function declaration. + *) + method function_declared (immediate_execution:bool) (fn:tfunc) = + let scope = + if immediate_execution || mode = SMLoose then + new safety_scope mode STImmediateClosure self#get_current_scope#get_safe_locals self#get_current_scope#get_never_safe + else + new safety_scope mode STClosure (Hashtbl.create 100) (Hashtbl.create 100) + in + scopes <- scope :: scopes; + List.iter (fun (v, _) -> scope#declare_var v) fn.tf_args + (** + Should be called upon entering a loop. + *) + method loop_declared e = + let scope = new safety_scope mode STLoop self#get_current_scope#get_safe_locals self#get_current_scope#get_never_safe in + (* let scope = new safety_scope mode STLoop (Hashtbl.create 100) (Hashtbl.create 100) in *) + scopes <- scope :: scopes; + match e.eexpr with + | TFor (v, _, _) -> scope#declare_var v + | TWhile _ -> () + | _ -> fail ~msg:"Expected TFor or TWhile." e.epos __POS__ + (** + Should be called upon leaving local function declaration. + *) + method scope_closed = + match scopes with + | [] -> fail ~msg:"No scopes left." null_pos __POS__ + | [scope] -> fail ~msg:"Cannot close the last scope." null_pos __POS__ + | _ :: rest -> scopes <- rest + (** + Should be called for each local var declared + *) + method declare_var ?(is_safe=false) (v:tvar) = + let scope = self#get_current_scope in + scope#declare_var v; + if is_safe then scope#add_to_safety { eexpr = TVar (v, None); etype = v.v_type; epos = v.v_pos } + (** + Check if local variable is guaranteed to not have a `null` value. + *) + method is_safe expr = + if not (is_nullable_type expr.etype) then + true + else + let captured () = + match expr.eexpr with + | TLocal local_var -> + let rec traverse scopes = + match scopes with + | [] -> false + | current :: rest -> + if current#owns_var local_var then + false + else if current#get_type = STClosure then + true + else + traverse rest + in + traverse scopes + | _ -> false + in + (mode = SMLoose || not (captured())) && self#get_current_scope#is_safe expr + (** + This method should be called upon passing `while`. + It collects locals which are checked against `null` and executes callbacks for expressions with proper statuses of locals. + *) + method process_while expr is_nullable_expr (condition_callback:texpr->unit) (body_callback:(unit->unit)->texpr->unit) = + match expr.eexpr with + | TWhile (condition, body, DoWhile) -> + let original_safe_locals = self#get_safe_locals_copy in + condition_callback condition; + let (_, not_nulls) = process_condition (mode <> SMStrict) condition is_nullable_expr (fun _ -> ()) in + body_callback + (fun () -> + List.iter + (fun not_null -> + match get_subject (mode <> SMStrict) not_null with + | SNotSuitable -> () + | subj -> + if Hashtbl.mem original_safe_locals subj then + self#get_current_scope#add_to_safety not_null + ) + not_nulls + ) + body + | TWhile (condition, body, NormalWhile) -> + condition_callback condition; + let (nulls, not_nulls) = process_condition (mode <> SMStrict) condition is_nullable_expr (fun _ -> ()) in + (** execute `body` with known not-null variables *) + List.iter self#get_current_scope#add_to_safety not_nulls; + body_callback + (fun () -> List.iter self#get_current_scope#add_to_safety not_nulls) + body; + List.iter self#get_current_scope#remove_from_safety not_nulls; + | _ -> fail ~msg:"Expected TWhile" expr.epos __POS__ + (** + Should be called for bodies of loops (for, while) + *) + method process_loop_body (first_check:unit->unit) (intermediate_action:(unit->unit) option) (second_check:unit->unit) = + let original_safe_locals = self#get_safe_locals_copy in + (** The first check to find out which vars will become unsafe in a loop *) + first_check(); + (* If local var became safe in a loop, then we need to remove it from safety to make it unsafe outside of a loop again *) + self#get_current_scope#filter_safety original_safe_locals; + Option.may (fun action -> action()) intermediate_action; + (** The second check with unsafe vars removed from safety *) + second_check() + (** + This method should be called upon passing `try`. + *) + method process_try (try_block:texpr) (catches:(tvar * texpr) list) (check_expr:texpr->unit) = + let original_safe_locals = self#get_safe_locals_copy in + check_expr try_block; + (* Remove locals which became safe inside of a try block from safety *) + self#get_current_scope#filter_safety original_safe_locals; + let safe_after_try = self#get_safe_locals_copy + and safe_after_catches = self#get_safe_locals_copy in + List.iter + (fun (_, catch_block) -> + self#get_current_scope#reset_to safe_after_try; + check_expr catch_block; + Hashtbl.iter + (fun var_id v -> + if not (self#is_safe v) then + Hashtbl.remove safe_after_catches var_id + ) + (Hashtbl.copy safe_after_catches) + ) + catches; + self#get_current_scope#reset_to safe_after_catches + (** + This method should be called upon passing `if`. + It collects locals which are checked against `null` and executes callbacks for expressions with proper statuses of locals. + *) + method process_if expr is_nullable_expr (condition_callback:texpr->unit) (body_callback:texpr->unit) = + match expr.eexpr with + | TIf (condition, if_body, else_body) -> + condition_callback condition; + let (nulls, not_nulls) = + process_condition (mode <> SMStrict) condition is_nullable_expr (fun _ -> ()) + in + let not_condition = + { eexpr = TUnop (Not, Prefix, condition); etype = condition.etype; epos = condition.epos } + in + let (else_nulls, else_not_nulls) = + process_condition (mode <> SMStrict) not_condition is_nullable_expr (fun _ -> ()) + in + (** execute `if_body` with known not-null variables *) + List.iter self#get_current_scope#add_to_safety not_nulls; + body_callback if_body; + List.iter self#get_current_scope#remove_from_safety not_nulls; + (** execute `else_body` with known not-null variables *) + let handle_dead_end body safe_vars = + if is_dead_end body then + List.iter self#get_current_scope#add_to_safety safe_vars + in + (match else_body with + | None -> + (** If `if_body` terminates execution, then bypassing `if` means `else_not_nulls` are safe now *) + handle_dead_end if_body else_not_nulls + | Some else_body -> + List.iter self#get_current_scope#add_to_safety else_not_nulls; + body_callback else_body; + List.iter self#get_current_scope#remove_from_safety else_not_nulls; + (** If `if_body` terminates execution, then bypassing `if` means `else_not_nulls` are safe now *) + handle_dead_end if_body else_not_nulls; + (** If `else_body` terminates execution, then bypassing `else` means `not_nulls` are safe now *) + handle_dead_end else_body not_nulls + ); + | _ -> fail ~msg:"Expected TIf" expr.epos __POS__ + (** + Handle boolean AND outside of `if` condition. + *) + method process_and left_expr right_expr is_nullable_expr (callback:texpr->unit) = + callback left_expr; + let (_, not_nulls) = process_condition (mode <> SMStrict) left_expr is_nullable_expr (fun e -> ()) in + List.iter self#get_current_scope#add_to_safety not_nulls; + callback right_expr; + List.iter self#get_current_scope#remove_from_safety not_nulls + (** + Handle boolean OR outside of `if` condition. + *) + method process_or left_expr right_expr is_nullable_expr (callback:texpr->unit) = + let (nulls, _) = process_condition (mode <> SMStrict) left_expr is_nullable_expr callback in + List.iter self#get_current_scope#add_to_safety nulls; + callback right_expr; + List.iter self#get_current_scope#remove_from_safety nulls + (** + Remove subject from the safety list if a nullable value is assigned or if an object with safe field is reassigned. + *) + method handle_assignment is_nullable_expr left_expr (right_expr:texpr) = + if is_suitable (mode <> SMStrict) left_expr then + self#get_current_scope#reassigned left_expr; + if is_nullable_expr right_expr then + match left_expr.eexpr with + | TLocal v -> + let captured = ref false in + let rec traverse (lst:safety_scope list) = + match lst with + | [] -> () + | current :: rest -> + if current#owns_var v then + current#remove_from_safety ~forever:!captured left_expr + else begin + captured := !captured || current#get_type = STClosure; + current#remove_from_safety ~forever:!captured left_expr; + traverse rest + end + in + traverse scopes + | _ -> () + else if is_nullable_type left_expr.etype then + self#get_current_scope#add_to_safety left_expr + end + +(** + This class is used to recursively check typed expressions for null-safety +*) +class expr_checker mode immediate_execution report = + object (self) + val local_safety = new local_safety mode + val mutable return_types = [] + val mutable in_closure = false + (* if this flag is `true` then spotted errors and warnings will not be reported *) + val mutable is_pretending = false + (* val mutable cnt = 0 *) + (** + Get safety mode for this expression checker + *) + method get_mode = mode + (** + Register an error + *) + method error msg (positions:Globals.pos list) = + if not is_pretending then begin + let rec get_first_valid_pos positions = + match positions with + | [] -> null_pos + | p :: rest -> + if p <> null_pos then p + else get_first_valid_pos rest + in + add_error report msg (get_first_valid_pos positions) + end + (** + Check if `e` is nullable even if the type is reported not-nullable. + Haxe type system lies sometimes. + *) + method private is_nullable_expr e = + match e.eexpr with + | TConst TNull -> true + | TConst _ -> false + | TParenthesis e -> self#is_nullable_expr e + | TMeta (m, _) when contains_unsafe_meta [m] -> false + | TMeta (_, e) -> self#is_nullable_expr e + | TThrow _ -> false + | TReturn (Some e) -> self#is_nullable_expr e + | TBinop ((OpAssign | OpAssignOp _), _, right) -> self#is_nullable_expr right + | TBlock exprs -> + (match exprs with + | [] -> false + | _ -> self#is_nullable_expr (List.hd (List.rev exprs)) + ) + | TIf _ -> + let nullable = ref false in + let check body = nullable := !nullable || self#is_nullable_expr body in + local_safety#process_if e self#is_nullable_expr (fun _ -> ()) check; + !nullable + | _ -> + is_nullable_type e.etype && not (local_safety#is_safe e) + (** + Check if `expr` can be passed to a place where `to_type` is expected. + This method has side effect: it logs an error if `expr` has a type parameter incompatible with the type parameter of `to_type`. + E.g.: `Array>` vs `Array` returns `true`, but also adds a compilation error. + *) + method can_pass_expr expr to_type p = + match expr.eexpr, to_type with + | TObjectDecl fields, TAnon to_type -> + List.for_all + (fun ((name, _, _), field_expr) -> + try + let field_to_type = PMap.find name to_type.a_fields in + self#can_pass_expr field_expr field_to_type.cf_type p + with Not_found -> false) + fields + | _, _ -> + if self#is_nullable_expr expr && not (is_nullable_type to_type) then + false + else begin + let expr_type = unfold_null expr.etype in + try + new unificator#unify expr_type to_type; + true + with + | Safety_error err -> + self#error ("Cannot unify " ^ (str_type expr_type) ^ " with " ^ (str_type to_type)) [p; expr.epos]; + (* returning `true` because error is already logged in the line above *) + true + | e -> + fail ~msg:"Null safety unification failure" expr.epos __POS__ + (* can_pass_type expr.etype to_type *) + end + (** + Should be called for the root expressions of a method or for then initialization expressions of fields. + *) + method check_root_expr e = + self#check_expr e; + local_safety#clear; + return_types <- []; + in_closure <- false + (** + Recursively checks an expression + *) + method private check_expr e = + match e.eexpr with + | TConst _ -> () + | TLocal _ -> () + | TArray (arr, idx) -> self#check_array_access arr idx e.epos + | TBinop (op, left_expr, right_expr) -> self#check_binop op left_expr right_expr e.epos + | TField (target, access) -> self#check_field target access e.epos + | TTypeExpr _ -> () + | TParenthesis e -> self#check_expr e + | TObjectDecl fields -> List.iter (fun (_, e) -> self#check_expr e) fields + | TArrayDecl items -> self#check_array_decl items e.etype e.epos + | TCall (callee, args) -> self#check_call callee args e.epos + | TNew _ -> self#check_new e + | TUnop (_, _, expr) -> self#check_unop expr e.epos + | TFunction fn -> self#check_function fn + | TVar (v, init_expr) -> self#check_var v init_expr e.epos + | TBlock exprs -> self#check_block exprs e.epos + | TFor _ -> self#check_for e + | TIf _ -> self#check_if e + | TWhile _ -> self#check_while e + | TSwitch (target, cases, default) -> self#check_switch target cases default e.epos + | TTry (try_block, catches) -> self#check_try try_block catches + | TReturn (Some expr) -> self#check_return expr e.epos + | TReturn None -> () + | TBreak -> () + | TContinue -> () + | TThrow expr -> self#check_throw expr e.epos + | TCast (expr, _) -> self#check_cast expr e.etype e.epos + | TMeta (m, _) when contains_unsafe_meta [m] -> () + | TMeta (_, e) -> self#check_expr e + | TEnumIndex idx -> self#check_enum_index idx e.epos + | TEnumParameter (e, _, _) -> self#check_expr e (** Checking enum value itself is not needed here because this expr always follows after TEnumIndex *) + | TIdent _ -> () + (** + Check expressions in a block + *) + method private check_block exprs p = + match exprs with + | [] -> () + | e :: rest -> + self#check_expr e; + self#check_block rest p + (** + Don't allow to use nullable values as items in declaration of not-nullable arrays + *) + method private check_array_decl items arr_type p = + (match Abstract.follow_with_abstracts arr_type with + | TInst ({ cl_path = ([], "Array") }, [item_type]) -> + List.iter + (fun e -> + if not (self#can_pass_expr e item_type e.epos) then + self#error ("Cannot use nullable value of " ^ (str_type e.etype) ^ " as an item in Array<" ^ (str_type item_type) ^ ">") [e.epos; p] + ) + items; + | _ -> () + ); + List.iter self#check_expr items + (** + Deal with nullable enum values + *) + method private check_enum_index idx p = + if self#is_nullable_expr idx then + self#error "Cannot access nullable enum value." [idx.epos; p]; + self#check_expr idx + (** + Check try...catch + *) + method private check_try try_block catches = + local_safety#process_try try_block catches self#check_expr + (** + Don't use nullable value as a condition in `while` + *) + method private check_while e = + match e.eexpr with + | TWhile _ -> + let check_condition condition = + if self#is_nullable_expr condition then + self#error "Cannot use nullable value as a condition in \"while\"." [condition.epos; e.epos]; + self#check_expr condition + in + local_safety#loop_declared e; + local_safety#process_while + e + self#is_nullable_expr + check_condition + (* self#check_loop_body; *) + (fun handle_condition_effect body -> + self#check_loop_body + (Some handle_condition_effect) + body + ); + local_safety#scope_closed + | _ -> fail ~msg:"Expected TWhile." e.epos __POS__ + (** + Don't iterate on nullable values + *) + method private check_for e = + match e.eexpr with + | TFor (v, iterable, body) -> + if self#is_nullable_expr iterable then + self#error "Cannot iterate over nullable value." [iterable.epos; e.epos]; + self#check_expr iterable; + local_safety#declare_var v; + local_safety#loop_declared e; + self#check_loop_body None body; + local_safety#scope_closed + | _ -> fail ~msg:"Expected TFor." e.epos __POS__ + (** + Handle safety inside of loops + *) + method private check_loop_body (handle_condition_effect:(unit->unit) option) body = + local_safety#process_loop_body + (* Start pretending to ignore errors *) + (fun () -> + is_pretending <- true; + self#check_expr body + ) + handle_condition_effect + (* Now we know, which vars will become unsafe in this loop. Stop pretending and check again *) + (fun () -> + is_pretending <- false; + self#check_expr body; + ) + (** + Don't throw nullable values + *) + method private check_throw e p = + if self#is_nullable_expr e then + self#error "Cannot throw nullable value." [p; e.epos]; + self#check_expr e + (** + Don't cast nullable expressions to not-nullable types + *) + method private check_cast expr to_type p = + self#check_expr expr; + match to_type with + (* untyped cast *) + | TMono _ -> () + (* typed cast and type check *) + | _ -> + if not (self#can_pass_expr expr to_type p) then + self#error "Cannot cast nullable value to not nullable type." [p; expr.epos] + (** + Check safety in a function + *) + method private check_function ?(immediate_execution=false) fn = + local_safety#function_declared immediate_execution fn; + return_types <- fn.tf_type :: return_types; + if immediate_execution || mode = SMLoose then + begin + (* Start pretending to ignore errors *) + is_pretending <- true; + self#check_expr fn.tf_expr; + (* Now we know, which vars will become unsafe in this closure. Stop pretending and perform real check *) + is_pretending <- false; + self#check_expr fn.tf_expr + end + else + self#check_expr fn.tf_expr; + return_types <- List.tl return_types; + local_safety#scope_closed + (** + Don't return nullable values as not-nullable return types. + *) + method private check_return e p = + self#check_expr e; + match return_types with + | t :: _ when not (self#can_pass_expr e t p) -> + self#error ("Cannot return nullable value of " ^ (str_type e.etype) ^ " as " ^ (str_type t)) [p; e.epos] + | _ -> () + (** + Check safety in `switch` expressions. + *) + method private check_switch target cases default p = + if self#is_nullable_expr target then + self#error "Cannot switch on nullable value." [target.epos; p]; + self#check_expr target; + let rec traverse_cases cases = + match cases with + | [] -> () + | (_, body) :: rest -> + self#check_expr body; + traverse_cases rest + in + traverse_cases cases; + match default with + | None -> () + | Some e -> self#check_expr e + (** + Check safety in `if` expressions + *) + method private check_if expr = + let check_condition e = + if self#is_nullable_expr e then + self#error "Cannot use nullable value as condition in \"if\"." [e.epos; expr.epos]; + self#check_expr e + in + local_safety#process_if expr self#is_nullable_expr check_condition self#check_expr + (** + Check array access on nullable values or using nullable indexes + *) + method private check_array_access arr idx p = + if self#is_nullable_expr arr then + self#error "Cannot perform array access on nullable value." [p; arr.epos]; + if self#is_nullable_expr idx then + self#error "Cannot use nullable value as an index for array access." [p; idx.epos]; + self#check_expr arr; + self#check_expr idx + (** + Don't perform unsafe binary operations + *) + method private check_binop op left_expr right_expr p = + let check_both () = + self#check_expr left_expr; + self#check_expr right_expr + in + match op with + | OpEq | OpNotEq -> check_both() + | OpBoolAnd -> + local_safety#process_and left_expr right_expr self#is_nullable_expr self#check_expr + | OpBoolOr -> + local_safety#process_or left_expr right_expr self#is_nullable_expr self#check_expr + (* String concatination is safe if one of operands is safe *) + | OpAdd + | OpAssignOp OpAdd when is_string_type left_expr.etype || is_string_type right_expr.etype -> + check_both(); + if is_nullable_type left_expr.etype && is_nullable_type right_expr.etype then + self#error "Cannot concatenate two nullable values." [p; left_expr.epos; right_expr.epos] + | OpAssign -> + check_both(); + if not (self#can_pass_expr right_expr left_expr.etype p) then + self#error "Cannot assign nullable value here." [p; right_expr.epos; left_expr.epos] + else + local_safety#handle_assignment self#is_nullable_expr left_expr right_expr; + | _-> + if self#is_nullable_expr left_expr || self#is_nullable_expr right_expr then + self#error "Cannot perform binary operation on nullable value." [p; left_expr.epos; right_expr.epos]; + check_both() + (** + Don't perform unops on nullable values + *) + method private check_unop e p = + if self#is_nullable_expr e then + self#error "Cannot perform unary operation on nullable value." [p; e.epos]; + self#check_expr e + (** + Don't assign nullable value to not-nullable variable on var declaration + *) + method private check_var v init p = + local_safety#declare_var v; + match init with + | None -> () + (* Local named functions like `function fn() {}`, which are generated as `var fn = null; fn = function(){}` *) + | Some { eexpr = TConst TNull } when v.v_kind = VUser TVOLocalFunction -> () + | Some e -> + let local = { eexpr = TLocal v; epos = v.v_pos; etype = v.v_type } in + self#check_binop OpAssign local e p + (* self#check_expr e; + local_safety#handle_assignment self#is_nullable_expr local e; + if not (self#can_pass_expr e v.v_type p) then + self#error "Cannot assign nullable value to not-nullable variable." p; *) + (** + Make sure nobody tries to access a field on a nullable value + *) + method private check_field target access p = + if self#is_nullable_expr target then + self#error ("Cannot access \"" ^ accessed_field_name access ^ "\" of a nullable value.") [p; target.epos]; + self#check_expr target + (** + Check constructor invocation: don't pass nulable values to not-nullable arguments + *) + method private check_new e_new = + match e_new.eexpr with + | TNew (cls, params, args) -> + let ctor = + try + Some (get_constructor (fun ctor -> apply_params cls.cl_params params ctor.cf_type) cls) + with + | Not_found -> None + in + (match ctor with + | None -> + List.iter self#check_expr args + | Some (ctor_type, _) -> + let rec traverse t = + match follow t with + | TFun (types, _) -> self#check_args e_new args types + | _ -> fail ~msg:"Unexpected constructor type." e_new.epos __POS__ + in + traverse ctor_type + ) + | _ -> fail ~msg:"TNew expected" e_new.epos __POS__ + (** + Check calls: don't call a nullable value, dont' pass nulable values to not-nullable arguments + *) + method private check_call callee args p = + if self#is_nullable_expr callee then + self#error "Cannot call a nullable value." [callee.epos; p]; + self#check_expr callee; + match follow callee.etype with + | TFun (types, _) -> + self#check_args callee args types + | _ -> + List.iter self#check_expr args + (** + Check if specified expressions can be passed to a call which expects `types`. + *) + method private check_args ?(arg_num=0) callee args types = + match (args, types) with + | (arg :: args, (arg_name, optional, t) :: types) -> + if not optional && not (self#can_pass_expr arg t arg.epos) then begin + let fn_str = match symbol_name callee with "" -> "" | name -> " of function \"" ^ name ^ "\"" + and arg_str = if arg_name = "" then "" else " \"" ^ arg_name ^ "\"" in + self#error ("Cannot pass nullable value to not-nullable argument" ^ arg_str ^ fn_str ^ ".") [arg.epos; callee.epos] + end; + (match arg.eexpr with + | TFunction fn -> + self#check_function ~immediate_execution:(immediate_execution#check callee arg_num) fn + | _ -> + self#check_expr arg + ); + self#check_args ~arg_num:(arg_num + 1) callee args types; + | _ -> () + end + +class class_checker cls immediate_execution report = + let cls_meta = cls.cl_meta @ (match cls.cl_kind with KAbstractImpl a -> a.a_meta | _ -> []) in + object (self) + val is_safe_class = (safety_enabled cls_meta) + val mutable checker = new expr_checker SMLoose immediate_execution report + val mutable mode = None + (** + Entry point for checking a class + *) + method check = + (* if snd cls.cl_path = "AllVarsInitializedInConstructor_thisShouldBeUsable" then + Option.may (fun f -> Option.may (fun e -> print_endline (s_expr (fun t -> "") e)) f.cf_expr) cls.cl_constructor; *) + if is_safe_class && (not cls.cl_extern) && (not cls.cl_interface) then + self#check_var_fields; + let check_field is_static f = + (* if f.cf_name = "wtf_foo" then + Option.may (fun e -> print_endline (s_expr str_type e)) f.cf_expr; *) + match (safety_mode (cls_meta @ f.cf_meta)) with + | SMOff -> () + | mode -> + Option.may ((self#get_checker mode)#check_root_expr) f.cf_expr; + self#check_accessors is_static f + in + if is_safe_class then + Option.may ((self#get_checker (safety_mode cls_meta))#check_root_expr) cls.cl_init; + Option.may (check_field false) cls.cl_constructor; + List.iter (check_field false) cls.cl_ordered_fields; + List.iter (check_field true) cls.cl_ordered_statics; + (** + Check if a getter/setter for non-nullable property return safe values. + E.g. + ``` + var str(get,never):String; + function get_str() return (null:Null); //should fail null safety check + ``` + *) + method private check_accessors is_static field = + match field.cf_kind with + | Var { v_read = read_access; v_write = write_access } when not (is_nullable_type field.cf_type) -> + let fields = if is_static then cls.cl_statics else cls.cl_fields in + let check_accessor prefix = + let accessor = + try Some (PMap.find (prefix ^ field.cf_name) fields) + with Not_found -> None + in + match accessor with + | None -> () + | Some accessor -> + if self#is_in_safety accessor then + match accessor.cf_expr with + | Some ({ eexpr = TFunction fn } as accessor_expr) -> + let fn = { fn with tf_type = field.cf_type } in + (self#get_checker self#class_safety_mode)#check_root_expr { accessor_expr with eexpr = TFunction fn } + | _ -> () + in + if read_access = AccCall then check_accessor "get_"; + if write_access = AccCall then check_accessor "set_" + | _ -> () + (** + Get safety mode for the current class + *) + method private class_safety_mode = + match mode with + | Some mode -> mode + | None -> + let m = safety_mode cls_meta in + mode <- Some m; + m + (** + Get an instance of expression checker with safety mode set to `mode` + *) + method private get_checker mode = + if checker#get_mode <> mode then + checker <- new expr_checker mode immediate_execution report; + checker + (** + Check if field should be checked by null safety + *) + method private is_in_safety field = + (is_safe_class && not (contains_unsafe_meta field.cf_meta)) || safety_enabled field.cf_meta + (** + Check `var` fields are initialized properly + *) + method check_var_fields = + let check_field is_static field = + if should_be_initialized field then + if not (is_nullable_type field.cf_type) && self#is_in_safety field then + match field.cf_expr with + | None -> + if is_static then + checker#error + ("Field \"" ^ field.cf_name ^ "\" is not nullable thus should have an initial value.") + [field.cf_pos] + | Some e -> + if not (checker#can_pass_expr e field.cf_type e.epos) then + checker#error ("Cannot set nullable initial value for not-nullable field \"" ^ field.cf_name ^ "\".") [field.cf_pos] + in + List.iter (check_field false) cls.cl_ordered_fields; + List.iter (check_field true) cls.cl_ordered_statics; + self#check_fields_initialization_in_constructor () + (** + Check instance fields without initial values are properly initialized in constructor + *) + method private check_fields_initialization_in_constructor () = + let fields_to_initialize = Hashtbl.create 20 + (* Compiler-autogenerated local vars for transfering `this` to local functions *) + and this_vars = Hashtbl.create 5 in + List.iter + (fun f -> + if + should_be_initialized f + && not (is_nullable_type f.cf_type) + && not (contains_unsafe_meta f.cf_meta) + then + match f.cf_expr with + | Some _ -> () + | None -> Hashtbl.add fields_to_initialize f.cf_name f + ) + cls.cl_ordered_fields; + let rec check_unsafe_usage init_list safety_enabled e = + if Hashtbl.length init_list > 0 then + match e.eexpr with + | TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) -> + if Hashtbl.mem init_list field.cf_name then + checker#error ("Cannot use field " ^ field.cf_name ^ " until initialization.") [e.epos] + | TField ({ eexpr = TConst TThis }, FClosure (_, field)) -> + checker#error ("Cannot use method " ^ field.cf_name ^ " until all instance fields are initialized.") [e.epos]; + | TCall ({ eexpr = TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) }, args) -> + checker#error ("Cannot call method " ^ field.cf_name ^ " until all instance fields are initialized.") [e.epos]; + List.iter (check_unsafe_usage init_list safety_enabled) args + | TConst TThis when safety_enabled -> + checker#error "Cannot use \"this\" until all instance fields are initialized." [e.epos] + | TLocal v when Hashtbl.mem this_vars v.v_id -> + checker#error "Cannot use \"this\" until all instance fields are initialized." [e.epos] + | TMeta ((Meta.NullSafety, [(EConst (Ident "Off"), _)], _), e) -> + iter (check_unsafe_usage init_list false) e + | TMeta ((Meta.NullSafety, _, _), e) -> + iter (check_unsafe_usage init_list true) e + | _ -> + iter (check_unsafe_usage init_list safety_enabled) e + in + let rec traverse init_list e = + (match e.eexpr with + | TBinop (OpAssign, { eexpr = TField ({ eexpr = TConst TThis }, FInstance (_, _, f)) }, right_expr) -> + Hashtbl.remove init_list f.cf_name; + ignore (traverse init_list right_expr) + | TWhile (condition, body, DoWhile) -> + check_unsafe_usage init_list true condition; + ignore (traverse init_list body) + | TBlock exprs -> + List.iter (fun e -> ignore (traverse init_list e)) exprs + | TIf (_, if_block, Some else_block) -> + let if_init_list = traverse (Hashtbl.copy init_list) if_block + and else_init_list = traverse (Hashtbl.copy init_list) else_block in + Hashtbl.clear init_list; + Hashtbl.iter (Hashtbl.replace init_list) if_init_list; + Hashtbl.iter (Hashtbl.replace init_list) else_init_list + (* var _gthis = this *) + | TVar (v, Some { eexpr = TConst TThis }) -> + Hashtbl.add this_vars v.v_id v + | _ -> + check_unsafe_usage init_list true e + ); + init_list + in + (match cls.cl_constructor with + | Some { cf_expr = Some { eexpr = TFunction { tf_expr = e } } } -> + ignore (traverse fields_to_initialize e); + | _ -> () + ); + Hashtbl.iter + (fun name field -> + checker#error + ("Field \"" ^ name ^ "\" is not nullable thus should have an initial value or should be initialized in constructor.") + [field.cf_pos] + ) + fields_to_initialize + end + +(** + Run null safety checks. +*) +let run (com:Common.context) (types:module_type list) = + let timer = Timer.timer ["null safety"] in + let report = { sr_errors = [] } in + let immediate_execution = new immediate_execution in + let rec traverse module_type = + match module_type with + | TEnumDecl enm -> () + | TTypeDecl typedef -> () + | TAbstractDecl abstr -> () + | TClassDecl cls -> (new class_checker cls immediate_execution report)#check + in + List.iter traverse types; + timer(); + match com.callbacks#get_null_safety_report with + | [] -> + List.iter (fun err -> com.error err.sm_msg err.sm_pos) (List.rev report.sr_errors) + | callbacks -> + let errors = + List.map (fun err -> (err.sm_msg, err.sm_pos)) report.sr_errors + in + List.iter (fun fn -> fn errors) callbacks + +;; diff --git a/src/typing/typeload.ml b/src/typing/typeload.ml index 51db3a8d958..809556c9d6f 100644 --- a/src/typing/typeload.ml +++ b/src/typing/typeload.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -17,391 +17,160 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) +(* Type instance and type parameter handling. *) + open Ast open Common -open Common.DisplayMode +open DisplayTypes.DisplayMode +open DisplayTypes.CompletionResultKind +open CompletionItem +open CompletionModuleType +open CompletionModuleKind +open ClassFieldOrigin +open DisplayException open Type open Typecore open Error open Globals +open Filename -exception Build_canceled of build_state - -let locate_macro_error = ref true let build_count = ref 0 -let transform_abstract_field com this_t a_t a f = - let stat = List.mem AStatic f.cff_access in - let p = f.cff_pos in - match f.cff_kind with - | FProp ((("get" | "never"),_),(("set" | "never"),_),_,_) when not stat -> - (* TODO: hack to avoid issues with abstract property generation on As3 *) - if Common.defined com Define.As3 then f.cff_meta <- (Meta.Extern,[],null_pos) :: f.cff_meta; - { f with cff_access = AStatic :: f.cff_access; cff_meta = (Meta.Impl,[],null_pos) :: f.cff_meta } - | FProp _ when not stat -> - error "Member property accessors must be get/set or never" p; - | FFun fu when fst f.cff_name = "new" && not stat -> - let init p = (EVars [("this",null_pos),Some this_t,None],p) in - let cast e = (ECast(e,None)),pos e in - let ret p = (EReturn (Some (cast (EConst (Ident "this"),p))),p) in - let meta = (Meta.Impl,[],null_pos) :: f.cff_meta in - let meta = if Meta.has Meta.MultiType a.a_meta then begin - if List.mem AInline f.cff_access then error "MultiType constructors cannot be inline" f.cff_pos; - if fu.f_expr <> None then error "MultiType constructors cannot have a body" f.cff_pos; - (Meta.Extern,[],null_pos) :: meta - end else - meta - in - (* We don't want the generated expression positions to shadow the real code. *) - let p = { p with pmax = p.pmin } in - let fu = { - fu with - f_expr = (match fu.f_expr with - | None -> if Meta.has Meta.MultiType a.a_meta then Some (EConst (Ident "null"),p) else None - | Some (EBlock el,_) -> Some (EBlock (init p :: el @ [ret p]),p) - | Some e -> Some (EBlock [init p;e;ret p],p) - ); - f_type = Some a_t; - } in - { f with cff_name = "_new",pos f.cff_name; cff_access = AStatic :: f.cff_access; cff_kind = FFun fu; cff_meta = meta } - | FFun fu when not stat -> - if Meta.has Meta.From f.cff_meta then error "@:from cast functions must be static" f.cff_pos; - let fu = { fu with f_args = (if List.mem AMacro f.cff_access then fu.f_args else (("this",null_pos),false,[],Some this_t,None) :: fu.f_args) } in - { f with cff_kind = FFun fu; cff_access = AStatic :: f.cff_access; cff_meta = (Meta.Impl,[],null_pos) :: f.cff_meta } - | _ -> - f - -let get_policy ctx mpath = - let sl1 = full_dot_path mpath mpath in - List.fold_left (fun acc (sl2,policy,recursive) -> if match_path recursive sl1 sl2 then policy @ acc else acc) [] ctx.g.module_check_policies - -let make_module ctx mpath file loadp = - let m = { - m_id = alloc_mid(); - m_path = mpath; - m_types = []; - m_extra = module_extra (Path.unique_full_path file) (Define.get_signature ctx.com.defines) (file_time file) (if ctx.in_macro then MMacro else MCode) (get_policy ctx mpath); - } in - m - -(* - Build module structure : should be atomic - no type loading is possible -*) -let module_pass_1 ctx m tdecls loadp = - let com = ctx.com in - let decls = ref [] in - let make_path name priv = - if List.exists (fun (t,_) -> snd (t_path t) = name) !decls then error ("Type name " ^ name ^ " is already defined in this module") loadp; - if priv then (fst m.m_path @ ["_" ^ snd m.m_path], name) else (fst m.m_path, name) - in - let pt = ref None in - let rec make_decl acc decl = - let p = snd decl in - let acc = (match fst decl with - | EImport _ | EUsing _ -> - (match !pt with - | None -> acc - | Some _ -> error "import and using may not appear after a type declaration" p) - | EClass d -> - let name = fst d.d_name in - if String.length name > 0 && name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; - pt := Some p; - let priv = List.mem HPrivate d.d_flags in - let path = make_path name priv in - let c = mk_class m path p (pos d.d_name) in - (* we shouldn't load any other type until we propertly set cl_build *) - c.cl_build <- (fun() -> error (s_type_path c.cl_path ^ " is not ready to be accessed, separate your type declarations in several files") p); - c.cl_module <- m; - c.cl_private <- priv; - c.cl_doc <- d.d_doc; - c.cl_meta <- d.d_meta; - decls := (TClassDecl c, decl) :: !decls; - acc - | EEnum d -> - let name = fst d.d_name in - if String.length name > 0 && name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; - pt := Some p; - let priv = List.mem EPrivate d.d_flags in - let path = make_path name priv in - let e = { - e_path = path; - e_module = m; - e_pos = p; - e_name_pos = (pos d.d_name); - e_doc = d.d_doc; - e_meta = d.d_meta; - e_params = []; - e_private = priv; - e_extern = List.mem EExtern d.d_flags; - e_constrs = PMap.empty; - e_names = []; - e_type = { - t_path = [], "Enum<" ^ (s_type_path path) ^ ">"; - t_module = m; - t_doc = None; - t_pos = p; - t_name_pos = null_pos; - t_type = mk_mono(); - t_private = true; - t_params = []; - t_meta = []; - }; - } in - decls := (TEnumDecl e, decl) :: !decls; - acc - | ETypedef d -> - let name = fst d.d_name in - if String.length name > 0 && name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; - pt := Some p; - let priv = List.mem EPrivate d.d_flags in - let path = make_path name priv in - let t = { - t_path = path; - t_module = m; - t_pos = p; - t_name_pos = pos d.d_name; - t_doc = d.d_doc; - t_private = priv; - t_params = []; - t_type = mk_mono(); - t_meta = d.d_meta; - } in - (* failsafe in case the typedef is not initialized (see #3933) *) - delay ctx PBuildModule (fun () -> - match t.t_type with - | TMono r -> (match !r with None -> r := Some com.basic.tvoid | _ -> ()) - | _ -> () - ); - decls := (TTypeDecl t, decl) :: !decls; - acc - | EAbstract d -> - let name = fst d.d_name in - if String.length name > 0 && name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; - let priv = List.mem APrivAbstract d.d_flags in - let path = make_path name priv in - let a = { - a_path = path; - a_private = priv; - a_module = m; - a_pos = p; - a_name_pos = pos d.d_name; - a_doc = d.d_doc; - a_params = []; - a_meta = d.d_meta; - a_from = []; - a_to = []; - a_from_field = []; - a_to_field = []; - a_ops = []; - a_unops = []; - a_impl = None; - a_array = []; - a_this = mk_mono(); - a_resolve = None; - } in - decls := (TAbstractDecl a, decl) :: !decls; - match d.d_data with - | [] when Meta.has Meta.CoreType a.a_meta -> - a.a_this <- t_dynamic; - acc - | fields -> - let a_t = - let params = List.map (fun t -> TPType (CTPath { tname = fst t.tp_name; tparams = []; tsub = None; tpackage = [] },null_pos)) d.d_params in - CTPath { tpackage = []; tname = fst d.d_name; tparams = params; tsub = None },null_pos - in - let rec loop = function - | [] -> a_t - | AIsType t :: _ -> t - | _ :: l -> loop l - in - let this_t = loop d.d_flags in - let fields = List.map (transform_abstract_field com this_t a_t a) fields in - let meta = ref [] in - if has_meta Meta.Dce a.a_meta then meta := (Meta.Dce,[],null_pos) :: !meta; - let acc = make_decl acc (EClass { d_name = (fst d.d_name) ^ "_Impl_",snd d.d_name; d_flags = [HPrivate]; d_data = fields; d_doc = None; d_params = []; d_meta = !meta },p) in - (match !decls with - | (TClassDecl c,_) :: _ -> - List.iter (fun m -> match m with - | ((Meta.Build | Meta.CoreApi | Meta.Allow | Meta.Access | Meta.Enum | Meta.Dce | Meta.Native | Meta.JsRequire | Meta.PythonImport | Meta.Expose | Meta.Deprecated | Meta.PhpGlobal),_,_) -> - c.cl_meta <- m :: c.cl_meta; - | _ -> - () - ) a.a_meta; - a.a_impl <- Some c; - c.cl_kind <- KAbstractImpl a; - c.cl_meta <- (Meta.Final,[],null_pos) :: c.cl_meta - | _ -> assert false); - acc - ) in - decl :: acc - in - let tdecls = List.fold_left make_decl [] tdecls in - let decls = List.rev !decls in - decls, List.rev tdecls - -let parse_file_from_lexbuf com file p lexbuf = - let t = Common.timer ["parsing"] in - Lexer.init file true; - incr stats.s_files_parsed; - let data = try - ParserEntry.parse com.defines lexbuf - with - | Sedlexing.MalFormed -> - t(); - error "Malformed file. Source files must be encoded with UTF-8." {pfile = file; pmin = 0; pmax = 0} - | e -> - t(); - raise e - in - begin match !display_default with - | DMModuleSymbols filter when filter <> None || Display.is_display_file file -> - let ds = Display.DocumentSymbols.collect_module_symbols data in - com.shared.shared_display_information.document_symbols <- (file,ds) :: com.shared.shared_display_information.document_symbols; - | _ -> - () - end; - t(); - Common.log com ("Parsed " ^ file); - data - -let parse_file_from_string com file p string = - parse_file_from_lexbuf com file p (Sedlexing.Utf8.from_string string) - -let current_stdin = ref None (* TODO: we're supposed to clear this at some point *) +let type_function_params_rec = ref (fun _ _ _ _ -> assert false) -let parse_file com file p = - let use_stdin = (Common.defined com Define.DisplayStdin) && Display.is_display_file file in - if use_stdin then - let s = - match !current_stdin with - | Some s -> - s - | None -> - let s = Std.input_all stdin in - close_in stdin; - current_stdin := Some s; - s +let check_field_access ctx cff = + let display_access = ref None in + let rec loop p0 acc l = + let check_display p1 = + let pmid = {p0 with pmin = p0.pmax; pmax = p1.pmin} in + if DisplayPosition.display_position#enclosed_in pmid then match acc with + | access :: _ -> display_access := Some access; + | [] -> () in - parse_file_from_string com file p s - else - let ch = try open_in_bin file with _ -> error ("Could not open " ^ file) p in - Std.finally (fun() -> close_in ch) (parse_file_from_lexbuf com file p) (Sedlexing.Utf8.from_channel ch) - -let parse_hook = ref parse_file -let type_module_hook = ref (fun _ _ _ -> None) -let type_function_params_rec = ref (fun _ _ _ _ -> assert false) -let return_partial_type = ref false + match l with + | [] -> + (* This is a bit dodgy. Ideally we would use the position of the `function` keyword, but we don't have that... + Using the name means this is going to complete within the `function` keyword too. Not sure what we + can do about it. *) + check_display (pos (cff.cff_name)) + | (access,p1) :: l -> + check_display p1; + try + let _,p2 = List.find (fun (access',_) -> access = access') acc in + if p1 <> null_pos && p2 <> null_pos then begin + display_error ctx (Printf.sprintf "Duplicate access modifier %s" (Ast.s_access access)) p1; + display_error ctx "Previously defined here" p2; + end; + loop p1 acc l + with Not_found -> match access with + | APublic | APrivate -> + begin try + let _,p2 = List.find (fun (access',_) -> match access' with APublic | APrivate -> true | _ -> false) acc in + display_error ctx (Printf.sprintf "Conflicting access modifier %s" (Ast.s_access access)) p1; + display_error ctx "Conflicts with this" p2; + loop p1 acc l + with Not_found -> + loop p1 ((access,p1) :: acc) l + end + | _ -> + loop p1 ((access,p1) :: acc) l + in + let pmin = {cff.cff_pos with pmax = cff.cff_pos.pmin} in + loop pmin [] cff.cff_access; + !display_access -let type_function_arg ctx t e opt p = - if opt then - let e = (match e with None -> Some (EConst (Ident "null"),p) | _ -> e) in - ctx.t.tnull t, e - else - let t = match e with Some (EConst (Ident "null"),p) -> ctx.t.tnull t | _ -> t in - t, e +let find_type_in_module m tname = + List.find (fun mt -> + let infos = t_infos mt in + not infos.mt_private && snd infos.mt_path = tname + ) m.m_types -let type_var_field ctx t e stat do_display p = - if stat then ctx.curfun <- FunStatic else ctx.curfun <- FunMember; - let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in - let e = type_expr ctx e (WithType t) in - let e = (!cast_or_unify_ref) ctx t e p in - match t with - | TType ({ t_path = ([],"UInt") },[]) | TAbstract ({ a_path = ([],"UInt") },[]) when stat -> { e with etype = t } - | _ -> e +(* raises Module_not_found or Type_not_found *) +let load_type_raise ctx mpath tname p = + let m = ctx.g.do_load_module ctx mpath p in + try + find_type_in_module m tname + with Not_found -> + raise_error (Type_not_found(mpath,tname)) p -let apply_macro ctx mode path el p = - let cpath, meth = (match List.rev (ExtString.String.nsplit path ".") with - | meth :: name :: pack -> (List.rev pack,name), meth - | _ -> error "Invalid macro path" p - ) in - ctx.g.do_macro ctx mode cpath meth el p +(* raises Not_found *) +let load_type ctx mpath tname p = try + load_type_raise ctx mpath tname p +with Error((Module_not_found _ | Type_not_found _),p2) when p = p2 -> + raise Not_found (** since load_type_def and load_instance are used in PASS2, they should not access the structure of a type **) (* load a type or a subtype definition *) -let rec load_type_def ctx p t = +let load_type_def ctx p t = let no_pack = t.tpackage = [] in + if t = Parser.magic_type_path then raise_fields (DisplayToplevel.collect ctx TKType NoValue) CRTypeHint None; + (* The type name is the module name or the module sub-type name *) let tname = (match t.tsub with None -> t.tname | Some n -> n) in - if tname = "" then raise (Display.DisplayToplevel (Display.ToplevelCollector.run ctx true)); try + (* If there's a sub-type, there's no reason to look in our module or its imports *) if t.tsub <> None then raise Not_found; let path_matches t2 = let tp = t_path t2 in tp = (t.tpackage,tname) || (no_pack && snd tp = tname) in try + (* Check the types in our own module *) List.find path_matches ctx.m.curmod.m_types with Not_found -> + (* Check the local imports *) let t,pi = List.find (fun (t2,pi) -> path_matches t2) ctx.m.module_types in - Display.ImportHandling.mark_import_position ctx.com pi; + ImportHandling.mark_import_position ctx.com pi; t with - Not_found -> - let next() = - let t, m = (try - t, ctx.g.do_load_module ctx (t.tpackage,t.tname) p - with Error (Module_not_found _,p2) as e when p == p2 -> - match t.tpackage with - | "std" :: l -> - let t = { t with tpackage = l } in - t, ctx.g.do_load_module ctx (t.tpackage,t.tname) p - | _ -> raise e - ) in - let tpath = (t.tpackage,tname) in - try - List.find (fun t -> not (t_infos t).mt_private && t_path t = tpath) m.m_types - with - Not_found -> raise (Error (Type_not_found (m.m_path,tname),p)) + | Not_found when no_pack -> + (* Unqualified *) + begin try + let rec loop l = match l with + | [] -> + raise Exit + | (pack,ppack) :: l -> + begin try + let mt = load_type ctx (pack,t.tname) tname p in + ImportHandling.mark_import_position ctx.com ppack; + mt + with Not_found -> + loop l + end in - (* lookup in wildcard imported packages *) - try - if not no_pack then raise Exit; - let rec loop l = match l with - | [] -> raise Exit - | (wp,pi) :: l -> - try - let t = load_type_def ctx p { t with tpackage = wp } in - Display.ImportHandling.mark_import_position ctx.com pi; - t - with - | Error (Module_not_found _,p2) - | Error (Type_not_found _,p2) when p == p2 -> loop l - in - loop ctx.m.wildcard_packages - with Exit -> - (* lookup in our own package - and its upper packages *) - let rec loop = function - | [] -> raise Exit - | (_ :: lnext) as l -> - try - load_type_def ctx p { t with tpackage = List.rev l } - with - | Error (Module_not_found _,p2) - | Error (Type_not_found _,p2) when p == p2 -> loop lnext + (* Check wildcard packages by using their package *) + loop ctx.m.wildcard_packages + with Exit -> + let rec loop l = match l with + | [] -> + load_type_raise ctx ([],t.tname) tname p + | _ :: sl as l -> + (try load_type ctx (List.rev l,t.tname) tname p with Not_found -> loop sl) in - try - if not no_pack then raise Exit; - (match fst ctx.m.curmod.m_path with - | [] -> raise Exit - | x :: _ -> - (* this can occur due to haxe remoting : a module can be - already defined in the "js" package and is not allowed - to access the js classes *) - try - (match PMap.find x ctx.com.package_rules with - | Forbidden -> raise Exit - | _ -> ()) - with Not_found -> ()); - loop (List.rev (fst ctx.m.curmod.m_path)); - with - Exit -> next() + (* Check our current module's path and its parent paths *) + loop (List.rev (fst ctx.m.curmod.m_path)) + end + | Not_found -> + (* Qualified *) + try + (* Try loading the fully qualified module *) + load_type_raise ctx (t.tpackage,t.tname) tname p + with Error((Module_not_found _ | Type_not_found _),_) as exc -> match t.tpackage with + | "std" :: l -> + load_type_raise ctx (l,t.tname) tname p + | _ -> + raise exc + +(* let load_type_def ctx p t = + let timer = Timer.timer ["typing";"load_type_def"] in + Std.finally timer (load_type_def ctx p) t *) let resolve_position_by_path ctx path p = let mt = load_type_def ctx p path in let p = (t_infos mt).mt_pos in - raise (Display.DisplayPosition [p]) + raise_positions [p] let check_param_constraints ctx types t pl c p = match follow t with @@ -420,28 +189,54 @@ let check_param_constraints ctx types t pl c p = try unify_raise ctx t ti p with Error(Unify l,p) -> - if not ctx.untyped then display_error ctx (error_msg (Unify (Constraint_failure (s_type_path c.cl_path) :: l))) p; + let fail() = + if not ctx.untyped then display_error ctx (error_msg (Unify (Constraint_failure (s_type_path c.cl_path) :: l))) p; + in + match follow t with + | TInst({cl_kind = KExpr e},_) -> + let e = type_expr {ctx with locals = PMap.empty} e (WithType.with_type ti) in + begin try unify_raise ctx e.etype ti p + with Error (Unify _,_) -> fail() end + | _ -> + fail() + ) ctl -let requires_value_meta com co = - Common.defined com Define.DocGen || (match co with - | None -> false - | Some c -> c.cl_extern || Meta.has Meta.Rtti c.cl_meta) +let generate_value_meta com co fadd args = + let values = List.fold_left (fun acc ((name,p),_,_,_,eo) -> match eo with Some e -> ((name,p,NoQuotes),e) :: acc | _ -> acc) [] args in + match values with + | [] -> () + | _ -> fadd (Meta.Value,[EObjectDecl values,null_pos],null_pos) -let generate_value_meta com co cf args = - if requires_value_meta com co then begin - let values = List.fold_left (fun acc ((name,p),_,_,_,eo) -> match eo with Some e -> ((name,p,NoQuotes),e) :: acc | _ -> acc) [] args in - match values with - | [] -> () - | _ -> cf.cf_meta <- ((Meta.Value,[EObjectDecl values,cf.cf_pos],null_pos) :: cf.cf_meta) - end +let is_redefined ctx cf1 fields p = + try + let cf2 = PMap.find cf1.cf_name fields in + let st = s_type (print_context()) in + if not (type_iseq cf1.cf_type cf2.cf_type) then begin + display_error ctx ("Cannot redefine field " ^ cf1.cf_name ^ " with different type") p; + display_error ctx ("First type was " ^ (st cf1.cf_type)) cf1.cf_pos; + error ("Second type was " ^ (st cf2.cf_type)) cf2.cf_pos + end else + true + with Not_found -> + false -let pselect p1 p2 = - if p1 = null_pos then p2 else p1 +let make_extension_type ctx tl p = + let mk_extension fields t = match follow t with + | TAnon a -> + PMap.fold (fun cf fields -> + if not (is_redefined ctx cf fields p) then PMap.add cf.cf_name cf fields + else fields + ) a.a_fields fields + | _ -> + error "Can only extend structures" p + in + let fields = List.fold_left mk_extension PMap.empty tl in + let ta = TAnon { a_fields = fields; a_status = ref (Extend tl); } in + ta (* build an instance from a full type *) -let rec load_instance ?(allow_display=false) ctx (t,pn) allow_no_params p = - let p = pselect pn p in +let rec load_instance' ctx (t,p) allow_no_params = let t = try if t.tpackage <> [] || t.tsub <> None then raise Not_found; let pt = List.assoc t.tname ctx.type_params in @@ -452,6 +247,18 @@ let rec load_instance ?(allow_display=false) ctx (t,pn) allow_no_params p = let is_generic,is_generic_build = match mt with | TClassDecl {cl_kind = KGeneric} -> true,false | TClassDecl {cl_kind = KGenericBuild _} -> false,true + | TTypeDecl td -> + if not (Common.defined ctx.com Define.NoDeprecationWarnings) then + begin try + let msg = match Meta.get Meta.Deprecated td.t_meta with + | _,[EConst(String s),_],_ -> s + | _ -> "This typedef is deprecated in favor of " ^ (s_type (print_context()) td.t_type) + in + DeprecationCheck.warn_deprecation ctx.com msg p + with Not_found -> + () + end; + false,false | _ -> false,false in let types , path , f = ctx.g.do_build_instance ctx mt p in @@ -470,7 +277,7 @@ let rec load_instance ?(allow_display=false) ctx (t,pn) allow_no_params p = end else if path = ([],"Dynamic") then match t.tparams with | [] -> t_dynamic - | [TPType t] -> TDynamic (load_complex_type ctx true p t) + | [TPType t] -> TDynamic (load_complex_type ctx true t) | _ -> error "Too many parameters for Dynamic" p else begin if not is_rest && ctx.com.display.dms_error_policy <> EPIgnore && List.length types <> List.length t.tparams then error ("Invalid number of type parameters for " ^ s_type_path path) p; @@ -481,12 +288,15 @@ let rec load_instance ?(allow_display=false) ctx (t,pn) allow_no_params p = | EConst (String s) -> "S" ^ s | EConst (Int i) -> "I" ^ i | EConst (Float f) -> "F" ^ f + | EDisplay _ -> + ignore(type_expr ctx e WithType.value); + "Expr" | _ -> "Expr" ) in - let c = mk_class null_module ([],name) p (pos e) in + let c = mk_class ctx.m.curmod ([],name) p (pos e) in c.cl_kind <- KExpr e; TInst (c,[]) - | TPType t -> load_complex_type ctx true p t + | TPType t -> load_complex_type ctx true t ) t.tparams in let rec loop tl1 tl2 is_rest = match tl1,tl2 with | t :: tl1,(name,t2) :: tl2 -> @@ -527,6 +337,8 @@ let rec load_instance ?(allow_display=false) ctx (t,pn) allow_no_params p = | t :: tl,[] -> if is_rest then t :: loop tl [] true + else if ctx.com.display.dms_error_policy = EPIgnore then + [] else error ("Too many parameters for " ^ s_type_path path) p in @@ -534,34 +346,49 @@ let rec load_instance ?(allow_display=false) ctx (t,pn) allow_no_params p = f params end in - if allow_display then Display.DisplayEmitter.check_display_type ctx t pn; t +and load_instance ctx ?(allow_display=false) (t,pn) allow_no_params = + try + let t = load_instance' ctx (t,pn) allow_no_params in + if allow_display then DisplayEmitter.check_display_type ctx t pn; + t + with Error (Module_not_found path,_) when (ctx.com.display.dms_kind = DMDefault) && DisplayPosition.display_position#enclosed_in pn -> + let s = s_type_path path in + DisplayToplevel.collect_and_raise ctx TKType NoValue CRTypeHint (s,pn) (Some {pn with pmin = pn.pmax - String.length s;}) + (* build an instance from a complex type *) -and load_complex_type ctx allow_display p (t,pn) = - let p = pselect pn p in +and load_complex_type' ctx allow_display (t,p) = match t with - | CTParent t -> load_complex_type ctx allow_display p t - | CTPath t -> load_instance ~allow_display ctx (t,pn) false p + | CTParent t -> load_complex_type ctx allow_display t + | CTPath t -> load_instance ~allow_display ctx (t,p) false | CTOptional _ -> error "Optional type not allowed here" p + | CTNamed _ -> error "Named type not allowed here" p + | CTIntersection tl -> + let tl = List.map (fun (t,pn) -> + try + load_complex_type ctx allow_display (t,pn) + with DisplayException(DisplayFields Some({fkind = CRTypeHint} as r)) -> + let l = List.filter (fun item -> match item.ci_kind with + | ITType({kind = Struct},_) -> true + | _ -> false + ) r.fitems in + raise_fields l (CRStructExtension true) r.finsert_pos + ) tl in + let tr = ref None in + let t = TMono tr in + let r = exc_protect ctx (fun r -> + r := lazy_processing (fun() -> t); + let ta = make_extension_type ctx tl p in + tr := Some ta; + ta + ) "constraint" in + TLazy r | CTExtend (tl,l) -> - (match load_complex_type ctx allow_display p (CTAnonymous l,p) with + begin match load_complex_type ctx allow_display (CTAnonymous l,p) with | TAnon a as ta -> - let is_redefined cf1 a2 = - try - let cf2 = PMap.find cf1.cf_name a2.a_fields in - let st = s_type (print_context()) in - if not (type_iseq cf1.cf_type cf2.cf_type) then begin - display_error ctx ("Cannot redefine field " ^ cf1.cf_name ^ " with different type") p; - display_error ctx ("First type was " ^ (st cf1.cf_type)) cf1.cf_pos; - error ("Second type was " ^ (st cf2.cf_type)) cf2.cf_pos - end else - true - with Not_found -> - false - in let mk_extension t = match follow t with | TInst ({cl_kind = KTypeParameter _},_) -> @@ -569,20 +396,29 @@ and load_complex_type ctx allow_display p (t,pn) = | TMono _ -> error "Loop found in cascading signatures definitions. Please change order/import" p | TAnon a2 -> - PMap.iter (fun _ cf -> ignore(is_redefined cf a2)) a.a_fields; + PMap.iter (fun _ cf -> ignore(is_redefined ctx cf a2.a_fields p)) a.a_fields; TAnon { a_fields = (PMap.foldi PMap.add a.a_fields a2.a_fields); a_status = ref (Extend [t]); } | _ -> error "Can only extend structures" p in let loop t = match follow t with | TAnon a2 -> PMap.iter (fun f cf -> - if not (is_redefined cf a) then + if not (is_redefined ctx cf a.a_fields p) then a.a_fields <- PMap.add f cf a.a_fields ) a2.a_fields | _ -> error "Can only extend structures" p in - let il = List.map (fun (t,pn) -> load_instance ctx ~allow_display (t,pn) false p) tl in + let il = List.map (fun (t,pn) -> + try + load_instance ctx ~allow_display (t,pn) false + with DisplayException(DisplayFields Some({fkind = CRTypeHint} as r)) -> + let l = List.filter (fun item -> match item.ci_kind with + | ITType({kind = Struct},_) -> true + | _ -> false + ) r.fitems in + raise_fields l (CRStructExtension false) r.finsert_pos + ) tl in let tr = ref None in let t = TMono tr in let r = exc_protect ctx (fun r -> @@ -597,15 +433,17 @@ and load_complex_type ctx allow_display p (t,pn) = t ) "constraint" in TLazy r - | _ -> assert false) + | _ -> assert false + end | CTAnonymous l -> + let displayed_field = ref None in let rec loop acc f = let n = fst f.cff_name in let p = f.cff_pos in if PMap.mem n acc then error ("Duplicate field declaration : " ^ n) p; let topt = function | None -> error ("Explicit type required for field " ^ n) p - | Some t -> load_complex_type ctx allow_display p t + | Some t -> load_complex_type ctx allow_display t in if n = "new" then ctx.com.warning "Structures with new are deprecated, use haxe.Constraints.Constructible instead" p; let no_expr = function @@ -615,14 +453,25 @@ and load_complex_type ctx allow_display p (t,pn) = let pub = ref true in let dyn = ref false in let params = ref [] in + let final = ref false in + ignore(check_field_access ctx f); (* TODO: do we want to do anything with this? *) List.iter (fun a -> - match a with + match fst a with | APublic -> () - | APrivate -> pub := false; + | APrivate -> + let p = pos a in + if Filename.basename p.pfile <> "NativeIterable.hx" then (* Terrible workaround for #7436 *) + ctx.com.warning "private structure fields are deprecated" p; + pub := false; | ADynamic when (match f.cff_kind with FFun _ -> true | _ -> false) -> dyn := true - | AStatic | AOverride | AInline | ADynamic | AMacro | AFinal -> error ("Invalid access " ^ Ast.s_access a) p + | AFinal -> final := true + | AStatic | AOverride | AInline | ADynamic | AMacro | AExtern as a -> error ("Invalid access " ^ Ast.s_access a) p ) f.cff_access; let t , access = (match f.cff_kind with + | FVar(t,e) when !final -> + no_expr e; + let t = (match t with None -> error "Type required for structure property" p | Some t -> t) in + load_complex_type ctx allow_display t, Var { v_read = AccNormal; v_write = AccNever } | FVar (Some (CTPath({tpackage=[];tname="Void"}),_), _) | FProp (_,_,Some (CTPath({tpackage=[];tname="Void"}),_),_) -> error "Fields of type Void are not allowed in structures" p | FVar (t, e) -> @@ -653,34 +502,54 @@ and load_complex_type ctx allow_display p (t,pn) = error "Custom property access is no longer supported in Haxe 3" f.cff_pos; in let t = (match t with None -> error "Type required for structure property" p | Some t -> t) in - load_complex_type ctx allow_display p t, Var { v_read = access i1 true; v_write = access i2 false } + load_complex_type ctx allow_display t, Var { v_read = access i1 true; v_write = access i2 false } ) in let t = if Meta.has Meta.Optional f.cff_meta then ctx.t.tnull t else t in let cf = { - (mk_field n t p (pos f.cff_name)) with - cf_public = !pub; + (mk_field n ~public:!pub t p (pos f.cff_name)) with cf_kind = access; cf_params = !params; cf_doc = f.cff_doc; cf_meta = f.cff_meta; } in + if !final then add_class_field_flag cf CfFinal; init_meta_overloads ctx None cf; if ctx.is_display_file then begin - Display.DisplayEmitter.check_display_metadata ctx cf.cf_meta; - Display.DisplayEmitter.maybe_display_field ctx (cf.cf_name_pos) cf; + DisplayEmitter.check_display_metadata ctx cf.cf_meta; + if DisplayPosition.display_position#enclosed_in cf.cf_name_pos then displayed_field := Some cf; end; PMap.add n cf acc in - mk_anon (List.fold_left loop PMap.empty l) + let a = { a_fields = (List.fold_left loop PMap.empty l); a_status = ref Closed; } in + begin match !displayed_field with + | None -> + () + | Some cf -> + delay ctx PBuildClass (fun () -> DisplayEmitter.display_field ctx (AnonymousStructure a) CFSMember cf cf.cf_name_pos); + end; + TAnon a | CTFunction (args,r) -> match args with | [CTPath { tpackage = []; tparams = []; tname = "Void" },_] -> - TFun ([],load_complex_type ctx allow_display p r) + TFun ([],load_complex_type ctx allow_display r) | _ -> TFun (List.map (fun t -> - let t, opt = (match fst t with CTOptional t -> t, true | _ -> t,false) in - "",opt,load_complex_type ctx allow_display p t - ) args,load_complex_type ctx allow_display p r) + let t, opt = (match fst t with CTOptional t | CTParent((CTOptional t,_)) -> t, true | _ -> t,false) in + let n,t = (match fst t with CTNamed (n,t) -> (fst n), t | _ -> "", t) in + n,opt,load_complex_type ctx allow_display t + ) args,load_complex_type ctx allow_display r) + +and load_complex_type ctx allow_display (t,pn) = + try + load_complex_type' ctx allow_display (t,pn) + with Error(Module_not_found(([],name)),p) as exc -> + if Diagnostics.is_diagnostics_run p then begin + delay ctx PForce (fun () -> DisplayToplevel.handle_unresolved_identifier ctx name p true); + t_dynamic + end else if ctx.com.display.dms_display && not (DisplayPosition.display_position#enclosed_in pn) then + t_dynamic + else + raise exc and init_meta_overloads ctx co cf = let overloads = ref [] in @@ -700,10 +569,10 @@ and init_meta_overloads ctx co cf = | l -> ctx.type_params <- List.filter (fun t -> not (List.mem t l)) ctx.type_params); let params = (!type_function_params_rec) ctx f cf.cf_name p in ctx.type_params <- params @ ctx.type_params; - let topt = function None -> error "Explicit type required" p | Some t -> load_complex_type ctx true p t in - let args = List.map (fun ((a,_),opt,_,t,_) -> a,opt,topt t) f.f_args in + let topt = function None -> error "Explicit type required" p | Some t -> load_complex_type ctx true t in + let args = List.map (fun ((a,_),opt,_,t,cto) -> a,opt || cto <> None,topt t) f.f_args in let cf = { cf with cf_type = TFun (args,topt f.f_type); cf_params = params; cf_meta = cf_meta} in - generate_value_meta ctx.com co cf f.f_args; + generate_value_meta ctx.com co (fun meta -> cf.cf_meta <- meta :: cf.cf_meta) f.f_args; overloads := cf :: !overloads; ctx.type_params <- old; false @@ -747,7 +616,7 @@ let hide_params ctx = *) let load_core_type ctx name = let show = hide_params ctx in - let t = load_instance ctx ({ tpackage = []; tname = name; tparams = []; tsub = None; },null_pos) false null_pos in + let t = load_instance ctx ({ tpackage = []; tname = name; tparams = []; tsub = None; },null_pos) false in show(); add_dependency ctx.m.curmod (match t with | TInst (c,_) -> c.cl_module @@ -775,326 +644,13 @@ let t_iterator ctx = let load_type_hint ?(opt=false) ctx pcur t = let t = match t with | None -> mk_mono() - | Some (t,p) -> - try - load_complex_type ctx true pcur (t,p) - with Error(Module_not_found(([],name)),p) as exc -> - if Display.Diagnostics.is_diagnostics_run ctx then Display.ToplevelCollector.handle_unresolved_identifier ctx name p true; - (* Default to Dynamic in display mode *) - if ctx.com.display.dms_display then t_dynamic else raise exc + | Some (t,p) -> load_complex_type ctx true (t,p) in if opt then ctx.t.tnull t else t -(* ---------------------------------------------------------------------- *) -(* Structure check *) - -let valid_redefinition ctx f1 t1 f2 t2 = (* child, parent *) - let valid t1 t2 = - Type.unify t1 t2; - if is_null t1 <> is_null t2 || ((follow t1) == t_dynamic && (follow t2) != t_dynamic) then raise (Unify_error [Cannot_unify (t1,t2)]); - in - let open OptimizerTexpr in - begin match PurityState.get_purity_from_meta f2.cf_meta,PurityState.get_purity_from_meta f1.cf_meta with - | PurityState.Pure,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),f2.cf_pos],null_pos) :: f1.cf_meta - | PurityState.ExpectPure p,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),p],null_pos) :: f1.cf_meta - | _ -> () - end; - let t1, t2 = (match f1.cf_params, f2.cf_params with - | [], [] -> t1, t2 - | l1, l2 when List.length l1 = List.length l2 -> - let to_check = ref [] in - let monos = List.map2 (fun (name,p1) (_,p2) -> - (match follow p1, follow p2 with - | TInst ({ cl_kind = KTypeParameter ct1 } as c1,pl1), TInst ({ cl_kind = KTypeParameter ct2 } as c2,pl2) -> - (match ct1, ct2 with - | [], [] -> () - | _, _ when List.length ct1 = List.length ct2 -> - (* if same constraints, they are the same type *) - let check monos = - List.iter2 (fun t1 t2 -> - try - let t1 = apply_params l1 monos (apply_params c1.cl_params pl1 t1) in - let t2 = apply_params l2 monos (apply_params c2.cl_params pl2 t2) in - type_eq EqStrict t1 t2 - with Unify_error l -> - raise (Unify_error (Unify_custom "Constraints differ" :: l)) - ) ct1 ct2 - in - to_check := check :: !to_check; - | _ -> - raise (Unify_error [Unify_custom "Different number of constraints"])) - | _ -> ()); - TInst (mk_class null_module ([],name) null_pos null_pos,[]) - ) l1 l2 in - List.iter (fun f -> f monos) !to_check; - apply_params l1 monos t1, apply_params l2 monos t2 - | _ -> - (* ignore type params, will create other errors later *) - t1, t2 - ) in - match f1.cf_kind,f2.cf_kind with - | Method m1, Method m2 when not (m1 = MethDynamic) && not (m2 = MethDynamic) -> - begin match follow t1, follow t2 with - | TFun (args1,r1) , TFun (args2,r2) -> ( - if not (List.length args1 = List.length args2) then raise (Unify_error [Unify_custom "Different number of function arguments"]); - try - List.iter2 (fun (n,o1,a1) (_,o2,a2) -> - if o1 <> o2 then raise (Unify_error [Not_matching_optional n]); - (try valid a2 a1 with Unify_error _ -> raise (Unify_error [Cannot_unify(a1,a2)])) - ) args1 args2; - valid r1 r2 - with Unify_error l -> - raise (Unify_error (Cannot_unify (t1,t2) :: l))) - | _ -> - assert false - end - | _,(Var { v_write = AccNo | AccNever }) -> - (* write variance *) - valid t1 t2 - | _,(Var { v_read = AccNo | AccNever }) -> - (* read variance *) - valid t2 t1 - | _ , _ -> - (* in case args differs, or if an interface var *) - type_eq EqStrict t1 t2; - if is_null t1 <> is_null t2 then raise (Unify_error [Cannot_unify (t1,t2)]) - -let copy_meta meta_src meta_target sl = - let meta = ref meta_target in - List.iter (fun (m,e,p) -> - if List.mem m sl then meta := (m,e,p) :: !meta - ) meta_src; - !meta - -let check_overriding ctx c f = - match c.cl_super with - | None -> - display_error ctx ("Field " ^ f.cf_name ^ " is declared 'override' but doesn't override any field") f.cf_pos - | _ when c.cl_extern && Meta.has Meta.CsNative c.cl_meta -> () (* -net-lib specific: do not check overrides on extern CsNative classes *) - | Some (csup,params) -> - let p = f.cf_pos in - let i = f.cf_name in - let check_field f get_super_field is_overload = try - (if is_overload && not (Meta.has Meta.Overload f.cf_meta) then - display_error ctx ("Missing @:overload declaration for field " ^ i) p); - let t, f2 = get_super_field csup i in - (* allow to define fields that are not defined for this platform version in superclass *) - (match f2.cf_kind with - | Var { v_read = AccRequire _ } -> raise Not_found; - | _ -> ()); - if ctx.com.config.pf_overload && (Meta.has Meta.Overload f2.cf_meta && not (Meta.has Meta.Overload f.cf_meta)) then - display_error ctx ("Field " ^ i ^ " should be declared with @:overload since it was already declared as @:overload in superclass") p - else if not (List.memq f c.cl_overrides) then - display_error ctx ("Field " ^ i ^ " should be declared with 'override' since it is inherited from superclass " ^ s_type_path csup.cl_path) p - else if not f.cf_public && f2.cf_public then - display_error ctx ("Field " ^ i ^ " has less visibility (public/private) than superclass one") p - else (match f.cf_kind, f2.cf_kind with - | _, Method MethInline -> - display_error ctx ("Field " ^ i ^ " is inlined and cannot be overridden") p - | a, b when a = b -> () - | Method MethInline, Method MethNormal -> - () (* allow to redefine a method as inlined *) - | _ -> - display_error ctx ("Field " ^ i ^ " has different property access than in superclass") p); - if has_meta Meta.Final f2.cf_meta then display_error ctx ("Cannot override final method " ^ i) p; - try - let t = apply_params csup.cl_params params t in - valid_redefinition ctx f f.cf_type f2 t - with - Unify_error l -> - display_error ctx ("Field " ^ i ^ " overloads parent class with different or incomplete type") p; - display_error ctx ("Base field is defined here") f2.cf_pos; - display_error ctx (error_msg (Unify l)) p; - with - Not_found -> - if List.memq f c.cl_overrides then - let msg = if is_overload then - ("Field " ^ i ^ " is declared 'override' but no compatible overload was found") - else - ("Field " ^ i ^ " is declared 'override' but doesn't override any field") - in - display_error ctx msg p - in - if ctx.com.config.pf_overload && Meta.has Meta.Overload f.cf_meta then begin - let overloads = Overloads.get_overloads csup i in - List.iter (fun (t,f2) -> - (* check if any super class fields are vars *) - match f2.cf_kind with - | Var _ -> - display_error ctx ("A variable named '" ^ f2.cf_name ^ "' was already declared in a superclass") f.cf_pos - | _ -> () - ) overloads; - List.iter (fun f -> - (* find the exact field being overridden *) - check_field f (fun csup i -> - List.find (fun (t,f2) -> - Overloads.same_overload_args f.cf_type (apply_params csup.cl_params params t) f f2 - ) overloads - ) true - ) (f :: f.cf_overloads) - end else - check_field f (fun csup i -> - let _, t, f2 = raw_class_field (fun f -> f.cf_type) csup params i in - t, f2) false - -let class_field_no_interf c i = - try - let f = PMap.find i c.cl_fields in - f.cf_type , f - with Not_found -> - match c.cl_super with - | None -> - raise Not_found - | Some (c,tl) -> - (* rec over class_field *) - let _, t , f = raw_class_field (fun f -> f.cf_type) c tl i in - apply_params c.cl_params tl t , f - -let rec return_flow ctx e = - let error() = - display_error ctx (Printf.sprintf "Missing return: %s" (s_type (print_context()) ctx.ret)) e.epos; raise Exit - in - let return_flow = return_flow ctx in - let rec uncond e = match e.eexpr with - | TIf _ | TWhile _ | TSwitch _ | TTry _ | TFunction _ -> () - | TReturn _ | TThrow _ -> raise Exit - | _ -> Type.iter uncond e - in - let has_unconditional_flow e = try uncond e; false with Exit -> true in - match e.eexpr with - | TReturn _ | TThrow _ -> () - | TParenthesis e | TMeta(_,e) -> - return_flow e - | TBlock el -> - let rec loop = function - | [] -> error() - | [e] -> return_flow e - | e :: _ when has_unconditional_flow e -> () - | _ :: l -> loop l - in - loop el - | TIf (_,e1,Some e2) -> - return_flow e1; - return_flow e2; - | TSwitch (v,cases,Some e) -> - List.iter (fun (_,e) -> return_flow e) cases; - return_flow e - | TSwitch ({eexpr = TMeta((Meta.Exhaustive,_,_),_)},cases,None) -> - List.iter (fun (_,e) -> return_flow e) cases; - | TTry (e,cases) -> - return_flow e; - List.iter (fun (_,e) -> return_flow e) cases; - | TWhile({eexpr = (TConst (TBool true))},e,_) -> - (* a special case for "inifite" while loops that have no break *) - let rec loop e = match e.eexpr with - (* ignore nested loops to not accidentally get one of its breaks *) - | TWhile _ | TFor _ -> () - | TBreak -> error() - | _ -> Type.iter loop e - in - loop e - | _ -> - error() - (* ---------------------------------------------------------------------- *) (* PASS 1 & 2 : Module and Class Structure *) -let is_generic_parameter ctx c = - (* first check field parameters, then class parameters *) - try - ignore (List.assoc (snd c.cl_path) ctx.curfield.cf_params); - Meta.has Meta.Generic ctx.curfield.cf_meta - with Not_found -> try - ignore(List.assoc (snd c.cl_path) ctx.type_params); - (match ctx.curclass.cl_kind with | KGeneric -> true | _ -> false); - with Not_found -> - false - -let type_function_arg_value ctx t c do_display = - match c with - | None -> None - | Some e -> - let p = pos e in - let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in - let e = ctx.g.do_optimize ctx (type_expr ctx e (WithType t)) in - unify ctx e.etype t p; - let rec loop e = match e.eexpr with - | TConst c -> Some c - | TCast(e,None) -> loop e - | _ -> - if not ctx.com.display.dms_display || ctx.com.display.dms_inline && ctx.com.display.dms_error_policy = EPCollect then - display_error ctx "Parameter default value should be constant" p; - None - in - loop e - -(**** strict meta ****) -let get_native_repr md pos = - let path, meta = match md with - | TClassDecl cl -> cl.cl_path, cl.cl_meta - | TEnumDecl e -> e.e_path, e.e_meta - | TTypeDecl t -> t.t_path, t.t_meta - | TAbstractDecl a -> a.a_path, a.a_meta - in - let rec loop acc = function - | (Meta.JavaCanonical,[EConst(String pack),_; EConst(String name),_],_) :: _ -> - ExtString.String.nsplit pack ".", name - | (Meta.Native,[EConst(String name),_],_) :: meta -> - loop (Ast.parse_path name) meta - | _ :: meta -> - loop acc meta - | [] -> - acc - in - let pack, name = loop path meta in - match pack with - | [] -> - (EConst(Ident(name)), pos) - | hd :: tl -> - let rec loop pack expr = match pack with - | hd :: tl -> - loop tl (EField(expr,hd),pos) - | [] -> - (EField(expr,name),pos) - in - loop tl (EConst(Ident(hd)),pos) - -let rec process_meta_argument ?(toplevel=true) ctx expr = match expr.eexpr with - | TField(e,f) -> - (EField(process_meta_argument ~toplevel:false ctx e,field_name f),expr.epos) - | TConst(TInt i) -> - (EConst(Int (Int32.to_string i)), expr.epos) - | TConst(TFloat f) -> - (EConst(Float f), expr.epos) - | TConst(TString s) -> - (EConst(String s), expr.epos) - | TConst TNull -> - (EConst(Ident "null"), expr.epos) - | TConst(TBool b) -> - (EConst(Ident (string_of_bool b)), expr.epos) - | TCast(e,_) | TMeta(_,e) | TParenthesis(e) -> - process_meta_argument ~toplevel ctx e - | TTypeExpr md when toplevel -> - let p = expr.epos in - if ctx.com.platform = Cs then - (ECall( (EConst(Ident "typeof"), p), [get_native_repr md expr.epos] ), p) - else - (EField(get_native_repr md expr.epos, "class"), p) - | TTypeExpr md -> - get_native_repr md expr.epos - | _ -> - display_error ctx "This expression is too complex to be a strict metadata argument" expr.epos; - (EConst(Ident "null"), expr.epos) - -let make_meta ctx texpr extra = - match texpr.eexpr with - | TNew(c,_,el) -> - ECall(get_native_repr (TClassDecl c) texpr.epos, (List.map (process_meta_argument ctx) el) @ extra), texpr.epos - | TTypeExpr(md) -> - ECall(get_native_repr md texpr.epos, extra), texpr.epos - | _ -> - display_error ctx "Unexpected expression" texpr.epos; assert false - let field_to_type_path ctx e = let rec loop e pack name = match e with | EField(e,f),p when Char.lowercase (String.get f 0) <> String.get f 0 -> (match name with @@ -1129,373 +685,6 @@ let field_to_type_path ctx e = in loop e [] [] -let handle_fields ctx fields_to_check with_type_expr = - List.map (fun ((name,_,_),expr) -> - let pos = snd expr in - let field = (EField(with_type_expr,name), pos) in - let fieldexpr = (EConst(Ident name),pos) in - let left_side = match ctx.com.platform with - | Cs -> field - | Java -> (ECall(field,[]),pos) - | _ -> assert false - in - - let left = type_expr ctx left_side NoValue in - let right = type_expr ctx expr (WithType left.etype) in - unify ctx left.etype right.etype (snd expr); - (EBinop(Ast.OpAssign,fieldexpr,process_meta_argument ctx right), pos) - ) fields_to_check - -let get_strict_meta ctx params pos = - let pf = ctx.com.platform in - let changed_expr, fields_to_check, ctype = match params with - | [ECall(ef, el),p] -> - (* check last argument *) - let el, fields = match List.rev el with - | (EObjectDecl(decl),_) :: el -> - List.rev el, decl - | _ -> - el, [] - in - let tpath = field_to_type_path ctx ef in - if pf = Cs then - (ENew((tpath,snd ef), el), p), fields, CTPath tpath - else - ef, fields, CTPath tpath - | [EConst(Ident i),p as expr] -> - let tpath = { tpackage=[]; tname=i; tparams=[]; tsub=None } in - if pf = Cs then - (ENew((tpath,p), []), p), [], CTPath tpath - else - expr, [], CTPath tpath - | [ (EField(_),p as field) ] -> - let tpath = field_to_type_path ctx field in - if pf = Cs then - (ENew((tpath,p), []), p), [], CTPath tpath - else - field, [], CTPath tpath - | _ -> - display_error ctx "A @:strict metadata must contain exactly one parameter. Please check the documentation for more information" pos; - raise Exit - in - let texpr = type_expr ctx changed_expr NoValue in - let with_type_expr = (ECheckType( (EConst (Ident "null"), pos), (ctype,null_pos) ), pos) in - let extra = handle_fields ctx fields_to_check with_type_expr in - Meta.Meta, [make_meta ctx texpr extra], pos - -let check_strict_meta ctx metas = - let pf = ctx.com.platform in - match pf with - | Cs | Java -> - let ret = ref [] in - List.iter (function - | Meta.Strict,params,pos -> (try - ret := get_strict_meta ctx params pos :: !ret - with | Exit -> ()) - | _ -> () - ) metas; - !ret - | _ -> [] - -(**** end of strict meta handling *****) - -let add_constructor ctx c force_constructor p = - match c.cl_constructor, c.cl_super with - | None, Some ({ cl_constructor = Some cfsup } as csup,cparams) when not c.cl_extern -> - let cf = { - cfsup with - cf_pos = p; - cf_meta = List.filter (fun (m,_,_) -> m = Meta.CompilerGenerated) cfsup.cf_meta; - cf_doc = None; - cf_expr = None; - } in - let r = exc_protect ctx (fun r -> - let t = mk_mono() in - r := lazy_processing (fun() -> t); - let ctx = { ctx with - curfield = cf; - pass = PTypeField; - } in - ignore (follow cfsup.cf_type); (* make sure it's typed *) - (if ctx.com.config.pf_overload then List.iter (fun cf -> ignore (follow cf.cf_type)) cf.cf_overloads); - let map_arg (v,def) = - (* - let's optimize a bit the output by not always copying the default value - into the inherited constructor when it's not necessary for the platform - *) - match ctx.com.platform, def with - | _, Some _ when not ctx.com.config.pf_static -> v, (Some TNull) - | Flash, Some (TString _) -> v, (Some TNull) - | Cpp, Some (TString _) -> v, def - | Cpp, Some _ -> { v with v_type = ctx.t.tnull v.v_type }, (Some TNull) - | _ -> v, def - in - let args = (match cfsup.cf_expr with - | Some { eexpr = TFunction f } -> - List.map map_arg f.tf_args - | _ -> - let values = get_value_meta cfsup.cf_meta in - match follow cfsup.cf_type with - | TFun (args,_) -> - List.map (fun (n,o,t) -> - let def = try type_function_arg_value ctx t (Some (PMap.find n values)) false with Not_found -> if o then Some TNull else None in - map_arg (alloc_var n (if o then ctx.t.tnull t else t) p,def) (* TODO: var pos *) - ) args - | _ -> assert false - ) in - let p = c.cl_pos in - let vars = List.map (fun (v,def) -> alloc_var v.v_name (apply_params csup.cl_params cparams v.v_type) v.v_pos, def) args in - let super_call = mk (TCall (mk (TConst TSuper) (TInst (csup,cparams)) p,List.map (fun (v,_) -> mk (TLocal v) v.v_type p) vars)) ctx.t.tvoid p in - let constr = mk (TFunction { - tf_args = vars; - tf_type = ctx.t.tvoid; - tf_expr = super_call; - }) (TFun (List.map (fun (v,c) -> v.v_name, c <> None, v.v_type) vars,ctx.t.tvoid)) p in - cf.cf_expr <- Some constr; - cf.cf_type <- t; - unify ctx t constr.etype p; - t - ) "add_constructor" in - cf.cf_type <- TLazy r; - c.cl_constructor <- Some cf; - | None,_ when force_constructor -> - let constr = mk (TFunction { - tf_args = []; - tf_type = ctx.t.tvoid; - tf_expr = mk (TBlock []) ctx.t.tvoid p; - }) (tfun [] ctx.t.tvoid) p in - let cf = mk_field "new" constr.etype p null_pos in - cf.cf_expr <- Some constr; - cf.cf_type <- constr.etype; - cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos]; - cf.cf_kind <- Method MethNormal; - c.cl_constructor <- Some cf; - | _ -> - (* nothing to do *) - () - -let check_struct_init_constructor ctx c p = match c.cl_constructor with - | Some _ -> - () - | None -> - let params = List.map snd c.cl_params in - let ethis = mk (TConst TThis) (TInst(c,params)) p in - let args,el,tl = List.fold_left (fun (args,el,tl) cf -> match cf.cf_kind with - | Var _ -> - let opt = Meta.has Meta.Optional cf.cf_meta in - let t = if opt then ctx.t.tnull cf.cf_type else cf.cf_type in - let v = alloc_var cf.cf_name t p in - let ef = mk (TField(ethis,FInstance(c,params,cf))) t p in - let ev = mk (TLocal v) v.v_type p in - let e = mk (TBinop(OpAssign,ef,ev)) ev.etype p in - (v,None) :: args,e :: el,(cf.cf_name,opt,t) :: tl - | Method _ -> - args,el,tl - ) ([],[],[]) (List.rev c.cl_ordered_fields) in - let tf = { - tf_args = args; - tf_type = ctx.t.tvoid; - tf_expr = mk (TBlock el) ctx.t.tvoid p - } in - let e = mk (TFunction tf) (TFun(tl,ctx.t.tvoid)) p in - let cf = mk_field "new" e.etype p null_pos in - cf.cf_expr <- Some e; - cf.cf_type <- e.etype; - cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos]; - cf.cf_kind <- Method MethNormal; - c.cl_constructor <- Some cf - -module Inheritance = struct - let check_extends ctx c t p = match follow t with - | TInst ({ cl_path = [],"Array"; cl_extern = basic_extern },_) - | TInst ({ cl_path = [],"String"; cl_extern = basic_extern },_) - | TInst ({ cl_path = [],"Date"; cl_extern = basic_extern },_) - | TInst ({ cl_path = [],"Xml"; cl_extern = basic_extern },_) when not (c.cl_extern && basic_extern) -> - error "Cannot extend basic class" p; - | TInst (csup,params) -> - if is_parent c csup then error "Recursive class" p; - begin match csup.cl_kind with - | KTypeParameter _ -> - if is_generic_parameter ctx csup then error "Extending generic type parameters is no longer allowed in Haxe 4" p; - error "Cannot extend type parameters" p - | _ -> csup,params - end - | _ -> error "Should extend by using a class" p - - let rec check_interface ctx c intf params = - let p = c.cl_pos in - let rec check_field i f = - (if ctx.com.config.pf_overload then - List.iter (function - | f2 when f != f2 -> - check_field i f2 - | _ -> ()) f.cf_overloads); - let is_overload = ref false in - try - let t2, f2 = class_field_no_interf c i in - let t2, f2 = - if ctx.com.config.pf_overload && (f2.cf_overloads <> [] || Meta.has Meta.Overload f2.cf_meta) then - let overloads = Overloads.get_overloads c i in - is_overload := true; - let t = (apply_params intf.cl_params params f.cf_type) in - List.find (fun (t1,f1) -> Overloads.same_overload_args t t1 f f1) overloads - else - t2, f2 - in - if ctx.com.display.dms_collect_data then begin - let h = ctx.com.display_information in - h.interface_field_implementations <- (intf,f,c,Some f2) :: h.interface_field_implementations; - end; - ignore(follow f2.cf_type); (* force evaluation *) - let p = (match f2.cf_expr with None -> p | Some e -> e.epos) in - let mkind = function - | MethNormal | MethInline -> 0 - | MethDynamic -> 1 - | MethMacro -> 2 - in - if f.cf_public && not f2.cf_public && not (Meta.has Meta.CompilerGenerated f.cf_meta) then - display_error ctx ("Field " ^ i ^ " should be public as requested by " ^ s_type_path intf.cl_path) p - else if not (unify_kind f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then - display_error ctx ("Field " ^ i ^ " has different property access than in " ^ s_type_path intf.cl_path ^ " (" ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind ^ ")") p - else try - valid_redefinition ctx f2 t2 f (apply_params intf.cl_params params f.cf_type) - with - Unify_error l -> - if not (Meta.has Meta.CsNative c.cl_meta && c.cl_extern) then begin - display_error ctx ("Field " ^ i ^ " has different type than in " ^ s_type_path intf.cl_path) p; - display_error ctx ("Interface field is defined here") f.cf_pos; - display_error ctx (error_msg (Unify l)) p; - end - with - | Not_found when not c.cl_interface -> - let msg = if !is_overload then - let ctx = print_context() in - let args = match follow f.cf_type with | TFun(args,_) -> String.concat ", " (List.map (fun (n,o,t) -> (if o then "?" else "") ^ n ^ " : " ^ (s_type ctx t)) args) | _ -> assert false in - "No suitable overload for " ^ i ^ "( " ^ args ^ " ), as needed by " ^ s_type_path intf.cl_path ^ " was found" - else - ("Field " ^ i ^ " needed by " ^ s_type_path intf.cl_path ^ " is missing") - in - display_error ctx msg p - | Not_found -> () - in - PMap.iter check_field intf.cl_fields; - List.iter (fun (i2,p2) -> - check_interface ctx c i2 (List.map (apply_params intf.cl_params params) p2) - ) intf.cl_implements - - let check_interfaces ctx c = - match c.cl_path with - | "Proxy" :: _ , _ -> () - | _ when c.cl_extern && Meta.has Meta.CsNative c.cl_meta -> () - | _ -> - List.iter (fun (intf,params) -> check_interface ctx c intf params) c.cl_implements - - let set_heritance ctx c herits p = - let is_lib = Meta.has Meta.LibType c.cl_meta in - let ctx = { ctx with curclass = c; type_params = c.cl_params; } in - let old_meta = c.cl_meta in - let process_meta csup = - List.iter (fun m -> - match m with - | Meta.Final, _, _ -> if not (Meta.has Meta.Hack c.cl_meta || (match c.cl_kind with KTypeParameter _ -> true | _ -> false)) then error "Cannot extend a final class" p; - | Meta.AutoBuild, el, p -> c.cl_meta <- (Meta.Build,el,{ c.cl_pos with pmax = c.cl_pos.pmin }(* prevent display metadata *)) :: m :: c.cl_meta - | _ -> () - ) csup.cl_meta - in - let check_cancel_build csup = - match csup.cl_build() with - | Built -> () - | state -> - (* for macros reason, our super class is not yet built - see #2177 *) - (* let's reset our build and delay it until we are done *) - c.cl_meta <- old_meta; - raise (Build_canceled state) - in - let has_interf = ref false in - (* - resolve imports before calling build_inheritance, since it requires full paths. - that means that typedefs are not working, but that's a fair limitation - *) - let resolve_imports (t,p) = - match t.tpackage with - | _ :: _ -> t,p - | [] -> - try - let path_matches lt = snd (t_path lt) = t.tname in - let lt = try - List.find path_matches ctx.m.curmod.m_types - with Not_found -> - let t,pi = List.find (fun (lt,_) -> path_matches lt) ctx.m.module_types in - Display.ImportHandling.mark_import_position ctx.com pi; - t - in - { t with tpackage = fst (t_path lt) },p - with - Not_found -> t,p - in - let herits = ExtList.List.filter_map (function - | HExtends t -> Some(true,resolve_imports t) - | HImplements t -> Some(false,resolve_imports t) - | t -> None - ) herits in - let herits = List.filter (ctx.g.do_inherit ctx c p) herits in - (* Pass 1: Check and set relations *) - let check_herit t is_extends = - if is_extends then begin - if c.cl_super <> None then error "Cannot extend several classes" p; - let csup,params = check_extends ctx c t p in - if c.cl_interface then begin - if not csup.cl_interface then error "Cannot extend by using a class" p; - c.cl_implements <- (csup,params) :: c.cl_implements; - if not !has_interf then begin - if not is_lib then delay ctx PForce (fun() -> check_interfaces ctx c); - has_interf := true; - end - end else begin - if csup.cl_interface then error "Cannot extend by using an interface" p; - c.cl_super <- Some (csup,params) - end; - (fun () -> - check_cancel_build csup; - process_meta csup; - ) - end else begin match follow t with - | TInst ({ cl_path = [],"ArrayAccess"; cl_extern = true; },[t]) -> - if c.cl_array_access <> None then error "Duplicate array access" p; - c.cl_array_access <- Some t; - (fun () -> ()) - | TInst (intf,params) -> - if is_parent c intf then error "Recursive class" p; - if c.cl_interface then error "Interfaces cannot implement another interface (use extends instead)" p; - if not intf.cl_interface then error "You can only implement an interface" p; - c.cl_implements <- (intf, params) :: c.cl_implements; - if not !has_interf && not is_lib && not (Meta.has (Meta.Custom "$do_not_check_interf") c.cl_meta) then begin - delay ctx PForce (fun() -> check_interfaces ctx c); - has_interf := true; - end; - (fun () -> - check_cancel_build intf; - process_meta intf; - ) - | TDynamic t -> - if c.cl_dynamic <> None then error "Cannot have several dynamics" p; - c.cl_dynamic <- Some t; - (fun () -> ()) - | _ -> - error "Should implement by using an interface" p - end - in - let fl = ExtList.List.filter_map (fun (is_extends,t) -> - try - let t = load_instance ~allow_display:true ctx t false p in - Some (check_herit t is_extends) - with Error(Module_not_found(([],name)),p) when ctx.com.display.dms_display -> - if Display.Diagnostics.is_diagnostics_run ctx then Display.ToplevelCollector.handle_unresolved_identifier ctx name p true; - None - ) herits in - fl -end - let rec type_type_param ?(enum_constructor=false) ctx path get_params p tp = let n = fst tp.tp_name in let c = mk_class ctx.m.curmod (fst path @ [snd path],n) (pos tp.tp_name) (pos tp.tp_name) in @@ -1504,16 +693,19 @@ let rec type_type_param ?(enum_constructor=false) ctx path get_params p tp = c.cl_meta <- tp.Ast.tp_meta; if enum_constructor then c.cl_meta <- (Meta.EnumConstructorParam,[],null_pos) :: c.cl_meta; let t = TInst (c,List.map snd c.cl_params) in - if ctx.is_display_file && Display.is_display_position (pos tp.tp_name) then - Display.DisplayEmitter.display_type ctx.com.display t (pos tp.tp_name); + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos tp.tp_name) then + DisplayEmitter.display_type ctx t (pos tp.tp_name); match tp.tp_constraints with - | [] -> + | None -> n, t - | _ -> + | Some th -> let r = exc_protect ctx (fun r -> r := lazy_processing (fun() -> t); let ctx = { ctx with type_params = ctx.type_params @ get_params() } in - let constr = List.map (load_complex_type ctx true p) tp.tp_constraints in + let constr = match fst th with + | CTIntersection tl -> List.map (load_complex_type ctx true) tl + | _ -> [load_complex_type ctx true th] + in (* check against direct recursion *) let rec loop t = match follow t with @@ -1537,150 +729,6 @@ and type_type_params ?(enum_constructor=false) ctx path get_params p tpl = type_type_param ~enum_constructor ctx path get_params p tp ) tpl -let type_function_params ctx fd fname p = - let params = ref [] in - params := type_type_params ctx ([],fname) (fun() -> !params) p fd.f_params; - !params - -let type_function ctx args ret fmode f do_display p = - let locals = save_locals ctx in - let fargs = List.map2 (fun (n,c,t) ((_,pn),_,m,_,_) -> - if n.[0] = '$' then error "Function argument names starting with a dollar are not allowed" p; - let c = type_function_arg_value ctx t c do_display in - let v,c = add_local ctx n t pn, c in - v.v_meta <- m; - if do_display && Display.is_display_position pn then - Display.DisplayEmitter.display_variable ctx.com.display v pn; - if n = "this" then v.v_meta <- (Meta.This,[],null_pos) :: v.v_meta; - v,c - ) args f.f_args in - let old_ret = ctx.ret in - let old_fun = ctx.curfun in - let old_opened = ctx.opened in - ctx.curfun <- fmode; - ctx.ret <- ret; - ctx.opened <- []; - let e = match f.f_expr with - | None -> - if ctx.com.display.dms_error_policy = EPIgnore then - (* when we don't care because we're in display mode, just act like - the function has an empty block body. this is fine even if function - defines a return type, because returns aren't checked in this mode - *) - EBlock [],p - else - error "Function body required" p - | Some e -> e - in - let e = if not do_display then - type_expr ctx e NoValue - else begin - let e = Display.ExprPreprocessing.process_expr ctx.com e in - try - if Common.defined ctx.com Define.NoCOpt then raise Exit; - type_expr ctx (Optimizer.optimize_completion_expr e) NoValue - with - | Parser.TypePath (_,None,_) | Exit -> - type_expr ctx e NoValue - | Display.DisplayType (t,_,_) when (match follow t with TMono _ -> true | _ -> false) -> - type_expr ctx (if ctx.com.display.dms_kind = DMToplevel then Display.ExprPreprocessing.find_enclosing ctx.com e else e) NoValue - end in - let e = match e.eexpr with - | TMeta((Meta.MergeBlock,_,_), ({eexpr = TBlock el} as e1)) -> e1 - | _ -> e - in - let has_return e = - let rec loop e = - match e.eexpr with - | TReturn (Some _) -> raise Exit - | TFunction _ -> () - | _ -> Type.iter loop e - in - try loop e; false with Exit -> true - in - begin match follow ret with - | TAbstract({a_path=[],"Void"},_) -> () - (* We have to check for the presence of return expressions here because - in the case of Dynamic ctx.ret is still a monomorph. If we indeed - don't have a return expression we can link the monomorph to Void. We - can _not_ use type_iseq to avoid the Void check above because that - would turn Dynamic returns to Void returns. *) - | TMono t when not (has_return e) -> ignore(link t ret ctx.t.tvoid) - | _ when ctx.com.display.dms_error_policy = EPIgnore -> () - | _ -> (try return_flow ctx e with Exit -> ()) - end; - let rec loop e = - match e.eexpr with - | TCall ({ eexpr = TConst TSuper },_) -> raise Exit - | TFunction _ -> () - | _ -> Type.iter loop e - in - let has_super_constr() = - match ctx.curclass.cl_super with - | None -> - None - | Some (csup,tl) -> - try - let _,cf = get_constructor (fun f->f.cf_type) csup in - Some (Meta.has Meta.CompilerGenerated cf.cf_meta,TInst(csup,tl)) - with Not_found -> - None - in - let e = if fmode <> FunConstructor then - e - else begin - let final_vars = Hashtbl.create 0 in - List.iter (fun cf -> match cf.cf_kind with - | Var _ when Meta.has Meta.Final cf.cf_meta && cf.cf_expr = None -> - Hashtbl.add final_vars cf.cf_name cf - | _ -> - () - ) ctx.curclass.cl_ordered_fields; - if Hashtbl.length final_vars > 0 then begin - let rec find_inits e = match e.eexpr with - | TBinop(OpAssign,{eexpr = TField({eexpr = TConst TThis},fa)},e2) -> - Hashtbl.remove final_vars (field_name fa); - find_inits e2; - | _ -> - Type.iter find_inits e - in - find_inits e; - Hashtbl.iter (fun _ cf -> - display_error ctx ("final field " ^ cf.cf_name ^ " must be initialized immediately or in the constructor") cf.cf_pos; - ) final_vars - end; - match has_super_constr() with - | Some (was_forced,t_super) -> - (try - loop e; - if was_forced then - let e_super = mk (TConst TSuper) t_super e.epos in - let e_super_call = mk (TCall(e_super,[])) ctx.t.tvoid e.epos in - concat e_super_call e - else begin - display_error ctx "Missing super constructor call" p; - e - end - with - Exit -> e); - | None -> - e - end in - locals(); - let e = match ctx.curfun, ctx.vthis with - | (FunMember|FunConstructor), Some v -> - let ev = mk (TVar (v,Some (mk (TConst TThis) ctx.tthis p))) ctx.t.tvoid p in - (match e.eexpr with - | TBlock l -> { e with eexpr = TBlock (ev::l) } - | _ -> mk (TBlock [ev;e]) e.etype p) - | _ -> e - in - List.iter (fun r -> r := Closed) ctx.opened; - ctx.ret <- old_ret; - ctx.curfun <- old_fun; - ctx.opened <- old_opened; - e , fargs - let load_core_class ctx c = let ctx2 = (match ctx.g.core_api with | None -> @@ -1688,8 +736,11 @@ let load_core_class ctx c = com2.defines.Define.values <- PMap.empty; Common.define com2 Define.CoreApi; Common.define com2 Define.Sys; + Define.raw_define_value com2.defines "target.threaded" "true"; (* hack because we check this in sys.thread classes *) if ctx.in_macro then Common.define com2 Define.Macro; com2.class_path <- ctx.com.std_path; + if com2.display.dms_check_core_api then com2.display <- {com2.display with dms_check_core_api = false}; + Option.may (fun cs -> CompilationServer.maybe_add_context_sign cs com2 "load_core_class") (CompilationServer.get ()); let ctx2 = ctx.g.do_create com2 in ctx.g.core_api <- Some ctx2; ctx2 @@ -1700,7 +751,7 @@ let load_core_class ctx c = | KAbstractImpl a -> { tpackage = fst a.a_path; tname = snd a.a_path; tparams = []; tsub = None; } | _ -> { tpackage = fst c.cl_path; tname = snd c.cl_path; tparams = []; tsub = None; } in - let t = load_instance ctx2 (tpath,c.cl_pos) true c.cl_pos in + let t = load_instance ctx2 (tpath,c.cl_pos) true in flush_pass ctx2 PFinal "core_final"; match t with | TInst (ccore,_) | TAbstract({a_impl = Some ccore}, _) -> @@ -1739,7 +790,7 @@ let init_core_api ctx c = with Unify_error l -> display_error ctx ("Field " ^ f.cf_name ^ " has different type than in core type") p; display_error ctx (error_msg (Unify l)) p); - if f2.cf_public <> f.cf_public then error ("Field " ^ f.cf_name ^ " has different visibility than core type") p; + if (has_class_field_flag f2 CfPublic) <> (has_class_field_flag f CfPublic) then error ("Field " ^ f.cf_name ^ " has different visibility than core type") p; (match f2.cf_doc with | None -> f2.cf_doc <- f.cf_doc | Some _ -> ()); @@ -1760,2311 +811,125 @@ let init_core_api ctx c = in let check_fields fcore fl = PMap.iter (fun i f -> - if not f.cf_public then () else + if not (has_class_field_flag f CfPublic) then () else let f2 = try PMap.find f.cf_name fl with Not_found -> error ("Missing field " ^ i ^ " required by core type") c.cl_pos in compare_fields f f2; ) fcore; PMap.iter (fun i f -> let p = (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos) in - if f.cf_public && not (Meta.has Meta.Hack f.cf_meta) && not (PMap.mem f.cf_name fcore) && not (List.memq f c.cl_overrides) then error ("Public field " ^ i ^ " is not part of core type") p; + if (has_class_field_flag f CfPublic) && not (Meta.has Meta.Hack f.cf_meta) && not (PMap.mem f.cf_name fcore) && not (List.memq f c.cl_overrides) then error ("Public field " ^ i ^ " is not part of core type") p; ) fl; in check_fields ccore.cl_fields c.cl_fields; check_fields ccore.cl_statics c.cl_statics; (match ccore.cl_constructor, c.cl_constructor with | None, None -> () - | Some { cf_public = false }, _ -> () + | Some cf, _ when not (has_class_field_flag cf CfPublic) -> () | Some f, Some f2 -> compare_fields f f2 - | None, Some { cf_public = false } -> () + | None, Some cf when not (has_class_field_flag cf CfPublic) -> () | _ -> error "Constructor differs from core type" c.cl_pos) -let check_global_metadata ctx meta f_add mpath tpath so = - let sl1 = full_dot_path mpath tpath in - let sl1,field_mode = match so with None -> sl1,false | Some s -> sl1 @ [s],true in - List.iter (fun (sl2,m,(recursive,to_types,to_fields)) -> - let add = ((field_mode && to_fields) || (not field_mode && to_types)) && (match_path recursive sl1 sl2) in - if add then f_add m - ) ctx.g.global_metadata; - if ctx.is_display_file then delay ctx PCheckConstraint (fun () -> Display.DisplayEmitter.check_display_metadata ctx meta) - -let patch_class ctx c fields = - let path = match c.cl_kind with - | KAbstractImpl a -> a.a_path - | _ -> c.cl_path - in - let h = (try Some (Hashtbl.find ctx.g.type_patches path) with Not_found -> None) in - match h with - | None -> fields - | Some (h,hcl) -> - c.cl_meta <- c.cl_meta @ hcl.tp_meta; - let rec loop acc = function - | [] -> acc - | f :: l -> - (* patch arguments types *) - (match f.cff_kind with - | FFun ff -> - let param (((n,pn),opt,m,_,e) as p) = - try - let t2 = (try Hashtbl.find h (("$" ^ (fst f.cff_name) ^ "__" ^ n),false) with Not_found -> Hashtbl.find h (("$" ^ n),false)) in - (n,pn), opt, m, (match t2.tp_type with None -> None | Some t -> Some (t,null_pos)), e - with Not_found -> - p - in - f.cff_kind <- FFun { ff with f_args = List.map param ff.f_args } - | _ -> ()); - (* other patches *) - match (try Some (Hashtbl.find h (fst f.cff_name,List.mem AStatic f.cff_access)) with Not_found -> None) with - | None -> loop (f :: acc) l - | Some { tp_remove = true } -> loop acc l - | Some p -> - f.cff_meta <- f.cff_meta @ p.tp_meta; - (match p.tp_type with - | None -> () - | Some t -> - f.cff_kind <- match f.cff_kind with - | FVar (_,e) -> FVar (Some (t,null_pos),e) - | FProp (get,set,_,eo) -> FProp (get,set,Some (t,null_pos),eo) - | FFun f -> FFun { f with f_type = Some (t,null_pos) }); - loop (f :: acc) l - in - List.rev (loop [] fields) - let string_list_of_expr_path (e,p) = try string_list_of_expr_path_raise (e,p) with Exit -> error "Invalid path" p -let build_enum_abstract ctx c a fields p = - List.iter (fun field -> - match field.cff_kind with - | FVar(ct,eo) when not (List.mem AStatic field.cff_access) -> - field.cff_access <- [AStatic; if (List.mem APrivate field.cff_access) then APrivate else APublic]; - field.cff_meta <- (Meta.Enum,[],null_pos) :: (Meta.Impl,[],null_pos) :: field.cff_meta; - let ct = match ct with - | Some _ -> ct - | None -> Some (TExprToExpr.convert_type (TAbstract(a,List.map snd a.a_params)),null_pos) +let handle_path_display ctx path p = + let open ImportHandling in + let class_field c name = + ignore(c.cl_build()); + let cf = PMap.find name c.cl_statics in + let origin = match c.cl_kind with + | KAbstractImpl a -> Self (TAbstractDecl a) + | _ -> Self (TClassDecl c) + in + DisplayEmitter.display_field ctx origin CFSStatic cf p + in + match ImportHandling.convert_import_to_something_usable DisplayPosition.display_position#get path,ctx.com.display.dms_kind with + | (IDKPackage [s],p),DMDefault -> + DisplayToplevel.collect_and_raise ctx TKType WithType.no_value CRImport (s,p) (Some p) + | (IDKPackage sl,p),DMDefault -> + let sl = match List.rev sl with + | s :: sl -> List.rev sl + | [] -> assert false in - begin match eo with - | None -> - if not c.cl_extern then error "Value required" field.cff_pos - else field.cff_kind <- FProp(("default",null_pos),("never",null_pos),ct,None) - | Some e -> - field.cff_access <- AInline :: field.cff_access; - let e = (ECast(e,None),(pos e)) in - field.cff_kind <- FVar(ct,Some e) + raise (Parser.TypePath(sl,None,true,p)) + | (IDKPackage _,_),_ -> + () (* ? *) + | (IDKModule(sl,s),_),(DMDefinition | DMTypeDefinition) -> + (* We assume that we want to go to the module file, not a specific type + which might not even exist anyway. *) + let mt = ctx.g.do_load_module ctx (sl,s) p in + let p = { pfile = mt.m_extra.m_file; pmin = 0; pmax = 0} in + DisplayException.raise_positions [p] + | (IDKModule(sl,s),_),DMHover -> + let m = ctx.g.do_load_module ctx (sl,s) p in + begin try + let mt = List.find (fun mt -> snd (t_infos mt).mt_path = s) m.m_types in + DisplayEmitter.display_module_type ctx mt p; + with Not_found -> + () end - | _ -> + | (IDKSubType(sl,sm,st),p),DMHover -> + (* TODO: remove code duplication once load_type_def change is in *) + let m = ctx.g.do_load_module ctx (sl,sm) p in + begin try + let mt = List.find (fun mt -> snd (t_infos mt).mt_path = st) m.m_types in + DisplayEmitter.display_module_type ctx mt p; + with Not_found -> + () + end + | (IDKModule(sl,s),p),_ -> + raise (Parser.TypePath(sl,None,true,p)) + | (IDKSubType(sl,sm,st),p),(DMDefinition | DMTypeDefinition) -> + resolve_position_by_path ctx { tpackage = sl; tname = sm; tparams = []; tsub = Some st} p + | (IDKSubType(sl,sm,st),p),_ -> + raise (Parser.TypePath(sl,Some(sm,false),true,p)) + | ((IDKSubTypeField(sl,sm,st,sf) | IDKModuleField(sl,(sm as st),sf)),p),DMDefault -> + raise (Parser.TypePath(sl @ [sm],Some(st,false),true,p)); + | ((IDKSubTypeField(sl,sm,st,sf) | IDKModuleField(sl,(sm as st),sf)),p),_ -> + let m = ctx.g.do_load_module ctx (sl,sm) p in + List.iter (fun t -> match t with + | TClassDecl c when snd c.cl_path = st -> + class_field c sf + | TAbstractDecl {a_impl = Some c; a_path = (_,st')} when st' = st -> + class_field c sf + | _ -> + () + ) m.m_types; + | (IDK,_),_ -> () - ) fields; - EVars [("",null_pos),Some (CTAnonymous fields,p),None],p - -let is_java_native_function meta = try - match Meta.get Meta.Native meta with - | (Meta.Native,[],_) -> true - | _ -> false - with | Not_found -> false -let build_module_def ctx mt meta fvars context_init fbuild = - let loop (f_build,f_enum) = function - | Meta.Build,args,p -> (fun () -> - let epath, el = (match args with - | [ECall (epath,el),p] -> epath, el - | _ -> error "Invalid build parameters" p - ) in - let s = try String.concat "." (List.rev (string_list_of_expr_path epath)) with Error (_,p) -> error "Build call parameter must be a class path" p in - if ctx.in_macro then error "You cannot use @:build inside a macro : make sure that your type is not used in macro" p; - let old = ctx.g.get_build_infos in - ctx.g.get_build_infos <- (fun() -> Some (mt, List.map snd (t_infos mt).mt_params, fvars())); - context_init(); - let r = try apply_macro ctx MBuild s el p with e -> ctx.g.get_build_infos <- old; raise e in - ctx.g.get_build_infos <- old; - (match r with - | None -> error "Build failure" p - | Some e -> fbuild e) - ) :: f_build,f_enum - | Meta.Enum,_,p -> f_build,Some (fun () -> - begin match mt with - | TClassDecl ({cl_kind = KAbstractImpl a} as c) -> - context_init(); - let e = build_enum_abstract ctx c a (fvars()) p in - fbuild e; - | _ -> - () - end - ) - | _ -> - f_build,f_enum - in - (* let errors go through to prevent resume if build fails *) - let f_build,f_enum = List.fold_left loop ([],None) meta in - List.iter (fun f -> f()) (List.rev f_build); - (match f_enum with None -> () | Some f -> f()) - -module ClassInitializer = struct - type class_init_ctx = { - tclass : tclass; (* I don't trust ctx.curclass because it's mutable. *) - is_lib : bool; - is_native : bool; - is_core_api : bool; - is_class_debug : bool; - extends_public : bool; - abstract : tabstract option; - context_init : unit -> unit; - mutable delayed_expr : (typer * tlazy ref option) list; - mutable force_constructor : bool; - mutable uninitialized_final : pos option; - } - - type field_kind = - | FKNormal - | FKConstructor - | FKInit - - type field_init_ctx = { - is_inline : bool; - is_final : bool; - is_static : bool; - is_override : bool; - is_extern : bool; - is_macro : bool; - is_abstract_member : bool; - is_display_field : bool; - is_field_debug : bool; - field_kind : field_kind; - mutable do_bind : bool; - mutable do_add : bool; - } - - let dump_class_context cctx = - Printer.s_record_fields "" [ - "tclass",Printer.s_tclass "\t" cctx.tclass; - "is_lib",string_of_bool cctx.is_lib; - "is_native",string_of_bool cctx.is_native; - "is_core_api",string_of_bool cctx.is_core_api; - "is_class_debug",string_of_bool cctx.is_class_debug; - "extends_public",string_of_bool cctx.extends_public; - "abstract",Printer.s_opt (Printer.s_tabstract "\t") cctx.abstract; - "force_constructor",string_of_bool cctx.force_constructor; - ] - - let s_field_kind = function - | FKNormal -> "FKNormal" - | FKConstructor -> "FKConstructor" - | FKInit -> "FKInit" - - let dump_field_context fctx = - Printer.s_record_fields "" [ - "is_inline",string_of_bool fctx.is_inline; - "is_static",string_of_bool fctx.is_static; - "is_override",string_of_bool fctx.is_override; - "is_extern",string_of_bool fctx.is_extern; - "is_macro",string_of_bool fctx.is_macro; - "is_abstract_member",string_of_bool fctx.is_abstract_member; - "is_display_field",string_of_bool fctx.is_display_field; - "is_field_debug",string_of_bool fctx.is_field_debug; - "field_kind",s_field_kind fctx.field_kind; - "do_bind",string_of_bool fctx.do_bind; - "do_add",string_of_bool fctx.do_add; - ] - - let create_class_context ctx c context_init p = - locate_macro_error := true; - incr stats.s_classes_built; - let abstract = match c.cl_kind with - | KAbstractImpl a -> Some a - | _ -> None - in - let ctx = { - ctx with - curclass = c; - type_params = c.cl_params; - pass = PBuildClass; - tthis = (match abstract with - | Some a -> - (match a.a_this with - | TMono r when !r = None -> TAbstract (a,List.map snd c.cl_params) - | t -> t) - | None -> TInst (c,List.map snd c.cl_params)); - on_error = (fun ctx msg ep -> - ctx.com.error msg ep; - (* macros expressions might reference other code, let's recall which class we are actually compiling *) - if !locate_macro_error && (ep.pfile <> c.cl_pos.pfile || ep.pmax < c.cl_pos.pmin || ep.pmin > c.cl_pos.pmax) then ctx.com.error "Defined in this class" c.cl_pos - ); - } in - (* a lib type will skip most checks *) - let is_lib = Meta.has Meta.LibType c.cl_meta in - if is_lib && not c.cl_extern then ctx.com.error "@:libType can only be used in extern classes" c.cl_pos; - (* a native type will skip one check: the static vs non-static field *) - let is_native = Meta.has Meta.JavaNative c.cl_meta || Meta.has Meta.CsNative c.cl_meta in - if Meta.has Meta.Macro c.cl_meta then display_error ctx "Macro classes are no longer allowed in haxe 3" c.cl_pos; - let rec extends_public c = - Meta.has Meta.PublicFields c.cl_meta || - match c.cl_super with - | None -> false - | Some (c,_) -> extends_public c - in - let cctx = { - tclass = c; - is_lib = is_lib; - is_native = is_native; - is_core_api = Meta.has Meta.CoreApi c.cl_meta; - is_class_debug = false; - extends_public = extends_public c; - abstract = abstract; - context_init = context_init; - force_constructor = false; - uninitialized_final = None; - delayed_expr = []; - } in - ctx,cctx - - let create_field_context (ctx,cctx) c cff = - let ctx = { - ctx with - pass = PBuildClass; (* will be set later to PTypeExpr *) - } in - let is_static = List.mem AStatic cff.cff_access in - let is_extern = Meta.has Meta.Extern cff.cff_meta || c.cl_extern in - let allow_inline = cctx.abstract <> None || match cff.cff_kind with - | FFun _ -> ctx.g.doinline || is_extern - | _ -> true - in - let is_inline = allow_inline && List.mem AInline cff.cff_access in - let is_override = List.mem AOverride cff.cff_access in - let is_macro = List.mem AMacro cff.cff_access in - let field_kind = match fst cff.cff_name with - | "new" -> FKConstructor - | "__init__" when is_static -> FKInit - | _ -> FKNormal - in - let fctx = { - is_inline = is_inline; - is_static = is_static; - is_override = is_override; - is_macro = is_macro; - is_extern = is_extern; - is_final = List.mem AFinal cff.cff_access; - is_display_field = ctx.is_display_file && Display.is_display_position cff.cff_pos; - is_field_debug = cctx.is_class_debug; - is_abstract_member = cctx.abstract <> None && Meta.has Meta.Impl cff.cff_meta; - field_kind = field_kind; - do_bind = (((not c.cl_extern || is_inline) && not c.cl_interface) || field_kind = FKInit); - do_add = true; - } in - ctx,fctx - - let is_public (ctx,cctx) access parent = - let c = cctx.tclass in - if List.mem APrivate access then - false - else if List.mem APublic access then - true - else match parent with - | Some { cf_public = p } -> p - | _ -> c.cl_extern || c.cl_interface || cctx.extends_public - - let rec get_parent c name = - match c.cl_super with - | None -> None - | Some (csup,_) -> - try - Some (PMap.find name csup.cl_fields) - with - Not_found -> get_parent csup name - - let add_field c cf is_static = - if is_static then begin - c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics; - c.cl_ordered_statics <- cf :: c.cl_ordered_statics; - end else begin - c.cl_fields <- PMap.add cf.cf_name cf c.cl_fields; - c.cl_ordered_fields <- cf :: c.cl_ordered_fields; - end - - let type_opt (ctx,cctx) p t = - let c = cctx.tclass in - match t with - | None when c.cl_extern || c.cl_interface -> - display_error ctx "Type required for extern classes and interfaces" p; - t_dynamic - | None when cctx.is_core_api -> - display_error ctx "Type required for core api classes" p; - t_dynamic - | _ -> - load_type_hint ctx p t - - let build_fields (ctx,cctx) c fields = - let fields = ref fields in - let get_fields() = !fields in - let pending = ref [] in - c.cl_build <- (fun() -> BuildMacro pending); - build_module_def ctx (TClassDecl c) c.cl_meta get_fields cctx.context_init (fun (e,p) -> - match e with - | EVars [_,Some (CTAnonymous f,p),None] -> - let f = List.map (fun f -> - let f = match cctx.abstract with - | Some a -> - let a_t = TExprToExpr.convert_type' (TAbstract(a,List.map snd a.a_params)) in - let this_t = TExprToExpr.convert_type' a.a_this in (* TODO: better pos? *) - transform_abstract_field ctx.com this_t a_t a f - | None -> - f - in - if List.mem AMacro f.cff_access then - (match ctx.g.macros with - | Some (_,mctx) when Hashtbl.mem mctx.g.types_module c.cl_path -> - (* assume that if we had already a macro with the same name, it has not been changed during the @:build operation *) - if not (List.exists (fun f2 -> f2.cff_name = f.cff_name && List.mem AMacro f2.cff_access) (!fields)) then - error "Class build macro cannot return a macro function when the class has already been compiled into the macro context" p - | _ -> ()); - f - ) f in - fields := f - | _ -> error "Class build macro must return a single variable with anonymous fields" p - ); - c.cl_build <- (fun() -> Building [c]); - List.iter (fun f -> f()) !pending; - !fields - - let bind_type (ctx,cctx,fctx) cf r p = - let c = cctx.tclass in - let rec is_full_type t = - match t with - | TFun (args,ret) -> is_full_type ret && List.for_all (fun (_,_,t) -> is_full_type t) args - | TMono r -> (match !r with None -> false | Some t -> is_full_type t) - | TAbstract _ | TInst _ | TEnum _ | TLazy _ | TDynamic _ | TAnon _ | TType _ -> true - in - let force_macro () = - (* force macro system loading of this class in order to get completion *) - delay ctx PTypeField (fun() -> try ignore(ctx.g.do_macro ctx MDisplay c.cl_path cf.cf_name [] p) with Exit | Error _ -> ()) - in - let handle_display_field () = - if fctx.is_macro && not ctx.in_macro then - force_macro() - else begin - cf.cf_type <- TLazy r; - cctx.delayed_expr <- (ctx,Some r) :: cctx.delayed_expr; - end - in - if ctx.com.display.dms_full_typing then begin - if fctx.is_macro && not ctx.in_macro then - () - else begin - cf.cf_type <- TLazy r; - (* is_lib ? *) - cctx.delayed_expr <- (ctx,Some r) :: cctx.delayed_expr; - end - end else if ctx.com.display.dms_force_macro_typing && fctx.is_macro && not ctx.in_macro then - force_macro() - else begin - if fctx.is_display_field then begin - handle_display_field() - end else begin - if not (is_full_type cf.cf_type) then begin - cctx.delayed_expr <- (ctx, None) :: cctx.delayed_expr; - cf.cf_type <- TLazy r; - end; - end - end - - let bind_var (ctx,cctx,fctx) cf e = - let c = cctx.tclass in - let p = cf.cf_pos in - let rec get_declared f = function - | None -> None - | Some (c,a) when PMap.exists f c.cl_fields -> - Some (c,a) - | Some (c,_) -> - let ret = get_declared f c.cl_super in - match ret with - | Some r -> Some r - | None -> - let rec loop ifaces = match ifaces with - | [] -> None - | i :: ifaces -> match get_declared f (Some i) with - | Some r -> Some r - | None -> loop ifaces - in - loop c.cl_implements - in - if not fctx.is_static && not cctx.is_lib then begin match get_declared cf.cf_name c.cl_super with - | None -> () - | Some (csup,_) -> - (* this can happen on -net-lib generated classes if a combination of explicit interfaces and variables with the same name happens *) - if not (csup.cl_interface && Meta.has Meta.CsNative c.cl_meta) then - error ("Redefinition of variable " ^ cf.cf_name ^ " in subclass is not allowed. Previously declared at " ^ (s_type_path csup.cl_path) ) p - end; - let t = cf.cf_type in - - match e with - | None -> - if fctx.is_display_field then Display.DisplayEmitter.maybe_display_field ctx (cf.cf_name_pos) cf; - | Some e -> - if requires_value_meta ctx.com (Some c) then cf.cf_meta <- ((Meta.Value,[e],null_pos) :: cf.cf_meta); - let check_cast e = - (* insert cast to keep explicit field type (issue #1901) *) - if type_iseq e.etype cf.cf_type then - e - else begin match e.eexpr,follow cf.cf_type with - | TConst (TInt i),TAbstract({a_path=[],"Float"},_) -> - (* turn int constant to float constant if expected type is float *) - {e with eexpr = TConst (TFloat (Int32.to_string i))} - | _ -> - mk_cast e cf.cf_type e.epos - end - in - let r = exc_protect ~force:false ctx (fun r -> - (* type constant init fields (issue #1956) *) - if not !return_partial_type || (match fst e with EConst _ -> true | _ -> false) then begin - r := lazy_processing (fun() -> t); - cctx.context_init(); - if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name); - let e = type_var_field ctx t e fctx.is_static fctx.is_display_field p in - let maybe_run_analyzer e = match e.eexpr with - | TConst _ | TLocal _ | TFunction _ -> e - | _ -> !analyzer_run_on_expr_ref ctx.com e - in - let require_constant_expression e msg = - if ctx.com.display.dms_display && ctx.com.display.dms_error_policy <> EPCollect then - e - else match Optimizer.make_constant_expression ctx (maybe_run_analyzer e) with - | Some e -> e - | None -> display_error ctx msg p; e - in - let e = (match cf.cf_kind with - | Var v when c.cl_extern || Meta.has Meta.Extern cf.cf_meta -> - if not fctx.is_static then begin - display_error ctx "Extern non-static variables may not be initialized" p; - e - end else if not fctx.is_inline then begin - display_error ctx "Extern non-inline variables may not be initialized" p; - e - end else require_constant_expression e "Extern variable initialization must be a constant value" - | Var v when not (is_physical_field cf) -> - (* disallow initialization of non-physical fields (issue #1958) *) - display_error ctx "This field cannot be initialized because it is not a real variable" p; e - | Var v when not fctx.is_static -> - let e = if ctx.com.display.dms_display && ctx.com.display.dms_error_policy <> EPCollect then - e - else begin - let rec check_this e = match e.eexpr with - | TConst TThis -> - display_error ctx "Cannot access this or other member field in variable initialization" e.epos; - raise Exit - | TLocal v when (match ctx.vthis with Some v2 -> v == v2 | None -> false) -> - display_error ctx "Cannot access this or other member field in variable initialization" e.epos; - raise Exit - | _ -> - Type.iter check_this e - in - try - check_this e; - match Optimizer.make_constant_expression ctx (maybe_run_analyzer e) with - | Some e -> e - | None -> e - with Exit -> - e - end in - e - | Var v when v.v_read = AccInline -> - let e = require_constant_expression e "Inline variable initialization must be a constant value" in - begin match c.cl_kind with - | KAbstractImpl a when Meta.has Meta.Enum cf.cf_meta && Meta.has Meta.Enum a.a_meta -> - unify ctx t (TAbstract(a,(List.map (fun _ -> mk_mono()) a.a_params))) p; - begin match e.eexpr with - | TCast(e1,None) -> unify ctx e1.etype a.a_this e1.epos - | _ -> assert false - end - | _ -> - () - end; - e - | _ -> - e - ) in - let e = check_cast e in - cf.cf_expr <- Some e; - cf.cf_type <- t; - if fctx.is_display_field then Display.DisplayEmitter.maybe_display_field ctx (cf.cf_name_pos) cf; - end; - t - ) "bind_var" in - if not fctx.is_static then cctx.force_constructor <- true; - bind_type (ctx,cctx,fctx) cf r (snd e) - - let create_variable (ctx,cctx,fctx) c f t eo p = - if not fctx.is_static && cctx.abstract <> None then error (fst f.cff_name ^ ": Cannot declare member variable in abstract") p; - if fctx.is_inline && not fctx.is_static then error (fst f.cff_name ^ ": Inline variable must be static") p; - if fctx.is_inline && eo = None then error (fst f.cff_name ^ ": Inline variable must be initialized") p; - if fctx.is_final && eo = None then begin - if fctx.is_static then error (fst f.cff_name ^ ": Static final variable must be initialized") p - else cctx.uninitialized_final <- Some f.cff_pos; - end; - let t = (match t with - | None when not fctx.is_static && eo = None -> - error ("Type required for member variable " ^ fst f.cff_name) p; - | None -> - mk_mono() - | Some t -> - (* TODO is_lib: only load complex type if needed *) - let old = ctx.type_params in - if fctx.is_static then ctx.type_params <- (match cctx.abstract with - | Some a -> a.a_params - | _ -> [] - ); - let t = load_complex_type ctx true p t in - if fctx.is_static then ctx.type_params <- old; - t - ) in - let kind = if fctx.is_inline then - { v_read = AccInline ; v_write = AccNever } - else if fctx.is_final then - { v_read = AccNormal ; v_write = if fctx.is_static then AccNever else AccCtor } - else - { v_read = AccNormal ; v_write = AccNormal } - in - let cf = { - (mk_field (fst f.cff_name) t f.cff_pos (pos f.cff_name)) with - cf_doc = f.cff_doc; - cf_meta = (if fctx.is_final && not (Meta.has Meta.Final f.cff_meta) then (Meta.Final,[],null_pos) :: f.cff_meta else f.cff_meta); - cf_kind = Var kind; - cf_public = is_public (ctx,cctx) f.cff_access None; - } in - ctx.curfield <- cf; - bind_var (ctx,cctx,fctx) cf eo; - cf - - let check_abstract (ctx,cctx,fctx) c cf fd t ret p = - match cctx.abstract with - | Some a -> - let m = mk_mono() in - let ta = TAbstract(a, List.map (fun _ -> mk_mono()) a.a_params) in - let tthis = if fctx.is_abstract_member || Meta.has Meta.To cf.cf_meta then monomorphs a.a_params a.a_this else a.a_this in - let allows_no_expr = ref (Meta.has Meta.CoreType a.a_meta) in - let rec loop ml = match ml with - | (Meta.From,_,_) :: _ -> - let r = exc_protect ctx (fun r -> - r := lazy_processing (fun () -> t); - (* the return type of a from-function must be the abstract, not the underlying type *) - if not fctx.is_macro then (try type_eq EqStrict ret ta with Unify_error l -> error (error_msg (Unify l)) p); - match t with - | TFun([_,_,t],_) -> t - | _ -> error (cf.cf_name ^ ": @:from cast functions must accept exactly one argument") p - ) "@:from" in - a.a_from_field <- (TLazy r,cf) :: a.a_from_field; - | (Meta.To,_,_) :: _ -> - if fctx.is_macro then error (cf.cf_name ^ ": Macro cast functions are not supported") p; - (* TODO: this doesn't seem quite right... *) - if not (Meta.has Meta.Impl cf.cf_meta) then cf.cf_meta <- (Meta.Impl,[],null_pos) :: cf.cf_meta; - let resolve_m args = - (try unify_raise ctx t (tfun (tthis :: args) m) cf.cf_pos with Error (Unify l,p) -> error (error_msg (Unify l)) p); - match follow m with - | TMono _ when (match t with TFun(_,r) -> r == t_dynamic | _ -> false) -> t_dynamic - | m -> m - in - let r = exc_protect ctx (fun r -> - r := lazy_processing (fun () -> t); - let args = if Meta.has Meta.MultiType a.a_meta then begin - let ctor = try - PMap.find "_new" c.cl_statics - with Not_found -> - error "Constructor of multi-type abstract must be defined before the individual @:to-functions are" cf.cf_pos - in - (* delay ctx PFinal (fun () -> unify ctx m tthis f.cff_pos); *) - let args = match follow (monomorphs a.a_params ctor.cf_type) with - | TFun(args,_) -> List.map (fun (_,_,t) -> t) args - | _ -> assert false - in - args - end else - [] - in - let t = resolve_m args in - t - ) "@:to" in - a.a_to_field <- (TLazy r, cf) :: a.a_to_field - | ((Meta.ArrayAccess,_,_) | (Meta.Op,[(EArrayDecl _),_],_)) :: _ -> - if fctx.is_macro then error (cf.cf_name ^ ": Macro array-access functions are not supported") p; - a.a_array <- cf :: a.a_array; - | (Meta.Op,[EBinop(op,_,_),_],_) :: _ -> - if fctx.is_macro then error (cf.cf_name ^ ": Macro operator functions are not supported") p; - let targ = if fctx.is_abstract_member then tthis else ta in - let left_eq,right_eq = match follow t with - | TFun([(_,_,t1);(_,_,t2)],_) -> - type_iseq targ t1,type_iseq targ t2 - | _ -> - if fctx.is_abstract_member then - error (cf.cf_name ^ ": Member @:op functions must accept exactly one argument") cf.cf_pos - else - error (cf.cf_name ^ ": Static @:op functions must accept exactly two arguments") cf.cf_pos - in - if not (left_eq || right_eq) then error (cf.cf_name ^ ": The left or right argument type must be " ^ (s_type (print_context()) targ)) cf.cf_pos; - if right_eq && Meta.has Meta.Commutative cf.cf_meta then error (cf.cf_name ^ ": @:commutative is only allowed if the right argument is not " ^ (s_type (print_context()) targ)) cf.cf_pos; - a.a_ops <- (op,cf) :: a.a_ops; - allows_no_expr := true; - | (Meta.Op,[EUnop(op,flag,_),_],_) :: _ -> - if fctx.is_macro then error (cf.cf_name ^ ": Macro operator functions are not supported") p; - let targ = if fctx.is_abstract_member then tthis else ta in - (try type_eq EqStrict t (tfun [targ] (mk_mono())) with Unify_error l -> raise (Error ((Unify l),cf.cf_pos))); - a.a_unops <- (op,flag,cf) :: a.a_unops; - allows_no_expr := true; - | (Meta.Impl,_,_) :: ml when cf.cf_name <> "_new" && not fctx.is_macro -> - begin match follow t with - | TFun((_,_,t1) :: _, _) when type_iseq tthis t1 -> - () - | _ -> - display_error ctx ("First argument of implementation function must be " ^ (s_type (print_context()) tthis)) cf.cf_pos - end; - loop ml - | ((Meta.Resolve,_,_) | (Meta.Op,[EField _,_],_)) :: _ -> - if a.a_resolve <> None then error "Multiple resolve methods are not supported" cf.cf_pos; - let targ = if fctx.is_abstract_member then tthis else ta in - begin match follow t with - | TFun([(_,_,t1);(_,_,t2)],_) -> - if not fctx.is_macro then begin - if not (type_iseq targ t1) then error ("First argument type must be " ^ (s_type (print_context()) targ)) cf.cf_pos; - if not (type_iseq ctx.t.tstring t2) then error ("Second argument type must be String") cf.cf_pos - end - | _ -> - error ("Field type of resolve must be " ^ (s_type (print_context()) targ) ^ " -> String -> T") cf.cf_pos - end; - a.a_resolve <- Some cf; - | _ :: ml -> - loop ml - | [] -> - () - in - loop cf.cf_meta; - let check_bind () = - if fd.f_expr = None then begin - if fctx.is_inline then error (cf.cf_name ^ ": Inline functions must have an expression") cf.cf_pos; - begin match fd.f_type with - | None -> error (cf.cf_name ^ ": Functions without expressions must have an explicit return type") cf.cf_pos - | Some _ -> () - end; - cf.cf_meta <- (Meta.NoExpr,[],null_pos) :: cf.cf_meta; - fctx.do_bind <- false; - if not (Meta.has Meta.CoreType a.a_meta) then fctx.do_add <- false; - end - in - if cf.cf_name = "_new" && Meta.has Meta.MultiType a.a_meta then fctx.do_bind <- false; - if !allows_no_expr then check_bind() - | _ -> - () - - let create_method (ctx,cctx,fctx) c f fd p = - let params = type_function_params ctx fd (fst f.cff_name) p in - if Meta.has Meta.Generic f.cff_meta then begin - if params = [] then error (fst f.cff_name ^ ": Generic functions must have type parameters") p; - end; - let fd = if fctx.is_macro && not ctx.in_macro && not fctx.is_static then - (* remove display of first argument which will contain the "this" expression *) - { fd with f_args = match fd.f_args with [] -> [] | _ :: l -> l } - else - fd - in - let fd = if not fctx.is_macro then - fd - else begin - if ctx.in_macro then begin - (* a class with a macro cannot be extern in macro context (issue #2015) *) - c.cl_extern <- false; - let texpr = CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = None } in - (* ExprOf type parameter might contain platform-specific type, let's replace it by Expr *) - let no_expr_of (t,p) = match t with - | CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some ("ExprOf"); tparams = [TPType _] } - | CTPath { tpackage = []; tname = ("ExprOf"); tsub = None; tparams = [TPType _] } -> Some (texpr,p) - | t -> Some (t,p) - in - { - f_params = fd.f_params; - f_type = (match fd.f_type with None -> Some (texpr,null_pos) | Some t -> no_expr_of t); - f_args = List.map (fun (a,o,m,t,e) -> a,o,m,(match t with None -> Some (texpr,null_pos) | Some t -> no_expr_of t),e) fd.f_args; - f_expr = fd.f_expr; - } - end else - let tdyn = Some (CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None },null_pos) in - let to_dyn p t = match t with - | { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some ("ExprOf"); tparams = [TPType t] } -> Some t - | { tpackage = []; tname = ("ExprOf"); tsub = None; tparams = [TPType t] } -> Some t - | { tpackage = ["haxe"]; tname = ("PosInfos"); tsub = None; tparams = [] } -> error "haxe.PosInfos is not allowed on macro functions, use Context.currentPos() instead" p - | _ -> tdyn - in - { - f_params = fd.f_params; - f_type = (match fd.f_type with Some (CTPath t,p) -> to_dyn p t | _ -> tdyn); - f_args = List.map (fun (a,o,m,t,_) -> a,o,m,(match t with Some (CTPath t,p) -> to_dyn p t | _ -> tdyn),None) fd.f_args; - f_expr = None; - } - end in - begin match c.cl_interface,fctx.field_kind with - | true,FKConstructor -> - error "An interface cannot have a constructor" p; - | true,_ -> - if not fctx.is_static && fd.f_expr <> None then error (fst f.cff_name ^ ": An interface method cannot have a body") p; - if fctx.is_inline && c.cl_interface then error (fst f.cff_name ^ ": You can't declare inline methods in interfaces") p; - | false,FKConstructor -> - if fctx.is_static then error "A constructor must not be static" p; - begin match fd.f_type with - | None | Some (CTPath { tpackage = []; tname = "Void" },_) -> () - | _ -> error "A class constructor can't have a return value" p; - end - | false,_ -> - () - end; - let parent = (if not fctx.is_static then get_parent c (fst f.cff_name) else None) in - let dynamic = List.mem ADynamic f.cff_access || (match parent with Some { cf_kind = Method MethDynamic } -> true | _ -> false) in - if fctx.is_inline && dynamic then error (fst f.cff_name ^ ": You can't have both 'inline' and 'dynamic'") p; - ctx.type_params <- (match cctx.abstract with - | Some a when fctx.is_abstract_member -> - params @ a.a_params - | _ -> - if fctx.is_static then params else params @ ctx.type_params); - (* TODO is_lib: avoid forcing the return type to be typed *) - let ret = if fctx.field_kind = FKConstructor then ctx.t.tvoid else type_opt (ctx,cctx) p fd.f_type in - let rec loop args = match args with - | ((name,p),opt,m,t,ct) :: args -> - (* TODO is_lib: avoid forcing the field to be typed *) - let t, ct = type_function_arg ctx (type_opt (ctx,cctx) p t) ct opt p in - delay ctx PTypeField (fun() -> match follow t with - | TAbstract({a_path = ["haxe";"extern"],"Rest"},_) -> - if not c.cl_extern then error "Rest argument are only supported for extern methods" p; - if opt then error "Rest argument cannot be optional" p; - begin match ct with None -> () | Some (_,p) -> error "Rest argument cannot have default value" p end; - if args <> [] then error "Rest should only be used for the last function argument" p; - | _ -> - () - ); - (name, ct, t) :: (loop args) - | [] -> - [] - in - let args = loop fd.f_args in - let t = TFun (fun_args args,ret) in - let cf = { - (mk_field (fst f.cff_name) t f.cff_pos (pos f.cff_name)) with - cf_doc = f.cff_doc; - cf_meta = (if fctx.is_final && not (Meta.has Meta.Final f.cff_meta) then (Meta.Final,[],null_pos) :: f.cff_meta else f.cff_meta); - cf_kind = Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal); - cf_public = is_public (ctx,cctx) f.cff_access parent; - cf_params = params; - } in - cf.cf_meta <- List.map (fun (m,el,p) -> match m,el with - | Meta.AstSource,[] -> (m,(match fd.f_expr with None -> [] | Some e -> [e]),p) - | _ -> m,el,p - ) cf.cf_meta; - generate_value_meta ctx.com (Some c) cf fd.f_args; - check_abstract (ctx,cctx,fctx) c cf fd t ret p; - init_meta_overloads ctx (Some c) cf; - ctx.curfield <- cf; - let r = exc_protect ~force:false ctx (fun r -> - if not !return_partial_type then begin - r := lazy_processing (fun() -> t); - cctx.context_init(); - incr stats.s_methods_typed; - if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ fst f.cff_name); - let fmode = (match cctx.abstract with - | Some _ -> - (match args with - | ("this",_,_) :: _ -> FunMemberAbstract - | _ when fst f.cff_name = "_new" -> FunMemberAbstract - | _ -> FunStatic) - | None -> - if fctx.field_kind = FKConstructor then FunConstructor else if fctx.is_static then FunStatic else FunMember - ) in - (match ctx.com.platform with - | Java when is_java_native_function cf.cf_meta -> - if fd.f_expr <> None then - ctx.com.warning "@:native function definitions shouldn't include an expression. This behaviour is deprecated." cf.cf_pos; - cf.cf_expr <- None; - cf.cf_type <- t - | _ -> - let e , fargs = type_function ctx args ret fmode fd fctx.is_display_field p in - if fctx.is_override then check_overriding ctx c cf; - (* Disabled for now, see https://github.com/HaxeFoundation/haxe/issues/3033 *) - (* List.iter (fun (v,_) -> - if v.v_name <> "_" && has_mono v.v_type then ctx.com.warning "Uninferred function argument, please add a type-hint" v.v_pos; - ) fargs; *) - let tf = { - tf_args = fargs; - tf_type = ret; - tf_expr = e; - } in - if fctx.field_kind = FKInit then - (match e.eexpr with - | TBlock [] | TBlock [{ eexpr = TConst _ }] | TConst _ | TObjectDecl [] -> () - | _ -> c.cl_init <- Some e); - cf.cf_expr <- Some (mk (TFunction tf) t p); - cf.cf_type <- t; - if fctx.is_display_field then Display.DisplayEmitter.maybe_display_field ctx (cf.cf_name_pos) cf); - end; - t - ) "type_fun" in - if fctx.do_bind then bind_type (ctx,cctx,fctx) cf r (match fd.f_expr with Some e -> snd e | None -> f.cff_pos) - else if fctx.is_display_field then Display.DisplayEmitter.maybe_display_field ctx (cf.cf_name_pos) cf; - cf - - let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p = - let name = fst f.cff_name in - (match cctx.abstract with - | Some a when fctx.is_abstract_member -> - ctx.type_params <- a.a_params; - | _ -> ()); - (* TODO is_lib: lazify load_complex_type *) - let ret = (match t, eo with - | None, None -> error (name ^ ": Property must either define a type or a default value") p; - | None, _ -> mk_mono() - | Some t, _ -> load_complex_type ctx true p t - ) in - let t_get,t_set = match cctx.abstract with - | Some a when fctx.is_abstract_member -> - if Meta.has Meta.IsVar f.cff_meta then error (name ^ ": Abstract properties cannot be real variables") f.cff_pos; - let ta = apply_params a.a_params (List.map snd a.a_params) a.a_this in - tfun [ta] ret, tfun [ta;ret] ret - | _ -> tfun [] ret, TFun(["value",false,ret],ret) - in - let find_accessor m = - (* on pf_overload platforms, the getter/setter may have been defined as an overloaded function; get all overloads *) - if ctx.com.config.pf_overload then - if fctx.is_static then - let f = PMap.find m c.cl_statics in - (f.cf_type, f) :: (List.map (fun f -> f.cf_type, f) f.cf_overloads) - else - Overloads.get_overloads c m - else - [ if fctx.is_static then - let f = PMap.find m c.cl_statics in - f.cf_type, f - else match class_field c (List.map snd c.cl_params) m with - | _, t,f -> t,f ] - in - let check_method m t req_name = - if ctx.com.display.dms_error_policy = EPIgnore then () else - try - let overloads = find_accessor m in - (* choose the correct overload if and only if there is more than one overload found *) - let rec get_overload overl = match overl with - | [tf] -> tf - | (t2,f2) :: overl -> - if type_iseq t t2 then - (t2,f2) - else - get_overload overl - | [] -> - if c.cl_interface then - raise Not_found - else - raise (Error (Custom - (Printf.sprintf "No overloaded method named %s was compatible with the property %s with expected type %s" m (name) (s_type (print_context()) t) - ), p)) - in - let t2, f2 = get_overload overloads in - (* accessors must be public on As3 (issue #1872) *) - if Common.defined ctx.com Define.As3 then f2.cf_meta <- (Meta.Public,[],null_pos) :: f2.cf_meta; - (match f2.cf_kind with - | Method MethMacro -> - display_error ctx (f2.cf_name ^ ": Macro methods cannot be used as property accessor") p; - display_error ctx (f2.cf_name ^ ": Accessor method is here") f2.cf_pos; - | _ -> ()); - unify_raise ctx t2 t f2.cf_pos; - if (fctx.is_abstract_member && not (Meta.has Meta.Impl f2.cf_meta)) || (Meta.has Meta.Impl f2.cf_meta && not (fctx.is_abstract_member)) then - display_error ctx "Mixing abstract implementation and static properties/accessors is not allowed" f2.cf_pos; - (match req_name with None -> () | Some n -> display_error ctx ("Please use " ^ n ^ " to name your property access method") f2.cf_pos); - f2.cf_meta <- List.fold_left (fun acc ((m,_,_) as meta) -> match m with - | Meta.Deprecated -> meta :: acc - | _ -> acc - ) f2.cf_meta f.cff_meta; - with - | Error (Unify l,p) -> raise (Error (Stack (Custom ("In method " ^ m ^ " required by property " ^ name),Unify l),p)) - | Not_found -> - if req_name <> None then display_error ctx (name ^ ": Custom property accessor is no longer supported, please use get/set") p else - if c.cl_interface then begin - let cf = mk_field m t p null_pos in - cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos]; - cf.cf_kind <- Method MethNormal; - c.cl_fields <- PMap.add cf.cf_name cf c.cl_fields; - c.cl_ordered_fields <- cf :: c.cl_ordered_fields; - end else if not c.cl_extern then begin - try - let _, _, f2 = (if not fctx.is_static then let f = PMap.find m c.cl_statics in None, f.cf_type, f else class_field c (List.map snd c.cl_params) m) in - display_error ctx (Printf.sprintf "Method %s is no valid accessor for %s because it is %sstatic" m (name) (if fctx.is_static then "not " else "")) f2.cf_pos - with Not_found -> - display_error ctx ("Method " ^ m ^ " required by property " ^ name ^ " is missing") p - end - in - let display_accessor m p = - try - let cf = match find_accessor m with [_,cf] -> cf | _ -> raise Not_found in - Display.DisplayEmitter.display_field ctx.com.display cf p - with Not_found -> - () - in - let get = (match get with - | "null",_ -> AccNo - | "dynamic",_ -> AccCall - | "never",_ -> AccNever - | "default",_ -> AccNormal - | get,pget -> - let get = if get = "get" then "get_" ^ name else get in - if fctx.is_display_field && Display.is_display_position pget then delay ctx PTypeField (fun () -> display_accessor get pget); - if not cctx.is_lib then delay ctx PTypeField (fun() -> check_method get t_get (if get <> "get" && get <> "get_" ^ name then Some ("get_" ^ name) else None)); - AccCall - ) in - let set = (match set with - | "null",_ -> - (* standard flash library read-only variables can't be accessed for writing, even in subclasses *) - if c.cl_extern && (match c.cl_path with "flash" :: _ , _ -> true | _ -> false) && ctx.com.platform = Flash then - AccNever - else - AccNo - | "never",_ -> AccNever - | "dynamic",_ -> AccCall - | "default",_ -> AccNormal - | set,pset -> - let set = if set = "set" then "set_" ^ name else set in - if fctx.is_display_field && Display.is_display_position pset then delay ctx PTypeField (fun () -> display_accessor set pset); - if not cctx.is_lib then delay ctx PTypeField (fun() -> check_method set t_set (if set <> "set" && set <> "set_" ^ name then Some ("set_" ^ name) else None)); - AccCall - ) in - if set = AccNormal && (match get with AccCall -> true | _ -> false) then error (name ^ ": Unsupported property combination") p; - let cf = { - (mk_field name ret f.cff_pos (pos f.cff_name)) with - cf_doc = f.cff_doc; - cf_meta = f.cff_meta; - cf_kind = Var { v_read = get; v_write = set }; - cf_public = is_public (ctx,cctx) f.cff_access None; - } in - ctx.curfield <- cf; - bind_var (ctx,cctx,fctx) cf eo; - cf - - let init_field (ctx,cctx,fctx) f = - let c = cctx.tclass in - let name = fst f.cff_name in - check_global_metadata ctx f.cff_meta (fun m -> f.cff_meta <- m :: f.cff_meta) c.cl_module.m_path c.cl_path (Some name); - let p = f.cff_pos in - if name.[0] = '$' then display_error ctx "Field names starting with a dollar are not allowed" p; - List.iter (fun acc -> - match (acc, f.cff_kind) with - | APublic, _ | APrivate, _ | AStatic, _ | AFinal, _ -> () - | ADynamic, FFun _ | AOverride, FFun _ | AMacro, FFun _ | AInline, FFun _ | AInline, FVar _ -> () - | _, FVar _ -> error ("Invalid accessor '" ^ Ast.s_access acc ^ "' for variable " ^ name) p - | _, FProp _ -> error ("Invalid accessor '" ^ Ast.s_access acc ^ "' for property " ^ name) p - ) f.cff_access; - if fctx.is_override then (match c.cl_super with None -> error ("Invalid override on field '" ^ name ^ "': class has no super class") p | _ -> ()); - match f.cff_kind with - | FVar (t,e) -> - create_variable (ctx,cctx,fctx) c f t e p - | FFun fd -> - create_method (ctx,cctx,fctx) c f fd p - | FProp (get,set,t,eo) -> - create_property (ctx,cctx,fctx) c f (get,set,t,eo) p - - let check_overloads ctx c = - (* check if field with same signature was declared more than once *) - List.iter (fun f -> - if Meta.has Meta.Overload f.cf_meta then - List.iter (fun f2 -> - try - ignore (List.find (fun f3 -> f3 != f2 && Overloads.same_overload_args f2.cf_type f3.cf_type f2 f3) (f :: f.cf_overloads)); - display_error ctx ("Another overloaded field of same signature was already declared : " ^ f2.cf_name) f2.cf_pos - with | Not_found -> () - ) (f :: f.cf_overloads)) (c.cl_ordered_fields @ c.cl_ordered_statics) - - let init_class ctx c p context_init herits fields = - let ctx,cctx = create_class_context ctx c context_init p in - if cctx.is_class_debug then print_endline ("Created class context: " ^ dump_class_context cctx); - let fields = patch_class ctx c fields in - let fields = build_fields (ctx,cctx) c fields in - if cctx.is_core_api && ctx.com.display.dms_check_core_api then delay ctx PForce (fun() -> init_core_api ctx c); - if not cctx.is_lib then begin - if ctx.com.config.pf_overload then delay ctx PForce (fun() -> check_overloads ctx c) - end; - let rec has_field f = function - | None -> false - | Some (c,_) -> - PMap.exists f c.cl_fields || has_field f c.cl_super || List.exists (fun i -> has_field f (Some i)) c.cl_implements - in - let rec check_require = function - | [] -> None - | (Meta.Require,conds,_) :: l -> - let rec loop = function - | [] -> check_require l - | e :: l -> - let sc = match fst e with - | EConst (Ident s) -> s - | EBinop ((OpEq|OpNotEq|OpGt|OpGte|OpLt|OpLte) as op,(EConst (Ident s),_),(EConst ((Int _ | Float _ | String _) as c),_)) -> s ^ s_binop op ^ s_constant c - | _ -> "" - in - if not (ParserEntry.is_true (ParserEntry.eval ctx.com.defines e)) then - Some (sc,(match List.rev l with (EConst (String msg),_) :: _ -> Some msg | _ -> None)) - else - loop l - in - loop conds - | _ :: l -> - check_require l - in - let rec check_if_feature = function - | [] -> [] - | (Meta.IfFeature,el,_) :: _ -> List.map (fun (e,p) -> match e with EConst (String s) -> s | _ -> error "String expected" p) el - | _ :: l -> check_if_feature l - in - let cl_if_feature = check_if_feature c.cl_meta in - let cl_req = check_require c.cl_meta in - List.iter (fun f -> - let p = f.cff_pos in - try - let ctx,fctx = create_field_context (ctx,cctx) c f in - if fctx.is_field_debug then print_endline ("Created field context: " ^ dump_field_context fctx); - let cf = init_field (ctx,cctx,fctx) f in - if fctx.is_field_debug then print_endline ("Created field: " ^ Printer.s_tclass_field "" cf); - if fctx.is_static && c.cl_interface && fctx.field_kind <> FKInit && not cctx.is_lib then error "You can't declare static fields in interfaces" p; - let set_feature s = - ctx.m.curmod.m_extra.m_if_feature <- (s,(c,cf,fctx.is_static)) :: ctx.m.curmod.m_extra.m_if_feature - in - List.iter set_feature cl_if_feature; - List.iter set_feature (check_if_feature cf.cf_meta); - let req = check_require f.cff_meta in - let req = (match req with None -> if fctx.is_static || fctx.field_kind = FKConstructor then cl_req else None | _ -> req) in - (match req with - | None -> () - | Some r -> cf.cf_kind <- Var { v_read = AccRequire (fst r, snd r); v_write = AccRequire (fst r, snd r) }); - begin match fctx.field_kind with - | FKConstructor -> - begin match c.cl_constructor with - | None -> - c.cl_constructor <- Some cf - | Some ctor when ctx.com.config.pf_overload -> - if Meta.has Meta.Overload cf.cf_meta && Meta.has Meta.Overload ctor.cf_meta then - ctor.cf_overloads <- cf :: ctor.cf_overloads - else - display_error ctx ("If using overloaded constructors, all constructors must be declared with @:overload") (if Meta.has Meta.Overload cf.cf_meta then ctor.cf_pos else cf.cf_pos) - | Some ctor -> - display_error ctx "Duplicate constructor" p - end - | FKInit -> - () - | FKNormal -> - let dup = if fctx.is_static then PMap.exists cf.cf_name c.cl_fields || has_field cf.cf_name c.cl_super else PMap.exists cf.cf_name c.cl_statics in - if not cctx.is_native && not c.cl_extern && dup then error ("Same field name can't be use for both static and instance : " ^ cf.cf_name) p; - if fctx.is_override then c.cl_overrides <- cf :: c.cl_overrides; - let is_var f = match cf.cf_kind with | Var _ -> true | _ -> false in - if PMap.mem cf.cf_name (if fctx.is_static then c.cl_statics else c.cl_fields) then - if ctx.com.config.pf_overload && Meta.has Meta.Overload cf.cf_meta && not (is_var f) then - let mainf = PMap.find cf.cf_name (if fctx.is_static then c.cl_statics else c.cl_fields) in - if is_var mainf then display_error ctx "Cannot declare a variable with same name as a method" mainf.cf_pos; - (if not (Meta.has Meta.Overload mainf.cf_meta) then display_error ctx ("Overloaded methods must have @:overload metadata") mainf.cf_pos); - mainf.cf_overloads <- cf :: mainf.cf_overloads - else - display_error ctx ("Duplicate class field declaration : " ^ cf.cf_name) p - else - if fctx.do_add then add_field c cf (fctx.is_static || fctx.is_macro && ctx.in_macro) - end - with Error (Custom str,p2) when p = p2 -> - display_error ctx str p - ) fields; - (match cctx.abstract with - | Some a -> - a.a_to_field <- List.rev a.a_to_field; - a.a_from_field <- List.rev a.a_from_field; - a.a_ops <- List.rev a.a_ops; - a.a_unops <- List.rev a.a_unops; - a.a_array <- List.rev a.a_array; - | None -> ()); - c.cl_ordered_statics <- List.rev c.cl_ordered_statics; - c.cl_ordered_fields <- List.rev c.cl_ordered_fields; - (* - make sure a default contructor with same access as super one will be added to the class structure at some point. - *) - begin match cctx.uninitialized_final with - | Some pf when c.cl_constructor = None -> - display_error ctx "This class has uninitialized final vars, which requires a constructor" p; - error "Example of an uninitialized final var" pf - | _ -> - () - end; - (* add_constructor does not deal with overloads correctly *) - if not ctx.com.config.pf_overload then add_constructor ctx c cctx.force_constructor p; - if Meta.has Meta.StructInit c.cl_meta then check_struct_init_constructor ctx c p; - (* check overloaded constructors *) - (if ctx.com.config.pf_overload && not cctx.is_lib then match c.cl_constructor with - | Some ctor -> - delay ctx PTypeField (fun() -> - List.iter (fun f -> - try - (* TODO: consider making a broader check, and treat some types, like TAnon and type parameters as Dynamic *) - ignore(List.find (fun f2 -> f != f2 && Overloads.same_overload_args f.cf_type f2.cf_type f f2) (ctor :: ctor.cf_overloads)); - display_error ctx ("Another overloaded field of same signature was already declared : " ^ f.cf_name) f.cf_pos; - with Not_found -> () - ) (ctor :: ctor.cf_overloads) - ) - | _ -> ()); - (* push delays in reverse order so they will be run in correct order *) - List.iter (fun (ctx,r) -> - init_class_done ctx; - (match r with - | None -> () - | Some r -> delay ctx PTypeField (fun() -> ignore(lazy_type r))) - ) cctx.delayed_expr -end - -let check_module_types ctx m p t = - let t = t_infos t in - try - let m2 = Hashtbl.find ctx.g.types_module t.mt_path in - if m.m_path <> m2 && String.lowercase (s_type_path m2) = String.lowercase (s_type_path m.m_path) then error ("Module " ^ s_type_path m2 ^ " is loaded with a different case than " ^ s_type_path m.m_path) p; - error ("Type name " ^ s_type_path t.mt_path ^ " is redefined from module " ^ s_type_path m2) p - with - Not_found -> - Hashtbl.add ctx.g.types_module t.mt_path m.m_path - -let add_module ctx m p = - List.iter (check_module_types ctx m p) m.m_types; - Hashtbl.add ctx.g.modules m.m_path m - -let handle_path_display ctx path p = - let open Display.ImportHandling in - match Display.ImportHandling.convert_import_to_something_usable !Parser.resume_display path,ctx.com.display.dms_kind with - | (IDKPackage sl,_),_ -> - raise (Parser.TypePath(sl,None,true)) - | (IDKModule(sl,s),_),DMPosition -> - (* We assume that we want to go to the module file, not a specific type - which might not even exist anyway. *) - let mt = ctx.g.do_load_module ctx (sl,s) p in - let p = { pfile = mt.m_extra.m_file; pmin = 0; pmax = 0} in - raise (Display.DisplayPosition [p]) - | (IDKModule(sl,s),_),_ -> - (* TODO: wait till nadako requests @type display for these, then implement it somehow *) - raise (Parser.TypePath(sl,Some(s,false),true)) - | (IDKSubType(sl,sm,st),p),DMPosition -> - resolve_position_by_path ctx { tpackage = sl; tname = sm; tparams = []; tsub = Some st} p - | (IDKSubType(sl,sm,st),_),_ -> - raise (Parser.TypePath(sl @ [sm],Some(st,false),true)) - | ((IDKSubTypeField(sl,sm,st,sf) | IDKModuleField(sl,(sm as st),sf)),p),_ -> - let m = ctx.g.do_load_module ctx (sl,sm) p in - List.iter (fun t -> match t with - | TClassDecl c when snd c.cl_path = st -> - ignore(c.cl_build()); - let cf = PMap.find sf c.cl_statics in - Display.DisplayEmitter.display_field ctx.com.display cf p - | _ -> - () - ) m.m_types; - | (IDK,_),_ -> - () - -(* - In this pass, we can access load and access other modules types, but we cannot follow them or access their structure - since they have not been setup. We also build a context_init list that will be evaluated the first time we evaluate - an expression into the context -*) -let init_module_type ctx context_init do_init (decl,p) = - let get_type name = - try List.find (fun t -> snd (t_infos t).mt_path = name) ctx.m.curmod.m_types with Not_found -> assert false - in - let check_path_display path p = match ctx.com.display.dms_kind with - (* We cannot use ctx.is_display_file because the import could come from an import.hx file. *) - | DMDiagnostics b when (b || Display.is_display_file p.pfile) && not (ExtString.String.ends_with p.pfile "import.hx") -> - Display.ImportHandling.add_import_position ctx.com p path; - | DMStatistics | DMUsage _ -> - Display.ImportHandling.add_import_position ctx.com p path; - | _ -> - if Display.is_display_file p.pfile then handle_path_display ctx path p - in - match decl with - | EImport (path,mode) -> - ctx.m.module_imports <- (path,mode) :: ctx.m.module_imports; - check_path_display path p; - let rec loop acc = function - | x :: l when is_lower_ident (fst x) -> loop (x::acc) l - | rest -> List.rev acc, rest - in - let pack, rest = loop [] path in - (match rest with +let handle_using ctx path p = + let t = match List.rev path with + | (s1,_) :: (s2,_) :: sl -> + if is_lower_ident s2 then { tpackage = (List.rev (s2 :: List.map fst sl)); tname = s1; tsub = None; tparams = [] } + else { tpackage = List.rev (List.map fst sl); tname = s2; tsub = Some s1; tparams = [] } + | (s1,_) :: sl -> + { tpackage = List.rev (List.map fst sl); tname = s1; tsub = None; tparams = [] } | [] -> - (match mode with - | IAll -> - ctx.m.wildcard_packages <- (List.map fst pack,p) :: ctx.m.wildcard_packages - | _ -> - (match List.rev path with - | [] -> raise (Display.DisplayToplevel (Display.ToplevelCollector.run ctx true)); - | (_,p) :: _ -> error "Module name must start with an uppercase letter" p)) - | (tname,p2) :: rest -> - let p1 = (match pack with [] -> p2 | (_,p1) :: _ -> p1) in - let p_type = punion p1 p2 in - let md = ctx.g.do_load_module ctx (List.map fst pack,tname) p_type in - let types = md.m_types in - let no_private (t,_) = not (t_infos t).mt_private in - let chk_private t p = if (t_infos t).mt_private then error "You can't import a private type" p in - let has_name name t = snd (t_infos t).mt_path = name in - let get_type tname = - let t = (try List.find (has_name tname) types with Not_found -> error (StringError.string_error tname (List.map (fun mt -> snd (t_infos mt).mt_path) types) ("Module " ^ s_type_path md.m_path ^ " does not define type " ^ tname)) p_type) in - chk_private t p_type; - t - in - let rebind t name = - if not (name.[0] >= 'A' && name.[0] <= 'Z') then - error "Type aliases must start with an uppercase letter" p; - let _, _, f = ctx.g.do_build_instance ctx t p_type in - (* create a temp private typedef, does not register it in module *) - TTypeDecl { - t_path = (fst md.m_path @ ["_" ^ snd md.m_path],name); - t_module = md; - t_pos = p; - t_name_pos = null_pos; - t_private = true; - t_doc = None; - t_meta = []; - t_params = (t_infos t).mt_params; - t_type = f (List.map snd (t_infos t).mt_params); - } - in - let add_static_init t name s = - let name = (match name with None -> s | Some n -> n) in - match resolve_typedef t with - | TClassDecl c -> - ignore(c.cl_build()); - ignore(PMap.find s c.cl_statics); - ctx.m.module_globals <- PMap.add name (TClassDecl c,s,p) ctx.m.module_globals - | TEnumDecl e -> - ignore(PMap.find s e.e_constrs); - ctx.m.module_globals <- PMap.add name (TEnumDecl e,s,p) ctx.m.module_globals - | _ -> - raise Not_found - in - (match mode with - | INormal | IAsName _ -> - let name = (match mode with IAsName n -> Some n | _ -> None) in - (match rest with - | [] -> - (match name with - | None -> - ctx.m.module_types <- List.filter no_private (List.map (fun t -> t,p) types) @ ctx.m.module_types - | Some newname -> - ctx.m.module_types <- (rebind (get_type tname) newname,p) :: ctx.m.module_types); - | [tsub,p2] -> - let pu = punion p1 p2 in - (try - let tsub = List.find (has_name tsub) types in - chk_private tsub pu; - ctx.m.module_types <- ((match name with None -> tsub | Some n -> rebind tsub n),p) :: ctx.m.module_types - with Not_found -> - (* this might be a static property, wait later to check *) - let tmain = get_type tname in - context_init := (fun() -> - try - add_static_init tmain name tsub - with Not_found -> - error (s_type_path (t_infos tmain).mt_path ^ " has no field or subtype " ^ tsub) p - ) :: !context_init) - | (tsub,p2) :: (fname,p3) :: rest -> - (match rest with - | [] -> () - | (n,p) :: _ -> error ("Unexpected " ^ n) p); - let tsub = get_type tsub in - context_init := (fun() -> - try - add_static_init tsub name fname - with Not_found -> - error (s_type_path (t_infos tsub).mt_path ^ " has no field " ^ fname) (punion p p3) - ) :: !context_init; - ) - | IAll -> - let t = (match rest with - | [] -> get_type tname - | [tsub,_] -> get_type tsub - | _ :: (n,p) :: _ -> error ("Unexpected " ^ n) p - ) in - context_init := (fun() -> - match resolve_typedef t with - | TClassDecl c - | TAbstractDecl {a_impl = Some c} -> - ignore(c.cl_build()); - PMap.iter (fun _ cf -> if not (has_meta Meta.NoImportGlobal cf.cf_meta) then ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name,p) ctx.m.module_globals) c.cl_statics - | TEnumDecl e -> - PMap.iter (fun _ c -> if not (has_meta Meta.NoImportGlobal c.ef_meta) then ctx.m.module_globals <- PMap.add c.ef_name (TEnumDecl e,c.ef_name,p) ctx.m.module_globals) e.e_constrs - | _ -> - error "No statics to import from this type" p - ) :: !context_init - )) - | EUsing path -> - check_path_display path p; - let t = match List.rev path with - | (s1,_) :: (s2,_) :: sl -> - if is_lower_ident s2 then { tpackage = (List.rev (s2 :: List.map fst sl)); tname = s1; tsub = None; tparams = [] } - else { tpackage = List.rev (List.map fst sl); tname = s2; tsub = Some s1; tparams = [] } - | (s1,_) :: sl -> - { tpackage = List.rev (List.map fst sl); tname = s1; tsub = None; tparams = [] } - | [] -> - raise (Display.DisplayToplevel (Display.ToplevelCollector.run ctx true)); - in - (* do the import first *) - let types = (match t.tsub with - | None -> - let md = ctx.g.do_load_module ctx (t.tpackage,t.tname) p in - let types = List.filter (fun t -> not (t_infos t).mt_private) md.m_types in - ctx.m.module_types <- (List.map (fun t -> t,p) types) @ ctx.m.module_types; - types - | Some _ -> - let t = load_type_def ctx p t in - ctx.m.module_types <- (t,p) :: ctx.m.module_types; - [t] - ) in - (* delay the using since we need to resolve typedefs *) - let filter_classes types = - let rec loop acc types = match types with - | td :: l -> - (match resolve_typedef td with - | TClassDecl c | TAbstractDecl({a_impl = Some c}) -> - loop ((c,p) :: acc) l - | td -> - loop acc l) - | [] -> - acc - in - loop [] types - in - context_init := (fun() -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using) :: !context_init - | EClass d -> - let c = (match get_type (fst d.d_name) with TClassDecl c -> c | _ -> assert false) in - if ctx.is_display_file && Display.is_display_position (pos d.d_name) then - Display.DisplayEmitter.display_module_type ctx.com.display (match c.cl_kind with KAbstractImpl a -> TAbstractDecl a | _ -> TClassDecl c) (pos d.d_name); - check_global_metadata ctx c.cl_meta (fun m -> c.cl_meta <- m :: c.cl_meta) c.cl_module.m_path c.cl_path None; - let herits = d.d_flags in - c.cl_extern <- List.mem HExtern herits; - c.cl_interface <- List.mem HInterface herits; - let prev_build_count = ref (!build_count - 1) in - let build() = - let fl = Inheritance.set_heritance ctx c herits p in - let rec build() = - c.cl_build <- (fun()-> Building [c]); - try - List.iter (fun f -> f()) fl; - ClassInitializer.init_class ctx c p do_init d.d_flags d.d_data; - c.cl_build <- (fun()-> Built); - incr build_count; - List.iter (fun (_,t) -> ignore(follow t)) c.cl_params; - Built; - with Build_canceled state -> - c.cl_build <- make_pass ctx build; - let rebuild() = - delay_late ctx PBuildClass (fun() -> ignore(c.cl_build())); - in - (match state with - | Built -> assert false - | Building cl -> - if !build_count = !prev_build_count then error ("Loop in class building prevent compiler termination (" ^ String.concat "," (List.map (fun c -> s_type_path c.cl_path) cl) ^ ")") c.cl_pos; - prev_build_count := !build_count; - rebuild(); - Building (c :: cl) - | BuildMacro f -> - f := rebuild :: !f; - state); - | exn -> - c.cl_build <- (fun()-> Built); - raise exn - in - build() - in - ctx.pass <- PBuildClass; - ctx.curclass <- c; - c.cl_build <- make_pass ctx build; - ctx.pass <- PBuildModule; - ctx.curclass <- null_class; - delay ctx PBuildClass (fun() -> ignore(c.cl_build())); - if (ctx.com.platform = Java || ctx.com.platform = Cs) && not c.cl_extern then - delay ctx PTypeField (fun () -> - let metas = check_strict_meta ctx c.cl_meta in - if metas <> [] then c.cl_meta <- metas @ c.cl_meta; - let rec run_field cf = - let metas = check_strict_meta ctx cf.cf_meta in - if metas <> [] then cf.cf_meta <- metas @ cf.cf_meta; - List.iter run_field cf.cf_overloads - in - List.iter run_field c.cl_ordered_statics; - List.iter run_field c.cl_ordered_fields; - match c.cl_constructor with - | Some f -> run_field f - | _ -> () - ); - | EEnum d -> - let e = (match get_type (fst d.d_name) with TEnumDecl e -> e | _ -> assert false) in - if ctx.is_display_file && Display.is_display_position (pos d.d_name) then - Display.DisplayEmitter.display_module_type ctx.com.display (TEnumDecl e) (pos d.d_name); - let ctx = { ctx with type_params = e.e_params } in - let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in - check_global_metadata ctx e.e_meta (fun m -> e.e_meta <- m :: e.e_meta) e.e_module.m_path e.e_path None; - (match h with - | None -> () - | Some (h,hcl) -> - Hashtbl.iter (fun _ _ -> error "Field type patch not supported for enums" e.e_pos) h; - e.e_meta <- e.e_meta @ hcl.tp_meta); - let constructs = ref d.d_data in - let get_constructs() = - List.map (fun c -> - { - cff_name = c.ec_name; - cff_doc = c.ec_doc; - cff_meta = c.ec_meta; - cff_pos = c.ec_pos; - cff_access = []; - cff_kind = (match c.ec_args, c.ec_params with - | [], [] -> FVar (c.ec_type,None) - | _ -> FFun { f_params = c.ec_params; f_type = c.ec_type; f_expr = None; f_args = List.map (fun (n,o,t) -> (n,null_pos),o,[],Some t,None) c.ec_args }); - } - ) (!constructs) - in - let init () = List.iter (fun f -> f()) !context_init in - build_module_def ctx (TEnumDecl e) e.e_meta get_constructs init (fun (e,p) -> - match e with - | EVars [_,Some (CTAnonymous fields,p),None] -> - constructs := List.map (fun f -> - let args, params, t = (match f.cff_kind with - | FVar (t,None) -> [], [], t - | FFun { f_params = pl; f_type = t; f_expr = (None|Some (EBlock [],_)); f_args = al } -> - let al = List.map (fun ((n,_),o,_,t,_) -> match t with None -> error "Missing function parameter type" f.cff_pos | Some t -> n,o,t) al in - al, pl, t - | _ -> - error "Invalid enum constructor in @:build result" p - ) in - { - ec_name = f.cff_name; - ec_doc = f.cff_doc; - ec_meta = f.cff_meta; - ec_pos = f.cff_pos; - ec_args = args; - ec_params = params; - ec_type = t; - } - ) fields - | _ -> error "Enum build macro must return a single variable with anonymous object fields" p - ); - let et = TEnum (e,List.map snd e.e_params) in - let names = ref [] in - let index = ref 0 in - let is_flat = ref true in - let fields = ref PMap.empty in - List.iter (fun c -> - let p = c.ec_pos in - let params = ref [] in - params := type_type_params ~enum_constructor:true ctx ([],fst c.ec_name) (fun() -> !params) c.ec_pos c.ec_params; - let params = !params in - let ctx = { ctx with type_params = params @ ctx.type_params } in - let rt = (match c.ec_type with - | None -> et - | Some t -> - let t = load_complex_type ctx true p t in - (match follow t with - | TEnum (te,_) when te == e -> - () - | _ -> - error "Explicit enum type must be of the same enum type" p); - t - ) in - let t = (match c.ec_args with - | [] -> rt - | l -> - is_flat := false; - let pnames = ref PMap.empty in - TFun (List.map (fun (s,opt,(t,tp)) -> - (match t with CTPath({tpackage=[];tname="Void"}) -> error "Arguments of type Void are not allowed in enum constructors" c.ec_pos | _ -> ()); - if PMap.mem s (!pnames) then error ("Duplicate parameter '" ^ s ^ "' in enum constructor " ^ fst c.ec_name) p; - pnames := PMap.add s () (!pnames); - s, opt, load_type_hint ~opt ctx p (Some (t,tp)) - ) l, rt) - ) in - if PMap.mem (fst c.ec_name) e.e_constrs then error ("Duplicate constructor " ^ fst c.ec_name) p; - let f = { - ef_name = fst c.ec_name; - ef_type = t; - ef_pos = p; - ef_name_pos = snd c.ec_name; - ef_doc = c.ec_doc; - ef_index = !index; - ef_params = params; - ef_meta = c.ec_meta; - } in - let cf = { - (mk_field f.ef_name f.ef_type p f.ef_name_pos) with - cf_kind = (match follow f.ef_type with - | TFun _ -> Method MethNormal - | _ -> Var { v_read = AccNormal; v_write = AccNo } - ); - cf_doc = f.ef_doc; - cf_params = f.ef_params; - } in - if ctx.is_display_file && Display.is_display_position p then - Display.DisplayEmitter.display_enum_field ctx.com.display f p; - e.e_constrs <- PMap.add f.ef_name f e.e_constrs; - fields := PMap.add cf.cf_name cf !fields; - incr index; - names := (fst c.ec_name) :: !names; - ) (!constructs); - e.e_names <- List.rev !names; - e.e_extern <- e.e_extern; - e.e_type.t_params <- e.e_params; - e.e_type.t_type <- TAnon { - a_fields = !fields; - a_status = ref (EnumStatics e); - }; - if !is_flat then e.e_meta <- (Meta.FlatEnum,[],null_pos) :: e.e_meta; - - if (ctx.com.platform = Java || ctx.com.platform = Cs) && not e.e_extern then - delay ctx PTypeField (fun () -> - let metas = check_strict_meta ctx e.e_meta in - e.e_meta <- metas @ e.e_meta; - PMap.iter (fun _ ef -> - let metas = check_strict_meta ctx ef.ef_meta in - if metas <> [] then ef.ef_meta <- metas @ ef.ef_meta - ) e.e_constrs - ); - | ETypedef d -> - let t = (match get_type (fst d.d_name) with TTypeDecl t -> t | _ -> assert false) in - if ctx.is_display_file && Display.is_display_position (pos d.d_name) then - Display.DisplayEmitter.display_module_type ctx.com.display (TTypeDecl t) (pos d.d_name); - check_global_metadata ctx t.t_meta (fun m -> t.t_meta <- m :: t.t_meta) t.t_module.m_path t.t_path None; - let ctx = { ctx with type_params = t.t_params } in - let tt = load_complex_type ctx true p d.d_data in - let tt = (match fst d.d_data with - | CTExtend _ -> tt - | CTPath { tpackage = ["haxe";"macro"]; tname = "MacroType" } -> - (* we need to follow MacroType immediately since it might define other module types that we will load afterwards *) - if t.t_type == follow tt then error "Recursive typedef is not allowed" p; - tt - | _ -> - if (Meta.has Meta.Eager d.d_meta) then - follow tt - else begin - let rec check_rec tt = - if tt == t.t_type then error "Recursive typedef is not allowed" p; - match tt with - | TMono r -> - (match !r with - | None -> () - | Some t -> check_rec t) - | TLazy f -> - check_rec (lazy_type f); - | TType (td,tl) -> - if td == t then error "Recursive typedef is not allowed" p; - check_rec (apply_params td.t_params tl td.t_type) - | _ -> - () - in - let r = exc_protect ctx (fun r -> - r := lazy_processing (fun() -> tt); - check_rec tt; - tt - ) "typedef_rec_check" in - TLazy r - end - ) in - (match t.t_type with - | TMono r -> - (match !r with - | None -> r := Some tt; - | Some _ -> assert false); - | _ -> assert false); - if ctx.com.platform = Cs && t.t_meta <> [] then - delay ctx PTypeField (fun () -> - let metas = check_strict_meta ctx t.t_meta in - if metas <> [] then t.t_meta <- metas @ t.t_meta; - ); - | EAbstract d -> - let a = (match get_type (fst d.d_name) with TAbstractDecl a -> a | _ -> assert false) in - if ctx.is_display_file && Display.is_display_position (pos d.d_name) then - Display.DisplayEmitter.display_module_type ctx.com.display (TAbstractDecl a) (pos d.d_name); - check_global_metadata ctx a.a_meta (fun m -> a.a_meta <- m :: a.a_meta) a.a_module.m_path a.a_path None; - let ctx = { ctx with type_params = a.a_params } in - let is_type = ref false in - let load_type t from = - let t = load_complex_type ctx true p t in - let t = if not (Meta.has Meta.CoreType a.a_meta) then begin - if !is_type then begin - let r = exc_protect ctx (fun r -> - r := lazy_processing (fun() -> t); - let at = monomorphs a.a_params a.a_this in - (try (if from then Type.unify t at else Type.unify at t) with Unify_error _ -> error "You can only declare from/to with compatible types" p); - t - ) "constraint" in - TLazy r - end else - error "Missing underlying type declaration or @:coreType declaration" p; - end else begin - if Meta.has Meta.Callable a.a_meta then - error "@:coreType abstracts cannot be @:callable" p; - t - end in - t - in - List.iter (function - | AFromType t -> a.a_from <- (load_type t true) :: a.a_from - | AToType t -> a.a_to <- (load_type t false) :: a.a_to - | AIsType t -> - if a.a_impl = None then error "Abstracts with underlying type must have an implementation" a.a_pos; - if Meta.has Meta.CoreType a.a_meta then error "@:coreType abstracts cannot have an underlying type" p; - let at = load_complex_type ctx true p t in - delay ctx PForce (fun () -> - begin match follow at with - | TAbstract(a2,_) when a == a2 -> error "Abstract underlying type cannot be recursive" a.a_pos - | _ -> () - end; - ); - a.a_this <- at; - is_type := true; - | AExtern -> - (match a.a_impl with Some c -> c.cl_extern <- true | None -> (* Hmmmm.... *) ()) - | APrivAbstract -> () - ) d.d_flags; - if not !is_type then begin - if Meta.has Meta.CoreType a.a_meta then - a.a_this <- TAbstract(a,List.map snd a.a_params) - else - error "Abstract is missing underlying type declaration" a.a_pos - end - -let module_pass_2 ctx m decls tdecls p = - (* here is an additional PASS 1 phase, which define the type parameters for all module types. - Constraints are handled lazily (no other type is loaded) because they might be recursive anyway *) - List.iter (fun d -> - match d with - | (TClassDecl c, (EClass d, p)) -> - c.cl_params <- type_type_params ctx c.cl_path (fun() -> c.cl_params) p d.d_params; - if Meta.has Meta.Generic c.cl_meta && c.cl_params <> [] then c.cl_kind <- KGeneric; - if Meta.has Meta.GenericBuild c.cl_meta then begin - if ctx.in_macro then error "@:genericBuild cannot be used in macros" c.cl_pos; - c.cl_kind <- KGenericBuild d.d_data; - end; - if c.cl_path = (["haxe";"macro"],"MacroType") then c.cl_kind <- KMacroType; - | (TEnumDecl e, (EEnum d, p)) -> - e.e_params <- type_type_params ctx e.e_path (fun() -> e.e_params) p d.d_params; - | (TTypeDecl t, (ETypedef d, p)) -> - t.t_params <- type_type_params ctx t.t_path (fun() -> t.t_params) p d.d_params; - | (TAbstractDecl a, (EAbstract d, p)) -> - a.a_params <- type_type_params ctx a.a_path (fun() -> a.a_params) p d.d_params; - | _ -> - assert false - ) decls; - (* setup module types *) - let context_init = ref [] in - let do_init() = - match !context_init with - | [] -> () - | l -> context_init := []; List.iter (fun f -> f()) (List.rev l) - in - List.iter (init_module_type ctx context_init do_init) tdecls - -(* - Creates a module context for [m] and types [tdecls] using it. -*) -let type_types_into_module ctx m tdecls p = - let decls, tdecls = module_pass_1 ctx m tdecls p in - let types = List.map fst decls in - List.iter (check_module_types ctx m p) types; - m.m_types <- m.m_types @ types; - (* define the per-module context for the next pass *) - let ctx = { - com = ctx.com; - g = ctx.g; - t = ctx.t; - m = { - curmod = m; - module_types = List.map (fun t -> t,null_pos) ctx.g.std.m_types; - module_using = []; - module_globals = PMap.empty; - wildcard_packages = []; - module_imports = []; - }; - is_display_file = (ctx.com.display.dms_display && Display.is_display_file m.m_extra.m_file); - meta = []; - this_stack = []; - with_type_stack = []; - call_argument_stack = []; - pass = PBuildModule; - on_error = (fun ctx msg p -> ctx.com.error msg p); - macro_depth = ctx.macro_depth; - curclass = null_class; - curfield = null_field; - tthis = ctx.tthis; - ret = ctx.ret; - locals = PMap.empty; - type_params = []; - curfun = FunStatic; - untyped = false; - in_macro = ctx.in_macro; - in_display = false; - in_loop = false; - opened = []; - in_call_args = false; - vthis = None; - } in - if ctx.g.std != null_module then begin - add_dependency m ctx.g.std; - (* this will ensure both String and (indirectly) Array which are basic types which might be referenced *) - ignore(load_core_type ctx "String"); - end; - module_pass_2 ctx m decls tdecls p; - ctx - -let handle_import_hx ctx m decls p = - let path_split = match List.rev (Path.get_path_parts m.m_extra.m_file) with - | [] -> [] - | _ :: l -> l - in - let join l = String.concat Path.path_sep (List.rev ("import.hx" :: l)) in - let rec loop path pack = match path,pack with - | _,[] -> [join path] - | (p :: path),(_ :: pack) -> (join (p :: path)) :: (loop path pack) - | _ -> [] - in - let candidates = loop path_split (fst m.m_path) in - let make_import_module path r = - Hashtbl.replace ctx.com.parser_cache path r; - (* We use the file path as module name to make it unique. This may or may not be a good idea... *) - let m_import = make_module ctx ([],path) path p in - m_import.m_extra.m_kind <- MImport; - add_module ctx m_import p; - m_import - in - List.fold_left (fun acc path -> - let decls = try - let r = Hashtbl.find ctx.com.parser_cache path in - let mimport = Hashtbl.find ctx.g.modules ([],path) in - if mimport.m_extra.m_kind <> MFake then add_dependency m mimport; - r - with Not_found -> - if Sys.file_exists path then begin - let _,r = parse_file ctx.com path p in - List.iter (fun (d,p) -> match d with EImport _ | EUsing _ -> () | _ -> error "Only import and using is allowed in import.hx files" p) r; - add_dependency m (make_import_module path r); - r - end else begin - let r = [] in - (* Add empty decls so we don't check the file system all the time. *) - (make_import_module path r).m_extra.m_kind <- MFake; - r - end - in - decls @ acc - ) decls candidates - -(* - Creates a new module and types [tdecls] into it. -*) -let type_module ctx mpath file ?(is_extern=false) tdecls p = - let m = make_module ctx mpath file p in - Hashtbl.add ctx.g.modules m.m_path m; - let tdecls = handle_import_hx ctx m tdecls p in - let ctx = type_types_into_module ctx m tdecls p in - if is_extern then m.m_extra.m_kind <- MExtern; - begin if ctx.is_display_file then match ctx.com.display.dms_kind with - | DMResolve s -> - resolve_position_by_path ctx {tname = s; tpackage = []; tsub = None; tparams = []} p - | _ -> - () - end; - m - -let resolve_module_file com m remap p = - let forbid = ref false in - let compose_path no_rename = - (match m with - | [] , name -> name - | x :: l , name -> - let x = (try - match PMap.find x com.package_rules with - | Forbidden -> forbid := true; x - | Directory d -> if no_rename then x else d - | Remap d -> remap := d :: l; d - with Not_found -> x - ) in - String.concat "/" (x :: l) ^ "/" ^ name - ) ^ ".hx" + DisplayException.raise_fields (DisplayToplevel.collect ctx TKType NoValue) CRUsing None; in - let file = try - Common.find_file com (compose_path false) - with Not_found -> - Common.find_file com (compose_path true) - in - let file = (match String.lowercase (snd m) with - | "con" | "aux" | "prn" | "nul" | "com1" | "com2" | "com3" | "lpt1" | "lpt2" | "lpt3" when Sys.os_type = "Win32" -> - (* these names are reserved by the OS - old DOS legacy, such files cannot be easily created but are reported as visible *) - if (try (Unix.stat file).Unix.st_size with _ -> 0) > 0 then file else raise Not_found - | _ -> file - ) in - (* if we try to load a std.xxxx class and resolve a real std file, the package name is not valid, ignore *) - (match fst m with - | "std" :: _ -> - let file = Path.unique_full_path file in - if List.exists (fun path -> ExtString.String.starts_with file (try Path.unique_full_path path with _ -> path)) com.std_path then raise Not_found; - | _ -> ()); - if !forbid then begin - let _, decls = (!parse_hook) com file p in - let rec loop decls = match decls with - | ((EImport _,_) | (EUsing _,_)) :: decls -> loop decls - | (EClass d,_) :: _ -> d.d_meta - | (EEnum d,_) :: _ -> d.d_meta - | (EAbstract d,_) :: _ -> d.d_meta - | (ETypedef d,_) :: _ -> d.d_meta - | [] -> [] - in - let meta = loop decls in - if not (Meta.has Meta.NoPackageRestrict meta) then begin - let x = (match fst m with [] -> assert false | x :: _ -> x) in - raise (Forbid_package ((x,m,p),[],if Common.defined com Define.Macro then "macro" else platform_name com.platform)); - end; - end; - file - -let parse_module ctx m p = - let remap = ref (fst m) in - let file = resolve_module_file ctx.com m remap p in - let pack, decls = (!parse_hook) ctx.com file p in - if pack <> !remap then begin - let spack m = if m = [] then "" else String.concat "." m in - if p == null_pos then - display_error ctx ("Invalid commandline class : " ^ s_type_path m ^ " should be " ^ s_type_path (pack,snd m)) p - else - display_error ctx ("Invalid package : " ^ spack (fst m) ^ " should be " ^ spack pack) p - end; - file, if !remap <> fst m then - (* build typedefs to redirect to real package *) - List.rev (List.fold_left (fun acc (t,p) -> - let build f d = - let priv = List.mem f d.d_flags in - (ETypedef { - d_name = d.d_name; - d_doc = None; - d_meta = []; - d_params = d.d_params; - d_flags = if priv then [EPrivate] else []; - d_data = CTPath (if priv then { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; } else - { - tpackage = !remap; - tname = fst d.d_name; - tparams = List.map (fun tp -> - TPType (CTPath { tpackage = []; tname = fst tp.tp_name; tparams = []; tsub = None; },null_pos) - ) d.d_params; - tsub = None; - }),null_pos; - },p) :: acc - in - match t with - | EClass d -> build HPrivate d - | EEnum d -> build EPrivate d - | ETypedef d -> build EPrivate d - | EAbstract d -> build APrivAbstract d - | EImport _ | EUsing _ -> acc - ) [(EImport (List.map (fun s -> s,null_pos) (!remap @ [snd m]),INormal),null_pos)] decls) - else - decls - -let load_module ctx m p = - let m2 = (try - Hashtbl.find ctx.g.modules m - with - Not_found -> - match !type_module_hook ctx m p with - | Some m -> m - | None -> - let is_extern = ref false in - let file, decls = (try - parse_module ctx m p - with Not_found -> - let rec loop = function - | [] -> - raise (Error (Module_not_found m,p)) - | load :: l -> - match load m p with - | None -> loop l - | Some (file,(_,a)) -> file, a - in - is_extern := true; - loop ctx.com.load_extern_type - ) in - let is_extern = !is_extern in - try - type_module ctx m file ~is_extern decls p - with Forbid_package (inf,pl,pf) when p <> null_pos -> - raise (Forbid_package (inf,p::pl,pf)) + let types = (match t.tsub with + | None -> + let md = ctx.g.do_load_module ctx (t.tpackage,t.tname) p in + let types = List.filter (fun t -> not (t_infos t).mt_private) md.m_types in + types + | Some _ -> + let t = load_type_def ctx p t in + [t] ) in - add_dependency ctx.m.curmod m2; - if ctx.pass = PTypeField then flush_pass ctx PBuildClass "load_module"; - m2 - -;; -type_function_params_rec := type_function_params - -(* -------------------------------------------------------------------------- *) -(* generic classes *) - -exception Generic_Exception of string * pos - -type generic_context = { - ctx : typer; - subst : (t * t) list; - name : string; - p : pos; - mutable mg : module_def option; -} - -let make_generic ctx ps pt p = - let rec loop l1 l2 = - match l1, l2 with - | [] , [] -> [] - | (x,TLazy f) :: l1, _ -> loop ((x,lazy_type f) :: l1) l2 - | (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2 - | _ -> assert false - in - let name = - String.concat "_" (List.map2 (fun (s,_) t -> - let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in - let rec loop top t = match follow t with - | TInst(c,tl) -> (s_type_path_underscore c.cl_path) ^ (loop_tl tl) - | TEnum(en,tl) -> (s_type_path_underscore en.e_path) ^ (loop_tl tl) - | TAbstract(a,tl) -> (s_type_path_underscore a.a_path) ^ (loop_tl tl) - | _ when not top -> "_" (* allow unknown/incompatible types as type parameters to retain old behavior *) - | TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p)) - | TDynamic _ -> "Dynamic" - | t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p)) - and loop_tl tl = match tl with - | [] -> "" - | tl -> "_" ^ String.concat "_" (List.map (loop false) tl) - in - loop true t - ) ps pt) - in - { - ctx = ctx; - subst = loop ps pt; - name = name; - p = p; - mg = None; - } - -let rec generic_substitute_type gctx t = - match t with - | TInst ({ cl_kind = KGeneric } as c2,tl2) -> - (* maybe loop, or generate cascading generics *) - let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in - let t = f (List.map (generic_substitute_type gctx) tl2) in - (match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ()); - t - | _ -> - try - generic_substitute_type gctx (List.assq t gctx.subst) - with Not_found -> - Type.map (generic_substitute_type gctx) t - -let generic_substitute_expr gctx e = - let vars = Hashtbl.create 0 in - let build_var v = - try - Hashtbl.find vars v.v_id - with Not_found -> - let v2 = alloc_var v.v_name (generic_substitute_type gctx v.v_type) v.v_pos in - v2.v_meta <- v.v_meta; - Hashtbl.add vars v.v_id v2; - v2 - in - let rec build_expr e = - match e.eexpr with - | TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) -> - let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c) gctx.p in - let t = f (List.map (generic_substitute_type gctx) tl) in - let fa = try - quick_field t cf.cf_name - with Not_found -> - error (Printf.sprintf "Type %s has no field %s (possible typing order issue)" (s_type (print_context()) t) cf.cf_name) e.epos - in - build_expr {e with eexpr = TField(e1,fa)} - | TTypeExpr (TClassDecl ({cl_kind = KTypeParameter _;} as c)) when Meta.has Meta.Const c.cl_meta -> - let rec loop subst = match subst with - | (t1,t2) :: subst -> - begin match follow t1 with - | TInst(c2,_) when c == c2 -> t2 - | _ -> loop subst - end - | [] -> raise Not_found - in - begin try - let t = loop gctx.subst in - begin match follow t with - | TInst({cl_kind = KExpr e},_) -> type_expr gctx.ctx e Value - | _ -> error "Only Const type parameters can be used as value" e.epos - end - with Not_found -> - e - end - | _ -> - map_expr_type build_expr (generic_substitute_type gctx) build_var e - in - build_expr e - -let get_short_name = - let i = ref (-1) in - (fun () -> - incr i; - Printf.sprintf "Hx___short___hx_type_%i" !i - ) - -let rec build_generic ctx c p tl = - let pack = fst c.cl_path in - let recurse = ref false in - let rec check_recursive t = - match follow t with - | TInst (c2,tl) -> - (match c2.cl_kind with - | KTypeParameter tl -> - if not (is_generic_parameter ctx c2) && has_ctor_constraint c2 then - error "Type parameters with a constructor cannot be used non-generically" p; - recurse := true - | _ -> ()); - List.iter check_recursive tl; - | _ -> - () - in - List.iter check_recursive tl; - if !recurse || not (ctx.com.display.dms_full_typing) then begin - TInst (c,tl) (* build a normal instance *) - end else begin - let gctx = make_generic ctx c.cl_params tl p in - let name = (snd c.cl_path) ^ "_" ^ gctx.name in - try - load_instance ctx ({ tpackage = pack; tname = name; tparams = []; tsub = None },p) false p - with Error(Module_not_found path,_) when path = (pack,name) -> - let m = (try Hashtbl.find ctx.g.modules (Hashtbl.find ctx.g.types_module c.cl_path) with Not_found -> assert false) in - (* let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in *) - ignore(c.cl_build()); (* make sure the super class is already setup *) - let mg = { - m_id = alloc_mid(); - m_path = (pack,name); - m_types = []; - m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake m.m_extra.m_check_policy; - } in - gctx.mg <- Some mg; - let cg = mk_class mg (pack,name) c.cl_pos null_pos in - mg.m_types <- [TClassDecl cg]; - Hashtbl.add ctx.g.modules mg.m_path mg; - add_dependency mg m; - add_dependency ctx.m.curmod mg; - (* ensure that type parameters are set in dependencies *) - let dep_stack = ref [] in - let rec loop t = - if not (List.memq t !dep_stack) then begin - dep_stack := t :: !dep_stack; - match t with - | TInst (c,tl) -> add_dep c.cl_module tl - | TEnum (e,tl) -> add_dep e.e_module tl - | TType (t,tl) -> add_dep t.t_module tl - | TAbstract (a,tl) -> add_dep a.a_module tl - | TMono r -> - (match !r with - | None -> () - | Some t -> loop t) - | TLazy f -> - loop (lazy_type f); - | TDynamic t2 -> - if t == t2 then () else loop t2 - | TAnon a -> - PMap.iter (fun _ f -> loop f.cf_type) a.a_fields - | TFun (args,ret) -> - List.iter (fun (_,_,t) -> loop t) args; - loop ret - end - and add_dep m tl = - add_dependency mg m; - List.iter loop tl - in - List.iter loop tl; - let build_field cf_old = - (* We have to clone the type parameters (issue #4672). We cannot substitute the constraints immediately because - we need the full substitution list first. *) - let param_subst,params = List.fold_left (fun (subst,params) (s,t) -> match follow t with - | TInst(c,tl) as t -> - let t2 = TInst({c with cl_pos = c.cl_pos;},tl) in - (t,t2) :: subst,(s,t2) :: params - | _ -> assert false - ) ([],[]) cf_old.cf_params in - let gctx = {gctx with subst = param_subst @ gctx.subst} in - let cf_new = {cf_old with cf_pos = cf_old.cf_pos} in (* copy *) - (* Type parameter constraints are substituted here. *) - cf_new.cf_params <- List.rev_map (fun (s,t) -> match follow t with - | TInst({cl_kind = KTypeParameter tl1} as c,_) -> - let tl1 = List.map (generic_substitute_type gctx) tl1 in - c.cl_kind <- KTypeParameter tl1; - s,t - | _ -> assert false - ) params; - let f () = - let t = generic_substitute_type gctx cf_old.cf_type in - ignore (follow t); - begin try (match cf_old.cf_expr with - | None -> - begin match cf_old.cf_kind with - | Method _ when not c.cl_interface && not c.cl_extern -> - display_error ctx (Printf.sprintf "Field %s has no expression (possible typing order issue)" cf_new.cf_name) cf_new.cf_pos; - display_error ctx (Printf.sprintf "While building %s" (s_type_path cg.cl_path)) p; - | _ -> - () - end - | Some e -> - cf_new.cf_expr <- Some (generic_substitute_expr gctx e) - ) with Unify_error l -> - error (error_msg (Unify l)) cf_new.cf_pos - end; - t - in - let r = exc_protect ctx (fun r -> - let t = mk_mono() in - r := lazy_processing (fun() -> t); - unify_raise ctx (f()) t p; - t - ) "build_generic" in - cf_new.cf_type <- TLazy r; - cf_new + (* delay the using since we need to resolve typedefs *) + let filter_classes types = + let rec loop acc types = match types with + | td :: l -> + (match resolve_typedef td with + | TClassDecl c | TAbstractDecl({a_impl = Some c}) -> + loop ((c,p) :: acc) l + | td -> + loop acc l) + | [] -> + acc in - if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p; - List.iter (fun cf -> match cf.cf_kind with - | Method MethMacro when not ctx.in_macro -> () - | _ -> error "A generic class can't have static fields" cf.cf_pos - ) c.cl_ordered_statics; - cg.cl_super <- (match c.cl_super with - | None -> None - | Some (cs,pl) -> - let ts = follow (apply_params c.cl_params tl (TInst(cs,pl))) in - let cs,pl = Inheritance.check_extends ctx c ts p in - match cs.cl_kind with - | KGeneric -> - (match build_generic ctx cs p pl with - | TInst (cs,pl) -> Some (cs,pl) - | _ -> assert false) - | _ -> Some(cs,pl) - ); - add_constructor ctx cg false p; - cg.cl_kind <- KGenericInstance (c,tl); - cg.cl_meta <- (Meta.NoDoc,[],null_pos) :: cg.cl_meta; - if has_meta Meta.Keep c.cl_meta then cg.cl_meta <- (Meta.Keep,[],null_pos) :: cg.cl_meta; - cg.cl_interface <- c.cl_interface; - cg.cl_constructor <- (match cg.cl_constructor, c.cl_constructor, c.cl_super with - | _, Some cf, _ -> Some (build_field cf) - | Some ctor, _, _ -> Some ctor - | None, None, None -> None - | _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos - ); - cg.cl_implements <- List.map (fun (i,tl) -> - (match follow (generic_substitute_type gctx (TInst (i, List.map (generic_substitute_type gctx) tl))) with - | TInst (i,tl) -> i, tl - | _ -> assert false) - ) c.cl_implements; - cg.cl_ordered_fields <- List.map (fun f -> - let f = build_field f in - cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields; - f - ) c.cl_ordered_fields; - cg.cl_overrides <- List.map (fun f -> - try PMap.find f.cf_name cg.cl_fields with Not_found -> assert false - ) c.cl_overrides; - (* In rare cases the class name can become too long, so let's shorten it (issue #3090). *) - if String.length (snd cg.cl_path) > 254 then begin - let n = get_short_name () in - cg.cl_meta <- (Meta.Native,[EConst(String (n)),p],null_pos) :: cg.cl_meta; - end; - TInst (cg,[]) - end - -(* -------------------------------------------------------------------------- *) -(* MACRO TYPE *) - -let get_macro_path ctx e args p = - let rec loop e = - match fst e with - | EField (e,f) -> f :: loop e - | EConst (Ident i) -> [i] - | _ -> error "Invalid macro call" p - in - let path = match e with - | (EConst(Ident i)),_ -> - let path = try - if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found; - ctx.curclass.cl_path - with Not_found -> try - (t_infos (let path,_,_ = PMap.find i ctx.m.module_globals in path)).mt_path - with Not_found -> - error "Invalid macro call" p - in - i :: (snd path) :: (fst path) - | _ -> - loop e - in - (match path with - | meth :: cl :: path -> (List.rev path,cl), meth, args - | _ -> error "Invalid macro call" p) - -let build_macro_type ctx pl p = - let path, field, args = (match pl with - | [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)] - | [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] -> - get_macro_path ctx e args p - | _ -> - error "MacroType requires a single expression call parameter" p - ) in - let old = ctx.ret in - let t = (match ctx.g.do_macro ctx MMacroType path field args p with - | None -> mk_mono() - | Some _ -> ctx.ret - ) in - ctx.ret <- old; - t - -let build_macro_build ctx c pl cfl p = - let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with - | _,[ECall(e,args),_],_ -> get_macro_path ctx e args p - | _ -> error "genericBuild requires a single expression call parameter" p + loop [] types in - let old = ctx.ret,ctx.g.get_build_infos in - ctx.g.get_build_infos <- (fun() -> Some (TClassDecl c, pl, cfl)); - let t = (match ctx.g.do_macro ctx MMacroType path field args p with - | None -> mk_mono() - | Some _ -> ctx.ret - ) in - ctx.ret <- fst old; - ctx.g.get_build_infos <- snd old; - t - -(* -------------------------------------------------------------------------- *) -(* API EVENTS *) - -let build_instance ctx mtype p = - match mtype with - | TClassDecl c -> - if ctx.pass > PBuildClass then ignore(c.cl_build()); - let build f s = - let r = exc_protect ctx (fun r -> - let t = mk_mono() in - r := lazy_processing (fun() -> t); - let tf = (f()) in - unify_raise ctx tf t p; - link_dynamic t tf; - if ctx.pass >= PBuildClass then flush_pass ctx PBuildClass "after_build_instance"; - t - ) s in - TLazy r - in - let ft = (fun pl -> - match c.cl_kind with - | KGeneric -> - build (fun () -> build_generic ctx c p pl) "build_generic" - | KMacroType -> - build (fun () -> build_macro_type ctx pl p) "macro_type" - | KGenericBuild cfl -> - build (fun () -> build_macro_build ctx c pl cfl p) "generic_build" - | _ -> - TInst (c,pl) - ) in - c.cl_params , c.cl_path , ft - | TEnumDecl e -> - e.e_params , e.e_path , (fun t -> TEnum (e,t)) - | TTypeDecl t -> - t.t_params , t.t_path , (fun tl -> TType(t,tl)) - | TAbstractDecl a -> - a.a_params, a.a_path, (fun tl -> TAbstract(a,tl)) + types,filter_classes \ No newline at end of file diff --git a/src/typing/typeloadCheck.ml b/src/typing/typeloadCheck.ml new file mode 100644 index 00000000000..ff28dbab25c --- /dev/null +++ b/src/typing/typeloadCheck.ml @@ -0,0 +1,545 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(* Various checks performed while loading types. *) + +open Globals +open Ast +open Type +open Typecore +open DisplayException +open DisplayTypes +open DisplayMode +open CompletionItem +open CompletionModuleKind +open CompletionModuleType +open CompletionResultKind +open Common +open Error + +exception Build_canceled of build_state + +let is_generic_parameter ctx c = + (* first check field parameters, then class parameters *) + try + ignore (List.assoc (snd c.cl_path) ctx.curfield.cf_params); + Meta.has Meta.Generic ctx.curfield.cf_meta + with Not_found -> try + ignore(List.assoc (snd c.cl_path) ctx.type_params); + (match ctx.curclass.cl_kind with | KGeneric -> true | _ -> false); + with Not_found -> + false + +let valid_redefinition ctx f1 t1 f2 t2 = (* child, parent *) + let valid t1 t2 = + Type.unify t1 t2; + if is_null t1 <> is_null t2 || ((follow t1) == t_dynamic && (follow t2) != t_dynamic) then raise (Unify_error [Cannot_unify (t1,t2)]); + in + let open OptimizerTexpr in + begin match PurityState.get_purity_from_meta f2.cf_meta,PurityState.get_purity_from_meta f1.cf_meta with + | PurityState.Pure,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),f2.cf_pos],null_pos) :: f1.cf_meta + | PurityState.ExpectPure p,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),p],null_pos) :: f1.cf_meta + | _ -> () + end; + let t1, t2 = (match f1.cf_params, f2.cf_params with + | [], [] -> t1, t2 + | l1, l2 when List.length l1 = List.length l2 -> + let to_check = ref [] in + let monos = List.map2 (fun (name,p1) (_,p2) -> + (match follow p1, follow p2 with + | TInst ({ cl_kind = KTypeParameter ct1 } as c1,pl1), TInst ({ cl_kind = KTypeParameter ct2 } as c2,pl2) -> + (match ct1, ct2 with + | [], [] -> () + | _, _ when List.length ct1 = List.length ct2 -> + (* if same constraints, they are the same type *) + let check monos = + List.iter2 (fun t1 t2 -> + try + let t1 = apply_params l1 monos (apply_params c1.cl_params pl1 t1) in + let t2 = apply_params l2 monos (apply_params c2.cl_params pl2 t2) in + type_eq EqStrict t1 t2 + with Unify_error l -> + raise (Unify_error (Unify_custom "Constraints differ" :: l)) + ) ct1 ct2 + in + to_check := check :: !to_check; + | _ -> + raise (Unify_error [Unify_custom "Different number of constraints"])) + | _ -> ()); + TInst (mk_class null_module ([],name) null_pos null_pos,[]) + ) l1 l2 in + List.iter (fun f -> f monos) !to_check; + apply_params l1 monos t1, apply_params l2 monos t2 + | _ -> + (* ignore type params, will create other errors later *) + t1, t2 + ) in + match f1.cf_kind,f2.cf_kind with + | Method m1, Method m2 when not (m1 = MethDynamic) && not (m2 = MethDynamic) -> + begin match follow t1, follow t2 with + | TFun (args1,r1) , TFun (args2,r2) -> ( + if not (List.length args1 = List.length args2) then raise (Unify_error [Unify_custom "Different number of function arguments"]); + let i = ref 0 in + try + valid r1 r2; + List.iter2 (fun (n,o1,a1) (_,o2,a2) -> + incr i; + if o1 <> o2 then raise (Unify_error [Not_matching_optional n]); + (try valid a2 a1 with Unify_error _ -> raise (Unify_error [Cannot_unify(a1,a2)])) + ) args1 args2; + with Unify_error l -> + let msg = if !i = 0 then Invalid_return_type else Invalid_function_argument(!i,List.length args1) in + raise (Unify_error (Cannot_unify (t1,t2) :: msg :: l))) + | _ -> + assert false + end + | _,(Var { v_write = AccNo | AccNever }) -> + (* write variance *) + valid t1 t2 + | _,(Var { v_read = AccNo | AccNever }) -> + (* read variance *) + valid t2 t1 + | _,_ when has_class_field_flag f2 CfFinal -> + (* write variance *) + valid t1 t2 + | _ , _ -> + (* in case args differs, or if an interface var *) + type_eq EqStrict t1 t2; + if is_null t1 <> is_null t2 then raise (Unify_error [Cannot_unify (t1,t2)]) + +let copy_meta meta_src meta_target sl = + let meta = ref meta_target in + List.iter (fun (m,e,p) -> + if List.mem m sl then meta := (m,e,p) :: !meta + ) meta_src; + !meta + +(** retrieve string from @:native metadata or raise Not_found *) +let get_native_name meta = + let rec get_native meta = match meta with + | [] -> raise Not_found + | (Meta.Native,[v],p as meta) :: _ -> + meta + | _ :: meta -> + get_native meta + in + let (_,e,mp) = get_native meta in + match e with + | [Ast.EConst (Ast.String name),p] -> + name,p + | [] -> + raise Not_found + | _ -> + error "String expected" mp + +let check_native_name_override ctx child base = + let error() = + display_error ctx ("Field " ^ child.cf_name ^ " has different @:native value than in superclass") child.cf_pos; + display_error ctx ("Base field is defined here") base.cf_pos + in + try + let native_name = fst (get_native_name child.cf_meta) in + try if fst (get_native_name base.cf_meta) <> native_name then error() + with Not_found -> error() + with Not_found -> () + +let check_overriding ctx c f = + match c.cl_super with + | None -> + if List.memq f c.cl_overrides then display_error ctx ("Field " ^ f.cf_name ^ " is declared 'override' but doesn't override any field") f.cf_pos + | _ when c.cl_extern && Meta.has Meta.CsNative c.cl_meta -> () (* -net-lib specific: do not check overrides on extern CsNative classes *) + | Some (csup,params) -> + let p = f.cf_pos in + let i = f.cf_name in + let check_field f get_super_field is_overload = try + (if is_overload && not (Meta.has Meta.Overload f.cf_meta) then + display_error ctx ("Missing @:overload declaration for field " ^ i) p); + let t, f2 = get_super_field csup i in + check_native_name_override ctx f f2; + (* allow to define fields that are not defined for this platform version in superclass *) + (match f2.cf_kind with + | Var { v_read = AccRequire _ } -> raise Not_found; + | _ -> ()); + if ctx.com.config.pf_overload && (Meta.has Meta.Overload f2.cf_meta && not (Meta.has Meta.Overload f.cf_meta)) then + display_error ctx ("Field " ^ i ^ " should be declared with @:overload since it was already declared as @:overload in superclass") p + else if not (List.memq f c.cl_overrides) then + display_error ctx ("Field " ^ i ^ " should be declared with 'override' since it is inherited from superclass " ^ s_type_path csup.cl_path) p + else if not (has_class_field_flag f CfPublic) && (has_class_field_flag f2 CfPublic) then + display_error ctx ("Field " ^ i ^ " has less visibility (public/private) than superclass one") p + else (match f.cf_kind, f2.cf_kind with + | _, Method MethInline -> + display_error ctx ("Field " ^ i ^ " is inlined and cannot be overridden") p + | a, b when a = b -> () + | Method MethInline, Method MethNormal -> + () (* allow to redefine a method as inlined *) + | _ -> + display_error ctx ("Field " ^ i ^ " has different property access than in superclass") p); + if (has_class_field_flag f2 CfFinal) then display_error ctx ("Cannot override final method " ^ i) p; + try + let t = apply_params csup.cl_params params t in + valid_redefinition ctx f f.cf_type f2 t; + add_class_field_flag f2 CfOverridden; + with + Unify_error l -> + display_error ctx ("Field " ^ i ^ " overrides parent class with different or incomplete type") p; + display_error ctx ("Base field is defined here") f2.cf_pos; + display_error ctx (error_msg (Unify l)) p; + with + Not_found -> + if List.memq f c.cl_overrides then + let msg = if is_overload then + ("Field " ^ i ^ " is declared 'override' but no compatible overload was found") + else begin + let fields = TClass.get_all_super_fields c in + let fields = PMap.fold (fun (_,cf) acc -> match cf.cf_kind with + | Method MethNormal when not (has_class_field_flag cf CfFinal) -> cf.cf_name :: acc + | _ -> acc + ) fields [] in + StringError.string_error i fields ("Field " ^ i ^ " is declared 'override' but doesn't override any field") + end in + display_error ctx msg p + in + if ctx.com.config.pf_overload && Meta.has Meta.Overload f.cf_meta then begin + let overloads = Overloads.get_overloads csup i in + List.iter (fun (t,f2) -> + (* check if any super class fields are vars *) + match f2.cf_kind with + | Var _ -> + display_error ctx ("A variable named '" ^ f2.cf_name ^ "' was already declared in a superclass") f.cf_pos + | _ -> () + ) overloads; + List.iter (fun f -> + (* find the exact field being overridden *) + check_field f (fun csup i -> + List.find (fun (t,f2) -> + Overloads.same_overload_args f.cf_type (apply_params csup.cl_params params t) f f2 + ) overloads + ) true + ) (f :: f.cf_overloads) + end else + check_field f (fun csup i -> + let _, t, f2 = raw_class_field (fun f -> f.cf_type) csup params i in + t, f2) false + +let class_field_no_interf c i = + try + let f = PMap.find i c.cl_fields in + f.cf_type , f + with Not_found -> + match c.cl_super with + | None -> + raise Not_found + | Some (c,tl) -> + (* rec over class_field *) + let _, t , f = raw_class_field (fun f -> f.cf_type) c tl i in + apply_params c.cl_params tl t , f + +let rec return_flow ctx e = + let error() = + display_error ctx (Printf.sprintf "Missing return: %s" (s_type (print_context()) ctx.ret)) e.epos; raise Exit + in + let return_flow = return_flow ctx in + let rec uncond e = match e.eexpr with + | TIf _ | TWhile _ | TSwitch _ | TTry _ | TFunction _ -> () + | TReturn _ | TThrow _ -> raise Exit + | _ -> Type.iter uncond e + in + let has_unconditional_flow e = try uncond e; false with Exit -> true in + match e.eexpr with + | TReturn _ | TThrow _ -> () + | TParenthesis e | TMeta(_,e) -> + return_flow e + | TBlock el -> + let rec loop = function + | [] -> error() + | [e] -> return_flow e + | e :: _ when has_unconditional_flow e -> () + | _ :: l -> loop l + in + loop el + | TIf (_,e1,Some e2) -> + return_flow e1; + return_flow e2; + | TSwitch (v,cases,Some e) -> + List.iter (fun (_,e) -> return_flow e) cases; + return_flow e + | TSwitch ({eexpr = TMeta((Meta.Exhaustive,_,_),_)},cases,None) -> + List.iter (fun (_,e) -> return_flow e) cases; + | TTry (e,cases) -> + return_flow e; + List.iter (fun (_,e) -> return_flow e) cases; + | TWhile({eexpr = (TConst (TBool true))},e,_) -> + (* a special case for "inifite" while loops that have no break *) + let rec loop e = match e.eexpr with + (* ignore nested loops to not accidentally get one of its breaks *) + | TWhile _ | TFor _ -> () + | TBreak -> error() + | _ -> Type.iter loop e + in + loop e + | _ -> + error() + +let check_global_metadata ctx meta f_add mpath tpath so = + let sl1 = full_dot_path2 mpath tpath in + let sl1,field_mode = match so with None -> sl1,false | Some s -> sl1 @ [s],true in + List.iter (fun (sl2,m,(recursive,to_types,to_fields)) -> + let add = ((field_mode && to_fields) || (not field_mode && to_types)) && (match_path recursive sl1 sl2) in + if add then f_add m + ) ctx.g.global_metadata; + if ctx.is_display_file then delay ctx PCheckConstraint (fun () -> DisplayEmitter.check_display_metadata ctx meta) + +let check_module_types ctx m p t = + let t = t_infos t in + try + let m2 = Hashtbl.find ctx.g.types_module t.mt_path in + if m.m_path <> m2 && String.lowercase (s_type_path m2) = String.lowercase (s_type_path m.m_path) then error ("Module " ^ s_type_path m2 ^ " is loaded with a different case than " ^ s_type_path m.m_path) p; + error ("Type name " ^ s_type_path t.mt_path ^ " is redefined from module " ^ s_type_path m2) p + with + Not_found -> + Hashtbl.add ctx.g.types_module t.mt_path m.m_path + +module Inheritance = struct + let is_basic_class_path path = match path with + | ([],("Array" | "String" | "Date" | "Xml")) -> true + | _ -> false + + let check_extends ctx c t p = match follow t with + | TInst (csup,params) -> + if is_basic_class_path csup.cl_path && not (c.cl_extern && csup.cl_extern) then error "Cannot extend basic class" p; + if is_parent c csup then error "Recursive class" p; + begin match csup.cl_kind with + | KTypeParameter _ -> + if is_generic_parameter ctx csup then error "Extending generic type parameters is no longer allowed in Haxe 4" p; + error "Cannot extend type parameters" p + | _ -> csup,params + end + | _ -> error "Should extend by using a class" p + + let rec check_interface ctx c intf params = + let p = c.cl_pos in + let rec check_field i f = + (if ctx.com.config.pf_overload then + List.iter (function + | f2 when f != f2 -> + check_field i f2 + | _ -> ()) f.cf_overloads); + let is_overload = ref false in + try + let t2, f2 = class_field_no_interf c i in + let t2, f2 = + if ctx.com.config.pf_overload && (f2.cf_overloads <> [] || Meta.has Meta.Overload f2.cf_meta) then + let overloads = Overloads.get_overloads c i in + is_overload := true; + let t = (apply_params intf.cl_params params f.cf_type) in + List.find (fun (t1,f1) -> Overloads.same_overload_args t t1 f f1) overloads + else + t2, f2 + in + if ctx.com.display.dms_collect_data then begin + let h = ctx.com.display_information in + h.interface_field_implementations <- (intf,f,c,Some f2) :: h.interface_field_implementations; + end; + ignore(follow f2.cf_type); (* force evaluation *) + let p = (match f2.cf_expr with None -> p | Some e -> e.epos) in + let mkind = function + | MethNormal | MethInline -> 0 + | MethDynamic -> 1 + | MethMacro -> 2 + in + if (has_class_field_flag f CfPublic) && not (has_class_field_flag f2 CfPublic) && not (Meta.has Meta.CompilerGenerated f.cf_meta) then + display_error ctx ("Field " ^ i ^ " should be public as requested by " ^ s_type_path intf.cl_path) p + else if not (unify_kind f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then + display_error ctx ("Field " ^ i ^ " has different property access than in " ^ s_type_path intf.cl_path ^ " (" ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind ^ ")") p + else try + valid_redefinition ctx f2 t2 f (apply_params intf.cl_params params f.cf_type) + with + Unify_error l -> + if not (Meta.has Meta.CsNative c.cl_meta && c.cl_extern) then begin + display_error ctx ("Field " ^ i ^ " has different type than in " ^ s_type_path intf.cl_path) p; + display_error ctx ("Interface field is defined here") f.cf_pos; + display_error ctx (error_msg (Unify l)) p; + end + with + | Not_found when not c.cl_interface -> + let msg = if !is_overload then + let ctx = print_context() in + let args = match follow f.cf_type with | TFun(args,_) -> String.concat ", " (List.map (fun (n,o,t) -> (if o then "?" else "") ^ n ^ " : " ^ (s_type ctx t)) args) | _ -> assert false in + "No suitable overload for " ^ i ^ "( " ^ args ^ " ), as needed by " ^ s_type_path intf.cl_path ^ " was found" + else + ("Field " ^ i ^ " needed by " ^ s_type_path intf.cl_path ^ " is missing") + in + display_error ctx msg p + | Not_found -> () + in + PMap.iter check_field intf.cl_fields; + List.iter (fun (i2,p2) -> + check_interface ctx c i2 (List.map (apply_params intf.cl_params params) p2) + ) intf.cl_implements + + let check_interfaces ctx c = + match c.cl_path with + | "Proxy" :: _ , _ -> () + | _ when c.cl_extern && Meta.has Meta.CsNative c.cl_meta -> () + | _ -> + List.iter (fun (intf,params) -> check_interface ctx c intf params) c.cl_implements + + let set_heritance ctx c herits p = + let is_lib = Meta.has Meta.LibType c.cl_meta in + let ctx = { ctx with curclass = c; type_params = c.cl_params; } in + let old_meta = c.cl_meta in + let process_meta csup = + List.iter (fun m -> + match m with + | Meta.AutoBuild, el, p -> c.cl_meta <- (Meta.Build,el,{ c.cl_pos with pmax = c.cl_pos.pmin }(* prevent display metadata *)) :: m :: c.cl_meta + | _ -> () + ) csup.cl_meta; + if csup.cl_final && not ((csup.cl_extern && Meta.has Meta.Hack c.cl_meta) || (match c.cl_kind with KTypeParameter _ -> true | _ -> false)) then + error ("Cannot extend a final " ^ if c.cl_interface then "interface" else "class") p; + in + let check_cancel_build csup = + match csup.cl_build() with + | Built -> () + | state -> + (* for macros reason, our super class is not yet built - see #2177 *) + (* let's reset our build and delay it until we are done *) + c.cl_meta <- old_meta; + raise (Build_canceled state) + in + let has_interf = ref false in + (* + resolve imports before calling build_inheritance, since it requires full paths. + that means that typedefs are not working, but that's a fair limitation + *) + let resolve_imports (t,p) = + match t.tpackage with + | _ :: _ -> t,p + | [] -> + try + let path_matches lt = snd (t_path lt) = t.tname in + let lt = try + List.find path_matches ctx.m.curmod.m_types + with Not_found -> + let t,pi = List.find (fun (lt,_) -> path_matches lt) ctx.m.module_types in + ImportHandling.mark_import_position ctx.com pi; + t + in + { t with tpackage = fst (t_path lt) },p + with + Not_found -> t,p + in + let herits = ExtList.List.filter_map (function + | HExtends t -> Some(true,resolve_imports t) + | HImplements t -> Some(false,resolve_imports t) + | t -> None + ) herits in + let herits = List.filter (ctx.g.do_inherit ctx c p) herits in + (* Pass 1: Check and set relations *) + let check_herit t is_extends p = + if is_extends then begin + if c.cl_super <> None then error "Cannot extend several classes" p; + let csup,params = check_extends ctx c t p in + if c.cl_interface then begin + if not csup.cl_interface then error "Cannot extend by using a class" p; + c.cl_implements <- (csup,params) :: c.cl_implements; + if not !has_interf then begin + if not is_lib then delay ctx PForce (fun() -> check_interfaces ctx c); + has_interf := true; + end + end else begin + if csup.cl_interface then error "Cannot extend by using an interface" p; + c.cl_super <- Some (csup,params) + end; + (fun () -> + check_cancel_build csup; + process_meta csup; + ) + end else begin match follow t with + | TInst ({ cl_path = [],"ArrayAccess"; cl_extern = true; },[t]) -> + if c.cl_array_access <> None then error "Duplicate array access" p; + c.cl_array_access <- Some t; + (fun () -> ()) + | TInst (intf,params) -> + if is_parent c intf then error "Recursive class" p; + if c.cl_interface then error "Interfaces cannot implement another interface (use extends instead)" p; + if not intf.cl_interface then error "You can only implement an interface" p; + c.cl_implements <- (intf, params) :: c.cl_implements; + if not !has_interf && not is_lib && not (Meta.has (Meta.Custom "$do_not_check_interf") c.cl_meta) then begin + delay ctx PForce (fun() -> check_interfaces ctx c); + has_interf := true; + end; + (fun () -> + check_cancel_build intf; + process_meta intf; + ) + | TDynamic t -> + if c.cl_dynamic <> None then error "Cannot have several dynamics" p; + if not c.cl_extern then display_error ctx "In haxe 4, implements Dynamic is only supported on externs" p; + c.cl_dynamic <- Some t; + (fun () -> ()) + | _ -> + error "Should implement by using an interface" p + end + in + let fl = ExtList.List.filter_map (fun (is_extends,(ct,p)) -> + try + let t = try + Typeload.load_instance ~allow_display:true ctx (ct,p) false + with DisplayException(DisplayFields Some({fkind = CRTypeHint} as r)) -> + (* We don't allow `implements` on interfaces. Just raise fields completion with no fields. *) + if not is_extends && c.cl_interface then raise_fields [] CRImplements r.finsert_pos; + let l = List.filter (fun item -> match item.ci_kind with + | ITType({kind = Interface} as cm,_) -> (not is_extends || c.cl_interface) && CompletionModuleType.get_path cm <> c.cl_path + | ITType({kind = Class} as cm,_) -> + is_extends && not c.cl_interface && CompletionModuleType.get_path cm <> c.cl_path && + (not cm.is_final || Meta.has Meta.Hack c.cl_meta) && + (not (is_basic_class_path (cm.pack,cm.name)) || (c.cl_extern && cm.is_extern)) + | _ -> false + ) r.fitems in + raise_fields l (if is_extends then CRExtends else CRImplements) r.finsert_pos + in + Some (check_herit t is_extends p) + with Error(Module_not_found(([],name)),p) when ctx.com.display.dms_kind <> DMNone -> + if Diagnostics.is_diagnostics_run p then DisplayToplevel.handle_unresolved_identifier ctx name p true; + None + ) herits in + fl +end + +let check_final_vars ctx e = + let final_vars = Hashtbl.create 0 in + List.iter (fun cf -> match cf.cf_kind with + | Var _ when (has_class_field_flag cf CfFinal) && cf.cf_expr = None -> + Hashtbl.add final_vars cf.cf_name cf + | _ -> + () + ) ctx.curclass.cl_ordered_fields; + if Hashtbl.length final_vars > 0 then begin + let rec find_inits e = match e.eexpr with + | TBinop(OpAssign,{eexpr = TField({eexpr = TConst TThis},fa)},e2) -> + Hashtbl.remove final_vars (field_name fa); + find_inits e2; + | _ -> + Type.iter find_inits e + in + find_inits e; + Hashtbl.iter (fun _ cf -> + display_error ctx ("final field " ^ cf.cf_name ^ " must be initialized immediately or in the constructor") cf.cf_pos; + ) final_vars + end \ No newline at end of file diff --git a/src/typing/typeloadFields.ml b/src/typing/typeloadFields.ml new file mode 100644 index 00000000000..28d4fbee632 --- /dev/null +++ b/src/typing/typeloadFields.ml @@ -0,0 +1,1528 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(* Logic for building fields. *) + +open Globals +open Ast +open Type +open Typecore +open Typeload +open DisplayTypes.DisplayMode +open CompletionItem.ClassFieldOrigin +open Common +open Error + +type class_init_ctx = { + tclass : tclass; (* I don't trust ctx.curclass because it's mutable. *) + is_lib : bool; + is_native : bool; + is_core_api : bool; + is_class_debug : bool; + extends_public : bool; + abstract : tabstract option; + context_init : unit -> unit; + mutable has_display_field : bool; + mutable delayed_expr : (typer * tlazy ref option) list; + mutable force_constructor : bool; + mutable uninitialized_final : pos option; +} + +type field_kind = + | FKNormal + | FKConstructor + | FKInit + +type field_init_ctx = { + is_inline : bool; + is_final : bool; + is_static : bool; + override : pos option; + is_extern : bool; + is_macro : bool; + is_abstract_member : bool; + is_display_field : bool; + is_field_debug : bool; + field_kind : field_kind; + display_modifier : placed_access option; + mutable do_bind : bool; + mutable do_add : bool; + (* If true, cf_expr = None makes a difference in the logic. We insert a dummy expression in + display mode in order to address this. *) + mutable expr_presence_matters : bool; +} + +let locate_macro_error = ref true + +let dump_class_context cctx = + Printer.s_record_fields "" [ + "tclass",Printer.s_tclass "\t" cctx.tclass; + "is_lib",string_of_bool cctx.is_lib; + "is_native",string_of_bool cctx.is_native; + "is_core_api",string_of_bool cctx.is_core_api; + "is_class_debug",string_of_bool cctx.is_class_debug; + "extends_public",string_of_bool cctx.extends_public; + "abstract",Printer.s_opt (Printer.s_tabstract "\t") cctx.abstract; + "force_constructor",string_of_bool cctx.force_constructor; + ] + +let s_field_kind = function + | FKNormal -> "FKNormal" + | FKConstructor -> "FKConstructor" + | FKInit -> "FKInit" + +let dump_field_context fctx = + Printer.s_record_fields "" [ + "is_inline",string_of_bool fctx.is_inline; + "is_static",string_of_bool fctx.is_static; + "is_extern",string_of_bool fctx.is_extern; + "is_macro",string_of_bool fctx.is_macro; + "is_abstract_member",string_of_bool fctx.is_abstract_member; + "is_display_field",string_of_bool fctx.is_display_field; + "is_field_debug",string_of_bool fctx.is_field_debug; + "field_kind",s_field_kind fctx.field_kind; + "do_bind",string_of_bool fctx.do_bind; + "do_add",string_of_bool fctx.do_add; + "expr_presence_matters",string_of_bool fctx.expr_presence_matters; + ] + + +let is_java_native_function meta = try + match Meta.get Meta.Native meta with + | (Meta.Native,[],_) -> true + | _ -> false + with | Not_found -> false + +(**** end of strict meta handling *****) + +let get_method_args field = + match field.cf_expr with + | Some { eexpr = TFunction { tf_args = args } } -> args + | _ -> raise Not_found + +(** + Get super constructor data required for @:structInit descendants. +*) +let get_struct_init_super_info ctx c p = + match c.cl_super with + | Some ({ cl_constructor = Some ctor } as csup, cparams) -> + let args = (try get_method_args ctor with Not_found -> []) in + let tl,el = + List.fold_left (fun (args,exprs) (v,value) -> + let opt = match value with Some _ -> true | None -> false in + let t = if opt then ctx.t.tnull v.v_type else v.v_type in + (v.v_name,opt,t) :: args,(mk (TLocal v) v.v_type p) :: exprs + ) ([],[]) args + in + let super_expr = mk (TCall (mk (TConst TSuper) (TInst (csup,cparams)) p, el)) ctx.t.tvoid p in + (args,Some super_expr,tl) + | _ -> + [],None,[] + +(** + Generates a constructor for a @:structInit class `c` if it does not have one yet. +*) +let ensure_struct_init_constructor ctx c ast_fields p = + match c.cl_constructor with + | Some _ -> + () + | None -> + let field_has_default_expr field_name = + List.exists + (fun ast_field -> + match ast_field.cff_name with + | (name, _) when name <> field_name -> false + | _ -> + match ast_field.cff_kind with + | FVar (_, Some _) | FProp (_, _, _, Some _) -> true + | _ -> false + ) + ast_fields + in + let super_args,super_expr,super_tl = get_struct_init_super_info ctx c p in + let params = List.map snd c.cl_params in + let ethis = mk (TConst TThis) (TInst(c,params)) p in + let args,el,tl = List.fold_left (fun (args,el,tl) cf -> match cf.cf_kind with + | Var _ -> + let has_default_expr = field_has_default_expr cf.cf_name in + let opt = has_default_expr || (Meta.has Meta.Optional cf.cf_meta) in + let t = if opt then ctx.t.tnull cf.cf_type else cf.cf_type in + let v = alloc_var VGenerated cf.cf_name t p in + let ef = mk (TField(ethis,FInstance(c,params,cf))) cf.cf_type p in + let ev = mk (TLocal v) v.v_type p in + (* this.field = *) + let assign_expr = mk (TBinop(OpAssign,ef,ev)) cf.cf_type p in + let e = + if has_default_expr then + begin + (* != null *) + let condition = mk (TBinop(OpNotEq, ev, (null t p))) ctx.t.tbool p in + (* if( != null) this.field = *) + mk (TIf(condition, assign_expr, None)) ctx.t.tvoid p + end + else + assign_expr + in + (v,None) :: args,e :: el,(cf.cf_name,opt,t) :: tl + | Method _ -> + args,el,tl + ) ([],[],[]) (List.rev c.cl_ordered_fields) in + let el = match super_expr with Some e -> e :: el | None -> el in + let tf = { + tf_args = args @ super_args; + tf_type = ctx.t.tvoid; + tf_expr = mk (TBlock el) ctx.t.tvoid p + } in + let e = mk (TFunction tf) (TFun(tl @ super_tl,ctx.t.tvoid)) p in + let cf = mk_field "new" e.etype p null_pos in + cf.cf_expr <- Some e; + cf.cf_type <- e.etype; + cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos]; + cf.cf_kind <- Method MethNormal; + c.cl_constructor <- Some cf + +let transform_abstract_field com this_t a_t a f = + let stat = List.mem_assoc AStatic f.cff_access in + let p = f.cff_pos in + match f.cff_kind with + | FProp ((("get" | "never"),_),(("set" | "never"),_),_,_) when not stat -> + (* TODO: hack to avoid issues with abstract property generation on As3 *) + if Common.defined com Define.As3 then f.cff_access <- (AExtern,null_pos) :: f.cff_access; + { f with cff_access = (AStatic,null_pos) :: f.cff_access; cff_meta = (Meta.Impl,[],null_pos) :: f.cff_meta } + | FProp _ when not stat -> + error "Member property accessors must be get/set or never" p; + | FFun fu when fst f.cff_name = "new" && not stat -> + let init p = (EVars [("this",null_pos),false,Some this_t,None],p) in + let cast e = (ECast(e,None)),pos e in + let ret p = (EReturn (Some (cast (EConst (Ident "this"),p))),p) in + let meta = (Meta.Impl,[],null_pos) :: (Meta.NoCompletion,[],null_pos) :: f.cff_meta in + if Meta.has Meta.MultiType a.a_meta then begin + if List.mem_assoc AInline f.cff_access then error "MultiType constructors cannot be inline" f.cff_pos; + if fu.f_expr <> None then error "MultiType constructors cannot have a body" f.cff_pos; + f.cff_access <- (AExtern,null_pos) :: f.cff_access; + end; + (try + let _, p = List.find (fun (acc, _) -> acc = AMacro) f.cff_access in + error "Macro abstract constructors are not supported" p + with Not_found -> ()); + (* We don't want the generated expression positions to shadow the real code. *) + let p = { p with pmax = p.pmin } in + let fu = { + fu with + f_expr = (match fu.f_expr with + | None -> None + | Some (EBlock el,_) -> Some (EBlock (init p :: el @ [ret p]),p) + | Some e -> Some (EBlock [init p;e;ret p],p) + ); + f_type = Some a_t; + } in + { f with cff_name = "_new",pos f.cff_name; cff_access = (AStatic,null_pos) :: f.cff_access; cff_kind = FFun fu; cff_meta = meta } + | FFun fu when not stat -> + if Meta.has Meta.From f.cff_meta then error "@:from cast functions must be static" f.cff_pos; + let fu = { fu with f_args = (if List.mem_assoc AMacro f.cff_access then fu.f_args else (("this",null_pos),false,[],Some this_t,None) :: fu.f_args) } in + { f with cff_kind = FFun fu; cff_access = (AStatic,null_pos) :: f.cff_access; cff_meta = (Meta.Impl,[],null_pos) :: f.cff_meta } + | _ -> + f + +let patch_class ctx c fields = + let path = match c.cl_kind with + | KAbstractImpl a -> a.a_path + | _ -> c.cl_path + in + let h = (try Some (Hashtbl.find ctx.g.type_patches path) with Not_found -> None) in + match h with + | None -> fields + | Some (h,hcl) -> + c.cl_meta <- c.cl_meta @ hcl.tp_meta; + let patch_getter t fn = + { fn with f_type = t } + in + let patch_setter t fn = + match fn.f_args with + | [(name,opt,meta,_,expr)] -> + { fn with f_args = [(name,opt,meta,t,expr)]; f_type = t } + | _ -> fn + in + let rec loop acc accessor_acc = function + | [] -> acc, accessor_acc + | f :: l -> + (* patch arguments types *) + (match f.cff_kind with + | FFun ff -> + let param (((n,pn),opt,m,_,e) as p) = + try + let t2 = (try Hashtbl.find h (("$" ^ (fst f.cff_name) ^ "__" ^ n),false) with Not_found -> Hashtbl.find h (("$" ^ n),false)) in + (n,pn), opt, m, (match t2.tp_type with None -> None | Some t -> Some (t,null_pos)), e + with Not_found -> + p + in + f.cff_kind <- FFun { ff with f_args = List.map param ff.f_args } + | _ -> ()); + (* other patches *) + match (try Some (Hashtbl.find h (fst f.cff_name,List.mem_assoc AStatic f.cff_access)) with Not_found -> None) with + | None -> loop (f :: acc) accessor_acc l + | Some { tp_remove = true } -> loop acc accessor_acc l + | Some p -> + f.cff_meta <- f.cff_meta @ p.tp_meta; + let accessor_acc = + match p.tp_type with + | None -> accessor_acc + | Some t -> + match f.cff_kind with + | FVar (_,e) -> + f.cff_kind <- FVar (Some (t,null_pos),e); accessor_acc + | FProp (get,set,_,eo) -> + let typehint = Some (t,null_pos) in + let accessor_acc = if fst get = "get" then ("get_" ^ fst f.cff_name, patch_getter typehint) :: accessor_acc else accessor_acc in + let accessor_acc = if fst set = "set" then ("set_" ^ fst f.cff_name, patch_setter typehint) :: accessor_acc else accessor_acc in + f.cff_kind <- FProp (get,set,typehint,eo); accessor_acc + | FFun fn -> + f.cff_kind <- FFun { fn with f_type = Some (t,null_pos) }; accessor_acc + in + loop (f :: acc) accessor_acc l + in + let fields, accessor_patches = loop [] [] fields in + List.iter (fun (accessor_name, patch) -> + try + let f_accessor = List.find (fun f -> fst f.cff_name = accessor_name) fields in + match f_accessor.cff_kind with + | FFun fn -> f_accessor.cff_kind <- FFun (patch fn) + | _ -> () + with Not_found -> + () + ) accessor_patches; + List.rev fields + +let lazy_display_type ctx f = + (* if ctx.is_display_file then begin + let r = exc_protect ctx (fun r -> + let t = f () in + r := lazy_processing (fun () -> t); + t + ) "" in + TLazy r + end else *) + f () + +type enum_abstract_mode = + | EAString + | EAInt of int ref + | EAOther + +let build_enum_abstract ctx c a fields p = + let mode = + if does_unify a.a_this ctx.t.tint then EAInt (ref 0) + else if does_unify a.a_this ctx.t.tstring then EAString + else EAOther + in + List.iter (fun field -> + match field.cff_kind with + | FVar(ct,eo) when not (List.mem_assoc AStatic field.cff_access) -> + field.cff_access <- [AStatic,null_pos; if (List.mem_assoc APrivate field.cff_access) then (APrivate,null_pos) else (APublic,null_pos)]; + field.cff_meta <- (Meta.Enum,[],null_pos) :: (Meta.Impl,[],null_pos) :: field.cff_meta; + let ct = match ct with + | Some _ -> ct + | None -> Some (TExprToExpr.convert_type (TAbstract(a,List.map snd a.a_params)),null_pos) + in + let set_field e = + field.cff_access <- (AInline,null_pos) :: field.cff_access; + let e = (ECast(e,None),(pos e)) in + field.cff_kind <- FVar(ct,Some e) + in + begin match eo with + | None -> + if not c.cl_extern then begin match mode with + | EAString -> + set_field (EConst (String (fst field.cff_name)),null_pos) + | EAInt i -> + set_field (EConst (Int (string_of_int !i)),null_pos); + incr i; + | EAOther -> + error "Value required" field.cff_pos + end else field.cff_kind <- FProp(("default",null_pos),("never",null_pos),ct,None) + | Some e -> + begin match mode,e with + | EAInt i,(EConst(Int s),_) -> + begin try + let i' = int_of_string s in + i := (i' + 1) + with _ -> + () + end + | _ -> () + end; + set_field e + end + | _ -> + () + ) fields; + EVars [("",null_pos),false,Some (CTAnonymous fields,p),None],p + +let apply_macro ctx mode path el p = + let cpath, meth = (match List.rev (ExtString.String.nsplit path ".") with + | meth :: name :: pack -> (List.rev pack,name), meth + | _ -> error "Invalid macro path" p + ) in + ctx.g.do_macro ctx mode cpath meth el p + +let build_module_def ctx mt meta fvars context_init fbuild = + let loop (f_build,f_enum) = function + | Meta.Build,args,p -> (fun () -> + let epath, el = (match args with + | [ECall (epath,el),p] -> epath, el + | _ -> error "Invalid build parameters" p + ) in + let s = try String.concat "." (List.rev (string_list_of_expr_path epath)) with Error (_,p) -> error "Build call parameter must be a class path" p in + if ctx.in_macro then error "You cannot use @:build inside a macro : make sure that your type is not used in macro" p; + let old = ctx.get_build_infos in + ctx.get_build_infos <- (fun() -> Some (mt, List.map snd (t_infos mt).mt_params, fvars())); + context_init(); + let r = try apply_macro ctx MBuild s el p with e -> ctx.get_build_infos <- old; raise e in + ctx.get_build_infos <- old; + (match r with + | None -> error "Build failure" p + | Some e -> fbuild e) + ) :: f_build,f_enum + | Meta.Enum,_,p -> f_build,Some (fun () -> + begin match mt with + | TClassDecl ({cl_kind = KAbstractImpl a} as c) -> + (* if p <> null_pos && not (Define.is_haxe3_compat ctx.com.defines) then + ctx.com.warning "`@:enum abstract` is deprecated in favor of `enum abstract`" p; *) + context_init(); + let e = build_enum_abstract ctx c a (fvars()) p in + fbuild e; + | _ -> + () + end + ) + | Meta.Using,el,p -> (fun () -> + List.iter (fun e -> + try + let path = List.rev (string_pos_list_of_expr_path_raise e) in + let types,filter_classes = handle_using ctx path (pos e) in + let ti = + match mt with + | TClassDecl { cl_kind = KAbstractImpl a } -> t_infos (TAbstractDecl a) + | _ -> t_infos mt + in + ti.mt_using <- (filter_classes types) @ ti.mt_using; + with Exit -> + error "dot path expected" (pos e) + ) el; + ) :: f_build,f_enum + | _ -> + f_build,f_enum + in + (* let errors go through to prevent resume if build fails *) + let f_build,f_enum = List.fold_left loop ([],None) meta in + (* Go for @:using in parents and interfaces *) + (match mt with + | TClassDecl { cl_super = csup; cl_implements = interfaces; cl_kind = kind } -> + let ti = t_infos mt in + let inherit_using (c,_) = + ti.mt_using <- ti.mt_using @ (t_infos (TClassDecl c)).mt_using + in + Option.may inherit_using csup; + List.iter inherit_using interfaces + | _ -> () + ); + List.iter (fun f -> f()) (List.rev f_build); + (match f_enum with None -> () | Some f -> f()) + +let create_class_context ctx c context_init p = + locate_macro_error := true; + incr stats.s_classes_built; + let abstract = match c.cl_kind with + | KAbstractImpl a -> Some a + | _ -> None + in + let ctx = { + ctx with + curclass = c; + type_params = c.cl_params; + pass = PBuildClass; + tthis = (match abstract with + | Some a -> + (match a.a_this with + | TMono r when !r = None -> TAbstract (a,List.map snd c.cl_params) + | t -> t) + | None -> TInst (c,List.map snd c.cl_params)); + on_error = (fun ctx msg ep -> + ctx.com.error msg ep; + (* macros expressions might reference other code, let's recall which class we are actually compiling *) + if !locate_macro_error && (ep.pfile <> c.cl_pos.pfile || ep.pmax < c.cl_pos.pmin || ep.pmin > c.cl_pos.pmax) then ctx.com.error "Defined in this class" c.cl_pos + ); + } in + (* a lib type will skip most checks *) + let is_lib = Meta.has Meta.LibType c.cl_meta in + if is_lib && not c.cl_extern then ctx.com.error "@:libType can only be used in extern classes" c.cl_pos; + (* a native type will skip one check: the static vs non-static field *) + let is_native = Meta.has Meta.JavaNative c.cl_meta || Meta.has Meta.CsNative c.cl_meta in + if Meta.has Meta.Macro c.cl_meta then display_error ctx "Macro classes are no longer allowed in haxe 3" c.cl_pos; + let rec extends_public c = + Meta.has Meta.PublicFields c.cl_meta || + match c.cl_super with + | None -> false + | Some (c,_) -> extends_public c + in + let cctx = { + tclass = c; + is_lib = is_lib; + is_native = is_native; + is_core_api = Meta.has Meta.CoreApi c.cl_meta; + is_class_debug = Meta.has (Meta.Custom ":debug.typeload") c.cl_meta; + extends_public = extends_public c; + abstract = abstract; + context_init = context_init; + force_constructor = false; + uninitialized_final = None; + delayed_expr = []; + has_display_field = false; + } in + ctx,cctx + +let create_field_context (ctx,cctx) c cff = + let ctx = { + ctx with + pass = PBuildClass; (* will be set later to PTypeExpr *) + } in + let display_modifier = Typeload.check_field_access ctx cff in + let is_static = List.mem_assoc AStatic cff.cff_access in + let is_extern = ref (List.mem_assoc AExtern cff.cff_access) in + let is_final = ref (List.mem_assoc AFinal cff.cff_access) in + List.iter (fun (m,_,p) -> + match m with + | Meta.Final -> + is_final := true; + (* if p <> null_pos && not (Define.is_haxe3_compat ctx.com.defines) then + ctx.com.warning "`@:final` is deprecated in favor of `final`" p; *) + | Meta.Extern -> + (* if not (Define.is_haxe3_compat ctx.com.defines) then + ctx.com.warning "`@:extern` on fields is deprecated in favor of `extern`" (pos cff.cff_name); *) + is_extern := true; + | _ -> + () + ) cff.cff_meta; + let allow_inline = cctx.abstract <> None || match cff.cff_kind with + | FFun _ -> ctx.g.doinline || !is_extern || c.cl_extern + | _ -> true + in + let is_inline = allow_inline && List.mem_assoc AInline cff.cff_access in + let override = try Some (List.assoc AOverride cff.cff_access) with Not_found -> None in + let is_macro = List.mem_assoc AMacro cff.cff_access in + let field_kind = match fst cff.cff_name with + | "new" -> FKConstructor + | "__init__" when is_static -> FKInit + | _ -> FKNormal + in + let fctx = { + is_inline = is_inline; + is_static = is_static; + override = override; + is_macro = is_macro; + is_extern = !is_extern; + is_final = !is_final; + is_display_field = ctx.is_display_file && DisplayPosition.display_position#enclosed_in cff.cff_pos; + is_field_debug = cctx.is_class_debug || Meta.has (Meta.Custom ":debug.typeload") cff.cff_meta; + display_modifier = display_modifier; + is_abstract_member = cctx.abstract <> None && Meta.has Meta.Impl cff.cff_meta; + field_kind = field_kind; + do_bind = (((not (c.cl_extern || !is_extern) || is_inline) && not c.cl_interface) || field_kind = FKInit); + do_add = true; + expr_presence_matters = false; + } in + if fctx.is_display_field then cctx.has_display_field <- true; + ctx,fctx + +let is_public (ctx,cctx) access parent = + let c = cctx.tclass in + if List.mem_assoc APrivate access then + false + else if List.mem_assoc APublic access then + true + else match parent with + | Some cf -> (has_class_field_flag cf CfPublic) + | _ -> c.cl_extern || c.cl_interface || cctx.extends_public + +let rec get_parent c name = + match c.cl_super with + | None -> None + | Some (csup,_) -> + try + Some (PMap.find name csup.cl_fields) + with + Not_found -> get_parent csup name + +let add_field c cf is_static = + if is_static then begin + c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics; + c.cl_ordered_statics <- cf :: c.cl_ordered_statics; + end else begin + c.cl_fields <- PMap.add cf.cf_name cf c.cl_fields; + c.cl_ordered_fields <- cf :: c.cl_ordered_fields; + end + +let type_opt (ctx,cctx) p t = + let c = cctx.tclass in + match t with + | None when c.cl_extern || c.cl_interface -> + display_error ctx "Type required for extern classes and interfaces" p; + t_dynamic + | None when cctx.is_core_api -> + display_error ctx "Type required for core api classes" p; + t_dynamic + | _ -> + load_type_hint ctx p t + +let build_fields (ctx,cctx) c fields = + let fields = ref fields in + let get_fields() = !fields in + let pending = ref [] in + c.cl_build <- (fun() -> BuildMacro pending); + build_module_def ctx (TClassDecl c) c.cl_meta get_fields cctx.context_init (fun (e,p) -> + match e with + | EVars [_,_,Some (CTAnonymous f,p),None] -> + let f = List.map (fun f -> + let f = match cctx.abstract with + | Some a -> + let a_t = TExprToExpr.convert_type' (TAbstract(a,List.map snd a.a_params)) in + let this_t = TExprToExpr.convert_type' a.a_this in (* TODO: better pos? *) + transform_abstract_field ctx.com this_t a_t a f + | None -> + f + in + if List.mem_assoc AMacro f.cff_access then + (match ctx.g.macros with + | Some (_,mctx) when Hashtbl.mem mctx.g.types_module c.cl_path -> + (* assume that if we had already a macro with the same name, it has not been changed during the @:build operation *) + if not (List.exists (fun f2 -> f2.cff_name = f.cff_name && List.mem_assoc AMacro f2.cff_access) (!fields)) then + error "Class build macro cannot return a macro function when the class has already been compiled into the macro context" p + | _ -> ()); + f + ) f in + fields := f + | _ -> error "Class build macro must return a single variable with anonymous fields" p + ); + c.cl_build <- (fun() -> Building [c]); + List.iter (fun f -> f()) !pending; + !fields + +let bind_type (ctx,cctx,fctx) cf r p = + let c = cctx.tclass in + let rec is_full_type t = + match t with + | TFun (args,ret) -> is_full_type ret && List.for_all (fun (_,_,t) -> is_full_type t) args + | TMono r -> (match !r with None -> false | Some t -> is_full_type t) + | TAbstract _ | TInst _ | TEnum _ | TLazy _ | TDynamic _ | TAnon _ | TType _ -> true + in + let force_macro () = + (* force macro system loading of this class in order to get completion *) + delay ctx PTypeField (fun() -> try ignore(ctx.g.do_macro ctx MDisplay c.cl_path cf.cf_name [] p) with Exit | Error _ -> ()) + in + let handle_display_field () = + if fctx.is_macro && not ctx.in_macro then + force_macro() + else begin + cf.cf_type <- TLazy r; + cctx.delayed_expr <- (ctx,Some r) :: cctx.delayed_expr; + end + in + if ctx.com.display.dms_full_typing then begin + if fctx.is_macro && not ctx.in_macro then + () + else begin + cf.cf_type <- TLazy r; + (* is_lib ? *) + cctx.delayed_expr <- (ctx,Some r) :: cctx.delayed_expr; + end + end else if ctx.com.display.dms_force_macro_typing && fctx.is_macro && not ctx.in_macro then + force_macro() + else begin + if fctx.is_display_field then begin + handle_display_field() + end else begin + if not (is_full_type cf.cf_type) then begin + cctx.delayed_expr <- (ctx, None) :: cctx.delayed_expr; + cf.cf_type <- TLazy r; + end else if fctx.expr_presence_matters then + cf.cf_expr <- Some (mk (TConst TNull) t_dynamic null_pos) + end + end + +let check_field_display ctx fctx c cf = + if fctx.is_display_field then begin + let scope, cf = match c.cl_kind with + | KAbstractImpl _ -> + if Meta.has Meta.Impl cf.cf_meta then + (if cf.cf_name = "_new" then + CFSConstructor, {cf with cf_name = "new"} + else + CFSMember, cf) + else + CFSStatic, cf; + | _ -> + (if fctx.is_static then + CFSStatic + else if fctx.field_kind = FKConstructor then + CFSConstructor + else + CFSMember), cf; + in + let origin = match c.cl_kind with + | KAbstractImpl a -> Self (TAbstractDecl a) + | _ -> Self (TClassDecl c) + in + DisplayEmitter.maybe_display_field ctx origin scope cf cf.cf_name_pos; + DisplayEmitter.check_field_modifiers ctx c cf fctx.override fctx.display_modifier; + end + +let bind_var (ctx,cctx,fctx) cf e = + let c = cctx.tclass in + let p = cf.cf_pos in + let rec get_declared f = function + | None -> None + | Some (c,a) when PMap.exists f c.cl_fields -> + Some (c,a) + | Some (c,_) -> + let ret = get_declared f c.cl_super in + match ret with + | Some r -> Some r + | None -> + let rec loop ifaces = match ifaces with + | [] -> None + | i :: ifaces -> match get_declared f (Some i) with + | Some r -> Some r + | None -> loop ifaces + in + loop c.cl_implements + in + if not fctx.is_static && not cctx.is_lib then begin match get_declared cf.cf_name c.cl_super with + | None -> () + | Some (csup,_) -> + (* this can happen on -net-lib generated classes if a combination of explicit interfaces and variables with the same name happens *) + if not (csup.cl_interface && Meta.has Meta.CsNative c.cl_meta) then + error ("Redefinition of variable " ^ cf.cf_name ^ " in subclass is not allowed. Previously declared at " ^ (s_type_path csup.cl_path) ) p + end; + let t = cf.cf_type in + + match e with + | None -> + check_field_display ctx fctx c cf; + | Some e -> + if c.cl_interface then display_error ctx "Default values on interfaces are not allowed" (pos e); + cf.cf_meta <- ((Meta.Value,[e],null_pos) :: cf.cf_meta); + let check_cast e = + (* insert cast to keep explicit field type (issue #1901) *) + if type_iseq e.etype cf.cf_type then + e + else begin match e.eexpr,follow cf.cf_type with + | TConst (TInt i),TAbstract({a_path=[],"Float"},_) -> + (* turn int constant to float constant if expected type is float *) + {e with eexpr = TConst (TFloat (Int32.to_string i)); etype = cf.cf_type} + | _ -> + mk_cast e cf.cf_type e.epos + end + in + let r = exc_protect ~force:false ctx (fun r -> + (* type constant init fields (issue #1956) *) + if not !return_partial_type || (match fst e with EConst _ -> true | _ -> false) then begin + r := lazy_processing (fun() -> t); + cctx.context_init(); + if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name); + let e = TypeloadFunction.type_var_field ctx t e fctx.is_static fctx.is_display_field p in + let maybe_run_analyzer e = match e.eexpr with + | TConst _ | TLocal _ | TFunction _ -> e + | _ -> !analyzer_run_on_expr_ref ctx.com e + in + let require_constant_expression e msg = + if ctx.com.display.dms_kind <> DMNone && ctx.com.display.dms_error_policy <> EPCollect then + e + else match Optimizer.make_constant_expression ctx (maybe_run_analyzer e) with + | Some e -> e + | None -> display_error ctx msg p; e + in + let e = (match cf.cf_kind with + | Var v when c.cl_extern || fctx.is_extern -> + if not fctx.is_static then begin + display_error ctx "Extern non-static variables may not be initialized" p; + e + end else if not fctx.is_inline then begin + display_error ctx "Extern non-inline variables may not be initialized" p; + e + end else require_constant_expression e "Extern variable initialization must be a constant value" + | Var v when not (is_physical_field cf) -> + (* disallow initialization of non-physical fields (issue #1958) *) + display_error ctx "This field cannot be initialized because it is not a real variable" p; e + | Var v when not fctx.is_static -> + let e = if ctx.com.display.dms_display && ctx.com.display.dms_error_policy <> EPCollect then + e + else begin + let e = Optimizer.reduce_loop ctx (maybe_run_analyzer e) in + let e = (match Optimizer.make_constant_expression ctx e with + | Some e -> e + | None -> e + ) in + let rec check_this e = match e.eexpr with + | TConst TThis -> + display_error ctx "Cannot access this or other member field in variable initialization" e.epos; + raise Exit + | TLocal v when (match ctx.vthis with Some v2 -> v == v2 | None -> false) -> + display_error ctx "Cannot access this or other member field in variable initialization" e.epos; + raise Exit + | _ -> + Type.iter check_this e + in + (try check_this e with Exit -> ()); + e + end in + e + | Var v when v.v_read = AccInline -> + let e = require_constant_expression e "Inline variable initialization must be a constant value" in + begin match c.cl_kind with + | KAbstractImpl a when Meta.has Meta.Enum cf.cf_meta && Meta.has Meta.Enum a.a_meta -> + unify ctx t (TAbstract(a,(List.map (fun _ -> mk_mono()) a.a_params))) p; + begin match e.eexpr with + | TCast(e1,None) -> unify ctx e1.etype a.a_this e1.epos + | _ -> assert false + end + | _ -> + () + end; + e + | _ -> + e + ) in + let e = check_cast e in + cf.cf_expr <- Some e; + cf.cf_type <- t; + check_field_display ctx fctx c cf; + end; + t + ) "bind_var" in + if not fctx.is_static then cctx.force_constructor <- true; + bind_type (ctx,cctx,fctx) cf r (snd e) + +let create_variable (ctx,cctx,fctx) c f t eo p = + if not fctx.is_static && cctx.abstract <> None then error (fst f.cff_name ^ ": Cannot declare member variable in abstract") p; + if fctx.is_inline && not fctx.is_static then error (fst f.cff_name ^ ": Inline variable must be static") p; + if fctx.is_inline && eo = None then error (fst f.cff_name ^ ": Inline variable must be initialized") p; + if fctx.is_final && not (fctx.is_extern || c.cl_extern || c.cl_interface) && eo = None then begin + if fctx.is_static then error (fst f.cff_name ^ ": Static final variable must be initialized") p + else cctx.uninitialized_final <- Some f.cff_pos; + end; + let t = (match t with + | None when eo = None -> + error ("Variable requires type-hint or initialization") (pos f.cff_name); + | None -> + mk_mono() + | Some t -> + lazy_display_type ctx (fun () -> load_type_hint ctx p (Some t)) + ) in + let kind = if fctx.is_inline then + { v_read = AccInline ; v_write = AccNever } + else if fctx.is_final then + { v_read = AccNormal ; v_write = if fctx.is_static then AccNever else AccCtor } + else + { v_read = AccNormal ; v_write = AccNormal } + in + let cf = { + (mk_field (fst f.cff_name) ~public:(is_public (ctx,cctx) f.cff_access None) t f.cff_pos (pos f.cff_name)) with + cf_doc = f.cff_doc; + cf_meta = f.cff_meta; + cf_kind = Var kind; + } in + if fctx.is_final then add_class_field_flag cf CfFinal; + if fctx.is_extern then add_class_field_flag cf CfExtern; + ctx.curfield <- cf; + bind_var (ctx,cctx,fctx) cf eo; + cf + +let check_abstract (ctx,cctx,fctx) c cf fd t ret p = + match cctx.abstract with + | Some a -> + let m = mk_mono() in + let ta = TAbstract(a, List.map (fun _ -> mk_mono()) a.a_params) in + let tthis = if fctx.is_abstract_member || Meta.has Meta.To cf.cf_meta then monomorphs a.a_params a.a_this else a.a_this in + let allows_no_expr = ref (Meta.has Meta.CoreType a.a_meta) in + let rec loop ml = + (match ml with + | (Meta.From,_,_) :: _ -> + let r = exc_protect ctx (fun r -> + r := lazy_processing (fun () -> t); + (* the return type of a from-function must be the abstract, not the underlying type *) + if not fctx.is_macro then (try type_eq EqStrict ret ta with Unify_error l -> error (error_msg (Unify l)) p); + match t with + | TFun([_,_,t],_) -> t + | _ -> error (cf.cf_name ^ ": @:from cast functions must accept exactly one argument") p + ) "@:from" in + a.a_from_field <- (TLazy r,cf) :: a.a_from_field; + | (Meta.To,_,_) :: _ -> + if fctx.is_macro then error (cf.cf_name ^ ": Macro cast functions are not supported") p; + (* TODO: this doesn't seem quite right... *) + if not (Meta.has Meta.Impl cf.cf_meta) then cf.cf_meta <- (Meta.Impl,[],null_pos) :: cf.cf_meta; + let resolve_m args = + (try unify_raise ctx t (tfun (tthis :: args) m) cf.cf_pos with Error (Unify l,p) -> error (error_msg (Unify l)) p); + match follow m with + | TMono _ when (match t with TFun(_,r) -> r == t_dynamic | _ -> false) -> t_dynamic + | m -> m + in + let r = exc_protect ctx (fun r -> + r := lazy_processing (fun () -> t); + let args = if Meta.has Meta.MultiType a.a_meta then begin + let ctor = try + PMap.find "_new" c.cl_statics + with Not_found -> + error "Constructor of multi-type abstract must be defined before the individual @:to-functions are" cf.cf_pos + in + (* delay ctx PFinal (fun () -> unify ctx m tthis f.cff_pos); *) + let args = match follow (monomorphs a.a_params ctor.cf_type) with + | TFun(args,_) -> List.map (fun (_,_,t) -> t) args + | _ -> assert false + in + args + end else + [] + in + let t = resolve_m args in + t + ) "@:to" in + a.a_to_field <- (TLazy r, cf) :: a.a_to_field + | ((Meta.ArrayAccess,_,_) | (Meta.Op,[(EArrayDecl _),_],_)) :: _ -> + if fctx.is_macro then error (cf.cf_name ^ ": Macro array-access functions are not supported") p; + a.a_array <- cf :: a.a_array; + fctx.expr_presence_matters <- true; + | (Meta.Op,[EBinop(OpAssign,_,_),_],_) :: _ -> + error (cf.cf_name ^ ": Assignment overloading is not supported") p; + | (Meta.Op,[EBinop(op,_,_),_],_) :: _ -> + if fctx.is_macro then error (cf.cf_name ^ ": Macro operator functions are not supported") p; + let targ = if fctx.is_abstract_member then tthis else ta in + let left_eq,right_eq = match follow t with + | TFun([(_,_,t1);(_,_,t2)],_) -> + type_iseq targ t1,type_iseq targ t2 + | _ -> + if fctx.is_abstract_member then + error (cf.cf_name ^ ": Member @:op functions must accept exactly one argument") cf.cf_pos + else + error (cf.cf_name ^ ": Static @:op functions must accept exactly two arguments") cf.cf_pos + in + if not (left_eq || right_eq) then error (cf.cf_name ^ ": The left or right argument type must be " ^ (s_type (print_context()) targ)) cf.cf_pos; + if right_eq && Meta.has Meta.Commutative cf.cf_meta then error (cf.cf_name ^ ": @:commutative is only allowed if the right argument is not " ^ (s_type (print_context()) targ)) cf.cf_pos; + a.a_ops <- (op,cf) :: a.a_ops; + allows_no_expr := true; + fctx.expr_presence_matters <- true; + | (Meta.Op,[EUnop(op,flag,_),_],_) :: _ -> + if fctx.is_macro then error (cf.cf_name ^ ": Macro operator functions are not supported") p; + let targ = if fctx.is_abstract_member then tthis else ta in + (try type_eq EqStrict t (tfun [targ] (mk_mono())) with Unify_error l -> raise (Error ((Unify l),cf.cf_pos))); + a.a_unops <- (op,flag,cf) :: a.a_unops; + allows_no_expr := true; + fctx.expr_presence_matters <- true; + | (Meta.Impl,_,_) :: ml when cf.cf_name <> "_new" && not fctx.is_macro -> + begin match follow t with + | TFun((_,_,t1) :: _, _) when type_iseq tthis t1 -> + () + | _ -> + display_error ctx ("First argument of implementation function must be " ^ (s_type (print_context()) tthis)) cf.cf_pos + end; + | ((Meta.Resolve,_,_) | (Meta.Op,[EField _,_],_)) :: _ -> + let targ = if fctx.is_abstract_member then tthis else ta in + let check_fun t1 t2 = + if not fctx.is_macro then begin + if not (type_iseq targ t1) then error ("First argument type must be " ^ (s_type (print_context()) targ)) cf.cf_pos; + if not (type_iseq ctx.t.tstring t2) then error ("Second argument type must be String") cf.cf_pos + end + in + begin match follow t with + | TFun([(_,_,t1);(_,_,t2)],_) -> + if a.a_read <> None then error "Multiple resolve-read methods are not supported" cf.cf_pos; + check_fun t1 t2; + a.a_read <- Some cf; + | TFun([(_,_,t1);(_,_,t2);(_,_,t3)],_) -> + if a.a_write <> None then error "Multiple resolve-write methods are not supported" cf.cf_pos; + check_fun t1 t2; + a.a_write <- Some cf; + | _ -> + error ("Field type of resolve must be " ^ (s_type (print_context()) targ) ^ " -> String -> T") cf.cf_pos + end; + | _ -> ()); + match ml with + | _ :: ml -> loop ml + | [] -> () + in + loop cf.cf_meta; + let check_bind () = + if fd.f_expr = None then begin + if fctx.is_inline then error (cf.cf_name ^ ": Inline functions must have an expression") cf.cf_pos; + begin match fd.f_type with + | None -> error (cf.cf_name ^ ": Functions without expressions must have an explicit return type") cf.cf_pos + | Some _ -> () + end; + cf.cf_meta <- (Meta.NoExpr,[],null_pos) :: cf.cf_meta; + fctx.do_bind <- false; + if not (Meta.has Meta.CoreType a.a_meta) then fctx.do_add <- false; + end + in + if cf.cf_name = "_new" && Meta.has Meta.MultiType a.a_meta then fctx.do_bind <- false; + if !allows_no_expr then check_bind() + | _ -> + () + +let create_method (ctx,cctx,fctx) c f fd p = + let params = TypeloadFunction.type_function_params ctx fd (fst f.cff_name) p in + if Meta.has Meta.Generic f.cff_meta then begin + if params = [] then error (fst f.cff_name ^ ": Generic functions must have type parameters") p; + end; + let fd = if fctx.is_macro && not ctx.in_macro && not fctx.is_static then + (* remove display of first argument which will contain the "this" expression *) + { fd with f_args = match fd.f_args with [] -> [] | _ :: l -> l } + else + fd + in + let fd = if not fctx.is_macro then + fd + else begin + if ctx.in_macro then begin + (* a class with a macro cannot be extern in macro context (issue #2015) *) + c.cl_extern <- false; + let texpr = CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = None } in + (* ExprOf type parameter might contain platform-specific type, let's replace it by Expr *) + let no_expr_of (t,p) = match t with + | CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some ("ExprOf"); tparams = [TPType _] } + | CTPath { tpackage = []; tname = ("ExprOf"); tsub = None; tparams = [TPType _] } -> Some (texpr,p) + | t -> Some (t,p) + in + { + f_params = fd.f_params; + f_type = (match fd.f_type with None -> Some (texpr,null_pos) | Some t -> no_expr_of t); + f_args = List.map (fun (a,o,m,t,e) -> a,o,m,(match t with None -> Some (texpr,null_pos) | Some t -> no_expr_of t),e) fd.f_args; + f_expr = fd.f_expr; + } + end else + let tdyn = Some (CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None },null_pos) in + let to_dyn p t = match t with + | { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some ("ExprOf"); tparams = [TPType t] } -> Some t + | { tpackage = []; tname = ("ExprOf"); tsub = None; tparams = [TPType t] } -> Some t + | { tpackage = ["haxe"]; tname = ("PosInfos"); tsub = None; tparams = [] } -> error "haxe.PosInfos is not allowed on macro functions, use Context.currentPos() instead" p + | _ -> tdyn + in + { + f_params = fd.f_params; + f_type = (match fd.f_type with Some (CTPath t,p) -> to_dyn p t | _ -> tdyn); + f_args = List.map (fun (a,o,m,t,_) -> a,o,m,(match t with Some (CTPath t,p) -> to_dyn p t | _ -> tdyn),None) fd.f_args; + f_expr = None; + } + end in + begin match c.cl_interface,fctx.field_kind with + | true,FKConstructor -> + error "An interface cannot have a constructor" p; + | true,_ -> + if not fctx.is_static && fd.f_expr <> None then error (fst f.cff_name ^ ": An interface method cannot have a body") p; + if fctx.is_inline && c.cl_interface then error (fst f.cff_name ^ ": You can't declare inline methods in interfaces") p; + | false,FKConstructor -> + if fctx.is_static then error "A constructor must not be static" p; + begin match fd.f_type with + | None -> () + | Some (CTPath ({ tpackage = []; tname = "Void" } as tp),p) -> + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in p then + ignore(load_instance ~allow_display:true ctx (tp,p) false); + | _ -> error "A class constructor can't have a return value" p; + end + | false,_ -> + () + end; + let parent = (if not fctx.is_static then get_parent c (fst f.cff_name) else None) in + let dynamic = List.mem_assoc ADynamic f.cff_access || (match parent with Some { cf_kind = Method MethDynamic } -> true | _ -> false) in + if fctx.is_inline && dynamic then error (fst f.cff_name ^ ": You can't have both 'inline' and 'dynamic'") p; + ctx.type_params <- if fctx.is_static && not fctx.is_abstract_member then params else params @ ctx.type_params; + (* TODO is_lib: avoid forcing the return type to be typed *) + let ret = if fctx.field_kind = FKConstructor then ctx.t.tvoid else type_opt (ctx,cctx) p fd.f_type in + let rec loop args = match args with + | ((name,p),opt,m,t,ct) :: args -> + (* TODO is_lib: avoid forcing the field to be typed *) + let t, ct = TypeloadFunction.type_function_arg ctx (type_opt (ctx,cctx) p t) ct opt p in + delay ctx PTypeField (fun() -> match follow t with + | TAbstract({a_path = ["haxe";"extern"],"Rest"},_) -> + if not fctx.is_extern && not c.cl_extern then error "Rest argument are only supported for extern methods" p; + if opt then error "Rest argument cannot be optional" p; + begin match ct with None -> () | Some (_,p) -> error "Rest argument cannot have default value" p end; + if args <> [] then error "Rest should only be used for the last function argument" p; + | _ -> + () + ); + (name, ct, t) :: (loop args) + | [] -> + [] + in + let args = loop fd.f_args in + let t = TFun (fun_args args,ret) in + let cf = { + (mk_field (fst f.cff_name) ~public:(is_public (ctx,cctx) f.cff_access parent) t f.cff_pos (pos f.cff_name)) with + cf_doc = f.cff_doc; + cf_meta = f.cff_meta; + cf_kind = Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal); + cf_params = params; + } in + if fctx.is_final then add_class_field_flag cf CfFinal; + if fctx.is_extern then add_class_field_flag cf CfExtern; + cf.cf_meta <- List.map (fun (m,el,p) -> match m,el with + | Meta.AstSource,[] -> (m,(match fd.f_expr with None -> [] | Some e -> [e]),p) + | _ -> m,el,p + ) cf.cf_meta; + Option.may (fun cf_parent -> + if not (Meta.has Meta.Native cf.cf_meta) then + try + let native_meta = Meta.get Meta.Native cf_parent.cf_meta in + cf.cf_meta <- native_meta :: cf.cf_meta; + with Not_found -> + () + ) parent; + generate_value_meta ctx.com (Some c) (fun meta -> cf.cf_meta <- meta :: cf.cf_meta) fd.f_args; + check_abstract (ctx,cctx,fctx) c cf fd t ret p; + init_meta_overloads ctx (Some c) cf; + ctx.curfield <- cf; + let r = exc_protect ~force:false ctx (fun r -> + if not !return_partial_type then begin + r := lazy_processing (fun() -> t); + cctx.context_init(); + incr stats.s_methods_typed; + if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ fst f.cff_name); + let fmode = (match cctx.abstract with + | Some _ -> + (match args with + | ("this",_,_) :: _ -> FunMemberAbstract + | _ when fst f.cff_name = "_new" -> FunMemberAbstract + | _ -> FunStatic) + | None -> + if fctx.field_kind = FKConstructor then FunConstructor else if fctx.is_static then FunStatic else FunMember + ) in + begin match ctx.com.platform with + | Java when is_java_native_function cf.cf_meta -> + if fd.f_expr <> None then + ctx.com.warning "@:native function definitions shouldn't include an expression. This behaviour is deprecated." cf.cf_pos; + cf.cf_expr <- None; + cf.cf_type <- t + | _ -> + if cf.cf_name = Parser.magic_display_field_name then DisplayEmitter.check_field_modifiers ctx c cf fctx.override fctx.display_modifier; + let e , fargs = TypeloadFunction.type_function ctx args ret fmode fd fctx.is_display_field p in + begin match fctx.field_kind with + | FKNormal when not fctx.is_static -> TypeloadCheck.check_overriding ctx c cf + | _ -> () + end; + (* Disabled for now, see https://github.com/HaxeFoundation/haxe/issues/3033 *) + (* List.iter (fun (v,_) -> + if v.v_name <> "_" && has_mono v.v_type then ctx.com.warning "Uninferred function argument, please add a type-hint" v.v_pos; + ) fargs; *) + let tf = { + tf_args = fargs; + tf_type = ret; + tf_expr = e; + } in + if fctx.field_kind = FKInit then + (match e.eexpr with + | TBlock [] | TBlock [{ eexpr = TConst _ }] | TConst _ | TObjectDecl [] -> () + | _ -> c.cl_init <- Some e); + cf.cf_expr <- Some (mk (TFunction tf) t p); + cf.cf_type <- t; + check_field_display ctx fctx c cf; + end; + end; + t + ) "type_fun" in + if fctx.do_bind then + bind_type (ctx,cctx,fctx) cf r (match fd.f_expr with Some e -> snd e | None -> f.cff_pos) + else begin + delay ctx PTypeField (fun () -> + (* We never enter type_function so we're missing out on the argument processing there. Let's do it here. *) + List.iter2 (fun (n,ct,t) ((_,pn),_,m,_,_) -> + (* dirty dodge to avoid flash extern problems until somebody fixes that *) + begin if ctx.com.platform = Flash && c.cl_extern then + () + else + ignore(TypeloadFunction.process_function_arg ctx n t ct fctx.is_display_field pn) + end; + if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pn then begin + let v = add_local_with_origin ctx TVOArgument n t pn in + DisplayEmitter.display_variable ctx v pn; + end + ) args fd.f_args; + ); + check_field_display ctx fctx c cf; + if fd.f_expr <> None && not (fctx.is_inline || fctx.is_macro) then ctx.com.warning "Extern non-inline function may not have an expression" p; + end; + cf + +let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p = + let name = fst f.cff_name in + (* TODO is_lib: lazify load_complex_type *) + let ret = (match t, eo with + | None, None -> error (name ^ ": Property requires type-hint or initialization") p; + | None, _ -> mk_mono() + | Some t, _ -> lazy_display_type ctx (fun () -> load_type_hint ctx p (Some t)) + ) in + let t_get,t_set = match cctx.abstract with + | Some a when fctx.is_abstract_member -> + if Meta.has Meta.IsVar f.cff_meta then error (name ^ ": Abstract properties cannot be real variables") f.cff_pos; + let ta = apply_params a.a_params (List.map snd a.a_params) a.a_this in + tfun [ta] ret, tfun [ta;ret] ret + | _ -> tfun [] ret, TFun(["value",false,ret],ret) + in + let find_accessor m = + (* on pf_overload platforms, the getter/setter may have been defined as an overloaded function; get all overloads *) + if ctx.com.config.pf_overload then + if fctx.is_static then + let f = PMap.find m c.cl_statics in + (f.cf_type, f) :: (List.map (fun f -> f.cf_type, f) f.cf_overloads) + else + Overloads.get_overloads c m + else + [ if fctx.is_static then + let f = PMap.find m c.cl_statics in + f.cf_type, f + else match class_field c (List.map snd c.cl_params) m with + | _, t,f -> t,f ] + in + let check_method m t = + if ctx.com.display.dms_error_policy = EPIgnore then () else + try + let overloads = find_accessor m in + (* choose the correct overload if and only if there is more than one overload found *) + let rec get_overload overl = match overl with + | [tf] -> tf + | (t2,f2) :: overl -> + if type_iseq t t2 then + (t2,f2) + else + get_overload overl + | [] -> + if c.cl_interface then + raise Not_found + else + raise (Error (Custom + (Printf.sprintf "No overloaded method named %s was compatible with the property %s with expected type %s" m (name) (s_type (print_context()) t) + ), p)) + in + let t2, f2 = get_overload overloads in + (* accessors must be public on As3 (issue #1872) *) + if Common.defined ctx.com Define.As3 then f2.cf_meta <- (Meta.Public,[],null_pos) :: f2.cf_meta; + (match f2.cf_kind with + | Method MethMacro -> + display_error ctx (f2.cf_name ^ ": Macro methods cannot be used as property accessor") p; + display_error ctx (f2.cf_name ^ ": Accessor method is here") f2.cf_pos; + | _ -> ()); + unify_raise ctx t2 t f2.cf_pos; + if (fctx.is_abstract_member && not (Meta.has Meta.Impl f2.cf_meta)) || (Meta.has Meta.Impl f2.cf_meta && not (fctx.is_abstract_member)) then + display_error ctx "Mixing abstract implementation and static properties/accessors is not allowed" f2.cf_pos; + f2.cf_meta <- List.fold_left (fun acc ((m,_,_) as meta) -> match m with + | Meta.Deprecated -> meta :: acc + | _ -> acc + ) f2.cf_meta f.cff_meta; + with + | Error (Unify l,p) -> raise (Error (Stack (Custom ("In method " ^ m ^ " required by property " ^ name),Unify l),p)) + | Not_found -> + if c.cl_interface then begin + let cf = mk_field m t p null_pos in + cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos]; + cf.cf_kind <- Method MethNormal; + c.cl_fields <- PMap.add cf.cf_name cf c.cl_fields; + c.cl_ordered_fields <- cf :: c.cl_ordered_fields; + end else if not c.cl_extern then begin + try + let _, _, f2 = (if not fctx.is_static then let f = PMap.find m c.cl_statics in None, f.cf_type, f else class_field c (List.map snd c.cl_params) m) in + display_error ctx (Printf.sprintf "Method %s is no valid accessor for %s because it is %sstatic" m (name) (if fctx.is_static then "not " else "")) f2.cf_pos + with Not_found -> + display_error ctx ("Method " ^ m ^ " required by property " ^ name ^ " is missing") p + end + in + let display_accessor m p = + try + let cf = match find_accessor m with [_,cf] -> cf | _ -> raise Not_found in + DisplayEmitter.display_field ctx (Self (TClassDecl c)) (if fctx.is_static then CFSStatic else CFSMember) cf p + with Not_found -> + () + in + let delay_check = delay ctx PConnectField in + let get = (match get with + | "null",_ -> AccNo + | "dynamic",_ -> AccCall + | "never",_ -> AccNever + | "default",_ -> AccNormal + | "get",pget -> + let get = "get_" ^ name in + if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pget then delay ctx PConnectField (fun () -> display_accessor get pget); + if not cctx.is_lib then delay_check (fun() -> check_method get t_get); + AccCall + | _,pget -> + display_error ctx (name ^ ": Custom property accessor is no longer supported, please use `get`") pget; + AccCall + ) in + let set = (match set with + | "null",_ -> + (* standard flash library read-only variables can't be accessed for writing, even in subclasses *) + if c.cl_extern && (match c.cl_path with "flash" :: _ , _ -> true | _ -> false) && ctx.com.platform = Flash then + AccNever + else + AccNo + | "never",_ -> AccNever + | "dynamic",_ -> AccCall + | "default",_ -> AccNormal + | "set",pset -> + let set = "set_" ^ name in + if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pset then delay ctx PConnectField (fun () -> display_accessor set pset); + if not cctx.is_lib then delay_check (fun() -> check_method set t_set); + AccCall + | _,pset -> + display_error ctx (name ^ ": Custom property accessor is no longer supported, please use `set`") pset; + AccCall + ) in + if (set = AccNormal && get = AccCall) || (set = AccNever && get = AccNever) then error (name ^ ": Unsupported property combination") p; + let cf = { + (mk_field name ~public:(is_public (ctx,cctx) f.cff_access None) ret f.cff_pos (pos f.cff_name)) with + cf_doc = f.cff_doc; + cf_meta = f.cff_meta; + cf_kind = Var { v_read = get; v_write = set }; + } in + if fctx.is_extern then add_class_field_flag cf CfExtern; + ctx.curfield <- cf; + bind_var (ctx,cctx,fctx) cf eo; + cf + +(** + Emit compilation error on `final static function` +*) +let reject_final_static_method ctx cctx fctx f = + if fctx.is_static && fctx.is_final && not cctx.tclass.cl_extern then + let p = + try snd (List.find (fun (a,p) -> a = AFinal) f.cff_access) + with Not_found -> + try match Meta.get Meta.Final f.cff_meta with _, _, p -> p + with Not_found -> + try snd (List.find (fun (a,p) -> a = AStatic) f.cff_access) + with Not_found -> f.cff_pos + in + ctx.com.error "Static method cannot be final" p + +let init_field (ctx,cctx,fctx) f = + let c = cctx.tclass in + let name = fst f.cff_name in + TypeloadCheck.check_global_metadata ctx f.cff_meta (fun m -> f.cff_meta <- m :: f.cff_meta) c.cl_module.m_path c.cl_path (Some name); + let p = f.cff_pos in + if starts_with name '$' then display_error ctx "Field names starting with a dollar are not allowed" p; + List.iter (fun acc -> + match (fst acc, f.cff_kind) with + | APublic, _ | APrivate, _ | AStatic, _ | AFinal, _ | AExtern, _ -> () + | ADynamic, FFun _ | AOverride, FFun _ | AMacro, FFun _ | AInline, FFun _ | AInline, FVar _ -> () + | _, FVar _ -> display_error ctx ("Invalid accessor '" ^ Ast.s_placed_access acc ^ "' for variable " ^ name) p + | _, FProp _ -> display_error ctx ("Invalid accessor '" ^ Ast.s_placed_access acc ^ "' for property " ^ name) p + ) f.cff_access; + begin match fctx.override with + | Some _ -> (match c.cl_super with None -> error ("Invalid override on field '" ^ name ^ "': class has no super class") p | _ -> ()); + | None -> () + end; + begin match cctx.abstract with + | Some a when fctx.is_abstract_member -> ctx.type_params <- a.a_params; + | _ -> () + end; + match f.cff_kind with + | FVar (t,e) -> + create_variable (ctx,cctx,fctx) c f t e p + | FFun fd -> + reject_final_static_method ctx cctx fctx f; + create_method (ctx,cctx,fctx) c f fd p + | FProp (get,set,t,eo) -> + create_property (ctx,cctx,fctx) c f (get,set,t,eo) p + +let check_overloads ctx c = + (* check if field with same signature was declared more than once *) + List.iter (fun f -> + if Meta.has Meta.Overload f.cf_meta then + List.iter (fun f2 -> + try + ignore (List.find (fun f3 -> f3 != f2 && Overloads.same_overload_args f2.cf_type f3.cf_type f2 f3) (f :: f.cf_overloads)); + display_error ctx ("Another overloaded field of same signature was already declared : " ^ f2.cf_name) f2.cf_pos + with | Not_found -> () + ) (f :: f.cf_overloads)) (c.cl_ordered_fields @ c.cl_ordered_statics) + +let init_class ctx c p context_init herits fields = + let ctx,cctx = create_class_context ctx c context_init p in + if cctx.is_class_debug then print_endline ("Created class context: " ^ dump_class_context cctx); + let fields = patch_class ctx c fields in + let fields = build_fields (ctx,cctx) c fields in + if cctx.is_core_api && ctx.com.display.dms_check_core_api then delay ctx PForce (fun() -> init_core_api ctx c); + if not cctx.is_lib then begin + if ctx.com.config.pf_overload then delay ctx PForce (fun() -> check_overloads ctx c) + end; + let rec has_field f = function + | None -> false + | Some (c,_) -> + PMap.exists f c.cl_fields || has_field f c.cl_super || List.exists (fun i -> has_field f (Some i)) c.cl_implements + in + let rec check_require = function + | [] -> None + | (Meta.Require,conds,_) :: l -> + let rec loop = function + | [] -> check_require l + | e :: l -> + let sc = match fst e with + | EConst (Ident s) -> s + | EBinop ((OpEq|OpNotEq|OpGt|OpGte|OpLt|OpLte) as op,(EConst (Ident s),_),(EConst ((Int _ | Float _ | String _) as c),_)) -> s ^ s_binop op ^ s_constant c + | _ -> "" + in + if not (ParserEntry.is_true (ParserEntry.eval ctx.com.defines e)) then + Some (sc,(match List.rev l with (EConst (String msg),_) :: _ -> Some msg | _ -> None)) + else + loop l + in + loop conds + | _ :: l -> + check_require l + in + let rec check_if_feature = function + | [] -> [] + | (Meta.IfFeature,el,_) :: _ -> List.map (fun (e,p) -> match e with EConst (String s) -> s | _ -> error "String expected" p) el + | _ :: l -> check_if_feature l + in + let cl_if_feature = check_if_feature c.cl_meta in + let cl_req = check_require c.cl_meta in + List.iter (fun f -> + let p = f.cff_pos in + try + let ctx,fctx = create_field_context (ctx,cctx) c f in + if fctx.is_field_debug then print_endline ("Created field context: " ^ dump_field_context fctx); + let cf = init_field (ctx,cctx,fctx) f in + if fctx.is_field_debug then print_endline ("Created field: " ^ Printer.s_tclass_field "" cf); + if fctx.is_static && c.cl_interface && fctx.field_kind <> FKInit && not cctx.is_lib && not (c.cl_extern) then + error "You can't declare static fields in interfaces" p; + let set_feature s = + ctx.m.curmod.m_extra.m_if_feature <- (s,(c,cf,fctx.is_static)) :: ctx.m.curmod.m_extra.m_if_feature + in + List.iter set_feature cl_if_feature; + List.iter set_feature (check_if_feature cf.cf_meta); + let req = check_require f.cff_meta in + let req = (match req with None -> if fctx.is_static || fctx.field_kind = FKConstructor then cl_req else None | _ -> req) in + (match req with + | None -> () + | Some r -> cf.cf_kind <- Var { v_read = AccRequire (fst r, snd r); v_write = AccRequire (fst r, snd r) }); + begin match fctx.field_kind with + | FKConstructor -> + begin match c.cl_super with + | Some ({ cl_extern = false; cl_constructor = Some ctor_sup }, _) when has_class_field_flag ctor_sup CfFinal -> + ctx.com.error "Cannot override final constructor" cf.cf_pos + | _ -> () + end; + begin match c.cl_constructor with + | None -> + c.cl_constructor <- Some cf + | Some ctor when ctx.com.config.pf_overload -> + if Meta.has Meta.Overload cf.cf_meta && Meta.has Meta.Overload ctor.cf_meta then + ctor.cf_overloads <- cf :: ctor.cf_overloads + else + display_error ctx ("If using overloaded constructors, all constructors must be declared with @:overload") (if Meta.has Meta.Overload cf.cf_meta then ctor.cf_pos else cf.cf_pos) + | Some ctor -> + display_error ctx "Duplicate constructor" p + end + | FKInit -> + () + | FKNormal -> + let dup = if fctx.is_static then PMap.exists cf.cf_name c.cl_fields || has_field cf.cf_name c.cl_super else PMap.exists cf.cf_name c.cl_statics in + if not cctx.is_native && not c.cl_extern && dup then error ("Same field name can't be used for both static and instance : " ^ cf.cf_name) p; + if fctx.override <> None then c.cl_overrides <- cf :: c.cl_overrides; + let is_var cf = match cf.cf_kind with | Var _ -> true | _ -> false in + if PMap.mem cf.cf_name (if fctx.is_static then c.cl_statics else c.cl_fields) then + if ctx.com.config.pf_overload && Meta.has Meta.Overload cf.cf_meta && not (is_var cf) then + let mainf = PMap.find cf.cf_name (if fctx.is_static then c.cl_statics else c.cl_fields) in + if is_var mainf then display_error ctx "Cannot declare a variable with same name as a method" mainf.cf_pos; + (if not (Meta.has Meta.Overload mainf.cf_meta) then display_error ctx ("Overloaded methods must have @:overload metadata") mainf.cf_pos); + mainf.cf_overloads <- cf :: mainf.cf_overloads + else + display_error ctx ("Duplicate class field declaration : " ^ s_type_path c.cl_path ^ "." ^ cf.cf_name) p + else + if fctx.do_add then add_field c cf (fctx.is_static || fctx.is_macro && ctx.in_macro) + end + with Error (Custom str,p2) when p = p2 -> + display_error ctx str p + ) fields; + (match cctx.abstract with + | Some a -> + a.a_to_field <- List.rev a.a_to_field; + a.a_from_field <- List.rev a.a_from_field; + a.a_ops <- List.rev a.a_ops; + a.a_unops <- List.rev a.a_unops; + a.a_array <- List.rev a.a_array; + | None -> ()); + c.cl_ordered_statics <- List.rev c.cl_ordered_statics; + c.cl_ordered_fields <- List.rev c.cl_ordered_fields; + (* if ctx.is_display_file && not cctx.has_display_field && Display.is_display_position c.cl_pos && ctx.com.display.dms_kind = DMToplevel then begin + let rec loop acc c tl = + let maybe_add acc cf = match cf.cf_kind with + | Method MethNormal when not (PMap.mem cf.cf_name acc) -> PMap.add cf.cf_name cf acc + | _ -> acc + in + let acc = List.fold_left maybe_add PMap.empty c.cl_ordered_fields in + match c.cl_super with + | Some(c,tl) -> loop acc c tl + | None -> acc + in + let fields = match c.cl_super with + | Some(c,tl) -> loop PMap.empty c tl + | None -> PMap.empty + in + let open Display in + let l = PMap.fold (fun cf acc -> + if not (List.exists (fun cf' -> cf'.cf_name = cf.cf_name) c.cl_overrides) then + (IdentifierType.ITClassMember cf) :: acc + else acc + ) fields [] in + raise (Display.DisplayToplevel l) + end; *) + (* + make sure a default contructor with same access as super one will be added to the class structure at some point. + *) + let has_struct_init = Meta.has Meta.StructInit c.cl_meta in + if has_struct_init then + ensure_struct_init_constructor ctx c fields p; + begin match cctx.uninitialized_final with + | Some pf when c.cl_constructor = None -> + display_error ctx "This class has uninitialized final vars, which requires a constructor" p; + display_error ctx "Example of an uninitialized final var" pf; + | _ -> + () + end; + if not has_struct_init then + (* add_constructor does not deal with overloads correctly *) + if not ctx.com.config.pf_overload then TypeloadFunction.add_constructor ctx c cctx.force_constructor p; + (* check overloaded constructors *) + (if ctx.com.config.pf_overload && not cctx.is_lib then match c.cl_constructor with + | Some ctor -> + delay ctx PTypeField (fun() -> + List.iter (fun f -> + try + (* TODO: consider making a broader check, and treat some types, like TAnon and type parameters as Dynamic *) + ignore(List.find (fun f2 -> f != f2 && Overloads.same_overload_args f.cf_type f2.cf_type f f2) (ctor :: ctor.cf_overloads)); + display_error ctx ("Another overloaded field of same signature was already declared : " ^ f.cf_name) f.cf_pos; + with Not_found -> () + ) (ctor :: ctor.cf_overloads) + ) + | _ -> ()); + (* push delays in reverse order so they will be run in correct order *) + List.iter (fun (ctx,r) -> + init_class_done ctx; + (match r with + | None -> () + | Some r -> delay ctx PTypeField (fun() -> ignore(lazy_type r))) + ) cctx.delayed_expr \ No newline at end of file diff --git a/src/typing/typeloadFunction.ml b/src/typing/typeloadFunction.ml new file mode 100644 index 00000000000..e85a9164a71 --- /dev/null +++ b/src/typing/typeloadFunction.ml @@ -0,0 +1,310 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(* Typing of functions and their arguments. *) + +open Globals +open Ast +open Type +open Typecore +open DisplayTypes.DisplayMode +open DisplayException +open Common +open Error + +let type_function_arg ctx t e opt p = + (* TODO https://github.com/HaxeFoundation/haxe/issues/8461 *) + (* delay ctx PTypeField (fun() -> + if ExtType.is_void (follow t) then + error "Arguments of type Void are not allowed" p + ); *) + if opt then + let e = (match e with None -> Some (EConst (Ident "null"),null_pos) | _ -> e) in + ctx.t.tnull t, e + else + let t = match e with Some (EConst (Ident "null"),null_pos) -> ctx.t.tnull t | _ -> t in + t, e + +let save_field_state ctx = + let old_ret = ctx.ret in + let old_fun = ctx.curfun in + let old_opened = ctx.opened in + let locals = ctx.locals in + (fun () -> + ctx.locals <- locals; + ctx.ret <- old_ret; + ctx.curfun <- old_fun; + ctx.opened <- old_opened; + ) + +let type_var_field ctx t e stat do_display p = + if stat then ctx.curfun <- FunStatic else ctx.curfun <- FunMember; + let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in + let e = type_expr ctx e (WithType.with_type t) in + let e = AbstractCast.cast_or_unify ctx t e p in + match t with + | TType ({ t_path = ([],"UInt") },[]) | TAbstract ({ a_path = ([],"UInt") },[]) when stat -> { e with etype = t } + | _ -> e + +let type_var_field ctx t e stat do_display p = + let save = save_field_state ctx in + Std.finally save (type_var_field ctx t e stat do_display) p + +let type_function_params ctx fd fname p = + let params = ref [] in + params := Typeload.type_type_params ctx ([],fname) (fun() -> !params) p fd.f_params; + !params + +let type_function_arg_value ctx t c do_display = + match c with + | None -> None + | Some e -> + let p = pos e in + let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in + let e = ctx.g.do_optimize ctx (type_expr ctx e (WithType.with_type t)) in + unify ctx e.etype t p; + let rec loop e = match e.eexpr with + | TConst _ -> Some e + | TField({eexpr = TTypeExpr _},FEnum _) -> Some e + | TCast(e,None) -> loop e + | _ -> + if ctx.com.display.dms_kind = DMNone || ctx.com.display.dms_inline && ctx.com.display.dms_error_policy = EPCollect then + display_error ctx "Parameter default value should be constant" p; + None + in + loop e + +let process_function_arg ctx n t c do_display p = + if starts_with n '$' then error "Function argument names starting with a dollar are not allowed" p; + type_function_arg_value ctx t c do_display + +let type_function ctx args ret fmode f do_display p = + let fargs = List.map2 (fun (n,c,t) ((_,pn),_,m,_,_) -> + let c = process_function_arg ctx n t c do_display pn in + let v = add_local_with_origin ctx TVOArgument n t pn in + v.v_meta <- v.v_meta @ m; + if do_display && DisplayPosition.display_position#enclosed_in pn then + DisplayEmitter.display_variable ctx v pn; + if n = "this" then v.v_meta <- (Meta.This,[],null_pos) :: v.v_meta; + v,c + ) args f.f_args in + ctx.curfun <- fmode; + ctx.ret <- ret; + ctx.opened <- []; + let e = match f.f_expr with + | None -> + if ctx.com.display.dms_error_policy = EPIgnore then + (* when we don't care because we're in display mode, just act like + the function has an empty block body. this is fine even if function + defines a return type, because returns aren't checked in this mode + *) + EBlock [],p + else + error "Function body required" p + | Some e -> e + in + let is_position_debug = Meta.has (Meta.Custom ":debug.position") ctx.curfield.cf_meta in + let e = if not do_display then begin + if is_position_debug then print_endline ("syntax:\n" ^ (Expr.dump_with_pos e)); + type_expr ctx e NoValue + end else begin + let is_display_debug = Meta.has (Meta.Custom ":debug.display") ctx.curfield.cf_meta in + if is_display_debug then print_endline ("before processing:\n" ^ (Expr.dump_with_pos e)); + let e = if !Parser.had_resume then e else Display.ExprPreprocessing.process_expr ctx.com e in + if is_display_debug then print_endline ("after processing:\n" ^ (Expr.dump_with_pos e)); + type_expr ctx e NoValue + end in + let e = match e.eexpr with + | TMeta((Meta.MergeBlock,_,_), ({eexpr = TBlock el} as e1)) -> e1 + | _ -> e + in + let has_return e = + let rec loop e = + match e.eexpr with + | TReturn (Some _) -> raise Exit + | TFunction _ -> () + | _ -> Type.iter loop e + in + try loop e; false with Exit -> true + in + begin match follow ret with + | TAbstract({a_path=[],"Void"},_) -> () + (* We have to check for the presence of return expressions here because + in the case of Dynamic ctx.ret is still a monomorph. If we indeed + don't have a return expression we can link the monomorph to Void. We + can _not_ use type_iseq to avoid the Void check above because that + would turn Dynamic returns to Void returns. *) + | TMono t when not (has_return e) -> ignore(link t ret ctx.t.tvoid) + | _ when ctx.com.display.dms_error_policy = EPIgnore -> () + | _ -> (try TypeloadCheck.return_flow ctx e with Exit -> ()) + end; + let rec loop e = + match e.eexpr with + | TCall ({ eexpr = TConst TSuper },_) -> raise Exit + | TFunction _ -> () + | _ -> Type.iter loop e + in + let has_super_constr() = + match ctx.curclass.cl_super with + | None -> + None + | Some (csup,tl) -> + try + let _,cf = get_constructor (fun f->f.cf_type) csup in + Some (Meta.has Meta.CompilerGenerated cf.cf_meta,TInst(csup,tl)) + with Not_found -> + None + in + let e = if fmode <> FunConstructor then + e + else begin + delay ctx PForce (fun () -> TypeloadCheck.check_final_vars ctx e); + match has_super_constr() with + | Some (was_forced,t_super) -> + (try + loop e; + if was_forced then + let e_super = mk (TConst TSuper) t_super e.epos in + let e_super_call = mk (TCall(e_super,[])) ctx.t.tvoid e.epos in + concat e_super_call e + else begin + display_error ctx "Missing super constructor call" p; + e + end + with + Exit -> e); + | None -> + e + end in + let e = match ctx.curfun, ctx.vthis with + | (FunMember|FunConstructor), Some v -> + let ev = mk (TVar (v,Some (mk (TConst TThis) ctx.tthis p))) ctx.t.tvoid p in + (match e.eexpr with + | TBlock l -> + if ctx.com.config.pf_this_before_super then + { e with eexpr = TBlock (ev :: l) } + else begin + let rec has_v e = match e.eexpr with + | TLocal v' when v == v -> true + | _ -> check_expr has_v e + in + let rec loop el = match el with + | e :: el -> + if has_v e then + ev :: e :: el + else + e :: loop el + | [] -> + (* should not happen... *) + [] + in + { e with eexpr = TBlock (loop l) } + end + | _ -> mk (TBlock [ev;e]) e.etype p) + | _ -> e + in + List.iter (fun r -> r := Closed) ctx.opened; + if is_position_debug then print_endline ("typing:\n" ^ (Texpr.dump_with_pos "" e)); + e , fargs + +let type_function ctx args ret fmode f do_display p = + let save = save_field_state ctx in + Std.finally save (type_function ctx args ret fmode f do_display) p + +let add_constructor ctx c force_constructor p = + match c.cl_constructor, c.cl_super with + | None, Some ({ cl_constructor = Some cfsup } as csup,cparams) when not c.cl_extern -> + let cf = { + cfsup with + cf_pos = p; + cf_meta = List.filter (fun (m,_,_) -> m = Meta.CompilerGenerated) cfsup.cf_meta; + cf_doc = None; + cf_expr = None; + } in + let r = exc_protect ctx (fun r -> + let t = mk_mono() in + r := lazy_processing (fun() -> t); + let ctx = { ctx with + curfield = cf; + pass = PTypeField; + } in + ignore (follow cfsup.cf_type); (* make sure it's typed *) + (if ctx.com.config.pf_overload then List.iter (fun cf -> ignore (follow cf.cf_type)) cf.cf_overloads); + let map_arg (v,def) = + (* + let's optimize a bit the output by not always copying the default value + into the inherited constructor when it's not necessary for the platform + *) + let null () = Some (Texpr.Builder.make_null v.v_type v.v_pos) in + match ctx.com.platform, def with + | _, Some _ when not ctx.com.config.pf_static -> v, null() + | Flash, Some ({eexpr = TConst (TString _)}) -> v, null() + | Cpp, Some ({eexpr = TConst (TString _)}) -> v, def + | Cpp, Some _ -> { v with v_type = ctx.t.tnull v.v_type }, null() + | _ -> v, def + in + let args = (match cfsup.cf_expr with + | Some { eexpr = TFunction f } -> + List.map map_arg f.tf_args + | _ -> + let values = get_value_meta cfsup.cf_meta in + match follow cfsup.cf_type with + | TFun (args,_) -> + List.map (fun (n,o,t) -> + let def = try + type_function_arg_value ctx t (Some (PMap.find n values)) false + with Not_found -> + if o then Some (Texpr.Builder.make_null t null_pos) else None + in + map_arg (alloc_var (VUser TVOArgument) n (if o then ctx.t.tnull t else t) p,def) (* TODO: var pos *) + ) args + | _ -> assert false + ) in + let p = c.cl_pos in + let vars = List.map (fun (v,def) -> alloc_var (VUser TVOArgument) v.v_name (apply_params csup.cl_params cparams v.v_type) v.v_pos, def) args in + let super_call = mk (TCall (mk (TConst TSuper) (TInst (csup,cparams)) p,List.map (fun (v,_) -> mk (TLocal v) v.v_type p) vars)) ctx.t.tvoid p in + let constr = mk (TFunction { + tf_args = vars; + tf_type = ctx.t.tvoid; + tf_expr = super_call; + }) (TFun (List.map (fun (v,c) -> v.v_name, c <> None, v.v_type) vars,ctx.t.tvoid)) p in + cf.cf_expr <- Some constr; + cf.cf_type <- t; + unify ctx t constr.etype p; + t + ) "add_constructor" in + cf.cf_type <- TLazy r; + c.cl_constructor <- Some cf; + | None,_ when force_constructor -> + let constr = mk (TFunction { + tf_args = []; + tf_type = ctx.t.tvoid; + tf_expr = mk (TBlock []) ctx.t.tvoid p; + }) (tfun [] ctx.t.tvoid) p in + let cf = mk_field "new" constr.etype p null_pos in + cf.cf_expr <- Some constr; + cf.cf_type <- constr.etype; + cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos]; + cf.cf_kind <- Method MethNormal; + c.cl_constructor <- Some cf; + | _ -> + (* nothing to do *) + () +;; +Typeload.type_function_params_rec := type_function_params \ No newline at end of file diff --git a/src/typing/typeloadModule.ml b/src/typing/typeloadModule.ml new file mode 100644 index 00000000000..32bfb74155d --- /dev/null +++ b/src/typing/typeloadModule.ml @@ -0,0 +1,989 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(* Initial typing of modules and their types. *) + +open Globals +open Ast +open Filename +open Type +open Typecore +open DisplayTypes.DisplayMode +open DisplayTypes.CompletionResultKind +open Common +open Typeload +open Error + +let get_policy ctx mpath = + let sl1 = full_dot_path2 mpath mpath in + List.fold_left (fun acc (sl2,policy,recursive) -> if match_path recursive sl1 sl2 then policy @ acc else acc) [] ctx.g.module_check_policies + +let make_module ctx mpath file loadp = + let m = { + m_id = alloc_mid(); + m_path = mpath; + m_types = []; + m_extra = module_extra (Path.unique_full_path file) (Define.get_signature ctx.com.defines) (file_time file) (if ctx.in_macro then MMacro else MCode) (get_policy ctx mpath); + } in + m + +let add_module ctx m p = + List.iter (TypeloadCheck.check_module_types ctx m p) m.m_types; + Hashtbl.add ctx.g.modules m.m_path m + +module StrictMeta = struct + let get_native_repr md pos = + let path, meta = match md with + | TClassDecl cl -> cl.cl_path, cl.cl_meta + | TEnumDecl e -> e.e_path, e.e_meta + | TTypeDecl t -> t.t_path, t.t_meta + | TAbstractDecl a -> a.a_path, a.a_meta + in + let rec loop acc = function + | (Meta.JavaCanonical,[EConst(String pack),_; EConst(String name),_],_) :: _ -> + ExtString.String.nsplit pack ".", name + | (Meta.Native,[EConst(String name),_],_) :: meta -> + loop (Ast.parse_path name) meta + | _ :: meta -> + loop acc meta + | [] -> + acc + in + let pack, name = loop path meta in + match pack with + | [] -> + (EConst(Ident(name)), pos) + | hd :: tl -> + let rec loop pack expr = match pack with + | hd :: tl -> + loop tl (EField(expr,hd),pos) + | [] -> + (EField(expr,name),pos) + in + loop tl (EConst(Ident(hd)),pos) + + let rec process_meta_argument ?(toplevel=true) ctx expr = match expr.eexpr with + | TField(e,f) -> + (EField(process_meta_argument ~toplevel:false ctx e,field_name f),expr.epos) + | TConst(TInt i) -> + (EConst(Int (Int32.to_string i)), expr.epos) + | TConst(TFloat f) -> + (EConst(Float f), expr.epos) + | TConst(TString s) -> + (EConst(String s), expr.epos) + | TConst TNull -> + (EConst(Ident "null"), expr.epos) + | TConst(TBool b) -> + (EConst(Ident (string_of_bool b)), expr.epos) + | TCast(e,_) | TMeta(_,e) | TParenthesis(e) -> + process_meta_argument ~toplevel ctx e + | TTypeExpr md when toplevel -> + let p = expr.epos in + if ctx.com.platform = Cs then + (ECall( (EConst(Ident "typeof"), p), [get_native_repr md expr.epos] ), p) + else + (EField(get_native_repr md expr.epos, "class"), p) + | TTypeExpr md -> + get_native_repr md expr.epos + | _ -> + display_error ctx "This expression is too complex to be a strict metadata argument" expr.epos; + (EConst(Ident "null"), expr.epos) + + let handle_fields ctx fields_to_check with_type_expr = + List.map (fun ((name,_,_),expr) -> + let pos = snd expr in + let field = (EField(with_type_expr,name), pos) in + let fieldexpr = (EConst(Ident name),pos) in + let left_side = match ctx.com.platform with + | Cs -> field + | Java -> (ECall(field,[]),pos) + | _ -> assert false + in + + let left = type_expr ctx left_side NoValue in + let right = type_expr ctx expr (WithType.with_type left.etype) in + unify ctx left.etype right.etype (snd expr); + (EBinop(Ast.OpAssign,fieldexpr,process_meta_argument ctx right), pos) + ) fields_to_check + + let make_meta ctx texpr extra = + match texpr.eexpr with + | TNew(c,_,el) -> + ECall(get_native_repr (TClassDecl c) texpr.epos, (List.map (process_meta_argument ctx) el) @ extra), texpr.epos + | TTypeExpr(md) -> + ECall(get_native_repr md texpr.epos, extra), texpr.epos + | _ -> + display_error ctx "Unexpected expression" texpr.epos; assert false + + let get_strict_meta ctx params pos = + let pf = ctx.com.platform in + let changed_expr, fields_to_check, ctype = match params with + | [ECall(ef, el),p] -> + (* check last argument *) + let el, fields = match List.rev el with + | (EObjectDecl(decl),_) :: el -> + List.rev el, decl + | _ -> + el, [] + in + let tpath = field_to_type_path ctx ef in + if pf = Cs then + (ENew((tpath,snd ef), el), p), fields, CTPath tpath + else + ef, fields, CTPath tpath + | [EConst(Ident i),p as expr] -> + let tpath = { tpackage=[]; tname=i; tparams=[]; tsub=None } in + if pf = Cs then + (ENew((tpath,p), []), p), [], CTPath tpath + else + expr, [], CTPath tpath + | [ (EField(_),p as field) ] -> + let tpath = field_to_type_path ctx field in + if pf = Cs then + (ENew((tpath,p), []), p), [], CTPath tpath + else + field, [], CTPath tpath + | _ -> + display_error ctx "A @:strict metadata must contain exactly one parameter. Please check the documentation for more information" pos; + raise Exit + in + let texpr = type_expr ctx changed_expr NoValue in + let with_type_expr = (ECheckType( (EConst (Ident "null"), pos), (ctype,null_pos) ), pos) in + let extra = handle_fields ctx fields_to_check with_type_expr in + Meta.Meta, [make_meta ctx texpr extra], pos + + let check_strict_meta ctx metas = + let pf = ctx.com.platform in + match pf with + | Cs | Java -> + let ret = ref [] in + List.iter (function + | Meta.Strict,params,pos -> (try + ret := get_strict_meta ctx params pos :: !ret + with | Exit -> ()) + | _ -> () + ) metas; + !ret + | _ -> [] +end + +(* + Build module structure : should be atomic - no type loading is possible +*) +let module_pass_1 ctx m tdecls loadp = + let com = ctx.com in + let decls = ref [] in + let make_path name priv = + if List.exists (fun (t,_) -> snd (t_path t) = name) !decls then error ("Type name " ^ name ^ " is already defined in this module") loadp; + if priv then (fst m.m_path @ ["_" ^ snd m.m_path], name) else (fst m.m_path, name) + in + let pt = ref None in + let rec make_decl acc decl = + let p = snd decl in + let acc = (match fst decl with + | EImport _ | EUsing _ -> + (match !pt with + | None -> acc + | Some _ -> error "import and using may not appear after a type declaration" p) + | EClass d -> + let name = fst d.d_name in + if starts_with name '$' then error "Type names starting with a dollar are not allowed" p; + pt := Some p; + let priv = List.mem HPrivate d.d_flags in + let path = make_path name priv in + let c = mk_class m path p (pos d.d_name) in + (* we shouldn't load any other type until we propertly set cl_build *) + c.cl_build <- (fun() -> error (s_type_path c.cl_path ^ " is not ready to be accessed, separate your type declarations in several files") p); + c.cl_module <- m; + c.cl_private <- priv; + c.cl_doc <- d.d_doc; + c.cl_meta <- d.d_meta; + List.iter (function + | HExtern -> c.cl_extern <- true + | HInterface -> c.cl_interface <- true + | HFinal -> c.cl_final <- true + | _ -> () + ) d.d_flags; + decls := (TClassDecl c, decl) :: !decls; + acc + | EEnum d -> + let name = fst d.d_name in + if starts_with name '$' then error "Type names starting with a dollar are not allowed" p; + pt := Some p; + let priv = List.mem EPrivate d.d_flags in + let path = make_path name priv in + if Meta.has (Meta.Custom ":fakeEnum") d.d_meta then error "@:fakeEnum enums is no longer supported in Haxe 4, use extern enum abstract instead" p; + let e = { + e_path = path; + e_module = m; + e_pos = p; + e_name_pos = (pos d.d_name); + e_doc = d.d_doc; + e_meta = d.d_meta; + e_params = []; + e_using = []; + e_private = priv; + e_extern = List.mem EExtern d.d_flags; + e_constrs = PMap.empty; + e_names = []; + e_type = enum_module_type m path p; + } in + decls := (TEnumDecl e, decl) :: !decls; + acc + | ETypedef d -> + let name = fst d.d_name in + if starts_with name '$' then error "Type names starting with a dollar are not allowed" p; + if has_meta Meta.Using d.d_meta then error "@:using on typedef is not allowed" p; + pt := Some p; + let priv = List.mem EPrivate d.d_flags in + let path = make_path name priv in + let t = { + t_path = path; + t_module = m; + t_pos = p; + t_name_pos = pos d.d_name; + t_doc = d.d_doc; + t_private = priv; + t_params = []; + t_using = []; + t_type = mk_mono(); + t_meta = d.d_meta; + } in + (* failsafe in case the typedef is not initialized (see #3933) *) + delay ctx PBuildModule (fun () -> + match t.t_type with + | TMono r -> (match !r with None -> r := Some com.basic.tvoid | _ -> ()) + | _ -> () + ); + decls := (TTypeDecl t, decl) :: !decls; + acc + | EAbstract d -> + let name = fst d.d_name in + if starts_with name '$' then error "Type names starting with a dollar are not allowed" p; + let priv = List.mem AbPrivate d.d_flags in + let path = make_path name priv in + let a = { + a_path = path; + a_private = priv; + a_module = m; + a_pos = p; + a_name_pos = pos d.d_name; + a_doc = d.d_doc; + a_params = []; + a_using = []; + a_meta = d.d_meta; + a_from = []; + a_to = []; + a_from_field = []; + a_to_field = []; + a_ops = []; + a_unops = []; + a_impl = None; + a_array = []; + a_this = mk_mono(); + a_read = None; + a_write = None; + } in + decls := (TAbstractDecl a, decl) :: !decls; + match d.d_data with + | [] when Meta.has Meta.CoreType a.a_meta -> + a.a_this <- t_dynamic; + acc + | fields -> + let a_t = + let params = List.map (fun t -> TPType (CTPath { tname = fst t.tp_name; tparams = []; tsub = None; tpackage = [] },null_pos)) d.d_params in + CTPath { tpackage = []; tname = fst d.d_name; tparams = params; tsub = None },null_pos + in + let rec loop = function + | [] -> a_t + | AbOver t :: _ -> t + | _ :: l -> loop l + in + let this_t = loop d.d_flags in + let fields = List.map (TypeloadFields.transform_abstract_field com this_t a_t a) fields in + let meta = ref [] in + if has_meta Meta.Dce a.a_meta then meta := (Meta.Dce,[],null_pos) :: !meta; + let acc = make_decl acc (EClass { d_name = (fst d.d_name) ^ "_Impl_",snd d.d_name; d_flags = [HPrivate]; d_data = fields; d_doc = None; d_params = []; d_meta = !meta },p) in + (match !decls with + | (TClassDecl c,_) :: _ -> + List.iter (fun m -> match m with + | ((Meta.Using | Meta.Build | Meta.CoreApi | Meta.Allow | Meta.Access | Meta.Enum | Meta.Dce | Meta.Native | Meta.HlNative | Meta.JsRequire | Meta.PythonImport | Meta.Expose | Meta.Deprecated | Meta.PhpGlobal),_,_) -> + c.cl_meta <- m :: c.cl_meta; + | _ -> + () + ) a.a_meta; + a.a_impl <- Some c; + c.cl_kind <- KAbstractImpl a; + c.cl_final <- true; + | _ -> assert false); + acc + ) in + decl :: acc + in + let tdecls = List.fold_left make_decl [] tdecls in + let decls = List.rev !decls in + decls, List.rev tdecls + +(* + In this pass, we can access load and access other modules types, but we cannot follow them or access their structure + since they have not been setup. We also build a context_init list that will be evaluated the first time we evaluate + an expression into the context +*) +let init_module_type ctx context_init do_init (decl,p) = + let get_type name = + try List.find (fun t -> snd (t_infos t).mt_path = name) ctx.m.curmod.m_types with Not_found -> assert false + in + let check_path_display path p = match ctx.com.display.dms_kind with + (* We cannot use ctx.is_display_file because the import could come from an import.hx file. *) + | DMDiagnostics b when (b || DisplayPosition.display_position#is_in_file p.pfile) && Filename.basename p.pfile <> "import.hx" -> + ImportHandling.add_import_position ctx.com p path; + | DMStatistics -> + ImportHandling.add_import_position ctx.com p path; + | DMUsage _ -> + ImportHandling.add_import_position ctx.com p path; + if DisplayPosition.display_position#is_in_file p.pfile then handle_path_display ctx path p + | _ -> + if DisplayPosition.display_position#is_in_file p.pfile then handle_path_display ctx path p + in + match decl with + | EImport (path,mode) -> + ctx.m.module_imports <- (path,mode) :: ctx.m.module_imports; + check_path_display path p; + let rec loop acc = function + | x :: l when is_lower_ident (fst x) -> loop (x::acc) l + | rest -> List.rev acc, rest + in + let pack, rest = loop [] path in + (match rest with + | [] -> + (match mode with + | IAll -> + ctx.m.wildcard_packages <- (List.map fst pack,p) :: ctx.m.wildcard_packages + | _ -> + (match List.rev path with + | [] -> DisplayException.raise_fields (DisplayToplevel.collect ctx TKType NoValue) CRImport None; + | (_,p) :: _ -> error "Module name must start with an uppercase letter" p)) + | (tname,p2) :: rest -> + let p1 = (match pack with [] -> p2 | (_,p1) :: _ -> p1) in + let p_type = punion p1 p2 in + let md = ctx.g.do_load_module ctx (List.map fst pack,tname) p_type in + let types = md.m_types in + let no_private (t,_) = not (t_infos t).mt_private in + let chk_private t p = if (t_infos t).mt_private then error "You can't import a private type" p in + let has_name name t = snd (t_infos t).mt_path = name in + let get_type tname = + let t = (try List.find (has_name tname) types with Not_found -> error (StringError.string_error tname (List.map (fun mt -> snd (t_infos mt).mt_path) types) ("Module " ^ s_type_path md.m_path ^ " does not define type " ^ tname)) p_type) in + chk_private t p_type; + t + in + let rebind t name p = + if not (name.[0] >= 'A' && name.[0] <= 'Z') then + error "Type aliases must start with an uppercase letter" p; + let _, _, f = ctx.g.do_build_instance ctx t p_type in + (* create a temp private typedef, does not register it in module *) + let mt = TTypeDecl { + t_path = (fst md.m_path @ ["_" ^ snd md.m_path],name); + t_module = ctx.m.curmod; + t_pos = p; + t_name_pos = p; + t_private = true; + t_doc = None; + t_meta = []; + t_params = (t_infos t).mt_params; + t_using = []; + t_type = f (List.map snd (t_infos t).mt_params); + } in + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in p then + DisplayEmitter.display_module_type ctx mt p; + mt + in + let add_static_init t name s = + let name = (match name with None -> s | Some (n,_) -> n) in + match resolve_typedef t with + | TClassDecl c | TAbstractDecl {a_impl = Some c} -> + ignore(c.cl_build()); + ignore(PMap.find s c.cl_statics); + ctx.m.module_globals <- PMap.add name (TClassDecl c,s,p) ctx.m.module_globals + | TEnumDecl e -> + ignore(PMap.find s e.e_constrs); + ctx.m.module_globals <- PMap.add name (TEnumDecl e,s,p) ctx.m.module_globals + | _ -> + raise Not_found + in + (match mode with + | INormal | IAsName _ -> + let name = (match mode with IAsName n -> Some n | _ -> None) in + (match rest with + | [] -> + (match name with + | None -> + ctx.m.module_types <- List.filter no_private (List.map (fun t -> t,p) types) @ ctx.m.module_types + | Some(newname,pname) -> + ctx.m.module_types <- (rebind (get_type tname) newname pname,p) :: ctx.m.module_types); + | [tsub,p2] -> + let pu = punion p1 p2 in + (try + let tsub = List.find (has_name tsub) types in + chk_private tsub pu; + ctx.m.module_types <- ((match name with None -> tsub | Some(n,pname) -> rebind tsub n pname),p) :: ctx.m.module_types + with Not_found -> + (* this might be a static property, wait later to check *) + let tmain = get_type tname in + context_init := (fun() -> + try + add_static_init tmain name tsub + with Not_found -> + error (s_type_path (t_infos tmain).mt_path ^ " has no field or subtype " ^ tsub) p + ) :: !context_init) + | (tsub,p2) :: (fname,p3) :: rest -> + (match rest with + | [] -> () + | (n,p) :: _ -> error ("Unexpected " ^ n) p); + let tsub = get_type tsub in + context_init := (fun() -> + try + add_static_init tsub name fname + with Not_found -> + error (s_type_path (t_infos tsub).mt_path ^ " has no field " ^ fname) (punion p p3) + ) :: !context_init; + ) + | IAll -> + let t = (match rest with + | [] -> get_type tname + | [tsub,_] -> get_type tsub + | _ :: (n,p) :: _ -> error ("Unexpected " ^ n) p + ) in + context_init := (fun() -> + match resolve_typedef t with + | TClassDecl c + | TAbstractDecl {a_impl = Some c} -> + ignore(c.cl_build()); + PMap.iter (fun _ cf -> if not (has_meta Meta.NoImportGlobal cf.cf_meta) then ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name,p) ctx.m.module_globals) c.cl_statics + | TEnumDecl e -> + PMap.iter (fun _ c -> if not (has_meta Meta.NoImportGlobal c.ef_meta) then ctx.m.module_globals <- PMap.add c.ef_name (TEnumDecl e,c.ef_name,p) ctx.m.module_globals) e.e_constrs + | _ -> + error "No statics to import from this type" p + ) :: !context_init + )) + | EUsing path -> + check_path_display path p; + let types,filter_classes = handle_using ctx path p in + (* do the import first *) + ctx.m.module_types <- (List.map (fun t -> t,p) types) @ ctx.m.module_types; + context_init := (fun() -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using) :: !context_init + | EClass d -> + let c = (match get_type (fst d.d_name) with TClassDecl c -> c | _ -> assert false) in + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then + DisplayEmitter.display_module_type ctx (match c.cl_kind with KAbstractImpl a -> TAbstractDecl a | _ -> TClassDecl c) (pos d.d_name); + TypeloadCheck.check_global_metadata ctx c.cl_meta (fun m -> c.cl_meta <- m :: c.cl_meta) c.cl_module.m_path c.cl_path None; + let herits = d.d_flags in + List.iter (fun (m,_,p) -> + if m = Meta.Final then begin + c.cl_final <- true; + (* if p <> null_pos && not (Define.is_haxe3_compat ctx.com.defines) then + ctx.com.warning "`@:final class` is deprecated in favor of `final class`" p; *) + end + ) d.d_meta; + let prev_build_count = ref (!build_count - 1) in + let build() = + let fl = TypeloadCheck.Inheritance.set_heritance ctx c herits p in + let rec build() = + c.cl_build <- (fun()-> Building [c]); + try + List.iter (fun f -> f()) fl; + TypeloadFields.init_class ctx c p do_init d.d_flags d.d_data; + c.cl_build <- (fun()-> Built); + incr build_count; + List.iter (fun (_,t) -> ignore(follow t)) c.cl_params; + Built; + with TypeloadCheck.Build_canceled state -> + c.cl_build <- make_pass ctx build; + let rebuild() = + delay_late ctx PBuildClass (fun() -> ignore(c.cl_build())); + in + (match state with + | Built -> assert false + | Building cl -> + if !build_count = !prev_build_count then error ("Loop in class building prevent compiler termination (" ^ String.concat "," (List.map (fun c -> s_type_path c.cl_path) cl) ^ ")") c.cl_pos; + prev_build_count := !build_count; + rebuild(); + Building (c :: cl) + | BuildMacro f -> + f := rebuild :: !f; + state); + | exn -> + c.cl_build <- (fun()-> Built); + raise exn + in + build() + in + ctx.pass <- PBuildClass; + ctx.curclass <- c; + c.cl_build <- make_pass ctx build; + ctx.pass <- PBuildModule; + ctx.curclass <- null_class; + delay ctx PBuildClass (fun() -> ignore(c.cl_build())); + if (ctx.com.platform = Java || ctx.com.platform = Cs) && not c.cl_extern then + delay ctx PTypeField (fun () -> + let metas = StrictMeta.check_strict_meta ctx c.cl_meta in + if metas <> [] then c.cl_meta <- metas @ c.cl_meta; + let rec run_field cf = + let metas = StrictMeta.check_strict_meta ctx cf.cf_meta in + if metas <> [] then cf.cf_meta <- metas @ cf.cf_meta; + List.iter run_field cf.cf_overloads + in + List.iter run_field c.cl_ordered_statics; + List.iter run_field c.cl_ordered_fields; + match c.cl_constructor with + | Some f -> run_field f + | _ -> () + ); + | EEnum d -> + let e = (match get_type (fst d.d_name) with TEnumDecl e -> e | _ -> assert false) in + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then + DisplayEmitter.display_module_type ctx (TEnumDecl e) (pos d.d_name); + let ctx = { ctx with type_params = e.e_params } in + let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in + TypeloadCheck.check_global_metadata ctx e.e_meta (fun m -> e.e_meta <- m :: e.e_meta) e.e_module.m_path e.e_path None; + (match h with + | None -> () + | Some (h,hcl) -> + Hashtbl.iter (fun _ _ -> error "Field type patch not supported for enums" e.e_pos) h; + e.e_meta <- e.e_meta @ hcl.tp_meta); + let constructs = ref d.d_data in + let get_constructs() = + List.map (fun c -> + { + cff_name = c.ec_name; + cff_doc = c.ec_doc; + cff_meta = c.ec_meta; + cff_pos = c.ec_pos; + cff_access = []; + cff_kind = (match c.ec_args, c.ec_params with + | [], [] -> FVar (c.ec_type,None) + | _ -> FFun { f_params = c.ec_params; f_type = c.ec_type; f_expr = None; f_args = List.map (fun (n,o,t) -> (n,null_pos),o,[],Some t,None) c.ec_args }); + } + ) (!constructs) + in + let init () = List.iter (fun f -> f()) !context_init in + TypeloadFields.build_module_def ctx (TEnumDecl e) e.e_meta get_constructs init (fun (e,p) -> + match e with + | EVars [_,_,Some (CTAnonymous fields,p),None] -> + constructs := List.map (fun f -> + let args, params, t = (match f.cff_kind with + | FVar (t,None) -> [], [], t + | FFun { f_params = pl; f_type = t; f_expr = (None|Some (EBlock [],_)); f_args = al } -> + let al = List.map (fun ((n,_),o,_,t,_) -> match t with None -> error "Missing function parameter type" f.cff_pos | Some t -> n,o,t) al in + al, pl, t + | _ -> + error "Invalid enum constructor in @:build result" p + ) in + { + ec_name = f.cff_name; + ec_doc = f.cff_doc; + ec_meta = f.cff_meta; + ec_pos = f.cff_pos; + ec_args = args; + ec_params = params; + ec_type = t; + } + ) fields + | _ -> error "Enum build macro must return a single variable with anonymous object fields" p + ); + let et = TEnum (e,List.map snd e.e_params) in + let names = ref [] in + let index = ref 0 in + let is_flat = ref true in + let fields = ref PMap.empty in + List.iter (fun c -> + let p = c.ec_pos in + let params = ref [] in + params := type_type_params ~enum_constructor:true ctx ([],fst c.ec_name) (fun() -> !params) c.ec_pos c.ec_params; + let params = !params in + let ctx = { ctx with type_params = params @ ctx.type_params } in + let rt = (match c.ec_type with + | None -> et + | Some (t,pt) -> + let t = load_complex_type ctx true (t,pt) in + (match follow t with + | TEnum (te,_) when te == e -> + () + | _ -> + error "Explicit enum type must be of the same enum type" pt); + t + ) in + let t = (match c.ec_args with + | [] -> rt + | l -> + is_flat := false; + let pnames = ref PMap.empty in + TFun (List.map (fun (s,opt,(t,tp)) -> + (match t with CTPath({tpackage=[];tname="Void"}) -> error "Arguments of type Void are not allowed in enum constructors" tp | _ -> ()); + if PMap.mem s (!pnames) then error ("Duplicate argument `" ^ s ^ "` in enum constructor " ^ fst c.ec_name) p; + pnames := PMap.add s () (!pnames); + s, opt, load_type_hint ~opt ctx p (Some (t,tp)) + ) l, rt) + ) in + if PMap.mem (fst c.ec_name) e.e_constrs then error ("Duplicate constructor " ^ fst c.ec_name) (pos c.ec_name); + let f = { + ef_name = fst c.ec_name; + ef_type = t; + ef_pos = p; + ef_name_pos = snd c.ec_name; + ef_doc = c.ec_doc; + ef_index = !index; + ef_params = params; + ef_meta = c.ec_meta; + } in + let cf = { + (mk_field f.ef_name f.ef_type p f.ef_name_pos) with + cf_kind = (match follow f.ef_type with + | TFun _ -> Method MethNormal + | _ -> Var { v_read = AccNormal; v_write = AccNo } + ); + cf_doc = f.ef_doc; + cf_params = f.ef_params; + } in + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in f.ef_name_pos then + DisplayEmitter.display_enum_field ctx e f p; + e.e_constrs <- PMap.add f.ef_name f e.e_constrs; + fields := PMap.add cf.cf_name cf !fields; + incr index; + names := (fst c.ec_name) :: !names; + ) (!constructs); + e.e_names <- List.rev !names; + e.e_extern <- e.e_extern; + e.e_type.t_params <- e.e_params; + e.e_type.t_type <- TAnon { + a_fields = !fields; + a_status = ref (EnumStatics e); + }; + if !is_flat then e.e_meta <- (Meta.FlatEnum,[],null_pos) :: e.e_meta; + + if (ctx.com.platform = Java || ctx.com.platform = Cs) && not e.e_extern then + delay ctx PTypeField (fun () -> + let metas = StrictMeta.check_strict_meta ctx e.e_meta in + e.e_meta <- metas @ e.e_meta; + PMap.iter (fun _ ef -> + let metas = StrictMeta.check_strict_meta ctx ef.ef_meta in + if metas <> [] then ef.ef_meta <- metas @ ef.ef_meta + ) e.e_constrs + ); + | ETypedef d -> + let t = (match get_type (fst d.d_name) with TTypeDecl t -> t | _ -> assert false) in + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then + DisplayEmitter.display_module_type ctx (TTypeDecl t) (pos d.d_name); + TypeloadCheck.check_global_metadata ctx t.t_meta (fun m -> t.t_meta <- m :: t.t_meta) t.t_module.m_path t.t_path None; + let ctx = { ctx with type_params = t.t_params } in + let tt = load_complex_type ctx true d.d_data in + let tt = (match fst d.d_data with + | CTExtend _ -> tt + | CTPath { tpackage = ["haxe";"macro"]; tname = "MacroType" } -> + (* we need to follow MacroType immediately since it might define other module types that we will load afterwards *) + if t.t_type == follow tt then error "Recursive typedef is not allowed" p; + tt + | _ -> + if (Meta.has Meta.Eager d.d_meta) then + follow tt + else begin + let rec check_rec tt = + if tt == t.t_type then error "Recursive typedef is not allowed" p; + match tt with + | TMono r -> + (match !r with + | None -> () + | Some t -> check_rec t) + | TLazy f -> + check_rec (lazy_type f); + | TType (td,tl) -> + if td == t then error "Recursive typedef is not allowed" p; + check_rec (apply_params td.t_params tl td.t_type) + | _ -> + () + in + let r = exc_protect ctx (fun r -> + r := lazy_processing (fun() -> tt); + check_rec tt; + tt + ) "typedef_rec_check" in + TLazy r + end + ) in + (match t.t_type with + | TMono r -> + (match !r with + | None -> r := Some tt; + | Some _ -> assert false); + | _ -> assert false); + if ctx.com.platform = Cs && t.t_meta <> [] then + delay ctx PTypeField (fun () -> + let metas = StrictMeta.check_strict_meta ctx t.t_meta in + if metas <> [] then t.t_meta <- metas @ t.t_meta; + ); + | EAbstract d -> + let a = (match get_type (fst d.d_name) with TAbstractDecl a -> a | _ -> assert false) in + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then + DisplayEmitter.display_module_type ctx (TAbstractDecl a) (pos d.d_name); + TypeloadCheck.check_global_metadata ctx a.a_meta (fun m -> a.a_meta <- m :: a.a_meta) a.a_module.m_path a.a_path None; + let ctx = { ctx with type_params = a.a_params } in + let is_type = ref false in + let load_type t from = + let _, pos = t in + let t = load_complex_type ctx true t in + let t = if not (Meta.has Meta.CoreType a.a_meta) then begin + if !is_type then begin + let r = exc_protect ctx (fun r -> + r := lazy_processing (fun() -> t); + (try (if from then Type.unify t a.a_this else Type.unify a.a_this t) with Unify_error _ -> error "You can only declare from/to with compatible types" pos); + t + ) "constraint" in + TLazy r + end else + error "Missing underlying type declaration or @:coreType declaration" p; + end else begin + if Meta.has Meta.Callable a.a_meta then + error "@:coreType abstracts cannot be @:callable" p; + t + end in + t + in + List.iter (function + | AbFrom t -> a.a_from <- (load_type t true) :: a.a_from + | AbTo t -> a.a_to <- (load_type t false) :: a.a_to + | AbOver t -> + if a.a_impl = None then error "Abstracts with underlying type must have an implementation" a.a_pos; + if Meta.has Meta.CoreType a.a_meta then error "@:coreType abstracts cannot have an underlying type" p; + let at = load_complex_type ctx true t in + delay ctx PForce (fun () -> + let rec loop stack t = + match follow t with + | TAbstract(a,_) when not (Meta.has Meta.CoreType a.a_meta) -> + if List.memq a stack then + error "Abstract underlying type cannot be recursive" a.a_pos + else + loop (a :: stack) a.a_this + | _ -> () + in + loop [] at + ); + a.a_this <- at; + is_type := true; + | AbExtern -> + (match a.a_impl with Some c -> c.cl_extern <- true | None -> (* Hmmmm.... *) ()) + | AbPrivate -> () + ) d.d_flags; + if not !is_type then begin + if Meta.has Meta.CoreType a.a_meta then + a.a_this <- TAbstract(a,List.map snd a.a_params) + else + error "Abstract is missing underlying type declaration" a.a_pos + end + +let module_pass_2 ctx m decls tdecls p = + (* here is an additional PASS 1 phase, which define the type parameters for all module types. + Constraints are handled lazily (no other type is loaded) because they might be recursive anyway *) + List.iter (fun d -> + match d with + | (TClassDecl c, (EClass d, p)) -> + c.cl_params <- type_type_params ctx c.cl_path (fun() -> c.cl_params) p d.d_params; + if Meta.has Meta.Generic c.cl_meta && c.cl_params <> [] then c.cl_kind <- KGeneric; + if Meta.has Meta.GenericBuild c.cl_meta then begin + if ctx.in_macro then error "@:genericBuild cannot be used in macros" c.cl_pos; + c.cl_kind <- KGenericBuild d.d_data; + end; + if c.cl_path = (["haxe";"macro"],"MacroType") then c.cl_kind <- KMacroType; + | (TEnumDecl e, (EEnum d, p)) -> + e.e_params <- type_type_params ctx e.e_path (fun() -> e.e_params) p d.d_params; + | (TTypeDecl t, (ETypedef d, p)) -> + t.t_params <- type_type_params ctx t.t_path (fun() -> t.t_params) p d.d_params; + | (TAbstractDecl a, (EAbstract d, p)) -> + a.a_params <- type_type_params ctx a.a_path (fun() -> a.a_params) p d.d_params; + | _ -> + assert false + ) decls; + (* setup module types *) + let context_init = ref [] in + let do_init() = + match !context_init with + | [] -> () + | l -> context_init := []; List.iter (fun f -> f()) (List.rev l) + in + List.iter (init_module_type ctx context_init do_init) tdecls + +(* + Creates a module context for [m] and types [tdecls] using it. +*) +let type_types_into_module ctx m tdecls p = + let decls, tdecls = module_pass_1 ctx m tdecls p in + let types = List.map fst decls in + List.iter (TypeloadCheck.check_module_types ctx m p) types; + m.m_types <- m.m_types @ types; + (* define the per-module context for the next pass *) + let ctx = { + com = ctx.com; + g = ctx.g; + t = ctx.t; + m = { + curmod = m; + module_types = List.map (fun t -> t,null_pos) ctx.g.std.m_types; + module_using = []; + module_globals = PMap.empty; + wildcard_packages = []; + module_imports = []; + }; + is_display_file = (ctx.com.display.dms_kind <> DMNone && DisplayPosition.display_position#is_in_file m.m_extra.m_file); + bypass_accessor = 0; + meta = []; + this_stack = []; + with_type_stack = []; + call_argument_stack = []; + pass = PBuildModule; + get_build_infos = (fun() -> None); + on_error = (fun ctx msg p -> ctx.com.error msg p); + macro_depth = ctx.macro_depth; + curclass = null_class; + curfield = null_field; + tthis = ctx.tthis; + ret = ctx.ret; + locals = PMap.empty; + type_params = []; + curfun = FunStatic; + untyped = false; + in_macro = ctx.in_macro; + in_display = false; + in_loop = false; + opened = []; + in_call_args = false; + vthis = None; + } in + if ctx.g.std != null_module then begin + add_dependency m ctx.g.std; + (* this will ensure both String and (indirectly) Array which are basic types which might be referenced *) + ignore(load_core_type ctx "String"); + end; + module_pass_2 ctx m decls tdecls p; + ctx + +let handle_import_hx ctx m decls p = + let path_split = match List.rev (Path.get_path_parts m.m_extra.m_file) with + | [] -> [] + | _ :: l -> l + in + let join l = String.concat Path.path_sep (List.rev ("import.hx" :: l)) in + let rec loop path pack = match path,pack with + | _,[] -> [join path] + | (p :: path),(_ :: pack) -> (join (p :: path)) :: (loop path pack) + | _ -> [] + in + let candidates = loop path_split (fst m.m_path) in + let make_import_module path r = + Hashtbl.replace ctx.com.parser_cache path r; + (* We use the file path as module name to make it unique. This may or may not be a good idea... *) + let m_import = make_module ctx ([],path) path p in + m_import.m_extra.m_kind <- MImport; + add_module ctx m_import p; + m_import + in + List.fold_left (fun acc path -> + let decls = try + let r = Hashtbl.find ctx.com.parser_cache path in + let mimport = Hashtbl.find ctx.g.modules ([],path) in + if mimport.m_extra.m_kind <> MFake then add_dependency m mimport; + r + with Not_found -> + if Sys.file_exists path then begin + let _,r = match !TypeloadParse.parse_hook ctx.com path p with + | ParseSuccess data -> data + | ParseDisplayFile(data,_) -> data + | ParseError(_,(msg,p),_) -> Parser.error msg p + in + List.iter (fun (d,p) -> match d with EImport _ | EUsing _ -> () | _ -> error "Only import and using is allowed in import.hx files" p) r; + add_dependency m (make_import_module path r); + r + end else begin + let r = [] in + (* Add empty decls so we don't check the file system all the time. *) + (make_import_module path r).m_extra.m_kind <- MFake; + r + end + in + decls @ acc + ) decls candidates + +(* + Creates a new module and types [tdecls] into it. +*) +let type_module ctx mpath file ?(is_extern=false) tdecls p = + let m = make_module ctx mpath file p in + Hashtbl.add ctx.g.modules m.m_path m; + let tdecls = handle_import_hx ctx m tdecls p in + let ctx = type_types_into_module ctx m tdecls p in + if is_extern then m.m_extra.m_kind <- MExtern; + begin if ctx.is_display_file then match ctx.com.display.dms_kind with + | DMResolve s -> + resolve_position_by_path ctx {tname = s; tpackage = []; tsub = None; tparams = []} p + | _ -> + () + end; + m + +(* let type_module ctx mpath file ?(is_extern=false) tdecls p = + let timer = Timer.timer ["typing";"type_module"] in + Std.finally timer (type_module ctx mpath file ~is_extern tdecls) p *) + +let type_module_hook = ref (fun _ _ _ -> None) + +let load_module ctx m p = + let m2 = (try + Hashtbl.find ctx.g.modules m + with + Not_found -> + match !type_module_hook ctx m p with + | Some m -> m + | None -> + let is_extern = ref false in + let file, decls = (try + TypeloadParse.parse_module ctx m p + with Not_found -> + let rec loop = function + | [] -> + raise (Error (Module_not_found m,p)) + | (file,load) :: l -> + match load m p with + | None -> loop l + | Some (_,a) -> file, a + in + is_extern := true; + loop ctx.com.load_extern_type + ) in + let is_extern = !is_extern in + try + type_module ctx m file ~is_extern decls p + with Forbid_package (inf,pl,pf) when p <> null_pos -> + raise (Forbid_package (inf,p::pl,pf)) + ) in + add_dependency ctx.m.curmod m2; + if ctx.pass = PTypeField then flush_pass ctx PBuildClass "load_module"; + m2 + +(* let load_module ctx m p = + let timer = Timer.timer ["typing";"load_module"] in + Std.finally timer (load_module ctx m) p *) + +;; diff --git a/src/typing/typeloadParse.ml b/src/typing/typeloadParse.ml new file mode 100644 index 00000000000..62e4143bc06 --- /dev/null +++ b/src/typing/typeloadParse.ml @@ -0,0 +1,218 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2019 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(* Parsing of module files into modules. *) + +open Globals +open Ast +open DisplayTypes.DiagnosticsSeverity +open DisplayTypes.DisplayMode +open Common +open Typecore +open Error + +let parse_file_from_lexbuf com file p lexbuf = + let t = Timer.timer ["parsing"] in + Lexer.init file true; + incr stats.s_files_parsed; + let parse_result = try + ParserEntry.parse com.defines lexbuf file + with + | Sedlexing.MalFormed -> + t(); + error "Malformed file. Source files must be encoded with UTF-8." {pfile = file; pmin = 0; pmax = 0} + | e -> + t(); + raise e + in + begin match !Parser.display_mode,parse_result with + | DMModuleSymbols (Some ""),_ -> () + | DMModuleSymbols filter,(ParseSuccess data | ParseDisplayFile(data,_)) when filter = None && DisplayPosition.display_position#is_in_file file -> + let ds = DocumentSymbols.collect_module_symbols (filter = None) data in + DisplayException.raise_module_symbols (DocumentSymbols.Printer.print_module_symbols com [file,ds] filter); + | _ -> + () + end; + t(); + Common.log com ("Parsed " ^ file); + parse_result + +let parse_file_from_string com file p string = + parse_file_from_lexbuf com file p (Sedlexing.Utf8.from_string string) + +let current_stdin = ref None (* TODO: we're supposed to clear this at some point *) + +let parse_file com file p = + let use_stdin = (Common.defined com Define.DisplayStdin) && DisplayPosition.display_position#is_in_file file in + if use_stdin then + let s = + match !current_stdin with + | Some s -> + s + | None -> + let s = Std.input_all stdin in + close_in stdin; + current_stdin := Some s; + s + in + parse_file_from_string com file p s + else + let ch = try open_in_bin file with _ -> error ("Could not open " ^ file) p in + Std.finally (fun() -> close_in ch) (parse_file_from_lexbuf com file p) (Sedlexing.Utf8.from_channel ch) + +let parse_hook = ref parse_file + +let resolve_module_file com m remap p = + let forbid = ref false in + let compose_path no_rename = + (match m with + | [] , name -> name + | x :: l , name -> + let x = (try + match PMap.find x com.package_rules with + | Forbidden -> forbid := true; x + | Directory d -> if no_rename then x else d + | Remap d -> remap := d :: l; d + with Not_found -> x + ) in + String.concat "/" (x :: l) ^ "/" ^ name + ) ^ ".hx" + in + let file = try + Common.find_file com (compose_path false) + with Not_found -> + Common.find_file com (compose_path true) + in + let file = (match String.lowercase (snd m) with + | "con" | "aux" | "prn" | "nul" | "com1" | "com2" | "com3" | "lpt1" | "lpt2" | "lpt3" when Sys.os_type = "Win32" -> + (* these names are reserved by the OS - old DOS legacy, such files cannot be easily created but are reported as visible *) + if (try (Unix.stat file).Unix.st_size with _ -> 0) > 0 then file else raise Not_found + | _ -> file + ) in + (* if we try to load a std.xxxx class and resolve a real std file, the package name is not valid, ignore *) + (match fst m with + | "std" :: _ -> + let file = Path.unique_full_path file in + if List.exists (fun path -> ExtString.String.starts_with file (try Path.unique_full_path path with _ -> path)) com.std_path then raise Not_found; + | _ -> ()); + if !forbid then begin + let parse_result = (!parse_hook) com file p in + let rec loop decls = match decls with + | ((EImport _,_) | (EUsing _,_)) :: decls -> loop decls + | (EClass d,_) :: _ -> d.d_meta + | (EEnum d,_) :: _ -> d.d_meta + | (EAbstract d,_) :: _ -> d.d_meta + | (ETypedef d,_) :: _ -> d.d_meta + | [] -> [] + in + let meta = match parse_result with + | ParseSuccess(_,decls) | ParseDisplayFile((_,decls),_) -> loop decls + | ParseError _ -> [] + in + if not (Meta.has Meta.NoPackageRestrict meta) then begin + let x = (match fst m with [] -> assert false | x :: _ -> x) in + raise (Forbid_package ((x,m,p),[],platform_name_macro com)); + end; + end; + file + +let resolve_module_file com m remap p = + try + Hashtbl.find com.module_to_file m + with Not_found -> + let file = resolve_module_file com m remap p in + Hashtbl.add com.module_to_file m file; + file + +(* let resolve_module_file com m remap p = + let timer = Timer.timer ["typing";"resolve_module_file"] in + Std.finally timer (resolve_module_file com m remap) p *) + +let parse_module_file com file p = + let handle_parser_error msg p = + let msg = Parser.error_msg msg in + match com.display.dms_error_policy with + | EPShow -> error msg p + | EPIgnore -> () + | EPCollect -> add_diagnostics_message com msg p DKParserError Error + in + let pack,decls = match (!parse_hook) com file p with + | ParseSuccess data -> data + | ParseDisplayFile(data,errors) -> + begin match errors with + | (msg,p) :: _ -> handle_parser_error msg p + | [] -> () + end; + data + | ParseError(data,(msg,p),_) -> + handle_parser_error msg p; + data + in + pack,decls + +let parse_module' com m p = + let remap = ref (fst m) in + let file = resolve_module_file com m remap p in + let pack,decls = parse_module_file com file p in + file,remap,pack,decls + +let parse_module ctx m p = + let file,remap,pack,decls = parse_module' ctx.com m p in + if pack <> !remap then begin + let spack m = if m = [] then "`package;`" else "`package " ^ (String.concat "." m) ^ ";`" in + if p == null_pos then + display_error ctx ("Invalid commandline class : " ^ s_type_path m ^ " should be " ^ s_type_path (pack,snd m)) p + else + display_error ctx (spack pack ^ " in " ^ file ^ " should be " ^ spack (fst m)) {p with pmax = p.pmin} + end; + file, if !remap <> fst m then + (* build typedefs to redirect to real package *) + List.rev (List.fold_left (fun acc (t,p) -> + let build f d = + let priv = List.mem f d.d_flags in + (ETypedef { + d_name = d.d_name; + d_doc = None; + d_meta = []; + d_params = d.d_params; + d_flags = if priv then [EPrivate] else []; + d_data = CTPath (if priv then { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; } else + { + tpackage = !remap; + tname = fst d.d_name; + tparams = List.map (fun tp -> + TPType (CTPath { tpackage = []; tname = fst tp.tp_name; tparams = []; tsub = None; },null_pos) + ) d.d_params; + tsub = None; + }),null_pos; + },p) :: acc + in + match t with + | EClass d -> build HPrivate d + | EEnum d -> build EPrivate d + | ETypedef d -> build EPrivate d + | EAbstract d -> build AbPrivate d + | EImport _ | EUsing _ -> acc + ) [(EImport (List.map (fun s -> s,null_pos) (!remap @ [snd m]),INormal),null_pos)] decls) + else + decls + +(* let parse_module ctx m p = + let timer = Timer.timer ["typing";"parse_module"] in + Std.finally timer (parse_module ctx m) p *) \ No newline at end of file diff --git a/src/typing/typer.ml b/src/typing/typer.ml index b759af3c3c0..d8caeeaee44 100644 --- a/src/typing/typer.ml +++ b/src/typing/typer.ml @@ -1,6 +1,6 @@ (* The Haxe Compiler - Copyright (C) 2005-2017 Haxe Foundation + Copyright (C) 2005-2019 Haxe Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -15,64 +15,34 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - *) - +*) open Ast -open Common.DisplayMode +open DisplayTypes.DisplayMode +open DisplayException +open DisplayTypes.CompletionResultKind +open CompletionItem.ClassFieldOrigin open Common open Type open Typecore open Error open Globals +open TyperBase +open Fields +open Calls (* ---------------------------------------------------------------------- *) (* TOOLS *) -type switch_mode = - | CMatch of (tenum_field * (string * t) option list option * pos) - | CExpr of texpr - -type access_mode = - | MGet - | MSet - | MCall - -type access_kind = - | AKNo of string - | AKExpr of texpr - | AKSet of texpr * t * tclass_field - | AKInline of texpr * tclass_field * tfield_access * t - | AKMacro of texpr * tclass_field - | AKUsing of texpr * tclass * tclass_field * texpr - | AKAccess of tabstract * tparams * tclass * texpr * texpr - -type object_decl_kind = - | ODKWithStructure of tanon - | ODKWithClass of tclass * tparams - | ODKPlain - -let build_call_ref : (typer -> access_kind -> expr list -> with_type -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false) - -let mk_infos ctx p params = - let file = if ctx.in_macro then p.pfile else if Common.defined ctx.com Define.AbsolutePath then Path.get_full_path p.pfile else Filename.basename p.pfile in - (EObjectDecl ( - (("fileName",null_pos,NoQuotes) , (EConst (String file) , p)) :: - (("lineNumber",null_pos,NoQuotes) , (EConst (Int (string_of_int (Lexer.get_error_line p))),p)) :: - (("className",null_pos,NoQuotes) , (EConst (String (s_type_path ctx.curclass.cl_path)),p)) :: - if ctx.curfield.cf_name = "" then - params - else - (("methodName",null_pos,NoQuotes), (EConst (String ctx.curfield.cf_name),p)) :: params - ) ,p) - let check_assign ctx e = match e.eexpr with + | TLocal {v_final = true} -> + error "Cannot assign to final" e.epos | TLocal {v_extra = None} | TArray _ | TField _ | TIdent _ -> () | TConst TThis | TTypeExpr _ when ctx.untyped -> () | _ -> - error "Invalid assign" e.epos + invalid_assign e.epos type type_class = | KInt @@ -81,7 +51,8 @@ type type_class = | KUnk | KDyn | KOther - | KParam of t + | KNumParam of t + | KStrParam of t | KAbstract of tabstract * t list let rec classify t = @@ -90,8 +61,10 @@ let rec classify t = | TAbstract({a_impl = Some _} as a,tl) -> KAbstract (a,tl) | TAbstract ({ a_path = [],"Int" },[]) -> KInt | TAbstract ({ a_path = [],"Float" },[]) -> KFloat - | TAbstract (a,[]) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) a.a_to -> KParam t - | TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) ctl -> KParam t + | TAbstract (a,[]) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) a.a_to -> KNumParam t + | TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) ctl -> KNumParam t + | TAbstract (a,[]) when List.exists (fun t -> match classify t with KString -> true | _ -> false) a.a_to -> KStrParam t + | TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KString -> true | _ -> false) ctl -> KStrParam t | TMono r when !r = None -> KUnk | TDynamic _ -> KDyn | _ -> KOther @@ -122,241 +95,76 @@ let get_iterable_param t = raise Not_found) | _ -> raise Not_found -let get_abstract_froms a pl = - let l = List.map (apply_params a.a_params pl) a.a_from in - List.fold_left (fun acc (t,f) -> - match follow (field_type f) with - | TFun ([_,_,v],t) -> - (try - ignore(type_eq EqStrict t (TAbstract(a,List.map dup pl))); (* unify fields monomorphs *) - v :: acc - with Unify_error _ -> - acc) - | _ -> - acc - ) l a.a_from_field - -(* - temporally remove the constant flag from structures to allow larger unification -*) -let remove_constant_flag t callb = - let tmp = ref [] in - let rec loop t = - match follow t with - | TAnon a -> - if !(a.a_status) = Const then begin - a.a_status := Closed; - tmp := a :: !tmp; - end; - PMap.iter (fun _ f -> loop f.cf_type) a.a_fields; - | _ -> - () - in - let restore() = - List.iter (fun a -> a.a_status := Const) (!tmp) - in +let maybe_type_against_enum ctx f with_type iscall p = try - loop t; - let ret = callb (!tmp <> []) in - restore(); - ret - with e -> - restore(); - raise e - -let rec is_pos_infos = function - | TMono r -> - (match !r with - | Some t -> is_pos_infos t - | _ -> false) - | TLazy f -> - is_pos_infos (lazy_type f) - | TType ({ t_path = ["haxe"] , "PosInfos" },[]) -> - true - | TType (t,tl) -> - is_pos_infos (apply_params t.t_params tl t.t_type) - | TAbstract({a_path=[],"Null"},[t]) -> - is_pos_infos t - | _ -> - false - -let check_constraints ctx tname tpl tl map delayed p = - List.iter2 (fun m (name,t) -> - match follow t with - | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> - let f = (fun() -> - List.iter (fun ct -> - try - Type.unify (map m) (map ct) - with Unify_error l -> - let l = Constraint_failure (tname ^ "." ^ name) :: l in - raise (Unify_error l) - ) constr - ) in - if delayed then - delay ctx PCheckConstraint (fun () -> try f() with Unify_error l -> display_error ctx (error_msg (Unify l)) p) - else + begin match with_type with + | WithType.WithType(t,_) -> + let rec loop stack t = match follow t with + | TEnum (en,_) -> + true,en.e_path,en.e_names,TEnumDecl en + | TAbstract ({a_impl = Some c} as a,_) when has_meta Meta.Enum a.a_meta -> + let fields = ExtList.List.filter_map (fun cf -> + if Meta.has Meta.Enum cf.cf_meta then Some cf.cf_name else None + ) c.cl_ordered_statics in + false,a.a_path,fields,TAbstractDecl a + | TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> + begin match get_abstract_froms a pl with + | [t2] -> + if (List.exists (fast_eq_anon ~mono_equals_dynamic:true t) stack) then raise Exit; + loop (t :: stack) t2 + | _ -> raise Exit + end + | _ -> + raise Exit + in + let is_enum,path,fields,mt = loop [] t in + let old = ctx.m.curmod.m_types in + let restore () = ctx.m.curmod.m_types <- old in + ctx.m.curmod.m_types <- ctx.m.curmod.m_types @ [mt]; + let e = try f() + with + | Error (Unknown_ident n,_) -> + restore(); + raise_or_display_message ctx (StringError.string_error n fields ("Identifier '" ^ n ^ "' is not part of " ^ s_type_path path)) p; + AKExpr (mk (TConst TNull) (mk_mono()) p) + | exc -> + restore(); + raise exc; + in + restore(); + begin match e with + | AKExpr e -> + begin match follow e.etype with + | TFun(_,t') when is_enum -> + (* TODO: this is a dodge for #7603 *) + (try Type.unify t' t with Unify_error _ -> ()); + AKExpr e + | _ -> + if iscall then + AKExpr e + else begin + AKExpr (AbstractCast.cast_or_unify ctx t e e.epos) + end + end + | _ -> e (* ??? *) + end | _ -> - () - ) tl tpl - -let enum_field_type ctx en ef tl_en tl_ef p = - let map t = apply_params en.e_params tl_en (apply_params ef.ef_params tl_ef t) in - begin try - check_constraints ctx (s_type_path en.e_path) en.e_params 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 - -let add_constraint_checks ctx ctypes pl f tl p = - List.iter2 (fun m (name,t) -> - match follow t with - | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> - let constr = List.map (fun t -> - let t = apply_params f.cf_params tl t in - (* only apply params if not static : in that case no param is passed *) - let t = (if pl = [] then t else apply_params ctypes pl t) in - t - ) constr in - delay ctx PCheckConstraint (fun() -> - List.iter (fun ct -> - try - (* if has_mono m then raise (Unify_error [Unify_custom "Could not resolve full type for constraint checks"; Unify_custom ("Type was " ^ (s_type (print_context()) m))]); *) - Type.unify m ct - with Unify_error l -> - display_error ctx (error_msg (Unify (Constraint_failure (f.cf_name ^ "." ^ name) :: l))) p; - ) constr - ); - | _ -> () - ) tl f.cf_params - -let field_type ctx c pl f p = - match f.cf_params with - | [] -> f.cf_type - | l -> - let monos = List.map (fun _ -> mk_mono()) l in - if not (Meta.has Meta.Generic f.cf_meta) then add_constraint_checks ctx c.cl_params pl f monos p; - apply_params l monos f.cf_type - -let class_field ctx c tl name p = - raw_class_field (fun f -> field_type ctx c tl f p) c tl name - -(* checks if we can access to a given class field using current context *) -let rec can_access ctx ?(in_overload=false) c cf stat = - if cf.cf_public then - true - else if not in_overload && ctx.com.config.pf_overload && Meta.has Meta.Overload cf.cf_meta then - true - else - (* TODO: should we add a c == ctx.curclass short check here? *) - (* has metadata path *) - let rec make_path c f = match c.cl_kind with - | KAbstractImpl a -> fst a.a_path @ [snd a.a_path; f.cf_name] - | KGenericInstance(c,_) -> make_path c f - | _ when c.cl_private -> List.rev (f.cf_name :: snd c.cl_path :: (List.tl (List.rev (fst c.cl_path)))) - | _ -> fst c.cl_path @ [snd c.cl_path; f.cf_name] - in - let rec expr_path acc e = - match fst e with - | EField (e,f) -> expr_path (f :: acc) e - | EConst (Ident n) -> n :: acc - | _ -> [] - in - let rec chk_path psub pfull = - match psub, pfull with - | [], _ -> true - | a :: l1, b :: l2 when a = b -> chk_path l1 l2 - | _ -> false - in - let has m c f path = - let rec loop = function - | (m2,el,_) :: l when m = m2 -> - List.exists (fun e -> - let p = expr_path [] e in - (p <> [] && chk_path p path) - ) el - || loop l - | _ :: l -> loop l - | [] -> false - in - loop c.cl_meta || loop f.cf_meta - in - let cur_paths = ref [] in - let rec loop c = - cur_paths := make_path c ctx.curfield :: !cur_paths; - begin match c.cl_super with - | Some (csup,_) -> loop csup - | None -> () - end; - List.iter (fun (c,_) -> loop c) c.cl_implements; - in - loop ctx.curclass; - let is_constr = cf.cf_name = "new" in - let rec loop c = - (try - (* if our common ancestor declare/override the field, then we can access it *) - let f = if is_constr then (match c.cl_constructor with None -> raise Not_found | Some c -> c) else PMap.find cf.cf_name (if stat then c.cl_statics else c.cl_fields) in - is_parent c ctx.curclass || (List.exists (has Meta.Allow c f) !cur_paths) - with Not_found -> - false - ) - || (match c.cl_super with - | Some (csup,_) -> loop csup - | None -> false) - || has Meta.Access ctx.curclass ctx.curfield (make_path c cf) - in - let b = loop c - (* access is also allowed of we access a type parameter which is constrained to our (base) class *) - || (match c.cl_kind with - | KTypeParameter tl -> - List.exists (fun t -> match follow t with TInst(c,_) -> loop c | _ -> false) tl - | _ -> false) - || (Meta.has Meta.PrivateAccess ctx.meta) in - (* TODO: find out what this does and move it to genas3 *) - if b && Common.defined ctx.com Common.Define.As3 && not (Meta.has Meta.Public cf.cf_meta) then cf.cf_meta <- (Meta.Public,[],cf.cf_pos) :: cf.cf_meta; - b - -(* removes the first argument of the class field's function type and all its overloads *) -let prepare_using_field cf = match follow cf.cf_type with - | TFun((_,_,tf) :: args,ret) -> - let rec loop acc overloads = match overloads with - | ({cf_type = TFun((_,_,tfo) :: args,ret)} as cfo) :: l -> - let tfo = apply_params cfo.cf_params (List.map snd cfo.cf_params) tfo in - (* ignore overloads which have a different first argument *) - if Type.type_iseq tf tfo then loop ({cfo with cf_type = TFun(args,ret)} :: acc) l else loop acc l - | _ :: l -> - loop acc l - | [] -> - acc - in - {cf with cf_overloads = loop [] cf.cf_overloads; cf_type = TFun(args,ret)} - | _ -> cf - -let merge_core_doc ctx c = - let c_core = Typeload.load_core_class ctx c in - if c.cl_doc = None then c.cl_doc <- c_core.cl_doc; - let maybe_merge cf_map cf = - if cf.cf_doc = None then try cf.cf_doc <- (PMap.find cf.cf_name cf_map).cf_doc with Not_found -> () - in - List.iter (maybe_merge c_core.cl_fields) c.cl_ordered_fields; - List.iter (maybe_merge c_core.cl_statics) c.cl_ordered_statics; - match c.cl_constructor,c_core.cl_constructor with - | Some ({cf_doc = None} as cf),Some cf2 -> cf.cf_doc <- cf2.cf_doc - | _ -> () + raise Exit + end + with Exit -> + f() let check_error ctx err p = match err with - | Module_not_found ([],name) when Display.Diagnostics.is_diagnostics_run ctx -> - Display.ToplevelCollector.handle_unresolved_identifier ctx name p true + | Module_not_found ([],name) when Diagnostics.is_diagnostics_run p -> + DisplayToplevel.handle_unresolved_identifier ctx name p true | _ -> display_error ctx (error_msg err) p (* ---------------------------------------------------------------------- *) (* PASS 3 : type expression & check structure *) -let rec unify_min_raise ctx (el:texpr list) : t = +let rec unify_min_raise basic (el:texpr list) : t = let rec base_types t = let tl = ref [] in let rec loop t = (match t with @@ -372,9 +180,6 @@ let rec unify_min_raise ctx (el:texpr list) : t = let t = apply_params cl.cl_params params (TInst (csup,pl)) in loop t); tl := t :: !tl; - | TEnum(en,(_ :: _ as tl2)) -> - tl := (TEnum(en,List.map (fun _ -> t_dynamic) tl2)) :: !tl; - tl := t :: !tl; | TType (td,pl) -> loop (apply_params td.t_params pl td.t_type); (* prioritize the most generic definition *) @@ -390,7 +195,7 @@ let rec unify_min_raise ctx (el:texpr list) : t = | [] -> mk_mono() | [e] -> e.etype | _ -> - let rec chk_null e = is_null e.etype || + let rec chk_null e = is_null e.etype || is_explicit_null e.etype || match e.eexpr with | TConst TNull -> true | TBlock el -> @@ -406,14 +211,14 @@ let rec unify_min_raise ctx (el:texpr list) : t = | [] -> false, t | e :: el -> - let t = if chk_null e then ctx.t.tnull t else t in + let t = if chk_null e then basic.tnull t else t in try - unify_raise ctx e.etype t e.epos; + Type.unify e.etype t; loop t el - with Error (Unify _,_) -> try - unify_raise ctx t e.etype e.epos; - loop (if is_null t then ctx.t.tnull e.etype else e.etype) el - with Error (Unify _,_) -> + with Unify_error _ -> try + Type.unify t e.etype; + loop (if is_null t then basic.tnull e.etype else e.etype) el + with Unify_error _ -> true, t in let has_error, t = loop (mk_mono()) el in @@ -440,7 +245,7 @@ let rec unify_min_raise ctx (el:texpr list) : t = raise Not_found ) PMap.empty el in let fields = PMap.foldi (fun n el acc -> - let t = try unify_min_raise ctx el with Error (Unify _, _) -> raise Not_found in + let t = try unify_min_raise basic el with Unify_error _ -> raise Not_found in PMap.add n (mk_field n t (List.hd el).epos null_pos) acc ) fields PMap.empty in TAnon { a_fields = fields; a_status = ref Closed } @@ -460,12 +265,12 @@ let rec unify_min_raise ctx (el:texpr list) : t = let common_types = ref (match List.rev dyn_types with [] -> common_types | l -> common_types @ l) in let loop e = let first_error = ref None in - let filter t = (try unify_raise ctx e.etype t e.epos; true - with Error (Unify l, p) as err -> if !first_error = None then first_error := Some(err); false) + let filter t = (try Type.unify e.etype t; true + with Unify_error l -> if !first_error = None then first_error := Some(Unify l,e.epos); false) in common_types := List.filter filter !common_types; match !common_types, !first_error with - | [], Some err -> raise err + | [], Some(err,p) -> raise_error err p | _ -> () in match !common_types with @@ -476,676 +281,17 @@ let rec unify_min_raise ctx (el:texpr list) : t = List.hd !common_types let unify_min ctx el = - try unify_min_raise ctx el + try unify_min_raise ctx.com.basic el with Error (Unify l,p) -> if not ctx.untyped then display_error ctx (error_msg (Unify l)) p; (List.hd el).etype -let is_forced_inline c cf = - match c with - | Some { cl_extern = true } -> true - | Some { cl_kind = KAbstractImpl _ } -> true - | _ when Meta.has Meta.Extern cf.cf_meta -> true - | _ -> false - -let rec unify_call_args' ctx el args r callp inline force_inline = - let in_call_args = ctx.in_call_args in - ctx.in_call_args <- true; - let call_error err p = - raise (Error (Call_error err,p)) - in - let arg_error ul name opt p = - let err = Stack (ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")) in - call_error (Could_not_unify err) p - in - let mk_pos_infos t = - let infos = mk_infos ctx callp [] in - type_expr ctx infos (WithType t) - in - let rec default_value name t = - if is_pos_infos t then - mk_pos_infos t - else - null (ctx.t.tnull t) callp - in - let skipped = ref [] in - let invalid_skips = ref [] in - let skip name ul t p = - if not ctx.com.config.pf_can_skip_non_nullable_argument && not (is_nullable t) then - invalid_skips := name :: !invalid_skips; - skipped := (name,ul,p) :: !skipped; - default_value name t - in - (* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, c.cl_extern | _ -> false, false in *) - let type_against t e = - try - let e = type_expr ctx e (WithType t) in - AbstractCast.cast_or_unify_raise ctx t e e.epos - with Error(l,p) when (match l with Call_error _ | Module_not_found _ -> false | _ -> true) -> - raise (WithTypeError (l,p)) - in - let rec loop el args = match el,args with - | [],[] -> - begin match List.rev !invalid_skips with - | [] -> () - | name :: _ -> call_error (Cannot_skip_non_nullable name) callp; - end; - [] - | _,[name,false,t] when (match follow t with TAbstract({a_path = ["haxe";"extern"],"Rest"},_) -> true | _ -> false) -> - begin match follow t with - | TAbstract({a_path=(["haxe";"extern"],"Rest")},[t]) -> - (try List.map (fun e -> type_against t e,false) el with WithTypeError(ul,p) -> arg_error ul name false p) - | _ -> - assert false - end - | [],(_,false,_) :: _ -> - call_error (Not_enough_arguments args) callp - | [],(name,true,t) :: args -> - begin match loop [] args with - | [] when not (inline && (ctx.g.doinline || force_inline)) && not ctx.com.config.pf_pad_nulls -> - if is_pos_infos t then [mk_pos_infos t,true] - else [] - | args -> - let e_def = default_value name t in - (e_def,true) :: args - end - | (_,p) :: _, [] -> - begin match List.rev !skipped with - | [] -> call_error Too_many_arguments p - | (s,ul,p) :: _ -> arg_error ul s true p - end - | e :: el,(name,opt,t) :: args -> - begin try - let e = type_against t e in - (e,opt) :: loop el args - with - WithTypeError (ul,p)-> - if opt then - let e_def = skip name ul t p in - (e_def,true) :: loop (e :: el) args - else - arg_error ul name false p - end - in - let el = try loop el args with exc -> ctx.in_call_args <- in_call_args; raise exc; in - ctx.in_call_args <- in_call_args; - el,TFun(args,r) - -let unify_call_args ctx el args r p inline force_inline = - let el,tf = unify_call_args' ctx el args r p inline force_inline in - List.map fst el,tf - -let unify_field_call ctx fa el args ret p inline = - let map_cf cf0 map cf = - let t = map (monomorphs cf.cf_params cf.cf_type) in - begin match cf.cf_expr,cf.cf_kind with - | None,Method MethInline when not ctx.com.config.pf_overload -> - (* This is really awkward and shouldn't be here. We'll keep it for - 3.2 in order to not break code that relied on the quirky behavior - in 3.1.3, but it should really be reviewed afterwards. - Related issue: https://github.com/HaxeFoundation/haxe/issues/3846 - *) - cf.cf_expr <- cf0.cf_expr; - cf.cf_kind <- cf0.cf_kind; - | _ -> - () - end; - t,cf - in - let expand_overloads map cf = - (TFun(args,ret),cf) :: (List.map (map_cf cf map) cf.cf_overloads) - in - let candidates,co,cf,mk_fa = match fa with - | FStatic(c,cf) -> - expand_overloads (fun t -> t) cf,Some c,cf,(fun cf -> FStatic(c,cf)) - | FAnon cf -> - expand_overloads (fun t -> t) cf,None,cf,(fun cf -> FAnon cf) - | FInstance(c,tl,cf) -> - let map = apply_params c.cl_params tl in - let cfl = if cf.cf_name = "new" || not (Meta.has Meta.Overload cf.cf_meta && ctx.com.config.pf_overload) then - List.map (map_cf cf map) cf.cf_overloads - else - List.map (fun (t,cf) -> map (monomorphs cf.cf_params t),cf) (Overloads.get_overloads c cf.cf_name) - in - (TFun(args,ret),cf) :: cfl,Some c,cf,(fun cf -> FInstance(c,tl,cf)) - | FClosure(co,cf) -> - let c = match co with None -> None | Some (c,_) -> Some c in - expand_overloads (fun t -> t) cf,c,cf,(fun cf -> match co with None -> FAnon cf | Some (c,tl) -> FInstance(c,tl,cf)) - | _ -> - error "Invalid field call" p - in - let is_forced_inline = is_forced_inline co cf in - let is_overload = Meta.has Meta.Overload cf.cf_meta in - let attempt_call t cf = match follow t with - | TFun(args,ret) -> - let el,tf = unify_call_args' ctx el args ret p inline is_forced_inline in - let mk_call ethis p_field = - let ef = mk (TField(ethis,mk_fa cf)) t p_field in - make_call ctx ef (List.map fst el) ret p - in - el,tf,mk_call - | _ -> - assert false - in - let rec loop candidates = match candidates with - | [] -> [],[] - | (t,cf) :: candidates -> - begin try - let candidate = attempt_call t cf in - if ctx.com.config.pf_overload && is_overload then begin - let candidates,failures = loop candidates in - candidate :: candidates,failures - end else - [candidate],[] - with Error ((Call_error _ as err),p) -> - let candidates,failures = loop candidates in - candidates,(cf,err,p) :: failures - end - in - let fail_fun () = - let tf = TFun(args,ret) in - [],tf,(fun ethis p_field -> - let e1 = mk (TField(ethis,mk_fa cf)) tf p_field in - mk (TCall(e1,[])) ret p) - in - match candidates with - | [t,cf] -> - begin try - let el,tf,mk_call = attempt_call t cf in - List.map fst el,tf,mk_call - with Error _ when ctx.com.display.dms_error_policy = EPIgnore -> - fail_fun(); - end - | _ -> - let candidates,failures = loop candidates in - let fail () = - let failures = List.map (fun (cf,err,p) -> cf,error_msg err,p) failures in - let failures = remove_duplicates (fun (_,msg1,_) (_,msg2,_) -> msg1 <> msg2) failures in - begin match failures with - | [_,msg,p] -> - error msg p - | _ -> - display_error ctx "Could not find a suitable overload, reasons follow" p; - List.iter (fun (cf,msg,p2) -> - display_error ctx ("Overload resolution failed for " ^ (s_type (print_context()) cf.cf_type)) p; - display_error ctx msg p2; - ) failures; - error "End of overload failure reasons" p - end - in - if is_overload && ctx.com.config.pf_overload then begin match Overloads.Resolution.reduce_compatible candidates with - | [] -> fail() - | [el,tf,mk_call] -> List.map fst el,tf,mk_call - | _ -> error "Ambiguous overload" p - end else begin match List.rev candidates with - | [] -> fail() - | (el,tf,mk_call) :: _ -> List.map fst el,tf,mk_call - end - -let fast_enum_field e ef p = - let et = mk (TTypeExpr (TEnumDecl e)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }) p in - TField (et,FEnum (e,ef)) - -let abstract_module_type a tl = { - t_path = [],Printf.sprintf "Abstract<%s%s>" (s_type_path a.a_path) (s_type_params (ref []) tl); - t_module = a.a_module; - t_doc = None; - t_pos = a.a_pos; - t_name_pos = null_pos; - t_type = TAnon { - a_fields = PMap.empty; - a_status = ref (AbstractStatics a); - }; - t_private = true; - t_params = []; - t_meta = no_meta; -} - -let rec type_module_type ctx t tparams p = - match t with - | TClassDecl {cl_kind = KGenericBuild _} -> - let _,_,f = Typeload.build_instance ctx t p in - let t = f (match tparams with None -> [] | Some tl -> tl) in - let mt = try - module_type_of_type t - with Exit -> - if follow t == t_dynamic then Typeload.load_type_def ctx p { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None } - else error "Invalid module type" p - in - type_module_type ctx mt None p - | TClassDecl c -> - let t_tmp = { - t_path = [],"Class<" ^ (s_type_path c.cl_path) ^ ">" ; - t_module = c.cl_module; - t_doc = None; - t_pos = c.cl_pos; - t_name_pos = null_pos; - t_type = TAnon { - a_fields = c.cl_statics; - a_status = ref (Statics c); - }; - t_private = true; - t_params = []; - t_meta = no_meta; - } in - mk (TTypeExpr (TClassDecl c)) (TType (t_tmp,[])) p - | TEnumDecl e -> - let types = (match tparams with None -> List.map (fun _ -> mk_mono()) e.e_params | Some l -> l) in - mk (TTypeExpr (TEnumDecl e)) (TType (e.e_type,types)) p - | TTypeDecl s -> - let t = apply_params s.t_params (List.map (fun _ -> mk_mono()) s.t_params) s.t_type in - if not (Common.defined ctx.com Define.NoDeprecationWarnings) then - Display.DeprecationCheck.check_typedef ctx.com s p; - (match follow t with - | TEnum (e,params) -> - type_module_type ctx (TEnumDecl e) (Some params) p - | TInst (c,params) -> - type_module_type ctx (TClassDecl c) (Some params) p - | TAbstract (a,params) -> - type_module_type ctx (TAbstractDecl a) (Some params) p - | _ -> - error (s_type_path s.t_path ^ " is not a value") p) - | TAbstractDecl { a_impl = Some c } -> - type_module_type ctx (TClassDecl c) tparams p - | TAbstractDecl a -> - if not (Meta.has Meta.RuntimeValue a.a_meta) then error (s_type_path a.a_path ^ " is not a value") p; - let t_tmp = abstract_module_type a [] in - mk (TTypeExpr (TAbstractDecl a)) (TType (t_tmp,[])) p - -let type_type ctx tpath p = - type_module_type ctx (Typeload.load_type_def ctx p { tpackage = fst tpath; tname = snd tpath; tparams = []; tsub = None }) None p - -let get_constructor ctx c params p = - match c.cl_kind with - | KAbstractImpl a -> - let f = (try PMap.find "_new" c.cl_statics with Not_found -> raise_error (No_constructor (TAbstractDecl a)) p) in - let ct = field_type ctx c params f p in - apply_params a.a_params params ct, f +let unify_min_for_type_source ctx el src = + match src with + | Some WithType.ImplicitReturn when List.exists (fun e -> ExtType.is_void (follow e.etype)) el -> + ctx.com.basic.tvoid | _ -> - let ct, f = (try Type.get_constructor (fun f -> field_type ctx c params f p) c with Not_found -> raise_error (No_constructor (TClassDecl c)) p) in - apply_params c.cl_params params ct, f - -let make_call ctx e params t p = - try - let ethis,cl,f = match e.eexpr with - | TField (ethis,fa) -> - let co,cf = match fa with - | FInstance(c,_,cf) | FStatic(c,cf) -> Some c,cf - | FAnon cf -> None,cf - | _ -> raise Exit - in - ethis,co,cf - | _ -> - raise Exit - in - if f.cf_kind <> Method MethInline then raise Exit; - let config = match cl with - | Some ({cl_kind = KAbstractImpl _}) when Meta.has Meta.Impl f.cf_meta -> - let t = if f.cf_name = "_new" then - t - else if params = [] then - error "Invalid abstract implementation function" f.cf_pos - else - follow (List.hd params).etype - in - begin match t with - | TAbstract(a,pl) -> - let has_params = a.a_params <> [] || f.cf_params <> [] in - let monos = List.map (fun _ -> mk_mono()) f.cf_params in - let map_type = fun t -> apply_params a.a_params pl (apply_params f.cf_params monos t) in - Some (has_params,map_type) - | _ -> - None - end - | _ -> - None - in - ignore(follow f.cf_type); (* force evaluation *) - let params = List.map (ctx.g.do_optimize ctx) params in - let force_inline = is_forced_inline cl f in - (match f.cf_expr_unoptimized,f.cf_expr with - | Some fd,_ - | None,Some { eexpr = TFunction fd } -> - (match Optimizer.type_inline ctx f fd ethis params t config p force_inline with - | None -> - if force_inline then error "Inline could not be done" p; - raise Exit; - | Some e -> e) - | _ -> - (* - we can't inline because there is most likely a loop in the typing. - this can be caused by mutually recursive vars/functions, some of them - being inlined or not. In that case simply ignore inlining. - *) - raise Exit) - with Exit -> - mk (TCall (e,params)) t p - -let mk_array_get_call ctx (cf,tf,r,e1,e2o) c ebase p = match cf.cf_expr with - | None -> - if not (Meta.has Meta.NoExpr cf.cf_meta) then display_error ctx "Recursive array get method" p; - mk (TArray(ebase,e1)) r p - | Some _ -> - let et = type_module_type ctx (TClassDecl c) None p in - let ef = mk (TField(et,(FStatic(c,cf)))) tf p in - make_call ctx ef [ebase;e1] r p - -let mk_array_set_call ctx (cf,tf,r,e1,e2o) c ebase p = - let evalue = match e2o with None -> assert false | Some e -> e in - match cf.cf_expr with - | None -> - if not (Meta.has Meta.NoExpr cf.cf_meta) then display_error ctx "Recursive array set method" p; - let ea = mk (TArray(ebase,e1)) r p in - mk (TBinop(OpAssign,ea,evalue)) r p - | Some _ -> - let et = type_module_type ctx (TClassDecl c) None p in - let ef = mk (TField(et,(FStatic(c,cf)))) tf p in - make_call ctx ef [ebase;e1;evalue] r p - -let rec acc_get ctx g p = - match g with - | AKNo f -> error ("Field " ^ f ^ " cannot be accessed for reading") p - | AKExpr e -> e - | AKSet _ | AKAccess _ -> assert false - | AKUsing (et,c,cf,e) when ctx.in_display -> - (* Generate a TField node so we can easily match it for position/usage completion (issue #1968) *) - let ec = type_module_type ctx (TClassDecl c) None p in - let t = match follow et.etype with - | TFun (_ :: args,ret) -> TFun(args,ret) - | _ -> et.etype - in - mk (TField(ec,FStatic(c,cf))) t et.epos - | AKUsing (et,_,cf,e) -> - (* build a closure with first parameter applied *) - (match follow et.etype with - | TFun (_ :: args,ret) -> - let tcallb = TFun (args,ret) in - let twrap = TFun ([("_e",false,e.etype)],tcallb) in - (* arguments might not have names in case of variable fields of function types, so we generate one (issue #2495) *) - let args = List.map (fun (n,o,t) -> - let t = if o then ctx.t.tnull t else t in - o,if n = "" then gen_local ctx t e.epos else alloc_var n t e.epos (* TODO: var pos *) - ) args in - let ve = alloc_var "_e" e.etype e.epos in - let ecall = make_call ctx et (List.map (fun v -> mk (TLocal v) v.v_type p) (ve :: List.map snd args)) ret p in - let ecallb = mk (TFunction { - tf_args = List.map (fun (o,v) -> v,if o then Some TNull else None) args; - tf_type = ret; - tf_expr = (match follow ret with | TAbstract ({a_path = [],"Void"},_) -> ecall | _ -> mk (TReturn (Some ecall)) t_dynamic p); - }) tcallb p in - let ewrap = mk (TFunction { - tf_args = [ve,None]; - tf_type = tcallb; - tf_expr = mk (TReturn (Some ecallb)) t_dynamic p; - }) twrap p in - make_call ctx ewrap [e] tcallb p - | _ -> assert false) - | AKInline (e,f,fmode,t) -> - (* do not create a closure for static calls *) - let cmode = (match fmode with FStatic _ -> fmode | FInstance (c,tl,f) -> FClosure (Some (c,tl),f) | _ -> assert false) in - ignore(follow f.cf_type); (* force computing *) - (match f.cf_expr with - | None when ctx.com.display.dms_display -> - mk (TField (e,cmode)) t p - | None -> - error "Recursive inline is not supported" p - | Some { eexpr = TFunction _ } -> - let chk_class c = (c.cl_extern || Meta.has Meta.Extern f.cf_meta) && not (Meta.has Meta.Runtime f.cf_meta) in - let wrap_extern c = - let c2 = - let m = c.cl_module in - let mpath = (fst m.m_path @ ["_" ^ snd m.m_path],(snd m.m_path) ^ "_Impl_") in - try - let rec loop mtl = match mtl with - | (TClassDecl c) :: _ when c.cl_path = mpath -> c - | _ :: mtl -> loop mtl - | [] -> raise Not_found - in - loop c.cl_module.m_types - with Not_found -> - let c2 = mk_class c.cl_module mpath c.cl_pos null_pos in - c.cl_module.m_types <- (TClassDecl c2) :: c.cl_module.m_types; - c2 - in - let cf = try - PMap.find f.cf_name c2.cl_statics - with Not_found -> - let cf = {f with cf_kind = Method MethNormal} in - c2.cl_statics <- PMap.add cf.cf_name cf c2.cl_statics; - c2.cl_ordered_statics <- cf :: c2.cl_ordered_statics; - cf - in - let e_t = type_module_type ctx (TClassDecl c2) None p in - mk (TField(e_t,FStatic(c2,cf))) t p - in - let e_def = mk (TField (e,cmode)) t p in - begin match follow e.etype with - | TInst (c,_) when chk_class c -> - display_error ctx "Can't create closure on an extern inline member method" p; - e_def - | TAnon a -> - begin match !(a.a_status) with - | Statics {cl_extern = false} when Meta.has Meta.Extern f.cf_meta -> - display_error ctx "Cannot create closure on @:extern inline method" p; - e_def - | Statics c when chk_class c -> wrap_extern c - | _ -> e_def - end - | _ -> e_def - end - | Some e -> - let rec loop e = Type.map_expr loop { e with epos = p } in - loop e) - | AKMacro _ -> - assert false - -let error_require r p = - if r = "" then - error "This field is not available with the current compilation flags" p - else - let r = if r = "sys" then - "a system platform (php,neko,cpp,etc.)" - else try - if String.sub r 0 5 <> "flash" then raise Exit; - let _, v = ExtString.String.replace (String.sub r 5 (String.length r - 5)) "_" "." in - "flash version " ^ v ^ " (use -swf-version " ^ v ^ ")" - with _ -> - "'" ^ r ^ "' to be enabled" - in - error ("Accessing this field requires " ^ r) p - -let get_this ctx p = - match ctx.curfun with - | FunStatic -> - error "Cannot access this from a static function" p - | FunMemberClassLocal | FunMemberAbstractLocal -> - let v = match ctx.vthis with - | None -> - let v = if ctx.curfun = FunMemberAbstractLocal then - PMap.find "this" ctx.locals - else - add_local ctx "`this" ctx.tthis p - in - ctx.vthis <- Some v; - v - | Some v -> - ctx.locals <- PMap.add v.v_name v ctx.locals; - v - in - mk (TLocal v) ctx.tthis p - | FunMemberAbstract -> - let v = (try PMap.find "this" ctx.locals with Not_found -> assert false) in - mk (TLocal v) v.v_type p - | FunConstructor | FunMember -> - mk (TConst TThis) ctx.tthis p - -let field_access ctx mode f fmode t e p = - let fnormal() = AKExpr (mk (TField (e,fmode)) t p) in - let normal() = - match follow e.etype with - | TAnon a -> - (match !(a.a_status) with - | EnumStatics en -> - let c = (try PMap.find f.cf_name en.e_constrs with Not_found -> assert false) in - let fmode = FEnum (en,c) in - AKExpr (mk (TField (e,fmode)) t p) - | _ -> fnormal()) - | _ -> fnormal() - in - match f.cf_kind with - | Method m -> - if mode = MSet && m <> MethDynamic && not ctx.untyped then error "Cannot rebind this method : please use 'dynamic' before method declaration" p; - begin match ctx.curfun,e.eexpr with - | (FunMemberAbstract | FunMemberAbstractLocal),TTypeExpr(TClassDecl ({cl_kind = KAbstractImpl a} as c)) when c == ctx.curclass && Meta.has Meta.Impl f.cf_meta -> - let e = mk (TField(e,fmode)) t p in - let ethis = get_this ctx p in - let ethis = {ethis with etype = TAbstract(a,List.map snd a.a_params)} in - AKUsing(e,ctx.curclass,f,ethis) - | _ -> - (match m, mode with - | MethInline, _ -> AKInline (e,f,fmode,t) - | MethMacro, MGet -> display_error ctx "Macro functions must be called immediately" p; normal() - | MethMacro, MCall -> AKMacro (e,f) - | _ , MGet -> - let cmode = (match fmode with - | FInstance(_, _, cf) | FStatic(_, cf) when Meta.has Meta.Generic cf.cf_meta -> display_error ctx "Cannot create closure on generic function" p; fmode - | FInstance (c,tl,cf) -> FClosure (Some (c,tl),cf) - | FStatic _ | FEnum _ -> fmode - | FAnon f -> FClosure (None, f) - | FDynamic _ | FClosure _ -> assert false - ) in - AKExpr (mk (TField (e,cmode)) t p) - | _ -> normal()) - end - | Var v -> - match (match mode with MGet | MCall -> v.v_read | MSet -> v.v_write) with - | AccNo when not (Meta.has Meta.PrivateAccess ctx.meta) -> - (match follow e.etype with - | TInst (c,_) when is_parent c ctx.curclass || can_access ctx c { f with cf_public = false } false -> normal() - | TAnon a -> - (match !(a.a_status) with - | Opened when mode = MSet -> - f.cf_kind <- Var { v with v_write = AccNormal }; - normal() - | Statics c2 when ctx.curclass == c2 || can_access ctx c2 { f with cf_public = false } true -> normal() - | _ -> if ctx.untyped then normal() else AKNo f.cf_name) - | _ -> - if ctx.untyped then normal() else AKNo f.cf_name) - | AccNormal | AccNo -> - (* - if we are reading from a read-only variable on an anonymous object, it might actually be a method, so make sure to create a closure - *) - let is_maybe_method() = - match v.v_write, follow t, follow e.etype with - | (AccNo | AccNever), TFun _, TAnon a -> - (match !(a.a_status) with - | Statics _ | EnumStatics _ -> false - | _ -> true) - | _ -> false - in - if mode = MGet && is_maybe_method() then - AKExpr (mk (TField (e,FClosure (None,f))) t p) - else - normal() - | AccCall when ctx.in_display -> - normal() - | AccCall -> - let m = (match mode with MSet -> "set_" | _ -> "get_") ^ f.cf_name in - let is_abstract_this_access () = match e.eexpr,ctx.curfun with - | TTypeExpr (TClassDecl ({cl_kind = KAbstractImpl _} as c)),(FunMemberAbstract | FunMemberAbstractLocal) -> - c == ctx.curclass - | _ -> - false - in - if m = ctx.curfield.cf_name && (match e.eexpr with TConst TThis -> true | TLocal v -> Option.map_default (fun vthis -> v == vthis) false ctx.vthis | TTypeExpr (TClassDecl c) when c == ctx.curclass -> true | _ -> false) then - let prefix = (match ctx.com.platform with Flash when Common.defined ctx.com Define.As3 -> "$" | _ -> "") in - (match e.eexpr with TLocal _ when Common.defined ctx.com Define.Haxe3Compat -> ctx.com.warning "Field set has changed here in Haxe 4: call setter explicitly to keep Haxe 3.x behaviour" p | _ -> ()); - if not (is_physical_field f) then begin - display_error ctx "This field cannot be accessed because it is not a real variable" p; - display_error ctx "Add @:isVar here to enable it" f.cf_pos; - end; - AKExpr (mk (TField (e,if prefix = "" then fmode else FDynamic (prefix ^ f.cf_name))) t p) - else if is_abstract_this_access() then begin - let this = get_this ctx p in - if mode = MSet then begin - let c,a = match ctx.curclass with {cl_kind = KAbstractImpl a} as c -> c,a | _ -> assert false in - let f = PMap.find m c.cl_statics in - (* we don't have access to the type parameters here, right? *) - (* let t = apply_params a.a_params pl (field_type ctx c [] f p) in *) - let t = (field_type ctx c [] f p) in - let ef = mk (TField (e,FStatic (c,f))) t p in - AKUsing (ef,c,f,this) - end else - AKExpr (make_call ctx (mk (TField (e,quick_field_dynamic e.etype m)) (tfun [this.etype] t) p) [this] t p) - end else if mode = MSet then - AKSet (e,t,f) - else - AKExpr (make_call ctx (mk (TField (e,quick_field_dynamic e.etype m)) (tfun [] t) p) [] t p) - | AccResolve -> - let fstring = mk (TConst (TString f.cf_name)) ctx.t.tstring p in - let tresolve = tfun [ctx.t.tstring] t in - AKExpr (make_call ctx (mk (TField (e,FDynamic "resolve")) tresolve p) [fstring] t p) - | AccNever -> - if ctx.untyped then normal() else AKNo f.cf_name - | AccInline -> - AKInline (e,f,fmode,t) - | AccCtor -> - if ctx.curfun = FunConstructor then normal() else AKNo f.cf_name - | AccRequire (r,msg) -> - match msg with - | None -> error_require r p - | Some msg -> error msg p - -let rec using_field ctx mode e i p = - if mode = MSet then raise Not_found; - (* do not try to find using fields if the type is a monomorph, which could lead to side-effects *) - let is_dynamic = match follow e.etype with - | TMono _ -> raise Not_found - | t -> t == t_dynamic - in - let check_constant_struct = ref false in - let rec loop = function - | [] -> - raise Not_found - | (c,pc) :: l -> - try - let cf = PMap.find i c.cl_statics in - if Meta.has Meta.NoUsing cf.cf_meta || not (can_access ctx c cf true) || (Meta.has Meta.Impl cf.cf_meta) then raise Not_found; - let monos = List.map (fun _ -> mk_mono()) cf.cf_params in - let map = apply_params cf.cf_params monos in - let t = map cf.cf_type in - begin match follow t with - | TFun((_,_,(TType({t_path = ["haxe";"macro"],"ExprOf"},[t0]) | t0)) :: args,r) -> - if is_dynamic && follow t0 != t_dynamic then raise Not_found; - let e = AbstractCast.cast_or_unify_raise ctx t0 e p in - (* early constraints check is possible because e.etype has no monomorphs *) - List.iter2 (fun m (name,t) -> match follow t with - | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] && not (has_mono m) -> - List.iter (fun tc -> Type.unify m (map tc)) constr - | _ -> () - ) monos cf.cf_params; - let et = type_module_type ctx (TClassDecl c) None p in - Display.ImportHandling.maybe_mark_import_position ctx pc; - AKUsing (mk (TField (et,FStatic (c,cf))) t p,c,cf,e) - | _ -> - raise Not_found - end - with Not_found -> - loop l - | Unify_error el | Error (Unify el,_) -> - if List.exists (function Has_extra_field _ -> true | _ -> false) el then check_constant_struct := true; - loop l - in - try loop ctx.m.module_using with Not_found -> - try - let acc = loop ctx.g.global_using in - (match acc with - | AKUsing (_,c,_,_) -> add_dependency ctx.m.curmod c.cl_module - | _ -> assert false); - acc - with Not_found -> - if not !check_constant_struct then raise Not_found; - remove_constant_flag e.etype (fun ok -> if ok then using_field ctx mode e i p else raise Not_found) + unify_min ctx el let rec type_ident_raise ctx i p mode = match i with @@ -1160,12 +306,11 @@ let rec type_ident_raise ctx i p mode = else AKNo i | "this" -> + if mode = MSet then add_class_field_flag ctx.curfield CfModifiesThis; (match mode, ctx.curclass.cl_kind with | MSet, KAbstractImpl _ -> - (match ctx.curfield.cf_kind with - | Method MethInline -> () - | Method _ when ctx.curfield.cf_name = "_new" -> () - | _ -> error "You can only modify 'this' inside an inline function" p); + if not (assign_to_this_is_allowed ctx) then + error "Abstract 'this' value can only be modified inside an inline function" p; AKExpr (get_this ctx p) | (MCall, KAbstractImpl _) | (MGet, _)-> AKExpr(get_this ctx p) | _ -> AKNo i) @@ -1192,7 +337,7 @@ let rec type_ident_raise ctx i p mode = | Some (params,e) -> let t = monomorphs params v.v_type in (match e with - | Some ({ eexpr = TFunction f } as e) when ctx.com.display.dms_full_typing -> + | Some ({ eexpr = TFunction f } as e) when ctx.com.display.dms_inline -> begin match mode with | MSet -> error "Cannot set inline closure" p | MGet -> error "Cannot create closure on inline closure" p @@ -1213,12 +358,6 @@ let rec type_ident_raise ctx i p mode = if ctx.curfun = FunStatic then raise Not_found; let c , t , f = class_field ctx ctx.curclass (List.map snd ctx.curclass.cl_params) i p in field_access ctx mode f (match c with None -> FAnon f | Some (c,tl) -> FInstance (c,tl,f)) t (get_this ctx p) p - with Not_found -> try - (* lookup using on 'this' *) - if ctx.curfun = FunStatic then raise Not_found; - (match using_field ctx mode (mk (TConst TThis) ctx.tthis p) i p with - | AKUsing (et,c,f,_) -> AKUsing (et,c,f,get_this ctx p) - | _ -> assert false) with Not_found -> try (* static variable lookup *) let f = PMap.find i ctx.curclass.cl_statics in @@ -1248,7 +387,7 @@ let rec type_ident_raise ctx i p mode = let et = type_module_type ctx (TClassDecl c) None p in let fa = FStatic(c,cf) in let t = monomorphs cf.cf_params cf.cf_type in - Display.ImportHandling.maybe_mark_import_position ctx pt; + ImportHandling.maybe_mark_import_position ctx pt; begin match cf.cf_kind with | Var {v_read = AccInline} -> AKInline(et,cf,fa,t) | _ -> AKExpr (mk (TField(et,fa)) t p) @@ -1262,6 +401,7 @@ let rec type_ident_raise ctx i p mode = | TTypeDecl t -> (match follow t.t_type with | TEnum (e,_) -> loop ((TEnumDecl e,pt) :: l) + | TAbstract (a,_) when Meta.has Meta.Enum a.a_meta -> loop ((TAbstractDecl a,pt) :: l) | _ -> loop l) | TEnumDecl e -> try @@ -1269,7 +409,7 @@ let rec type_ident_raise ctx i p mode = let et = type_module_type ctx t None p in let monos = List.map (fun _ -> mk_mono()) e.e_params in let monos2 = List.map (fun _ -> mk_mono()) ef.ef_params in - Display.ImportHandling.maybe_mark_import_position ctx pt; + ImportHandling.maybe_mark_import_position ctx pt; wrap (mk (TField (et,FEnum (e,ef))) (enum_field_type ctx e ef monos monos2 p) p) with Not_found -> loop l @@ -1278,343 +418,21 @@ let rec type_ident_raise ctx i p mode = with Not_found -> (* lookup imported globals *) let t, name, pi = PMap.find i ctx.m.module_globals in - Display.ImportHandling.maybe_mark_import_position ctx pi; + ImportHandling.maybe_mark_import_position ctx pi; let e = type_module_type ctx t None p in - type_field ctx e name p mode + type_field_default_cfg ctx e name p mode -and type_field ?(resume=false) ctx e i p mode = - let no_field() = - if resume then raise Not_found; - let t = match follow e.etype with - | TAnon a -> (match !(a.a_status) with - | Statics {cl_kind = KAbstractImpl a} -> TAbstract(a,[]) - | _ -> e.etype) - | TInst({cl_kind = KAbstractImpl a},_) -> TAbstract(a,[]) - | _ -> e.etype - in - let has_special_field a = - List.exists (fun (_,cf) -> cf.cf_name = i) a.a_ops - || List.exists (fun (_,_,cf) -> cf.cf_name = i) a.a_unops - || List.exists (fun cf -> cf.cf_name = i) a.a_array - in - if not ctx.untyped then begin - match t with - | TAbstract(a,_) when has_special_field a -> - (* the abstract field is not part of the field list, which is only true when it has no expression (issue #2344) *) - display_error ctx ("Field " ^ i ^ " cannot be called directly because it has no expression") p; - | _ -> - display_error ctx (StringError.string_error i (string_source t) (s_type (print_context()) t ^ " has no field " ^ i)) p; - end; - AKExpr (mk (TField (e,FDynamic i)) (mk_mono()) p) - in - let does_forward a stat = - try - let _,el,_ = Meta.get (if stat then Meta.ForwardStatics else Meta.Forward) a.a_meta in - match el with - | [] -> - true - | _ -> - List.exists (fun e -> match fst e with - | EConst(Ident s | String s) -> s = i - | _ -> error "Identifier or string expected as argument to @:forward" (pos e) - ) el - with Not_found -> - false - in - match follow e.etype with - | TInst (c,params) -> - let rec loop_dyn c params = - match c.cl_dynamic with - | Some t -> - let t = apply_params c.cl_params params t in - if (mode = MGet || mode = MCall) && PMap.mem "resolve" c.cl_fields then begin - let f = PMap.find "resolve" c.cl_fields in - begin match f.cf_kind with - | Method MethMacro -> display_error ctx "The macro accessor is not allowed for field resolve" f.cf_pos - | _ -> () - end; - let texpect = tfun [ctx.t.tstring] t in - let tfield = apply_params c.cl_params params (monomorphs f.cf_params f.cf_type) in - (try Type.unify tfield texpect - with Unify_error l -> - display_error ctx "Field resolve has an invalid type" f.cf_pos; - display_error ctx (error_msg (Unify [Cannot_unify(tfield,texpect)])) f.cf_pos); - AKExpr (make_call ctx (mk (TField (e,FInstance (c,params,f))) tfield p) [Codegen.type_constant ctx.com (String i) p] t p) - end else - AKExpr (mk (TField (e,FDynamic i)) t p) - | None -> - match c.cl_super with - | None -> raise Not_found - | Some (c,params) -> loop_dyn c params - in - (try - let c2, t , f = class_field ctx c params i p in - if e.eexpr = TConst TSuper then (match mode,f.cf_kind with - | MGet,Var {v_read = AccCall } - | MSet,Var {v_write = AccCall } - | MCall,Var {v_read = AccCall } -> - () - | MCall, Var _ -> - display_error ctx "Cannot access superclass variable for calling: needs to be a proper method" p - | MCall, _ -> - () - | MGet,Var _ - | MSet,Var _ when (match c2 with Some ({ cl_extern = true; cl_path = ("flash" :: _,_) }, _) -> true | _ -> false) -> - () - | _, Method _ -> - display_error ctx "Cannot create closure on super method" p - | _ -> - display_error ctx "Normal variables cannot be accessed with 'super', use 'this' instead" p); - if not (can_access ctx c f false) && not ctx.untyped then display_error ctx ("Cannot access private field " ^ i) p; - field_access ctx mode f (match c2 with None -> FAnon f | Some (c,tl) -> FInstance (c,tl,f)) (apply_params c.cl_params params t) e p - with Not_found -> try - begin match e.eexpr with - | TConst TSuper -> raise Not_found - | _ -> using_field ctx mode e i p - end - with Not_found -> try - loop_dyn c params - with Not_found -> try - (* if we have an abstract constraint we have to check its static fields and recurse (issue #2343) *) - begin match c.cl_kind with - | KTypeParameter tl -> - let rec loop tl = match tl with - | t :: tl -> - begin match follow t with - | TAbstract({a_impl = Some c},tl) when PMap.mem i c.cl_statics -> - let e = mk_cast e t p in - type_field ctx e i p mode; - | _ -> - loop tl - end - | [] -> - raise Not_found - in - loop tl - | _ -> - raise Not_found - end - with Not_found -> - if PMap.mem i c.cl_statics then error ("Cannot access static field " ^ i ^ " from a class instance") p; - no_field()) - | TDynamic t -> - (try - using_field ctx mode e i p - with Not_found -> - AKExpr (mk (TField (e,FDynamic i)) t p)) - | TAnon a -> - (try - let f = PMap.find i a.a_fields in - if Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Enum f.cf_meta) then display_error ctx "Cannot access non-static abstract field statically" p; - if not f.cf_public && not ctx.untyped then begin - match !(a.a_status) with - | Closed | Extend _ -> () (* always allow anon private fields access *) - | Statics c when can_access ctx c f true -> () - | _ -> display_error ctx ("Cannot access private field " ^ i) p - end; - let fmode, ft = (match !(a.a_status) with - | Statics c -> FStatic (c,f), field_type ctx c [] f p - | EnumStatics e -> FEnum (e,try PMap.find f.cf_name e.e_constrs with Not_found -> assert false), Type.field_type f - | _ -> - match f.cf_params with - | [] -> - FAnon f, Type.field_type f - | l -> - (* handle possible constraints *) - let monos = List.map (fun _ -> mk_mono()) l in - let t = apply_params f.cf_params monos f.cf_type in - add_constraint_checks ctx [] [] f monos p; - FAnon f, t - ) in - field_access ctx mode f fmode ft e p - with Not_found -> try - match !(a.a_status) with - | Statics {cl_kind = KAbstractImpl a} when does_forward a true -> - let mt = try module_type_of_type a.a_this with Exit -> raise Not_found in - let et = type_module_type ctx mt None p in - type_field ctx et i p mode; - | _ -> - raise Not_found - with Not_found -> - if is_closed a then try - using_field ctx mode e i p - with Not_found -> - no_field() - else - let f = { - (mk_field i (mk_mono()) p null_pos) with - cf_kind = Var { v_read = AccNormal; v_write = (match mode with MSet -> AccNormal | MGet | MCall -> AccNo) }; - } in - a.a_fields <- PMap.add i f a.a_fields; - field_access ctx mode f (FAnon f) (Type.field_type f) e p - ) - | TMono r -> - let f = { - (mk_field i (mk_mono()) p null_pos) with - cf_kind = Var { v_read = AccNormal; v_write = (match mode with MSet -> AccNormal | MGet | MCall -> AccNo) }; - } in - let x = ref Opened in - let t = TAnon { a_fields = PMap.add i f PMap.empty; a_status = x } in - ctx.opened <- x :: ctx.opened; - r := Some t; - field_access ctx mode f (FAnon f) (Type.field_type f) e p - | TAbstract (a,pl) -> - let static_abstract_access_through_instance = ref false in - (try - let c = (match a.a_impl with None -> raise Not_found | Some c -> c) in - let f = PMap.find i c.cl_statics in - if not (can_access ctx c f true) && not ctx.untyped then display_error ctx ("Cannot access private field " ^ i) p; - let field_type f = - if not (Meta.has Meta.Impl f.cf_meta) then begin - static_abstract_access_through_instance := true; - raise Not_found; - end; - let t = field_type ctx c [] f p in - apply_params a.a_params pl t - in - let et = type_module_type ctx (TClassDecl c) None p in - let field_expr f t = mk (TField (et,FStatic (c,f))) t p in - (match mode, f.cf_kind with - | (MGet | MCall), Var {v_read = AccCall } -> - (* getter call *) - let f = PMap.find ("get_" ^ f.cf_name) c.cl_statics in - let t = field_type f in - let r = match follow t with TFun(_,r) -> r | _ -> raise Not_found in - let ef = field_expr f t in - AKExpr(make_call ctx ef [e] r p) - | MSet, Var {v_write = AccCall } -> - let f = PMap.find ("set_" ^ f.cf_name) c.cl_statics in - let t = field_type f in - let ef = field_expr f t in - AKUsing (ef,c,f,e) - | (MGet | MCall), Var {v_read = AccNever} -> - AKNo f.cf_name - | (MGet | MCall), _ -> - let rec loop cfl = match cfl with - | [] -> error (Printf.sprintf "Field %s cannot be called on %s" f.cf_name (s_type (print_context()) e.etype)) p - | cf :: cfl -> - match follow (apply_params a.a_params pl (monomorphs cf.cf_params cf.cf_type)) with - | TFun((_,_,t1) :: _,_) when type_iseq t1 (Abstract.get_underlying_type a pl) -> - cf - | _ -> - loop cfl - in - let f = match f.cf_overloads with - | [] -> f - | cfl -> loop (f :: cfl) - in - let t = field_type f in - begin match follow t with - | TFun((_,_,t1) :: _,_) -> () - | _ -> error ("Invalid call to static function " ^ i ^ " through abstract instance") p - end; - let ef = field_expr f t in - AKUsing (ef,c,f,e) - | MSet, _ -> - error "This operation is unsupported" p) - with Not_found -> try - if does_forward a false then - type_field ~resume:true ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode - else - raise Not_found - with Not_found -> try - using_field ctx mode e i p - with Not_found -> try - (match ctx.curfun, e.eexpr with - | FunMemberAbstract, TConst (TThis) -> type_field ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode; - | _ -> raise Not_found) - with Not_found -> try - let c,cf = match a.a_impl,a.a_resolve with - | Some c,Some cf -> c,cf - | _ -> raise Not_found - in - let et = type_module_type ctx (TClassDecl c) None p in - let t = apply_params a.a_params pl (field_type ctx c [] cf p) in - let ef = mk (TField (et,FStatic (c,cf))) t p in - AKExpr ((!build_call_ref) ctx (AKUsing(ef,c,cf,e)) [EConst (String i),p] NoValue p) - with Not_found -> - if !static_abstract_access_through_instance then error ("Invalid call to static function " ^ i ^ " through abstract instance") p - else no_field()) - | _ -> - try using_field ctx mode e i p with Not_found -> no_field() - -let type_bind ctx (e : texpr) (args,ret) params p = - let vexpr v = mk (TLocal v) v.v_type p in - let acount = ref 0 in - let alloc_name n = - if n = "" && not ctx.is_display_file then begin - incr acount; - "a" ^ string_of_int !acount; - end else - n - in - let rec loop args params given_args missing_args ordered_args = match args, params with - | [], [] -> given_args,missing_args,ordered_args - | [], _ -> error "Too many callback arguments" p - | (n,o,t) :: args , [] when o -> - let a = if is_pos_infos t then - let infos = mk_infos ctx p [] in - ordered_args @ [type_expr ctx infos (WithType t)] - else if ctx.com.config.pf_pad_nulls then - (ordered_args @ [(mk (TConst TNull) t_dynamic p)]) - else - ordered_args - in - loop args [] given_args missing_args a - | (n,o,t) :: _ , (EConst(Ident "_"),p) :: _ when not ctx.com.config.pf_can_skip_non_nullable_argument && o && not (is_nullable t) -> - error "Usage of _ is not supported for optional non-nullable arguments" p - | (n,o,t) :: args , ([] as params) - | (n,o,t) :: args , (EConst(Ident "_"),_) :: params -> - let v = alloc_var (alloc_name n) (if o then ctx.t.tnull t else t) p in - loop args params given_args (missing_args @ [v,o]) (ordered_args @ [vexpr v]) - | (n,o,t) :: args , param :: params -> - let e = type_expr ctx param (WithType t) in - let e = AbstractCast.cast_or_unify ctx t e p in - let v = alloc_var (alloc_name n) t (pos param) in - loop args params (given_args @ [v,o,Some e]) missing_args (ordered_args @ [vexpr v]) - in - let given_args,missing_args,ordered_args = loop args params [] [] [] in - let rec gen_loc_name n = - let name = if n = 0 then "f" else "f" ^ (string_of_int n) in - if List.exists (fun (n,_,_) -> name = n) args then gen_loc_name (n + 1) else name - in - let loc = alloc_var (gen_loc_name 0) e.etype e.epos in - let given_args = (loc,false,Some e) :: given_args in - let inner_fun_args l = List.map (fun (v,o) -> v.v_name, o, v.v_type) l in - let t_inner = TFun(inner_fun_args missing_args, ret) in - let call = make_call ctx (vexpr loc) ordered_args ret p in - let e_ret = match follow ret with - | TAbstract ({a_path = [],"Void"},_) -> - call - | TMono _ -> - mk (TReturn (Some call)) t_dynamic p; - | _ -> - mk (TReturn (Some call)) t_dynamic p; - in - let func = mk (TFunction { - tf_args = List.map (fun (v,o) -> v, if o then Some TNull else None) missing_args; - tf_type = ret; - tf_expr = e_ret; - }) t_inner p in - let outer_fun_args l = List.map (fun (v,o,_) -> v.v_name, o, v.v_type) l in - let func = mk (TFunction { - tf_args = List.map (fun (v,_,_) -> v,None) given_args; - tf_type = t_inner; - tf_expr = mk (TReturn (Some func)) t_inner p; - }) (TFun(outer_fun_args given_args, t_inner)) p in - make_call ctx func (List.map (fun (_,_,e) -> (match e with Some e -> e | None -> assert false)) given_args) t_inner p - -(* - We want to try unifying as an integer and apply side effects. - However, in case the value is not a normal Monomorph but one issued - from a Dynamic relaxation, we will instead unify with float since - we don't want to accidentaly truncate the value -*) -let unify_int ctx e k = - let is_dynamic t = - match follow t with - | TDynamic _ -> true - | _ -> false +(* + We want to try unifying as an integer and apply side effects. + However, in case the value is not a normal Monomorph but one issued + from a Dynamic relaxation, we will instead unify with float since + we don't want to accidentaly truncate the value +*) +let unify_int ctx e k = + let is_dynamic t = + match follow t with + | TDynamic _ -> true + | _ -> false in let is_dynamic_array t = match follow t with @@ -1662,123 +480,37 @@ let unify_int ctx e k = unify ctx e.etype ctx.t.tint e.epos; true - let type_generic_function ctx (e,fa) el ?(using_param=None) with_type p = - let c,tl,cf,stat = match fa with - | FInstance(c,tl,cf) -> c,tl,cf,false - | FStatic(c,cf) -> c,[],cf,true - | _ -> assert false - in - if cf.cf_params = [] then error "Function has no type parameters and cannot be generic" p; - let monos = List.map (fun _ -> mk_mono()) cf.cf_params in - let map_monos t = apply_params cf.cf_params monos t in - let map t = if stat then map_monos t else apply_params c.cl_params tl (map_monos t) in - let t = map cf.cf_type in - let args,ret = match t,using_param with - | TFun((_,_,ta) :: args,ret),Some e -> - let ta = if not (Meta.has Meta.Impl cf.cf_meta) then ta - else match follow ta with TAbstract(a,tl) -> Abstract.get_underlying_type a tl | _ -> assert false - in - (* manually unify first argument *) - unify ctx e.etype ta p; - args,ret - | TFun(args,ret),None -> args,ret - | _ -> error "Invalid field type for generic call" p - in - begin match with_type with - | WithType t -> unify ctx ret t p - | _ -> () - end; - let el,_ = unify_call_args ctx el args ret p false false in - begin try - check_constraints ctx cf.cf_name cf.cf_params monos map false p - with Unify_error l -> - display_error ctx (error_msg (Unify l)) p - end; - let el = match using_param with None -> el | Some e -> e :: el in - (try - let gctx = Typeload.make_generic ctx cf.cf_params monos p in - let name = cf.cf_name ^ "_" ^ gctx.Typeload.name in - let unify_existing_field tcf pcf = try - unify_raise ctx tcf t p - with Error(Unify _,_) as err -> - display_error ctx ("Cannot create field " ^ name ^ " due to type mismatch") p; - display_error ctx "Conflicting field was defined here" pcf; - raise err - in - let cf2 = try - let cf2 = if stat then - let cf2 = PMap.find name c.cl_statics in - unify_existing_field cf2.cf_type cf2.cf_pos; - cf2 - else - let cf2 = PMap.find name c.cl_fields in - unify_existing_field cf2.cf_type cf2.cf_pos; - cf2 - in - cf2 - with Not_found -> - let cf2 = mk_field name (map_monos cf.cf_type) cf.cf_pos cf.cf_name_pos in - if stat then begin - c.cl_statics <- PMap.add name cf2 c.cl_statics; - c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics - end else begin - if List.memq cf c.cl_overrides then c.cl_overrides <- cf2 :: c.cl_overrides; - c.cl_fields <- PMap.add name cf2 c.cl_fields; - c.cl_ordered_fields <- cf2 :: c.cl_ordered_fields - end; - ignore(follow cf.cf_type); - let rec check e = match e.eexpr with - | TNew({cl_kind = KTypeParameter _} as c,_,_) when not (Typeload.is_generic_parameter ctx c) -> - display_error ctx "Only generic type parameters can be constructed" e.epos; - display_error ctx "While specializing this call" p; - | _ -> - Type.iter check e - in - cf2.cf_expr <- (match cf.cf_expr with - | None -> - display_error ctx "Recursive @:generic function" p; None; - | Some e -> - let e = Typeload.generic_substitute_expr gctx e in - check e; - Some e - ); - cf2.cf_kind <- cf.cf_kind; - cf2.cf_public <- cf.cf_public; - let metadata = List.filter (fun (m,_,_) -> match m with - | Meta.Generic -> false - | _ -> true - ) cf.cf_meta in - cf2.cf_meta <- (Meta.NoCompletion,[],p) :: (Meta.NoUsing,[],p) :: (Meta.GenericInstance,[],p) :: metadata; - cf2 - in - let path = match c.cl_kind with - | KAbstractImpl(a) -> - a.a_path - | _ -> c.cl_path - in - let e = if stat then type_type ctx path p else e in - let fa = if stat then FStatic (c,cf2) else FInstance (c,tl,cf2) in - let e = mk (TField(e,fa)) cf2.cf_type p in - make_call ctx e el ret p - with Typeload.Generic_Exception (msg,p) -> - error msg p) - -let call_to_string ctx ?(resume=false) e = - (* Ignore visibility of the toString field. *) - ctx.meta <- (Meta.PrivateAccess,[],e.epos) :: ctx.meta; - let acc = type_field ~resume ctx e "toString" e.epos MCall in - ctx.meta <- List.tl ctx.meta; - !build_call_ref ctx acc [] (WithType ctx.t.tstring) e.epos - let rec type_binop ctx op e1 e2 is_assign_op with_type p = + let type_non_assign_op abstract_overload_only = + (* 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.WithType(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 + | _ -> WithType.value + end + | _ -> + WithType.value + end + | _ -> + WithType.value + in + let e1 = type_expr ctx e1 wt in + type_binop2 ~abstract_overload_only ctx op e1 e2 is_assign_op wt p + in match op with | OpAssign -> let e1 = type_access ctx (fst e1) (snd e1) MSet in - let tt = (match e1 with AKNo _ | AKInline _ | AKUsing _ | AKMacro _ | AKAccess _ -> Value | AKSet(_,t,_) -> WithType t | AKExpr e -> WithType e.etype) in - let e2 = type_expr ctx e2 tt in + let e2 with_type = type_expr ctx e2 with_type in (match e1 with | AKNo s -> error ("Cannot access field or identifier " ^ s ^ " for writing") p + | AKExpr { eexpr = TLocal { v_kind = VUser TVOLocalFunction; v_name = name } } -> + error ("Cannot access function " ^ name ^ " for writing") p | AKExpr e1 -> + let e2 = e2 (WithType.with_type e1.etype) in let e2 = AbstractCast.cast_or_unify ctx e1.etype e2 p in check_assign ctx e1; (match e1.eexpr , e2.eexpr with @@ -1788,14 +520,24 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = | _ , _ -> ()); mk (TBinop (op,e1,e2)) e1.etype p | AKSet (e,t,cf) -> + let e2 = e2 (WithType.with_type t) in let e2 = AbstractCast.cast_or_unify ctx t e2 p in make_call ctx (mk (TField (e,quick_field_dynamic e.etype ("set_" ^ cf.cf_name))) (tfun [t] t) p) [e2] t p | AKAccess(a,tl,c,ebase,ekey) -> + let e2 = e2 WithType.value in mk_array_set_call ctx (AbstractCast.find_array_access ctx a tl ekey (Some e2) p) c ebase p - | AKUsing(ef,_,_,et) -> + | AKFieldSet(ethis,e1,fname,t) -> + let e2 = e2 (WithType.with_type t) in + begin match follow e1.etype with + | TFun([_;_;(_,_,t)],_) -> unify ctx e2.etype t e2.epos; + | _ -> assert false + end; + make_call ctx e1 [ethis;Texpr.Builder.make_string ctx.t fname null_pos;e2] t p + | AKUsing(ef,_,_,et,_) -> (* this must be an abstract setter *) let e2,ret = match follow ef.etype with | TFun([_;(_,_,t)],ret) -> + let e2 = e2 (WithType.with_type t) in AbstractCast.cast_or_unify ctx t e2 p,ret | _ -> error "Invalid field type for abstract setter" p in @@ -1806,7 +548,11 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = error "The operators ||= and &&= are not supported" p | OpAssignOp op -> (match type_access ctx (fst e1) (snd e1) MSet with - | AKNo s -> error ("Cannot access field or identifier " ^ s ^ " for writing") p + | AKNo s -> + (* try abstract operator overloading *) + (try type_non_assign_op true + with Not_found -> error ("Cannot access field or identifier " ^ s ^ " for writing") p + ) | AKExpr e -> let save = save_locals ctx in let v = gen_local ctx e.etype e.epos in @@ -1875,7 +621,7 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = mk (TVar (v,Some e)) ctx.t.tvoid p; e' ]) t p - | AKUsing(ef,c,cf,et) -> + | AKUsing(ef,c,cf,et,_) -> (* abstract setter + getter *) let ta = match c.cl_kind with KAbstractImpl a -> TAbstract(a, List.map (fun _ -> mk_mono()) a.a_params) | _ -> assert false in let ret = match follow ef.etype with @@ -1915,7 +661,7 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = let ekey,ekey' = maybe_bind_to_temp ekey in let ebase,ebase' = maybe_bind_to_temp ebase in let eget = mk_array_get_call ctx (cf_get,tf_get,r_get,ekey,None) c ebase p in - let eget = type_binop2 ctx op eget e2 true (WithType eget.etype) p in + let eget = type_binop2 ctx op eget e2 true (WithType.with_type eget.etype) p in unify ctx eget.etype r_get p; let cf_set,tf_set,r_set,ekey,eget = AbstractCast.find_array_access ctx a tl ekey (Some eget) p in let eget = match eget with None -> assert false | Some e -> e in @@ -1923,7 +669,7 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = let e = match cf_set.cf_expr,cf_get.cf_expr with | None,None -> let ea = mk (TArray(ebase,ekey)) r_get p in - mk (TBinop(OpAssignOp op,ea,type_expr ctx e2 (WithType r_get))) r_set p + mk (TBinop(OpAssignOp op,ea,type_expr ctx e2 (WithType.with_type r_get))) r_set p | Some _,Some _ -> let ef_set = mk (TField(et,(FStatic(c,cf_set)))) tf_set p in let el = [make_call ctx ef_set [ebase;ekey;eget] r_set p] in @@ -1938,30 +684,19 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = in save(); e + | AKFieldSet _ -> + error "Invalid operation" p | AKInline _ | AKMacro _ -> assert false) | _ -> - (* If the with_type is an abstract which has exactly one applicable @:op method, we can promote it - to the individual arguments (issue #2786). *) - let wt = match with_type with - | WithType t -> - 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 - type_binop2 ctx op e1 e2 is_assign_op wt p + type_non_assign_op false -and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = - let e2 = type_expr ctx e2 (if op == OpEq || op == OpNotEq then WithType e1.etype else wt) in +and type_binop2 ?(abstract_overload_only=false) ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = + let with_type = match op with + | OpEq | OpNotEq | OpLt | OpLte | OpGt | OpGte -> WithType.with_type e1.etype + | _ -> wt + in + let e2 = type_expr ctx e2 with_type in let tint = ctx.t.tint in let tfloat = ctx.t.tfloat in let tstring = ctx.t.tstring in @@ -1970,9 +705,9 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = | KAbstract ({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx e | KInt | KFloat | KString -> e - | KUnk | KDyn | KParam _ | KOther -> + | KUnk | KDyn | KNumParam _ | KStrParam _ | KOther -> let std = type_type ctx ([],"Std") e.epos in - let acc = acc_get ctx (type_field ctx std "string" e.epos MCall) e.epos in + let acc = acc_get ctx (type_field_default_cfg ctx std "string" e.epos MCall) e.epos in ignore(follow acc.etype); let acc = (match acc.eexpr with TField (e,FClosure (Some (c,tl),f)) -> { acc with eexpr = TField (e,FInstance (c,tl,f)) } | _ -> acc) in make_call ctx acc [e] ctx.t.tstring e.epos @@ -2024,18 +759,21 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = let ok1 = unify_int ctx e1 KUnk in let ok2 = unify_int ctx e2 KUnk in if ok1 && ok2 then tint else tfloat - | KParam t1, KParam t2 when Type.type_iseq t1 t2 -> + | KNumParam t1, KNumParam t2 when Type.type_iseq t1 t2 -> t1 - | KParam t, KInt | KInt, KParam t -> + | KNumParam t, KInt | KInt, KNumParam t -> t - | KParam _, KFloat | KFloat, KParam _ | KParam _, KParam _ -> + | KNumParam _, KFloat | KFloat, KNumParam _ | KNumParam _, KNumParam _ -> tfloat - | KParam t, KUnk -> + | KNumParam t, KUnk -> unify ctx e2.etype tfloat e2.epos; tfloat - | KUnk, KParam t -> + | KUnk, KNumParam t -> unify ctx e1.etype tfloat e1.epos; tfloat + | KStrParam _, _ + | _, KStrParam _ -> + tstring | KAbstract _,KFloat -> unify ctx e1.etype tfloat e1.epos; tfloat @@ -2050,8 +788,8 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = ctx.t.tint | KAbstract _,_ | _,KAbstract _ - | KParam _, _ - | _, KParam _ + | KNumParam _, _ + | _, KNumParam _ | KOther, _ | _ , KOther -> let pr = print_context() in @@ -2075,13 +813,13 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = (match classify e1.etype, classify e2.etype with | KFloat, KFloat -> result := tfloat - | KParam t1, KParam t2 when Type.type_iseq t1 t2 -> + | KNumParam t1, KNumParam t2 when Type.type_iseq t1 t2 -> if op <> OpDiv then result := t1 - | KParam _, KParam _ -> + | KNumParam _, KNumParam _ -> result := tfloat - | KParam t, KInt | KInt, KParam t -> + | KNumParam t, KInt | KInt, KNumParam t -> if op <> OpDiv then result := t - | KParam _, KFloat | KFloat, KParam _ -> + | KNumParam _, KFloat | KFloat, KNumParam _ -> result := tfloat | KFloat, k -> ignore(unify_int ctx e2 k); @@ -2104,6 +842,13 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = with Error (Unify _,_) -> e1,AbstractCast.cast_or_unify ctx e1.etype e2 p in + if not ctx.com.config.pf_supports_function_equality then begin match e1.eexpr, e2.eexpr with + | TConst TNull , _ | _ , TConst TNull -> () + | _ -> + match follow e1.etype, follow e2.etype with + | TFun _ , _ | _, TFun _ -> ctx.com.warning "Comparison of function values is unspecified on this target, use Reflect.compareMethods instead" p + | _ -> () + end; mk_op e1 e2 ctx.t.tbool | OpGt | OpGte @@ -2121,8 +866,10 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = | KDyn , KInt | KDyn , KFloat | KDyn , KString -> () | KInt , KDyn | KFloat , KDyn | KString , KDyn -> () | KDyn , KDyn -> () - | KParam _ , x when x <> KString && x <> KOther -> () - | x , KParam _ when x <> KString && x <> KOther -> () + | KNumParam _ , (KInt | KFloat | KNumParam _ | KDyn | KUnk ) -> () + | (KInt | KFloat | KDyn | KUnk ), KNumParam _ -> () + | KStrParam _ , (KString | KStrParam _ | KUnk | KDyn) -> () + | (KString | KUnk | KDyn) , KStrParam _ -> () | KAbstract _,_ | _,KAbstract _ | KDyn , KUnk @@ -2131,8 +878,10 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = | KString , KFloat | KInt , KString | KFloat , KString - | KParam _ , _ - | _ , KParam _ + | KNumParam _ , _ + | _ , KNumParam _ + | KStrParam _ , _ + | _ , KStrParam _ | KOther , _ | _ , KOther -> let pr = print_context() in @@ -2178,9 +927,8 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = error (Printf.sprintf "The result of this operation (%s) is not compatible with declared return type %s" (st t_expected) (st tret)) p end; end; - let e = Codegen.binop op e1 e2 tret p in + let e = Texpr.Builder.binop op e1 e2 tret p in mk_cast e tret p - (* Codegen.maybe_cast e tret *) end else begin let e = make_static_call ctx c cf map [e1;e2] tret p in e @@ -2188,7 +936,7 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = in (* special case for == and !=: if the second type is a monomorph, assume that we want to unify it with the first type to preserve comparison semantics. *) - let is_eq_op = match op with OpEq | OpNotEq -> true | _ -> false in + let is_eq_op = match op with OpEq | OpNotEq -> true | _ -> false in if is_eq_op then begin match follow e1.etype,follow e2.etype with | TMono _,_ | _,TMono _ -> Type.unify e1.etype e2.etype @@ -2265,7 +1013,7 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = | [] -> raise Not_found in - loop (if left then a.a_ops else List.filter (fun (_,cf) -> not (Meta.has Meta.Impl cf.cf_meta)) a.a_ops) + loop a.a_ops in try begin match follow e1.etype with @@ -2278,7 +1026,8 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = | _ -> raise Not_found end with Not_found -> - make e1 e2 + if abstract_overload_only then raise Not_found + else make e1 e2 and type_unop ctx op flag e p = let set = (op = Increment || op = Decrement) in @@ -2299,7 +1048,7 @@ and type_unop ctx op flag e p = if set then check_assign ctx e; (match classify e.etype with | KFloat -> ctx.t.tfloat - | KParam t -> + | KNumParam t -> unify ctx e.etype ctx.t.tfloat e.epos; t | k -> @@ -2344,12 +1093,12 @@ and type_unop ctx op flag e p = | AKAccess(a,tl,c,ebase,ekey) -> begin try (match op with Increment | Decrement -> () | _ -> raise Not_found); - let v_key = alloc_var "tmp" ekey.etype ekey.epos in + let v_key = alloc_var VGenerated "tmp" ekey.etype ekey.epos in let evar_key = mk (TVar(v_key,Some ekey)) ctx.com.basic.tvoid ekey.epos in let ekey = mk (TLocal v_key) ekey.etype ekey.epos in (* get *) let e_get = mk_array_get_call ctx (AbstractCast.find_array_access_raise ctx a tl ekey None p) c ebase p in - let v_get = alloc_var "tmp" e_get.etype e_get.epos in + let v_get = alloc_var VGenerated "tmp" e_get.etype e_get.epos in let ev_get = mk (TLocal v_get) v_get.v_type p in let evar_get = mk (TVar(v_get,Some e_get)) ctx.com.basic.tvoid p in (* op *) @@ -2365,6 +1114,8 @@ and type_unop ctx op flag e p = end | AKInline _ | AKUsing _ | AKMacro _ -> error "This kind of operation is not supported" p + | AKFieldSet _ -> + error "Invalid operation" p | AKSet (e,t,cf) -> let l = save_locals ctx in let v = gen_local ctx e.etype p in @@ -2374,7 +1125,7 @@ and type_unop ctx op flag e p = let eget = (EField ((EConst (Ident v.v_name),p),cf.cf_name),p) in match flag with | Prefix -> - let get = type_binop ctx op eget one false Value p in + let get = type_binop ctx op eget one false WithType.value p in unify ctx get.etype t p; l(); mk (TBlock [ @@ -2384,8 +1135,8 @@ and type_unop ctx op flag e p = | Postfix -> let v2 = gen_local ctx t p in let ev2 = mk (TLocal v2) t p in - let get = type_expr ctx eget Value in - let plusone = type_binop ctx op (EConst (Ident v2.v_name),p) one false Value p in + let get = type_expr ctx eget WithType.value in + let plusone = type_binop ctx op (EConst (Ident v2.v_name),p) one false WithType.value p in unify ctx get.etype t p; l(); mk (TBlock [ @@ -2406,44 +1157,50 @@ and type_ident ctx i p mode = let e = (try type_type ctx ([],i) p with Error (Module_not_found ([],name),_) when name = i -> raise Not_found) in AKExpr e with Not_found -> - if ctx.untyped then begin - if i = "__this__" then - AKExpr (mk (TConst TThis) ctx.tthis p) - else - let t = mk_mono() in - AKExpr ((mk (TIdent i)) t p) - end else begin - if ctx.curfun = FunStatic && PMap.mem i ctx.curclass.cl_fields then error ("Cannot access " ^ i ^ " in static function") p; - begin try - let t = List.find (fun (i2,_) -> i2 = i) ctx.type_params in - let c = match follow (snd t) with TInst(c,_) -> c | _ -> assert false in - if Typeload.is_generic_parameter ctx c && Meta.has Meta.Const c.cl_meta then - AKExpr (type_module_type ctx (TClassDecl c) None p) - else begin - display_error ctx ("Type parameter " ^ i ^ " is only available at compilation and is not a runtime value") p; + let resolved_to_type_parameter = ref false in + try + let t = List.find (fun (i2,_) -> i2 = i) ctx.type_params in + resolved_to_type_parameter := true; + let c = match follow (snd t) with TInst(c,_) -> c | _ -> assert false in + if TypeloadCheck.is_generic_parameter ctx c && Meta.has Meta.Const c.cl_meta then begin + let e = type_module_type ctx (TClassDecl c) None p in + AKExpr {e with etype = (snd t)} + end else + raise Not_found + with Not_found -> + if ctx.untyped then begin + if i = "__this__" then + AKExpr (mk (TConst TThis) ctx.tthis p) + else + let t = mk_mono() in + AKExpr ((mk (TIdent i)) t p) + end else begin + if ctx.curfun = FunStatic && PMap.mem i ctx.curclass.cl_fields then error ("Cannot access " ^ i ^ " in static function") p; + if !resolved_to_type_parameter then begin + display_error ctx ("Only @:const type parameters on @:generic classes can be used as value") p; AKExpr (mk (TConst TNull) t_dynamic p) + end else begin + let err = Unknown_ident i in + if ctx.in_display then begin + raise (Error (err,p)) + end; + match ctx.com.display.dms_kind with + | DMNone -> + raise (Error(err,p)) + | DMDiagnostics b when b || ctx.is_display_file -> + DisplayToplevel.handle_unresolved_identifier ctx i p false; + let t = mk_mono() in + AKExpr (mk (TIdent i) t p) + | _ -> + display_error ctx (error_msg err) p; + let t = mk_mono() in + AKExpr (mk (TIdent i) t p) end - with Not_found -> - let err = Unknown_ident i in - if ctx.in_display then begin - raise (Error (err,p)) - end; - match ctx.com.display.dms_kind with - | DMNone -> - raise (Error(err,p)) - | DMDiagnostics b when b || ctx.is_display_file -> - Display.ToplevelCollector.handle_unresolved_identifier ctx i p false; - let t = mk_mono() in - AKExpr (mk (TIdent i) t p) - | _ -> - display_error ctx (error_msg err) p; - let t = mk_mono() in - AKExpr (mk (TIdent i) t p) end - end (* MORDOR *) and handle_efield ctx e p mode = + let p0 = p in (* given chain of fields as the `path` argument and an `access_mode->access_kind` getter for some starting expression as `e`, return a new `access_mode->access_kind` getter for the whole field access chain. @@ -2456,7 +1213,7 @@ and handle_efield ctx e p mode = let force = ref false in let e = List.fold_left (fun e (f,_,p) -> let e = acc_get ctx (e MGet) p in - let f = type_field ~resume:(!resume) ctx e f p in + let f = type_field (TypeFieldConfig.create !resume) ctx e f p in force := !resume; resume := false; f @@ -2520,7 +1277,7 @@ and handle_efield ctx e p mode = (* try accessing subtype or main class static field by `sname` in given module with path `m` *) let check_module m = try - let md = Typeload.load_module ctx m p in + let md = TypeloadModule.load_module ctx m p in (* first look for existing subtype *) (try let t = List.find (fun t -> not (t_infos t).mt_private && t_path t = (fst m,sname)) md.m_types in @@ -2548,7 +1305,7 @@ and handle_efield ctx e p mode = List.find path_match ctx.m.curmod.m_types (* types in this modules *) with Not_found -> let t,p = List.find (fun (t,_) -> path_match t) ctx.m.module_types in (* imported types *) - Display.ImportHandling.maybe_mark_import_position ctx p; + ImportHandling.maybe_mark_import_position ctx p; t in get_static true t @@ -2605,8 +1362,12 @@ and handle_efield ctx e p mode = raise (Error (Module_not_found (List.rev !path,name),p)) with Not_found -> + let sl = List.map (fun (n,_,_) -> n) (List.rev acc) in (* if there was no module name part, last guess is that we're trying to get package completion *) - if ctx.in_display then raise (Parser.TypePath (List.map (fun (n,_,_) -> n) (List.rev acc),None,false)); + if ctx.in_display then begin + if ctx.com.json_out = None then raise (Parser.TypePath (sl,None,false,p)) + else DisplayToplevel.collect_and_raise ctx TKType WithType.no_value (CRToplevel None) (String.concat "." sl,p0) (Some p0) + end; raise e) in match path with @@ -2651,15 +1412,16 @@ and type_access ctx e p mode = | EConst (Ident s) -> type_ident ctx s p mode | EField (e1,"new") -> - let e1 = type_expr ctx e1 Value in + let e1 = type_expr ctx e1 WithType.value in begin match e1.eexpr with | TTypeExpr (TClassDecl c) -> if mode = MSet then error "Cannot set constructor" p; if mode = MCall then error ("Cannot call constructor like this, use 'new " ^ (s_type_path c.cl_path) ^ "()' instead") p; - let monos = List.map (fun _ -> mk_mono()) c.cl_params in + let monos = List.map (fun _ -> mk_mono()) (match c.cl_kind with KAbstractImpl a -> a.a_params | _ -> c.cl_params) in let ct, cf = get_constructor ctx c monos p in + check_constructor_access ctx c cf p; let args = match follow ct with TFun(args,ret) -> args | _ -> assert false in - let vl = List.map (fun (n,_,t) -> alloc_var n t c.cl_pos) args in + let vl = List.map (fun (n,_,t) -> alloc_var VGenerated n t c.cl_pos) args in let vexpr v = mk (TLocal v) v.v_type p in let el = List.map vexpr vl in let ec,t = match c.cl_kind with @@ -2682,72 +1444,48 @@ and type_access ctx e p mode = | EField _ -> handle_efield ctx e p mode | EArray (e1,e2) -> - let e1 = type_expr ctx e1 Value in - let e2 = type_expr ctx e2 Value in - let has_abstract_array_access = ref false in - (try (match follow e1.etype with - | TAbstract ({a_impl = Some c} as a,pl) when a.a_array <> [] -> - begin match mode with - | MSet -> - (* resolve later *) - AKAccess (a,pl,c,e1,e2) - | _ -> - has_abstract_array_access := true; - let e = mk_array_get_call ctx (AbstractCast.find_array_access ctx a pl e2 None p) c e1 p in - AKExpr e - end - | _ -> raise Not_found) - with Not_found -> - unify ctx e2.etype ctx.t.tint e2.epos; - let rec loop et = - match follow et with - | TInst ({ cl_array_access = Some t; cl_params = pl },tl) -> - apply_params pl tl t - | TInst ({ cl_super = Some (c,stl); cl_params = pl },tl) -> - apply_params pl tl (loop (TInst (c,stl))) - | TInst ({ cl_path = [],"ArrayAccess" },[t]) -> - t - | TInst ({ cl_path = [],"Array"},[t]) when t == t_dynamic -> - t_dynamic - | TAbstract(a,tl) when Meta.has Meta.ArrayAccess a.a_meta -> - loop (apply_params a.a_params tl a.a_this) - | _ -> - let pt = mk_mono() in - let t = ctx.t.tarray pt in - (try unify_raise ctx et t p - with Error(Unify _,_) -> if not ctx.untyped then begin - if !has_abstract_array_access then error ("No @:arrayAccess function accepts an argument of " ^ (s_type (print_context()) e2.etype)) e1.epos - else error ("Array access is not allowed on " ^ (s_type (print_context()) e1.etype)) e1.epos - end); - pt - in - let pt = loop e1.etype in - AKExpr (mk (TArray (e1,e2)) pt p)) + type_array_access ctx e1 e2 p mode + | EDisplay (e,dk) -> + let resume_typing = type_expr ~mode in + AKExpr (TyperDisplay.handle_edisplay ~resume_typing ctx e dk WithType.value) | _ -> - AKExpr (type_expr ctx (e,p) Value) + AKExpr (type_expr ~mode ctx (e,p) WithType.value) + +and type_array_access ctx e1 e2 p mode = + let e1 = type_expr ctx e1 WithType.value in + let e2 = type_expr ctx e2 WithType.value in + Calls.array_access ctx e1 e2 mode p and type_vars ctx vl p = - let vl = List.map (fun ((v,pv),t,e) -> + let vl = List.map (fun ((v,pv),final,t,e) -> try let t = Typeload.load_type_hint ctx p t in let e = (match e with | None -> None | Some e -> - let e = type_expr ctx e (WithType t) in + let e = type_expr ctx e (WithType.with_type t) in let e = AbstractCast.cast_or_unify ctx t e p in Some e ) in - if v.[0] = '$' then display_error ctx "Variables names starting with a dollar are not allowed" p; - let v = add_local ctx v t pv in - v.v_meta <- (Meta.UserVariable,[],pv) :: v.v_meta; - if ctx.in_display && Display.is_display_position pv then - Display.DisplayEmitter.display_variable ctx.com.display v pv; + if starts_with v '$' then display_error ctx "Variables names starting with a dollar are not allowed" p; + let v = add_local_with_origin ctx TVOLocalVariable v t pv in + if final then v.v_final <- true; + if ctx.in_display && DisplayPosition.display_position#enclosed_in pv then + DisplayEmitter.display_variable ctx v pv; v,e with Error (e,p) -> check_error ctx e p; - add_local ctx v t_dynamic pv, None (* TODO: What to do with this... *) + add_local ctx VGenerated v t_dynamic pv, None (* TODO: What to do with this... *) ) vl in + delay ctx PTypeField (fun() -> + List.iter + (fun (v,_) -> + if ExtType.is_void (follow v.v_type) then + error "Variables of type Void are not allowed" v.v_pos + ) + vl + ); match vl with | [v,eo] -> mk (TVar (v,eo)) ctx.t.tvoid p @@ -2761,7 +1499,7 @@ and format_string ctx s p = let min = ref (p.pmin + 1) in let add_expr (enext,p) len = min := !min + len; - let enext = if ctx.in_display && Display.is_display_position p then + let enext = if ctx.in_display && DisplayPosition.display_position#enclosed_in p then Display.ExprPreprocessing.process_expr ctx.com (enext,p) else enext,p @@ -2779,10 +1517,6 @@ and format_string ctx s p = let len = pos - start in if len > 0 || !e = None then add (EConst (String (String.sub s start len))) len in - let warn_escape = Common.defined ctx.com Define.FormatWarning in - let warn pos len = - ctx.com.warning "This string is formatted" { p with pmin = !pmin + 1 + pos; pmax = !pmin + 1 + pos + len } - in let len = String.length s in let rec parse start pos = if pos = len then add_sub start pos else @@ -2795,7 +1529,6 @@ and format_string ctx s p = if c <> '$' || pos = len then parse start pos else match String.unsafe_get s pos with | '$' -> - if warn_escape then warn pos 1; (* double $ *) add_sub start pos; parse (pos + 1) (pos + 1) @@ -2813,7 +1546,6 @@ and format_string ctx s p = in let iend = loop (pos + 1) in let len = iend - pos in - if warn_escape then warn pos len; add (EConst (Ident (String.sub s pos len))) len; parse (pos + len) (pos + len) | _ -> @@ -2839,10 +1571,20 @@ and format_string ctx s p = let send = loop [pos] (pos + 1) in let slen = send - pos - 1 in let scode = String.sub s (pos + 1) slen in - if warn_escape then warn (pos + 1) slen; min := !min + 2; - if slen > 0 then - add_expr (ParserEntry.parse_expr_string ctx.com.defines scode { p with pmin = !pmin + pos + 2; pmax = !pmin + send + 1 } error true) slen; + if slen > 0 then begin + let e = + let ep = { p with pmin = !pmin + pos + 2; pmax = !pmin + send + 1 } in + try + begin match ParserEntry.parse_expr_string ctx.com.defines scode ep error true with + | ParseSuccess data | ParseDisplayFile(data,_) -> data + | ParseError(_,(msg,p),_) -> error (Parser.error_msg msg) p + end + with Exit -> + error "Invalid interpolated expression" ep + in + add_expr e slen + end; min := !min + 1; parse (send + 1) (send + 1) in @@ -2852,25 +1594,19 @@ and format_string ctx s p = | Some e -> e and type_block ctx el with_type p = - let merge e = match e.eexpr with + let merge acc e = match e.eexpr with | TMeta((Meta.MergeBlock,_,_), {eexpr = TBlock el}) -> - el - | _ -> [e] + List.rev el @ acc + | _ -> + e :: acc in - let rec loop = function - | [] -> [] - | [e] -> - (try - merge (type_expr ctx e with_type) - with Error (e,p) -> check_error ctx e p; []) + let rec loop acc = function + | [] -> List.rev acc | e :: l -> - try - let e = type_expr ctx e NoValue in - merge e @ loop l - with - Error (e,p) -> check_error ctx e p; loop l + let acc = try merge acc (type_expr ctx e (if l = [] then with_type else WithType.no_value)) with Error (e,p) -> check_error ctx e p; acc in + loop acc l in - let l = loop el in + let l = loop [] el in let rec loop = function | [] -> ctx.t.tvoid | [e] -> e.etype @@ -2881,12 +1617,16 @@ and type_block ctx el with_type p = and type_object_decl ctx fl with_type p = let dynamic_parameter = ref None in let a = (match with_type with - | WithType t -> - let rec loop in_abstract_from t = + | WithType.WithType(t,_) -> + let rec loop seen t = match follow t with - | TAnon a when not (PMap.is_empty a.a_fields) && not in_abstract_from -> ODKWithStructure a - | TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> - (match List.fold_left (fun acc t -> match loop true t with ODKPlain -> acc | t -> t :: acc) [] (get_abstract_froms a pl) with + | TAnon a -> ODKWithStructure a + | TAbstract (a,pl) as t + when not (Meta.has Meta.CoreType a.a_meta) + && not (List.exists (fun t' -> fast_eq_anon ~mono_equals_dynamic:true t t') seen) -> + let froms = get_abstract_froms a pl + and fold = fun acc t' -> match loop (t :: seen) t' with ODKPlain -> acc | t -> t :: acc in + (match List.fold_left fold [] froms with | [t] -> t | _ -> ODKPlain) | TDynamic t when (follow t != t_dynamic) -> @@ -2900,7 +1640,7 @@ and type_object_decl ctx fl with_type p = | _ -> ODKPlain in - loop false t + loop [] t | _ -> ODKPlain ) in @@ -2910,25 +1650,29 @@ and type_object_decl ctx fl with_type p = let fl = List.map (fun ((n,pn,qs),e) -> let is_valid = Lexer.is_valid_identifier n in if PMap.mem n !fields then error ("Duplicate field in object declaration : " ^ n) p; + let is_final = ref false in let e = try let t = match !dynamic_parameter with | Some t -> t | None -> let cf = PMap.find n field_map in - if ctx.in_display && Display.is_display_position pn then Display.DisplayEmitter.display_field ctx.com.display cf pn; + if (has_class_field_flag cf CfFinal) then is_final := true; + if ctx.in_display && DisplayPosition.display_position#enclosed_in pn then DisplayEmitter.display_field ctx Unknown CFSMember cf pn; cf.cf_type in - let e = type_expr ctx e (WithType t) in - let e = AbstractCast.cast_or_unify ctx t e p in + let e = type_expr ctx e (WithType.with_structure_field t n) in + let e = AbstractCast.cast_or_unify ctx t e e.epos in + let e = if is_null t && not (is_null e.etype) then mk (TCast(e,None)) (ctx.t.tnull e.etype) e.epos else e in (try type_eq EqStrict e.etype t; e with Unify_error _ -> mk (TCast (e,None)) t e.epos) with Not_found -> if is_valid then extra_fields := n :: !extra_fields; - type_expr ctx e Value + type_expr ctx e WithType.value in if is_valid then begin - if String.length n > 0 && n.[0] = '$' then error "Field names starting with a dollar are not allowed" p; + if starts_with n '$' then error "Field names starting with a dollar are not allowed" p; let cf = mk_field n e.etype (punion pn e.epos) pn in + if !is_final then add_class_field_flag cf CfFinal; fields := PMap.add n cf !fields; end; ((n,pn,qs),e) @@ -2945,17 +1689,16 @@ and type_object_decl ctx fl with_type p = end; t, fl in - (match a with - | ODKPlain -> + let type_plain_fields () = let rec loop (l,acc) ((f,pf,qs),e) = let is_valid = Lexer.is_valid_identifier f in if PMap.mem f acc then error ("Duplicate field in object declaration : " ^ f) p; - let e = type_expr ctx e Value in + let e = type_expr ctx e (WithType.named_structure_field f) in (match follow e.etype with TAbstract({a_path=[],"Void"},_) -> error "Fields of type Void are not allowed in structures" e.epos | _ -> ()); let cf = mk_field f e.etype (punion pf e.epos) pf in - if ctx.in_display && Display.is_display_position pf then Display.DisplayEmitter.display_field ctx.com.display cf pf; + if ctx.in_display && DisplayPosition.display_position#enclosed_in pf then DisplayEmitter.display_field ctx Unknown CFSMember cf pf; (((f,pf,qs),e) :: l, if is_valid then begin - if String.length f > 0 && f.[0] = '$' then error "Field names starting with a dollar are not allowed" p; + if starts_with f '$' then error "Field names starting with a dollar are not allowed" p; PMap.add f cf acc end else acc) in @@ -2963,6 +1706,10 @@ and type_object_decl ctx fl with_type p = let x = ref Const in ctx.opened <- x :: ctx.opened; mk (TObjectDecl (List.rev fields)) (TAnon { a_fields = types; a_status = x }) p + in + (match a with + | ODKPlain -> type_plain_fields() + | ODKWithStructure a when PMap.is_empty a.a_fields && !dynamic_parameter = None -> type_plain_fields() | ODKWithStructure a -> let t, fl = type_fields a.a_fields in if !(a.a_status) = Opened then a.a_status := Closed; @@ -3001,7 +1748,7 @@ and type_object_decl ctx fl with_type p = mk (TBlock (List.rev (e :: (List.rev evars)))) e.etype e.epos ) -and type_new ctx path el with_type p = +and type_new ctx path el with_type force_inline p = let unify_constructor_call c params f ct = match follow ct with | TFun (args,r) -> (try @@ -3013,33 +1760,40 @@ and type_new ctx path el with_type p = | _ -> error "Constructor is not a function" p in - let t = if (fst path).tparams <> [] then - follow (Typeload.load_instance ctx path false p) - else try + let t = if (fst path).tparams <> [] then begin + try + Typeload.load_instance ctx path false + with Error _ as exc when ctx.com.display.dms_display -> + (* If we fail for some reason, process the arguments in case we want to display them (#7650). *) + List.iter (fun e -> ignore(type_expr ctx e WithType.value)) el; + raise exc + end else try ctx.call_argument_stack <- el :: ctx.call_argument_stack; - let t = follow (Typeload.load_instance ctx path true p) in + let t = Typeload.load_instance ctx path true in + let t_follow = follow t in ctx.call_argument_stack <- List.tl ctx.call_argument_stack; (* Try to properly build @:generic classes here (issue #2016) *) - begin match t with - | TInst({cl_kind = KGeneric } as c,tl) -> follow (Typeload.build_generic ctx c p tl) + begin match t_follow with + | TInst({cl_kind = KGeneric } as c,tl) -> follow (Generic.build_generic ctx c p tl) | _ -> t end - with Typeload.Generic_Exception _ -> + with + | Generic.Generic_Exception _ -> (* Try to infer generic parameters from the argument list (issue #2044) *) - match resolve_typedef (Typeload.load_type_def ctx p (fst path)) with + begin match resolve_typedef (Typeload.load_type_def ctx p (fst path)) with | TClassDecl ({cl_constructor = Some cf} as c) -> let monos = List.map (fun _ -> mk_mono()) c.cl_params in let ct, f = get_constructor ctx c monos p in ignore (unify_constructor_call c monos f ct); begin try - let t = Typeload.build_generic ctx c p monos in + let t = Generic.build_generic ctx c p monos in let map = apply_params c.cl_params monos in check_constraints ctx (s_type_path c.cl_path) c.cl_params monos map true p; t - with Typeload.Generic_Exception _ as exc -> + with Generic.Generic_Exception _ as exc -> (* If we have an expected type, just use that (issue #3804) *) begin match with_type with - | WithType t -> + | WithType.WithType(t,_) -> begin match follow t with | TMono _ -> raise exc | t -> t @@ -3050,12 +1804,16 @@ and type_new ctx path el with_type p = end | mt -> error ((s_type_path (t_infos mt).mt_path) ^ " cannot be constructed") p + end + | Error _ as exc when ctx.com.display.dms_display -> + List.iter (fun e -> ignore(type_expr ctx e WithType.value)) el; + raise exc in - Display.DisplayEmitter.check_display_type ctx t (pos path); + DisplayEmitter.check_display_type ctx t (pos path); + let t = follow t in let build_constructor_call c tl = let ct, f = get_constructor ctx c tl p in - if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx (error_msg (No_constructor (TClassDecl c))) p; - if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx "Cannot access private constructor" p; + check_constructor_access ctx c f p; (match f.cf_kind with | Var { v_read = AccRequire (r,msg) } -> (match msg with Some msg -> error msg p | None -> error_require r p) | _ -> ()); @@ -3064,36 +1822,28 @@ and type_new ctx path el with_type p = in try begin match t with | TInst ({cl_kind = KTypeParameter tl} as c,params) -> - if not (Typeload.is_generic_parameter ctx c) then error "Only generic type parameters can be constructed" p; - let el = List.map (fun e -> type_expr ctx e Value) el in - let ct = (tfun (List.map (fun e -> e.etype) el) ctx.t.tvoid) in - let rec loop t = match follow t with - | TAnon a -> - (try - unify ctx (PMap.find "new" a.a_fields).cf_type ct p; - true - with Not_found -> - false) - | TAbstract({a_path = ["haxe"],"Constructible"},_) -> true - | TInst({cl_kind = KTypeParameter tl},_) -> List.exists loop tl - | _ -> false - in - if not (List.exists loop tl) then raise_error (No_constructor (TClassDecl c)) p; - mk (TNew (c,params,el)) t p + if not (TypeloadCheck.is_generic_parameter ctx c) then error "Only generic type parameters can be constructed" p; + begin match get_constructible_constraint ctx tl p with + | None -> + raise_error (No_constructor (TClassDecl c)) p + | Some(tl,tr) -> + let el,_ = unify_call_args ctx el tl tr p false false in + mk (TNew (c,params,el)) t p + end | TAbstract({a_impl = Some c} as a,tl) when not (Meta.has Meta.MultiType a.a_meta) -> let el,cf,ct = build_constructor_call c tl in let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in let e = mk (TTypeExpr (TClassDecl c)) ta p in let e = mk (TField (e,(FStatic (c,cf)))) ct p in - make_call ctx e el t p + make_call ctx e el t ~force_inline p | TInst (c,params) | TAbstract({a_impl = Some c},params) -> let el,_,_ = build_constructor_call c params in mk (TNew (c,params,el)) t p | _ -> error (s_type (print_context()) t ^ " cannot be constructed") p - end with Error(No_constructor _ as err,p) when ctx.com.display.dms_display -> + end with Error(No_constructor _ as err,p) when ctx.com.display.dms_kind <> DMNone -> display_error ctx (error_msg err) p; - Display.Diagnostics.secure_generated_code ctx (mk (TConst TNull) t p) + Diagnostics.secure_generated_code ctx (mk (TConst TNull) t p) and type_try ctx e1 catches with_type p = let e1 = type_expr ctx (Expr.ensure_block e1) with_type in @@ -3128,10 +1878,10 @@ and type_try ctx e1 catches with_type p = | x :: _ , _ -> x | [] , name -> name) in - let catches = List.fold_left (fun acc ((v,pv),t,e_ast,pc) -> - let t = Typeload.load_complex_type ctx true p t in + let catches,el = List.fold_left (fun (acc1,acc2) ((v,pv),t,e_ast,pc) -> + let t = Typeload.load_complex_type ctx true t in let rec loop t = match follow t with - | TInst ({ cl_kind = KTypeParameter _} as c,_) when not (Typeload.is_generic_parameter ctx c) -> + | TInst ({ cl_kind = KTypeParameter _} as c,_) when not (TypeloadCheck.is_generic_parameter ctx c) -> error "Cannot catch non-generic type parameter" p | TInst ({ cl_path = path },params) | TEnum ({ e_path = path },params) -> @@ -3144,23 +1894,34 @@ and type_try ctx e1 catches with_type p = | _ -> error "Catch type must be a class, an enum or Dynamic" (pos e_ast) in let name,t2 = loop t in - if v.[0] = '$' then display_error ctx "Catch variable names starting with a dollar are not allowed" p; - check_unreachable acc t2 (pos e_ast); + if starts_with v '$' then display_error ctx "Catch variable names starting with a dollar are not allowed" p; + check_unreachable acc1 t2 (pos e_ast); let locals = save_locals ctx in - let v = add_local ctx v t pv in - if ctx.is_display_file && Display.is_display_position pv then - Display.DisplayEmitter.display_variable ctx.com.display v pv; + let v = add_local_with_origin ctx TVOCatchVariable v t pv in + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in pv then + DisplayEmitter.display_variable ctx v pv; let e = type_expr ctx e_ast with_type in (* If the catch position is the display position it means we get completion on the catch keyword or some punctuation. Otherwise we wouldn't reach this point. *) - if ctx.is_display_file && Display.is_display_position pc then ignore(display_expr ctx e_ast e with_type pc); + if ctx.is_display_file && DisplayPosition.display_position#enclosed_in pc then ignore(TyperDisplay.display_expr ctx e_ast e DKMarked with_type pc); v.v_type <- t2; locals(); - if with_type <> NoValue then unify ctx e.etype e1.etype e.epos; if PMap.mem name ctx.locals then error ("Local variable " ^ name ^ " is preventing usage of this type here") e.epos; - (v , e) :: acc - ) [] catches in - mk (TTry (e1,List.rev catches)) (if with_type = NoValue then ctx.t.tvoid else e1.etype) p + ((v,e) :: acc1),(e :: acc2) + ) ([],[e1]) catches in + let e1,catches,t = match with_type with + | WithType.NoValue -> e1,catches,ctx.t.tvoid + | WithType.Value _ -> e1,catches,unify_min ctx el + | WithType.WithType(t,src) when (match follow t with TMono _ -> true | t -> ExtType.is_void t) -> + e1,catches,unify_min_for_type_source ctx el src + | WithType.WithType(t,_) -> + let e1 = AbstractCast.cast_or_unify ctx t e1 e1.epos in + let catches = List.map (fun (v,e) -> + v,AbstractCast.cast_or_unify ctx t e e.epos + ) catches in + e1,catches,t + in + mk (TTry (e1,List.rev catches)) t p and type_map_declaration ctx e1 el with_type p = let (tkey,tval,has_type) = @@ -3172,7 +1933,7 @@ and type_map_declaration ctx e1 el with_type p = | _ -> mk_mono(),mk_mono(),false in match with_type with - | WithType t -> get_map_params t + | WithType.WithType(t,_) -> get_map_params t | _ -> (mk_mono(),mk_mono(),false) in let keys = Hashtbl.create 0 in @@ -3191,23 +1952,23 @@ and type_map_declaration ctx e1 el with_type p = ) el in let el_k,el_v,tkey,tval = if has_type then begin let el_k,el_v = List.fold_left (fun (el_k,el_v) (e1,e2) -> - let e1 = type_expr ctx e1 (WithType tkey) in + let e1 = type_expr ctx e1 (WithType.with_type tkey) in check_key e1; let e1 = AbstractCast.cast_or_unify ctx tkey e1 e1.epos in - let e2 = type_expr ctx e2 (WithType tval) in + let e2 = type_expr ctx e2 (WithType.with_type tval) in let e2 = AbstractCast.cast_or_unify ctx tval e2 e2.epos in (e1 :: el_k,e2 :: el_v) ) ([],[]) el_kv in el_k,el_v,tkey,tval end else begin let el_k,el_v = List.fold_left (fun (el_k,el_v) (e1,e2) -> - let e1 = type_expr ctx e1 Value in + let e1 = type_expr ctx e1 WithType.value in check_key e1; - let e2 = type_expr ctx e2 Value in + let e2 = type_expr ctx e2 WithType.value in (e1 :: el_k,e2 :: el_v) ) ([],[]) el_kv in let unify_min_resume el = try - unify_min_raise ctx el + unify_min_raise ctx.com.basic el with Error (Unify l,p) when ctx.in_call_args -> raise (WithTypeError(Unify l,p)) in @@ -3215,7 +1976,7 @@ and type_map_declaration ctx e1 el with_type p = let tval = unify_min_resume el_v in el_k,el_v,tkey,tval end in - let m = Typeload.load_module ctx (["haxe";"ds"],"Map") null_pos in + let m = TypeloadModule.load_module ctx (["haxe";"ds"],"Map") null_pos in let a,c = match m.m_types with | (TAbstractDecl ({a_impl = Some c} as a)) :: _ -> a,c | _ -> assert false @@ -3231,17 +1992,16 @@ and type_map_declaration ctx e1 el with_type p = let el = (mk (TVar (v,Some enew)) t_dynamic p) :: (List.rev el) in mk (TBlock el) tmap p -and type_local_function ctx name f with_type p = - let params = Typeload.type_function_params ctx f (match name with None -> "localfun" | Some n -> n) p in +and type_local_function ctx name inline f with_type p = + let params = TypeloadFunction.type_function_params ctx f (match name with None -> "localfun" | Some (n,_) -> n) p in if params <> [] then begin if name = None then display_error ctx "Type parameters not supported in unnamed local functions" p; - if with_type <> NoValue then error "Type parameters are not supported for rvalue functions" p + if with_type <> WithType.NoValue then error "Type parameters are not supported for rvalue functions" p end; - List.iter (fun tp -> if tp.tp_constraints <> [] then display_error ctx "Type parameter constraints are not supported for local functions" p) f.f_params; - let inline, v = (match name with - | None -> false, None - | Some v when ExtString.String.starts_with v "inline_" -> true, Some (String.sub v 7 (String.length v - 7)) - | Some v -> false, Some v + List.iter (fun tp -> if tp.tp_constraints <> None then display_error ctx "Type parameter constraints are not supported for local functions" p) f.f_params; + let v,pname = (match name with + | None -> None,p + | Some (v,pn) -> Some v,pn ) in let old_tp,old_in_loop = ctx.type_params,ctx.in_loop in ctx.type_params <- params @ ctx.type_params; @@ -3249,11 +2009,11 @@ and type_local_function ctx name f with_type p = let rt = Typeload.load_type_hint ctx p f.f_type in let args = List.map (fun ((s,_),opt,_,t,c) -> let t = Typeload.load_type_hint ctx p t in - let t, c = Typeload.type_function_arg ctx t c opt p in + let t, c = TypeloadFunction.type_function_arg ctx t c opt p in s, c, t ) f.f_args in (match with_type with - | WithType t -> + | WithType.WithType(t,_) -> let rec loop t = (match follow t with | TFun (args2,tr) when List.length args2 = List.length args -> @@ -3273,7 +2033,7 @@ and type_local_function ctx name f with_type p = | _ -> ()) in loop t - | NoValue -> + | WithType.NoValue -> if name = None then display_error ctx "Unnamed lvalue functions are not supported" p | _ -> ()); @@ -3281,26 +2041,30 @@ and type_local_function ctx name f with_type p = let v = (match v with | None -> None | Some v -> - if v.[0] = '$' then display_error ctx "Variable names starting with a dollar are not allowed" p; - Some (add_local ctx v ft p) (* TODO: var pos *) + if starts_with v '$' then display_error ctx "Variable names starting with a dollar are not allowed" p; + let v = (add_local_with_origin ctx TVOLocalFunction v ft pname) in + if params <> [] then v.v_extra <- Some (params,None); + Some v ) in let curfun = match ctx.curfun with | FunStatic -> FunStatic - | FunMemberAbstract -> FunMemberAbstractLocal + | FunMemberAbstract + | FunMemberAbstractLocal -> FunMemberAbstractLocal | _ -> FunMemberClassLocal in - let e , fargs = Typeload.type_function ctx args rt curfun f ctx.in_display p in + let e , fargs = TypeloadFunction.type_function ctx args rt curfun f ctx.in_display p in ctx.type_params <- old_tp; ctx.in_loop <- old_in_loop; - let f = { + let tf = { tf_args = fargs; tf_type = rt; tf_expr = e; } in - let e = mk (TFunction f) ft p in - (match v with + let e = mk (TFunction tf) ft p in + match v with | None -> e | Some v -> + Typeload.generate_value_meta ctx.com None (fun m -> v.v_meta <- m :: v.v_meta) f.f_args; let open LocalUsage in if params <> [] || inline then v.v_extra <- Some (params,if inline then Some e else None); let rec loop = function @@ -3309,53 +2073,78 @@ and type_local_function ctx name f with_type p = | LocalUsage.Use _ | LocalUsage.Assign _ | LocalUsage.Declare _ -> () in let is_rec = (try local_usage loop e; false with Exit -> true) in - let decl = (if is_rec then begin - if inline then display_error ctx "Inline function cannot be recursive" e.epos; - let vnew = add_local ctx v.v_name ft v.v_pos in - mk (TVar (vnew,Some (mk (TBlock [ - mk (TVar (v,Some (mk (TConst TNull) ft p))) ctx.t.tvoid p; - mk (TBinop (OpAssign,mk (TLocal v) ft p,e)) ft p; - mk (TLocal v) ft p - ]) ft p))) ctx.t.tvoid p - end else if inline then - mk (TBlock []) ctx.t.tvoid p (* do not add variable since it will be inlined *) - else - mk (TVar (v,Some e)) ctx.t.tvoid p - ) in - if with_type <> NoValue && not inline then mk (TBlock [decl;mk (TLocal v) v.v_type p]) v.v_type p else decl) + let exprs = + if with_type <> WithType.NoValue && not inline then [mk (TLocal v) v.v_type p] + else [] + in + let exprs = + if is_rec then begin + if inline then display_error ctx "Inline function cannot be recursive" e.epos; + (mk (TVar (v,Some (mk (TConst TNull) ft p))) ctx.t.tvoid p) :: + (mk (TBinop (OpAssign,mk (TLocal v) ft p,e)) ft p) :: + exprs + end else if inline && not ctx.com.display.dms_display then + (mk (TBlock []) ctx.t.tvoid p) :: exprs (* do not add variable since it will be inlined *) + else + (mk (TVar (v,Some e)) ctx.t.tvoid p) :: exprs + in + match exprs with + | [e] -> e + | _ -> + let block = mk (TBlock exprs) v.v_type p in + mk (TMeta ((Meta.MergeBlock, [], null_pos), block)) v.v_type p and type_array_decl ctx el with_type p = + let allow_array_dynamic = ref false in let tp = (match with_type with - | WithType t -> - let rec loop t = + | WithType.WithType(t,_) -> + let rec loop seen t = (match follow t with | TInst ({ cl_path = [],"Array" },[tp]) -> (match follow tp with | TMono _ -> None - | _ -> Some tp) + | _ as t -> + if t == t_dynamic then allow_array_dynamic := true; + Some tp) | TAnon _ -> (try Some (get_iterable_param t) with Not_found -> None) - | TAbstract (a,pl) -> - (match List.fold_left (fun acc t -> match loop t with None -> acc | Some t -> t :: acc) [] (get_abstract_froms a pl) with + | TAbstract (a,pl) as t when not (List.exists (fun t' -> fast_eq_anon ~mono_equals_dynamic:true t (follow t')) seen) -> + let types = + List.fold_left + (fun acc t' -> match loop (t :: seen) t' with + | None -> acc + | Some t -> t :: acc + ) + [] + (get_abstract_froms a pl) + in + (match types with | [t] -> Some t | _ -> None) | t -> - if t == t_dynamic then Some t else None) + if t == t_dynamic then begin + allow_array_dynamic := true; + Some t + end else + None + ) in - loop t + loop [] t | _ -> None ) in (match tp with | None -> - let el = List.map (fun e -> type_expr ctx e Value) el in + let el = List.map (fun e -> type_expr ctx e WithType.value) el in let t = try - unify_min_raise ctx el + unify_min_raise ctx.com.basic el with Error (Unify l,p) -> - if ctx.untyped || ctx.com.display.dms_error_policy = EPIgnore then t_dynamic else begin + if !allow_array_dynamic || ctx.untyped || ctx.com.display.dms_error_policy = EPIgnore then + t_dynamic + else begin display_error ctx "Arrays of mixed types are only allowed if the type is forced to Array" p; raise (Error (Unify l, p)) end @@ -3363,768 +2152,226 @@ and type_array_decl ctx el with_type p = mk (TArrayDecl el) (ctx.t.tarray t) p | Some t -> let el = List.map (fun e -> - let e = type_expr ctx e (WithType t) in + let e = type_expr ctx e (WithType.with_type t) in AbstractCast.cast_or_unify ctx t e p; ) el in mk (TArrayDecl el) (ctx.t.tarray t) p) -and type_expr ctx (e,p) (with_type:with_type) = +and type_array_comprehension ctx e with_type p = + let v = gen_local ctx (mk_mono()) p in + let et = ref (EConst(Ident "null"),p) in + let comprehension_pos = p in + let rec map_compr (e,p) = + match e with + | EFor(it,e2) -> (EFor (it, map_compr e2),p) + | EWhile(cond,e2,flag) -> (EWhile (cond,map_compr e2,flag),p) + | EIf (cond,e2,None) -> (EIf (cond,map_compr e2,None),p) + | EBlock [e] -> (EBlock [map_compr e],p) + | EBlock el -> begin match List.rev el with + | e :: el -> (EBlock ((List.rev el) @ [map_compr e]),p) + | [] -> e,p + end + | EParenthesis e2 -> (EParenthesis (map_compr e2),p) + | EBinop(OpArrow,a,b) -> + et := (ENew(({tpackage=["haxe";"ds"];tname="Map";tparams=[];tsub=None},null_pos),[]),comprehension_pos); + (ECall ((EField ((EConst (Ident v.v_name),p),"set"),p),[a;b]),p) + | _ -> + et := (EArrayDecl [],comprehension_pos); + (ECall ((EField ((EConst (Ident v.v_name),p),"push"),p),[(e,p)]),p) + in + let e = map_compr e in + let ea = type_expr ctx !et with_type in + unify ctx v.v_type ea.etype p; + let efor = type_expr ctx e WithType.NoValue in + mk (TBlock [ + mk (TVar (v,Some ea)) ctx.t.tvoid p; + efor; + mk (TLocal v) v.v_type p; + ]) v.v_type p + +and type_return ?(implicit=false) ctx e with_type p = match e with - | EField ((EConst (String s),ps),"code") -> - if UTF8.length s <> 1 then error "String must be a single UTF8 char" ps; - mk (TConst (TInt (Int32.of_int (UChar.code (UTF8.get s 0))))) ctx.t.tint p - | EField(_,n) when n.[0] = '$' -> - error "Field names starting with $ are not allowed" p - | EConst (Ident s) -> - if s = "super" && with_type <> NoValue && not ctx.in_display then error "Cannot use super as value" p; - let e = maybe_type_against_enum ctx (fun () -> type_ident ctx s p MGet) with_type p in - acc_get ctx e p - | EField _ - | EArray _ -> - acc_get ctx (type_access ctx e p MGet) p - | EConst (Regexp (r,opt)) -> - let str = mk (TConst (TString r)) ctx.t.tstring p in - let opt = mk (TConst (TString opt)) ctx.t.tstring p in - let t = Typeload.load_core_type ctx "EReg" in - mk (TNew ((match t with TInst (c,[]) -> c | _ -> assert false),[],[str;opt])) t p - | EConst (String s) when s <> "" && Lexer.is_fmt_string p -> - type_expr ctx (format_string ctx s p) with_type - | EConst c -> - Codegen.type_constant ctx.com c p - | EBinop (op,e1,e2) -> - type_binop ctx op e1 e2 false with_type p - | EBlock [] when with_type <> NoValue -> - type_expr ctx (EObjectDecl [],p) with_type - | EBlock l -> - let locals = save_locals ctx in - let e = type_block ctx l with_type p in - locals(); - e - | EParenthesis e -> - let e = type_expr ctx e with_type in - mk (TParenthesis e) e.etype p - | EObjectDecl fl -> - type_object_decl ctx fl with_type p - | EArrayDecl [(EFor _,_) | (EWhile _,_) as e] -> - let v = gen_local ctx (mk_mono()) p in - let et = ref (EConst(Ident "null"),p) in - let rec map_compr (e,p) = - match e with - | EFor(it,e2) -> (EFor (it, map_compr e2),p) - | EWhile(cond,e2,flag) -> (EWhile (cond,map_compr e2,flag),p) - | EIf (cond,e2,None) -> (EIf (cond,map_compr e2,None),p) - | EBlock [e] -> (EBlock [map_compr e],p) - | EBlock el -> begin match List.rev el with - | e :: el -> (EBlock ((List.rev el) @ [map_compr e]),p) - | [] -> e,p - end - | EParenthesis e2 -> (EParenthesis (map_compr e2),p) - | EBinop(OpArrow,a,b) -> - et := (ENew(({tpackage=["haxe";"ds"];tname="Map";tparams=[];tsub=None},null_pos),[]),p); - (ECall ((EField ((EConst (Ident v.v_name),p),"set"),p),[a;b]),p) - | _ -> - et := (EArrayDecl [],p); - (ECall ((EField ((EConst (Ident v.v_name),p),"push"),p),[(e,p)]),p) - in - let e = map_compr e in - let ea = type_expr ctx !et with_type in - unify ctx v.v_type ea.etype p; - let efor = type_expr ctx e NoValue in - mk (TBlock [ - mk (TVar (v,Some ea)) ctx.t.tvoid p; - efor; - mk (TLocal v) v.v_type p; - ]) v.v_type p - | EArrayDecl ((EBinop(OpArrow,_,_),_) as e1 :: el) -> - type_map_declaration ctx e1 el with_type p - | EArrayDecl el -> - type_array_decl ctx el with_type p - | EVars vl -> - type_vars ctx vl p - | EFor (it,e2) -> - let rec loop_ident display e1 = match e1 with - | EConst(Ident i),p -> i,p,display - | EDisplay(e1,_),_ -> loop_ident true e1 - | _ -> error "Identifier expected" (pos e1) - in - let rec loop display e1 = match fst e1 with - | EBinop(OpIn,e1,e2) -> loop_ident display e1,e2 - | EDisplay(e1,_) -> loop true e1 - | _ -> error "For expression should be 'v in expr'" (snd it) + | None -> + let v = ctx.t.tvoid in + unify ctx v ctx.ret p; + let expect_void = match with_type with + | WithType.WithType(t,_) -> ExtType.is_void (follow t) + | WithType.Value (Some ImplicitReturn) -> true + | _ -> false in - let (i, pi, display), e1 = loop false it in - let e1 = type_expr ctx e1 Value in - let old_loop = ctx.in_loop in - let old_locals = save_locals ctx in - ctx.in_loop <- true; - let e2 = Expr.ensure_block e2 in - let default() = - let t, pt = Typeload.t_iterator ctx in - let i = add_local ctx i pt pi in - let e1 = (match follow e1.etype with - | TMono _ - | TDynamic _ -> - display_error ctx "You can't iterate on a Dynamic value, please specify Iterator or Iterable" e1.epos; - e1 - | TLazy _ -> - assert false + mk (TReturn None) (if expect_void then v else t_dynamic) p + | Some e -> + try + let with_expected_type = + if implicit then WithType.of_implicit_return ctx.ret + else WithType.with_type ctx.ret + in + let e = type_expr ctx e with_expected_type in + let e = AbstractCast.cast_or_unify ctx ctx.ret e p in + begin match follow e.etype with + | TAbstract({a_path=[],"Void"},_) -> + begin match (Texpr.skip e).eexpr with + | TConst TNull -> error "Cannot return `null` from Void-function" p + | _ -> () + end; + (* if we get a Void expression (e.g. from inlining) we don't want to return it (issue #4323) *) + mk (TBlock [ + e; + mk (TReturn None) t_dynamic p + ]) t_dynamic e.epos; | _ -> - (try - AbstractCast.cast_or_unify_raise ctx t e1 p - with Error (Unify _,_) -> - let acc = build_call ctx (type_field ctx e1 "iterator" e1.epos MCall) [] Value e1.epos in - try - unify_raise ctx acc.etype t acc.epos; - acc - with Error (Unify(l),p) -> - display_error ctx "Field iterator has an invalid type" acc.epos; - display_error ctx (error_msg (Unify l)) p; - mk (TConst TNull) t_dynamic p - ) - ) in - if display then ignore(handle_display ctx (EConst(Ident i.v_name),i.v_pos) (WithType i.v_type)); - let e2 = type_expr ctx e2 NoValue in - (try Optimizer.optimize_for_loop_iterator ctx i e1 e2 p with Exit -> mk (TFor (i,e1,e2)) ctx.t.tvoid p) - in - let e = match Optimizer.optimize_for_loop ctx (i,pi) e1 e2 p with - | Some e -> - if display then ignore(handle_display ctx (EConst(Ident i),pi) Value); - e - | None -> default() + mk (TReturn (Some e)) t_dynamic p + end + with Error(err,p) -> + check_error ctx err p; + (* If we have a bad return, let's generate a return null expression at least. This surpresses various + follow-up errors that come from the fact that the function no longer has a return expression (issue #6445). *) + let e_null = mk (TConst TNull) (mk_mono()) p in + mk (TReturn (Some e_null)) t_dynamic p + +and type_cast ctx e t p = + let t = Typeload.load_complex_type ctx true t in + let check_param pt = match follow pt with + | TMono _ -> () (* This probably means that Dynamic wasn't bound (issue #4675). *) + | t when t == t_dynamic -> () + | _ ->error "Cast type parameters must be Dynamic" p + in + let rec loop t = match follow t with + | TInst (_,params) | TEnum (_,params) -> + List.iter check_param params; + (match follow t with + | TInst (c,_) -> + (match c.cl_kind with KTypeParameter _ -> error "Can't cast to a type parameter" p | _ -> ()); + TClassDecl c + | TEnum (e,_) -> TEnumDecl e + | _ -> assert false); + | TAbstract (a,params) when Meta.has Meta.RuntimeValue a.a_meta -> + List.iter check_param params; + TAbstractDecl a + | TAbstract (a,params) -> + loop (Abstract.get_underlying_type a params) + | _ -> + error "Cast type must be a class or an enum" p + in + let texpr = loop t in + mk (TCast (type_expr ctx e WithType.value,Some texpr)) t p + +and type_if ctx e e1 e2 with_type p = + let e = type_expr ctx e WithType.value in + let e = AbstractCast.cast_or_unify ctx ctx.t.tbool e p in + let e1 = type_expr ctx (Expr.ensure_block e1) with_type in + (match e2 with + | None -> + mk (TIf (e,e1,None)) ctx.t.tvoid p + | Some e2 -> + let e2 = type_expr ctx (Expr.ensure_block e2) with_type in + let e1,e2,t = match with_type with + | WithType.NoValue -> e1,e2,ctx.t.tvoid + | WithType.Value _ -> e1,e2,unify_min ctx [e1; e2] + | WithType.WithType(t,src) when (match follow t with TMono _ -> true | t -> ExtType.is_void t) -> + e1,e2,unify_min_for_type_source ctx [e1; e2] src + | WithType.WithType(t,_) -> + let e1 = AbstractCast.cast_or_unify ctx t e1 e1.epos in + let e2 = AbstractCast.cast_or_unify ctx t e2 e2.epos in + e1,e2,t in - ctx.in_loop <- old_loop; - old_locals(); - e - | ETernary (e1,e2,e3) -> - type_expr ctx (EIf (e1,e2,Some e3),p) with_type - | EIf (e,e1,e2) -> - let e = type_expr ctx e Value in - let e = AbstractCast.cast_or_unify ctx ctx.t.tbool e p in - let e1 = type_expr ctx (Expr.ensure_block e1) with_type in - (match e2 with - | None -> - mk (TIf (e,e1,None)) ctx.t.tvoid p - | Some e2 -> - let e2 = type_expr ctx (Expr.ensure_block e2) with_type in - let e1,e2,t = match with_type with - | NoValue -> e1,e2,ctx.t.tvoid - | Value -> e1,e2,unify_min ctx [e1; e2] - | WithType t when (match follow t with TMono _ -> true | _ -> false) -> e1,e2,unify_min ctx [e1; e2] - | WithType t -> - let e1 = AbstractCast.cast_or_unify ctx t e1 e1.epos in - let e2 = AbstractCast.cast_or_unify ctx t e2 e2.epos in - e1,e2,t + mk (TIf (e,e1,Some e2)) t p) + +and type_meta ?(mode=MGet) ctx m e1 with_type p = + if ctx.is_display_file then DisplayEmitter.check_display_metadata ctx [m]; + let old = ctx.meta in + ctx.meta <- m :: ctx.meta; + let e () = type_expr ~mode ctx e1 with_type in + let e = match m with + | (Meta.ToString,_,_) -> + let e = e() in + (match follow e.etype with + | TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx e + | _ -> e) + | (Meta.Markup,_,_) -> + error "Markup literals must be processed by a macro" p + | (Meta.This,_,_) -> + let e = match ctx.this_stack with + | [] -> error "Cannot type @:this this here" p + | e :: _ -> e in - mk (TIf (e,e1,Some e2)) t p) - | EWhile (cond,e,NormalWhile) -> - let old_loop = ctx.in_loop in - let cond = type_expr ctx cond Value in - let cond = AbstractCast.cast_or_unify ctx ctx.t.tbool cond p in - ctx.in_loop <- true; - let e = type_expr ctx (Expr.ensure_block e) NoValue in - ctx.in_loop <- old_loop; - mk (TWhile (cond,e,NormalWhile)) ctx.t.tvoid p - | EWhile (cond,e,DoWhile) -> - let old_loop = ctx.in_loop in - ctx.in_loop <- true; - let e = type_expr ctx (Expr.ensure_block e) NoValue in - ctx.in_loop <- old_loop; - let cond = type_expr ctx cond Value in - let cond = AbstractCast.cast_or_unify ctx ctx.t.tbool cond cond.epos in - mk (TWhile (cond,e,DoWhile)) ctx.t.tvoid p - | ESwitch (e1,cases,def) -> - let wrap e1 = mk (TMeta((Meta.Ast,[e,p],p),e1)) e1.etype e1.epos in - let e = match_expr ctx e1 cases def with_type p in - wrap e - | EReturn e -> - begin match e with - | None -> - let v = ctx.t.tvoid in - unify ctx v ctx.ret p; - mk (TReturn None) t_dynamic p - | Some e -> - try - let e = type_expr ctx e (WithType ctx.ret) in - let e = AbstractCast.cast_or_unify ctx ctx.ret e p in - begin match follow e.etype with - | TAbstract({a_path=[],"Void"},_) -> - (* if we get a Void expression (e.g. from inlining) we don't want to return it (issue #4323) *) - mk (TBlock [ - e; - mk (TReturn None) t_dynamic p - ]) t_dynamic e.epos; - | _ -> - mk (TReturn (Some e)) t_dynamic p - end - with Error(err,p) -> - check_error ctx err p; - (* If we have a bad return, let's generate a return null expression at least. This surpresses various - follow-up errors that come from the fact that the function no longer has a return expression (issue #6445). *) - let e_null = mk (TConst TNull) (mk_mono()) p in - mk (TReturn (Some e_null)) t_dynamic p - end - | EBreak -> - if not ctx.in_loop then display_error ctx "Break outside loop" p; - mk TBreak t_dynamic p - | EContinue -> - if not ctx.in_loop then display_error ctx "Continue outside loop" p; - mk TContinue t_dynamic p - | ETry (e1,[]) -> - type_expr ctx e1 with_type - | ETry (e1,catches) -> - type_try ctx e1 catches with_type p - | EThrow e -> - let e = type_expr ctx e Value in - mk (TThrow e) (mk_mono()) p - | ECall (e,el) -> - type_call ctx e el with_type p - | ENew (t,el) -> - type_new ctx t el with_type p - | EUnop (op,flag,e) -> - type_unop ctx op flag e p - | EFunction (name,f) -> - type_local_function ctx name f with_type p - | EUntyped e -> - let old = ctx.untyped in - ctx.untyped <- true; - if not (Meta.has Meta.HasUntyped ctx.curfield.cf_meta) then ctx.curfield.cf_meta <- (Meta.HasUntyped,[],p) :: ctx.curfield.cf_meta; - let e = type_expr ctx e with_type in - ctx.untyped <- old; - { - eexpr = e.eexpr; - etype = mk_mono(); - epos = e.epos; - } - | ECast (e,None) -> - let e = type_expr ctx e Value in - mk (TCast (e,None)) (mk_mono()) p - | ECast (e, Some t) -> - let t = Typeload.load_complex_type ctx true p t in - let check_param pt = match follow pt with - | TMono _ -> () (* This probably means that Dynamic wasn't bound (issue #4675). *) - | t when t == t_dynamic -> () - | _ ->error "Cast type parameters must be Dynamic" p - in - let rec loop t = match follow t with - | TInst (_,params) | TEnum (_,params) -> - List.iter check_param params; - (match follow t with - | TInst (c,_) -> - (match c.cl_kind with KTypeParameter _ -> error "Can't cast to a type parameter" p | _ -> ()); - TClassDecl c - | TEnum (e,_) -> TEnumDecl e - | _ -> assert false); - | TAbstract (a,params) when Meta.has Meta.RuntimeValue a.a_meta -> - List.iter check_param params; - TAbstractDecl a - | TAbstract (a,params) -> - loop (Abstract.get_underlying_type a params) - | _ -> - error "Cast type must be a class or an enum" p - in - let texpr = loop t in - mk (TCast (type_expr ctx e Value,Some texpr)) t p - | EDisplay (e,iscall) -> - begin match ctx.com.display.dms_kind with - | DMField | DMSignature when iscall -> handle_signature_display ctx e with_type - | _ -> handle_display ctx e with_type - end - | EDisplayNew t -> - assert false - (*let t = Typeload.load_instance ctx t true p in - (match follow t with - | TInst (c,params) | TAbstract({a_impl = Some c},params) -> - let ct, f = get_constructor ctx c params p in - raise (Display.DisplaySignatures ((ct,f.cf_doc) :: List.map (fun f -> (f.cf_type,f.cf_doc)) f.cf_overloads)) - | _ -> - error "Not a class" p)*) - | ECheckType (e,t) -> - let t = Typeload.load_complex_type ctx true p t in - let e = type_expr ctx e (WithType t) in - let e = AbstractCast.cast_or_unify ctx t e p in - if e.etype == t then e else mk (TCast (e,None)) t p - | EMeta (m,e1) -> - if ctx.is_display_file then Display.DisplayEmitter.check_display_metadata ctx [m]; - let old = ctx.meta in - ctx.meta <- m :: ctx.meta; - let e () = type_expr ctx e1 with_type in - let e = match m with - | (Meta.ToString,_,_) -> - let e = e() in - (match follow e.etype with - | TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx e - | _ -> e) - | (Meta.This,_,_) -> - let e = match ctx.this_stack with - | [] -> error "Cannot type @:this this here" p - | e :: _ -> e - in - let rec loop e = match e.eexpr with - | TConst TThis -> get_this ctx e.epos - | _ -> Type.map_expr loop e - in - loop e - | (Meta.Analyzer,_,_) -> - let e = e() in - {e with eexpr = TMeta(m,e)} - | (Meta.MergeBlock,_,_) -> - begin match fst e1 with - | EBlock el -> - let e = type_block ctx el with_type p in - {e with eexpr = TMeta(m,e)} - | _ -> e() - end - | (Meta.StoredTypedExpr,_,_) -> - let id = match e1 with (EConst (Int s),_) -> int_of_string s | _ -> assert false in - MacroContext.get_stored_typed_expr ctx.com id - | (Meta.NoPrivateAccess,_,_) -> - ctx.meta <- List.filter (fun(m,_,_) -> m <> Meta.PrivateAccess) ctx.meta; - e() - | (Meta.Fixed,_,_) when ctx.com.platform=Cpp -> - let e = e() in + let rec loop e = match e.eexpr with + | TConst TThis -> get_this ctx e.epos + | _ -> Type.map_expr loop e + in + loop e + | (Meta.Analyzer,_,_) -> + let e = e() in + {e with eexpr = TMeta(m,e)} + | (Meta.MergeBlock,_,_) -> + begin match fst e1 with + | EBlock el -> + let e = type_block ctx el with_type p in {e with eexpr = TMeta(m,e)} | _ -> e() - in - ctx.meta <- old; - e - -and get_submodule_fields ctx path = - let m = Hashtbl.find ctx.g.modules path in - let tl = List.filter (fun t -> path <> (t_infos t).mt_path && not (t_infos t).mt_private) m.m_types in - let tl = List.map (fun mt -> - let infos = t_infos mt in - (snd infos.mt_path),Display.FKType (type_of_module_type mt),infos.mt_doc - ) tl in - tl - -and handle_display ctx e_ast with_type = - let old = ctx.in_display,ctx.in_call_args in - ctx.in_display <- true; - ctx.in_call_args <- false; - let e = match e_ast,with_type with - | (EConst (Ident "$type"),_),_ -> - let mono = mk_mono() in - raise (Display.DisplaySignatures ([((["expression",false,mono],mono),Some "Outputs type of argument as a warning and uses argument as value")],0)) - | (EConst (Ident "trace"),_),_ -> - raise (Display.DisplaySignatures ([((["value",false,t_dynamic],ctx.com.basic.tvoid),Some "Print given arguments")],0)) - | (EConst (Ident "_"),p),WithType t -> - mk (TConst TNull) t p (* This is "probably" a bind skip, let's just use the expected type *) - | _ -> try - type_expr ctx e_ast with_type - with Error (Unknown_ident n,_) -> - raise (Parser.TypePath ([n],None,false)) - | Error (Type_not_found (path,_),_) as err -> - begin try - raise (Display.DisplayFields (get_submodule_fields ctx path)) - with Not_found -> - raise err - end - in - let p = e.epos in - let e = match with_type with - | WithType t -> (try AbstractCast.cast_or_unify_raise ctx t e e.epos with Error (Unify l,p) -> e) - | _ -> e - in - ctx.in_display <- fst old; - ctx.in_call_args <- snd old; - display_expr ctx e_ast e with_type p - -and handle_signature_display ctx e_ast with_type = - ctx.in_display <- true; - let p = pos e_ast in - let find_constructor_types t = match follow t with - | TInst (c,tl) | TAbstract({a_impl = Some c},tl) -> - let ct,cf = get_constructor ctx c tl p in - let tl = (ct,cf.cf_doc) :: List.rev_map (fun cf' -> cf'.cf_type,cf.cf_doc) cf.cf_overloads in - tl - | _ -> - [] - in - let tl,el,p0 = match fst e_ast with - | ECall(e1,el) -> - let e1 = try - type_expr ctx e1 Value - with Error (Unknown_ident "trace",_) -> - let e = expr_of_type_path (["haxe";"Log"],"trace") p in - type_expr ctx e Value - in - let tl = match e1.eexpr with - | TField(_,fa) -> - begin match extract_field fa with - | Some cf -> (e1.etype,cf.cf_doc) :: List.rev_map (fun cf' -> cf'.cf_type,cf.cf_doc) cf.cf_overloads - | None -> [e1.etype,None] - end - | TConst TSuper -> - find_constructor_types e1.etype - | _ -> [e1.etype,None] - in - tl,el,e1.epos - | ENew(tpath,el) -> - let t = Typeload.load_instance ctx tpath true p in - find_constructor_types t,el,pos tpath - | _ -> error "Call expected" p - in - let rec follow_with_callable (t,doc) = match follow t with - | TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta -> follow_with_callable (Abstract.get_underlying_type a tl,doc) - | TFun(args,ret) -> ((args,ret),doc) - | _ -> error ("Not a callable type: " ^ (s_type (print_context()) t)) p - in - let tl = List.map follow_with_callable tl in - let rec loop i p1 el = match el with - | (e,p2) :: el -> - if Display.is_display_position (punion p1 p2) then i else loop (i + 1) p2 el - | [] -> - i - in - let display_arg = loop 0 p0 el in - (* If our display position exceeds the argument number we add a null expression in order to make - unify_call_args error out. *) - let el = if display_arg >= List.length el then el @ [EConst (Ident "null"),null_pos] else el in - let rec loop acc tl = match tl with - | (t,doc) :: tl -> - let keep (args,r) = - begin try - let _ = unify_call_args' ctx el args r p false false in - true - with - | Error(Call_error (Not_enough_arguments _),_) -> true - | _ -> false - end - in - loop (if keep t then (t,doc) :: acc else acc) tl - | [] -> - acc - in - let overloads = match loop [] tl with [] -> tl | tl -> tl in - raise (Display.DisplaySignatures(overloads,display_arg)) - -and display_expr ctx e_ast e with_type p = - let get_super_constructor () = match ctx.curclass.cl_super with - | None -> error "Current class does not have a super" p - | Some (c,params) -> - let _, f = get_constructor ctx c params p in - f - in - match ctx.com.display.dms_kind with - | DMResolve _ | DMPackage | DMSignature -> - assert false - | DMType -> - let rec loop e = match e.eexpr with - | TVar(v,_) -> v.v_type,None - | TCall({eexpr = TConst TSuper; etype = t},_) -> t,None - | TNew({cl_kind = KAbstractImpl a},tl,_) -> TType(abstract_module_type a tl,[]),None - | TNew(c,tl,_) -> - let t,_ = get_constructor ctx c tl p in - t,None - | TTypeExpr (TClassDecl {cl_kind = KAbstractImpl a}) -> TType(abstract_module_type a (List.map snd a.a_params),[]),None - | TField(e1,FDynamic "bind") when (match follow e1.etype with TFun _ -> true | _ -> false) -> e1.etype,None - | TReturn (Some e1) -> loop e1 (* No point in letting the internal Dynamic surface (issue #5655) *) - | TField(_,(FStatic(c,cf) | FInstance(c,_,cf) | FClosure(Some(c,_),cf))) -> - if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c; - e.etype,cf.cf_doc - | TField(_,FEnum(_,ef)) -> - e.etype,ef.ef_doc - | _ -> e.etype,None - in - let t,doc = loop e in - raise (Display.DisplayType (t,p,doc)) - | DMUsage _ -> - let rec loop e = match e.eexpr with - | TField(_,FEnum(_,ef)) -> - ef.ef_meta <- (Meta.Usage,[],p) :: ef.ef_meta; - | TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) -> - cf.cf_meta <- (Meta.Usage,[],p) :: cf.cf_meta; - | TLocal v | TVar(v,_) -> - v.v_meta <- (Meta.Usage,[],p) :: v.v_meta; - | TTypeExpr mt -> - let ti = t_infos mt in - ti.mt_meta <- (Meta.Usage,[],p) :: ti.mt_meta; - | TNew(c,tl,_) -> - begin try - let _,cf = get_constructor ctx c tl p in - cf.cf_meta <- (Meta.Usage,[],p) :: cf.cf_meta; - with Not_found -> - () - end - | TCall({eexpr = TConst TSuper},_) -> - begin try - let cf = get_super_constructor() in - cf.cf_meta <- (Meta.Usage,[],p) :: cf.cf_meta; - with Not_found -> - () end - | TConst TSuper -> - begin match ctx.curclass.cl_super with - | None -> () - | Some (c,_) -> c.cl_meta <- (Meta.Usage,[],p) :: c.cl_meta; - end - | TCall(e1,_) -> - loop e1 - | _ -> - () - in - loop e; - e - | DMPosition -> - let rec loop e = match e.eexpr with - | TField(_,FEnum(_,ef)) -> [ef.ef_pos] - | TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) -> [cf.cf_pos] - | TLocal v | TVar(v,_) -> [v.v_pos] - | TTypeExpr mt -> [(t_infos mt).mt_pos] - | TNew(c,tl,_) -> - begin try - let _,cf = get_constructor ctx c tl p in - [cf.cf_pos] - with Not_found -> - [] - end - | TCall({eexpr = TConst TSuper},_) -> - begin try - let cf = get_super_constructor() in - [cf.cf_pos] - with Not_found -> - [] + | (Meta.StoredTypedExpr,_,_) -> + MacroContext.type_stored_expr ctx e1 + | (Meta.NoPrivateAccess,_,_) -> + ctx.meta <- List.filter (fun(m,_,_) -> m <> Meta.PrivateAccess) ctx.meta; + e() + | (Meta.Fixed,_,_) when ctx.com.platform=Cpp -> + let e = e() in + {e with eexpr = TMeta(m,e)} + | (Meta.NullSafety, [(EConst (Ident "Off"), _)],_) -> + let e = e() in + {e with eexpr = TMeta(m,e)} + | (Meta.BypassAccessor,_,p) -> + let old_counter = ctx.bypass_accessor in + ctx.bypass_accessor <- old_counter + 1; + let e = e () in + (if ctx.bypass_accessor > old_counter then display_error ctx "Field access expression expected after @:bypassAccessor metadata" p); + e + | (Meta.Inline,_,_) -> + begin match fst e1 with + | ECall(e1,el) -> + type_call ctx e1 el WithType.value true p + | ENew (t,el) -> + let e = type_new ctx t el with_type true p in + {e with eexpr = TMeta((Meta.Inline,[],null_pos),e)} + | EFunction(Some(_) as name,e1) -> + type_local_function ctx name true e1 with_type p + | _ -> + display_error ctx "Call or function expected after inline keyword" p; + e(); end - | TConst TSuper -> - begin match ctx.curclass.cl_super with - | None -> [] - | Some (c,_) -> [c.cl_pos] + | (Meta.ImplicitReturn,_,_) -> + begin match e1 with + | (EReturn e, p) -> type_return ~implicit:true ctx e with_type p + | _ -> e() end - | TCall(e1,_) -> - loop e1 - | _ -> - [] - in - let pl = loop e in - raise (Display.DisplayPosition pl); - | DMToplevel -> - raise (Display.DisplayToplevel (Display.ToplevelCollector.run ctx false)) - | DMField | DMNone | DMModuleSymbols _ | DMDiagnostics _ | DMStatistics -> - let opt_args args ret = TFun(List.map(fun (n,o,t) -> n,true,t) args,ret) in - let e = match e.eexpr with - | TField (e1,fa) -> - if field_name fa = "bind" then (match follow e1.etype with - | TFun(args,ret) -> {e1 with etype = opt_args args ret} - | _ -> e) - else - e - | _ -> - e - in - let opt_type t = - match t with - | TLazy f -> - Typeload.return_partial_type := true; - let t = lazy_type f in - Typeload.return_partial_type := false; - t - | _ -> - t - in - let should_access c cf stat = - if c != ctx.curclass && not cf.cf_public && String.length cf.cf_name > 4 then begin match String.sub cf.cf_name 0 4 with - | "get_" | "set_" -> false - | _ -> can_access ctx c cf stat - end else - can_access ctx c cf stat - in - let rec get_fields t = - match follow t with - | TInst (c,params) -> - if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c; - let merge ?(cond=(fun _ -> true)) a b = - PMap.foldi (fun k f m -> if cond f then PMap.add k f m else m) a b - in - let rec loop c params = - let m = List.fold_left (fun m (i,params) -> - merge m (loop i params) - ) PMap.empty c.cl_implements in - let m = (match c.cl_super with - | None -> m - | Some (csup,cparams) -> merge m (loop csup cparams) - ) in - let m = merge ~cond:(fun f -> should_access c f false) c.cl_fields m in - let m = (match c.cl_kind with - | KTypeParameter pl -> List.fold_left (fun acc t -> merge acc (get_fields t)) m pl - | _ -> m - ) in - PMap.map (fun f -> { f with cf_type = apply_params c.cl_params params (opt_type f.cf_type); cf_public = true; }) m - in - loop c params - | TAbstract({a_impl = Some c} as a,pl) -> - if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c; - let fields = try - let _,el,_ = Meta.get Meta.Forward a.a_meta in - let sl = ExtList.List.filter_map (fun e -> match fst e with - | EConst(Ident s) -> Some s - | _ -> None - ) el in - let fields = get_fields (apply_params a.a_params pl a.a_this) in - if sl = [] then fields else PMap.fold (fun cf acc -> - if List.mem cf.cf_name sl then - PMap.add cf.cf_name cf acc - else - acc - ) fields PMap.empty - with Not_found -> - PMap.empty - in - PMap.fold (fun f acc -> - if f.cf_name <> "_new" && should_access c f true && Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Enum f.cf_meta) then begin - let f = prepare_using_field f in - let t = apply_params a.a_params pl (follow f.cf_type) in - PMap.add f.cf_name { f with cf_public = true; cf_type = opt_type t } acc - end else - acc - ) c.cl_statics fields - | TAnon a when PMap.is_empty a.a_fields -> - begin match with_type with - | WithType t -> get_fields t - | _ -> a.a_fields - end - | TAnon a -> - (match !(a.a_status) with - | Statics c -> - if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c; - let is_abstract_impl = match c.cl_kind with KAbstractImpl _ -> true | _ -> false in - let pm = match c.cl_constructor with None -> PMap.empty | Some cf -> PMap.add "new" cf PMap.empty in - PMap.fold (fun f acc -> - if should_access c f true && (not is_abstract_impl || not (Meta.has Meta.Impl f.cf_meta) || Meta.has Meta.Enum f.cf_meta) then - PMap.add f.cf_name { f with cf_public = true; cf_type = opt_type f.cf_type } acc else acc - ) a.a_fields pm - | _ -> - a.a_fields) - | TFun (args,ret) -> - let t = opt_args args ret in - let cf = mk_field "bind" (tfun [t] t) p null_pos in - cf.cf_kind <- Method MethNormal; - PMap.add "bind" cf PMap.empty - | _ -> - PMap.empty - in - let fields = get_fields e.etype in - (* - add 'using' methods compatible with this type - *) - let rec loop acc = function - | [] -> acc - | (c,_) :: l -> - let acc = ref (loop acc l) in - let rec dup t = Type.map dup t in - List.iter (fun f -> - if not (Meta.has Meta.NoUsing f.cf_meta) && not (Meta.has Meta.Impl f.cf_meta) then - let f = { f with cf_type = opt_type f.cf_type } in - let monos = List.map (fun _ -> mk_mono()) f.cf_params in - let map = apply_params f.cf_params monos in - match follow (map f.cf_type) with - | TFun((_,_,TType({t_path=["haxe";"macro"], "ExprOf"}, [t])) :: args, ret) - | TFun((_,_,t) :: args, ret) -> - (try - unify_raise ctx (dup e.etype) t e.epos; - List.iter2 (fun m (name,t) -> match follow t with - | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> - List.iter (fun tc -> unify_raise ctx m (map tc) e.epos) constr - | _ -> () - ) monos f.cf_params; - if not (can_access ctx c f true) || follow e.etype == t_dynamic && follow t != t_dynamic then - () - else begin - let f = prepare_using_field f in - let f = { f with cf_params = []; cf_public = true; cf_type = TFun(args,ret) } in - acc := PMap.add f.cf_name f (!acc) - end - with Error (Unify _,_) -> ()) - | _ -> () - ) c.cl_ordered_statics; - !acc - in - let use_methods = match follow e.etype with TMono _ -> PMap.empty | _ -> loop (loop PMap.empty ctx.g.global_using) ctx.m.module_using in - let fields = PMap.fold (fun f acc -> PMap.add f.cf_name f acc) fields use_methods in - let fields = match fst e_ast with - | EConst(String s) when String.length s = 1 -> - let cf = mk_field "code" ctx.t.tint e.epos null_pos in - cf.cf_doc <- Some "The character code of this character (inlined at compile-time)."; - cf.cf_kind <- Var { v_read = AccNormal; v_write = AccNever }; - PMap.add cf.cf_name cf fields - | _ -> - fields - in - let fields = PMap.fold (fun f acc -> if Meta.has Meta.NoCompletion f.cf_meta then acc else f :: acc) fields [] in - let get_field acc f = - List.fold_left (fun acc f -> - let kind = match f.cf_kind with Method _ -> Display.FKMethod f.cf_type | Var _ -> Display.FKVar f.cf_type in - if f.cf_public then (f.cf_name,kind,f.cf_doc) :: acc else acc - ) acc (f :: f.cf_overloads) - in - let fields = List.fold_left get_field [] fields in - let fields = try - let sl = string_list_of_expr_path_raise e_ast in - fields @ get_submodule_fields ctx (List.tl sl,List.hd sl) - with Exit | Not_found -> - fields - in - raise (Display.DisplayFields fields) + | _ -> e() + in + ctx.meta <- old; + e -and maybe_type_against_enum ctx f with_type p = - try - begin match with_type with - | WithType t -> - let rec loop stack t = match follow t with - | TEnum (en,_) -> - en.e_path,en.e_names,TEnumDecl en,t - | TAbstract ({a_impl = Some c} as a,_) when has_meta Meta.Enum a.a_meta -> - let fields = ExtList.List.filter_map (fun cf -> - if Meta.has Meta.Enum cf.cf_meta then Some cf.cf_name else None - ) c.cl_ordered_statics in - a.a_path,fields,TAbstractDecl a,t - | TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> - begin match get_abstract_froms a pl with - | [t2] -> - if (List.exists (fast_eq t) stack) then raise Exit; - loop (t :: stack) t2 - | _ -> raise Exit - end - | _ -> - raise Exit - in - let path,fields,mt,t = loop [] t in - let old = ctx.m.curmod.m_types in - let restore () = ctx.m.curmod.m_types <- old in - ctx.m.curmod.m_types <- ctx.m.curmod.m_types @ [mt]; - let e = try - f() - with - | Error (Unknown_ident n,_) -> - restore(); - raise_or_display_message ctx (StringError.string_error n fields ("Identifier '" ^ n ^ "' is not part of " ^ s_type_path path)) p; - AKExpr (mk (TConst TNull) (mk_mono()) p) - | exc -> - restore(); - raise exc; - in - restore(); - begin match e with - | AKExpr e -> - begin match follow e.etype with - | TFun(_,t') -> - unify ctx t' t e.epos; - AKExpr e - | _ -> - AKExpr (AbstractCast.cast_or_unify ctx t e e.epos) - end - | _ -> e (* ??? *) - end +and type_call_target ctx e with_type inline p = + let e = maybe_type_against_enum ctx (fun () -> type_access ctx (fst e) (snd e) MCall) with_type true p in + if not inline then + e + else match e with + | AKExpr {eexpr = TField(e1,fa); etype = t} -> + begin match extract_field fa with + | Some cf -> AKInline(e1,cf,fa,t) + | None -> e + end; + | AKUsing(e,c,cf,ef,_) -> + AKUsing(e,c,cf,ef,true) + | AKExpr {eexpr = TLocal _} -> + display_error ctx "Cannot force inline on local functions" p; + e | _ -> - raise Exit - end - with Exit -> - f() + e -and type_call ctx e el (with_type:with_type) p = +and type_call ?(mode=MGet) ctx e el (with_type:WithType.t) inline p = let def () = - let e = maybe_type_against_enum ctx (fun () -> type_access ctx (fst e) (snd e) MCall) with_type p in - let e = build_call ctx e el with_type p in - e + let e = type_call_target ctx e with_type inline p in + build_call ~mode ctx e el with_type p in match e, el with | (EConst (Ident "trace"),p) , e :: el -> @@ -4135,8 +2382,8 @@ and type_call ctx e el (with_type:with_type) p = let params = (match el with [] -> [] | _ -> [("customParams",null_pos,NoQuotes),(EArrayDecl (List.map mk_to_string_meta el) , p)]) in let infos = mk_infos ctx p params in if (platform ctx.com Js || platform ctx.com Python) && el = [] && has_dce ctx.com then - let e = type_expr ctx e Value in - let infos = type_expr ctx infos Value in + let e = type_expr ctx e WithType.value in + let infos = type_expr ctx infos WithType.value in let e = match follow e.etype with | TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx e @@ -4146,39 +2393,40 @@ and type_call ctx e el (with_type:with_type) p = let e_trace = mk (TIdent "`trace") t_dynamic p in mk (TCall (e_trace,[e;infos])) ctx.t.tvoid p else - type_expr ctx (ECall ((EField ((EField ((EConst (Ident "haxe"),p),"Log"),p),"trace"),p),[mk_to_string_meta e;infos]),p) NoValue + type_expr ctx (ECall ((EField ((EField ((EConst (Ident "haxe"),p),"Log"),p),"trace"),p),[mk_to_string_meta e;infos]),p) WithType.NoValue | (EField ((EConst (Ident "super"),_),_),_), _ -> - def() + (match def() with + | { eexpr = TCall ({ eexpr = TField (_, FInstance(_, _, { cf_kind = Method MethDynamic; cf_name = name })); epos = p }, _) } as e -> + ctx.com.error ("Cannot call super." ^ name ^ " since it's a dynamic method") p; + e + | e -> e + ) | (EField (e,"bind"),p), args -> - let e = type_expr ctx e Value in + let e = type_expr ctx e WithType.value in (match follow e.etype with | TFun signature -> type_bind ctx e signature args p | _ -> def ()) | (EConst (Ident "$type"),_) , [e] -> - let e = type_expr ctx e Value in + let e = type_expr ctx e WithType.value in ctx.com.warning (s_type (print_context()) e.etype) e.epos; - let e = Display.Diagnostics.secure_generated_code ctx e in + let e = Diagnostics.secure_generated_code ctx e in e | (EField(e,"match"),p), [epat] -> - let et = type_expr ctx e Value in + let et = type_expr ctx e WithType.value in (match follow et.etype with | TEnum _ -> - let e = match_expr ctx e [[epat],None,Some (EConst(Ident "true"),p),p] (Some (Some (EConst(Ident "false"),p),p)) (WithType ctx.t.tbool) p in - (* TODO: add that back *) -(* let locals = !get_pattern_locals_ref ctx epat t in - PMap.iter (fun _ (_,p) -> display_error ctx "Capture variables are not allowed" p) locals; *) - e + Matcher.Match.match_expr ctx e [[epat],None,Some (EConst(Ident "true"),p),p] (Some (Some (EConst(Ident "false"),p),p)) (WithType.with_type ctx.t.tbool) true p | _ -> def ()) | (EConst (Ident "__unprotect__"),_) , [(EConst (String _),_) as e] -> - let e = type_expr ctx e Value in + let e = type_expr ctx e WithType.value in if Common.platform ctx.com Flash then let t = tfun [e.etype] e.etype in let e_unprotect = mk (TIdent "__unprotect__") t p in mk (TCall (e_unprotect,[e])) e.etype e.epos else e - | (EDisplay((EConst (Ident "super"),_ as e1),false),_),_ -> - handle_display ctx (ECall(e1,el),p) with_type + | (EDisplay((EConst (Ident "super"),_ as e1),dk),_),_ -> + TyperDisplay.handle_display ctx (ECall(e1,el),p) dk with_type | (EConst (Ident "super"),sp) , el -> if ctx.curfun <> FunConstructor then error "Cannot call super constructor outside class constructor" p; let el, t = (match ctx.curclass.cl_super with @@ -4199,300 +2447,146 @@ and type_call ctx e el (with_type:with_type) p = | _ -> def () -and build_call ctx acc el (with_type:with_type) p = - match acc with - | AKInline (ethis,f,fmode,t) when Meta.has Meta.Generic f.cf_meta -> - type_generic_function ctx (ethis,fmode) el with_type p - | AKInline (ethis,f,fmode,t) -> - (match follow t with - | TFun (args,r) -> - let _,_,mk_call = unify_field_call ctx fmode el args r p true in - mk_call ethis p +and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) = + match e with + | EField ((EConst (String s),ps),"code") -> + if UTF8.length s <> 1 then error "String must be a single UTF8 char" ps; + mk (TConst (TInt (Int32.of_int (UChar.code (UTF8.get s 0))))) ctx.t.tint p + | EField(_,n) when starts_with n '$' -> + error "Field names starting with $ are not allowed" p + | EConst (Ident s) -> + if s = "super" && with_type <> WithType.NoValue && not ctx.in_display then error "Cannot use super as value" p; + let e = maybe_type_against_enum ctx (fun () -> type_ident ctx s p mode) with_type false p in + acc_get ctx e p + | EField _ + | EArray _ -> + acc_get ctx (type_access ctx e p mode) p + | EConst (Regexp (r,opt)) -> + let str = mk (TConst (TString r)) ctx.t.tstring p in + let opt = mk (TConst (TString opt)) ctx.t.tstring p in + let t = Typeload.load_core_type ctx "EReg" in + mk (TNew ((match t with TInst (c,[]) -> c | _ -> assert false),[],[str;opt])) t p + | EConst (String s) when s <> "" && Lexer.is_fmt_string p -> + type_expr ctx (format_string ctx s p) with_type + | EConst c -> + Texpr.type_constant ctx.com.basic c p + | EBinop (op,e1,e2) -> + type_binop ctx op e1 e2 false with_type p + | EBlock [] when (match with_type with + | NoValue -> false + (* + If expected type is unknown then treat `(...) -> {}` as an empty function + (just like `function(...) {}`) instead of returning an object. + *) + | WithType (t, Some ImplicitReturn) -> not (ExtType.is_mono (follow t)) + | _ -> true + ) -> + type_expr ctx (EObjectDecl [],p) with_type + | EBlock l -> + let locals = save_locals ctx in + let e = type_block ctx l with_type p in + locals(); + e + | EParenthesis e -> + let e = type_expr ctx e with_type in + mk (TParenthesis e) e.etype p + | EObjectDecl fl -> + type_object_decl ctx fl with_type p + | EArrayDecl [(EFor _,_) | (EWhile _,_) as e] -> + type_array_comprehension ctx e with_type p + | EArrayDecl ((EBinop(OpArrow,_,_),_) as e1 :: el) -> + type_map_declaration ctx e1 el with_type p + | EArrayDecl el -> + begin match el,with_type with + | [],WithType(t,_) -> + let rec loop t = match follow t with + | TAbstract({a_path = (["haxe";"ds"],"Map")},_) -> + type_expr ctx (ENew(({tpackage=["haxe";"ds"];tname="Map";tparams=[];tsub=None},null_pos),[]),p) with_type + | _ -> + type_array_decl ctx el with_type p + in + loop t | _ -> - error (s_type (print_context()) t ^ " cannot be called") p - ) - | AKUsing (et,cl,ef,eparam) when Meta.has Meta.Generic ef.cf_meta -> - (match et.eexpr with - | TField(ec,fa) -> - type_generic_function ctx (ec,fa) el ~using_param:(Some eparam) with_type p - | _ -> assert false) - | AKUsing (et,cl,ef,eparam) -> - begin match ef.cf_kind with - | Method MethMacro -> - let ethis = type_module_type ctx (TClassDecl cl) None p in - let eparam,f = push_this ctx eparam in - let e = build_call ctx (AKMacro (ethis,ef)) (eparam :: el) with_type p in - f(); - e - | _ -> - let t = follow (field_type ctx cl [] ef p) in - (* for abstracts we have to apply their parameters to the static function *) - let t,tthis = match follow eparam.etype with - | TAbstract(a,tl) when Meta.has Meta.Impl ef.cf_meta -> apply_params a.a_params tl t,apply_params a.a_params tl a.a_this - | te -> t,te - in - let params,args,r,eparam = match t with - | TFun ((_,_,t1) :: args,r) -> - unify ctx tthis t1 eparam.epos; - let ef = prepare_using_field ef in - begin match unify_call_args ctx el args r p (ef.cf_kind = Method MethInline) (is_forced_inline (Some cl) ef) with - | el,TFun(args,r) -> el,args,r,eparam - | _ -> assert false - end - | _ -> assert false - in - make_call ctx et (eparam :: params) r p + type_array_decl ctx el with_type p end - | AKMacro (ethis,cf) -> - if ctx.macro_depth > 300 then error "Stack overflow" p; - ctx.macro_depth <- ctx.macro_depth + 1; - ctx.with_type_stack <- with_type :: ctx.with_type_stack; - let ethis_f = ref (fun () -> ()) in - let f = (match ethis.eexpr with - | TTypeExpr (TClassDecl c) -> - (match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with - | None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value) - | Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = type_block ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos) - | Some e -> (fun() -> type_expr ctx e with_type)) - | _ -> - (* member-macro call : since we will make a static call, let's found the actual class and not its subclass *) - (match follow ethis.etype with - | TInst (c,_) -> - let rec loop c = - if PMap.mem cf.cf_name c.cl_fields then - let eparam,f = push_this ctx ethis in - ethis_f := f; - let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with - | None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value) - | Some e -> (fun() -> type_expr ctx e Value) - in - e - else - match c.cl_super with - | None -> assert false - | Some (csup,_) -> loop csup - in - loop c - | _ -> assert false)) - in - ctx.macro_depth <- ctx.macro_depth - 1; - ctx.with_type_stack <- List.tl ctx.with_type_stack; - let old = ctx.on_error in - ctx.on_error <- (fun ctx msg ep -> - (* display additional info in the case the error is not part of our original call *) - if ep.pfile <> p.pfile || ep.pmax < p.pmin || ep.pmin > p.pmax then begin - Typeload.locate_macro_error := false; - old ctx msg ep; - Typeload.locate_macro_error := true; - ctx.com.error "Called from macro here" p; - end else - old ctx msg ep; - ); - let e = try - f() - with Error (m,p) -> - ctx.on_error <- old; - !ethis_f(); - raise (Fatal_error ((error_msg m),p)) - in - let e = Display.Diagnostics.secure_generated_code ctx e in - ctx.on_error <- old; - !ethis_f(); - e - | AKNo _ | AKSet _ | AKAccess _ -> - ignore(acc_get ctx acc p); + | EVars vl -> + type_vars ctx vl p + | EFor (it,e2) -> + ForLoop.type_for_loop ctx TyperDisplay.handle_display it e2 p + | ETernary (e1,e2,e3) -> + type_expr ctx (EIf (e1,e2,Some e3),p) with_type + | EIf (e,e1,e2) -> + type_if ctx e e1 e2 with_type p + | EWhile (cond,e,NormalWhile) -> + let old_loop = ctx.in_loop in + let cond = type_expr ctx cond WithType.value in + let cond = AbstractCast.cast_or_unify ctx ctx.t.tbool cond p in + ctx.in_loop <- true; + let e = type_expr ctx (Expr.ensure_block e) WithType.NoValue in + ctx.in_loop <- old_loop; + mk (TWhile (cond,e,NormalWhile)) ctx.t.tvoid p + | EWhile (cond,e,DoWhile) -> + let old_loop = ctx.in_loop in + ctx.in_loop <- true; + let e = type_expr ctx (Expr.ensure_block e) WithType.NoValue in + ctx.in_loop <- old_loop; + let cond = type_expr ctx cond WithType.value in + let cond = AbstractCast.cast_or_unify ctx ctx.t.tbool cond cond.epos in + mk (TWhile (cond,e,DoWhile)) ctx.t.tvoid p + | ESwitch (e1,cases,def) -> + let wrap e1 = mk (TMeta((Meta.Ast,[e,p],p),e1)) e1.etype e1.epos in + let e = Matcher.Match.match_expr ctx e1 cases def with_type false p in + wrap e + | EReturn e -> + type_return ctx e with_type p + | EBreak -> + if not ctx.in_loop then display_error ctx "Break outside loop" p; + mk TBreak t_dynamic p + | EContinue -> + if not ctx.in_loop then display_error ctx "Continue outside loop" p; + mk TContinue t_dynamic p + | ETry (e1,[]) -> + type_expr ctx e1 with_type + | ETry (e1,catches) -> + type_try ctx e1 catches with_type p + | EThrow e -> + let e = type_expr ctx e WithType.value in + mk (TThrow e) (mk_mono()) p + | ECall (e,el) -> + type_call ~mode ctx e el with_type false p + | ENew (t,el) -> + type_new ctx t el with_type false p + | EUnop (op,flag,e) -> + type_unop ctx op flag e p + | EFunction (name,f) -> + type_local_function ctx name false f with_type p + | EUntyped e -> + let old = ctx.untyped in + ctx.untyped <- true; + if not (Meta.has Meta.HasUntyped ctx.curfield.cf_meta) then ctx.curfield.cf_meta <- (Meta.HasUntyped,[],p) :: ctx.curfield.cf_meta; + let e = type_expr ctx e with_type in + ctx.untyped <- old; + { + eexpr = e.eexpr; + etype = mk_mono(); + epos = e.epos; + } + | ECast (e,None) -> + let e = type_expr ctx e WithType.value in + mk (TCast (e,None)) (mk_mono()) p + | ECast (e, Some t) -> + type_cast ctx e t p + | EDisplay (e,dk) -> + TyperDisplay.handle_edisplay ctx e dk with_type + | EDisplayNew t -> assert false - | AKExpr e -> - let rec loop t = match follow t with - | TFun (args,r) -> - begin match e.eexpr with - | TField(e1,fa) when not (match fa with FEnum _ -> true | _ -> false) -> - begin match fa with - | FInstance(_,_,cf) | FStatic(_,cf) when Meta.has Meta.Generic cf.cf_meta -> - type_generic_function ctx (e1,fa) el with_type p - | _ -> - let _,_,mk_call = unify_field_call ctx fa el args r p false in - mk_call e1 e.epos - end - | _ -> - let el, tfunc = unify_call_args ctx el args r p false false in - let r = match tfunc with TFun(_,r) -> r | _ -> assert false in - mk (TCall (e,el)) r p - end - | TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta -> - loop (Abstract.get_underlying_type a tl) - | TMono _ -> - let t = mk_mono() in - let el = List.map (fun e -> type_expr ctx e Value) el in - unify ctx (tfun (List.map (fun e -> e.etype) el) t) e.etype e.epos; - mk (TCall (e,el)) t p - | t -> - let el = List.map (fun e -> type_expr ctx e Value) el in - let t = if t == t_dynamic then - t_dynamic - else if ctx.untyped then - mk_mono() - else - error (s_type (print_context()) e.etype ^ " cannot be called") e.epos - in - mk (TCall (e,el)) t p - in - loop e.etype - -(* ---------------------------------------------------------------------- *) -(* FINALIZATION *) - -let get_main ctx types = - match ctx.com.main_class with - | None -> None - | Some cl -> - let t = Typeload.load_type_def ctx null_pos { tpackage = fst cl; tname = snd cl; tparams = []; tsub = None } in - let fmode, ft, r = (match t with - | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ -> - error ("Invalid -main : " ^ s_type_path cl ^ " is not a class") null_pos - | TClassDecl c -> - try - let f = PMap.find "main" c.cl_statics in - let t = Type.field_type f in - (match follow t with - | TFun ([],r) -> FStatic (c,f), t, r - | _ -> error ("Invalid -main : " ^ s_type_path cl ^ " has invalid main function") c.cl_pos); - with - Not_found -> error ("Invalid -main : " ^ s_type_path cl ^ " does not have static function main") c.cl_pos - ) in - let emain = type_type ctx cl null_pos in - let main = mk (TCall (mk (TField (emain,fmode)) ft null_pos,[])) r null_pos in - (* add haxe.EntryPoint.run() call *) - let main = (try - let et = List.find (fun t -> t_path t = (["haxe"],"EntryPoint")) types in - let ec = (match et with TClassDecl c -> c | _ -> assert false) in - let ef = PMap.find "run" ec.cl_statics in - let p = null_pos in - let et = mk (TTypeExpr et) (TAnon { a_fields = PMap.empty; a_status = ref (Statics ec) }) p in - let call = mk (TCall (mk (TField (et,FStatic (ec,ef))) ef.cf_type p,[])) ctx.t.tvoid p in - mk (TBlock [main;call]) ctx.t.tvoid p - with Not_found -> - main - ) in - Some main - -let finalize ctx = - flush_pass ctx PFinal "final"; - match ctx.com.callbacks.after_typing with - | [] -> - () - | fl -> - let rec loop handled_types = - let all_types = Hashtbl.fold (fun _ m acc -> m.m_types @ acc) ctx.g.modules [] in - match (List.filter (fun mt -> not (List.memq mt handled_types)) all_types) with - | [] -> - () - | new_types -> - List.iter (fun f -> f new_types) fl; - flush_pass ctx PFinal "final"; - loop all_types - in - loop [] - -type state = - | Generating - | Done - | NotYet - -let generate ctx = - let types = ref [] in - let states = Hashtbl.create 0 in - let state p = try Hashtbl.find states p with Not_found -> NotYet in - let statics = ref PMap.empty in - - let rec loop t = - let p = t_path t in - match state p with - | Done -> () - | Generating -> - ctx.com.warning ("Warning : maybe loop in static generation of " ^ s_type_path p) (t_infos t).mt_pos; - | NotYet -> - Hashtbl.add states p Generating; - let t = (match t with - | TClassDecl c -> - walk_class p c; - t - | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ -> - t - ) in - Hashtbl.replace states p Done; - types := t :: !types - - and loop_class p c = - if c.cl_path <> p then loop (TClassDecl c) - - and loop_enum p e = - if e.e_path <> p then loop (TEnumDecl e) - - and loop_abstract p a = - if a.a_path <> p then loop (TAbstractDecl a) - - and walk_static_field p c cf = - match cf.cf_expr with - | None -> () - | Some e -> - if PMap.mem (c.cl_path,cf.cf_name) (!statics) then - () - else begin - statics := PMap.add (c.cl_path,cf.cf_name) () (!statics); - walk_expr p e; - end - - and walk_expr p e = - match e.eexpr with - | TTypeExpr t -> - (match t with - | TClassDecl c -> loop_class p c - | TEnumDecl e -> loop_enum p e - | TAbstractDecl a -> loop_abstract p a - | TTypeDecl _ -> assert false) - | TNew (c,_,_) -> - iter (walk_expr p) e; - loop_class p c; - let rec loop c = - if PMap.mem (c.cl_path,"new") (!statics) then - () - else begin - statics := PMap.add (c.cl_path,"new") () !statics; - (match c.cl_constructor with - | Some { cf_expr = Some e } -> walk_expr p e - | _ -> ()); - match c.cl_super with - | None -> () - | Some (csup,_) -> loop csup - end - in - loop c - | TField(e1,FStatic(c,cf)) -> - walk_expr p e1; - walk_static_field p c cf; - | _ -> - iter (walk_expr p) e - - and walk_class p c = - (match c.cl_super with None -> () | Some (c,_) -> loop_class p c); - List.iter (fun (c,_) -> loop_class p c) c.cl_implements; - (match c.cl_init with - | None -> () - | Some e -> walk_expr p e); - PMap.iter (fun _ f -> - match f.cf_expr with - | None -> () - | Some e -> - match e.eexpr with - | TFunction _ -> () - | _ -> walk_expr p e - ) c.cl_statics - - in - let sorted_modules = List.sort (fun m1 m2 -> compare m1.m_path m2.m_path) (Hashtbl.fold (fun _ m acc -> m :: acc) ctx.g.modules []) in - List.iter (fun m -> List.iter loop m.m_types) sorted_modules; - get_main ctx !types, List.rev !types, sorted_modules + | ECheckType (e,t) -> + let t = Typeload.load_complex_type ctx true t in + let e = type_expr ctx e (WithType.with_type t) in + let e = AbstractCast.cast_or_unify ctx t e p in + if e.etype == t then e else mk (TCast (e,None)) t p + | EMeta (m,e1) -> + type_meta ~mode ctx m e1 with_type p (* ---------------------------------------------------------------------- *) (* TYPER INITIALIZATION *) @@ -4511,21 +2605,22 @@ let rec create com = module_check_policies = []; delayed = []; debug_delayed = []; - delayed_macros = DynArray.create(); doinline = com.display.dms_inline && not (Common.defined com Define.NoInline); hook_generate = []; - get_build_infos = (fun() -> None); std = null_module; global_using = []; + complete = false; do_inherit = MagicTypes.on_inherit; do_create = create; do_macro = MacroContext.type_macro; - do_load_module = Typeload.load_module; + do_load_module = TypeloadModule.load_module; + do_load_type_def = Typeload.load_type_def; do_optimize = Optimizer.reduce_expression; - do_build_instance = Typeload.build_instance; + do_build_instance = InstanceBuilder.build_instance; do_format_string = format_string; - do_finalize = finalize; - do_generate = generate; + do_finalize = Finalization.finalize; + do_generate = Finalization.generate; + do_load_core_class = Typeload.load_core_class; }; m = { curmod = null_module; @@ -4536,6 +2631,7 @@ let rec create com = module_imports = []; }; is_display_file = false; + bypass_accessor = 0; meta = []; this_stack = []; with_type_stack = []; @@ -4546,6 +2642,7 @@ let rec create com = curfun = FunStatic; in_loop = false; in_display = false; + get_build_infos = (fun() -> None); in_macro = Common.defined com Define.Macro; ret = mk_mono(); locals = PMap.empty; @@ -4559,9 +2656,14 @@ let rec create com = on_error = (fun ctx msg p -> ctx.com.error msg p); } in ctx.g.std <- (try - Typeload.load_module ctx ([],"StdTypes") null_pos + TypeloadModule.load_module ctx ([],"StdTypes") null_pos with - Error (Module_not_found ([],"StdTypes"),_) -> error "Standard library not found" null_pos + Error (Module_not_found ([],"StdTypes"),_) -> + try + let std_path = Sys.getenv "HAXE_STD_PATH" in + error ("Standard library not found. Please check your `HAXE_STD_PATH` environment variable (current value: \"" ^ std_path ^ "\")") null_pos + with Not_found -> + error "Standard library not found. You may need to set your `HAXE_STD_PATH` environment variable" null_pos ); (* We always want core types to be available so we add them as default imports (issue #1904 and #3131). *) ctx.m.module_types <- List.map (fun t -> t,null_pos) ctx.g.std.m_types; @@ -4577,7 +2679,7 @@ let rec create com = | "Null" -> let mk_null t = try - if not (is_null ~no_lazy:true t) then TAbstract (a,[t]) else t + if not (is_null ~no_lazy:true t || is_explicit_null t) then TAbstract (a,[t]) else t with Exit -> (* don't force lazy evaluation *) let r = ref (lazy_available t_dynamic) in @@ -4593,11 +2695,12 @@ let rec create com = | TEnumDecl _ | TClassDecl _ | TTypeDecl _ -> () ) ctx.g.std.m_types; - let m = Typeload.load_module ctx ([],"String") null_pos in - (match m.m_types with - | [TClassDecl c] -> ctx.t.tstring <- TInst (c,[]) - | _ -> assert false); - let m = Typeload.load_module ctx ([],"Array") null_pos in + let m = TypeloadModule.load_module ctx ([],"String") null_pos in + List.iter (fun mt -> match mt with + | TClassDecl c -> ctx.t.tstring <- TInst (c,[]) + | _ -> () + ) m.m_types; + let m = TypeloadModule.load_module ctx ([],"Array") null_pos in (try List.iter (fun t -> ( match t with @@ -4608,24 +2711,22 @@ let rec create com = )) m.m_types; assert false with Exit -> ()); - let m = Typeload.load_module ctx (["haxe"],"EnumTools") null_pos in + let m = TypeloadModule.load_module ctx (["haxe"],"EnumTools") null_pos in (match m.m_types with | [TClassDecl c1;TClassDecl c2] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using | [TClassDecl c1] -> - let m = Typeload.load_module ctx (["haxe"],"EnumValueTools") null_pos in + let m = TypeloadModule.load_module ctx (["haxe"],"EnumWithType.valueTools") null_pos in (match m.m_types with | [TClassDecl c2 ] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using | _ -> assert false); | _ -> assert false); + ctx.g.complete <- true; ctx ;; unify_min_ref := unify_min; +unify_min_for_type_source_ref := unify_min_for_type_source; make_call_ref := make_call; -get_constructor_ref := get_constructor; -cast_or_unify_ref := AbstractCast.cast_or_unify_raise; -type_module_type_ref := type_module_type; -find_array_access_raise_ref := AbstractCast.find_array_access_raise; build_call_ref := build_call; -merge_core_doc_ref := merge_core_doc; -MacroContext.unify_call_args_ref := unify_call_args \ No newline at end of file +type_call_target_ref := type_call_target; +type_block_ref := type_block diff --git a/src/typing/typerBase.ml b/src/typing/typerBase.ml new file mode 100644 index 00000000000..1f9566eb601 --- /dev/null +++ b/src/typing/typerBase.ml @@ -0,0 +1,212 @@ +open Globals +open Ast +open Type +open Typecore +open Error + +type access_kind = + | AKNo of string + | AKExpr of texpr + | AKSet of texpr * t * tclass_field + | AKInline of texpr * tclass_field * tfield_access * t + | AKMacro of texpr * tclass_field + | AKUsing of texpr * tclass * tclass_field * texpr * bool (* forced inline *) + | AKAccess of tabstract * tparams * tclass * texpr * texpr + | AKFieldSet of texpr * texpr * string * t + +type object_decl_kind = + | ODKWithStructure of tanon + | ODKWithClass of tclass * tparams + | ODKPlain + +let build_call_ref : (typer -> access_kind -> expr list -> WithType.t -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false) +let type_call_target_ref : (typer -> expr -> WithType.t -> bool -> pos -> access_kind) ref = ref (fun _ _ _ _ _ -> assert false) + +let relative_path ctx file = + let slashes path = String.concat "/" (ExtString.String.nsplit path "\\") in + let fpath = slashes (Path.get_full_path file) in + let fpath_lower = String.lowercase fpath in + let flen = String.length fpath_lower in + let rec loop = function + | [] -> file + | path :: l -> + let spath = String.lowercase (slashes path) in + let slen = String.length spath in + if slen > 0 && slen < flen && String.sub fpath_lower 0 slen = spath then String.sub fpath slen (flen - slen) else loop l + in + loop ctx.com.Common.class_path + +let mk_infos ctx p params = + let file = if ctx.in_macro then p.pfile else if Common.defined ctx.com Define.AbsolutePath then Path.get_full_path p.pfile else relative_path ctx p.pfile in + (EObjectDecl ( + (("fileName",null_pos,NoQuotes) , (EConst (String file) , p)) :: + (("lineNumber",null_pos,NoQuotes) , (EConst (Int (string_of_int (Lexer.get_error_line p))),p)) :: + (("className",null_pos,NoQuotes) , (EConst (String (s_type_path ctx.curclass.cl_path)),p)) :: + if ctx.curfield.cf_name = "" then + params + else + (("methodName",null_pos,NoQuotes), (EConst (String ctx.curfield.cf_name),p)) :: params + ) ,p) + +let rec is_pos_infos = function + | TMono r -> + (match !r with + | Some t -> is_pos_infos t + | _ -> false) + | TLazy f -> + is_pos_infos (lazy_type f) + | TType ({ t_path = ["haxe"] , "PosInfos" },[]) -> + true + | TType (t,tl) -> + is_pos_infos (apply_params t.t_params tl t.t_type) + | TAbstract({a_path=[],"Null"},[t]) -> + is_pos_infos t + | _ -> + false + +let get_this ctx p = + match ctx.curfun with + | FunStatic -> + error "Cannot access this from a static function" p + | FunMemberClassLocal | FunMemberAbstractLocal -> + let v = match ctx.vthis with + | None -> + let v = if ctx.curfun = FunMemberAbstractLocal then + PMap.find "this" ctx.locals + else + add_local ctx VGenerated "`this" ctx.tthis p + in + ctx.vthis <- Some v; + v + | Some v -> + ctx.locals <- PMap.add v.v_name v ctx.locals; + v + in + mk (TLocal v) ctx.tthis p + | FunMemberAbstract -> + let v = (try PMap.find "this" ctx.locals with Not_found -> assert false) in + mk (TLocal v) v.v_type p + | FunConstructor | FunMember -> + mk (TConst TThis) ctx.tthis p + +let assign_to_this_is_allowed ctx = + match ctx.curclass.cl_kind with + | KAbstractImpl _ -> + (match ctx.curfield.cf_kind with + | Method MethInline -> true + | Method _ when ctx.curfield.cf_name = "_new" -> true + | _ -> false + ) + | _ -> false + +let rec type_module_type ctx t tparams p = + match t with + | TClassDecl {cl_kind = KGenericBuild _} -> + let _,_,f = InstanceBuilder.build_instance ctx t p in + let t = f (match tparams with None -> [] | Some tl -> tl) in + let mt = try + module_type_of_type t + with Exit -> + if follow t == t_dynamic then Typeload.load_type_def ctx p { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None } + else error "Invalid module type" p + in + type_module_type ctx mt None p + | TClassDecl c -> + let t_tmp = class_module_type c in + mk (TTypeExpr (TClassDecl c)) (TType (t_tmp,[])) p + | TEnumDecl e -> + let types = (match tparams with None -> List.map (fun _ -> mk_mono()) e.e_params | Some l -> l) in + mk (TTypeExpr (TEnumDecl e)) (TType (e.e_type,types)) p + | TTypeDecl s -> + let t = apply_params s.t_params (List.map (fun _ -> mk_mono()) s.t_params) s.t_type in + if not (Common.defined ctx.com Define.NoDeprecationWarnings) then + DeprecationCheck.check_typedef ctx.com s p; + (match follow t with + | TEnum (e,params) -> + type_module_type ctx (TEnumDecl e) (Some params) p + | TInst (c,params) -> + type_module_type ctx (TClassDecl c) (Some params) p + | TAbstract (a,params) -> + type_module_type ctx (TAbstractDecl a) (Some params) p + | _ -> + error (s_type_path s.t_path ^ " is not a value") p) + | TAbstractDecl { a_impl = Some c } -> + type_module_type ctx (TClassDecl c) tparams p + | TAbstractDecl a -> + if not (Meta.has Meta.RuntimeValue a.a_meta) then error (s_type_path a.a_path ^ " is not a value") p; + let t_tmp = abstract_module_type a [] in + mk (TTypeExpr (TAbstractDecl a)) (TType (t_tmp,[])) p + +let type_type ctx tpath p = + type_module_type ctx (Typeload.load_type_def ctx p { tpackage = fst tpath; tname = snd tpath; tparams = []; tsub = None }) None p + +let s_access_kind acc = + let st = s_type (print_context()) in + let se = s_expr_pretty true "" false st in + let sfa = s_field_access st in + match acc with + | AKNo s -> "AKNo " ^ s + | AKExpr e -> "AKExpr " ^ (se e) + | AKSet(e,t,cf) -> Printf.sprintf "AKSet(%s, %s, %s)" (se e) (st t) cf.cf_name + | AKInline(e,cf,fa,t) -> Printf.sprintf "AKInline(%s, %s, %s, %s)" (se e) cf.cf_name (sfa fa) (st t) + | AKMacro(e,cf) -> Printf.sprintf "AKMacro(%s, %s)" (se e) cf.cf_name + | AKUsing(e1,c,cf,e2,b) -> Printf.sprintf "AKUsing(%s, %s, %s, %s, %b)" (se e1) (s_type_path c.cl_path) cf.cf_name (se e2) b + | AKAccess(a,tl,c,e1,e2) -> Printf.sprintf "AKAccess(%s, [%s], %s, %s, %s)" (s_type_path a.a_path) (String.concat ", " (List.map st tl)) (s_type_path c.cl_path) (se e1) (se e2) + | AKFieldSet(_) -> "" + +let get_constructible_constraint ctx tl p = + let extract_function t = match follow t with + | TFun(tl,tr) -> tl,tr + | _ -> error "Constructible type parameter should be function" p + in + let rec loop tl = match tl with + | [] -> None + | t :: tl -> + begin match follow t with + | TAnon a -> + begin try + Some (extract_function (PMap.find "new" a.a_fields).cf_type); + with Not_found -> + loop tl + end; + | TAbstract({a_path = ["haxe"],"Constructible"},[t1]) -> + Some (extract_function t1) + | TInst({cl_kind = KTypeParameter tl1},_) -> + begin match loop tl1 with + | None -> loop tl + | Some _ as t -> t + end + | _ -> + loop tl + end + in + loop tl + +let unify_static_extension ctx e t p = + let multitype_involed t1 t2 = + let check t = match follow t with + | TAbstract(a,_) when Meta.has Meta.MultiType a.a_meta -> true + | _ -> false + in + check t1 || check t2 + in + if multitype_involed e.etype t then + AbstractCast.cast_or_unify_raise ctx t e p + else begin + Type.unify e.etype t; + e + end + +let get_abstract_froms a pl = + let l = List.map (apply_params a.a_params pl) a.a_from in + List.fold_left (fun acc (t,f) -> + match follow (Type.field_type f) with + | TFun ([_,_,v],t) -> + (try + ignore(type_eq EqStrict t (TAbstract(a,List.map duplicate pl))); (* unify fields monomorphs *) + v :: acc + with Unify_error _ -> + acc) + | _ -> + acc + ) l a.a_from_field \ No newline at end of file diff --git a/src/typing/typerDisplay.ml b/src/typing/typerDisplay.ml new file mode 100644 index 00000000000..f07a7ca8d12 --- /dev/null +++ b/src/typing/typerDisplay.ml @@ -0,0 +1,606 @@ +open Globals +open Ast +open DisplayTypes +open DisplayMode +open CompletionResultKind +open CompletionItem +open CompletionModuleKind +open CompletionModuleType +open ClassFieldOrigin +open DisplayException +open DisplayEmitter +open Common +open Type +open Typecore +open TyperBase +open Fields +open Calls +open Error + +let convert_function_signature ctx values (args,ret) = match DisplayEmitter.completion_type_of_type ctx ~values (TFun(args,ret)) with + | CompletionType.CTFunction ctf -> ((args,ret),ctf) + | _ -> assert false + +let completion_item_of_expr ctx e = + let retype e s t = + try + let e' = type_expr ctx (EConst(Ident s),null_pos) (WithType.with_type t) in + Texpr.equal e e' + with _ -> + false + in + let tpair ?(values=PMap.empty) t = + let ct = DisplayEmitter.completion_type_of_type ctx ~values t in + (t,ct) + in + let of_field e origin cf scope make_ci = + let is_qualified = retype e cf.cf_name e.etype in + make_ci (CompletionClassField.make cf scope origin is_qualified) (tpair ~values:(get_value_meta cf.cf_meta) e.etype) + in + let of_enum_field e origin ef = + let is_qualified = retype e ef.ef_name e.etype in + make_ci_enum_field (CompletionEnumField.make ef origin is_qualified) (tpair e.etype) + in + let itexpr e = + let t = tpair e.etype in + make_ci_expr e t + in + let rec loop e = match e.eexpr with + | TLocal v | TVar(v,_) -> make_ci_local v (tpair ~values:(get_value_meta v.v_meta) v.v_type) + | TField(e1,FStatic(c,cf)) -> + Display.merge_core_doc ctx (TClassDecl c); + let decl = decl_of_class c in + let origin = match c.cl_kind,e1.eexpr with + | KAbstractImpl _,_ when Meta.has Meta.Impl cf.cf_meta -> Self decl + | _,TMeta((Meta.StaticExtension,_,_),_) -> StaticExtension decl + | _ -> Self decl + in + let make_ci = match c.cl_kind with + | KAbstractImpl a when Meta.has Meta.Enum cf.cf_meta -> make_ci_enum_abstract_field a + | _ -> make_ci_class_field + in + of_field e origin cf CFSStatic make_ci + | TField(e1,(FInstance(c,_,cf) | FClosure(Some(c,_),cf))) -> + Display.merge_core_doc ctx (TClassDecl c); + let origin = match follow e1.etype with + | TInst(c',_) when c != c' -> + Parent (TClassDecl c) + | _ -> + Self (TClassDecl c) + in + of_field e origin cf CFSMember make_ci_class_field + | TField(_,FEnum(en,ef)) -> of_enum_field e (Self (TEnumDecl en)) ef + | TField(e1,(FAnon cf | FClosure(None,cf))) -> + begin match follow e1.etype with + | TAnon an -> + let origin = match e1.etype with + | TType(td,_) -> Self (TTypeDecl td) + | _ -> AnonymousStructure an + in + of_field e origin cf CFSMember make_ci_class_field + | _ -> itexpr e + end + | TTypeExpr (TClassDecl {cl_kind = KAbstractImpl a}) -> + Display.merge_core_doc ctx (TAbstractDecl a); + let t = TType(abstract_module_type a (List.map snd a.a_params),[]) in + let t = tpair t in + make_ci_type (CompletionModuleType.of_module_type (TAbstractDecl a)) ImportStatus.Imported (Some t) + | TTypeExpr mt -> + Display.merge_core_doc ctx mt; + let t = tpair e.etype in + make_ci_type (CompletionModuleType.of_module_type mt) ImportStatus.Imported (Some t) (* TODO *) + | TConst (TThis | TSuper) -> itexpr e (* TODO *) + | TConst(ct) -> make_ci_literal (s_const ct) (tpair e.etype) + | TObjectDecl _ -> + begin match follow e.etype with + | TAnon an -> make_ci_anon an (tpair e.etype) + | _ -> itexpr e + end + | TNew(c,tl,_) -> + Display.merge_core_doc ctx (TClassDecl c); + (* begin match fst e_ast with + | EConst (Regexp (r,opt)) -> + let present,absent = List.partition (String.contains opt) ['g';'i';'m';'s';'u'] in + let doc flag desc = Printf.sprintf "* %s: %s" (String.make 1 flag) desc in + let f c = match c with + | 'g' -> doc c "global split and replace" + | 'i' -> doc c "case insensitive matching" + | 'm' -> doc c "multiline matching" + | 's' -> doc c "dot also match newlines" + | 'u' -> doc c "use UTF-8 matching" + | _ -> assert false + in + let present = List.map f present in + let present = match present with [] -> [] | _ -> "\n\nActive flags:\n\n" :: present in + let absent = List.map f absent in + let absent = match absent with [] -> [] | _ -> "\n\nInactive flags:\n\n" :: absent in + (TInst(c,tl)),Some ("Regular expression\n\n" ^ (String.concat "\n" (present @ absent))) + | _ -> *) + let t,cf = get_constructor ctx c tl e.epos in + let t = match follow t with + | TFun(args,_) -> TFun(args,TInst(c,tl)) + | _ -> t + in + make_ci_class_field (CompletionClassField.make cf CFSConstructor (Self (decl_of_class c)) true) (tpair ~values:(get_value_meta cf.cf_meta) t) + (* end *) + | TCall({eexpr = TConst TSuper; etype = t} as e1,_) -> + itexpr e1 (* TODO *) + | TCast(e1,_) -> loop {e1 with etype = e.etype} + | TParenthesis e1 | TMeta(_,e1) -> loop e1 + | _ -> itexpr e + in + loop e + +let get_expected_type ctx with_type = + let t = match with_type with + | WithType.WithType(t,_) -> Some t + | _ -> None + in + match t with + | None -> None + | Some t -> Some (completion_type_of_type ctx t,completion_type_of_type ctx (follow t)) + +let raise_toplevel ctx dk with_type (subject,psubject) po = + let expected_type = get_expected_type ctx with_type in + DisplayToplevel.collect_and_raise ctx (match dk with DKPattern _ -> TKPattern psubject | _ -> TKExpr psubject) with_type (CRToplevel expected_type) (subject,psubject) po + +let display_dollar_type ctx p make_type = + let mono = mk_mono() in + let doc = Some "Outputs type of argument as a warning and uses argument as value" in + let arg = ["expression",false,mono] in + begin match ctx.com.display.dms_kind with + | DMSignature -> + raise_signatures [(convert_function_signature ctx PMap.empty (arg,mono),doc)] 0 0 SKCall + | DMHover -> + let t = TFun(arg,mono) in + raise_hover (make_ci_expr (mk (TIdent "trace") t p) (make_type t)) (Some (WithType.named_argument "expression")) p + | DMDefinition | DMTypeDefinition -> + raise_positions [] + | _ -> + error "Unsupported method" p + end + +let rec handle_signature_display ctx e_ast with_type = + ctx.in_display <- true; + let p = pos e_ast in + let handle_call tl el p0 = + let rec follow_with_callable (t,doc,values) = match follow t with + | TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta -> follow_with_callable (Abstract.get_underlying_type a tl,doc,values) + | TFun(args,ret) -> ((args,ret),doc,values) + | _ -> error ("Not a callable type: " ^ (s_type (print_context()) t)) p + in + let tl = List.map follow_with_callable tl in + let rec loop i acc el = match el with + | e :: el -> + begin match fst e with + | EDisplay(e1,DKMarked) -> i,List.rev (e1 :: acc) @ el + | _ -> loop (i + 1) (e :: acc) el + end + | [] -> + 0,List.rev acc + in + let display_arg,el = loop 0 [] el in + (* If our display position exceeds the argument number we add a null expression in order to make + unify_call_args error out. *) + let el = if el <> [] && display_arg >= List.length el then el @ [EConst (Ident "null"),null_pos] else el in + let rec loop acc tl = match tl with + | (t,doc,values) :: tl -> + let keep (args,r) = + begin try + let _ = unify_call_args' ctx el args r p false false in + true + with + | Error(Call_error (Not_enough_arguments _),_) -> true + | _ -> false + end + in + loop (if keep t then (t,doc,values) :: acc else acc) tl + | [] -> + acc + in + let overloads = match loop [] tl with [] -> tl | tl -> tl in + let overloads = List.map (fun (t,doc,values) -> (convert_function_signature ctx values t,doc)) overloads in + raise_signatures overloads 0 (* ? *) display_arg SKCall + in + let find_constructor_types t = match follow t with + | TInst ({cl_kind = KTypeParameter tl} as c,_) -> + let rec loop tl = match tl with + | [] -> raise_error (No_constructor (TClassDecl c)) p + | t :: tl -> match follow t with + | TAbstract({a_path = ["haxe"],"Constructible"},[t]) -> t + | _ -> loop tl + in + [loop tl,None,PMap.empty] + | TInst (c,tl) | TAbstract({a_impl = Some c},tl) -> + Display.merge_core_doc ctx (TClassDecl c); + let ct,cf = get_constructor ctx c tl p in + let tl = (ct,cf.cf_doc,get_value_meta cf.cf_meta) :: List.rev_map (fun cf' -> cf'.cf_type,cf.cf_doc,get_value_meta cf'.cf_meta) cf.cf_overloads in + tl + | _ -> + [] + in + match fst e_ast with + | ECall(e1,el) -> + let def () = + try + acc_get ctx (!type_call_target_ref ctx e1 with_type false (pos e1)) (pos e1) + with + | Error (Unknown_ident "trace",_) -> + let e = expr_of_type_path (["haxe";"Log"],"trace") p in + type_expr ctx e WithType.value + | Error (Unknown_ident "$type",p) -> + display_dollar_type ctx p (fun t -> t,(DisplayEmitter.completion_type_of_type ctx t)) + in + let e1 = match e1 with + | (EField (e,"bind"),p) -> + let e = type_expr ctx e WithType.value in + (match follow e.etype with + | TFun signature -> e + | _ -> def ()) + | _ -> def() + in + let tl = match e1.eexpr with + | TField(_,fa) -> + begin match extract_field fa with + | Some cf -> (e1.etype,cf.cf_doc,get_value_meta cf.cf_meta) :: List.rev_map (fun cf' -> cf'.cf_type,cf.cf_doc,get_value_meta cf'.cf_meta) cf.cf_overloads + | None -> [e1.etype,None,PMap.empty] + end + | TConst TSuper -> + find_constructor_types e1.etype + | TLocal v -> + [e1.etype,None,get_value_meta v.v_meta] + | _ -> [e1.etype,None,PMap.empty] + in + handle_call tl el e1.epos + | ENew(tpath,el) -> + let t = Typeload.load_instance ctx tpath true in + handle_call (find_constructor_types t) el (pos tpath) + | EArray(e1,e2) -> + let e1 = type_expr ctx e1 WithType.value in + begin match follow e1.etype with + | TInst({cl_path=([],"Array")},[t]) -> + let res = convert_function_signature ctx PMap.empty (["index",false,ctx.t.tint],t) in + raise_signatures [res,Some "The array index"] 0 0 SKCall + | TAbstract(a,tl) -> + (match a.a_impl with Some c -> ignore(c.cl_build()) | _ -> ()); + let sigs = ExtList.List.filter_map (fun cf -> match follow cf.cf_type with + | TFun(_ :: args,r) -> + if ExtType.is_void (follow r) && (match with_type with WithType.NoValue -> false | _ -> true) then + None + else begin + let map = apply_params a.a_params tl in + let tl = List.map (fun (n,o,t) -> n,o,map t) args in + let r = map r in + Some (convert_function_signature ctx PMap.empty (tl,r),cf.cf_doc) + end + | _ -> + None + ) a.a_array in + raise_signatures sigs 0 0 SKArrayAccess + | _ -> + raise_signatures [] 0 0 SKArrayAccess + end + | _ -> error "Call expected" p + +and display_expr ctx e_ast e dk with_type p = + let get_super_constructor () = match ctx.curclass.cl_super with + | None -> error "Current class does not have a super" p + | Some (c,params) -> + let _, f = get_constructor ctx c params p in + f + in + match ctx.com.display.dms_kind with + | DMResolve _ | DMPackage -> + assert false + | DMSignature -> + handle_signature_display ctx e_ast with_type + | DMHover -> + let item = completion_item_of_expr ctx e in + raise_hover item (Some with_type) e.epos + | DMUsage _ -> + let rec loop e = match e.eexpr with + | TField(_,FEnum(_,ef)) -> + Display.ReferencePosition.set (ef.ef_name,ef.ef_name_pos,KEnumField); + | TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) -> + Display.ReferencePosition.set (cf.cf_name,cf.cf_name_pos,KClassField); + | TLocal v | TVar(v,_) -> + Display.ReferencePosition.set (v.v_name,v.v_pos,KVar); + | TTypeExpr mt -> + let ti = t_infos mt in + Display.ReferencePosition.set (snd ti.mt_path,ti.mt_name_pos,KModuleType); + | TNew(c,tl,_) -> + begin try + let _,cf = get_constructor ctx c tl p in + Display.ReferencePosition.set (snd c.cl_path,cf.cf_name_pos,KConstructor); + with Not_found -> + () + end + | TCall({eexpr = TConst TSuper},_) -> + begin try + let cf = get_super_constructor() in + Display.ReferencePosition.set (cf.cf_name,cf.cf_name_pos,KClassField); + with Not_found -> + () + end + | TConst TSuper -> + begin match ctx.curclass.cl_super with + | None -> () + | Some (c,_) -> Display.ReferencePosition.set (snd c.cl_path,c.cl_name_pos,KModuleType); + end + | TCall(e1,_) -> + loop e1 + | _ -> + () + in + loop e; + e + | DMDefinition -> + let rec loop e = match e.eexpr with + | TField(_,FEnum(_,ef)) -> [ef.ef_name_pos] + | TField(_,(FStatic (c,cf))) when Meta.has Meta.CoreApi c.cl_meta -> + let c' = ctx.g.do_load_core_class ctx c in + cf.cf_name_pos :: (try [(PMap.find cf.cf_name c'.cl_statics).cf_name_pos] with Not_found -> []) + | TField(_,(FInstance (c,tl,cf) | FClosure (Some(c,tl),cf))) when Meta.has Meta.CoreApi c.cl_meta -> + let c' = ctx.g.do_load_core_class ctx c in + let l = try + let _,_,cf = Type.class_field c' tl cf.cf_name in + [cf.cf_name_pos] + with Not_found -> + [] + in + cf.cf_name_pos :: l + | TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) -> [cf.cf_name_pos] + | TLocal v | TVar(v,_) -> [v.v_pos] + | TTypeExpr (TClassDecl c) when Meta.has Meta.CoreApi c.cl_meta -> + let c' = ctx.g.do_load_core_class ctx c in + [c.cl_name_pos;c'.cl_name_pos] + | TTypeExpr mt -> [(t_infos mt).mt_name_pos] + | TNew(c,tl,_) -> + begin try + let _,cf = get_constructor ctx c tl p in + if Meta.has Meta.CoreApi c.cl_meta then begin + let c' = ctx.g.do_load_core_class ctx c in + begin match c'.cl_constructor with + | Some cf' -> [cf.cf_name_pos;cf'.cf_name_pos] + | None -> [cf.cf_name_pos] + end + end else + [cf.cf_name_pos] + with Not_found -> + [] + end + | TCall({eexpr = TConst TSuper},_) -> + begin try + let cf = get_super_constructor() in + [cf.cf_name_pos] + with Not_found -> + [] + end + | TConst TSuper -> + begin match ctx.curclass.cl_super with + | None -> [] + | Some (c,_) -> [c.cl_name_pos] + end + | TCall(e1,_) -> + loop e1 + | _ -> + [] + in + let pl = loop e in + raise_positions pl + | DMTypeDefinition -> + raise_position_of_type e.etype + | DMDefault when not (!Parser.had_resume)-> + let display_fields e_ast e1 l = + let fields = DisplayFields.collect ctx e_ast e1 dk with_type p in + let item = completion_item_of_expr ctx e1 in + raise_fields fields (CRField(item,e1.epos,None,None)) (Some {e.epos with pmin = e.epos.pmax - l;}) + in + begin match fst e_ast,e.eexpr with + | EField(e1,s),TField(e2,_) -> + display_fields e1 e2 (String.length s) + | _ -> + if dk = DKDot then display_fields e_ast e 0 + else begin + let name = try String.concat "." (string_list_of_expr_path_raise e_ast) with Exit -> "" in + let name = if name = "null" then "" else name in + raise_toplevel ctx dk with_type (name,pos e_ast) None + end + end + | DMDefault | DMNone | DMModuleSymbols _ | DMDiagnostics _ | DMStatistics -> + let fields = DisplayFields.collect ctx e_ast e dk with_type p in + let item = completion_item_of_expr ctx e in + let iterator = try + let it = (ForLoop.IterationKind.of_texpr ~resume:true ctx e (fun _ -> false) e.epos) in + match follow it.it_type with + | TDynamic _ -> None + | t -> Some t + with Error _ | Not_found -> + None + in + let keyValueIterator = + try begin + let _,pt = ForLoop.IterationKind.check_iterator ~resume:true ctx "keyValueIterator" e e.epos in + match follow pt with + | TAnon a -> + let key = PMap.find "key" a.a_fields in + let value = PMap.find "value" a.a_fields in + Some (key.cf_type,value.cf_type) + | _ -> + None + end with Error _ | Not_found -> + None + in + raise_fields fields (CRField(item,e.epos,iterator,keyValueIterator)) None + +let handle_structure_display ctx e fields origin = + let p = pos e in + let fields = PMap.foldi (fun _ cf acc -> cf :: acc) fields [] in + let fields = List.sort (fun cf1 cf2 -> -compare cf1.cf_pos.pmin cf2.cf_pos.pmin) fields in + let tpair ?(values=PMap.empty) t = + let ct = DisplayEmitter.completion_type_of_type ctx ~values t in + (t,ct) + in + match fst e with + | EObjectDecl fl -> + let fields = List.fold_left (fun acc cf -> + if Expr.field_mem_assoc cf.cf_name fl then acc + else (make_ci_class_field (CompletionClassField.make cf CFSMember origin true) (tpair ~values:(get_value_meta cf.cf_meta) cf.cf_type)) :: acc + ) [] fields in + raise_fields fields CRStructureField None + | EBlock [] -> + let fields = List.fold_left (fun acc cf -> + make_ci_class_field (CompletionClassField.make cf CFSMember origin true) (tpair ~values:(get_value_meta cf.cf_meta) cf.cf_type) :: acc + ) [] fields in + raise_fields fields CRStructureField None + | _ -> + error "Expected object expression" p + +let handle_display ?resume_typing ctx e_ast dk with_type = + let old = ctx.in_display,ctx.in_call_args in + ctx.in_display <- true; + ctx.in_call_args <- false; + let tpair t = + let ct = DisplayEmitter.completion_type_of_type ctx t in + (t,ct) + in + let e = match e_ast,with_type with + | (EConst (Ident "$type"),p),_ -> + display_dollar_type ctx p tpair + | (EConst (Ident "trace"),_),_ -> + let doc = Some "Print given arguments" in + let arg = ["value",false,t_dynamic] in + let ret = ctx.com.basic.tvoid in + let p = pos e_ast in + begin match ctx.com.display.dms_kind with + | DMSignature -> + raise_signatures [(convert_function_signature ctx PMap.empty (arg,ret),doc)] 0 0 SKCall + | DMHover -> + let t = TFun(arg,ret) in + raise_hover (make_ci_expr (mk (TIdent "trace") t p) (tpair t)) (Some (WithType.named_argument "value")) p + | DMDefinition | DMTypeDefinition -> + raise_positions [] + | _ -> + error "Unsupported method" p + end + | (EConst (Ident "_"),p),WithType.WithType(t,_) -> + mk (TConst TNull) t p (* This is "probably" a bind skip, let's just use the expected type *) + | (_,p),_ -> try + match resume_typing with + | None -> type_expr ctx e_ast with_type + | Some fn -> fn ctx e_ast with_type + with Error (Unknown_ident n,_) when ctx.com.display.dms_kind = DMDefault -> + if dk = DKDot && ctx.com.json_out = None then raise (Parser.TypePath ([n],None,false,p)) + else raise_toplevel ctx dk with_type (n,p) (Some p) + | Error ((Type_not_found (path,_) | Module_not_found path),_) as err when ctx.com.display.dms_kind = DMDefault -> + if ctx.com.json_out = None then begin try + raise_fields (DisplayFields.get_submodule_fields ctx path) (CRField((make_ci_module path),p,None,None)) None + with Not_found -> + raise err + end else + raise_toplevel ctx dk with_type (s_type_path path,p) (Some p) + | DisplayException(DisplayFields Some({fkind = CRTypeHint} as r)) when (match fst e_ast with ENew _ -> true | _ -> false) -> + let timer = Timer.timer ["display";"toplevel";"filter ctors"] in + ctx.pass <- PBuildClass; + let l = List.filter (fun item -> + let is_private_to_current_module mt = + (* Remove the _Module nonsense from the package *) + let pack = List.rev (List.tl (List.rev mt.pack)) in + (pack,mt.module_name) = ctx.m.curmod.m_path + in + match item.ci_kind with + | ITType({kind = (Class | Abstract | TypeAlias)} as mt,_) when not mt.is_private || is_private_to_current_module mt -> + begin match mt.has_constructor with + | Yes -> true + | YesButPrivate -> + if (Meta.has Meta.PrivateAccess ctx.meta) then true + else begin + let path = (mt.pack,mt.name) in + let rec loop c = + if c.cl_path = path then true + else match c.cl_super with + | Some(c,_) -> loop c + | None -> false + in + loop ctx.curclass + end + | No -> false + | Maybe -> + begin try + let mt = ctx.g.do_load_type_def ctx null_pos {tpackage=mt.pack;tname=mt.module_name;tsub=Some mt.name;tparams=[]} in + begin match resolve_typedef mt with + | TClassDecl c when has_constructor c -> true + | TAbstractDecl {a_impl = Some c} -> + ignore(c.cl_build()); + PMap.mem "_new" c.cl_statics + | _ -> false + end + with _ -> + false + end + end + | ITTypeParameter {cl_kind = KTypeParameter tl} when get_constructible_constraint ctx tl null_pos <> None -> + true + | _ -> false + ) r.fitems in + timer(); + raise_fields l CRNew r.finsert_pos + in + let e = match e.eexpr with + | TField(e1,FDynamic "bind") when (match follow e1.etype with TFun _ -> true | _ -> false) -> e1 + | _ -> e + in + let is_display_debug = Meta.has (Meta.Custom ":debug.display") ctx.curfield.cf_meta in + if is_display_debug then begin + print_endline (Printf.sprintf "expected type: %s" (WithType.to_string with_type)); + print_endline (Printf.sprintf "typed expr:\n%s" (s_expr_ast true "" (s_type (print_context())) e)); + end; + let p = e.epos in + begin match with_type with + | WithType.WithType(t,_) -> + (* We don't want to actually use the transformed expression which may have inserted implicit cast calls. + It only matters that unification takes place. *) + (try ignore(AbstractCast.cast_or_unify_raise ctx t e e.epos) with Error (Unify l,p) -> ()); + | _ -> + () + end; + if is_display_debug then begin + print_endline (Printf.sprintf "cast expr:\n%s" (s_expr_ast true "" (s_type (print_context())) e)); + end; + ctx.in_display <- fst old; + ctx.in_call_args <- snd old; + display_expr ctx e_ast e dk with_type p + +let handle_edisplay ?resume_typing ctx e dk with_type = + let handle_display ctx e dk with_type = + match resume_typing with + | Some resume_typing -> handle_display ~resume_typing ctx e dk with_type + | None -> handle_display ctx e dk with_type + in + match dk,ctx.com.display.dms_kind with + | DKCall,(DMSignature | DMDefault) -> handle_signature_display ctx e with_type + | DKStructure,DMDefault -> + begin match with_type with + | WithType.WithType(t,_) -> + begin match follow t with + | TAnon an -> + let origin = match t with + | TType(td,_) -> Self (TTypeDecl td) + | _ -> AnonymousStructure an + in + handle_structure_display ctx e an.a_fields origin + | TInst(c,tl) when Meta.has Meta.StructInit c.cl_meta -> + let fields = PMap.map (fun cf -> {cf with cf_type = apply_params c.cl_params tl cf.cf_type}) c.cl_fields in + handle_structure_display ctx e fields (Self (TClassDecl c)) + | _ -> handle_display ctx e dk with_type + end + | _ -> + handle_display ctx e dk with_type + end + | DKPattern outermost,DMDefault -> + begin try + handle_display ctx e dk with_type + with DisplayException(DisplayFields Some({fkind = CRToplevel _} as r)) -> + raise_fields r.fitems (CRPattern ((get_expected_type ctx with_type),outermost)) r.finsert_pos + end + | _ -> handle_display ctx e dk with_type \ No newline at end of file diff --git a/std/Any.hx b/std/Any.hx index e40221002fd..d5bc429d8a3 100644 --- a/std/Any.hx +++ b/std/Any.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,7 +32,12 @@ to another type. **/ abstract Any(Dynamic) { - @:noCompletion @:extern @:to inline function __promote():T return this; - @:noCompletion @:extern @:from inline static function __cast(value:T):Any return cast value; - @:noCompletion @:extern inline function toString():String return Std.string(this); + @:noCompletion @:to extern inline function __promote():T + return this; + + @:noCompletion @:from extern inline static function __cast(value:T):Any + return cast value; + + @:noCompletion extern inline function toString():String + return Std.string(this); } diff --git a/std/Array.hx b/std/Array.hx index d1e07538171..968bb774233 100644 --- a/std/Array.hx +++ b/std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + /** An Array is a storage for values. You can access it using indexes or with its API. @@ -27,16 +28,15 @@ @see https://haxe.org/manual/lf-array-comprehension.html **/ extern class Array { - /** The length of `this` Array. **/ - var length(default,null) : Int; + var length(default, null):Int; /** Creates a new Array. **/ - function new() : Void; + function new():Void; /** Returns a new Array by appending the elements of `a` to the elements of @@ -51,7 +51,7 @@ extern class Array { If `a` is `null`, the result is unspecified. **/ - function concat( a : Array ) : Array; + function concat(a:Array):Array; /** Returns a string representation of `this` Array, with `sep` separating @@ -66,7 +66,7 @@ extern class Array { If `sep` is null, the result is unspecified. **/ - function join( sep : String ) : String; + function join(sep:String):String; /** Removes the last element of `this` Array and returns it. @@ -78,7 +78,7 @@ extern class Array { If `this` is the empty Array `[]`, null is returned and the length remains 0. **/ - function pop() : Null; + function pop():Null; /** Adds the element `x` at the end of `this` Array and returns the new @@ -88,7 +88,7 @@ extern class Array { `this.length` increases by 1. **/ - function push(x : T) : Int; + function push(x:T):Int; /** Reverse the order of elements of `this` Array. @@ -97,7 +97,7 @@ extern class Array { If `this.length < 2`, `this` remains unchanged. **/ - function reverse() : Void; + function reverse():Void; /** Removes the first element of `this` Array and returns it. @@ -110,7 +110,7 @@ extern class Array { If `this` is the empty Array `[]`, `null` is returned and the length remains 0. **/ - function shift() : Null; + function shift():Null; /** Creates a shallow copy of the range of `this` Array, starting at and @@ -130,7 +130,7 @@ extern class Array { If `pos` exceeds `this.length` or if `end` is less than or equals `pos`, the result is `[]`. **/ - function slice( pos : Int, ?end : Int ) : Array; + function slice(pos:Int, ?end:Int):Array; /** Sorts `this` Array according to the comparison function `f`, where @@ -145,7 +145,7 @@ extern class Array { If `f` is null, the result is unspecified. **/ - function sort( f : T -> T -> Int ) : Void; + function sort(f:T->T->Int):Void; /** Removes `len` elements from `this` Array, starting at and including @@ -153,7 +153,7 @@ extern class Array { This operation modifies `this` Array in place. - If `len` is < 0 or `pos` exceeds `this`.length, an empty Array [] is + If `len` is < 0 or `pos` exceeds `this`.length, an empty Array [] is returned and `this` Array is unchanged. If `pos` is negative, its value is calculated from the end of `this` @@ -169,7 +169,7 @@ extern class Array { words, each element of the original `this` Array either remains in `this` Array or becomes an element of the returned Array. **/ - function splice( pos : Int, len : Int ) : Array; + function splice(pos:Int, len:Int):Array; /** Returns a string representation of `this` Array. @@ -179,7 +179,7 @@ extern class Array { use `Std.string()` to get a String representation that is consistent across platforms. **/ - function toString() : String; + function toString():String; /** Adds the element `x` at the start of `this` Array. @@ -188,7 +188,7 @@ extern class Array { `this.length` and the index of each Array element increases by 1. **/ - function unshift( x : T ) : Void; + function unshift(x:T):Void; /** Inserts the element `x` at the position `pos`. @@ -207,7 +207,7 @@ extern class Array { and including that offset to the end of `this` Array are moved one index ahead. **/ - function insert( pos : Int, x : T ) : Void; + function insert(pos:Int, x:T):Void; /** Removes the first occurrence of `x` in `this` Array. @@ -221,7 +221,7 @@ extern class Array { If `x` is not found, `this` Array is not changed and the function returns false. **/ - function remove( x : T ) : Bool; + function remove(x:T):Bool; /** Returns position of the first occurrence of `x` in `this` Array, searching front to back. @@ -236,7 +236,7 @@ extern class Array { starting index is less than 0, the whole array will be searched, if it is greater than or equal to the length of `this` Array, the function returns -1. **/ - function indexOf( x : T, ?fromIndex:Int ) : Int; + function indexOf(x:T, ?fromIndex:Int):Int; /** Returns position of the last occurrence of `x` in `this` Array, searching back to front. @@ -251,7 +251,7 @@ extern class Array { given or computed starting index is greater than or equal to the length of `this` Array, the whole array will be searched, if it is less than 0, the function returns -1. **/ - function lastIndexOf( x : T, ?fromIndex:Int ) : Int; + function lastIndexOf(x:T, ?fromIndex:Int):Int; /** Returns a shallow copy of `this` Array. @@ -260,12 +260,12 @@ extern class Array { `a[i] == a.copy()[i]` is true for any valid `i`. However, `a == a.copy()` is always false. **/ - function copy() : Array; + function copy():Array; /** Returns an iterator of the Array values. **/ - function iterator() : Iterator; + function iterator():Iterator; /** Creates a new Array by applying function `f` to all elements of `this`. @@ -274,7 +274,7 @@ extern class Array { If `f` is null, the result is unspecified. **/ - @:runtime inline function map( f : T -> S ) : Array { + @:runtime inline function map(f:T->S):Array { #if cpp var result = cpp.NativeArray.create(length); for (i in 0...length) cpp.NativeArray.unsafeSet(result, i, f(cpp.NativeArray.unsafeGet(this, i))); @@ -292,7 +292,21 @@ extern class Array { If `f` is null, the result is unspecified. **/ - @:runtime inline function filter( f : T -> Bool ) : Array { + @:runtime inline function filter(f:T->Bool):Array { return [for (v in this) if (f(v)) v]; } + + /** + Set the length of the Array. + + If `len` is shorter than the array's current size, the last + `length - len` elements will be removed. If `len` is longer, the Array + will be extended, with new elements set to a target-specific default + value: + + - always null on dynamic targets + - 0, 0.0 or false for Int, Float and Bool respectively on static targets + - null for other types on static targets + **/ + function resize(len:Int):Void; } diff --git a/std/Class.hx b/std/Class.hx index 5eb31102a84..73d91c3504a 100644 --- a/std/Class.hx +++ b/std/Class.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + /** An abstract type that represents a Class. @@ -26,5 +27,4 @@ @see https://haxe.org/manual/types-class-instance.html **/ -@:coreType @:runtimeValue abstract Class { -} +@:coreType @:runtimeValue abstract Class {} diff --git a/std/Date.hx b/std/Date.hx index cd4abd53cc9..309b340a74c 100644 --- a/std/Date.hx +++ b/std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ - /** +/** The Date class provides a basic structure for date and time related information. Date instances can be created by @@ -32,143 +32,152 @@ There are some extra functions available in the `DateTools` class. In the context of Haxe dates, a timestamp is defined as the number of - milliseconds elapsed since 1st January 1970. + milliseconds elapsed since 1st January 1970 UTC. + + ## Supported range + + Due to platform limitations, only dates in the range 1970 through 2038 are + supported consistently. Some targets may support dates outside this range, + depending on the OS at runtime. The `Date.fromTime` method will not work with + timestamps outside the range on any target. **/ -extern class Date -{ +extern class Date { /** Creates a new date object from the given arguments. The behaviour of a Date instance is only consistent across platforms if the the arguments describe a valid date. - - month: 0 to 11 + - month: 0 to 11 (note that this is zero-based) - day: 1 to 31 - hour: 0 to 23 - min: 0 to 59 - sec: 0 to 59 **/ - function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void; + function new(year:Int, month:Int, day:Int, hour:Int, min:Int, sec:Int):Void; + + /** + Returns the timestamp (in milliseconds) of `this` date. + On cpp and neko, this function only has a second resolution, so the + result will always be a multiple of `1000.0`, e.g. `1454698271000.0`. + To obtain the current timestamp with better precision on cpp and neko, + see the `Sys.time` API. + + For measuring time differences with millisecond accuracy on + all platforms, see `haxe.Timer.stamp`. + **/ + function getTime():Float; + + /** + Returns the hours of `this` Date (0-23 range) in the local timezone. + **/ + function getHours():Int; + + /** + Returns the minutes of `this` Date (0-59 range) in the local timezone. + **/ + function getMinutes():Int; + + /** + Returns the seconds of `this` Date (0-59 range) in the local timezone. + **/ + function getSeconds():Int; /** - Returns the timestamp (in milliseconds) of the date. It might - only have a per-second precision depending on the platforms. + Returns the full year of `this` Date (4 digits) in the local timezone. **/ - function getTime() : Float; + function getFullYear():Int; /** - Returns the hours of `this` Date (0-23 range). + Returns the month of `this` Date (0-11 range) in the local timezone. + Note that the month number is zero-based. **/ - function getHours() : Int; + function getMonth():Int; /** - Returns the minutes of `this` Date (0-59 range). + Returns the day of `this` Date (1-31 range) in the local timezone. **/ - function getMinutes() : Int; + function getDate():Int; /** - Returns the seconds of `this` Date (0-59 range). + Returns the day of the week of `this` Date (0-6 range, where `0` is Sunday) + in the local timezone. **/ - function getSeconds() : Int; + function getDay():Int; /** - Returns the full year of `this` Date (4-digits). + Returns the hours of `this` Date (0-23 range) in UTC. **/ - function getFullYear() : Int; + function getUTCHours():Int; /** - Returns the month of `this` Date (0-11 range). + Returns the minutes of `this` Date (0-59 range) in UTC. **/ - function getMonth() : Int; + function getUTCMinutes():Int; /** - Returns the day of `this` Date (1-31 range). + Returns the seconds of `this` Date (0-59 range) in UTC. **/ - function getDate() : Int; + function getUTCSeconds():Int; /** - Returns the day of the week of `this` Date (0-6 range) where `0` is Sunday. + Returns the full year of `this` Date (4 digits) in UTC. **/ - function getDay() : Int; + function getUTCFullYear():Int; /** - Returns a string representation of `this` Date, by using the - standard format [YYYY-MM-DD HH:MM:SS]. See `DateTools.format` for - other formating rules. + Returns the month of `this` Date (0-11 range) in UTC. + Note that the month number is zero-based. + **/ + function getUTCMonth():Int; + + /** + Returns the day of `this` Date (1-31 range) in UTC. + **/ + function getUTCDate():Int; + + /** + Returns the day of the week of `this` Date (0-6 range, where `0` is Sunday) + in UTC. + **/ + function getUTCDay():Int; + + /** + Returns the time zone difference of `this` Date in the current locale + to UTC, in minutes. + + Assuming the function is executed on a machine in a UTC+2 timezone, + `Date.now().getTimezoneOffset()` will return `-120`. + **/ + function getTimezoneOffset():Int; + + /** + Returns a string representation of `this` Date in the local timezone + using the standard format `YYYY-MM-DD HH:MM:SS`. See `DateTools.format` for + other formatting rules. **/ function toString():String; /** Returns a Date representing the current local time. **/ - static function now() : Date; + static function now():Date; /** - Returns a Date from timestamp (in milliseconds) `t`. + Creates a Date from the timestamp (in milliseconds) `t`. **/ - static function fromTime( t : Float ) : Date; + static function fromTime(t:Float):Date; /** - Returns a Date from a formatted string `s`, with the following accepted - formats: + Creates a Date from the formatted string `s`. The following formats are + accepted by the function: - `"YYYY-MM-DD hh:mm:ss"` - `"YYYY-MM-DD"` - `"hh:mm:ss"` - The first two formats are expressed in local time, the third in UTC - Epoch. - **/ - static function fromString( s : String ) : Date; - - -#if flash - private static function __init__() : Void untyped { - var d : Dynamic = Date; - d.now = function() { - return __new__(Date); - }; - d.fromTime = function(t){ - var d : Date = __new__(Date); - d.setTime(t); - return d; - }; - d.fromString = function(s : String) { - switch( s.length ) { - case 8: // hh:mm:ss - var k = s.split(":"); - var d : Date = __new__(Date); - d.setTime(0); - d.setUTCHours(k[0]); - d.setUTCMinutes(k[1]); - d.setUTCSeconds(k[2]); - return d; - case 10: // YYYY-MM-DD - var k = s.split("-"); - return new Date(cast k[0],cast k[1] - 1,cast k[2],0,0,0); - case 19: // YYYY-MM-DD hh:mm:ss - var k = s.split(" "); - var y = k[0].split("-"); - var t = k[1].split(":"); - return new Date(cast y[0],cast y[1] - 1,cast y[2],cast t[0],cast t[1],cast t[2]); - default: - throw "Invalid date format : " + s; - } - }; - d.prototype[#if (as3 || no_flash_override) "toStringHX" #else "toString" #end] = function() { - var date : Date = __this__; - var m = date.getMonth() + 1; - var d = date.getDate(); - var h = date.getHours(); - var mi = date.getMinutes(); - var s = date.getSeconds(); - return date.getFullYear() - +"-"+(if( m < 10 ) "0"+m else ""+m) - +"-"+(if( d < 10 ) "0"+d else ""+d) - +" "+(if( h < 10 ) "0"+h else ""+h) - +":"+(if( mi < 10 ) "0"+mi else ""+mi) - +":"+(if( s < 10 ) "0"+s else ""+s); - }; - } -#end + The first two formats expressed a date in local time. The third is a time + relative to the UTC epoch. + **/ + static function fromString(s:String):Date; } diff --git a/std/DateTools.hx b/std/DateTools.hx index f7578bd97c3..c22afda95d8 100644 --- a/std/DateTools.hx +++ b/std/DateTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,93 +28,99 @@ milliseconds elapsed since 1st January 1970. **/ class DateTools { - #if php #elseif (neko && !(macro || interp)) - static var date_format = neko.Lib.load("std","date_format",2); + static var date_format = neko.Lib.load("std", "date_format", 2); #else static var DAY_SHORT_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; static var DAY_NAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; - static var MONTH_SHORT_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - static var MONTH_NAMES = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; - - private static function __format_get( d : Date, e : String ) : String { - return switch( e ){ + static var MONTH_SHORT_NAMES = [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + ]; + static var MONTH_NAMES = [ + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ]; + + private static function __format_get(d:Date, e:String):String { + return switch (e) { case "%": "%"; case "a": DAY_SHORT_NAMES[d.getDay()]; case "A": DAY_NAMES[d.getDay()]; - case "b","h": + case "b", "h": MONTH_SHORT_NAMES[d.getMonth()]; case "B": MONTH_NAMES[d.getMonth()]; case "C": - untyped StringTools.lpad(Std.string(Std.int(d.getFullYear()/100)),"0",2); + untyped StringTools.lpad(Std.string(Std.int(d.getFullYear() / 100)), "0", 2); case "d": - untyped StringTools.lpad(Std.string(d.getDate()),"0",2); + untyped StringTools.lpad(Std.string(d.getDate()), "0", 2); case "D": - __format(d,"%m/%d/%y"); + __format(d, "%m/%d/%y"); case "e": untyped Std.string(d.getDate()); case "F": - __format(d,"%Y-%m-%d"); - case "H","k": - untyped StringTools.lpad(Std.string(d.getHours()),if( e == "H" ) "0" else " ",2); - case "I","l": - var hour = d.getHours()%12; - untyped StringTools.lpad(Std.string(hour == 0 ? 12 : hour),if( e == "I" ) "0" else " ",2); + __format(d, "%Y-%m-%d"); + case "H", "k": + untyped StringTools.lpad(Std.string(d.getHours()), if (e == "H") "0" else " ", 2); + case "I", "l": + var hour = d.getHours() % 12; + untyped StringTools.lpad(Std.string(hour == 0 ? 12 : hour), if (e == "I") "0" else " ", 2); case "m": - untyped StringTools.lpad(Std.string(d.getMonth()+1),"0",2); + untyped StringTools.lpad(Std.string(d.getMonth() + 1), "0", 2); case "M": - untyped StringTools.lpad(Std.string(d.getMinutes()),"0",2); + untyped StringTools.lpad(Std.string(d.getMinutes()), "0", 2); case "n": "\n"; case "p": - untyped if( d.getHours() > 11 ) "PM"; else "AM"; + untyped if (d.getHours() > 11) "PM"; else "AM"; case "r": - __format(d,"%I:%M:%S %p"); + __format(d, "%I:%M:%S %p"); case "R": - __format(d,"%H:%M"); + __format(d, "%H:%M"); case "s": - Std.string(Std.int(d.getTime()/1000)); + Std.string(Std.int(d.getTime() / 1000)); case "S": - untyped StringTools.lpad(Std.string(d.getSeconds()),"0",2); + untyped StringTools.lpad(Std.string(d.getSeconds()), "0", 2); case "t": "\t"; case "T": - __format(d,"%H:%M:%S"); + __format(d, "%H:%M:%S"); case "u": - untyped{ + untyped { var t = d.getDay(); - if( t == 0 ) "7"; else Std.string(t); + if (t == 0) + "7"; + else + Std.string(t); } case "w": untyped Std.string(d.getDay()); case "y": - untyped StringTools.lpad(Std.string(d.getFullYear()%100),"0",2); + untyped StringTools.lpad(Std.string(d.getFullYear() % 100), "0", 2); case "Y": untyped Std.string(d.getFullYear()); default: - throw "Date.format %"+e+"- not implemented yet."; + throw "Date.format %" + e + "- not implemented yet."; } } - private static function __format( d : Date, f : String ) : String { + private static function __format(d:Date, f:String):String { var r = new StringBuf(); var p = 0; - while( true ){ + while (true) { var np = f.indexOf("%", p); - if( np < 0 ) + if (np < 0) break; - r.addSub(f,p,np-p); - r.add( __format_get(d, f.substr(np+1,1) ) ); + r.addSub(f, p, np - p); + r.add(__format_get(d, f.substr(np + 1, 1))); - p = np+2; + p = np + 2; } - r.addSub(f,p,f.length-p); + r.addSub(f, p, f.length - p); return r.toString(); } #end @@ -140,13 +146,13 @@ class DateTools { // 2016-07-08 ``` **/ - public static function format( d : Date, f : String ) : String { + public static function format(d:Date, f:String):String { #if (neko && !(macro || interp)) - return new String(untyped date_format(d.__t, f.__s)); + return new String(untyped date_format(d.__t, f.__s)); #elseif php - return untyped __call__("strftime",f,d.__t); + return php.Global.strftime(f, php.Syntax.int(@:privateAccess d.__t)); #else - return __format(d,f); + return __format(d, f); #end } @@ -156,8 +162,8 @@ class DateTools { This is a convenience function for calling `Date.fromTime(d.getTime() + t)`. **/ - public static inline function delta( d : Date, t : Float ) : Date { - return Date.fromTime( d.getTime() + t ); + public static inline function delta(d:Date, t:Float):Date { + return Date.fromTime(d.getTime() + t); } static var DAYS_OF_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; @@ -167,7 +173,7 @@ class DateTools { This method handles leap years. **/ - public static function getMonthDays( d : Date ) : Int { + public static function getMonthDays(d:Date):Int { var month = d.getMonth(); var year = d.getFullYear(); @@ -181,51 +187,57 @@ class DateTools { /** Converts a number of seconds to a timestamp. **/ - public static inline function seconds( n : Float ) : Float { + public static inline function seconds(n:Float):Float { return n * 1000.0; } /** Converts a number of minutes to a timestamp. **/ - #if as3 @:extern #end public static inline function minutes( n : Float ) : Float { + #if as3 extern #end public static inline function minutes(n:Float):Float { return n * 60.0 * 1000.0; } /** Converts a number of hours to a timestamp. **/ - public static inline function hours( n : Float ) : Float { + public static inline function hours(n:Float):Float { return n * 60.0 * 60.0 * 1000.0; } /** Converts a number of days to a timestamp. **/ - public static inline function days( n : Float ) : Float { + public static inline function days(n:Float):Float { return n * 24.0 * 60.0 * 60.0 * 1000.0; } /** Separate a date-time into several components **/ - public static function parse( t : Float ) { + public static function parse(t:Float) { var s = t / 1000; var m = s / 60; var h = m / 60; return { - ms : t % 1000, - seconds : Std.int(s % 60), - minutes : Std.int(m % 60), - hours : Std.int(h % 24), - days : Std.int(h / 24), + ms: t % 1000, + seconds: Std.int(s % 60), + minutes: Std.int(m % 60), + hours: Std.int(h % 24), + days: Std.int(h / 24), }; } /** Build a date-time from several components **/ - public static function make( o : { ms : Float, seconds : Int, minutes : Int, hours : Int, days : Int } ) { + public static function make(o:{ + ms:Float, + seconds:Int, + minutes:Int, + hours:Int, + days:Int + }) { return o.ms + 1000.0 * (o.seconds + 60.0 * (o.minutes + 60.0 * (o.hours + 24.0 * o.days))); } @@ -233,16 +245,16 @@ class DateTools { /** Retrieve Unix timestamp value from Date components. Takes same argument sequence as the Date constructor. **/ - public static #if (js || flash || php) inline #end function makeUtc(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ):Float { - #if (js || flash || python) - return untyped Date.UTC(year, month, day, hour, min, sec); + public static #if (js || flash || php) inline #end function makeUtc(year:Int, month:Int, day:Int, hour:Int, min:Int, sec:Int):Float { + #if (js || flash || python) + return untyped Date.UTC(year, month, day, hour, min, sec); #elseif php - return untyped __call__("gmmktime", hour, min, sec, month + 1, day, year) * 1000; + return php.Global.gmmktime(hour, min, sec, month + 1, day, year) * 1000; #elseif cpp - return untyped __global__.__hxcpp_utc_date(year,month,day,hour,min,sec)*1000.0 ; + return untyped __global__.__hxcpp_utc_date(year, month, day, hour, min, sec) * 1000.0; #else - //TODO - return 0.; + // TODO + return 0.; #end } #end diff --git a/std/EReg.hx b/std/EReg.hx index 5b2daacd041..ba33b85b9a1 100644 --- a/std/EReg.hx +++ b/std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -37,7 +37,6 @@ **/ class EReg { - /** Creates a new regular expression with pattern `r` and modifiers `opt`. @@ -45,7 +44,7 @@ class EReg { If `r` or `opt` are null, the result is unspecified. **/ - public function new( r : String, opt : String ) { + public function new(r:String, opt:String) { throw "Regular expressions are not implemented for this platform"; } @@ -56,7 +55,7 @@ class EReg { If `s` is `null`, the result is unspecified. **/ - public function match( s : String ) : Bool { + public function match(s:String):Bool { return false; } @@ -67,11 +66,11 @@ class EReg { `this.matchSub`, and then operates on the String of that operation. The index `n` corresponds to the n-th set of parentheses in the pattern - of `this` EReg. If no such sub-group exists, an exception is thrown. + of `this` EReg. If no such sub-group exists, the result is unspecified. If `n` equals 0, the whole matched substring is returned. **/ - public function matched( n : Int ) : String { + public function matched(n:Int):String { return null; } @@ -86,7 +85,7 @@ class EReg { The result does not include the matched part. **/ - public function matchedLeft() : String { + public function matchedLeft():String { return null; } @@ -101,7 +100,7 @@ class EReg { The result does not include the matched part. **/ - public function matchedRight() : String { + public function matchedRight():String { return null; } @@ -116,7 +115,7 @@ class EReg { If the global g modifier was in place for the matching, the position and length of the leftmost substring is returned. **/ - public function matchedPos() : { pos : Int, len : Int } { + public function matchedPos():{pos:Int, len:Int} { return null; } @@ -131,7 +130,7 @@ class EReg { If `s` is null, the result is unspecified. **/ - public function matchSub( s : String, pos : Int, len : Int = -1):Bool { + public function matchSub(s:String, pos:Int, len:Int = -1):Bool { return false; } @@ -153,7 +152,7 @@ class EReg { If `s` is null, the result is unspecified. **/ - public function split( s : String ) : Array { + public function split(s:String):Array { return null; } @@ -171,7 +170,7 @@ class EReg { If `s` or `by` are null, the result is unspecified. **/ - public function replace( s : String, by : String ) : String { + public function replace(s:String, by:String):String { return null; } @@ -189,7 +188,7 @@ class EReg { If `s` or `f` are null, the result is unspecified. **/ - public function map( s : String, f : EReg -> String ) : String { + public function map(s:String, f:EReg->String):String { return null; } @@ -198,7 +197,7 @@ class EReg { If `s` is null, the result is unspecified. **/ - public static function escape( s : String ) : String { + public static function escape(s:String):String { return null; } } diff --git a/std/Enum.hx b/std/Enum.hx index 8748bf94ebe..12f9a1f2aed 100644 --- a/std/Enum.hx +++ b/std/Enum.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -29,5 +29,4 @@ @see https://haxe.org/manual/types-enum-instance.html **/ -@:coreType @:runtimeValue abstract Enum { -} +@:coreType @:runtimeValue abstract Enum {} diff --git a/std/EnumValue.hx b/std/EnumValue.hx index eca6d58d484..7297d0b734e 100644 --- a/std/EnumValue.hx +++ b/std/EnumValue.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,4 +27,35 @@ @see https://haxe.org/manual/types-enum-instance.html **/ @:coreType abstract EnumValue { + /** + Matches enum instance `e` against pattern `pattern`, returning `true` if + matching succeeded and `false` otherwise. + + Example usage: + + ```haxe + if (e.match(pattern)) { + // codeIfTrue + } else { + // codeIfFalse + } + ``` + + This is equivalent to the following code: + + ```haxe + switch (e) { + case pattern: + // codeIfTrue + case _: + // codeIfFalse + } + ``` + + This method is implemented in the compiler. This definition exists only + for documentation. + **/ + public function match(pattern:Dynamic):Bool { + return false; + } } diff --git a/std/IntIterator.hx b/std/IntIterator.hx index 64705e2b5bd..f87bc09644f 100644 --- a/std/IntIterator.hx +++ b/std/IntIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ - /** +/** IntIterator is used for implementing interval iterations. It is usually not used explicitly, but through its special syntax: @@ -34,16 +34,15 @@ @see https://haxe.org/manual/lf-iterators.html **/ class IntIterator { - - var min : Int; - var max : Int; + var min:Int; + var max:Int; /** Iterates from `min` (inclusive) to `max` (exclusive). If `max <= min`, the iterator will not act as a countdown. **/ - public inline function new( min : Int, max : Int ) { + public inline function new(min:Int, max:Int) { this.min = min; this.max = max; } @@ -63,5 +62,4 @@ class IntIterator { public inline function next() { return min++; } - } diff --git a/std/Lambda.hx b/std/Lambda.hx index f7c93e39d76..e3f95eb800c 100644 --- a/std/Lambda.hx +++ b/std/Lambda.hx @@ -1,6 +1,5 @@ -import haxe.ds.List; /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,6 +20,8 @@ import haxe.ds.List; * DEALINGS IN THE SOFTWARE. */ +import haxe.ds.List; + /** The `Lambda` class is a collection of methods to support functional programming. It is ideally used with `using Lambda` and then acts as an @@ -35,18 +36,15 @@ import haxe.ds.List; @see https://haxe.org/manual/std-Lambda.html **/ - class Lambda { - - /** Creates an Array from Iterable `it`. If `it` is an Array, this function returns a copy of it. **/ - public static function array( it : Iterable ) : Array { + public static function array(it:Iterable):Array { var a = new Array(); - for(i in it) + for (i in it) a.push(i); return a; } @@ -56,63 +54,46 @@ class Lambda { If `it` is a List, this function returns a copy of it. **/ - public static function list( it : Iterable ) : List { + public static function list(it:Iterable):List { var l = new List(); - for(i in it) + for (i in it) l.add(i); return l; } /** - Creates a new List by applying function `f` to all elements of `it`. - + Creates a new Array by applying function `f` to all elements of `it`. The order of elements is preserved. - If `f` is null, the result is unspecified. **/ - public static function map( it : Iterable, f : A -> B ) : List { - var l = new List(); - for( x in it ) - l.add(f(x)); - return l; + public static inline function map(it:Iterable, f:(item:A) -> B):Array { + return [for (x in it) f(x)]; } /** Similar to map, but also passes the index of each element to `f`. - The order of elements is preserved. - If `f` is null, the result is unspecified. **/ - public static function mapi( it : Iterable, f : Int -> A -> B ) : List { - var l = new List(); + public static inline function mapi(it:Iterable, f:(index:Int, item:A) -> B):Array { var i = 0; - for( x in it ) - l.add(f(i++,x)); - return l; + return [for (x in it) f(i++, x)]; } /** - Concatenate a list of lists. - + Concatenate a list of iterables. The order of elements is preserved. **/ - public static function flatten( it : Iterable> ) : List { - var l = new List(); - for (e in it) - for (x in e) - l.add(x); - return l; + public static inline function flatten(it:Iterable>):Array { + return [for (e in it) for (x in e) x]; } /** A composition of map and flatten. - The order of elements is preserved. - If `f` is null, the result is unspecified. **/ - public static function flatMap( it : Iterable, f: A -> Iterable ) : List { + public static inline function flatMap(it:Iterable, f:(item:A) -> Iterable):Array { return Lambda.flatten(Lambda.map(it, f)); } @@ -124,9 +105,9 @@ class Lambda { If no such element is found, the result is false. **/ - public static function has( it : Iterable, elt : A ) : Bool { - for( x in it ) - if( x == elt ) + public static function has(it:Iterable, elt:A):Bool { + for (x in it) + if (x == elt) return true; return false; } @@ -141,9 +122,9 @@ class Lambda { If `f` is null, the result is unspecified. **/ - public static function exists( it : Iterable, f : A -> Bool ) { - for( x in it ) - if( f(x) ) + public static function exists(it:Iterable, f:(item:A) -> Bool) { + for (x in it) + if (f(x)) return true; return false; } @@ -160,9 +141,9 @@ class Lambda { If `f` is null, the result is unspecified. **/ - public static function foreach( it : Iterable, f : A -> Bool ) { - for( x in it ) - if( !f(x) ) + public static function foreach(it:Iterable, f:(item:A) -> Bool) { + for (x in it) + if (!f(x)) return false; return true; } @@ -172,25 +153,19 @@ class Lambda { If `f` is null, the result is unspecified. **/ - public static function iter( it : Iterable, f : A -> Void ) { - for( x in it ) + public static function iter(it:Iterable, f:(item:A) -> Void) { + for (x in it) f(x); } /** - Returns a List containing those elements of `it` for which `f` returned + Returns a Array containing those elements of `it` for which `f` returned true. - - If `it` is empty, the result is the empty List even if `f` is null. - + If `it` is empty, the result is the empty Array even if `f` is null. Otherwise if `f` is null, the result is unspecified. **/ - public static function filter( it : Iterable, f : A -> Bool ) { - var l = new List(); - for( x in it ) - if( f(x) ) - l.add(x); - return l; + public static function filter(it:Iterable, f:(item:A) -> Bool) { + return [for (x in it) if (f(x)) x]; } /** @@ -205,9 +180,9 @@ class Lambda { If `it` or `f` are null, the result is unspecified. **/ - public static function fold( it : Iterable, f : A -> B -> B, first : B ) : B { - for( x in it ) - first = f(x,first); + public static function fold(it:Iterable, f:(item:A, result:B) -> B, first:B):B { + for (x in it) + first = f(x, first); return first; } @@ -217,14 +192,14 @@ class Lambda { This function traverses all elements. **/ - public static function count( it : Iterable, ?pred : A -> Bool ) { + public static function count(it:Iterable, ?pred:(item:A) -> Bool) { var n = 0; - if( pred == null ) - for( _ in it ) + if (pred == null) + for (_ in it) n++; else - for( x in it ) - if( pred(x) ) + for (x in it) + if (pred(x)) n++; return n; } @@ -232,7 +207,7 @@ class Lambda { /** Tells if Iterable `it` does not contain any element. **/ - public static function empty( it : Iterable ) : Bool { + public static function empty(it:Iterable):Bool { return !it.iterator().hasNext(); } @@ -243,10 +218,10 @@ class Lambda { If `v` does not exist in `it`, the result is -1. **/ - public static function indexOf( it : Iterable, v : T ) : Int { + public static function indexOf(it:Iterable, v:T):Int { var i = 0; - for( v2 in it ) { - if( v == v2 ) + for (v2 in it) { + if (v == v2) return i; i++; } @@ -263,26 +238,26 @@ class Lambda { If `f` is null, the result is unspecified. **/ - public static function find( it : Iterable, f : T -> Bool ) : Null { - for( v in it ) { - if(f(v)) return v; + public static function find(it:Iterable, f:(item:T) -> Bool):Null { + for (v in it) { + if (f(v)) + return v; } return null; } /** - Returns a new List containing all elements of Iterable `a` followed by + Returns a new Array containing all elements of Iterable `a` followed by all elements of Iterable `b`. If `a` or `b` are null, the result is unspecified. **/ - public static function concat( a : Iterable, b : Iterable ) : List { - var l = new List(); - for( x in a ) - l.add(x); - for( x in b ) - l.add(x); + public static function concat(a:Iterable, b:Iterable):Array { + var l = new Array(); + for (x in a) + l.push(x); + for (x in b) + l.push(x); return l; } - } diff --git a/std/List.hx b/std/List.hx index 3fa8bd5c5c1..ee5b506794c 100644 --- a/std/List.hx +++ b/std/List.hx @@ -1 +1,22 @@ -typedef List = haxe.ds.List; \ No newline at end of file +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +typedef List = haxe.ds.List; diff --git a/std/Map.hx b/std/Map.hx index 9a7b167909a..4f38a916b91 100644 --- a/std/Map.hx +++ b/std/Map.hx @@ -1,5 +1,26 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ typedef Map = haxe.ds.Map; @:dox(hide) @:deprecated -typedef IMap = haxe.Constraints.IMap; \ No newline at end of file +typedef IMap = haxe.Constraints.IMap; diff --git a/std/Math.hx b/std/Math.hx index fe9402b375d..1fa4503afbd 100644 --- a/std/Math.hx +++ b/std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,20 +19,22 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + /** This class defines mathematical functions and constants. @see https://haxe.org/manual/std-math.html **/ -#if cpp @:include("hxMath.h") #end +#if cpp +@:include("hxMath.h") +#end @:pure -extern class Math -{ +extern class Math { /** Represents the ratio of the circumference of a circle to its diameter, specified by the constant, π. `PI` is approximately 3.141592653589793. **/ - static var PI(default,null) : Float; + static var PI(default, null):Float; /** A special `Float` constant which denotes negative infinity. @@ -45,7 +47,7 @@ extern class Math If this constant is converted to an `Int`, e.g. through `Std.int()`, the result is unspecified. **/ - static var NEGATIVE_INFINITY(default, null) : Float; + static var NEGATIVE_INFINITY(default, null):Float; /** A special `Float` constant which denotes positive infinity. @@ -58,7 +60,7 @@ extern class Math If this constant is converted to an `Int`, e.g. through `Std.int()`, the result is unspecified. **/ - static var POSITIVE_INFINITY(default,null) : Float; + static var POSITIVE_INFINITY(default, null):Float; /** A special `Float` constant which denotes an invalid number. @@ -74,7 +76,7 @@ extern class Math In order to test if a value is `NaN`, you should use `Math.isNaN()` function. **/ - static var NaN(default, null) : Float; + static var NaN(default, null):Float; /** Returns the absolute value of `v`. @@ -229,7 +231,7 @@ extern class Math Returns a pseudo-random number which is greater than or equal to 0.0, and less than 1.0. **/ - static function random() : Float; + static function random():Float; #if ((flash && !as3) || cpp || eval) /** @@ -238,7 +240,7 @@ extern class Math If `v` is is `NaN`, `NEGATIVE_INFINITY` or `POSITIVE_INFINITY`, the result is unspecified. **/ - static function ffloor( v : Float ) : Float; + static function ffloor(v:Float):Float; /** Returns the smallest integer value that is not less than `v`, as a `Float`. @@ -246,7 +248,7 @@ extern class Math If `v` is is `NaN`, `NEGATIVE_INFINITY` or `POSITIVE_INFINITY`, the result is unspecified. **/ - static function fceil( v : Float ) : Float; + static function fceil(v:Float):Float; /** Rounds `v` to the nearest integer value, as a Float. @@ -256,32 +258,28 @@ extern class Math If `v` is is `NaN`, `NEGATIVE_INFINITY` or `POSITIVE_INFINITY`, the result is unspecified. **/ - static function fround( v : Float ) : Float; - + static function fround(v:Float):Float; #else - - static inline function ffloor( v : Float ) : Float { + static inline function ffloor(v:Float):Float { return floor(v); } - static inline function fceil( v : Float ) : Float { + static inline function fceil(v:Float):Float { return ceil(v); } - static inline function fround( v : Float ) : Float { + static inline function fround(v:Float):Float { return round(v); } - #end - /** Tells if `f` is a finite number. If `f` is `POSITIVE_INFINITY`, `NEGATIVE_INFINITY` or `NaN`, the result is `false`, otherwise the result is `true`. **/ - static function isFinite( f : Float ) : Bool; + static function isFinite(f:Float):Bool; /** Tells if `f` is not a valid number. @@ -290,37 +288,28 @@ extern class Math In particular, both `POSITIVE_INFINITY` and `NEGATIVE_INFINITY` are not considered `NaN`. **/ - static function isNaN( f : Float ) : Bool; + static function isNaN(f:Float):Bool; #if !eval - private static function __init__() : Void untyped { - #if flash - NaN = __global__["Number"].NaN; - NEGATIVE_INFINITY = __global__["Number"].NEGATIVE_INFINITY; - POSITIVE_INFINITY = __global__["Number"].POSITIVE_INFINITY; - #else - Math.__name__ = ["Math"]; - Math.NaN = Number["NaN"]; - Math.NEGATIVE_INFINITY = Number["NEGATIVE_INFINITY"]; - Math.POSITIVE_INFINITY = Number["POSITIVE_INFINITY"]; - #end - Math.isFinite = function(i) { - return - #if flash - __global__["isFinite"](i); - #else - false; - #end - }; - Math.isNaN = function(i) { - return + private static function __init__():Void + untyped { #if flash - __global__["isNaN"](i); + NaN = __global__["Number"].NaN; + NEGATIVE_INFINITY = __global__["Number"].NEGATIVE_INFINITY; + POSITIVE_INFINITY = __global__["Number"].POSITIVE_INFINITY; #else - false; + // TODO: Abandoned code block? Js has its own _std/Math.hx + Math.__name__ = ["Math"]; + Math.NaN = Number["NaN"]; + Math.NEGATIVE_INFINITY = Number["NEGATIVE_INFINITY"]; + Math.POSITIVE_INFINITY = Number["POSITIVE_INFINITY"]; #end - }; - } + Math.isFinite = function(i) { + return #if flash __global__["isFinite"](i); #else false; #end + }; + Math.isNaN = function(i) { + return #if flash __global__["isNaN"](i); #else false; #end + }; + } #end - } diff --git a/std/Reflect.hx b/std/Reflect.hx index 71bef5bc4df..e91dd8a6a34 100644 --- a/std/Reflect.hx +++ b/std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + /** The Reflect API is a way to manipulate values dynamically through an abstract interface in an untyped manner. Use with care. @@ -26,7 +27,6 @@ @see https://haxe.org/manual/std-reflection.html **/ extern class Reflect { - /** Tells if structure `o` has a field named `field`. @@ -35,7 +35,7 @@ extern class Reflect { If `o` or `field` are null, the result is unspecified. **/ - public static function hasField( o : Dynamic, field : String ) : Bool; + public static function hasField(o:Dynamic, field:String):Bool; /** Returns the value of the field named `field` on object `o`. @@ -51,7 +51,7 @@ extern class Reflect { (As3) If used on a property field, the getter will be invoked. It is not possible to obtain the value directly. **/ - public static function field( o : Dynamic, field : String ) : Dynamic; + public static function field(o:Dynamic, field:String):Dynamic; /** Sets the field named `field` of object `o` to value `value`. @@ -64,7 +64,7 @@ extern class Reflect { (As3) If used on a property field, the setter will be invoked. It is not possible to set the value directly. **/ - public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void; + public static function setField(o:Dynamic, field:String, value:Dynamic):Void; /** Returns the value of the field named `field` on object `o`, taking @@ -75,7 +75,7 @@ extern class Reflect { If `o` or `field` are null, the result is unspecified. **/ - public static function getProperty( o : Dynamic, field : String ) : Dynamic; + public static function getProperty(o:Dynamic, field:String):Dynamic; /** Sets the field named `field` of object `o` to value `value`, taking @@ -86,12 +86,22 @@ extern class Reflect { If `field` is null, the result is unspecified. **/ - public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void; + public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void; /** - Call a method with the given object and arguments. + Call a method `func` with the given arguments `args`. + + The object `o` is ignored in most cases. It serves as the `this`-context in the following + situations: + + * (neko) Allows switching the context to `o` in all cases. + * (macro) Same as neko for Haxe 3. No context switching in Haxe 4. + * (js, lua) Require the `o` argument if `func` does not, but should have a context. + This can occur by accessing a function field natively, e.g. through `Reflect.field` + or by using `(object : Dynamic).field`. However, if `func` has a context, `o` is + ignored like on other targets. **/ - public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic; + public static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array):Dynamic; /** Returns the fields of structure `o`. @@ -101,14 +111,14 @@ extern class Reflect { If `o` is null, the result is unspecified. **/ - public static function fields( o : Dynamic ) : Array; + public static function fields(o:Dynamic):Array; /** Returns true if `f` is a function, false otherwise. If `f` is null, the result is false. **/ - public static function isFunction( f : Dynamic ) : Bool; + public static function isFunction(f:Dynamic):Bool; /** Compares `a` and `b`. @@ -131,11 +141,11 @@ extern class Reflect { If `a` and `b` are null, the result is 0. If only one of them is null, the result is unspecified. **/ - public static function compare( a : T, b : T ) : Int; + public static function compare(a:T, b:T):Int; /** Compares the functions `f1` and `f2`. - + If `f1` or `f2` are null, the result is false. If `f1` or `f2` are not functions, the result is unspecified. @@ -145,7 +155,7 @@ extern class Reflect { If `f1` or `f2` are member method closures, the result is true if they are closures of the same method on the same object value, false otherwise. **/ - public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool; + public static function compareMethods(f1:Dynamic, f2:Dynamic):Bool; /** Tells if `v` is an object. @@ -159,7 +169,7 @@ extern class Reflect { Otherwise, including if `v` is null, the result is false. **/ - public static function isObject( v : Dynamic ) : Bool; + public static function isObject(v:Dynamic):Bool; /** Tells if `v` is an enum value. @@ -169,7 +179,7 @@ extern class Reflect { Otherwise, including if `v` is null, the result is false. **/ - public static function isEnumValue( v : Dynamic ) : Bool; + public static function isEnumValue(v:Dynamic):Bool; /** Removes the field named `field` from structure `o`. @@ -178,22 +188,21 @@ extern class Reflect { If `o` or `field` are null, the result is unspecified. **/ - public static function deleteField( o : Dynamic, field : String ) : Bool; + public static function deleteField(o:Dynamic, field:String):Bool; /** Copies the fields of structure `o`. This is only guaranteed to work on anonymous structures. - If `o` is null, the result is unspecified. + If `o` is null, the result is `null`. **/ - public static function copy( o : T ) : T; + public static function copy(o:Null):Null; /** Transform a function taking an array of arguments into a function that can be called with any number of arguments. **/ - @:overload(function( f : Array -> Void ) : Dynamic {}) - public static function makeVarArgs( f : Array -> Dynamic ) : Dynamic; - + @:overload(function(f:Array->Void):Dynamic {}) + public static function makeVarArgs(f:Array->Dynamic):Dynamic; } diff --git a/std/Std.hx b/std/Std.hx index 4e1593d44bf..e919ae31643 100644 --- a/std/Std.hx +++ b/std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,29 +27,33 @@ The Std class provides standard methods for manipulating basic types. **/ extern class Std { - /** Tells if a value `v` is of the type `t`. Returns `false` if `v` or `t` are null. + + If `t` is a class or interface with `@:generic` meta, the result is `false`. **/ - public static function is( v : Dynamic, t : Dynamic ) : Bool; + public static function is(v:Dynamic, t:Dynamic):Bool; /** - Checks if object `value` is an instance of class `c`. + Checks if object `value` is an instance of class or interface `c`. - Compiles only if the class specified by `c` can be assigned to the type + Compiles only if the type specified by `c` can be assigned to the type of `value`. This method checks if a downcast is possible. That is, if the runtime - type of `value` is assignable to the class specified by `c`, `value` is + type of `value` is assignable to the type specified by `c`, `value` is returned. Otherwise null is returned. - This method is not guaranteed to work with interfaces or core types such - as `String`, `Array` and `Date`. + This method is not guaranteed to work with core types such as `String`, + `Array` and `Date`. If `value` is null, the result is null. If `c` is null, the result is unspecified. **/ - public static function instance( value : T, c : Class ) : S; + public static function downcast(value:T, c:Class):S; + + @:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.') + public static function instance(value:T, c:Class):S; /** Converts any value to a String. @@ -69,14 +73,14 @@ extern class Std { If s is null, "null" is returned. **/ - public static function string( s : Dynamic ) : String; + public static function string(s:Dynamic):String; /** Converts a `Float` to an `Int`, rounded towards 0. If `x` is outside of the signed Int32 range, or is `NaN`, `NEGATIVE_INFINITY` or `POSITIVE_INFINITY`, the result is unspecified. **/ - public static function int( x : Float ) : Int; + public static function int(x:Float):Int; /** Converts a `String` to an `Int`. @@ -96,9 +100,10 @@ extern class Std { Leading 0s that are not part of the 0x/0X hexadecimal notation are ignored, which means octal notation is not supported. - If the input cannot be recognized, the result is `null`. + If `x` is null, the result is unspecified. + If `x` cannot be parsed as integer, the result is `null`. **/ - public static function parseInt( x : String ) : Null; + public static function parseInt(x:String):Null; /** Converts a `String` to a `Float`. @@ -108,12 +113,12 @@ extern class Std { Additionally, decimal notation may contain a single `.` to denote the start of the fractions. **/ - public static function parseFloat( x : String ) : Float; + public static function parseFloat(x:String):Float; /** Return a random integer between 0 included and `x` excluded. If `x <= 1`, the result is always 0. **/ - public static function random( x : Int ) : Int; + public static function random(x:Int):Int; } diff --git a/std/StdTypes.hx b/std/StdTypes.hx index 120205e0ad9..2da4ff0a721 100644 --- a/std/StdTypes.hx +++ b/std/StdTypes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,7 +26,10 @@ @see https://haxe.org/manual/types-void.html **/ -@:coreType abstract Void { } +#if jvm +@:runtimeValue +#end +@:coreType abstract Void {} /** The standard `Float` type, this is a double-precision IEEE 64bit float. @@ -40,7 +43,7 @@ @see https://haxe.org/manual/types-basic-types.html @see https://haxe.org/manual/types-nullability.html **/ -@:coreType @:notNull @:runtimeValue abstract Float { } +@:coreType @:notNull @:runtimeValue abstract Float {} /** The standard `Int` type. Its precision depends on the platform. @@ -55,7 +58,7 @@ @see https://haxe.org/manual/std-math-integer-math.html @see https://haxe.org/manual/types-nullability.html **/ -@:coreType @:notNull @:runtimeValue abstract Int to Float { } +@:coreType @:notNull @:runtimeValue abstract Int to Float {} #if (java || cs || hl || cpp) /** @@ -65,16 +68,19 @@ #end /** - `Null` can be useful in two cases. In order to document some methods - that accept or can return a `null` value, or for the Flash compiler and AS3 - generator to distinguish between base values that can be `null` and others that - can't. + `Null` is a wrapper that can be used to make the basic types `Int`, + `Float` and `Bool` nullable on static targets. + + If null safety is enabled, only types wrapped in `Null` are nullable. + + Otherwise, it has no effect on non-basic-types, but it can be useful as a way to document + that `null` is an acceptable value for a method argument, return value or variable. @see https://haxe.org/manual/types-nullability.html **/ @:forward @:coreType -abstract Null from T to T { } +abstract Null from T to T {} /** The standard Boolean type, which can either be `true` or `false`. @@ -85,8 +91,7 @@ abstract Null from T to T { } @see https://haxe.org/manual/types-bool.html @see https://haxe.org/manual/types-nullability.html **/ -@:coreType @:notNull @:runtimeValue abstract Bool { -} +@:coreType @:notNull @:runtimeValue abstract Bool {} /** `Dynamic` is a special type which is compatible with all other types. @@ -97,8 +102,7 @@ abstract Null from T to T { } @see https://haxe.org/manual/types-dynamic.html **/ -@:coreType @:runtimeValue abstract Dynamic { -} +@:coreType @:runtimeValue abstract Dynamic {} /** An `Iterator` is a structure that permits iteration over elements of type `T`. @@ -110,7 +114,6 @@ abstract Null from T to T { } @see https://haxe.org/manual/lf-iterators.html **/ typedef Iterator = { - /** Returns `false` if the iteration is complete, `true` otherwise. @@ -119,7 +122,7 @@ typedef Iterator = { in custom iterators any logic may be used to determine the completion state. **/ - function hasNext() : Bool; + function hasNext():Bool; /** Returns the current item of the `Iterator` and advances to the next one. @@ -130,8 +133,7 @@ typedef Iterator = { On the other hand, iterators should not require a call to `hasNext()` before the first call to `next()` if an element is available. **/ - function next() : T; - + function next():T; } /** @@ -141,7 +143,20 @@ typedef Iterator = { @see https://haxe.org/manual/lf-iterators.html **/ typedef Iterable = { - function iterator() : Iterator; + function iterator():Iterator; +} + +/** + A `KeyValueIterator` is an `Iterator` that has a key and a value. +**/ +typedef KeyValueIterator = Iterator<{key:K, value:V}>; + +/** + A `KeyValueIterable` is a data structure which has a `keyValueIterator()` + method to iterate over key-value-pairs. +**/ +typedef KeyValueIterable = { + function keyValueIterator():KeyValueIterator; } /** @@ -154,4 +169,4 @@ typedef Iterable = { @see https://haxe.org/manual/types-abstract-array-access.html **/ -extern interface ArrayAccess { } +extern interface ArrayAccess {} diff --git a/std/String.hx b/std/String.hx index 74663a3248d..5f48050bd5e 100644 --- a/std/String.hx +++ b/std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + /** The basic String class. @@ -29,34 +30,29 @@ String can be concatenated by using the `+` operator. If an operand is not a String, it is passed through `Std.string()` first. - + @see https://haxe.org/manual/std-String.html **/ extern class String { - /** The number of characters in `this` String. **/ - var length(default,null) : Int; + var length(default, null):Int; /** Creates a copy from a given String. **/ - function new(string:String) : Void; + function new(string:String):Void; /** Returns a String where all characters of `this` String are upper case. - - Affects the characters `a-z`. Other characters remain unchanged. **/ - function toUpperCase() : String; + function toUpperCase():String; /** Returns a String where all characters of `this` String are lower case. - - Affects the characters `A-Z`. Other characters remain unchanged. **/ - function toLowerCase() : String; + function toLowerCase():String; /** Returns the character at position `index` of `this` String. @@ -64,7 +60,7 @@ extern class String { If `index` is negative or exceeds `this.length`, the empty String `""` is returned. **/ - function charAt(index : Int) : String; + function charAt(index:Int):String; /** Returns the character code at position `index` of `this` String. @@ -75,33 +71,37 @@ extern class String { used instead to inline the character code at compile time. Note that this only works on String literals of length 1. **/ - function charCodeAt( index : Int) : Null; + function charCodeAt(index:Int):Null; /** Returns the position of the leftmost occurrence of `str` within `this` String. If `startIndex` is given, the search is performed within the substring - of `this` String starting from `startIndex`. Otherwise the search is - performed within `this` String. In either case, the returned position - is relative to the beginning of `this` String. + of `this` String starting from `startIndex` (if `startIndex` is posivite + or 0) or `max(this.length + startIndex, 0)` (if `startIndex` is negative). + + If `startIndex` exceeds `this.length`, -1 is returned. + + Otherwise the search is performed within `this` String. In either case, + the returned position is relative to the beginning of `this` String. If `str` cannot be found, -1 is returned. **/ - function indexOf( str : String, ?startIndex : Int ) : Int; + function indexOf(str:String, ?startIndex:Int):Int; /** Returns the position of the rightmost occurrence of `str` within `this` String. If `startIndex` is given, the search is performed within the substring - of `this` String from 0 to `startIndex`. Otherwise the search is - performed within `this` String. In either case, the returned position + of `this` String from 0 to `startIndex + str.length`. Otherwise the search + is performed within `this` String. In either case, the returned position is relative to the beginning of `this` String. If `str` cannot be found, -1 is returned. **/ - function lastIndexOf( str : String, ?startIndex : Int ) : Int; + function lastIndexOf(str:String, ?startIndex:Int):Int; /** Splits `this` String at each occurrence of `delimiter`. @@ -123,7 +123,7 @@ extern class String { result `Array` contains a leading (or trailing) empty String `""` element. Two subsequent delimiters also result in an empty String `""` element. **/ - function split( delimiter : String ) : Array; + function split(delimiter:String):Array; /** Returns `len` characters of `this` String, starting at position `pos`. @@ -140,7 +140,7 @@ extern class String { If `len` is negative, the result is unspecified. **/ - function substr( pos : Int, ?len : Int ) : String; + function substr(pos:Int, ?len:Int):String; /** Returns the part of `this` String from `startIndex` to but not including `endIndex`. @@ -155,12 +155,12 @@ extern class String { If the (possibly swapped) `startIndex` exceeds `this.length`, the empty String `""` is returned. **/ - function substring( startIndex : Int, ?endIndex : Int ) : String; + function substring(startIndex:Int, ?endIndex:Int):String; /** Returns the String itself. **/ - function toString() : String; + function toString():String; /** Returns the String corresponding to the character code `code`. @@ -168,5 +168,5 @@ extern class String { If `code` is negative or has another invalid value, the result is unspecified. **/ - @:pure static function fromCharCode( code : Int ) : String; + @:pure static function fromCharCode(code:Int):String; } diff --git a/std/StringBuf.hx b/std/StringBuf.hx index 6b80b117818..1f84574b1c4 100644 --- a/std/StringBuf.hx +++ b/std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + /** A String buffer is an efficient way to build a big string by appending small elements together. @@ -31,13 +32,12 @@ values. However, the internal buffer cannot be modified. **/ class StringBuf { - var b:String; /** The length of `this` StringBuf in characters. **/ - public var length(get,never) : Int; + public var length(get, never):Int; /** Creates a new StringBuf instance. @@ -48,7 +48,7 @@ class StringBuf { b = ""; } - inline function get_length() : Int { + inline function get_length():Int { return b.length; } @@ -61,7 +61,7 @@ class StringBuf { If `x` is null, the String "null" is appended. **/ - public inline function add( x : T ) : Void { + public inline function add(x:T):Void { b += x; } @@ -71,7 +71,7 @@ class StringBuf { If `c` is negative or has another invalid value, the result is unspecified. **/ - public inline function addChar( c : Int ) : Void { + public inline function addChar(c:Int):Void { b += String.fromCharCode(c); } @@ -87,7 +87,7 @@ class StringBuf { If `len` is omitted or null, the substring ranges from `pos` to the end of `s`. **/ - public inline function addSub( s : String, pos : Int, ?len : Int) : Void { + public inline function addSub(s:String, pos:Int, ?len:Int):Void { b += (len == null ? s.substr(pos) : s.substr(pos, len)); } @@ -96,8 +96,7 @@ class StringBuf { The buffer is not emptied by this operation. **/ - public inline function toString() : String { + public inline function toString():String { return b; } - } diff --git a/std/StringTools.hx b/std/StringTools.hx index 4081935b6f3..c0dade39ba0 100644 --- a/std/StringTools.hx +++ b/std/StringTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + +import haxe.iterators.StringIterator; +import haxe.iterators.StringKeyValueIterator; + +#if cpp +using cpp.NativeString; +#end + /** This class provides advanced methods on Strings. It is ideally used with `using StringTools` and then acts as an [extension](https://haxe.org/manual/lf-static-extension.html) @@ -27,112 +35,109 @@ If the first argument to any of the methods is null, the result is unspecified. **/ -#if cpp -using cpp.NativeString; -#end class StringTools { /** Encode an URL by using the standard format. **/ - #if (!java && !cpp && !lua && !eval) inline #end public static function urlEncode( s : String ) : String { + #if (!java && !cpp && !lua && !eval) inline #end public static function urlEncode(s:String):String { #if flash - return untyped __global__["encodeURIComponent"](s); + return untyped __global__["encodeURIComponent"](s); #elseif neko - return untyped new String(_urlEncode(s.__s)); + return untyped new String(_urlEncode(s.__s)); #elseif js - return untyped encodeURIComponent(s); + return untyped encodeURIComponent(s); #elseif cpp - return untyped s.__URLEncode(); + return untyped s.__URLEncode(); #elseif java - return postProcessUrlEncode(java.net.URLEncoder.encode(s, "UTF-8")); + return postProcessUrlEncode(java.net.URLEncoder.encode(s, "UTF-8")); #elseif cs - return untyped cs.system.Uri.EscapeDataString(s); + return untyped cs.system.Uri.EscapeDataString(s); #elseif python - return python.lib.urllib.Parse.quote(s, ""); + return python.lib.urllib.Parse.quote(s, ""); #elseif hl - var len = 0; - var b = @:privateAccess s.bytes.urlEncode(len); - return @:privateAccess String.__alloc__(b,len); + var len = 0; + var b = @:privateAccess s.bytes.urlEncode(len); + return @:privateAccess String.__alloc__(b, len); #elseif lua - s = lua.NativeStringTools.gsub(s, "\n", "\r\n"); - s = lua.NativeStringTools.gsub(s, "([^%w %-%_%.%~])", function (c) { - return lua.NativeStringTools.format("%%%02X", lua.NativeStringTools.byte(c) + ''); - }); - s = lua.NativeStringTools.gsub(s, " ", "+"); - return s; + s = lua.NativeStringTools.gsub(s, "\n", "\r\n"); + s = lua.NativeStringTools.gsub(s, "([^%w %-%_%.%~])", function(c) { + return lua.NativeStringTools.format("%%%02X", lua.NativeStringTools.byte(c) + ''); + }); + s = lua.NativeStringTools.gsub(s, " ", "+"); + return s; #else - return null; + return null; #end } -#if java - private static function postProcessUrlEncode( s : String ) : String { + #if java + private static function postProcessUrlEncode(s:String):String { var ret = new StringBuf(); - var i = 0, - len = s.length; + var i = 0, len = s.length; while (i < len) { - switch(_charAt(s, i++)) { - case '+'.code: - ret.add('%20'); - case '%'.code if (i <= len - 2): - var c1 = _charAt(s, i++), - c2 = _charAt(s, i++); - switch[c1, c2] { - case ['2'.code, '1'.code]: - ret.addChar('!'.code); - case ['2'.code, '7'.code]: - ret.addChar('\''.code); - case ['2'.code, '8'.code]: - ret.addChar('('.code); - case ['2'.code, '9'.code]: - ret.addChar(')'.code); - case ['7'.code, 'E'.code] | ['7'.code, 'e'.code]: - ret.addChar('~'.code); - case _: - ret.addChar('%'.code); - ret.addChar(cast c1); - ret.addChar(cast c2); - } - case var chr: - ret.addChar(cast chr); + switch (_charAt(s, i++)) { + case '+'.code: + ret.add('%20'); + case '%'.code if (i <= len - 2): + var c1 = _charAt(s, i++), c2 = _charAt(s, i++); + switch [c1, c2] { + case ['2'.code, '1'.code]: + ret.addChar('!'.code); + case ['2'.code, '7'.code]: + ret.addChar('\''.code); + case ['2'.code, '8'.code]: + ret.addChar('('.code); + case ['2'.code, '9'.code]: + ret.addChar(')'.code); + case ['7'.code, 'E'.code] | ['7'.code, 'e'.code]: + ret.addChar('~'.code); + case _: + ret.addChar('%'.code); + ret.addChar(cast c1); + ret.addChar(cast c2); + } + case var chr: + ret.addChar(cast chr); } } return ret.toString(); } -#end + #end /** Decode an URL using the standard format. **/ - #if (!java && !cpp && !lua && !eval) inline #end public static function urlDecode( s : String ) : String { + #if (!java && !cpp && !lua && !eval) inline #end public static function urlDecode(s:String):String { #if flash - return untyped __global__["decodeURIComponent"](s.split("+").join(" ")); + return untyped __global__["decodeURIComponent"](s.split("+").join(" ")); #elseif neko - return untyped new String(_urlDecode(s.__s)); + return untyped new String(_urlDecode(s.__s)); #elseif js - return untyped decodeURIComponent(s.split("+").join(" ")); + return untyped decodeURIComponent(s.split("+").join(" ")); #elseif cpp - return untyped s.__URLDecode(); + return untyped s.__URLDecode(); #elseif java - try - return untyped __java__("java.net.URLDecoder.decode(s, \"UTF-8\")") - catch (e:Dynamic) throw e; + try + return java.net.URLDecoder.decode(s, "UTF-8") + catch (e:Dynamic) + throw e; #elseif cs - return untyped cs.system.Uri.UnescapeDataString(s); + return untyped cs.system.Uri.UnescapeDataString(s); #elseif python - return python.lib.urllib.Parse.unquote(s); + return python.lib.urllib.Parse.unquote(s); #elseif hl - var len = 0; - var b = @:privateAccess s.bytes.urlDecode(len); - return @:privateAccess String.__alloc__(b,len); + var len = 0; + var b = @:privateAccess s.bytes.urlDecode(len); + return @:privateAccess String.__alloc__(b, len); #elseif lua - s = lua.NativeStringTools.gsub (s, "+", " "); - s = lua.NativeStringTools.gsub (s, "%%(%x%x)", - function(h) {return lua.NativeStringTools.char(lua.Lua.tonumber(h,16));}); - s = lua.NativeStringTools.gsub (s, "\r\n", "\n"); - return s; + s = lua.NativeStringTools.gsub(s, "+", " "); + s = lua.NativeStringTools.gsub(s, "%%(%x%x)", function(h) { + return lua.NativeStringTools.char(lua.Lua.tonumber(h, 16)); + }); + s = lua.NativeStringTools.gsub(s, "\r\n", "\n"); + return s; #else - return null; + return null; #end } @@ -150,9 +155,25 @@ class StringTools { - `"` becomes `"`; - `'` becomes `'`; **/ - public static function htmlEscape( s : String, ?quotes : Bool ) : String { - s = s.split("&").join("&").split("<").join("<").split(">").join(">"); - return quotes ? s.split('"').join(""").split("'").join("'") : s; + public static function htmlEscape(s:String, ?quotes:Bool):String { + var buf = new StringBuf(); + for (code in new haxe.iterators.StringIteratorUnicode(s)) { + switch (code) { + case '&'.code: + buf.add("&"); + case '<'.code: + buf.add("<"); + case '>'.code: + buf.add(">"); + case '"'.code if (quotes): + buf.add("""); + case '\''.code if (quotes): + buf.add("'"); + case _: + buf.addChar(code); + } + } + return buf.toString(); } /** @@ -169,8 +190,26 @@ class StringTools { - `"` becomes `"` - `'` becomes `'` **/ - public static function htmlUnescape( s : String ) : String { - return s.split(">").join(">").split("<").join("<").split(""").join('"').split("'").join("'").split("&").join("&"); + public static function htmlUnescape(s:String):String { + return s.split(">") + .join(">") + .split("<") + .join("<") + .split(""") + .join('"') + .split("'") + .join("'") + .split("&") + .join("&"); + } + + /** + Returns `true` if `s` contains `value` and `false` otherwise. + + When `value` is `null`, the result is unspecified. + **/ + public static inline function contains(s:String, value:String):Bool { + return s.indexOf(value) != -1; } /** @@ -180,26 +219,26 @@ class StringTools { If `start` is the empty String `""`, the result is true. **/ - public static #if (cs || java || python) inline #end function startsWith( s : String, start : String ) : Bool { + public static #if (cs || java || python) inline #end function startsWith(s:String, start:String):Bool { #if java - return untyped s.startsWith(start); + return (cast s : java.NativeString).startsWith(start); #elseif cs return untyped s.StartsWith(start); #elseif cpp - if (s.length= start.length && s.bytes.compare(0,start.bytes,0,start.length<<1) == 0); + return @:privateAccess (s.length >= start.length && s.bytes.compare(0, start.bytes, 0, start.length << 1) == 0); #elseif python return python.NativeStringTools.startswith(s, start); #else - return( s.length >= start.length && s.substr(0, start.length) == start ); + return (s.length >= start.length && s.lastIndexOf(start, 0) == 0); #end } @@ -210,18 +249,18 @@ class StringTools { If `end` is the empty String `""`, the result is true. **/ - public static #if (cs || java || python) inline #end function endsWith( s : String, end : String ) : Bool { + public static #if (cs || java || python) inline #end function endsWith(s:String, end:String):Bool { #if java - return untyped s.endsWith(end); + return (cast s : java.NativeString).endsWith(end); #elseif cs return untyped s.EndsWith(end); #elseif cpp - if (s.length= elen && s.substr(slen - elen, elen) == end ); + return (slen >= elen && s.indexOf(end, (slen - elen)) == (slen - elen)); #end } @@ -246,11 +285,12 @@ class StringTools { If `s` is the empty String `""`, or if pos is not a valid position within `s`, the result is false. **/ - public static function isSpace( s : String, pos : Int ) : Bool { + public static function isSpace(s:String, pos:Int):Bool { #if (python || lua) - if (s.length == 0 || pos < 0 || pos >= s.length) return false; + if (s.length == 0 || pos < 0 || pos >= s.length) + return false; #end - var c = s.charCodeAt( pos ); + var c = s.charCodeAt(pos); return (c > 8 && c < 14) || c == 32; } @@ -263,17 +303,17 @@ class StringTools { If `s` is the empty String `""` or consists only of space characters, the result is the empty String `""`. **/ - public #if cs inline #end static function ltrim( s : String ) : String { + public #if cs inline #end static function ltrim(s:String):String { #if cs return untyped s.TrimStart(); #else var l = s.length; var r = 0; - while( r < l && isSpace(s,r) ){ + while (r < l && isSpace(s, r)) { r++; } - if( r > 0 ) - return s.substr(r, l-r); + if (r > 0) + return s.substr(r, l - r); else return s; #end @@ -288,18 +328,18 @@ class StringTools { If `s` is the empty String `""` or consists only of space characters, the result is the empty String `""`. **/ - public #if cs inline #end static function rtrim( s : String ) : String { + public #if cs inline #end static function rtrim(s:String):String { #if cs return untyped s.TrimEnd(); #else var l = s.length; var r = 0; - while( r < l && isSpace(s,l-r-1) ){ + while (r < l && isSpace(s, l - r - 1)) { r++; } - if( r > 0 ){ - return s.substr(0, l-r); - }else{ + if (r > 0) { + return s.substr(0, l - r); + } else { return s; } #end @@ -310,11 +350,11 @@ class StringTools { This is a convenience function for `ltrim(rtrim(s))`. **/ - public #if (cs || java) inline #end static function trim( s : String ) : String { + public #if (cs || java) inline #end static function trim(s:String):String { #if cs return untyped s.Trim(); #elseif java - return untyped s.trim(); + return (cast s : java.NativeString).trim(); #else return ltrim(rtrim(s)); #end @@ -332,14 +372,17 @@ class StringTools { If `c` is null, the result is unspecified. **/ - public static function lpad( s : String, c : String, l : Int ) : String { + public static function lpad(s:String, c:String, l:Int):String { if (c.length <= 0) return s; - while (s.length < l) { - s = c + s; + var buf = new StringBuf(); + l -= s.length; + while (buf.length < l) { + buf.add(c); } - return s; + buf.add(s); + return buf.toString(); } /** @@ -354,14 +397,16 @@ class StringTools { If `c` is null, the result is unspecified. **/ - public static function rpad( s : String, c : String, l : Int ) : String { + public static function rpad(s:String, c:String, l:Int):String { if (c.length <= 0) return s; - while (s.length < l) { - s = s + c; + var buf = new StringBuf(); + buf.add(s); + while (buf.length < l) { + buf.add(c); } - return s; + return buf.toString(); } /** @@ -369,18 +414,17 @@ class StringTools { String `by`. If `sub` is the empty String `""`, `by` is inserted after each character - of `s`. If `by` is also the empty String `""`, `s` remains unchanged. - - This is a convenience function for `s.split(sub).join(by)`. + of `s` except the last one. If `by` is also the empty String `""`, `s` + remains unchanged. If `sub` or `by` are null, the result is unspecified. **/ - public static function replace( s : String, sub : String, by : String ) : String { + public static function replace(s:String, sub:String, by:String):String { #if java if (sub.length == 0) return s.split(sub).join(by); else - return untyped s.replace(sub, by); + return (cast s : java.NativeString).replace(sub, by); #elseif cs if (sub.length == 0) return s.split(sub).join(by); @@ -397,18 +441,18 @@ class StringTools { If `digits` is specified, the resulting String is padded with "0" until its `length` equals `digits`. **/ - public static function hex( n : Int, ?digits : Int ) { + public static function hex(n:Int, ?digits:Int) { #if flash - var n : UInt = n; - var s : String = untyped n.toString(16); - s = s.toUpperCase(); + var n:UInt = n; + var s:String = untyped n.toString(16); + s = s.toUpperCase(); #else - var s = ""; - var hexChars = "0123456789ABCDEF"; - do { - s = hexChars.charAt(n&15) + s; - n >>>= 4; - } while( n > 0 ); + var s = ""; + var hexChars = "0123456789ABCDEF"; + do { + s = hexChars.charAt(n & 15) + s; + n >>>= 4; + } while (n > 0); #end #if python if (digits != null && s.length < digits) { @@ -418,9 +462,9 @@ class StringTools { } } #else - if( digits != null ) - while( s.length < digits ) - s = "0"+s; + if (digits != null) + while (s.length < digits) + s = "0" + s; #end return s; } @@ -439,7 +483,7 @@ class StringTools { This operation is not guaranteed to work if `s` contains the `\0` character. **/ - public static #if !eval inline #end function fastCodeAt( s : String, index : Int ) : Int { + public static #if !eval inline #end function fastCodeAt(s:String, index:Int):Int { #if neko return untyped __dollar__sget(s.__s, index); #elseif cpp @@ -447,37 +491,59 @@ class StringTools { #elseif flash return untyped s.cca(index); #elseif java - return ( index < s.length ) ? cast(_charAt(s, index), Int) : -1; + return (index < s.length) ? cast(_charAt(s, index), Int) : -1; #elseif cs - return ( cast(index, UInt) < s.length ) ? cast(s[index], Int) : -1; + return (cast(index, UInt) < s.length) ? cast(s[index], Int) : -1; #elseif js - return (untyped s).charCodeAt(index); + return (cast s).charCodeAt(index); #elseif python return if (index >= s.length) -1 else python.internal.UBuiltins.ord(python.Syntax.arrayAccess(s, index)); #elseif hl return @:privateAccess s.bytes.getUI16(index << 1); #elseif lua - return lua.NativeStringTools.byte(s,index+1); + #if lua_vanilla + return lua.NativeStringTools.byte(s, index + 1); + #else + return lua.lib.luautf8.Utf8.byte(s, index + 1); + #end #else return untyped s.cca(index); #end } - /* + /** + Returns an iterator of the char codes. + + Note that char codes may differ across platforms because of different + internal encoding of strings in different runtimes. + For the consistent cross-platform UTF8 char codes see `haxe.iterators.StringIteratorUnicode`. + **/ + public static inline function iterator(s:String):StringIterator { + return new StringIterator(s); + } + + /** + Returns an iterator of the char indexes and codes. + + Note that char codes may differ across platforms because of different + internal encoding of strings in different of runtimes. + For the consistent cross-platform UTF8 char codes see `haxe.iterators.StringKeyValueIteratorUnicode`. + **/ + public static inline function keyValueIterator(s:String):StringKeyValueIterator { + return new StringKeyValueIterator(s); + } + + /** Tells if `c` represents the end-of-file (EOF) character. - */ - @:noUsing public static inline function isEof( c : Int ) : Bool { + **/ + @:noUsing public static inline function isEof(c:Int):Bool { #if (flash || cpp || hl) return c == 0; #elseif js return c != c; // fast NaN #elseif (neko || lua || eval) return c == null; - #elseif cs - return c == -1; - #elseif java - return c == -1; - #elseif python + #elseif (cs || java || python) return c == -1; #else return false; @@ -488,26 +554,19 @@ class StringTools { Returns a String that can be used as a single command line argument on Unix. The input will be quoted, or escaped if necessary. - */ + **/ + @:noCompletion + @:deprecated('StringTools.quoteUnixArg() is deprecated. Use haxe.SysTools.quoteUnixArg() instead.') public static function quoteUnixArg(argument:String):String { - // Based on cpython's shlex.quote(). - // https://hg.python.org/cpython/file/a3f076d4f54f/Lib/shlex.py#l278 - - if (argument == "") - return "''"; - - if (!~/[^a-zA-Z0-9_@%+=:,.\/-]/.match(argument)) - return argument; - - // use single quotes, and put single quotes into double quotes - // the string $'b is then quoted as '$'"'"'b' - return "'" + replace(argument, "'", "'\"'\"'") + "'"; + return inline haxe.SysTools.quoteUnixArg(argument); } /** Character codes of the characters that will be escaped by `quoteWinArg(_, true)`. - */ - public static var winMetaCharacters = [" ".code, "(".code, ")".code, "%".code, "!".code, "^".code, "\"".code, "<".code, ">".code, "&".code, "|".code, "\n".code, "\r".code, ",".code, ";".code]; + **/ + @:noCompletion + @:deprecated('StringTools.winMetaCharacters is deprecated. Use haxe.SysTools.winMetaCharacters instead.') + public static var winMetaCharacters:Array = cast haxe.SysTools.winMetaCharacters; /** Returns a String that can be used as a single command line argument @@ -517,80 +576,36 @@ class StringTools { http://msdn.microsoft.com/en-us/library/ms880421 Examples: - ``` + ```haxe quoteWinArg("abc") == "abc"; quoteWinArg("ab c") == '"ab c"'; ``` - */ + **/ + @:noCompletion + @:deprecated('StringTools.quoteWinArg() is deprecated. Use haxe.SysTools.quoteWinArg() instead.') public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String { - // If there is no space, tab, back-slash, or double-quotes, and it is not an empty string. - if (!~/^[^ \t\\"]+$/.match(argument)) { - - // Based on cpython's subprocess.list2cmdline(). - // https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620 - - var result = new StringBuf(); - var needquote = argument.indexOf(" ") != -1 || argument.indexOf("\t") != -1 || argument == ""; - - if (needquote) - result.add('"'); - - var bs_buf = new StringBuf(); - for (i in 0...argument.length) { - switch (argument.charCodeAt(i)) { - case "\\".code: - // Don't know if we need to double yet. - bs_buf.add("\\"); - case '"'.code: - // Double backslashes. - var bs = bs_buf.toString(); - result.add(bs); - result.add(bs); - bs_buf = new StringBuf(); - result.add('\\"'); - case var c: - // Normal char - if (bs_buf.length > 0) { - result.add(bs_buf.toString()); - bs_buf = new StringBuf(); - } - result.addChar(c); - } - } - - // Add remaining backslashes, if any. - result.add(bs_buf.toString()); - - if (needquote) { - result.add(bs_buf.toString()); - result.add('"'); - } - - argument = result.toString(); - } - - if (escapeMetaCharacters) { - var result = new StringBuf(); - for (i in 0...argument.length) { - var c = argument.charCodeAt(i); - if (winMetaCharacters.indexOf(c) >= 0) { - result.addChar("^".code); - } - result.addChar(c); - } - return result.toString(); - } else { - return argument; - } + return inline haxe.SysTools.quoteWinArg(argument, escapeMetaCharacters); } #if java - private static inline function _charAt(str:String, idx:Int):java.StdTypes.Char16 return untyped str._charAt(idx); + private static inline function _charAt(str:String, idx:Int):java.StdTypes.Char16 + return (cast str : java.NativeString).charAt(idx); #end #if neko - private static var _urlEncode = neko.Lib.load("std","url_encode",1); - private static var _urlDecode = neko.Lib.load("std","url_decode",1); + private static var _urlEncode = neko.Lib.load("std", "url_encode", 1); + private static var _urlDecode = neko.Lib.load("std", "url_decode", 1); #end + #if utf16 + static inline var MIN_SURROGATE_CODE_POINT = 65536; + + static inline function utf16CodePointAt(s:String, index:Int):Int { + var c = StringTools.fastCodeAt(s, index); + if (c >= 0xD800 && c <= 0xDBFF) { + c = ((c - 0xD7C0) << 10) | (StringTools.fastCodeAt(s, index + 1) & 0x3FF); + } + return c; + } + #end } diff --git a/std/Sys.hx b/std/Sys.hx index a7ff763e3eb..fe378142113 100644 --- a/std/Sys.hx +++ b/std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,130 +19,153 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + /** - This class gives you access to many base functionalities of system platforms. Looks in `sys` sub packages for more system APIs. + This class provides access to various base functions of system platforms. + Look in the `sys` package for more system APIs. **/ @:require(sys) extern class Sys { - /** - Print any value on the standard output. + Prints any value to the standard output. **/ - static function print( v : Dynamic ) : Void; + static function print(v:Dynamic):Void; /** - Print any value on the standard output, followed by a newline. + Prints any value to the standard output, followed by a newline. + On Windows, this function outputs a CRLF newline. + LF newlines are printed on all other platforms. **/ - static function println( v : Dynamic ) : Void; + static function println(v:Dynamic):Void; /** - Returns all the arguments that were passed by the command line. + Returns all the arguments that were passed in the command line. + This does not include the interpreter or the name of the program file. + + (java)(eval) On Windows, non-ASCII Unicode arguments will not work correctly. + + (cs) Non-ASCII Unicode arguments will not work correctly. **/ - static function args() : Array; + static function args():Array; /** - Returns the value of the given environment variable. + Returns the value of the given environment variable, or `null` if it + doesn't exist. **/ - static function getEnv( s : String ) : String; + static function getEnv(s:String):String; /** - Set the value of the given environment variable. + Sets the value of the given environment variable. + + (java) This functionality is not available on Java; calling this function will throw. **/ - static function putEnv( s : String, v : String ) : Void; + static function putEnv(s:String, v:String):Void; /** Returns all environment variables. **/ - static function environment() : Map; + static function environment():Map; /** - Suspend the current execution for the given time (in seconds). + Suspends execution for the given length of time (in seconds). **/ - static function sleep( seconds : Float ) : Void; + static function sleep(seconds:Float):Void; /** - Change the current time locale, which will affect `DateTools.format` date formating. - Returns true if the locale was successfully changed + Changes the current time locale, which will affect `DateTools.format` date formating. + Returns `true` if the locale was successfully changed. **/ - static function setTimeLocale( loc : String ) : Bool; + static function setTimeLocale(loc:String):Bool; /** - Get the current working directory (usually the one in which the program was started) + Gets the current working directory (usually the one in which the program was started). **/ - static function getCwd() : String; + static function getCwd():String; /** - Change the current working directory. + Changes the current working directory. + + (java) This functionality is not available on Java; calling this function will throw. **/ - static function setCwd( s : String ) : Void; + static function setCwd(s:String):Void; /** - Returns the name of the system you are running on. For instance : - "Windows", "Linux", "BSD" and "Mac" depending on your desktop OS. + Returns the type of the current system. Possible values are: + - `"Windows"` + - `"Linux"` + - `"BSD"` + - `"Mac"` **/ - static function systemName() : String; + static function systemName():String; /** - Run the given command. The command output will be printed on the same output as the current process. - The current process will block until the command terminates and it will return the command result (0 if there was no error). + Runs the given command. The command output will be printed to the same output as the current process. + The current process will block until the command terminates. + The return value is the exit code of the command (usually `0` indicates no error). - Command arguments can be passed in two ways: 1. using `args`, 2. appending to `cmd` and leaving `args` as `null`. + Command arguments can be passed in two ways: - 1. When using `args` to pass command arguments, each argument will be automatically quoted, and shell meta-characters will be escaped if needed. - `cmd` should be an executable name that can be located in the `PATH` environment variable, or a path to an executable. + 1. Using `args` to pass command arguments. Each argument will be automatically quoted and shell meta-characters will be escaped if needed. + `cmd` should be an executable name that can be located in the `PATH` environment variable, or a full path to an executable. 2. When `args` is not given or is `null`, command arguments can be appended to `cmd`. No automatic quoting/escaping will be performed. `cmd` should be formatted exactly as it would be when typed at the command line. It can run executables, as well as shell commands that are not executables (e.g. on Windows: `dir`, `cd`, `echo` etc). - Read the `sys.io.Process` api for a more complete way to start background processes. + Use the `sys.io.Process` API for more complex tasks, such as background processes, or providing input to the command. **/ - static function command( cmd : String, ?args : Array ) : Int; + static function command(cmd:String, ?args:Array):Int; /** - Exit the current process with the given error code. + Exits the current process with the given exit code. + + (macro)(eval) Being invoked in a macro or eval context (e.g. with `-x` or `--run`) immediately terminates + the compilation process, which also prevents the execution of any `--next` sections of compilation arguments. **/ - static function exit( code : Int ) : Void; + static function exit(code:Int):Void; /** - Gives the most precise timestamp value (in seconds). + Gives the most precise timestamp value available (in seconds). **/ - static function time() : Float; + static function time():Float; /** - Gives the most precise timestamp value (in seconds) but only account for the actual time spent running on the CPU for the current thread/process. + Gives the most precise timestamp value available (in seconds), + but only accounts for the actual time spent running on the CPU for the current thread/process. **/ - static function cpuTime() : Float; + static function cpuTime():Float; /** Returns the path to the current executable that we are running. **/ - @:deprecated("Use programPath instead") static function executablePath() : String; + @:deprecated("Use programPath instead") static function executablePath():String; /** Returns the absolute path to the current program file that we are running. Concretely, for an executable binary, it returns the path to the binary. For a script (e.g. a PHP file), it returns the path to the script. **/ - static function programPath() : String; + static function programPath():String; /** - Read a single input character from the standard input and returns it. Setting `echo` to true will also display it on the output. + Reads a single input character from the standard input and returns it. + Setting `echo` to `true` will also display the character on the output. **/ - static function getChar( echo : Bool ) : Int; + static function getChar(echo:Bool):Int; /** - Returns the process standard input, from which you can read what user enters. Usually it will block until the user send a full input line. See `getChar` for an alternative. + Returns the standard input of the process, from which user input can be read. + Usually it will block until the user sends a full input line. + See `getChar` for an alternative. **/ - static function stdin() : haxe.io.Input; + static function stdin():haxe.io.Input; /** - Returns the process standard output on which you can write. + Returns the standard output of the process, to which program output can be written. **/ - static function stdout() : haxe.io.Output; + static function stdout():haxe.io.Output; /** - Returns the process standard error on which you can write. + Returns the standard error of the process, to which program errors can be written. **/ - static function stderr() : haxe.io.Output; - + static function stderr():haxe.io.Output; } diff --git a/std/Type.hx b/std/Type.hx index ca1d54b1b04..dab42fdda16 100644 --- a/std/Type.hx +++ b/std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -30,7 +30,6 @@ @see https://haxe.org/manual/std-reflection.html **/ extern class Type { - /** Returns the class of `o`, if `o` is a class instance. @@ -38,7 +37,7 @@ extern class Type { In general, type parameter information cannot be obtained at runtime. **/ - public static function getClass( o : T ) : Class; + public static function getClass(o:T):Class; /** Returns the enum of enum instance `o`. @@ -50,8 +49,7 @@ extern class Type { In general, type parameter information cannot be obtained at runtime. **/ - public static function getEnum( o : EnumValue ) : Enum; - + public static function getEnum(o:EnumValue):Enum; /** Returns the super-class of class `c`. @@ -62,8 +60,7 @@ extern class Type { In general, type parameter information cannot be obtained at runtime. **/ - public static function getSuperClass( c : Class ) : Class; - + public static function getSuperClass(c:Class):Class; /** Returns the name of class `c`, including its path. @@ -80,7 +77,7 @@ extern class Type { The class name does not include any type parameters. **/ - public static function getClassName( c : Class ) : String; + public static function getClassName(c:Class):String; /** Returns the name of enum `e`, including its path. @@ -97,7 +94,7 @@ extern class Type { The enum name does not include any type parameters. **/ - public static function getEnumName( e : Enum ) : String; + public static function getEnumName(e:Enum):String; /** Resolves a class by name. @@ -111,7 +108,7 @@ extern class Type { The class name must not include any type parameters. **/ - public static function resolveClass( name : String ) : Class; + public static function resolveClass(name:String):Class; /** Resolves an enum by name. @@ -126,7 +123,7 @@ extern class Type { The enum name must not include any type parameters. **/ - public static function resolveEnum( name : String ) : Enum; + public static function resolveEnum(name:String):Enum; /** Creates an instance of class `cl`, using `args` as arguments to the @@ -145,7 +142,7 @@ extern class Type { In particular, default values of constructor arguments are not guaranteed to be taken into account. **/ - public static function createInstance( cl : Class, args : Array ) : T; + public static function createInstance(cl:Class, args:Array):T; /** Creates an instance of class `cl`. @@ -154,7 +151,7 @@ extern class Type { If `cl` is null, the result is unspecified. **/ - public static function createEmptyInstance( cl : Class ) : T; + public static function createEmptyInstance(cl:Class):T; /** Creates an instance of enum `e` by calling its constructor `constr` with @@ -165,7 +162,7 @@ extern class Type { expected number of constructor arguments, or if any argument has an invalid type, the result is unspecified. **/ - public static function createEnum( e : Enum, constr : String, ?params : Array ) : T; + public static function createEnum(e:Enum, constr:String, ?params:Array):T; /** Creates an instance of enum `e` by calling its constructor number @@ -179,14 +176,15 @@ extern class Type { expected number of constructor arguments, or if any argument has an invalid type, the result is unspecified. **/ - public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T; + public static function createEnumIndex(e:Enum, index:Int, ?params:Array):T; /** - Returns a list of the instance fields of class `c`. + Returns a list of the instance fields of class `c`, including + inherited fields. This only includes fields which are known at compile-time. In - particular, using getInstanceFields(getClass(obj)) will not include - any fields which were added to obj at runtime. + particular, using `getInstanceFields(getClass(obj))` will not include + any fields which were added to `obj` at runtime. The order of the fields in the returned Array is unspecified. @@ -194,7 +192,7 @@ extern class Type { (As3) This method only returns instance fields that are public. **/ - public static function getInstanceFields( c : Class ) : Array; + public static function getInstanceFields(c:Class):Array; /** Returns a list of static fields of class `c`. @@ -207,7 +205,7 @@ extern class Type { (As3) This method only returns class fields that are public. **/ - public static function getClassFields( c : Class ) : Array; + public static function getClassFields(c:Class):Array; /** Returns a list of the names of all constructors of enum `e`. @@ -217,7 +215,7 @@ extern class Type { If `e` is null, the result is unspecified. **/ - public static function getEnumConstructs( e : Enum ) : Array; + public static function getEnumConstructs(e:Enum):Array; /** Returns the runtime type of value `v`. @@ -226,7 +224,7 @@ extern class Type { per platform. Assumptions regarding this should be minimized to avoid surprises. **/ - public static function typeof( v : Dynamic ) : ValueType; + public static function typeof(v:Dynamic):ValueType; /** Recursively compares two enum instances `a` and `b` by value. @@ -236,7 +234,7 @@ extern class Type { If `a` or `b` are null, the result is unspecified. **/ - public static function enumEq( a : T, b : T ) : Bool; + public static function enumEq(a:T, b:T):Bool; /** Returns the constructor name of enum instance `e`. @@ -245,7 +243,7 @@ extern class Type { If `e` is null, the result is unspecified. **/ - public static function enumConstructor( e : EnumValue ) : String; + public static function enumConstructor(e:EnumValue):String; /** Returns a list of the constructor arguments of enum instance `e`. @@ -257,7 +255,7 @@ extern class Type { If `e` is null, the result is unspecified. **/ - public static function enumParameters( e : EnumValue ) : Array; + public static function enumParameters(e:EnumValue):Array; /** Returns the index of enum instance `e`. @@ -267,7 +265,7 @@ extern class Type { If `e` is null, the result is unspecified. **/ - public static function enumIndex( e : EnumValue ) : Int; + public static function enumIndex(e:EnumValue):Int; /** Returns a list of all constructors of enum `e` that require no @@ -282,11 +280,9 @@ extern class Type { If `e` is null, the result is unspecified. **/ - public static function allEnums( e : Enum ) : Array; - + public static function allEnums(e:Enum):Array; } - /** The different possible runtime types of a value. **/ @@ -297,7 +293,7 @@ enum ValueType { TBool; TObject; TFunction; - TClass( c : Class ); - TEnum( e : Enum ); + TClass(c:Class); + TEnum(e:Enum); TUnknown; } diff --git a/std/UInt.hx b/std/UInt.hx index bdef243d411..eca400e0a0b 100644 --- a/std/UInt.hx +++ b/std/UInt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,6 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - #if ((flash || flash9doc || cs || hl) && !doc_gen) /** The unsigned `Int` type is only defined for Flash and C#. It's currently @@ -31,68 +30,100 @@ @:notNull @:runtimeValue @:analyzer(no_const_propagation) -abstract UInt to Int from Int -{ - @:commutative @:op(A+B) private static function addI(lhs:UInt, rhs:Int):UInt; - @:commutative @:op(A+B) private static function addF(lhs:UInt, rhs:Float):Float; - @:op(A+B) private static function add(lhs:UInt, rhs:UInt):UInt; - - @:commutative @:op(A*B) private static function mulI(lhs:UInt, rhs:Int):UInt; - @:commutative @:op(A*B) private static function mulF(lhs:UInt, rhs:Float):Float; - @:op(A*B) private static function mul(lhs:UInt, rhs:UInt):UInt; - - @:op(A%B) private static function modI(lhs:UInt, rhs:Int):UInt; - @:op(A%B) private static function modF(lhs:UInt, rhs:Float):Float; - @:op(A%B) private static function mod(lhs:UInt, rhs:UInt):UInt; - - @:op(A-B) private static function subI(lhs:UInt, rhs:Int):UInt; - @:op(A-B) private static function subF(lhs:UInt, rhs:Float):Float; - @:op(A-B) private static function sub(lhs:UInt, rhs:UInt):UInt; - - @:op(A/B) private static function divI(lhs:UInt, rhs:Int):Float; - @:op(A/B) private static function divF(lhs:UInt, rhs:Float):Float; - @:op(A/B) private static function div(lhs:UInt, rhs:UInt):Float; - - @:commutative @:op(A|B) private static function orI(lhs:UInt, rhs:Int):UInt; - @:op(A|B) private static function or(lhs:UInt, rhs:UInt):UInt; - - @:commutative @:op(A^B) private static function xorI(lhs:UInt, rhs:Int):UInt; - @:op(A^B) private static function xor(lhs:UInt, rhs:UInt):UInt; - - @:commutative @:op(A&B) private static function andI(lhs:UInt, rhs:Int):UInt; - @:op(A&B) private static function and(lhs:UInt, rhs:UInt):UInt; - - @:op(A<>B) private static inline function shr(lhs:UInt, rhs:Int):UInt return lhs >>> rhs; - @:op(A>>>B) private static function ushr(lhs:UInt, rhs:Int):UInt; - - @:op(A>B) private static function gt(lhs:UInt, rhs:UInt):Bool; - @:op(A>=B) private static function gte(lhs:UInt, rhs:UInt):Bool; - @:op(AB) private static function gtf(lhs:UInt, rhs:Float):Bool; - @:op(A>B) private static function gtf2(lhs:Float, rhs:UInt):Bool; - @:op(A>=B) private static function gtef(lhs:UInt, rhs:Float):Bool; - @:op(A>=B) private static function gtef2(lhs:Float, rhs:UInt):Bool; - @:op(A> B) private static inline function shr(lhs:UInt, rhs:Int):UInt + return lhs >>> rhs; + + @:op(A >>> B) private static function ushr(lhs:UInt, rhs:Int):UInt; + + @:op(A > B) private static function gt(lhs:UInt, rhs:UInt):Bool; + + @:op(A >= B) private static function gte(lhs:UInt, rhs:UInt):Bool; + + @:op(A < B) private static function lt(lhs:UInt, rhs:UInt):Bool; + + @:op(A <= B) private static function lte(lhs:UInt, rhs:UInt):Bool; + + @:op(A > B) private static function gtf(lhs:UInt, rhs:Float):Bool; + + @:op(A > B) private static function gtf2(lhs:Float, rhs:UInt):Bool; + + @:op(A >= B) private static function gtef(lhs:UInt, rhs:Float):Bool; + + @:op(A >= B) private static function gtef2(lhs:Float, rhs:UInt):Bool; + + @:op(A < B) private static function ltf(lhs:UInt, rhs:Float):Bool; + + @:op(A < B) private static function ltf2(lhs:Float, rhs:UInt):Bool; + + @:op(A <= B) private static function ltef(lhs:UInt, rhs:Float):Bool; + + @:op(A <= B) private static function ltef2(lhs:Float, rhs:UInt):Bool; @:op(~A) private static function bneg(t:UInt):UInt; @:commutative @:op(A == B) private static function equalsInt(a:UInt, b:T):Bool; + @:commutative @:op(A != B) private static function notEqualsInt(a:UInt, b:T):Bool; + @:commutative @:op(A == B) private static function equalsFloat(a:UInt, b:T):Bool; + @:commutative @:op(A != B) private static function notEqualsFloat(a:UInt, b:T):Bool; @:op(++A) private function prefixIncrement():UInt; + @:op(A++) private function postfixIncrement():UInt; + @:op(--A) private function prefixDecrement():UInt; + @:op(A--) private function postfixDecrement():UInt; } #else + /** The unsigned `Int` type is only defined for Flash and C#. Simulate it for other platforms. @@ -100,7 +131,6 @@ abstract UInt to Int from Int @see https://haxe.org/manual/types-basic-types.html **/ abstract UInt(Int) from Int to Int { - @:op(A + B) private static inline function add(a:UInt, b:UInt):UInt { return a.toInt() + b.toInt(); } @@ -117,20 +147,18 @@ abstract UInt(Int) from Int to Int { return a.toInt() - b.toInt(); } - @:op(A > B) private static #if !js inline #end function gt(a:UInt, b:UInt):Bool { + @:op(A > B) + private static #if !js inline #end function gt(a:UInt, b:UInt):Bool { var aNeg = a.toInt() < 0; var bNeg = b.toInt() < 0; - return - if( aNeg != bNeg ) aNeg; - else a.toInt() > b.toInt(); + return if (aNeg != bNeg) aNeg; else a.toInt() > b.toInt(); } - @:op(A >= B) private static #if !js inline #end function gte(a:UInt, b:UInt):Bool { + @:op(A >= B) + private static #if !js inline #end function gte(a:UInt, b:UInt):Bool { var aNeg = a.toInt() < 0; var bNeg = b.toInt() < 0; - return - if( aNeg != bNeg ) aNeg; - else a.toInt() >= b.toInt(); + return if (aNeg != bNeg) aNeg; else a.toInt() >= b.toInt(); } @:op(A < B) private static inline function lt(a:UInt, b:UInt):Bool { @@ -166,7 +194,7 @@ abstract UInt(Int) from Int to Int { } @:op(A % B) private static inline function mod(a:UInt, b:UInt):UInt { - return Std.int( a.toFloat() % b.toFloat() ); + return Std.int(a.toFloat() % b.toFloat()); } @:commutative @:op(A + B) private static inline function addWithFloat(a:UInt, b:Float):Float { @@ -217,7 +245,6 @@ abstract UInt(Int) from Int to Int { return a.toFloat() >= b; } - @:op(A > B) private static inline function floatGt(a:Float, b:UInt):Bool { return a > b.toFloat(); } @@ -283,8 +310,7 @@ abstract UInt(Int) from Int to Int { var int = toInt(); if (int < 0) { return 4294967296.0 + int; - } - else { + } else { // + 0.0 here to make sure we promote to Float on some platforms // In particular, PHP was having issues when comparing to Int in the == op. return int + 0.0; diff --git a/std/UnicodeString.hx b/std/UnicodeString.hx new file mode 100644 index 00000000000..7ac030e0d9f --- /dev/null +++ b/std/UnicodeString.hx @@ -0,0 +1,443 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +import haxe.io.Bytes; +import haxe.io.Encoding; +import haxe.iterators.StringIteratorUnicode; +import haxe.iterators.StringKeyValueIteratorUnicode; + +/** + This abstract provides consistent cross-target unicode support. + + @see https://haxe.org/manual/std-UnicodeString.html +**/ +@:forward +@:access(StringTools) +abstract UnicodeString(String) from String to String { + /** + Tells if `b` is a correctly encoded UTF8 byte sequence. + **/ + static public function validate(b:Bytes, encoding:Encoding):Bool { + switch (encoding) { + case RawNative: + throw "UnicodeString.validate: RawNative encoding is not supported"; + case UTF8: + var data = b.getData(); + var pos = 0; + var max = b.length; + while (pos < max) { + var c:Int = Bytes.fastGet(data, pos++); + if (c < 0x80) {} else if (c < 0xC2) { + return false; + } else if (c < 0xE0) { + if (pos + 1 > max) { + return false; + } + var c2:Int = Bytes.fastGet(data, pos++); + if (c2 < 0x80 || c2 > 0xBF) { + return false; + } + } else if (c < 0xF0) { + if (pos + 2 > max) { + return false; + } + var c2:Int = Bytes.fastGet(data, pos++); + if (c == 0xE0) { + if (c2 < 0xA0 || c2 > 0xBF) + return false; + } else { + if (c2 < 0x80 || c2 > 0xBF) + return false; + } + var c3:Int = Bytes.fastGet(data, pos++); + if (c3 < 0x80 || c3 > 0xBF) { + return false; + } + c = (c << 16) | (c2 << 8) | c3; + if (0xEDA080 <= c && c <= 0xEDBFBF) { // surrogate pairs + return false; + } + } else if (c > 0xF4) { + return false; + } else { + if (pos + 3 > max) { + return false; + } + var c2:Int = Bytes.fastGet(data, pos++); + if (c == 0xF0) { + if (c2 < 0x90 || c2 > 0xBF) + return false; + } else if (c == 0xF4) { + if (c2 < 0x80 || c2 > 0x8F) + return false; + } else { + if (c2 < 0x80 || c2 > 0xBF) + return false; + } + var c3:Int = Bytes.fastGet(data, pos++); + if (c3 < 0x80 || c3 > 0xBF) { + return false; + } + var c4:Int = Bytes.fastGet(data, pos++); + if (c4 < 0x80 || c4 > 0xBF) { + return false; + } + } + } + return true; + } + } + + #if target.unicode + /** + Creates an instance of UnicodeString. + **/ + public inline function new(string:String):Void { + this = string; + } + + /** + Returns an iterator of the unicode code points. + **/ + public inline function iterator():StringIteratorUnicode { + return new StringIteratorUnicode(this); + } + + /** + Returns an iterator of the code point indices and unicode code points. + **/ + public inline function keyValueIterator():StringKeyValueIteratorUnicode { + return new StringKeyValueIteratorUnicode(this); + } + + #if target.utf16 + /** + The number of characters in `this` String. + **/ + public var length(get, never):Int; + + /** + Returns the character at position `index` of `this` String. + + If `index` is negative or exceeds `this.length`, the empty String `""` + is returned. + **/ + public function charAt(index:Int):String { + if (index < 0) + return ''; + var unicodeOffset = 0; + var nativeOffset = 0; + while (nativeOffset < this.length) { + var c = StringTools.utf16CodePointAt(this, nativeOffset++); + if (unicodeOffset == index) { + return String.fromCharCode(c); + } + if (c >= StringTools.MIN_SURROGATE_CODE_POINT) { + nativeOffset++; + } + unicodeOffset++; + } + return ''; + } + + /** + Returns the character code at position `index` of `this` String. + + If `index` is negative or exceeds `this.length`, `null` is returned. + **/ + public function charCodeAt(index:Int):Null { + if (index < 0) + return null; + var unicodeOffset = 0; + var nativeOffset = 0; + while (nativeOffset < this.length) { + var c = StringTools.utf16CodePointAt(this, nativeOffset++); + if (unicodeOffset == index) { + return c; + } + if (c >= StringTools.MIN_SURROGATE_CODE_POINT) { + nativeOffset++; + } + unicodeOffset++; + } + return null; + } + + /** + Returns the position of the leftmost occurrence of `str` within `this` + String. + + If `startIndex` is given, the search is performed within the substring + of `this` String starting from `startIndex` (if `startIndex` is posivite + or 0) or `max(this.length + startIndex, 0)` (if `startIndex` is negative). + + If `startIndex` exceeds `this.length`, -1 is returned. + + Otherwise the search is performed within `this` String. In either case, + the returned position is relative to the beginning of `this` String. + + If `str` cannot be found, -1 is returned. + **/ + public function indexOf(str:String, ?startIndex:Int):Int { + if (startIndex == null) { + startIndex = 0; + } else { + if (startIndex < 0) { + startIndex = (this : UnicodeString).length + startIndex; + } + } + + var unicodeOffset = 0; + var nativeOffset = 0; + var matchingOffset = 0; + var result = -1; + while (nativeOffset <= this.length) { + var c = StringTools.utf16CodePointAt(this, nativeOffset); + + if (unicodeOffset >= startIndex) { + var c2 = StringTools.utf16CodePointAt(str, matchingOffset); + if (c == c2) { + if (matchingOffset == 0) { + result = unicodeOffset; + } + matchingOffset++; + if (c2 >= StringTools.MIN_SURROGATE_CODE_POINT) { + matchingOffset++; + } + if (matchingOffset == str.length) { + return result; + } + } else if (matchingOffset != 0) { + result = -1; + matchingOffset = 0; + continue; + } + } + + nativeOffset++; + if (c >= StringTools.MIN_SURROGATE_CODE_POINT) { + nativeOffset++; + } + unicodeOffset++; + } + return -1; + } + + /** + Returns the position of the rightmost occurrence of `str` within `this` + String. + + If `startIndex` is given, the search is performed within the substring + of `this` String from 0 to `startIndex + str.length`. Otherwise the search + is performed within `this` String. In either case, the returned position + is relative to the beginning of `this` String. + + If `str` cannot be found, -1 is returned. + **/ + public function lastIndexOf(str:String, ?startIndex:Int):Int { + if (startIndex == null) { + startIndex = this.length; + } else if (startIndex < 0) { + startIndex = 0; + } + + var unicodeOffset = 0; + var nativeOffset = 0; + var result = -1; + var lastIndex = -1; + var matchingOffset = 0; + var strUnicodeLength = (str : UnicodeString).length; + while (nativeOffset < this.length && unicodeOffset < startIndex + strUnicodeLength) { + var c = StringTools.utf16CodePointAt(this, nativeOffset); + + var c2 = StringTools.utf16CodePointAt(str, matchingOffset); + if (c == c2) { + if (matchingOffset == 0) { + lastIndex = unicodeOffset; + } + matchingOffset++; + if (c2 >= StringTools.MIN_SURROGATE_CODE_POINT) { + matchingOffset++; + } + if (matchingOffset == str.length) { + result = lastIndex; + lastIndex = -1; + } + } else if (matchingOffset != 0) { + lastIndex = -1; + matchingOffset = 0; + continue; + } + + nativeOffset++; + if (c >= StringTools.MIN_SURROGATE_CODE_POINT) { + nativeOffset++; + } + unicodeOffset++; + } + return result; + } + + /** + Returns `len` characters of `this` String, starting at position `pos`. + + If `len` is omitted, all characters from position `pos` to the end of + `this` String are included. + + If `pos` is negative, its value is calculated from the end of `this` + String by `this.length + pos`. If this yields a negative value, 0 is + used instead. + + If the calculated position + `len` exceeds `this.length`, the characters + from that position to the end of `this` String are returned. + + If `len` is negative, the result is unspecified. + **/ + public function substr(pos:Int, ?len:Int):String { + if (pos < 0) { + pos = (this : UnicodeString).length + pos; + if (pos < 0) { + pos = 0; + } + } + if (len != null) { + if (len < 0) { + len = (this : UnicodeString).length + len; + } + if (len <= 0) { + return ""; + } + } + var unicodeOffset = 0; + var nativeOffset = 0; + var fromOffset = -1; + var subLength = 0; + while (nativeOffset < this.length) { + var c = StringTools.utf16CodePointAt(this, nativeOffset); + + if (unicodeOffset >= pos) { + if (fromOffset < 0) { + if (len == null) { + return this.substr(nativeOffset); + } + fromOffset = nativeOffset; + } + subLength++; + if (subLength >= len) { + var lastOffset = (c < StringTools.MIN_SURROGATE_CODE_POINT ? nativeOffset : nativeOffset + 1); + return this.substr(fromOffset, lastOffset - fromOffset + 1); + } + } + + nativeOffset += (c >= StringTools.MIN_SURROGATE_CODE_POINT ? 2 : 1); + unicodeOffset++; + } + return (fromOffset < 0 ? "" : this.substr(fromOffset)); + } + + /** + Returns the part of `this` String from `startIndex` to but not including `endIndex`. + + If `startIndex` or `endIndex` are negative, 0 is used instead. + + If `startIndex` exceeds `endIndex`, they are swapped. + + If the (possibly swapped) `endIndex` is omitted or exceeds + `this.length`, `this.length` is used instead. + + If the (possibly swapped) `startIndex` exceeds `this.length`, the empty + String `""` is returned. + **/ + public function substring(startIndex:Int, ?endIndex:Int):String { + if (startIndex < 0) { + startIndex = 0; + } + if (endIndex != null) { + if (endIndex < 0) { + endIndex = 0; + } + if (startIndex == endIndex) { + return ""; + } + if (startIndex > endIndex) { + var tmp = startIndex; + startIndex = endIndex; + endIndex = tmp; + } + } + + var unicodeOffset = 0; + var nativeOffset = 0; + var fromOffset = -1; + var subLength = 0; + while (nativeOffset < this.length) { + var c = StringTools.utf16CodePointAt(this, nativeOffset); + + if (startIndex <= unicodeOffset) { + if (fromOffset < 0) { + if (endIndex == null) { + return this.substr(nativeOffset); + } + fromOffset = nativeOffset; + } + subLength++; + if (subLength >= endIndex - startIndex) { + var lastOffset = (c < StringTools.MIN_SURROGATE_CODE_POINT ? nativeOffset : nativeOffset + 1); + return this.substr(fromOffset, lastOffset - fromOffset + 1); + } + } + + nativeOffset += (c >= StringTools.MIN_SURROGATE_CODE_POINT ? 2 : 1); + unicodeOffset++; + } + return (fromOffset < 0 ? "" : this.substr(fromOffset)); + } + + function get_length():Int { + var l = 0; + for (c in new StringIteratorUnicode(this)) { + l++; + } + return l; + } + #end + #end + @:op(A < B) static function lt(a:UnicodeString, b:UnicodeString):Bool; + + @:op(A <= B) static function lte(a:UnicodeString, b:UnicodeString):Bool; + + @:op(A > B) static function gt(a:UnicodeString, b:UnicodeString):Bool; + + @:op(A >= B) static function gte(a:UnicodeString, b:UnicodeString):Bool; + + @:op(A == B) static function eq(a:UnicodeString, b:UnicodeString):Bool; + + @:op(A != B) static function neq(a:UnicodeString, b:UnicodeString):Bool; + + @:op(A + B) static function add(a:UnicodeString, b:UnicodeString):UnicodeString; + + @:op(A += B) static function assignAdd(a:UnicodeString, b:UnicodeString):UnicodeString; + + @:op(A + B) @:commutative static function add(a:UnicodeString, b:String):UnicodeString; + + @:op(A += B) @:commutative static function assignAdd(a:UnicodeString, b:String):UnicodeString; +} diff --git a/std/Xml.hx b/std/Xml.hx index 15e4cd51731..e9ac618f5fd 100644 --- a/std/Xml.hx +++ b/std/Xml.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,35 +25,53 @@ @see https://haxe.org/manual/std-Xml.html **/ -@:enum abstract XmlType(Int) { +enum abstract XmlType(Int) { /** Represents an XML element type. **/ var Element = 0; + /** Represents XML parsed character data type. **/ var PCData = 1; + /** Represents XML character data type. **/ var CData = 2; + /** Represents an XML comment type. **/ var Comment = 3; + /** Represents an XML doctype element type. **/ var DocType = 4; + /** - Represents an XML processing instruction type. + Represents an XML processing instruction type. **/ var ProcessingInstruction = 5; + /** Represents an XML document type. **/ var Document = 6; + + public function toString():String { + return switch (cast this : XmlType) { + case Element: "Element"; + case PCData: "PCData"; + case CData: "CData"; + case Comment: "Comment"; + case DocType: "DocType"; + case ProcessingInstruction: "ProcessingInstruction"; + case Document: "Document"; + }; + } } /** @@ -65,36 +83,42 @@ class Xml { /** XML element type. **/ - static public var Element(default,never) = XmlType.Element; + static public var Element(default, never) = XmlType.Element; + /** XML parsed character data type. **/ - static public var PCData(default,never) = XmlType.PCData; + static public var PCData(default, never) = XmlType.PCData; + /** XML character data type. **/ - static public var CData(default,never) = XmlType.CData; + static public var CData(default, never) = XmlType.CData; + /** XML comment type. **/ - static public var Comment(default,never) = XmlType.Comment; + static public var Comment(default, never) = XmlType.Comment; + /** XML doctype element type. **/ - static public var DocType(default,never) = XmlType.DocType; + static public var DocType(default, never) = XmlType.DocType; + /** - XML processing instruction type. + XML processing instruction type. **/ - static public var ProcessingInstruction(default,never) = XmlType.ProcessingInstruction; + static public var ProcessingInstruction(default, never) = XmlType.ProcessingInstruction; + /** XML document type. **/ - static public var Document(default,never) = XmlType.Document; + static public var Document(default, never) = XmlType.Document; /** Parses the String into an Xml document. **/ - static public function parse( str : String ) : Xml { + static public function parse(str:String):Xml { return haxe.xml.Parser.parse(str); } @@ -103,23 +127,23 @@ class Xml { accessing other functions since some might raise an exception if the node type is not correct. **/ - public var nodeType(default, null) : XmlType; + public var nodeType(default, null):XmlType; /** Returns the node name of an Element. **/ - @:isVar public var nodeName(get, set) : String; + @:isVar public var nodeName(get, set):String; /** Returns the node value. Only works if the Xml node is not an Element or a Document. **/ - @:isVar public var nodeValue(get, set) : String; + @:isVar public var nodeValue(get, set):String; /** Returns the parent object in the Xml hierarchy. The parent can be `null`, an Element or a Document. **/ - public var parent(default, null) : Xml; + public var parent(default, null):Xml; var children:Array; var attributeMap:Map; @@ -155,7 +179,7 @@ class Xml { /** Creates a node of the given type. **/ - static public function createElement( name : String ) : Xml { + static public function createElement(name:String):Xml { var xml = new Xml(Element); xml.nodeName = name; return xml; @@ -164,7 +188,7 @@ class Xml { /** Creates a node of the given type. **/ - static public function createPCData( data : String ) : Xml { + static public function createPCData(data:String):Xml { var xml = new Xml(PCData); xml.nodeValue = data; return xml; @@ -173,7 +197,7 @@ class Xml { /** Creates a node of the given type. **/ - static public function createCData( data : String ) : Xml { + static public function createCData(data:String):Xml { var xml = new Xml(CData); xml.nodeValue = data; return xml; @@ -182,7 +206,7 @@ class Xml { /** Creates a node of the given type. **/ - static public function createComment( data : String ) : Xml { + static public function createComment(data:String):Xml { var xml = new Xml(Comment); xml.nodeValue = data; return xml; @@ -191,7 +215,7 @@ class Xml { /** Creates a node of the given type. **/ - static public function createDocType( data : String ) : Xml { + static public function createDocType(data:String):Xml { var xml = new Xml(DocType); xml.nodeValue = data; return xml; @@ -200,7 +224,7 @@ class Xml { /** Creates a node of the given type. **/ - static public function createProcessingInstruction( data : String ) : Xml { + static public function createProcessingInstruction(data:String):Xml { var xml = new Xml(ProcessingInstruction); xml.nodeValue = data; return xml; @@ -209,7 +233,7 @@ class Xml { /** Creates a node of the given type. **/ - static public function createDocument() : Xml { + static public function createDocument():Xml { return new Xml(Document); } @@ -217,7 +241,7 @@ class Xml { Get the given attribute of an Element node. Returns `null` if not found. Attributes are case-sensitive. **/ - public function get( att : String ) : String { + public function get(att:String):String { if (nodeType != Element) { throw 'Bad node type, expected Element but found $nodeType'; } @@ -228,7 +252,7 @@ class Xml { Set the given attribute value for an Element node. Attributes are case-sensitive. **/ - public function set( att : String, value : String ) : Void { + public function set(att:String, value:String):Void { if (nodeType != Element) { throw 'Bad node type, expected Element but found $nodeType'; } @@ -239,7 +263,7 @@ class Xml { Removes an attribute for an Element node. Attributes are case-sensitive. **/ - public function remove( att : String ) : Void { + public function remove(att:String):Void { if (nodeType != Element) { throw 'Bad node type, expected Element but found $nodeType'; } @@ -250,7 +274,7 @@ class Xml { Tells if the Element node has a given attribute. Attributes are case-sensitive. **/ - public function exists( att : String ) : Bool { + public function exists(att:String):Bool { if (nodeType != Element) { throw 'Bad node type, expected Element but found $nodeType'; } @@ -260,7 +284,7 @@ class Xml { /** Returns an `Iterator` on all the attribute names. **/ - public function attributes() : Iterator { + public function attributes():Iterator { if (nodeType != Element) { throw 'Bad node type, expected Element but found $nodeType'; } @@ -271,7 +295,7 @@ class Xml { Returns an iterator of all child nodes. Only works if the current node is an Element or a Document. **/ - public #if !cppia inline #end function iterator() : Iterator { + public #if !cppia inline #end function iterator():Iterator { ensureElementType(); return children.iterator(); } @@ -280,7 +304,7 @@ class Xml { Returns an iterator of all child nodes which are Elements. Only works if the current node is an Element or a Document. **/ - public function elements() : Iterator { + public function elements():Iterator { ensureElementType(); var ret = [for (child in children) if (child.nodeType == Element) child]; return ret.iterator(); @@ -290,16 +314,19 @@ class Xml { Returns an iterator of all child nodes which are Elements with the given nodeName. Only works if the current node is an Element or a Document. **/ - public function elementsNamed( name : String ) : Iterator { + public function elementsNamed(name:String):Iterator { ensureElementType(); - var ret = [for (child in children) if (child.nodeType == Element && child.nodeName == name) child]; + var ret = [ + for (child in children) + if (child.nodeType == Element && child.nodeName == name) child + ]; return ret.iterator(); } /** Returns the first child node. **/ - public #if !cppia inline #end function firstChild() : Xml { + public #if !cppia inline #end function firstChild():Xml { ensureElementType(); return children[0]; } @@ -307,7 +334,7 @@ class Xml { /** Returns the first child node which is an Element. **/ - public function firstElement() : Xml { + public function firstElement():Xml { ensureElementType(); for (child in children) { if (child.nodeType == Element) { @@ -323,7 +350,7 @@ class Xml { If the child is already inside this Document or Element, it will be moved to the last position among the Document or Element's children. If the child node was previously inside a different node, it will be moved to this Document or Element. **/ - public function addChild( x : Xml ) : Void { + public function addChild(x:Xml):Void { ensureElementType(); if (x.parent != null) { x.parent.removeChild(x); @@ -336,7 +363,7 @@ class Xml { Removes a child from the Document or Element. Returns true if the child was successfuly removed. **/ - public function removeChild( x : Xml ) : Bool { + public function removeChild(x:Xml):Bool { ensureElementType(); if (children.remove(x)) { x.parent = null; @@ -351,7 +378,7 @@ class Xml { If the child is already inside this Document or Element, it will be moved to the new position among the Document or Element's children. If the child node was previously inside a different node, it will be moved to this Document or Element. **/ - public function insertChild( x : Xml, pos : Int ) : Void { + public function insertChild(x:Xml, pos:Int):Void { ensureElementType(); if (x.parent != null) { x.parent.children.remove(x); @@ -363,7 +390,7 @@ class Xml { /** Returns a String representation of the Xml node. **/ - public #if !cppia inline #end function toString() : String { + public #if !cppia inline #end function toString():String { return haxe.xml.Printer.print(this); } diff --git a/std/cpp/ArrayBase.hx b/std/cpp/ArrayBase.hx index 518db9a426f..a51154e3232 100644 --- a/std/cpp/ArrayBase.hx +++ b/std/cpp/ArrayBase.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; -extern class ArrayBase -{ - // Length is number of elements - public var length(default,null):Int; - public function getElementSize():Int; - public function getByteCount():Int; - public function getBase():RawPointer; -} +package cpp; +extern class ArrayBase { + // Length is number of elements + public var length(default, null):Int; + public function getElementSize():Int; + public function getByteCount():Int; + public function getBase():RawPointer; +} diff --git a/std/cpp/AtomicInt.hx b/std/cpp/AtomicInt.hx index cc88d8c07f1..f84e866c76c 100644 --- a/std/cpp/AtomicInt.hx +++ b/std/cpp/AtomicInt.hx @@ -1,18 +1,44 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; @:scalar @:coreType -extern abstract AtomicInt from(Int) to(Int) -{ - // returns true if exchange took place - @:native("_hx_atomic_exchange_if") - public static function exchangeIf(ioValue:Pointer, test:Int, newVal:Int) : Bool; +extern abstract AtomicInt from(Int) to(Int) { + /** + Returns true if exchange took place. + **/ + @:native("_hx_atomic_exchange_if") + public static function exchangeIf(ioValue:Pointer, test:Int, newVal:Int):Bool; - // returns value before increment - @:native("_hx_atomic_inc") - public static function atomicInc(ioValue:Pointer) : Int; + /** + Returns value before increment. + **/ + @:native("_hx_atomic_inc") + public static function atomicInc(ioValue:Pointer):Int; - // returns value before decrement - @:native("_hx_atomic_dec") - public static function atomicDec(ioValue:Pointer) : Int; + /** + Returns value before decrement. + **/ + @:native("_hx_atomic_dec") + public static function atomicDec(ioValue:Pointer):Int; } - diff --git a/std/cpp/AutoCast.hx b/std/cpp/AutoCast.hx index f7fe302abb5..2a0900cec76 100644 --- a/std/cpp/AutoCast.hx +++ b/std/cpp/AutoCast.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; -extern class AutoCast { } +extern class AutoCast {} diff --git a/std/cpp/Callable.hx b/std/cpp/Callable.hx index c57c4df068a..85fd050c62d 100644 --- a/std/cpp/Callable.hx +++ b/std/cpp/Callable.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,40 +19,54 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp; +package cpp; @:noPackageRestrict @:callable typedef CallableData = T; -// The generator intercepts this type and converts it to a cpp.Function on cpp -@:noPackageRestrict @:callable -#if cpp extern #end -abstract Callable( CallableData ) -{ - inline public function new(inValue:T) this = inValue; - public var call(get,never):CallableData; - inline function get_call():CallableData return this; - - #if cpp - @:from - inline static public function fromFunction( func:Function ) : Callable - return new Callable(cast func); - @:to - inline public function toFunction() : Function return cast this; - - - inline public static function getProcAddress(inModule:String, inFunction:String) : Function - return Function.getProcAddress(inModule, inFunction); - - inline public static function fromStaticFunction(inStaticFunction:T) : Callable - return Function.fromStaticFunction(inStaticFunction); - - inline public function lt(inOther:Callable):Bool return toFunction().lt(inOther.toFunction()); - inline public function leq(inOther:Callable):Bool return toFunction().leq(inOther.toFunction()); - inline public function gt(inOther:Callable):Bool return toFunction().gt(inOther.toFunction()); - inline public function geq(inOther:Callable):Bool return toFunction().geq(inOther.toFunction()); - #end -} +/** + The generator intercepts this type and converts it to a cpp.Function on cpp. +**/ +@:noPackageRestrict +@:callable +#if cpp +extern +#end +abstract Callable(CallableData) { + inline public function new(inValue:T) + this = inValue; + + public var call(get, never):CallableData; + + inline function get_call():CallableData + return this; + + #if cpp + @:from + inline static public function fromFunction(func:Function):Callable + return new Callable(cast func); + @:to + inline public function toFunction():Function + return cast this; + inline public static function getProcAddress(inModule:String, inFunction:String):Function + return Function.getProcAddress(inModule, inFunction); + + inline public static function fromStaticFunction(inStaticFunction:T):Callable + return Function.fromStaticFunction(inStaticFunction); + + inline public function lt(inOther:Callable):Bool + return toFunction().lt(inOther.toFunction()); + + inline public function leq(inOther:Callable):Bool + return toFunction().leq(inOther.toFunction()); + + inline public function gt(inOther:Callable):Bool + return toFunction().gt(inOther.toFunction()); + + inline public function geq(inOther:Callable):Bool + return toFunction().geq(inOther.toFunction()); + #end +} diff --git a/std/cpp/CastCharStar.hx b/std/cpp/CastCharStar.hx index fb91fb981c2..dc78863b09c 100644 --- a/std/cpp/CastCharStar.hx +++ b/std/cpp/CastCharStar.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,16 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; -abstract CastCharStar( RawPointer ) to(RawPointer) -{ - inline function new(s:String) this = cast untyped s.__s; +package cpp; - @:from - static public inline function fromString(s:String) return new CastCharStar(s); +abstract CastCharStar(RawPointer) to(RawPointer) { + inline function new(s:String) + this = cast untyped s.__s; - @:to - public inline function toPointer() return this; -} + @:from + static public inline function fromString(s:String) + return new CastCharStar(s); + @:to + public inline function toPointer() + return this; +} diff --git a/std/cpp/Char.hx b/std/cpp/Char.hx index 5524efa6f17..dec9d8888b4 100644 --- a/std/cpp/Char.hx +++ b/std/cpp/Char.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract Char from Int to Int {} diff --git a/std/cpp/ConstCharStar.hx b/std/cpp/ConstCharStar.hx index 5c7cd822543..04d3268b17d 100644 --- a/std/cpp/ConstCharStar.hx +++ b/std/cpp/ConstCharStar.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,19 +19,20 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; -@:extern abstract ConstCharStar( RawConstPointer ) to(RawConstPointer) -{ - inline function new(s:String) this = untyped s.__s; +package cpp; - @:from - static public inline function fromString(s:String) return new ConstCharStar(s); +extern abstract ConstCharStar(RawConstPointer) to(RawConstPointer) { + inline function new(s:String) + this = untyped s.__s; - @:to @:extern - public inline function toString():String return new String(untyped this); + @:from + static public inline function fromString(s:String):ConstCharStar + return new ConstCharStar(s); - @:to @:extern - public inline function toPointer() return this; -} + @:to extern public inline function toString():String + return new String(untyped this); + @:to extern public inline function toPointer():RawConstPointer + return this; +} diff --git a/std/cpp/ConstPointer.hx b/std/cpp/ConstPointer.hx index 3d1225c334b..ec2e2f5d1d3 100644 --- a/std/cpp/ConstPointer.hx +++ b/std/cpp/ConstPointer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,52 +19,51 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; -@:coreType @:include("cpp/Pointer.h") @:native("cpp.Pointer") @:analyzer(as_var) -extern class ConstPointer -{ - // ptr actually returns the pointer - not strictly a 'T' - for pointers to smart pointers - // Use value or ref to get dereferenced value - public var ptr:Star; +package cpp; - public var value(get,never):T; +@:coreType @:include("cpp/Pointer.h") @:native("cpp.Pointer") @:semantics(variable) +extern class ConstPointer { + // ptr actually returns the pointer - not strictly a 'T' - for pointers to smart pointers + // Use value or ref to get dereferenced value + public var ptr:Star; - // Typecast to non-const - public var raw(get,never):RawPointer; + public var value(get, never):T; - // const version - public var constRaw(get,never):RawConstPointer; + // Typecast to non-const + public var raw(get, never):RawPointer; - public function get_value() : Reference; + // const version + public var constRaw(get, never):RawConstPointer; - public function get_constRaw() : RawConstPointer; - public function get_raw() : RawPointer; + public function get_value():Reference; + public function get_constRaw():RawConstPointer; + public function get_raw():RawPointer; - public function lt(inOther:ConstPointer):Bool; - public function leq(inOther:ConstPointer):Bool; - public function gt(inOther:ConstPointer):Bool; - public function geq(inOther:ConstPointer):Bool; + public function lt(inOther:ConstPointer):Bool; + public function leq(inOther:ConstPointer):Bool; + public function gt(inOther:ConstPointer):Bool; + public function geq(inOther:ConstPointer):Bool; - public function setRaw(ptr:RawPointer) : Void; + public function setRaw(ptr:RawPointer):Void; - public static function fromRaw(ptr:RawConstPointer) : ConstPointer; + public static function fromRaw(ptr:RawConstPointer):ConstPointer; + @:native("::cpp::Pointer_obj::fromRaw") + public static function fromStar(star:Star):ConstPointer; - public static function fromPointer(inNativePointer:Dynamic) : ConstPointer; + public static function fromPointer(inNativePointer:Dynamic):ConstPointer; - public function reinterpret():Pointer; + public function reinterpret():Pointer; - public function rawCast():RawPointer; + public function rawCast():RawPointer; - public function at(inIndex:Int):Reference; - - public function inc():ConstPointer; - public function dec():ConstPointer; - public function postIncVal():Reference; - public function incBy(inT:Int):ConstPointer; - public function add(inT:Int):ConstPointer; + public function at(inIndex:Int):Reference; + public function inc():ConstPointer; + public function dec():ConstPointer; + public function postIncVal():Reference; + public function incBy(inT:Int):ConstPointer; + public function add(inT:Int):ConstPointer; } - diff --git a/std/cpp/ConstStar.hx b/std/cpp/ConstStar.hx index 43df45a23fa..b99fe00e545 100644 --- a/std/cpp/ConstStar.hx +++ b/std/cpp/ConstStar.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,9 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp; - -// Allows haxe to type result correctly, and hxcpp can recognise this use the correct type -typedef ConstStar = T; +package cpp; +/** + Allows haxe to type the result correctly, and hxcpp can recognise this uses + the correct type. +**/ +typedef ConstStar = Null; diff --git a/std/cpp/EnumBase.hx b/std/cpp/EnumBase.hx index 9cb66493f2c..507d12f14b7 100644 --- a/std/cpp/EnumBase.hx +++ b/std/cpp/EnumBase.hx @@ -1,31 +1,60 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; @:native("hx.EnumBase") -extern class EnumBase -{ - #if (hxcpp_api_level >= 330) - public function _hx_getIndex():Int; - public function _hx_getTag():String; - public function _hx_getParamCount():Int; - public function _hx_getParamI(inIndex:Int):Dynamic; - public function _hx_getParameters():Array; - - inline public function getIndex():Int return _hx_getIndex(); - inline public function getTag():String return _hx_getTag(); - inline public function getParamCount():Int return _hx_getParamCount(); - inline public function getParamI(inIndex:Int):Dynamic return _hx_getParamI(inIndex); - inline public function getParameters():Array return _hx_getParameters(); - #else - public function __EnumParams():Array; - public function __Tag():String; - public function __Index():Int; +extern class EnumBase { + #if (hxcpp_api_level >= 330) + public function _hx_getIndex():Int; + public function _hx_getTag():String; + public function _hx_getParamCount():Int; + public function _hx_getParamI(inIndex:Int):Dynamic; + public function _hx_getParameters():Array; - inline public function _hx_getIndex():Int return untyped __Index(); - inline public function _hx_getTag():String return untyped __Tag(); - inline public function _hx_getParamCount():Int return untyped __EnumParams()==null ? 0 : __EnumParams().length; - inline public function _hx_getParamI(inIndex:Int):Dynamic return untyped __EnumParams()[inIndex]; - inline public function _hx_getParameters():Array return __EnumParams()==null ? [] : __EnumParams(); + inline public function getIndex():Int + return _hx_getIndex(); + inline public function getTag():String + return _hx_getTag(); + inline public function getParamCount():Int + return _hx_getParamCount(); + inline public function getParamI(inIndex:Int):Dynamic + return _hx_getParamI(inIndex); + inline public function getParameters():Array + return _hx_getParameters(); + #else + public function __EnumParams():Array; + public function __Tag():String; + public function __Index():Int; - #end + inline public function _hx_getIndex():Int + return untyped __Index(); + inline public function _hx_getTag():String + return untyped __Tag(); + inline public function _hx_getParamCount():Int + return untyped __EnumParams() == null ? 0 : __EnumParams().length; + inline public function _hx_getParamI(inIndex:Int):Dynamic + return untyped __EnumParams()[inIndex]; + inline public function _hx_getParameters():Array + return __EnumParams() == null ? [] : __EnumParams(); + #end } - diff --git a/std/cpp/ErrorConstants.hx b/std/cpp/ErrorConstants.hx index 395127a2eaf..837e605ddde 100644 --- a/std/cpp/ErrorConstants.hx +++ b/std/cpp/ErrorConstants.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,21 +22,19 @@ package cpp; -extern class ErrorConstants -{ - @:native("HX_INVALID_CAST") - public static var invalidCast:Dynamic; +extern class ErrorConstants { + @:native("HX_INVALID_CAST") + public static var invalidCast:Dynamic; - @:native("HX_INDEX_OUT_OF_BOUNDS") - public static var indexOutOfBounds:Dynamic; + @:native("HX_INDEX_OUT_OF_BOUNDS") + public static var indexOutOfBounds:Dynamic; - @:native("HX_INVALID_OBJECT") - public static var invalidObject:Dynamic; + @:native("HX_INVALID_OBJECT") + public static var invalidObject:Dynamic; - @:native("HX_INVALID_ARG_COUNT") - public static var invalidArgCount:Dynamic; + @:native("HX_INVALID_ARG_COUNT") + public static var invalidArgCount:Dynamic; - @:native("HX_NULL_FUNCTION_POINTER") - public static var nullFunctionPointer:Dynamic; + @:native("HX_NULL_FUNCTION_POINTER") + public static var nullFunctionPointer:Dynamic; } - diff --git a/std/cpp/FILE.hx b/std/cpp/FILE.hx index f80371d979f..c22f24093fc 100644 --- a/std/cpp/FILE.hx +++ b/std/cpp/FILE.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,5 +24,4 @@ package cpp; @:include("stdio.h") @:native(" ::cpp::Pointer") -extern class FILE { } - +extern class FILE {} diff --git a/std/cpp/FastIterator.hx b/std/cpp/FastIterator.hx index b64f4179387..e5955e8d041 100644 --- a/std/cpp/FastIterator.hx +++ b/std/cpp/FastIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,10 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; -extern class FastIterator -{ +extern class FastIterator { public function hasNext():Bool; public function next():T; } - diff --git a/std/cpp/Finalizable.hx b/std/cpp/Finalizable.hx index 31a086ac1a2..02287270a39 100644 --- a/std/cpp/Finalizable.hx +++ b/std/cpp/Finalizable.hx @@ -1,14 +1,36 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; -// This is just a helper class. You do not actually need to inherit from this to use -// NativeGc.addFinalizable(this,inPin), you just need a function called "finalize" -class Finalizable -{ - public function new(inPin = false) - { - NativeGc.addFinalizable(this,inPin); - } +/** + This is just a helper class. It is not actually required to inherit from this + to use `NativeGc.addFinalizable(this,inPin)`, only a function called + `finalize` is needed. +**/ +class Finalizable { + public function new(inPin = false) { + NativeGc.addFinalizable(this, inPin); + } - public function finalize():Void { } + public function finalize():Void {} } - diff --git a/std/cpp/Float32.hx b/std/cpp/Float32.hx index 7b852f032a3..c00c1454598 100644 --- a/std/cpp/Float32.hx +++ b/std/cpp/Float32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract Float32 from Float to Float {} diff --git a/std/cpp/Float64.hx b/std/cpp/Float64.hx index 1bf957fda49..bd4b376b2c8 100644 --- a/std/cpp/Float64.hx +++ b/std/cpp/Float64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract Float64 from Float to Float {} diff --git a/std/cpp/Function.hx b/std/cpp/Function.hx index 2b4b52ec68c..22d0b4a860a 100644 --- a/std/cpp/Function.hx +++ b/std/cpp/Function.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,41 +19,42 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; @:callable -typedef FunctionData = T; - +typedef FunctionData = T; @:include("cpp/Pointer.h") @:callable -extern abstract Function( FunctionData ) -{ - inline public function new(inValue:T) this = inValue; - - // Legacy Api - public var call(get,never):FunctionData; - inline function get_call():FunctionData return this; - - - @:native("::cpp::Function_obj::getProcAddress") - @:extern static function nativeGetProcAddress(inModule:String, inFunction:String) : AutoCast return null; - inline public static function getProcAddress(inModule:String, inFunction:String) : Function - { - return cast nativeGetProcAddress(inModule, inFunction); - } - - @:native("::cpp::Function_obj::fromStaticFunction") - @:extern static function nativeFromStaticFunction(inStaticFunction:T) : AutoCast return null; - inline public static function fromStaticFunction(inStaticFunction:T) : Callable - { - return cast nativeFromStaticFunction(inStaticFunction); - } - - @:extern public function lt(inOther:Function):Bool return false; - @:extern public function leq(inOther:Function):Bool return false; - @:extern public function gt(inOther:Function):Bool return false; - @:extern public function geq(inOther:Function):Bool return false; -} +extern abstract Function(FunctionData) { + inline public function new(inValue:T) + this = inValue; + + // Legacy Api + public var call(get, never):FunctionData; + + inline function get_call():FunctionData + return this; + + @:native("::cpp::Function_obj::getProcAddress") + extern static function nativeGetProcAddress(inModule:String, inFunction:String):AutoCast; + inline public static function getProcAddress(inModule:String, inFunction:String):Function { + return cast nativeGetProcAddress(inModule, inFunction); + } + @:native("::cpp::Function_obj::fromStaticFunction") + extern static function nativeFromStaticFunction(inStaticFunction:T):AutoCast; + inline public static function fromStaticFunction(inStaticFunction:T):Callable { + return cast nativeFromStaticFunction(inStaticFunction); + } + + extern public function lt(inOther:Function):Bool; + + extern public function leq(inOther:Function):Bool; + + extern public function gt(inOther:Function):Bool; + + extern public function geq(inOther:Function):Bool; +} diff --git a/std/cpp/Int16.hx b/std/cpp/Int16.hx index 0b67d0d3470..713e1666c42 100644 --- a/std/cpp/Int16.hx +++ b/std/cpp/Int16.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract Int16 from Int to Int {} diff --git a/std/cpp/Int32.hx b/std/cpp/Int32.hx index 625499018d6..d60bd648464 100644 --- a/std/cpp/Int32.hx +++ b/std/cpp/Int32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract Int32 from Int to Int {} diff --git a/std/cpp/Int64.hx b/std/cpp/Int64.hx index b10e041f685..2e69337e8f3 100644 --- a/std/cpp/Int64.hx +++ b/std/cpp/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract Int64 from Int to Int {} diff --git a/std/cpp/Int8.hx b/std/cpp/Int8.hx index 844cdd3e2c4..faae9d7e1d6 100644 --- a/std/cpp/Int8.hx +++ b/std/cpp/Int8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract Int8 from Int to Int {} diff --git a/std/cpp/Lib.hx b/std/cpp/Lib.hx index aec125a4317..30696bdc270 100644 --- a/std/cpp/Lib.hx +++ b/std/cpp/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; /** @@ -27,15 +28,14 @@ package cpp; and vice-versa. **/ class Lib { - /** Load and return a Cpp primitive from a DLL library. **/ - public static function load( lib : String, prim : String, nargs : Int ) : Dynamic { + public static function load(lib:String, prim:String, nargs:Int):Dynamic { #if (iphone || emscripten) - return loadLazy(lib,prim,nargs); + return loadLazy(lib, prim, nargs); #else - return untyped __global__.__loadprim(lib,prim,nargs); + return untyped __global__.__loadprim(lib, prim, nargs); #end } @@ -43,64 +43,62 @@ class Lib { Unloaded all dynamic libraries in reverse order of loading. Returns the number of libraries unloaded. **/ - public static function unloadAllLibraries() : Int { + public static function unloadAllLibraries():Int { return untyped __global__.__hxcpp_unload_all_libraries(); } - public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic { - var factory:Callable< ConstCharStar -> Object > = - untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail); - if (factory!=null) - { + public static function _loadPrime(lib:String, prim:String, signature:String, quietFail = false):Dynamic { + var factory:CallableObject> = untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail); + if (factory != null) { var func:Dynamic = factory.call(signature); - if (func==null && !quietFail) + if (func == null && !quietFail) throw '$prim does not have signature $signature'; return func; } return null; } - /** Tries to load, and always returns a valid function, but the function may throw if called. **/ - public static function loadLazy(lib:String, prim:String, nargs:Int) : Dynamic { + public static function loadLazy(lib:String, prim:String, nargs:Int):Dynamic { try { - return untyped __global__.__loadprim(lib,prim,nargs); - } catch( e : Dynamic ) { - switch(nargs) { - case 0 : return function() { throw e; }; - case 2 : return function(_1,_2) { throw e; }; - case 3 : return function(_1,_2,_3) { throw e; }; - case 4 : return function(_1,_2,_3,_4) { throw e; }; - case 5 : return function(_1,_2,_3,_4,_5) { throw e; }; - default : return function(_1) { throw e; }; - } + return untyped __global__.__loadprim(lib, prim, nargs); + } catch (e:Dynamic) { + return switch (nargs) { + case 0: () -> throw e; + case 2: (_, _) -> throw e; + case 3: (_, _, _) -> throw e; + case 4: (_, _, _, _) -> throw e; + case 5: (_, _, _, _, _) -> throw e; + default: _ -> throw e; + }; } return null; } - @:extern @:noDebug @:native("HX_STACK_DO_RETHROW") - static function do_rethrow(inExp:Dynamic) { throw inExp; } + @:noDebug @:native("HX_STACK_DO_RETHROW") + extern static function do_rethrow(inExp:Dynamic); - @:noDebug #if(!cppia) inline #end - public static function rethrow(inExp:Dynamic) { do_rethrow(inExp); } + @:noDebug #if (!cppia) inline #end + public static function rethrow(inExp:Dynamic) { + do_rethrow(inExp); + } - public static function stringReference(inBytes:haxe.io.Bytes) : String - { + public static function stringReference(inBytes:haxe.io.Bytes):String { var result:String = ""; untyped __global__.__hxcpp_string_of_bytes(inBytes.b, result, 0, 0, true); return result; } - public static function pushDllSearchPath(inPath:String) : Void + public static function pushDllSearchPath(inPath:String):Void untyped __global__.__hxcpp_push_dll_path(inPath); - public static function getDllExtension() : String + public static function getDllExtension():String return untyped __global__.__hxcpp_get_dll_extension(); - public static function getBinDirectory() : String + public static function getBinDirectory():String return untyped __global__.__hxcpp_get_bin_dir(); /** @@ -109,7 +107,7 @@ class Lib { Changing one string can cause others to change unexpectedly. Only really safe if you are using it read-only or if it comes from stringReference above **/ - public inline static function bytesReference( s : String ) : haxe.io.Bytes { + public inline static function bytesReference(s:String):haxe.io.Bytes { var bytes = new haxe.io.BytesData(); untyped bytes.__unsafeStringReference(s); return haxe.io.Bytes.ofData(bytes); @@ -118,7 +116,7 @@ class Lib { /** Print the specified value on the default output. **/ - public static function print( v : Dynamic ) : Void { + public static function print(v:Dynamic):Void { untyped __global__.__hxcpp_print(v); } @@ -126,7 +124,7 @@ class Lib { This function is used to make porting from neko to cpp easy. It does not need to do anything because the c-code can work with any Dynamic **/ - public static function haxeToNeko( v : Dynamic ) : Dynamic { + public static function haxeToNeko(v:Dynamic):Dynamic { return v; } @@ -134,19 +132,18 @@ class Lib { This function is used to make porting from neko to cpp easy. It does not need to do anything because the c-code can work with any Dynamic **/ - public static function nekoToHaxe( v : Dynamic ) : Dynamic { + public static function nekoToHaxe(v:Dynamic):Dynamic { return v; } + /** Print the specified value on the default output followed by a newline character. **/ - public static function println( v : Dynamic ) : Void { + public static function println(v:Dynamic):Void { untyped __global__.__hxcpp_println(v); } - public static function setFloatFormat(inFormat:String):Void - { + public static function setFloatFormat(inFormat:String):Void { untyped __global__.__hxcpp_set_float_format(inFormat); } - } diff --git a/std/cpp/Native.hx b/std/cpp/Native.hx new file mode 100644 index 00000000000..d900b089d9e --- /dev/null +++ b/std/cpp/Native.hx @@ -0,0 +1,103 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package cpp; + +@:include("stdlib.h") +extern class Native { + @:native("malloc") + public static function nativeMalloc(bytes:Int):cpp.Star; + @:native("calloc") + public static function nativeCalloc(bytes:Int):cpp.Star; + @:native("realloc") + public static function nativeRealloc(inPtr:cpp.Star, bytes:Int):cpp.RawPointer; + @:native("free") + public static function nativeFree(ptr:cpp.Star):Void; + @:native("memcpy") + public static function nativeMemcpy(dest:cpp.Star, src:cpp.Star, bytes:Int):Void; + + @:native("hx::ClassSizeOf") @:templatedCall + public static function sizeof(t:T):Int; + + #if !cppia + @:native("hx::Dereference") + public static function star(ptr:cpp.Star):cpp.Reference; + + @:generic + public static inline function set(ptr:cpp.Star, value:T):Void { + var ref:cpp.Reference = star(ptr); + ref = value; + } + @:generic + public static inline function get(ptr:cpp.Star):T { + var ref:cpp.Reference = star(ptr); + return ref; + } + + @:generic + public static inline function memcpy(dest:cpp.Star, src:cpp.Star, bytes:Int):Void + nativeMemcpy(cast dest, cast src, bytes); + + @:generic + public static inline function malloc(bytes:Int):cpp.Star + return cast nativeMalloc(bytes); + + @:generic + public static inline function calloc(bytes:Int):cpp.Star + return cast nativeCalloc(bytes); + + @:generic + public static inline function realloc(ioPtr:cpp.Star, bytes:Int):cpp.Star + return cast nativeRealloc(cast ioPtr, bytes); + + @:generic + public static inline function free(ptr:cpp.Star):Void { + if (ptr != null) + nativeFree(cast ptr); + } + + @:native("hx::StarOf") + public static function addressOf(inVariable:Reference):Star; + #else + public static inline function addressOf(inVariable:Reference):Star { + throw "Native.addressOf not available in cppia"; + } + public static inline function star(ptr:cpp.Star):cpp.Reference { + throw "Native.star not available in cppia"; + } + + public static inline function set(ptr:cpp.Star, value:T):Void { + throw "Native.set not available in cppia"; + } + public static inline function get(ptr:cpp.Star):T { + throw "Native.get not available in cppia"; + var d:Dynamic = null; + return d; + } + + public static function memcpy(dest:cpp.Star, src:cpp.Star, bytes:Int):Void; + public static function malloc(bytes:Int):cpp.Star; + public static function calloc(bytes:Int):cpp.Star; + public static function realloc(ioPtr:cpp.Star, bytes:Int):cpp.Star; + public static function free(ptr:cpp.Star):Void; + #end +} diff --git a/std/cpp/NativeArc.hx b/std/cpp/NativeArc.hx index 286b7147b95..be889cc2a3c 100644 --- a/std/cpp/NativeArc.hx +++ b/std/cpp/NativeArc.hx @@ -1,12 +1,31 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; -extern class NativeArc -{ - @:native("(__bridge_transfer id)") - public static function _bridgeTransfer(ptr:cpp.RawPointer ):cpp.RawPointer; +extern class NativeArc { + @:native("(__bridge_transfer id)") + public static function _bridgeTransfer(ptr:cpp.RawPointer):cpp.RawPointer; - public static inline function bridgeTransfer(ptr:cpp.RawPointer ):T return cast _bridgeTransfer(ptr); + public static inline function bridgeTransfer(ptr:cpp.RawPointer):T + return cast _bridgeTransfer(ptr); } - - - diff --git a/std/cpp/NativeArray.hx b/std/cpp/NativeArray.hx index 05bec6222b0..e065edd56ae 100644 --- a/std/cpp/NativeArray.hx +++ b/std/cpp/NativeArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,87 +19,79 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; -extern class NativeArray { - - #if cppia - public static inline function create(length:Int):Array - { - var result = new Array(); - NativeArray.setSize(result,length); - return result; - } - - #else +package cpp; - @:native("_hx_create_array_length") - public static function create(length:Int):Array; - #end +extern class NativeArray { + #if cppia + public static inline function create(length:Int):Array { + var result = new Array(); + NativeArray.setSize(result, length); + return result; + } + #else + @:native("_hx_create_array_length") + public static function create(length:Int):Array; + #end - public static inline function blit( ioDestArray:Array, - inDestElement:Int, inSourceArray:Array, - inSourceElement:Int, inElementCount:Int ): Void { - untyped ioDestArray.blit(inDestElement, inSourceArray, inSourceElement, inElementCount); + public static inline function blit(ioDestArray:Array, inDestElement:Int, inSourceArray:Array, inSourceElement:Int, inElementCount:Int):Void { + untyped ioDestArray.blit(inDestElement, inSourceArray, inSourceElement, inElementCount); }; - public static inline function getBase( inArray:Array ) : ArrayBase { - return untyped inArray; - } - - @:nativeStaticExtension - public static function reserve( inArray:Array,inElements:Int ) : Void { } + public static inline function getBase(inArray:Array):ArrayBase { + return untyped inArray; + } - @:nativeStaticExtension - public static function capacity( inArray:Array ) : Int { } + @:nativeStaticExtension + public static function reserve(inArray:Array, inElements:Int):Void; - @:nativeStaticExtension - public static function getElementSize( inArray:Array ) : Int { } + @:nativeStaticExtension + public static function capacity(inArray:Array):Int; - public static inline function address( inArray:Array,inIndex:Int ) : Pointer { - return Pointer.arrayElem(inArray,inIndex); - } + @:nativeStaticExtension + public static function getElementSize(inArray:Array):Int; - @:nativeStaticExtension - public static function setData( inArray:Array,inData:Pointer,inElementCount:Int ) : Void { } + public static inline function address(inArray:Array, inIndex:Int):Pointer { + return Pointer.arrayElem(inArray, inIndex); + } - @:nativeStaticExtension - public static function setUnmanagedData( inArray:Array,inData:ConstPointer,inElementCount:Int ) : Void { } + @:nativeStaticExtension + public static function setData(inArray:Array, inData:Pointer, inElementCount:Int):Void; - @:nativeStaticExtension - public static function zero( ioDestArray:Array, ?inFirst:Int, ?inElements:Int ) : Void { }; + @:nativeStaticExtension + public static function setUnmanagedData(inArray:Array, inData:ConstPointer, inElementCount:Int):Void; - @:nativeStaticExtension - public static function memcmp( inArrayA:Array, inArrayB:Array) : Int { } + @:nativeStaticExtension + public static function zero(ioDestArray:Array, ?inFirst:Int, ?inElements:Int):Void; - @:native("_hx_reslove_virtual_array") - public static function resolveVirtualArray( inArray:Array) : Dynamic { } + @:nativeStaticExtension + public static function memcmp(inArrayA:Array, inArrayB:Array):Int; + @:native("_hx_reslove_virtual_array") + public static function resolveVirtualArray(inArray:Array):Dynamic; - #if cppia - public static inline function unsafeGet( inDestArray:Array, inIndex:Int) : T { + #if cppia + public static inline function unsafeGet(inDestArray:Array, inIndex:Int):T { return untyped inDestArray.__unsafe_get(inIndex); } - public static inline function unsafeSet( ioDestArray:Array, inIndex:Int, inValue:T) : T { - return untyped ioDestArray.__unsafe_set(inIndex,inValue); + public static inline function unsafeSet(ioDestArray:Array, inIndex:Int, inValue:T):T { + return untyped ioDestArray.__unsafe_set(inIndex, inValue); } - public static inline function setSize( ioArray:Array, inSize:Int) : Array { + public static inline function setSize(ioArray:Array, inSize:Int):Array { return untyped ioArray.__SetSizeExact(inSize); - } - - #else - @:native("_hx_array_unsafe_get") - public static function unsafeGet( inDestArray:Array, inIndex:Int) : T { return untyped null; } - - @:native("_hx_array_unsafe_set") - public static inline function unsafeSet( ioDestArray:Array, inIndex:Int, inValue:T) : T { - return untyped ioDestArray.__unsafe_set(inIndex,inValue); } + #else + @:native("_hx_array_unsafe_get") + public static function unsafeGet(inDestArray:Array, inIndex:Int):T; - @:native("_hx_array_set_size_exact") - public static function setSize( ioArray:Array, inSize:Int) : Array return null; - #end + @:native("_hx_array_unsafe_set") + public static inline function unsafeSet(ioDestArray:Array, inIndex:Int, inValue:T):T { + return untyped ioDestArray.__unsafe_set(inIndex, inValue); + } + @:native("_hx_array_set_size_exact") + public static function setSize(ioArray:Array, inSize:Int):Array; + #end } diff --git a/std/cpp/NativeFile.hx b/std/cpp/NativeFile.hx index 1caaf9b23de..add849a8337 100644 --- a/std/cpp/NativeFile.hx +++ b/std/cpp/NativeFile.hx @@ -1,64 +1,71 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; @:buildXml('') -extern class NativeFile -{ - @:extern @:native("_hx_std_file_open") - public static function file_open(fname:String,r:String) : Dynamic return null; - - @:extern @:native("_hx_std_file_close") - public static function file_close(handle:Dynamic) : Void { } - - - @:extern @:native("_hx_std_file_write") - public static function file_write(handle:Dynamic,s:haxe.io.BytesData,p:Int,n:Int) : Int return 0; - - - @:extern @:native("_hx_std_file_write_char") - public static function file_write_char(handle:Dynamic,c:Int) : Void { } - - - @:extern @:native("_hx_std_file_read") - public static function file_read(handle:Dynamic,s:haxe.io.BytesData,p:Int,n:Int) : Int return 0; - - - @:extern @:native("_hx_std_file_read_char") - public static function file_read_char(handle:Dynamic) : Int return 0; - - - @:extern @:native("_hx_std_file_seek") - public static function file_seek(handle:Dynamic,pos:Int,kind:Int) : Void { } - - - @:extern @:native("_hx_std_file_tell") - public static function file_tell(handle:Dynamic) : Int return 0; - +extern class NativeFile { + @:native("_hx_std_file_open") + extern public static function file_open(fname:String, r:String):Dynamic; - @:extern @:native("_hx_std_file_eof") - public static function file_eof(handle:Dynamic) : Bool return false; + @:native("_hx_std_file_close") + extern public static function file_close(handle:Dynamic):Void; + @:native("_hx_std_file_write") + extern public static function file_write(handle:Dynamic, s:haxe.io.BytesData, p:Int, n:Int):Int; - @:extern @:native("_hx_std_file_flush") - public static function file_flush(handle:Dynamic) : Void return null; + @:native("_hx_std_file_write_char") + extern public static function file_write_char(handle:Dynamic, c:Int):Void; + @:native("_hx_std_file_read") + extern public static function file_read(handle:Dynamic, s:haxe.io.BytesData, p:Int, n:Int):Int; - @:extern @:native("_hx_std_file_contents_string") - public static function file_contents_string(name:String) : String return null; + @:native("_hx_std_file_read_char") + extern public static function file_read_char(handle:Dynamic):Int; + @:native("_hx_std_file_seek") + extern public static function file_seek(handle:Dynamic, pos:Int, kind:Int):Void; - @:extern @:native("_hx_std_file_contents_bytes") - public static function file_contents_bytes(name:String) : haxe.io.BytesData return null; + @:native("_hx_std_file_tell") + extern public static function file_tell(handle:Dynamic):Int; + @:native("_hx_std_file_eof") + extern public static function file_eof(handle:Dynamic):Bool; - @:extern @:native("_hx_std_file_stdin") - public static function file_stdin() : Dynamic return null; + @:native("_hx_std_file_flush") + extern public static function file_flush(handle:Dynamic):Void; + @:native("_hx_std_file_contents_string") + extern public static function file_contents_string(name:String):String; - @:extern @:native("_hx_std_file_stdout") - public static function file_stdout() : Dynamic return null; + @:native("_hx_std_file_contents_bytes") + extern public static function file_contents_bytes(name:String):haxe.io.BytesData; + @:native("_hx_std_file_stdin") + extern public static function file_stdin():Dynamic; - @:extern @:native("_hx_std_file_stderr") - public static function file_stderr() : Dynamic return null; + @:native("_hx_std_file_stdout") + extern public static function file_stdout():Dynamic; + @:native("_hx_std_file_stderr") + extern public static function file_stderr():Dynamic; } diff --git a/std/cpp/NativeGc.hx b/std/cpp/NativeGc.hx index 6dd40115af6..ed0662e3f9d 100644 --- a/std/cpp/NativeGc.hx +++ b/std/cpp/NativeGc.hx @@ -1,59 +1,65 @@ -package cpp; +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ -extern class NativeGc -{ - @:native("__hxcpp_gc_mem_info") - static public function memInfo(inWhatInfo:Int) : Float return 0.0; +package cpp; - @:native("_hx_allocate_extended") @:templatedCall - static public function allocateExtended(cls:Class, size:Int) : T return null; +extern class NativeGc { + @:native("__hxcpp_gc_mem_info") + static public function memInfo(inWhatInfo:Int):Float; - @:native("_hx_add_finalizable") - public static function addFinalizable( instance:{ function finalize():Void; }, inPin:Bool ): Void {} + @:native("_hx_allocate_extended") @:templatedCall + static public function allocateExtended(cls:Class, size:Int):T; - @:native("hx::InternalNew") - public static function allocGcBytesRaw( inBytes : Int, isContainer:Bool ): RawPointer return null; + @:native("_hx_add_finalizable") + public static function addFinalizable(instance:{function finalize():Void;}, inPin:Bool):Void; - inline public static function allocGcBytes( inBytes : Int ): Pointer - { - return Pointer.fromRaw( allocGcBytesRaw(inBytes, false) ); - } + @:native("hx::InternalNew") + public static function allocGcBytesRaw(inBytes:Int, isContainer:Bool):RawPointer; + inline public static function allocGcBytes(inBytes:Int):Pointer { + return Pointer.fromRaw(allocGcBytesRaw(inBytes, false)); + } - @:native("__hxcpp_enable") @:extern - static public function enable(inEnable:Bool) : Void { } + @:native("__hxcpp_enable") extern static public function enable(inEnable:Bool):Void; - @:native("__hxcpp_collect") @:extern - static public function run(major:Bool) : Void { } + @:native("__hxcpp_collect") extern static public function run(major:Bool):Void; - @:native("__hxcpp_gc_compact") @:extern - static public function compact() : Void { } + @:native("__hxcpp_gc_compact") extern static public function compact():Void; - @:native("__hxcpp_gc_trace") @:extern - static public function nativeTrace(sought:Class,printInstances:Bool) : Int return 0; + @:native("__hxcpp_gc_trace") extern static public function nativeTrace(sought:Class, printInstances:Bool):Int; - @:native("__hxcpp_gc_do_not_kill") @:extern - static public function doNotKill(inObject:Dynamic) : Void { } + @:native("__hxcpp_gc_do_not_kill") extern static public function doNotKill(inObject:Dynamic):Void; - @:native("__hxcpp_get_next_zombie") @:extern - static public function getNextZombie() : Dynamic return null; + @:native("__hxcpp_get_next_zombie") extern static public function getNextZombie():Dynamic; - @:native("__hxcpp_gc_safe_point") @:extern - static public function safePoint() : Void { } + @:native("__hxcpp_gc_safe_point") extern static public function safePoint():Void; - @:native("__hxcpp_enter_gc_free_zone") @:extern - static public function enterGCFreeZone() : Void { } + @:native("__hxcpp_enter_gc_free_zone") extern static public function enterGCFreeZone():Void; - @:native("__hxcpp_exit_gc_free_zone") @:extern - static public function exitGCFreeZone() : Void { } + @:native("__hxcpp_exit_gc_free_zone") extern static public function exitGCFreeZone():Void; - @:native("__hxcpp_set_minimum_free_space") @:extern - static public function setMinimumFreeSpace(inBytes:Int) : Void { } + @:native("__hxcpp_set_minimum_free_space") extern static public function setMinimumFreeSpace(inBytes:Int):Void; - @:native("__hxcpp_set_target_free_space_percentage") @:extern - static public function setTargetFreeSpacePercentage(inPercentage:Int) : Void { } + @:native("__hxcpp_set_target_free_space_percentage") extern static public function setTargetFreeSpacePercentage(inPercentage:Int):Void; - @:native("__hxcpp_set_minimum_working_memory") @:extern - static public function setMinimumWorkingMemory(inBytes:Int) : Void { } + @:native("__hxcpp_set_minimum_working_memory") extern static public function setMinimumWorkingMemory(inBytes:Int):Void; } - diff --git a/std/cpp/NativeMath.hx b/std/cpp/NativeMath.hx index d6bfaa6ade1..75bbcf95283 100644 --- a/std/cpp/NativeMath.hx +++ b/std/cpp/NativeMath.hx @@ -1,31 +1,49 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; @:noPackageRestrict -extern class NativeMath -{ -#if (cpp && !cppia) - @:native("_hx_idiv") - public static function idiv(num:Int,denom:Int):Int return 0; - @:native("_hx_imod") - public static function imod(num:Int,denom:Int):Int return 0; - @:native("_hx_cast_int") - public static function castInt(f:Float):Int return 0; - @:native("_hx_fast_floor") - public static function fastInt(f:Float):Int return 0; - -#else - - public static inline function imod(num:Int,denom:Int):Int - return num%denom; - - public static inline function idiv(num:Int,denom:Int):Int - return Std.int(num/denom); +extern class NativeMath { + #if (cpp && !cppia) + @:native("_hx_idiv") + public static function idiv(num:Int, denom:Int):Int; + @:native("_hx_imod") + public static function imod(num:Int, denom:Int):Int; + @:native("_hx_cast_int") + public static function castInt(f:Float):Int; + @:native("_hx_fast_floor") + public static function fastInt(f:Float):Int; + #else + public static inline function imod(num:Int, denom:Int):Int + return num % denom; - public static inline function castInt(f:Float):Int - return Std.int(f); + public static inline function idiv(num:Int, denom:Int):Int + return Std.int(num / denom); - public static inline function fastInt(f:Float):Int - return Std.int(f); + public static inline function castInt(f:Float):Int + return Std.int(f); -#end + public static inline function fastInt(f:Float):Int + return Std.int(f); + #end } diff --git a/std/cpp/NativeProcess.hx b/std/cpp/NativeProcess.hx index fcce680fd3a..e73ab9d5795 100644 --- a/std/cpp/NativeProcess.hx +++ b/std/cpp/NativeProcess.hx @@ -1,40 +1,56 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; @:buildXml('') -extern class NativeProcess -{ - - @:extern @:native("_hx_std_process_run") - public static function process_run(cmd:String,vargs:Array) : Dynamic return null; - - @:extern @:native("_hx_std_process_run") - public static function process_run_with_show(cmd:String,vargs:Array,inShow:Int) : Dynamic return null; - - @:extern @:native("_hx_std_process_stdout_read") - public static function process_stdout_read(handle:Dynamic,buf:haxe.io.BytesData,pos:Int,len:Int) : Int return 0; - - - @:extern @:native("_hx_std_process_stderr_read") - public static function process_stderr_read(handle:Dynamic,buf:haxe.io.BytesData,pos:Int,len:Int) : Int return 0; - - - @:extern @:native("_hx_std_process_stdin_write") - public static function process_stdin_write(handle:Dynamic,buf:haxe.io.BytesData,pos:Int,len:Int) : Int return 0; +extern class NativeProcess { + @:native("_hx_std_process_run") + public static function process_run(cmd:String, vargs:Array):Dynamic; + @:native("_hx_std_process_run") + public static function process_run_with_show(cmd:String, vargs:Array, inShow:Int):Dynamic; - @:extern @:native("_hx_std_process_stdin_close") - public static function process_stdin_close(handle:Dynamic) : Void { } + @:native("_hx_std_process_stdout_read") + public static function process_stdout_read(handle:Dynamic, buf:haxe.io.BytesData, pos:Int, len:Int):Int; + @:native("_hx_std_process_stderr_read") + public static function process_stderr_read(handle:Dynamic, buf:haxe.io.BytesData, pos:Int, len:Int):Int; - @:extern @:native("_hx_std_process_exit") - public static function process_exit(handle:Dynamic) : Int return 0; + @:native("_hx_std_process_stdin_write") + public static function process_stdin_write(handle:Dynamic, buf:haxe.io.BytesData, pos:Int, len:Int):Int; + @:native("_hx_std_process_stdin_close") + public static function process_stdin_close(handle:Dynamic):Void; - @:extern @:native("_hx_std_process_pid") - public static function process_pid(handle:Dynamic) : Int return 0; + @:native("_hx_std_process_exit") + public static function process_exit(handle:Dynamic):Int; + @:native("_hx_std_process_pid") + public static function process_pid(handle:Dynamic):Int; - @:extern @:native("_hx_std_process_close") - public static function process_close(handle:Dynamic) : Void { }; + @:native("_hx_std_process_kill") + public static function process_kill(handle:Dynamic):Void; + @:native("_hx_std_process_close") + public static function process_close(handle:Dynamic):Void; } diff --git a/std/cpp/NativeRandom.hx b/std/cpp/NativeRandom.hx index 3b6a41be178..a8ee8a02937 100644 --- a/std/cpp/NativeRandom.hx +++ b/std/cpp/NativeRandom.hx @@ -1,23 +1,38 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; @:buildXml('') -extern class NativeRandom -{ - - @:extern @:native("_hx_std_random_new") - public static function random_new() : Dynamic return null; - - - @:extern @:native("_hx_std_random_set_seed") - public static function random_set_seed(handle:Dynamic,v:Int) : Void { } +extern class NativeRandom { + @:native("_hx_std_random_new") + public static function random_new():Dynamic; + @:native("_hx_std_random_set_seed") + public static function random_set_seed(handle:Dynamic, v:Int):Void; - @:extern @:native("_hx_std_random_int") - public static function random_int(handle:Dynamic,max:Int) : Int return 0; - - @:extern @:native("_hx_std_random_float") - public static function random_float(handle:Dynamic) : Float return 0.0; - + @:native("_hx_std_random_int") + public static function random_int(handle:Dynamic, max:Int):Int; + @:native("_hx_std_random_float") + public static function random_float(handle:Dynamic):Float; } - diff --git a/std/cpp/NativeSocket.hx b/std/cpp/NativeSocket.hx index 0125556405e..d81944cc1d5 100644 --- a/std/cpp/NativeSocket.hx +++ b/std/cpp/NativeSocket.hx @@ -1,155 +1,145 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; import sys.net.Socket; @:buildXml('') -extern class NativeSocket -{ - @:extern @:native("_hx_std_socket_init") - public static function socket_init() : Void { } - - - @:extern @:native("_hx_std_socket_new") - public static function socket_new(udp:Bool) : Dynamic return null; - - @:extern @:native("_hx_std_socket_new") - public static function socket_new_ip(udp:Bool,ipv6:Bool) : Dynamic return null; - - - @:extern @:native("_hx_std_socket_close") - public static function socket_close(handle:Dynamic) : Void { } - - - @:extern @:native("_hx_std_socket_bind") - public static function socket_bind(o:Dynamic,host:Int,port:Int) : Void { } - - @:extern @:native("_hx_std_socket_bind_ipv6") - public static function socket_bind_ipv6(o:Dynamic,host:haxe.io.BytesData,port:Int) : Void { } - - - @:extern @:native("_hx_std_socket_send_char") - public static function socket_send_char(o:Dynamic,c:Int) : Void { } - - - @:extern @:native("_hx_std_socket_send") - public static function socket_send(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int) : Int return 0; - - - @:extern @:native("_hx_std_socket_recv") - public static function socket_recv(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int) : Int return 0; - - - @:extern @:native("_hx_std_socket_recv_char") - public static function socket_recv_char(o:Dynamic) : Int return 0; - +extern class NativeSocket { + @:native("_hx_std_socket_init") + public static function socket_init():Void; - @:extern @:native("_hx_std_socket_write") - public static function socket_write(o:Dynamic,buf:haxe.io.BytesData) : Void { } + @:native("_hx_std_socket_new") + public static function socket_new(udp:Bool):Dynamic; + @:native("_hx_std_socket_new") + public static function socket_new_ip(udp:Bool, ipv6:Bool):Dynamic; - @:extern @:native("_hx_std_socket_read") - public static function socket_read(o:Dynamic) : haxe.io.BytesData return null; + @:native("_hx_std_socket_close") + public static function socket_close(handle:Dynamic):Void; - @:extern @:native("_hx_std_host_resolve_ipv6") - public static function host_resolve_ipv6(host:String) : haxe.io.BytesData return null; + @:native("_hx_std_socket_bind") + public static function socket_bind(o:Dynamic, host:Int, port:Int):Void; + @:native("_hx_std_socket_bind_ipv6") + public static function socket_bind_ipv6(o:Dynamic, host:haxe.io.BytesData, port:Int):Void; - @:extern @:native("_hx_std_host_resolve") - public static function host_resolve(host:String) : Int return 0; + @:native("_hx_std_socket_send_char") + public static function socket_send_char(o:Dynamic, c:Int):Void; + @:native("_hx_std_socket_send") + public static function socket_send(o:Dynamic, buf:haxe.io.BytesData, p:Int, l:Int):Int; - @:extern @:native("_hx_std_host_to_string") - public static function host_to_string(ip:Int) : String return null; + @:native("_hx_std_socket_recv") + public static function socket_recv(o:Dynamic, buf:haxe.io.BytesData, p:Int, l:Int):Int; - @:extern @:native("_hx_std_host_to_string_ipv6") - public static function host_to_string_ipv6(ipv6:haxe.io.BytesData) : String return null; + @:native("_hx_std_socket_recv_char") + public static function socket_recv_char(o:Dynamic):Int; + @:native("_hx_std_socket_write") + public static function socket_write(o:Dynamic, buf:haxe.io.BytesData):Void; - @:extern @:native("_hx_std_host_reverse") - public static function host_reverse(host:Int) : String return null; + @:native("_hx_std_socket_read") + public static function socket_read(o:Dynamic):haxe.io.BytesData; - @:extern @:native("_hx_std_host_reverse_ipv6") - public static function host_reverse_ipv6(ipv6:haxe.io.BytesData) : String return null; + @:native("_hx_std_host_resolve_ipv6") + public static function host_resolve_ipv6(host:String):haxe.io.BytesData; + @:native("_hx_std_host_resolve") + public static function host_resolve(host:String):Int; - @:extern @:native("_hx_std_host_local") - public static function host_local() : String return null; + @:native("_hx_std_host_to_string") + public static function host_to_string(ip:Int):String; - inline public static function host_local_ipv6() : String return "::1"; + @:native("_hx_std_host_to_string_ipv6") + public static function host_to_string_ipv6(ipv6:haxe.io.BytesData):String; + @:native("_hx_std_host_reverse") + public static function host_reverse(host:Int):String; - @:extern @:native("_hx_std_socket_connect") - public static function socket_connect(o:Dynamic,host:Int,port:Int) : Void { } + @:native("_hx_std_host_reverse_ipv6") + public static function host_reverse_ipv6(ipv6:haxe.io.BytesData):String; - @:extern @:native("_hx_std_socket_connect_ipv6") - public static function socket_connect_ipv6(o:Dynamic,host:haxe.io.BytesData,port:Int) : Void { } + @:native("_hx_std_host_local") + public static function host_local():String; + inline public static function host_local_ipv6():String + return "::1"; - @:extern @:native("_hx_std_socket_listen") - public static function socket_listen(o:Dynamic,n:Int) : Void { } + @:native("_hx_std_socket_connect") + public static function socket_connect(o:Dynamic, host:Int, port:Int):Void; + @:native("_hx_std_socket_connect_ipv6") + public static function socket_connect_ipv6(o:Dynamic, host:haxe.io.BytesData, port:Int):Void; - @:extern @:native("_hx_std_socket_select") - public static function socket_select(rs:Array,ws:Array,es:Array,timeout:Dynamic) : Array return null; + @:native("_hx_std_socket_listen") + public static function socket_listen(o:Dynamic, n:Int):Void; + @:native("_hx_std_socket_select") + public static function socket_select(rs:Array, ws:Array, es:Array, timeout:Dynamic):Array; - @:extern @:native("_hx_std_socket_fast_select") - public static function socket_fast_select(rs:Array,ws:Array,es:Array,timeout:Dynamic) : Void { } + @:native("_hx_std_socket_fast_select") + public static function socket_fast_select(rs:Array, ws:Array, es:Array, timeout:Dynamic):Void; + @:native("_hx_std_socket_accept") + public static function socket_accept(o:Dynamic):Dynamic; - @:extern @:native("_hx_std_socket_accept") - public static function socket_accept(o:Dynamic) : Dynamic return null; + @:native("_hx_std_socket_peer") + public static function socket_peer(o:Dynamic):Array; + @:native("_hx_std_socket_host") + public static function socket_host(o:Dynamic):Array; - @:extern @:native("_hx_std_socket_peer") - public static function socket_peer(o:Dynamic) : Array return null; + @:native("_hx_std_socket_set_timeout") + public static function socket_set_timeout(o:Dynamic, t:Dynamic):Void; + @:native("_hx_std_socket_shutdown") + public static function socket_shutdown(o:Dynamic, r:Bool, w:Bool):Void; - @:extern @:native("_hx_std_socket_host") - public static function socket_host(o:Dynamic) : Array return null; + @:native("_hx_std_socket_set_blocking") + public static function socket_set_blocking(o:Dynamic, b:Bool):Void; + @:native("_hx_std_socket_set_fast_send") + public static function socket_set_fast_send(o:Dynamic, b:Bool):Void; - @:extern @:native("_hx_std_socket_set_timeout") - public static function socket_set_timeout(o:Dynamic,t:Dynamic) : Void { } + @:native("_hx_std_socket_set_broadcast") + public static function socket_set_broadcast(o:Dynamic, b:Bool):Void; + @:native("_hx_std_socket_poll_alloc") + public static function socket_poll_alloc(nsocks:Int):Dynamic; - @:extern @:native("_hx_std_socket_shutdown") - public static function socket_shutdown(o:Dynamic,r:Bool,w:Bool) : Void { } + @:native("_hx_std_socket_poll_prepare") + public static function socket_poll_prepare(pdata:Dynamic, rsocks:Array, wsocks:Array):Array>; + @:native("_hx_std_socket_poll_events") + public static function socket_poll_events(pdata:Dynamic, timeout:Float):Void; - @:extern @:native("_hx_std_socket_set_blocking") - public static function socket_set_blocking(o:Dynamic,b:Bool) : Void { } - - - @:extern @:native("_hx_std_socket_set_fast_send") - public static function socket_set_fast_send(o:Dynamic,b:Bool) : Void { } - - - @:extern @:native("_hx_std_socket_poll_alloc") - public static function socket_poll_alloc(nsocks:Int) : Dynamic return null; - - - @:extern @:native("_hx_std_socket_poll_prepare") - public static function socket_poll_prepare(pdata:Dynamic,rsocks:Array,wsocks:Array) : Array< Array > return null; - - - @:extern @:native("_hx_std_socket_poll_events") - public static function socket_poll_events(pdata:Dynamic,timeout:Float) : Void { } - - - @:extern @:native("_hx_std_socket_poll") - public static function socket_poll(socks:Array,pdata:Dynamic,timeout:Float) : Array return null; - - - @:extern @:native("_hx_std_socket_send_to") - public static function socket_send_to(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int,inAddr:Dynamic) : Int return 0; - - - @:extern @:native("_hx_std_socket_recv_from") - public static function socket_recv_from(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int,outAddr:Dynamic) : Int return 0; - + @:native("_hx_std_socket_poll") + public static function socket_poll(socks:Array, pdata:Dynamic, timeout:Float):Array; + @:native("_hx_std_socket_send_to") + public static function socket_send_to(o:Dynamic, buf:haxe.io.BytesData, p:Int, l:Int, inAddr:Dynamic):Int; + @:native("_hx_std_socket_recv_from") + public static function socket_recv_from(o:Dynamic, buf:haxe.io.BytesData, p:Int, l:Int, outAddr:Dynamic):Int; } - - diff --git a/std/cpp/NativeSsl.hx b/std/cpp/NativeSsl.hx index 24766599619..4ec353fbf5b 100644 --- a/std/cpp/NativeSsl.hx +++ b/std/cpp/NativeSsl.hx @@ -1,114 +1,134 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; @:buildXml('') -extern class NativeSsl -{ - @:extern @:native("_hx_ssl_new") - public static function ssl_new( conf : Dynamic ) : Dynamic { } - - @:extern @:native("_hx_ssl_close") - public static function ssl_close( ctx : Dynamic ) : Void { } +extern class NativeSsl { + @:native("_hx_ssl_new") + public static function ssl_new(conf:Dynamic):Dynamic; - @:extern @:native("_hx_ssl_handshake") - public static function ssl_handshake( ctx : Dynamic ) : Void { } + @:native("_hx_ssl_close") + public static function ssl_close(ctx:Dynamic):Void; - @:extern @:native("_hx_ssl_set_socket") - public static function ssl_set_socket( ctx : Dynamic, socket : Dynamic ) : Void { } + @:native("_hx_ssl_handshake") + public static function ssl_handshake(ctx:Dynamic):Void; - @:extern @:native("_hx_ssl_set_hostname") - public static function ssl_set_hostname( ctx : Dynamic, hostname : String ) : Void { } + @:native("_hx_ssl_set_socket") + public static function ssl_set_socket(ctx:Dynamic, socket:Dynamic):Void; - @:extern @:native("_hx_ssl_get_peer_certificate") - public static function ssl_get_peer_certificate( ctx : Dynamic ) : Dynamic { } + @:native("_hx_ssl_set_hostname") + public static function ssl_set_hostname(ctx:Dynamic, hostname:String):Void; - @:extern @:native("_hx_ssl_get_verify_result") - public static function ssl_get_verify_result( ctx : Dynamic ) : Bool { } + @:native("_hx_ssl_get_peer_certificate") + public static function ssl_get_peer_certificate(ctx:Dynamic):Dynamic; - @:extern @:native("_hx_ssl_send_char") - public static function ssl_send_char( ctx : Dynamic, char : Int ) : Void { } + @:native("_hx_ssl_get_verify_result") + public static function ssl_get_verify_result(ctx:Dynamic):Bool; - @:extern @:native("_hx_ssl_send") - public static function ssl_send( ctx : Dynamic, buf : haxe.io.BytesData, p : Int, l : Int ) : Int { } + @:native("_hx_ssl_send_char") + public static function ssl_send_char(ctx:Dynamic, char:Int):Void; - @:extern @:native("_hx_ssl_write") - public static function ssl_write( ctx : Dynamic, data : haxe.io.BytesData ) : Void { } + @:native("_hx_ssl_send") + public static function ssl_send(ctx:Dynamic, buf:haxe.io.BytesData, p:Int, l:Int):Int; - @:extern @:native("_hx_ssl_recv_char") - public static function ssl_recv_char( ctx : Dynamic ) : Int { } + @:native("_hx_ssl_write") + public static function ssl_write(ctx:Dynamic, data:haxe.io.BytesData):Void; - @:extern @:native("_hx_ssl_recv") - public static function ssl_recv( ctx : Dynamic, buf : haxe.io.BytesData, p : Int, l : Int ) : Int { } + @:native("_hx_ssl_recv_char") + public static function ssl_recv_char(ctx:Dynamic):Int; - @:extern @:native("_hx_ssl_read") - public static function ssl_read( ctx : Dynamic ) : haxe.io.BytesData { } + @:native("_hx_ssl_recv") + public static function ssl_recv(ctx:Dynamic, buf:haxe.io.BytesData, p:Int, l:Int):Int; - @:extern @:native("_hx_ssl_conf_new") - public static function conf_new( server : Bool ) : Dynamic { } + @:native("_hx_ssl_read") + public static function ssl_read(ctx:Dynamic):haxe.io.BytesData; - @:extern @:native("_hx_ssl_conf_close") - public static function conf_close( conf : Dynamic ) : Void { } + @:native("_hx_ssl_conf_new") + public static function conf_new(server:Bool):Dynamic; - @:extern @:native("_hx_ssl_conf_set_ca") - public static function conf_set_ca( conf : Dynamic, cert : Dynamic ) : Void { } + @:native("_hx_ssl_conf_close") + public static function conf_close(conf:Dynamic):Void; - @:extern @:native("_hx_ssl_conf_set_verify") - public static function conf_set_verify( conf : Dynamic, mode : Int ) : Void { } + @:native("_hx_ssl_conf_set_ca") + public static function conf_set_ca(conf:Dynamic, cert:Dynamic):Void; - @:extern @:native("_hx_ssl_conf_set_cert") - public static function conf_set_cert( conf : Dynamic, cert : Dynamic, pkey : Dynamic ) : Void { } + @:native("_hx_ssl_conf_set_verify") + public static function conf_set_verify(conf:Dynamic, mode:Int):Void; - @:extern @:native("_hx_ssl_conf_set_servername_callback") - public static function conf_set_servername_callback( conf : Dynamic, cb : Dynamic ) : Void { } + @:native("_hx_ssl_conf_set_cert") + public static function conf_set_cert(conf:Dynamic, cert:Dynamic, pkey:Dynamic):Void; - @:extern @:native("_hx_ssl_cert_load_defaults") - public static function cert_load_defaults() : Dynamic { } + @:native("_hx_ssl_conf_set_servername_callback") + public static function conf_set_servername_callback(conf:Dynamic, cb:Dynamic):Void; - @:extern @:native("_hx_ssl_cert_load_file") - public static function cert_load_file( file : String ) : Dynamic { } + @:native("_hx_ssl_cert_load_defaults") + public static function cert_load_defaults():Dynamic; - @:extern @:native("_hx_ssl_cert_load_path") - public static function cert_load_path( path : String ) : Dynamic { } + @:native("_hx_ssl_cert_load_file") + public static function cert_load_file(file:String):Dynamic; - @:extern @:native("_hx_ssl_cert_get_subject") - public static function cert_get_subject( cert : Dynamic, field : String ) : String { } + @:native("_hx_ssl_cert_load_path") + public static function cert_load_path(path:String):Dynamic; - @:extern @:native("_hx_ssl_cert_get_issuer") - public static function cert_get_issuer( cert : Dynamic, field : String ) : String { } + @:native("_hx_ssl_cert_get_subject") + public static function cert_get_subject(cert:Dynamic, field:String):String; - @:extern @:native("_hx_ssl_cert_get_altnames") - public static function cert_get_altnames( cert : Dynamic ) : Array { } + @:native("_hx_ssl_cert_get_issuer") + public static function cert_get_issuer(cert:Dynamic, field:String):String; - @:extern @:native("_hx_ssl_cert_get_notbefore") - public static function cert_get_notbefore( cert : Dynamic ) : Array { } + @:native("_hx_ssl_cert_get_altnames") + public static function cert_get_altnames(cert:Dynamic):Array; - @:extern @:native("_hx_ssl_cert_get_notafter") - public static function cert_get_notafter( cert : Dynamic ) : Array { } + @:native("_hx_ssl_cert_get_notbefore") + public static function cert_get_notbefore(cert:Dynamic):Array; - @:extern @:native("_hx_ssl_cert_get_next") - public static function cert_get_next( cert : Dynamic ) : Dynamic { } + @:native("_hx_ssl_cert_get_notafter") + public static function cert_get_notafter(cert:Dynamic):Array; - @:extern @:native("_hx_ssl_cert_add_pem") - public static function cert_add_pem( cert : Dynamic, data : String ) : Dynamic { } + @:native("_hx_ssl_cert_get_next") + public static function cert_get_next(cert:Dynamic):Dynamic; - @:extern @:native("_hx_ssl_cert_add_der") - public static function cert_add_der( cert : Dynamic, data : haxe.io.BytesData ) : Dynamic { } + @:native("_hx_ssl_cert_add_pem") + public static function cert_add_pem(cert:Dynamic, data:String):Dynamic; - @:extern @:native("_hx_ssl_key_from_der") - public static function key_from_der( data : haxe.io.BytesData, pub : Bool ) : Dynamic { } + @:native("_hx_ssl_cert_add_der") + public static function cert_add_der(cert:Dynamic, data:haxe.io.BytesData):Dynamic; - @:extern @:native("_hx_ssl_key_from_pem") - public static function key_from_pem( data : String, pub : Bool, pass : String ) : Dynamic { } + @:native("_hx_ssl_key_from_der") + public static function key_from_der(data:haxe.io.BytesData, pub:Bool):Dynamic; - @:extern @:native("_hx_ssl_dgst_make") - public static function dgst_make( data : haxe.io.BytesData, alg : String ) : haxe.io.BytesData { } + @:native("_hx_ssl_key_from_pem") + public static function key_from_pem(data:String, pub:Bool, pass:String):Dynamic; - @:extern @:native("_hx_ssl_dgst_sign") - public static function dgst_sign( data : haxe.io.BytesData, key : Dynamic, alg : String ) : haxe.io.BytesData { } + @:native("_hx_ssl_dgst_make") + public static function dgst_make(data:haxe.io.BytesData, alg:String):haxe.io.BytesData; - @:extern @:native("_hx_ssl_dgst_verify") - public static function dgst_verify( data : haxe.io.BytesData, sign : haxe.io.BytesData, key : Dynamic, alg : String ) : Bool { } + @:native("_hx_ssl_dgst_sign") + public static function dgst_sign(data:haxe.io.BytesData, key:Dynamic, alg:String):haxe.io.BytesData; - @:extern @:native("_hx_ssl_init") - public static function init() : Void { } + @:native("_hx_ssl_dgst_verify") + public static function dgst_verify(data:haxe.io.BytesData, sign:haxe.io.BytesData, key:Dynamic, alg:String):Bool; + @:native("_hx_ssl_init") + public static function init():Void; } diff --git a/std/cpp/NativeString.hx b/std/cpp/NativeString.hx index b9e3ce5332d..6d90fc300d2 100644 --- a/std/cpp/NativeString.hx +++ b/std/cpp/NativeString.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,44 +19,41 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; -extern class NativeString { - - public static inline function raw( inString:String ) : RawConstPointer { - return untyped inString.__s; - } - public static inline function c_str( inString:String ) : ConstPointer { - return cpp.ConstPointer.fromPointer(untyped inString.__s); - } - public static inline function fromPointer(inPtr:ConstPointer ) : String { - return untyped __global__.String(inPtr.ptr); - } - public static inline function fromGcPointer(inPtr:ConstPointer, inLen:Int ) : String { - return untyped __global__.String(inPtr.ptr,inLen); - } - - - @:native("_hx_string_compare") - public static function compare(inString0:String, inString1:String) : Int return 0; - - @:native("_hx_utf8_char_code_at") - public static function utf8CharCodeAt(inString:String, inIndex:Int) : Int return 0; - - @:native("_hx_utf8_length") - public static function utf8Length(inString:String) : Int return 1; - - @:native("_hx_utf8_is_valid") - public static function utf8IsValid(inString:String) : Bool return false; - - @:native("_hx_utf8_sub") - public static function utf8Sub(inString:String,charStart:Int, inLen:Int) : String return null; - - @:native("_hx_string_create") - public static function fromPointerLen(inPtr:ConstPointer, len:Int ) : String; - - @:native("_hx_utf8_decode_advance") - public static function utf8DecodeAdvance(reference:Char) : Int return 0; +package cpp; +extern class NativeString { + public static inline function raw(inString:String):RawConstPointer { + return untyped inString.raw_ptr(); + } + public static inline function c_str(inString:String):ConstPointer { + return cpp.ConstPointer.fromPointer(untyped inString.c_str()); + } + public static inline function fromPointer(inPtr:ConstPointer):String { + return untyped __global__.String(inPtr.ptr); + } + public static inline function fromGcPointer(inPtr:ConstPointer, inLen:Int):String { + return untyped __global__.String(inPtr.ptr, inLen); + } + + @:native("_hx_string_compare") + public static function compare(inString0:String, inString1:String):Int; + + @:native("_hx_utf8_char_code_at") + public static function utf8CharCodeAt(inString:String, inIndex:Int):Int; + + @:native("_hx_utf8_length") + public static function utf8Length(inString:String):Int; + + @:native("_hx_utf8_is_valid") + public static function utf8IsValid(inString:String):Bool; + + @:native("_hx_utf8_sub") + public static function utf8Sub(inString:String, charStart:Int, inLen:Int):String; + + @:native("_hx_string_create") + public static function fromPointerLen(inPtr:ConstPointer, len:Int):String; + + @:native("_hx_utf8_decode_advance") + public static function utf8DecodeAdvance(reference:Char):Int; } - diff --git a/std/cpp/NativeSys.hx b/std/cpp/NativeSys.hx index 17e0383d2f8..d2656a28a4f 100644 --- a/std/cpp/NativeSys.hx +++ b/std/cpp/NativeSys.hx @@ -1,113 +1,107 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; @:buildXml('') -extern class NativeSys -{ - @:native("__hxcpp_print") - public static function print( v : Dynamic ) : Void { } - - @:native("__hxcpp_println") - public static function println( v : Dynamic ) : Void { } - - @:extern @:native("_hx_std_get_env") - public static function get_env(v:String) : String return null; - - - @:extern @:native("_hx_std_put_env") - public static function put_env(e:String,v:String) : Void { } - - - @:extern @:native("_hx_std_sys_sleep") - public static function sys_sleep(f:Float) : Void { } - - - @:extern @:native("_hx_std_set_time_locale") - public static function set_time_locale(l:String) : Bool return false; - - - @:extern @:native("_hx_std_get_cwd") - public static function get_cwd() : String return null; - - - @:extern @:native("_hx_std_set_cwd") - public static function set_cwd(d:String) : Void { } - +extern class NativeSys { + @:native("__hxcpp_print") + public static function print(v:Dynamic):Void; - @:extern @:native("_hx_std_sys_string") - public static function sys_string() : String return null; + @:native("__hxcpp_println") + public static function println(v:Dynamic):Void; + @:native("_hx_std_get_env") + extern public static function get_env(v:String):String; - @:extern @:native("_hx_std_sys_is64") - public static function sys_is64() : Bool return false; + @:native("_hx_std_put_env") + extern public static function put_env(e:String, v:String):Void; + @:native("_hx_std_sys_sleep") + extern public static function sys_sleep(f:Float):Void; - @:extern @:native("_hx_std_sys_command") - public static function sys_command(cmd:String) : Int return 0; + @:native("_hx_std_set_time_locale") + extern public static function set_time_locale(l:String):Bool; + @:native("_hx_std_get_cwd") + extern public static function get_cwd():String; - @:extern @:native("_hx_std_sys_exit") - public static function sys_exit(code:Int) : Void { } + @:native("_hx_std_set_cwd") + extern public static function set_cwd(d:String):Void; + @:native("_hx_std_sys_string") + extern public static function sys_string():String; - @:extern @:native("_hx_std_sys_exists") - public static function sys_exists(path:String) : Bool return false; + @:native("_hx_std_sys_is64") + extern public static function sys_is64():Bool; + @:native("_hx_std_sys_command") + extern public static function sys_command(cmd:String):Int; - @:extern @:native("_hx_std_file_delete") - public static function file_delete(path:String) : Void { } + @:native("_hx_std_sys_exit") + extern public static function sys_exit(code:Int):Void; + @:native("_hx_std_sys_exists") + extern public static function sys_exists(path:String):Bool; - @:extern @:native("_hx_std_sys_rename") - public static function sys_rename(path:String,newname:String) : Bool return false; + @:native("_hx_std_file_delete") + extern public static function file_delete(path:String):Void; + @:native("_hx_std_sys_rename") + extern public static function sys_rename(path:String, newname:String):Bool; - @:extern @:native("_hx_std_sys_stat") - public static function sys_stat(path:String) : Dynamic return null; + @:native("_hx_std_sys_stat") + extern public static function sys_stat(path:String):Dynamic; + @:native("_hx_std_sys_file_type") + extern public static function sys_file_type(path:String):String; - @:extern @:native("_hx_std_sys_file_type") - public static function sys_file_type(path:String) : String return null; + @:native("_hx_std_sys_create_dir") + extern public static function sys_create_dir(path:String, mode:Int):Bool; + @:native("_hx_std_sys_remove_dir") + extern public static function sys_remove_dir(path:String):Void; - @:extern @:native("_hx_std_sys_create_dir") - public static function sys_create_dir(path:String,mode:Int) : Bool return false; + @:native("_hx_std_sys_time") + extern public static function sys_time():Float; + @:native("_hx_std_sys_cpu_time") + extern public static function sys_cpu_time():Float; - @:extern @:native("_hx_std_sys_remove_dir") - public static function sys_remove_dir(path:String) : Void { } + @:native("_hx_std_sys_read_dir") + extern public static function sys_read_dir(p:String):Array; + @:native("_hx_std_file_full_path") + extern public static function file_full_path(path:String):String; - @:extern @:native("_hx_std_sys_time") - public static function sys_time() : Float return 0; + @:native("_hx_std_sys_exe_path") + extern public static function sys_exe_path():String; + @:native("_hx_std_sys_env") + extern public static function sys_env():Array; - @:extern @:native("_hx_std_sys_cpu_time") - public static function sys_cpu_time() : Float return 0; - - - @:extern @:native("_hx_std_sys_read_dir") - public static function sys_read_dir(p:String) : Array return null; - - - @:extern @:native("_hx_std_file_full_path") - public static function file_full_path(path:String) : String return null; - - - @:extern @:native("_hx_std_sys_exe_path") - public static function sys_exe_path() : String return null; - - - @:extern @:native("_hx_std_sys_env") - public static function sys_env() : Array return null; - - - @:extern @:native("_hx_std_sys_getch") - public static function sys_getch(b:Bool) : Int return 0; - - - @:extern @:native("_hx_std_sys_get_pid") - public static function sys_get_pid() : Int return 0; + @:native("_hx_std_sys_getch") + extern public static function sys_getch(b:Bool):Int; + @:native("_hx_std_sys_get_pid") + extern public static function sys_get_pid():Int; } - - diff --git a/std/cpp/NativeXml.hx b/std/cpp/NativeXml.hx index 0670d686109..a45aa888017 100644 --- a/std/cpp/NativeXml.hx +++ b/std/cpp/NativeXml.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,482 +19,455 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; -@:enum abstract XmlType(Int) { - /** - Represents an XML element type. - **/ - var Element = 0; - /** - Represents XML parsed character data type. - **/ - var PCData = 1; - /** - Represents XML character data type. - **/ - var CData = 2; - /** - Represents an XML comment type. - **/ - var Comment = 3; - /** - Represents an XML doctype element type. - **/ - var DocType = 4; - /** - Represents an XML processing instruction type. - **/ - var ProcessingInstruction = 5; - /** - Represents an XML document type. - **/ - var Document = 6; +enum abstract XmlType(Int) { + /** + Represents an XML element type. + **/ + var Element = 0; + + /** + Represents XML parsed character data type. + **/ + var PCData = 1; + + /** + Represents XML character data type. + **/ + var CData = 2; + + /** + Represents an XML comment type. + **/ + var Comment = 3; + + /** + Represents an XML doctype element type. + **/ + var DocType = 4; + + /** + Represents an XML processing instruction type. + **/ + var ProcessingInstruction = 5; + + /** + Represents an XML document type. + **/ + var Document = 6; } -class NativeXmlState -{ - var cur : Xml; - - public function new(x:Xml) - { - x._children = new Array(); - cur = x; - } - - - @:keep - public function xml(name:String, att:Dynamic) - { - var x = new Xml(); - x._parent = cur; - x.nodeType = Xml.Element; - x._nodeName = name; - x._attributes = att; - x._children = new Array(); - cur.addChild(x); - cur = x; - } - - @:keep - public function cdata(text:String) - { - var x = new Xml(); - x._parent = cur; - x.nodeType = Xml.CData; - x._nodeValue = text; - cur.addChild(x); - } - - @:keep - public function pcdata(text:String) - { - var x = new Xml(); - x._parent = cur; - x.nodeType = Xml.PCData; - x._nodeValue = text; - cur.addChild(x); - } - - @:keep - public function comment(text:String) - { - var x = new Xml(); - x._parent = cur; - if( text.length>1 && StringTools.fastCodeAt(text,0) == 63 ) - { - x.nodeType = Xml.ProcessingInstruction; - text = text.substr(1, text.length - 2); - } - else - { - x.nodeType = Xml.Comment; - } - x._nodeValue = text; - cur.addChild(x); - } - - @:keep - public function doctype(text:String) - { - var x = new Xml(); - x._parent = cur; - x.nodeType = Xml.DocType; - x._nodeValue = text.substr(1); - cur.addChild(x); - } - - @:keep - public function done() - { - cur = cur._parent; - } +class NativeXmlState { + var cur:Xml; + + public function new(x:Xml) { + x._children = new Array(); + cur = x; + } + + @:keep + public function xml(name:String, att:Dynamic) { + var x = new Xml(); + x._parent = cur; + x.nodeType = Xml.Element; + x._nodeName = name; + x._attributes = att; + x._children = new Array(); + cur.addChild(x); + cur = x; + } + + @:keep + public function cdata(text:String) { + var x = new Xml(); + x._parent = cur; + x.nodeType = Xml.CData; + x._nodeValue = text; + cur.addChild(x); + } + + @:keep + public function pcdata(text:String) { + var x = new Xml(); + x._parent = cur; + x.nodeType = Xml.PCData; + x._nodeValue = text; + cur.addChild(x); + } + + @:keep + public function comment(text:String) { + var x = new Xml(); + x._parent = cur; + if (text.length > 1 && StringTools.fastCodeAt(text, 0) == 63) { + x.nodeType = Xml.ProcessingInstruction; + text = text.substr(1, text.length - 2); + } else { + x.nodeType = Xml.Comment; + } + x._nodeValue = text; + cur.addChild(x); + } + + @:keep + public function doctype(text:String) { + var x = new Xml(); + x._parent = cur; + x.nodeType = Xml.DocType; + x._nodeValue = text.substr(1); + cur.addChild(x); + } + + @:keep + public function done() { + cur = cur._parent; + } } -private class NativeXmlIterator -{ - var cur = 0; - var children:Array; - - public function new(inChildren:Array) - { - children = inChildren; - cur = 0; - } - - public function hasNext() : Bool - { - var k = cur; - var l = children.length; - while( k < l ) - { - if (children[k].nodeType == Xml.Element) - break; - k += 1; - } - cur = k; - return k < l; - } - - public function next():Xml - { - var k = cur; - var l = children.length; - while( k < l ) - { - var n = children[k]; - k += 1; - if( n.nodeType == Xml.Element ) - { - cur = k; - return n; - } - } - return null; - } +private class NativeXmlIterator { + var cur = 0; + var children:Array; + + public function new(inChildren:Array) { + children = inChildren; + cur = 0; + } + + public function hasNext():Bool { + var k = cur; + var l = children.length; + while (k < l) { + if (children[k].nodeType == Xml.Element) + break; + k += 1; + } + cur = k; + return k < l; + } + + public function next():Xml { + var k = cur; + var l = children.length; + while (k < l) { + var n = children[k]; + k += 1; + if (n.nodeType == Xml.Element) { + cur = k; + return n; + } + } + return null; + } } -private class NativeXmlNamedIterator -{ - var cur = 0; - var children:Array; - var name:String; - - public function new(inChildren:Array, inName:String) - { - children = inChildren; - name = inName; - cur = 0; - } - - - public function hasNext() : Bool - { - var k = cur; - var l = children.length; - while( k < l ) - { - var n = children[k]; - if( n.nodeType == Xml.Element && n._nodeName == name ) - break; - k++; - } - cur = k; - return k < l; - } - - public function next():Xml - { - var k = cur; - var l = children.length; - while( k < l ) - { - var n = children[k]; - k++; - if( n.nodeType == Xml.Element && n._nodeName == name ) { - cur = k; - return n; - } - } - return null; - } +private class NativeXmlNamedIterator { + var cur = 0; + var children:Array; + var name:String; + + public function new(inChildren:Array, inName:String) { + children = inChildren; + name = inName; + cur = 0; + } + + public function hasNext():Bool { + var k = cur; + var l = children.length; + while (k < l) { + var n = children[k]; + if (n.nodeType == Xml.Element && n._nodeName == name) + break; + k++; + } + cur = k; + return k < l; + } + + public function next():Xml { + var k = cur; + var l = children.length; + while (k < l) { + var n = children[k]; + k++; + if (n.nodeType == Xml.Element && n._nodeName == name) { + cur = k; + return n; + } + } + return null; + } } - - - @:cppInclude("./NativeXmlImport.cpp") @:allow(cpp.NativeXmlState) @:allow(cpp.NativeXmlIterator) @:allow(cpp.NativeXmlNamedIterator) class Xml { - static inline var Element = XmlType.Element; - static inline var PCData = XmlType.PCData; - static inline var CData = XmlType.CData; - static inline var Comment = XmlType.Comment; - static inline var DocType = XmlType.DocType; - static inline var ProcessingInstruction = XmlType.ProcessingInstruction; - static inline var Document = XmlType.Document; - - - private var _nodeName : String; - private var _nodeValue : String; - private var _attributes : Dynamic; - private var _children : Array; - private var _parent : Xml; - - function new() : Void { - } - - @:extern @:native("parse_xml") - static function parse_xml(str:String, state:NativeXmlState) { } - - public static function parse( str : String ) : Xml - { - var x = new Xml(); - var state = new NativeXmlState(x); - parse_xml(str,state); - x.nodeType = Xml.Document; - return x; - } - - - public static function createElement( name : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.Element; - r._nodeName = name; - r._attributes = null; - r._children = new Array(); - return r; - } - - public static function createPCData( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.PCData; - r._nodeValue = data; - return r; - } - - public static function createCData( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.CData; - r._nodeValue = data; - return r; - } - - public static function createComment( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.Comment; - r._nodeValue = data; - return r; - } - - public static function createDocType( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.DocType; - r._nodeValue = data; - return r; - } - - public static function createProcessingInstruction( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.ProcessingInstruction; - r._nodeValue = data; - return r; - } - - public static function createDocument() : Xml { - var r = new Xml(); - r.nodeType = Xml.Document; - r._children = new Array(); - return r; - } - - public var nodeType(default,null) : XmlType; - - public var nodeName(get,set) : String; - - public var nodeValue(get,set) : String; - - - private function get_nodeName() : String { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return _nodeName; - } - - private function set_nodeName( n : String ) : String { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return _nodeName = n; - } - - private function get_nodeValue() : String { - if( nodeType == Xml.Element || nodeType == Xml.Document ) - throw "bad nodeType"; - return _nodeValue; - } - - private function set_nodeValue( v : String ) : String { - if( nodeType == Xml.Element || nodeType == Xml.Document ) - throw "bad nodeType"; - return _nodeValue = v; - } - - public var parent(get,null) : Xml; - private function get_parent() : Xml { - return _parent; - } - - public function get( att : String ) : String { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return Reflect.field( _attributes, att ); - } - - public function set( att : String, value : String ) : Void { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - if (_attributes==null) - _attributes = {}; - Reflect.setField (_attributes, att, value ); - return null; - } - - public function remove( att : String ) : Void{ - if( nodeType != Xml.Element ) - throw "bad nodeType"; - Reflect.deleteField( _attributes, att ); - return null; - } - - public function exists( att : String ) : Bool { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return Reflect.hasField( _attributes, att ); - } - - public function attributes() : Iterator { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return Reflect.fields( _attributes ).iterator(); - } - - public function iterator() : Iterator { - if( _children == null ) - throw "bad nodetype"; - return untyped _children.iterator(); - } - - - public function elements(): Iterator - { - if( _children == null ) - throw "bad nodetype"; - return new NativeXmlIterator(_children); - } - - public function elementsNamed( name : String ) : Iterator - { - if( _children == null ) - throw "bad nodetype"; - return new NativeXmlNamedIterator(_children,name); - } - - public function firstChild() : Xml { - if( _children == null ) - throw "bad nodetype"; - return _children[0]; - } - - public function firstElement() : Xml { - if( _children == null ) - throw "bad nodetype"; - for( cur in 0..._children.length ) { - var n:Xml = _children[cur]; - if( n.nodeType == Xml.Element ) - return n; - } - return null; - } - - public function addChild( x : Xml ) : Void { - if( _children == null ) - throw "bad nodetype"; - if( x._parent != null ) x._parent._children.remove(x); - x._parent = this; - _children.push( x ); - return null; - } - - public function removeChild( x : Xml ) : Bool { - if( _children == null ) - throw "bad nodetype"; - var b = _children.remove( x ); - if( b ) x._parent = null; - return b; - } - - public function insertChild( x : Xml, pos : Int ) : Void { - if( _children == null ) - throw "bad nodetype"; - if( x._parent != null ) x._parent._children.remove(x); - x._parent = this; - _children.insert( pos, x ); - return null; - } - - public function toString() : String { - var s = new StringBuf(); - toStringRec(s); - return s.toString(); - } - - private function toStringRec(s: StringBuf) : Void { - switch( nodeType ) { - case Xml.Document: - for( x in _children ) - x.toStringRec(s); - case Xml.Element: - s.addChar("<".code); - s.add(_nodeName); - for( k in Reflect.fields(_attributes) ) { - s.addChar(" ".code); - s.add(k); - s.addChar("=".code); - s.addChar("\"".code); - s.add(Reflect.field(_attributes,k)); - s.addChar("\"".code); - } - if( _children.length == 0 ) { - s.addChar("/".code); - s.addChar(">".code); - return; - } - s.addChar(">".code); - for( x in _children ) - x.toStringRec(s); - s.addChar("<".code); - s.addChar("/".code); - s.add(_nodeName); - s.addChar(">".code); - case Xml.PCData: - s.add(StringTools.htmlEscape(_nodeValue)); - case Xml.CData: - s.add(""); - case Xml.Comment: - s.add(""); - case Xml.DocType: - s.add(""); - case Xml.ProcessingInstruction: - s.add(""); - } - } - + static inline var Element = XmlType.Element; + static inline var PCData = XmlType.PCData; + static inline var CData = XmlType.CData; + static inline var Comment = XmlType.Comment; + static inline var DocType = XmlType.DocType; + static inline var ProcessingInstruction = XmlType.ProcessingInstruction; + static inline var Document = XmlType.Document; + + private var _nodeName:String; + private var _nodeValue:String; + private var _attributes:Dynamic; + private var _children:Array; + private var _parent:Xml; + + function new():Void {} + + @:native("parse_xml") + extern static function parse_xml(str:String, state:NativeXmlState); + + public static function parse(str:String):Xml { + var x = new Xml(); + var state = new NativeXmlState(x); + parse_xml(str, state); + x.nodeType = Xml.Document; + return x; + } + + public static function createElement(name:String):Xml { + var r = new Xml(); + r.nodeType = Xml.Element; + r._nodeName = name; + r._attributes = null; + r._children = new Array(); + return r; + } + + public static function createPCData(data:String):Xml { + var r = new Xml(); + r.nodeType = Xml.PCData; + r._nodeValue = data; + return r; + } + + public static function createCData(data:String):Xml { + var r = new Xml(); + r.nodeType = Xml.CData; + r._nodeValue = data; + return r; + } + + public static function createComment(data:String):Xml { + var r = new Xml(); + r.nodeType = Xml.Comment; + r._nodeValue = data; + return r; + } + + public static function createDocType(data:String):Xml { + var r = new Xml(); + r.nodeType = Xml.DocType; + r._nodeValue = data; + return r; + } + + public static function createProcessingInstruction(data:String):Xml { + var r = new Xml(); + r.nodeType = Xml.ProcessingInstruction; + r._nodeValue = data; + return r; + } + + public static function createDocument():Xml { + var r = new Xml(); + r.nodeType = Xml.Document; + r._children = new Array(); + return r; + } + + public var nodeType(default, null):XmlType; + + public var nodeName(get, set):String; + + public var nodeValue(get, set):String; + + private function get_nodeName():String { + if (nodeType != Xml.Element) + throw "bad nodeType"; + return _nodeName; + } + + private function set_nodeName(n:String):String { + if (nodeType != Xml.Element) + throw "bad nodeType"; + return _nodeName = n; + } + + private function get_nodeValue():String { + if (nodeType == Xml.Element || nodeType == Xml.Document) + throw "bad nodeType"; + return _nodeValue; + } + + private function set_nodeValue(v:String):String { + if (nodeType == Xml.Element || nodeType == Xml.Document) + throw "bad nodeType"; + return _nodeValue = v; + } + + public var parent(get, null):Xml; + + private function get_parent():Xml { + return _parent; + } + + public function get(att:String):String { + if (nodeType != Xml.Element) + throw "bad nodeType"; + return Reflect.field(_attributes, att); + } + + public function set(att:String, value:String):Void { + if (nodeType != Xml.Element) + throw "bad nodeType"; + if (_attributes == null) + _attributes = {}; + Reflect.setField(_attributes, att, value); + return; + } + + public function remove(att:String):Void { + if (nodeType != Xml.Element) + throw "bad nodeType"; + Reflect.deleteField(_attributes, att); + return; + } + + public function exists(att:String):Bool { + if (nodeType != Xml.Element) + throw "bad nodeType"; + return Reflect.hasField(_attributes, att); + } + + public function attributes():Iterator { + if (nodeType != Xml.Element) + throw "bad nodeType"; + return Reflect.fields(_attributes).iterator(); + } + + public function iterator():Iterator { + if (_children == null) + throw "bad nodetype"; + return untyped _children.iterator(); + } + + public function elements():Iterator { + if (_children == null) + throw "bad nodetype"; + return new NativeXmlIterator(_children); + } + + public function elementsNamed(name:String):Iterator { + if (_children == null) + throw "bad nodetype"; + return new NativeXmlNamedIterator(_children, name); + } + + public function firstChild():Xml { + if (_children == null) + throw "bad nodetype"; + return _children[0]; + } + + public function firstElement():Xml { + if (_children == null) + throw "bad nodetype"; + for (cur in 0..._children.length) { + var n:Xml = _children[cur]; + if (n.nodeType == Xml.Element) + return n; + } + return null; + } + + public function addChild(x:Xml):Void { + if (_children == null) + throw "bad nodetype"; + if (x._parent != null) + x._parent._children.remove(x); + x._parent = this; + _children.push(x); + return; + } + + public function removeChild(x:Xml):Bool { + if (_children == null) + throw "bad nodetype"; + var b = _children.remove(x); + if (b) + x._parent = null; + return b; + } + + public function insertChild(x:Xml, pos:Int):Void { + if (_children == null) + throw "bad nodetype"; + if (x._parent != null) + x._parent._children.remove(x); + x._parent = this; + _children.insert(pos, x); + return; + } + + public function toString():String { + var s = new StringBuf(); + toStringRec(s); + return s.toString(); + } + + private function toStringRec(s:StringBuf):Void { + switch (nodeType) { + case Xml.Document: + for (x in _children) + x.toStringRec(s); + case Xml.Element: + s.addChar("<".code); + s.add(_nodeName); + for (k in Reflect.fields(_attributes)) { + s.addChar(" ".code); + s.add(k); + s.addChar("=".code); + s.addChar("\"".code); + s.add(Reflect.field(_attributes, k)); + s.addChar("\"".code); + } + if (_children.length == 0) { + s.addChar("/".code); + s.addChar(">".code); + return; + } + s.addChar(">".code); + for (x in _children) + x.toStringRec(s); + s.addChar("<".code); + s.addChar("/".code); + s.add(_nodeName); + s.addChar(">".code); + case Xml.PCData: + s.add(StringTools.htmlEscape(_nodeValue)); + case Xml.CData: + s.add(""); + case Xml.Comment: + s.add(""); + case Xml.DocType: + s.add(""); + case Xml.ProcessingInstruction: + s.add(""); + } + } } diff --git a/std/cpp/NativeXmlImport.cpp b/std/cpp/NativeXmlImport.cpp index 140f3988d70..a98b748088f 100644 --- a/std/cpp/NativeXmlImport.cpp +++ b/std/cpp/NativeXmlImport.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ #ifdef EPPC #include diff --git a/std/cpp/Object.hx b/std/cpp/Object.hx index 0a038696496..e1adaf9759c 100644 --- a/std/cpp/Object.hx +++ b/std/cpp/Object.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,8 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:noPackageRestrict typedef Object = Dynamic; - diff --git a/std/cpp/ObjectType.hx b/std/cpp/ObjectType.hx index b527fc2a872..8b25ed754d2 100644 --- a/std/cpp/ObjectType.hx +++ b/std/cpp/ObjectType.hx @@ -1,19 +1,39 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; -extern class ObjectType -{ - public inline static var vtUnknown = -1; - public inline static var vtInt = 0xff; - public inline static var vtNull = 0; - public inline static var vtFloat = 1; - public inline static var vtBool = 2; - public inline static var vtString = 3; - public inline static var vtObject = 4; - public inline static var vtArray = 5; - public inline static var vtFunction = 6; - public inline static var vtEnum = 7; - public inline static var vtClass = 8; - public inline static var vtInt64 = 9; - public inline static var vtAbstractBase = 0x100; +extern class ObjectType { + public inline static var vtUnknown = -1; + public inline static var vtInt = 0xff; + public inline static var vtNull = 0; + public inline static var vtFloat = 1; + public inline static var vtBool = 2; + public inline static var vtString = 3; + public inline static var vtObject = 4; + public inline static var vtArray = 5; + public inline static var vtFunction = 6; + public inline static var vtEnum = 7; + public inline static var vtClass = 8; + public inline static var vtInt64 = 9; + public inline static var vtAbstractBase = 0x100; } - diff --git a/std/cpp/Pointer.hx b/std/cpp/Pointer.hx index 98cc1323964..bf836795e85 100644 --- a/std/cpp/Pointer.hx +++ b/std/cpp/Pointer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,69 +19,66 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; import haxe.extern.AsVar; @:coreType -@:analyzer(as_var) -extern class Pointer extends ConstPointer implements ArrayAccess -{ - public var ref(get,set):Reference; +@:semantics(variable) +extern class Pointer extends ConstPointer implements ArrayAccess { + public var ref(get, set):Reference; - public function get_ref() : Reference; - public function set_ref(t:T) : Reference; + public function get_ref():Reference; + public function set_ref(t:T):Reference; - public function setAt(inIndex:Int, value:T):Void; + public function setAt(inIndex:Int, value:T):Void; - public static function fromRaw(ptr:RawPointer) : Pointer; + public static function fromRaw(ptr:RawPointer):Pointer; - @:native("::cpp::Pointer_obj::fromHandle") - static function nativeFromHandle(inHandle:Dynamic,?inKind:String):AutoCast; - inline public static function fromHandle(inHandle:Dynamic,?inKind:String) : Pointer - { - return cast nativeFromHandle(inHandle,inKind); - } + @:native("::cpp::Pointer_obj::fromRaw") + public static function fromStar(star:Star):Pointer; - public static function fromPointer(inNativePointer:Dynamic) : Pointer; + @:native("::cpp::Pointer_obj::fromHandle") + static function nativeFromHandle(inHandle:Dynamic, ?inKind:String):AutoCast; + inline public static function fromHandle(inHandle:Dynamic, ?inKind:String):Pointer { + return cast nativeFromHandle(inHandle, inKind); + } - public static function addressOf(inVariable:cpp.Reference) : Pointer; + public static function fromPointer(inNativePointer:Dynamic):Pointer; - public static function endOf(inVariable:T) : Pointer; + public static function addressOf(inVariable:cpp.Reference):Pointer; - @:native("::cpp::Pointer_obj::arrayElem") - static function nativeArrayElem(array:Array, inElem:Int):AutoCast; - inline static function arrayElem(array:Array, inElem:Int):Pointer - { - return cast nativeArrayElem(array,inElem); - } + public static function endOf(inVariable:T):Pointer; - @:native("::cpp::Pointer_obj::ofArray") - static function nativeOfArray(array:Array):AutoCast; - inline public static function ofArray(array:Array):Pointer - { - return cast nativeOfArray(array); - } + @:native("::cpp::Pointer_obj::arrayElem") + static function nativeArrayElem(array:Array, inElem:Int):AutoCast; + inline static function arrayElem(array:Array, inElem:Int):Pointer { + return cast nativeArrayElem(array, inElem); + } - inline public function toUnmanagedArray(elementCount:Int) : Array - { - var result = new Array(); - NativeArray.setUnmanagedData(result,this,elementCount); - return result; - } + @:native("::cpp::Pointer_obj::ofArray") + static function nativeOfArray(array:Array):AutoCast; + inline public static function ofArray(array:Array):Pointer { + return cast nativeOfArray(array); + } - inline public function toUnmanagedVector(elementCount:Int) : haxe.ds.Vector - return cast toUnmanagedArray(elementCount); + inline public function toUnmanagedArray(elementCount:Int):Array { + var result = new Array(); + NativeArray.setUnmanagedData(result, this, elementCount); + return result; + } + inline public function toUnmanagedVector(elementCount:Int):haxe.ds.Vector + return cast toUnmanagedArray(elementCount); - override public function inc():Pointer; - override public function dec():Pointer; - override public function incBy(inT:Int):Pointer; - override public function add(inT:Int):Pointer; + override public function inc():Pointer; + override public function dec():Pointer; + override public function incBy(inT:Int):Pointer; + override public function add(inT:Int):Pointer; - public function postIncRef():Reference; + public function postIncRef():Reference; - public function destroy():Void; - public function destroyArray():Void; + public function destroy():Void; + public function destroyArray():Void; } - diff --git a/std/cpp/Prime.hx b/std/cpp/Prime.hx index b0ce509ff76..ecc2bac4ed4 100644 --- a/std/cpp/Prime.hx +++ b/std/cpp/Prime.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; #if macro @@ -29,94 +30,88 @@ import haxe.macro.Expr; @:noPackageRestrict class Prime { - - #if (!macro && cpp) - - public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic { - var factory:Callable< ConstCharStar -> Object > = - untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail); - if (factory!=null) - { - var func:Dynamic = factory.call(signature); - if (func==null && !quietFail) - throw '$prim does not have signature $signature'; - return func; - } - return null; + #if (!macro && cpp) + public static function _loadPrime(lib:String, prim:String, signature:String, quietFail = false):Dynamic { + var factory:CallableObject> = untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail); + if (factory != null) { + var func:Dynamic = factory.call(signature); + if (func == null && !quietFail) + throw '$prim does not have signature $signature'; + return func; + } + return null; } - #end - - #if (macro) - static function codeToType(code:String,forCpp:Bool) : String - { - var isCpp = Context.defined("cpp"); - - switch(code) - { - case "b" : return "Bool"; - case "i" : return "Int"; - case "d" : return "Float"; - case "s" : return "String"; - case "f" : return forCpp ? "cpp.Float32" : "Float"; - case "o" : return forCpp ? "cpp.Object" : "Dynamic"; - case "v" : return forCpp ? "cpp.Void" : "Dynamic"; - case "c" : - if (forCpp) - return "cpp.ConstCharStar"; - throw "const char * type only supported in cpp mode"; - default: - throw "Unknown signature type :" + code; - } - } - #end + #end - public static function nekoInit(inModuleName:String) : Bool - { - #if neko - var init = neko.Lib.load(inModuleName, "neko_init", 5); + #if (macro) + static function codeToType(code:String, forCpp:Bool):String { + if (code == "c" && !forCpp) + throw "const char * type only supported in cpp mode"; - if (init != null) - { - init( function(s) return new String(s), - function(len:Int) { var r = []; if (len > 0) r[len - 1] = null; return r; }, - null, - true, - false); - return true; - - } - #end - return false; - } + switch (code) { + case "b": + return "Bool"; + case "i": + return "Int"; + case "d": + return "Float"; + case "s": + return "String"; + case "f": + return forCpp ? "cpp.Float32" : "Float"; + case "o": + return forCpp ? "cpp.Object" : "Dynamic"; + case "v": + return forCpp ? "cpp.Void" : "Dynamic"; + case "c": + return "cpp.ConstCharStar"; + default: + throw "Unknown signature type :" + code; + } + } + #end + public static function nekoInit(inModuleName:String):Bool { + #if neko + var init = neko.Lib.load(inModuleName, "neko_init", 5); - public static macro function load(inModule:String, inName:String, inSig:String,inAllowFail:Bool = false) - { - var parts = inSig.split(""); - if (parts.length<1) - throw "Invalid function signature " + inSig; - var argCount = parts.length-1; + if (init != null) { + init(function(s) return new String(s), function(len:Int) { + var r = []; + if (len > 0) + r[len - 1] = null; + return r; + }, null, true, false); + return true; + } + #end + return false; + } - var cppMode = Context.defined("cpp"); + public static macro function load(inModule:String, inName:String, inSig:String, inAllowFail:Bool = false) { + var parts = inSig.split(""); + if (parts.length < 1) + throw "Invalid function signature " + inSig; + var argCount = parts.length - 1; - var typeString = parts.length==1 ? "Void" : codeToType(parts.shift(),cppMode); - for(p in parts) - typeString += "->" + codeToType(p,cppMode); + var cppiaMode = Context.defined("cppia"); + var cppMode = Context.defined("cpp") && !cppiaMode; - if (cppMode) - { - typeString = "cpp.Callable<" + typeString + ">"; - var expr = 'new $typeString(cpp.Prime._loadPrime("$inModule","$inName","$inSig",$inAllowFail))'; - return Context.parse( expr, Context.currentPos() ); - } - else - { - if (argCount>5) - argCount = -1; - var lazy = inAllowFail ? "loadLazy" : "load"; - var expr = 'new cpp.Callable<$typeString>(neko.Lib.$lazy("$inModule","$inName",$argCount))'; - return Context.parse( expr, Context.currentPos() ); - } - } + var typeString = parts.length == 1 ? "Void" : codeToType(parts.shift(), cppMode); + for (p in parts) + typeString += "->" + codeToType(p, cppMode); + if (cppMode) { + typeString = "cpp.Callable<" + typeString + ">"; + var expr = 'new $typeString(cpp.Prime._loadPrime("$inModule","$inName","$inSig",$inAllowFail))'; + return Context.parse(expr, Context.currentPos()); + } else { + if (argCount > 5) + argCount = -1; + var lazy = inAllowFail ? "loadLazy" : "load"; + var lib = cppiaMode ? "cpp" : "neko"; + var expr = 'new cpp.Callable<$typeString>($lib.Lib.$lazy("$inModule","$inName",$argCount))'; + return Context.parse(expr, Context.currentPos()); + } + } } diff --git a/std/cpp/Random.hx b/std/cpp/Random.hx index 3b47b8872e0..5ecbdfcf760 100644 --- a/std/cpp/Random.hx +++ b/std/cpp/Random.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,26 +19,25 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; class Random { - - var r : Dynamic; + var r:Dynamic; public function new() { r = cpp.NativeRandom.random_new(); } - public function setSeed( s : Int ) { - cpp.NativeRandom.random_set_seed(r,s); + public function setSeed(s:Int) { + cpp.NativeRandom.random_set_seed(r, s); } - public function int( max : Int ) : Int { - return cpp.NativeRandom.random_int(r,max); + public function int(max:Int):Int { + return cpp.NativeRandom.random_int(r, max); } - public function float() : Float { + public function float():Float { return cpp.NativeRandom.random_float(r); } - } diff --git a/std/cpp/RawConstPointer.hx b/std/cpp/RawConstPointer.hx index 426b0307625..adaf122c7e5 100644 --- a/std/cpp/RawConstPointer.hx +++ b/std/cpp/RawConstPointer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:unreflective -extern class RawConstPointer implements ArrayAccess -{ - @:native("hx::AddressOf") - public static function addressOf(t:T) : RawConstPointer; +extern class RawConstPointer implements ArrayAccess { + @:native("hx::AddressOf") + public static function addressOf(t:T):RawConstPointer; } diff --git a/std/cpp/RawPointer.hx b/std/cpp/RawPointer.hx index 2a9381bbd0a..c52bbd57da7 100644 --- a/std/cpp/RawPointer.hx +++ b/std/cpp/RawPointer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:unreflective -extern class RawPointer extends RawConstPointer -{ - @:native("hx::AddressOf") - public static function addressOf(t:T) : RawPointer; +extern class RawPointer extends RawConstPointer { + @:native("hx::AddressOf") + public static function addressOf(t:T):RawPointer; } diff --git a/std/cpp/Reference.hx b/std/cpp/Reference.hx index 884608cdcc3..c1ad6d0db7c 100644 --- a/std/cpp/Reference.hx +++ b/std/cpp/Reference.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,10 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; -// Allows haxe to type result correctly, and hxcpp can recognise this and prevent -// unwanted casting +/** + Allows haxe to type result correctly, and hxcpp can recognise this and + prevent unwanted casting. +**/ +@:semantics(reference) typedef Reference = T; - - diff --git a/std/cpp/SizeT.hx b/std/cpp/SizeT.hx index c476e72c8b2..3892c6a2b75 100644 --- a/std/cpp/SizeT.hx +++ b/std/cpp/SizeT.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,9 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:native("size_t") @:scalar @:coreType @:notNull -extern abstract SizeT from(Int) to(Int) { -} +extern abstract SizeT from(Int) to(Int) {} diff --git a/std/cpp/Star.hx b/std/cpp/Star.hx index 7adb8404295..2e60be25f8d 100644 --- a/std/cpp/Star.hx +++ b/std/cpp/Star.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,9 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp; - -// Allows haxe to type result correctly, and hxcpp can recognise this use the correct type -typedef Star = T; +package cpp; +/** + Allows haxe to type result correctly, and hxcpp can recognise this use the + correct type. +**/ +typedef Star = Null; diff --git a/std/cpp/StdString.hx b/std/cpp/StdString.hx index f640dc30e1b..41b4e6144f7 100644 --- a/std/cpp/StdString.hx +++ b/std/cpp/StdString.hx @@ -1,3 +1,25 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; using cpp.NativeString; @@ -6,17 +28,22 @@ using cpp.NativeString; @:include("hx/StdString.h") @:stackOnly @:structAccess -extern class StdString extends StdStringRef -{ - @:extern @:native("std::string::npos") - public static var npos(default,null):Int; +@:unreflective +extern class StdString { + @:native("std::string::npos") + public static var npos(default, null):Int; - //public function new(inData:StdStringData); + // public function new(inData:StdStringData); + @:native("hx::StdString") + static public function ofString(s:String):StdString; - @:native("hx::StdString") - static public function ofString(s:String) : StdString; - //public function toString():String; - //public function find(s:String):Int; - //public function substr(pos:Int, len:Int):StdString; + // public function toString():String; + // public function find(s:String):Int; + // public function substr(pos:Int, len:Int):StdString; + public function c_str():ConstPointer; + public function size():Int; + public function find(s:String):Int; + public function substr(pos:Int, len:Int):StdString; + public function toString():String; + public function toStdString():StdString; } - diff --git a/std/cpp/StdStringRef.hx b/std/cpp/StdStringRef.hx index 63dd8f272e3..a55472ad329 100644 --- a/std/cpp/StdStringRef.hx +++ b/std/cpp/StdStringRef.hx @@ -1,3 +1,25 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; using cpp.NativeString; @@ -5,13 +27,11 @@ using cpp.NativeString; @:native("hx::StdString const &") @:include("hx/StdString.h") @:structAccess -extern class StdStringRef -{ - public function c_str() : ConstPointer; - public function size() : Int; - public function find(s:String):Int; - public function substr(pos:Int, len:Int):StdString; - public function toString():String; - public function toStdString():StdString; +extern class StdStringRef { + public function c_str():ConstPointer; + public function size():Int; + public function find(s:String):Int; + public function substr(pos:Int, len:Int):StdString; + public function toString():String; + public function toStdString():StdString; } - diff --git a/std/cpp/Stdio.hx b/std/cpp/Stdio.hx index 6e09a66025a..6c30aeb62ec 100644 --- a/std/cpp/Stdio.hx +++ b/std/cpp/Stdio.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,27 +19,25 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; import haxe.extern.Rest; @:include("stdio.h") -extern class Stdio -{ - @:native("printf") - public static function printf(format:ConstCharStar, rest:Rest):Void; - - @:native("fopen") - public static function fopen(filename:ConstCharStar, mode:ConstCharStar) : FILE; +extern class Stdio { + @:native("printf") + public static function printf(format:ConstCharStar, rest:Rest):Void; - @:native("fwrite") - public static function fwrite(data:RawPointer, elemSize:SizeT, elemCount:SizeT, file:FILE ) : SizeT; + @:native("fopen") + public static function fopen(filename:ConstCharStar, mode:ConstCharStar):FILE; - @:native("fclose") - public static function fclose(file:FILE) : Int; + @:native("fwrite") + public static function fwrite(data:RawPointer, elemSize:SizeT, elemCount:SizeT, file:FILE):SizeT; + @:native("fclose") + public static function fclose(file:FILE):Int; - @:native("fprintf") - public static function fprintf(file:FILE,format:ConstCharStar, rest:Rest):Void; + @:native("fprintf") + public static function fprintf(file:FILE, format:ConstCharStar, rest:Rest):Void; } - diff --git a/std/cpp/Stdlib.hx b/std/cpp/Stdlib.hx index 12a46143882..2b299e58a5c 100644 --- a/std/cpp/Stdlib.hx +++ b/std/cpp/Stdlib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,40 +23,37 @@ package cpp; @:include("stdlib.h") -extern class Stdlib -{ - @:native("malloc") - public static function nativeMalloc(bytes:Int) : cpp.RawPointer return null; - @:native("calloc") - public static function nativeCalloc(bytes:Int) : cpp.RawPointer return null; - @:native("realloc") - public static function nativeRealloc(inPtr:cpp.RawPointer,bytes:Int) : cpp.RawPointer return null; - @:native("free") - public static function nativeFree(ptr:cpp.RawPointer) : Void { } - @:native("memcpy") - public static function nativeMemcpy(dest:cpp.RawPointer, src:cpp.RawConstPointer, bytes:Int) : Void { } - - @:native("hx::ClassSizeOf") @:templatedCall - public static function sizeof(t:T) : Int { } - - inline public static function memcpy(dest:cpp.Pointer, src:cpp.ConstPointer, bytes:Int) : Void - nativeMemcpy(cast dest.ptr, cast src.ptr, bytes); - - inline public static function malloc(bytes:Int) : cpp.Pointer - return cast nativeMalloc(bytes); - - inline public static function calloc(bytes:Int) : cpp.Pointer - return cast nativeCalloc(bytes); - - inline public static function realloc(ioPtr:cpp.Pointer, bytes:Int) : Void - ioPtr.setRaw( nativeRealloc(cast ioPtr.ptr, bytes) ); - - inline public static function free(ptr:cpp.Pointer) : Void - { - if (ptr!=null) - { - nativeFree(cast ptr.ptr); - ptr.ptr = null; - } - } +extern class Stdlib { + @:native("malloc") + public static function nativeMalloc(bytes:Int):cpp.RawPointer; + @:native("calloc") + public static function nativeCalloc(bytes:Int):cpp.RawPointer; + @:native("realloc") + public static function nativeRealloc(inPtr:cpp.RawPointer, bytes:Int):cpp.RawPointer; + @:native("free") + public static function nativeFree(ptr:cpp.RawPointer):Void; + @:native("memcpy") + public static function nativeMemcpy(dest:cpp.RawPointer, src:cpp.RawConstPointer, bytes:Int):Void; + + @:native("hx::ClassSizeOf") @:templatedCall + public static function sizeof(t:T):Int; + + inline public static function memcpy(dest:cpp.Pointer, src:cpp.ConstPointer, bytes:Int):Void + nativeMemcpy(cast dest.ptr, cast src.ptr, bytes); + + inline public static function malloc(bytes:Int):cpp.Pointer + return cast nativeMalloc(bytes); + + inline public static function calloc(bytes:Int):cpp.Pointer + return cast nativeCalloc(bytes); + + inline public static function realloc(ioPtr:cpp.Pointer, bytes:Int):Void + ioPtr.setRaw(nativeRealloc(cast ioPtr.ptr, bytes)); + + inline public static function free(ptr:cpp.Pointer):Void { + if (ptr != null) { + nativeFree(cast ptr.ptr); + ptr.ptr = null; + } + } } diff --git a/std/cpp/Struct.hx b/std/cpp/Struct.hx index c217939b279..957857a454a 100644 --- a/std/cpp/Struct.hx +++ b/std/cpp/Struct.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,10 +19,10 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; -// Wrap external types with a class that integrates with Dynamic +/** + Wraps external types with a class that integrates with Dynamic. +**/ typedef Struct = T; - - - diff --git a/std/cpp/UInt16.hx b/std/cpp/UInt16.hx index 9a82bbb4594..b155b9b8bcb 100644 --- a/std/cpp/UInt16.hx +++ b/std/cpp/UInt16.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract UInt16 from Int to Int {} diff --git a/std/cpp/UInt32.hx b/std/cpp/UInt32.hx index 0188d5b9633..e5dd135ba02 100644 --- a/std/cpp/UInt32.hx +++ b/std/cpp/UInt32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract UInt32 from Int to Int {} diff --git a/std/cpp/UInt64.hx b/std/cpp/UInt64.hx index 6662d6a603e..8a160e58c5e 100644 --- a/std/cpp/UInt64.hx +++ b/std/cpp/UInt64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract UInt64 from Int to Int {} diff --git a/std/cpp/UInt8.hx b/std/cpp/UInt8.hx index f32df37c2f6..d19bed91f74 100644 --- a/std/cpp/UInt8.hx +++ b/std/cpp/UInt8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; + +package cpp; @:coreType @:notNull @:runtimeValue abstract UInt8 from Int to Int {} diff --git a/std/cpp/VarArg.hx b/std/cpp/VarArg.hx index 655587fe847..41af99d9be7 100644 --- a/std/cpp/VarArg.hx +++ b/std/cpp/VarArg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,10 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp; -// Allows haxe to type params correctly, and hxcpp can recognise this use the correct type +/** + Allows haxe to type params correctly, and hxcpp can recognise this use the + correct type. +**/ typedef VarArg = Dynamic; - - - diff --git a/std/cpp/VirtualArray.hx b/std/cpp/VirtualArray.hx index 263ab752867..9af2d7faf57 100644 --- a/std/cpp/VirtualArray.hx +++ b/std/cpp/VirtualArray.hx @@ -1,76 +1,132 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp; @:native("cpp::VirtualArray") -@:coreType extern class NativeVirtualArray implements ArrayAccess -{ - public function new() : Void; - public var length(get,null) : Int; - // concat( a:Array ) : Array ? - public function concat( a : VirtualArray ) : VirtualArray; - public function join( sep : String ) : String; - public function pop() : Dynamic; - public function push(x : Dynamic) : Int; - public function reverse() : Void; - public function shift() : Dynamic; - public function slice( pos : Int, ?end : Int ) : VirtualArray; - public function sort( f : Dynamic -> Dynamic -> Int ) : Void; - public function splice( pos : Int, len : Int ) : VirtualArray; - public function toString() : String; - public function unshift( x : Dynamic ) : Void; - public function insert( pos : Int, x : Dynamic ) : Void; - public function remove( x : Dynamic ) : Bool; - public function indexOf( x : Dynamic, ?fromIndex:Int ) : Int; - public function lastIndexOf( x : Dynamic, ?fromIndex:Int ) : Int; - public function copy() : VirtualArray; - public function iterator() : Iterator; - public function map( f : Dynamic -> S ) : VirtualArray; - public function filter( f : Dynamic -> Bool ) : VirtualArray; +@:coreType extern class NativeVirtualArray implements ArrayAccess { + public function new():Void; + public var length(get, null):Int; + // concat( a:Array ) : Array ? + public function concat(a:VirtualArray):VirtualArray; + public function join(sep:String):String; + public function pop():Dynamic; + public function push(x:Dynamic):Int; + public function reverse():Void; + public function shift():Dynamic; + public function slice(pos:Int, ?end:Int):VirtualArray; + public function sort(f:Dynamic->Dynamic->Int):Void; + public function splice(pos:Int, len:Int):VirtualArray; + public function toString():String; + public function unshift(x:Dynamic):Void; + public function insert(pos:Int, x:Dynamic):Void; + public function remove(x:Dynamic):Bool; + public function indexOf(x:Dynamic, ?fromIndex:Int):Int; + public function lastIndexOf(x:Dynamic, ?fromIndex:Int):Int; + public function copy():VirtualArray; + public function iterator():Iterator; + public function map(f:Dynamic->S):VirtualArray; + public function filter(f:Dynamic->Bool):VirtualArray; + public function resize(len:Int):Void; } +abstract VirtualArray(NativeVirtualArray) { + // Add these two functions... + @:from extern inline static public function fromArray(a:Array):VirtualArray + return untyped a; -abstract VirtualArray(NativeVirtualArray) -{ - // Add these two functions... - @:from @:extern inline static public function fromArray(a:Array) : VirtualArray - return untyped a; - @:to @:extern inline public function toArray() : Array - return untyped this; + @:to extern inline public function toArray():Array + return untyped this; + // The rest is just boiler-plate + inline public function new() + this = new NativeVirtualArray(); + @:arrayAccess extern inline function get(idx:Int):Dynamic + return untyped this[idx]; + @:arrayAccess extern inline function set(pos:Int, value:T):T + return untyped this[idx] = value; - // The rest is just boiler-plate - inline public function new() this=new NativeVirtualArray(); + public var length(get, never):Int; - @:extern @:arrayAccess inline function get(idx:Int) : Dynamic - return untyped this[idx]; + extern inline public function get_length():Int + return this.length; - @:extern @:arrayAccess inline function set(pos:Int, value:T ) : T - return untyped this[idx] = value; + // concat( a:Array ) : Array ? + extern inline public function concat(a:VirtualArray):VirtualArray + return this.concat(a); - public var length(get,never) : Int; - @:extern inline public function get_length() : Int return this.length; + extern inline public function join(sep:String):String + return this.join(sep); + extern inline public function pop():Dynamic + return this.pop(); + extern inline public function push(x:Dynamic):Int + return this.push(x); - // concat( a:Array ) : Array ? - @:extern inline public function concat( a : VirtualArray ) : VirtualArray return this.concat(a); - @:extern inline public function join( sep : String ) : String return this.join(sep); - @:extern inline public function pop() : Dynamic return this.pop(); - @:extern inline public function push(x : Dynamic) : Int return this.push(x); - @:extern inline public function reverse() : Void this.reverse(); - @:extern inline public function shift() : Dynamic return this.shift(); - @:extern inline public function slice( pos : Int, ?end : Int ) : VirtualArray return this.slice(pos,end); - @:extern inline public function sort( f : Dynamic -> Dynamic -> Int ) : Void this.sort(f); - @:extern inline public function splice( pos : Int, len : Int ) : VirtualArray return this.slice(pos,len); - @:extern inline public function unshift( x : Dynamic ) : Void this.unshift(x); - @:extern inline public function insert( pos : Int, x : Dynamic ) : Void this.insert(pos,x); - @:extern inline public function remove( x : Dynamic ) : Bool return this.remove(x); - @:extern inline public function indexOf( x : Dynamic, ?fromIndex:Int ) : Int return this.indexOf(x,fromIndex); - @:extern inline public function lastIndexOf( x : Dynamic, ?fromIndex:Int ) : Int return this.lastIndexOf(x,fromIndex); - @:extern inline public function copy() : VirtualArray return this.copy(); - @:extern inline public function iterator() : Iterator return this.iterator(); - @:extern inline public function map( f : Dynamic -> S ) : VirtualArray return this.map(f); - @:extern inline public function filter( f : Dynamic -> Bool ) : VirtualArray return this.filter(f); -} + extern inline public function reverse():Void + this.reverse(); + + extern inline public function shift():Dynamic + return this.shift(); + + extern inline public function slice(pos:Int, ?end:Int):VirtualArray + return this.slice(pos, end); + + extern inline public function sort(f:Dynamic->Dynamic->Int):Void + this.sort(f); + + extern inline public function splice(pos:Int, len:Int):VirtualArray + return this.slice(pos, len); + + extern inline public function unshift(x:Dynamic):Void + this.unshift(x); + + extern inline public function insert(pos:Int, x:Dynamic):Void + this.insert(pos, x); + extern inline public function remove(x:Dynamic):Bool + return this.remove(x); + + extern inline public function indexOf(x:Dynamic, ?fromIndex:Int):Int + return this.indexOf(x, fromIndex); + + extern inline public function lastIndexOf(x:Dynamic, ?fromIndex:Int):Int + return this.lastIndexOf(x, fromIndex); + + extern inline public function copy():VirtualArray + return this.copy(); + + extern inline public function iterator():Iterator + return this.iterator(); + + extern inline public function map(f:Dynamic->S):VirtualArray + return this.map(f); + + extern inline public function filter(f:Dynamic->Bool):VirtualArray + return this.filter(f); + + extern inline public function resize(len:Int):Void + return this.resize(len); +} diff --git a/std/cpp/Void.hx b/std/cpp/Void.hx index af33561ef47..d002c538356 100644 --- a/std/cpp/Void.hx +++ b/std/cpp/Void.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,8 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp; -@:native("void") -extern class Void { } +package cpp; +@:native("void") +extern class Void {} diff --git a/std/cpp/_std/Date.hx b/std/cpp/_std/Date.hx index f960aa14b74..3556b10312e 100644 --- a/std/cpp/_std/Date.hx +++ b/std/cpp/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,65 +19,110 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -@:coreApi class Date { - +@:coreApi class Date { private var mSeconds:Float; - public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void { - mSeconds = untyped __global__.__hxcpp_new_date(year,month,day,hour,min,sec); + public function new(year:Int, month:Int, day:Int, hour:Int, min:Int, sec:Int):Void { + mSeconds = untyped __global__.__hxcpp_new_date(year, month, day, hour, min, sec); } - public function getTime() : Float { + public function getTime():Float { return mSeconds * 1000.0; } - public function getHours() : Int { return untyped __global__.__hxcpp_get_hours(mSeconds); } + public function getHours():Int { + return untyped __global__.__hxcpp_get_hours(mSeconds); + } + + public function getMinutes():Int { + return untyped __global__.__hxcpp_get_minutes(mSeconds); + } - public function getMinutes() : Int { return untyped __global__.__hxcpp_get_minutes(mSeconds); } + public function getSeconds():Int { + return untyped __global__.__hxcpp_get_seconds(mSeconds); + } + + public function getFullYear():Int { + return untyped __global__.__hxcpp_get_year(mSeconds); + } - public function getSeconds() : Int { return untyped __global__.__hxcpp_get_seconds(mSeconds); } + public function getMonth():Int { + return untyped __global__.__hxcpp_get_month(mSeconds); + } - public function getFullYear() : Int { return untyped __global__.__hxcpp_get_year(mSeconds); } + public function getDate():Int { + return untyped __global__.__hxcpp_get_date(mSeconds); + } - public function getMonth() : Int { return untyped __global__.__hxcpp_get_month(mSeconds); } + public function getDay():Int { + return untyped __global__.__hxcpp_get_day(mSeconds); + } - public function getDate() : Int { return untyped __global__.__hxcpp_get_date(mSeconds); } + public function getUTCHours():Int { + return untyped __global__.__hxcpp_get_utc_hours(mSeconds); + } - public function getDay() : Int { return untyped __global__.__hxcpp_get_day(mSeconds); } + public function getUTCMinutes():Int { + return untyped __global__.__hxcpp_get_utc_minutes(mSeconds); + } - public function toString():String { return untyped __global__.__hxcpp_to_string(mSeconds); } + public function getUTCSeconds():Int { + return untyped __global__.__hxcpp_get_utc_seconds(mSeconds); + } - public static function now() : Date { - return fromTime( untyped __global__.__hxcpp_date_now()*1000.0); + public function getUTCFullYear():Int { + return untyped __global__.__hxcpp_get_utc_year(mSeconds); } - private static function new1(t : Dynamic) : Date { - return new Date(2005,1,1,0,0,0); + + public function getUTCMonth():Int { + return untyped __global__.__hxcpp_get_utc_month(mSeconds); } - public static function fromTime( t : Float ) : Date { - var result = new Date(0,0,0,0,0,0); - result.mSeconds = t*0.001; + public function getUTCDate():Int { + return untyped __global__.__hxcpp_get_utc_date(mSeconds); + } + + public function getUTCDay():Int { + return untyped __global__.__hxcpp_get_utc_day(mSeconds); + } + + public function getTimezoneOffset():Int { + return -Std.int((untyped __global__.__hxcpp_timezone_offset(mSeconds)) / 60); + } + + public function toString():String { + return untyped __global__.__hxcpp_to_string(mSeconds); + } + + public static function now():Date { + return fromTime(untyped __global__.__hxcpp_date_now() * 1000.0); + } + + private static function new1(t:Dynamic):Date { + return new Date(2005, 1, 1, 0, 0, 0); + } + + public static function fromTime(t:Float):Date { + var result = new Date(0, 0, 0, 0, 0, 0); + result.mSeconds = t * 0.001; return result; } - public static function fromString( s : String ) : Date { - switch( s.length ) { + public static function fromString(s:String):Date { + switch (s.length) { case 8: // hh:mm:ss var k = s.split(":"); - var d : Date = new Date(0,0,0,Std.parseInt(k[0]),Std.parseInt(k[1]),Std.parseInt(k[2])); - return d; + return Date.fromTime(Std.parseInt(k[0]) * 3600000. + Std.parseInt(k[1]) * 60000. + Std.parseInt(k[2]) * 1000.); case 10: // YYYY-MM-DD var k = s.split("-"); - return new Date(Std.parseInt(k[0]),Std.parseInt(k[1])-1,Std.parseInt(k[2]),0,0,0); + return new Date(Std.parseInt(k[0]), Std.parseInt(k[1]) - 1, Std.parseInt(k[2]), 0, 0, 0); case 19: // YYYY-MM-DD hh:mm:ss var k = s.split(" "); var y = k[0].split("-"); var t = k[1].split(":"); - return new Date(Std.parseInt(y[0]),Std.parseInt(y[1]) - 1,Std.parseInt(y[2]), - Std.parseInt(t[0]),Std.parseInt(t[1]),Std.parseInt(t[2])); + return new Date(Std.parseInt(y[0]), Std.parseInt(y[1]) - 1, Std.parseInt(y[2]), Std.parseInt(t[0]), Std.parseInt(t[1]), Std.parseInt(t[2])); default: throw "Invalid date format : " + s; } } } - diff --git a/std/cpp/_std/EReg.hx b/std/cpp/_std/EReg.hx index 07fc145d727..b671550318b 100644 --- a/std/cpp/_std/EReg.hx +++ b/std/cpp/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,136 +19,134 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - @:buildXml('') @:coreApi class EReg { - - var r : Dynamic; - var last : String; - var global : Bool; - - public function new( r : String, opt : String ) : Void { - var a = opt.split("g"); - global = a.length > 1; - if( global ) - opt = a.join(""); - this.r = _hx_regexp_new_options(r, opt); + var r:Dynamic; + var last:String; + var global:Bool; + + public function new(r:String, opt:String):Void { + var a = opt.split("g"); + global = a.length > 1; + if (global) + opt = a.join(""); + this.r = _hx_regexp_new_options(r, opt); } - public function match( s : String ) : Bool { - var p = _hx_regexp_match(r,s,0,s.length); - if( p ) - last = s; - else - last = null; - return p; + public function match(s:String):Bool { + var p = _hx_regexp_match(r, s, 0, s.length); + if (p) + last = s; + else + last = null; + return p; } - public function matched( n : Int ) : String { - var m = _hx_regexp_matched(r,n); - return m; + public function matched(n:Int):String { + var m = _hx_regexp_matched(r, n); + return m; } - public function matchedLeft() : String { - var p = _hx_regexp_matched_pos(r,0); - return last.substr(0,p.pos); + public function matchedLeft():String { + var p = _hx_regexp_matched_pos(r, 0); + return last.substr(0, p.pos); } - public function matchedRight() : String { - var p = _hx_regexp_matched_pos(r,0); - var sz = p.pos+p.len; - return last.substr(sz,last.length-sz); + public function matchedRight():String { + var p = _hx_regexp_matched_pos(r, 0); + var sz = p.pos + p.len; + return last.substr(sz, last.length - sz); } - public function matchedPos() : { pos : Int, len : Int } { - return _hx_regexp_matched_pos(r,0); + public function matchedPos():{pos:Int, len:Int} { + return _hx_regexp_matched_pos(r, 0); } - public function matchSub( s : String, pos : Int, len : Int = -1):Bool { - var p = _hx_regexp_match(r, s, pos, len < 0 ? s.length - pos : len); - if (p) - last = s; - else - last = null; - return p; + public function matchSub(s:String, pos:Int, len:Int = -1):Bool { + var p = _hx_regexp_match(r, s, pos, len < 0 ? s.length - pos : len); + if (p) + last = s; + else + last = null; + return p; } - public function split( s : String ) : Array { - var pos = 0; - var len = s.length; - var a = new Array(); - var first = true; - do { - if( !_hx_regexp_match(r,s,pos,len) ) + public function split(s:String):Array { + var pos = 0; + var len = s.length; + var a = new Array(); + var first = true; + do { + if (!_hx_regexp_match(r, s, pos, len)) + break; + var p = _hx_regexp_matched_pos(r, 0); + if (p.len == 0 && !first) { + if (p.pos == s.length) break; - var p = _hx_regexp_matched_pos(r,0); - if( p.len == 0 && !first ) { - if( p.pos == s.length ) - break; - p.pos += 1; - } - a.push(s.substr(pos,p.pos - pos)); - var tot = p.pos + p.len - pos; - pos += tot; - len -= tot; - first = false; - } while( global ); - a.push(s.substr(pos,len)); - return a; + p.pos += 1; + } + a.push(s.substr(pos, p.pos - pos)); + var tot = p.pos + p.len - pos; + pos += tot; + len -= tot; + first = false; + } while (global); + a.push(s.substr(pos, len)); + return a; } - public function replace( s : String, by : String ) : String { - var b = new StringBuf(); - var pos = 0; - var len = s.length; - var a = by.split("$"); - var first = true; - do { - if( !_hx_regexp_match(r,s,pos,len) ) + public function replace(s:String, by:String):String { + var b = new StringBuf(); + var pos = 0; + var len = s.length; + var a = by.split("$"); + var first = true; + do { + if (!_hx_regexp_match(r, s, pos, len)) + break; + var p = _hx_regexp_matched_pos(r, 0); + if (p.len == 0 && !first) { + if (p.pos == s.length) break; - var p = _hx_regexp_matched_pos(r,0); - if( p.len == 0 && !first ) { - if( p.pos == s.length ) - break; - p.pos += 1; - } - b.addSub(s,pos,p.pos-pos); - if( a.length > 0 ) - b.add(a[0]); - var i = 1; - while( i < a.length ) { - var k = a[i]; - var c = k.charCodeAt(0); - // 1...9 - if( c >= 49 && c <= 57 ) { - var p = try _hx_regexp_matched_pos(r,Std.int(c)-48) catch( e : String ) null; - if( p == null ){ - b.add("$"); - b.add(k); - }else{ - b.addSub(s,p.pos,p.len); - b.addSub(k,1,k.length - 1); - } - } else if( c == null ) { + p.pos += 1; + } + b.addSub(s, pos, p.pos - pos); + if (a.length > 0) + b.add(a[0]); + var i = 1; + while (i < a.length) { + var k = a[i]; + var c = k.charCodeAt(0); + // 1...9 + if (c >= 49 && c <= 57) { + var p = try _hx_regexp_matched_pos(r, Std.int(c) - 48) catch (e:String) null; + if (p == null) { b.add("$"); - i++; - var k2 = a[i]; - if( k2 != null && k2.length > 0 ) - b.add(k2); - } else - b.add("$"+k); + b.add(k); + } else { + b.addSub(s, p.pos, p.len); + b.addSub(k, 1, k.length - 1); + } + } else if (c == null) { + b.add("$"); i++; - } - var tot = p.pos + p.len - pos; - pos += tot; - len -= tot; - first = false; - } while( global ); - b.addSub(s,pos,len); - return b.toString(); + var k2 = a[i]; + if (k2 != null && k2.length > 0) + b.add(k2); + } else + b.add("$" + k); + i++; + } + var tot = p.pos + p.len - pos; + pos += tot; + len -= tot; + first = false; + } while (global); + b.addSub(s, pos, len); + return b.toString(); } - public function map( s : String, f : EReg -> String ) : String { + public function map(s:String, f:EReg->String):String { var offset = 0; var buf = new StringBuf(); do { @@ -158,14 +156,13 @@ buf.add(s.substr(offset)); break; } - var p = _hx_regexp_matched_pos(r,0); + var p = _hx_regexp_matched_pos(r, 0); buf.add(s.substr(offset, p.pos - offset)); buf.add(f(this)); if (p.len == 0) { buf.add(s.substr(p.pos, 1)); offset = p.pos + 1; - } - else + } else offset = p.pos + p.len; } while (global); if (!global && offset > 0 && offset < s.length) @@ -173,20 +170,24 @@ return buf.toString(); } - public static function escape( s : String ) : String { + public static function escape(s:String):String { return escapeRegExpRe.map(s, function(r) return "\\" + r.matched(0)); } + static var escapeRegExpRe = ~/[\[\]{}()*+?.\\\^$|]/g; - @:extern @:native("_hx_regexp_new_options") - static function _hx_regexp_new_options(s:String, options:String) : Dynamic return null; + function toString():String + return 'EReg($r)'; + + @:native("_hx_regexp_new_options") + extern static function _hx_regexp_new_options(s:String, options:String):Dynamic; - @:extern @:native("_hx_regexp_match") - static function _hx_regexp_match(handler: Dynamic, string:String, pos:Int, len:Int) : Bool return false; + @:native("_hx_regexp_match") + extern static function _hx_regexp_match(handler:Dynamic, string:String, pos:Int, len:Int):Bool; - @:extern @:native("_hx_regexp_matched") - static function _hx_regexp_matched(handle:Dynamic, pos:Int) : String return null; + @:native("_hx_regexp_matched") + extern static function _hx_regexp_matched(handle:Dynamic, pos:Int):String; - @:extern @:native("_hx_regexp_matched_pos") - static function _hx_regexp_matched_pos(handle:Dynamic, match:Int) : {pos:Int, len:Int} return null; + @:native("_hx_regexp_matched_pos") + extern static function _hx_regexp_matched_pos(handle:Dynamic, match:Int):{pos:Int, len:Int}; } diff --git a/std/cpp/_std/Reflect.hx b/std/cpp/_std/Reflect.hx index 4f4c293604d..32ba5c8ecff 100644 --- a/std/cpp/_std/Reflect.hx +++ b/std/cpp/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,91 +25,105 @@ import cpp.ObjectType; @:coreApi @:analyzer(ignore) class Reflect { - - public static function hasField( o : Dynamic, field : String ) : Bool untyped { - return o!=null && o.__HasField(field); - } - - public static function field( o : Dynamic, field : String ) : Dynamic untyped { - return (o==null) ? null : o.__Field(field,untyped __cpp__("hx::paccNever") ); - } - - public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void untyped { - if (o!=null) - o.__SetField(field,value,untyped __cpp__("hx::paccNever") ); + public static function hasField(o:Dynamic, field:String):Bool + untyped { + return o != null && o.__HasField(field); + } + + public static function field(o:Dynamic, field:String):Dynamic + untyped { + return (o == null) ? null : o.__Field(field, untyped __cpp__("hx::paccNever")); + } + + public static function setField(o:Dynamic, field:String, value:Dynamic):Void + untyped { + if (o != null) + o.__SetField(field, value, untyped __cpp__("hx::paccNever")); + } + + public static function getProperty(o:Dynamic, field:String):Dynamic { + return (o == null) ? null : o.__Field(field, untyped __cpp__("hx::paccAlways")); } - public static function getProperty( o : Dynamic, field : String ) : Dynamic { - return (o==null) ? null : o.__Field(field,untyped __cpp__("hx::paccAlways") ); + public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void { + if (o != null) + o.__SetField(field, value, untyped __cpp__("hx::paccAlways")); } - public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void { - if (o!=null) - o.__SetField(field,value,untyped __cpp__("hx::paccAlways") ); - } - - public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic untyped { - if (func!=null && func.__GetType()==ObjectType.vtString) { - if (o==null) throw cpp.ErrorConstants.invalidObject; - func = o.__Field(func,untyped __cpp__("hx::paccDynamic")); + public static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array):Dynamic + untyped { + if (func != null && func.__GetType() == ObjectType.vtString) { + if (o == null) + throw cpp.ErrorConstants.invalidObject; + func = o.__Field(func, untyped __cpp__("hx::paccDynamic")); } - if (func==null) throw cpp.ErrorConstants.nullFunctionPointer; + if (func == null) + throw cpp.ErrorConstants.nullFunctionPointer; untyped func.__SetThis(o); - return untyped func.__Run(args); + return untyped func.__Run(args); + } + + public static function fields(o:Dynamic):Array + untyped { + if (o == null) + return new Array(); + var a:Array = []; + o.__GetFields(a); + return a; + } + + public static function isFunction(f:Dynamic):Bool + untyped { + return f != null && f.__GetType() == ObjectType.vtFunction; + } + + public static function compare(a:T, b:T):Int { + return (a == b) ? 0 : (((a : Dynamic) > (b : Dynamic)) ? 1 : -1); } - public static function fields( o : Dynamic ) : Array untyped { - if( o == null ) return new Array(); - var a : Array = []; - o.__GetFields(a); - return a; - } - - public static function isFunction( f : Dynamic ) : Bool untyped { - return f!=null && f.__GetType() == ObjectType.vtFunction; - } - - public static function compare( a : T, b : T ) : Int { - return ( a == b ) ? 0 : (((a:Dynamic) > (b:Dynamic)) ? 1 : -1); - } - - public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool { - if( f1 == f2 ) + public static function compareMethods(f1:Dynamic, f2:Dynamic):Bool { + if (f1 == f2) return true; - if( !isFunction(f1) || !isFunction(f2) ) + if (!isFunction(f1) || !isFunction(f2)) return false; - return untyped __global__.__hxcpp_same_closure(f1,f2); - } - - public static function isObject( v : Dynamic ) : Bool untyped { - if (v==null) return false; - var t:Int = v.__GetType(); - return t == ObjectType.vtObject || t==ObjectType.vtClass || t==ObjectType.vtString || - t==ObjectType.vtArray; - } - - public static function isEnumValue( v : Dynamic ) : Bool untyped { - return v!=null && v.__GetType() == ObjectType.vtEnum; - } - - public static function deleteField( o : Dynamic, field : String ) : Bool untyped { - if (o==null) return false; - return untyped __global__.__hxcpp_anon_remove(o,field); + return untyped __global__.__hxcpp_same_closure(f1, f2); } - public static function copy( o : T ) : T { - if (o==null) return null; - if(untyped o.__GetType()==ObjectType.vtString ) return o; - if(untyped o.__GetType()==ObjectType.vtArray ) + public static function isObject(v:Dynamic):Bool + untyped { + if (v == null) + return false; + var t:Int = v.__GetType(); + return t == ObjectType.vtObject || t == ObjectType.vtClass || t == ObjectType.vtString || t == ObjectType.vtArray; + } + + public static function isEnumValue(v:Dynamic):Bool + untyped { + return v != null && v.__GetType() == ObjectType.vtEnum; + } + + public static function deleteField(o:Dynamic, field:String):Bool + untyped { + if (o == null) + return false; + return untyped __global__.__hxcpp_anon_remove(o, field); + } + + public static function copy(o:Null):Null { + if (o == null) + return null; + if (untyped o.__GetType() == ObjectType.vtString) + return o; + if (untyped o.__GetType() == ObjectType.vtArray) return untyped o.__Field("copy", untyped __cpp__("hx::paccDynamic"))(); - var o2 : Dynamic = {}; - for( f in Reflect.fields(o) ) - Reflect.setField(o2,f,Reflect.field(o,f)); + var o2:Dynamic = {}; + for (f in Reflect.fields(o)) + Reflect.setField(o2, f, Reflect.field(o, f)); return o2; } - @:overload(function( f : Array -> Void ) : Dynamic {}) - public static function makeVarArgs( f : Array -> Dynamic ) : Dynamic { + @:overload(function(f:Array->Void):Dynamic {}) + public static function makeVarArgs(f:Array->Dynamic):Dynamic { return untyped __global__.__hxcpp_create_var_args(f); } } diff --git a/std/cpp/_std/Std.hx b/std/cpp/_std/Std.hx index fe7a71048a7..95be55dce55 100644 --- a/std/cpp/_std/Std.hx +++ b/std/cpp/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,33 +19,40 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +@:headerClassCode("\t\tstatic inline String string(String &s) { return s; }") @:coreApi class Std { - @:keep public static function is( v : Dynamic, t : Dynamic ) : Bool { - return untyped __global__.__instanceof(v,t); + @:keep public static function is(v:Dynamic, t:Dynamic):Bool { + return untyped __global__.__instanceof(v, t); } - @:keep public static function instance( value : T, c : Class ) : S { + @:keep public static function downcast(value:T, c:Class):S { return Std.is(value, c) ? cast value : null; } - @:keep public static function string( s : Dynamic ) : String { - return untyped s==null ? "null" : s.toString(); + @:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.') + @:keep public static function instance(value:T, c:Class):S { + return inline downcast(value, c); } - @:keep public static function int( x : Float ) : Int { + @:keep public static function string(s:Dynamic):String { + return untyped s == null ? "null" : s.toString(); + } + + @:keep public static function int(x:Float):Int { return untyped __global__.__int__(x); } - @:keep public static function parseInt( x : String ) : Null { + @:keep public static function parseInt(x:String):Null { return untyped __global__.__hxcpp_parse_int(x); } - @:keep public static function parseFloat( x : String ) : Float { + @:keep public static function parseFloat(x:String):Float { return untyped __global__.__hxcpp_parse_float(x); } - @:keep public static function random( x : Int ) : Int { - if (x <= 0) return 0; + @:keep public static function random(x:Int):Int { + if (x <= 0) + return 0; return untyped __global__.__hxcpp_irand(x); } } diff --git a/std/cpp/_std/StringBuf.hx b/std/cpp/_std/StringBuf.hx index 97d53810303..aca39e22dbe 100644 --- a/std/cpp/_std/StringBuf.hx +++ b/std/cpp/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,71 +19,83 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import cpp.NativeString; + using cpp.NativeArray; @:coreApi class StringBuf { - private var b : Array; - public var length(get,never) : Int; - var charBuf:Array; + private var b:Array; + + public var length(get, never):Int; + + var charBuf:Array; - public function new() : Void { - } + public function new():Void {} - private function charBufAsString() : String - { - var len = charBuf.length; - charBuf.push(0); - return NativeString.fromGcPointer( charBuf.address(0), len ); - } + private function charBufAsString():String { + var len = charBuf.length; + charBuf.push(0); + return NativeString.fromGcPointer(charBuf.address(0), len); + } - private function flush() : Void{ - if (b==null) - b = [charBufAsString()]; - else - b.push( charBufAsString() ); - charBuf = null; - } - function get_length() : Int { - var len = 0; - if (charBuf!=null) - len = charBuf.length; - if (b!=null) - for(s in b) - len += s==null ? 4 : s.length; - return len; - } + private function flush():Void { + if (b == null) + b = [charBufAsString()]; + else + b.push(charBufAsString()); + charBuf = null; + } - public inline function add( x : T ) : Void { - if (charBuf!=null) flush(); - if (b==null) - b = [Std.string(x)]; - else - b.push(Std.string(x)); - } + function get_length():Int { + var len = 0; + if (charBuf != null) + len = charBuf.length; + if (b != null) + for (s in b) + len += s == null ? 4 : s.length; + return len; + } - public #if !cppia inline #end function addSub( s : String, pos : Int, ?len : Int ) : Void { - if (charBuf!=null) flush(); - if (b==null) - b = [s.substr(pos,len)]; - else - b.push(s.substr(pos,len)); - } + public inline function add(x:T):Void { + if (charBuf != null) + flush(); + if (b == null) + b = [Std.string(x)]; + else + b.push(Std.string(x)); + } - public #if !cppia inline #end function addChar( c : Int ) : Void { - if (charBuf==null) charBuf = new Array(); - charBuf.push(c); - } + public #if !cppia inline #end function addSub(s:String, pos:Int, ?len:Int):Void { + if (charBuf != null) + flush(); + if (b == null) + b = [s.substr(pos, len)]; + else + b.push(s.substr(pos, len)); + } - public function toString() : String { - if (charBuf!=null) - flush(); - if (b==null || b.length==0) - return ""; - if (b.length==1) - return b[0]; - return b.join(""); - } + public #if !cppia inline #end function addChar(c:Int):Void { + #if hxcpp_smart_strings + if (c >= 127) + add(String.fromCharCode(c)); + else + #end + { + if (charBuf == null) + charBuf = new Array(); + charBuf.push(c); + } + } + public function toString():String { + if (charBuf != null) + flush(); + if (b == null || b.length == 0) + return ""; + if (b.length == 1) + return b[0]; + return b.join(""); + } } diff --git a/std/cpp/_std/Sys.hx b/std/cpp/_std/Sys.hx index 88a0c90f23e..0d2e77ab2c1 100644 --- a/std/cpp/_std/Sys.hx +++ b/std/cpp/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,73 +19,75 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import cpp.NativeSys; +import haxe.SysTools; @:coreApi class Sys { - - public static function print( v : Dynamic ) : Void { + public static function print(v:Dynamic):Void { untyped __global__.__hxcpp_print(v); } - public static function println( v : Dynamic ) : Void { + public static function println(v:Dynamic):Void { untyped __global__.__hxcpp_println(v); } - @:access(sys.io.FileInput) - public static function stdin() : haxe.io.Input { + @:access(sys.io.FileInput) + public static function stdin():haxe.io.Input { return new sys.io.FileInput(cpp.NativeFile.file_stdin()); } - @:access(sys.io.FileOutput) - public static function stdout() : haxe.io.Output { + @:access(sys.io.FileOutput) + public static function stdout():haxe.io.Output { return new sys.io.FileOutput(cpp.NativeFile.file_stdout()); } - @:access(sys.io.FileOutput) - public static function stderr() : haxe.io.Output { + @:access(sys.io.FileOutput) + public static function stderr():haxe.io.Output { return new sys.io.FileOutput(cpp.NativeFile.file_stderr()); } - public static function getChar( echo : Bool ) : Int { + public static function getChar(echo:Bool):Int { return NativeSys.sys_getch(echo); } - public static function args() : Array untyped { - return __global__.__get_args(); - } + public static function args():Array + untyped { + return __global__.__get_args(); + } - public static function getEnv( s : String ):String { + public static function getEnv(s:String):String { var v = NativeSys.get_env(s); - if( v == null ) + if (v == null) return null; return v; } - public static function putEnv( s : String, v : String ) : Void { - NativeSys.put_env(s,v); + public static function putEnv(s:String, v:String):Void { + NativeSys.put_env(s, v); } - public static function sleep( seconds : Float ) : Void { + public static function sleep(seconds:Float):Void { NativeSys.sys_sleep(seconds); } - public static function setTimeLocale( loc : String ) : Bool { + public static function setTimeLocale(loc:String):Bool { return NativeSys.set_time_locale(loc); } - public static function getCwd() : String { + public static function getCwd():String { return NativeSys.get_cwd(); } - public static function setCwd( s : String ) : Void { + public static function setCwd(s:String):Void { NativeSys.set_cwd(s); } - public static function systemName() : String { + public static function systemName():String { return NativeSys.sys_string(); } - public static function command( cmd : String, ?args : Array ) : Int { + public static function command(cmd:String, ?args:Array):Int { if (args == null) { return NativeSys.sys_command(cmd); } else { @@ -93,45 +95,44 @@ import cpp.NativeSys; case "Windows": cmd = [ for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) - StringTools.quoteWinArg(a, true) + SysTools.quoteWinArg(a, true) ].join(" "); return NativeSys.sys_command(cmd); case _: - cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + cmd = [cmd].concat(args).map(SysTools.quoteUnixArg).join(" "); return NativeSys.sys_command(cmd); } } } - public static function exit( code : Int ) : Void { + public static function exit(code:Int):Void { untyped __global__.__hxcpp_exit(code); } - public static function time() : Float { + public static function time():Float { return NativeSys.sys_time(); } - public static function cpuTime() : Float { + public static function cpuTime():Float { return NativeSys.sys_cpu_time(); } - @:deprecated("Use programPath instead") public static function executablePath() : String { + @:deprecated("Use programPath instead") public static function executablePath():String { return NativeSys.sys_exe_path(); } - public static function programPath() : String { + public static function programPath():String { return NativeSys.sys_exe_path(); } - public static function environment() : Map { + public static function environment():Map { var vars:Array = NativeSys.sys_env(); var result = new haxe.ds.StringMap(); var i = 0; - while(i ); - TEnum( e : Enum ); + TClass(c:Class); + TEnum(e:Enum); TUnknown; } @:coreApi class Type { - public static function getClass( o : T ) : Class untyped { - if (o==null || !Reflect.isObject(o)) return null; + public static function getClass(o:T):Class + untyped { + if (o == null || !Reflect.isObject(o)) + return null; var c = o.__GetClass(); - switch(c.toString()) - { - case "__Anon" : return null; - case "Class" : return null; + switch (c.toString()) { + case "__Anon": + return null; + case "Class": + return null; } return c; - } - - public static function getEnum( o : EnumValue ) : Enum untyped { - if (o==null) return null; - return untyped o.__GetClass(); - } - - - public static function getSuperClass( c : Class ) : Class untyped { - return c.GetSuper(); - } - - public static function getClassName( c : Class ) : String { - if( c == null ) + } + + public static function getEnum(o:EnumValue):Enum + untyped { + if (o == null) + return null; + return untyped o.__GetClass(); + } + + public static function getSuperClass(c:Class):Class + untyped { + return c.GetSuper(); + } + + public static function getClassName(c:Class):String { + if (c == null) return null; return untyped c.mName; } - public static function getEnumName( e : Enum ) : String { + public static function getEnumName(e:Enum):String { return untyped e.__ToString(); } - public static function resolveClass( name : String ) : Class untyped { - var result:Class = Class.Resolve(name); - if (result!=null && result.__IsEnum() ) - return null; - return result; - } - - public static function resolveEnum( name : String ) : Enum untyped { - var result:Class = Class.Resolve(name); - if (result!=null && !result.__IsEnum() ) + public static function resolveClass(name:String):Class + untyped { + var result:Class = Class.Resolve(name); + if (result != null && result.__IsEnum()) + return null; + return result; + } + + public static function resolveEnum(name:String):Enum + untyped { + var result:Class = Class.Resolve(name); + if (result != null && !result.__IsEnum()) + return null; + return result; + } + + public static function createInstance(cl:Class, args:Array):T + untyped { + if (cl != null) + return cl.ConstructArgs(args); return null; - return result; - } + } - public static function createInstance( cl : Class, args : Array ) : T untyped { - if (cl!=null) - return cl.ConstructArgs(args); - return null; - } - - public static function createEmptyInstance( cl : Class ) : T untyped { - return cl.ConstructEmpty(); - } + public static function createEmptyInstance(cl:Class):T + untyped { + return cl.ConstructEmpty(); + } - public static function createEnum( e : Enum, constr : String, ?params : Array ) : T { - return untyped e.ConstructEnum(constr,params); + public static function createEnum(e:Enum, constr:String, ?params:Array):T { + return untyped e.ConstructEnum(constr, params); } - public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T { + public static function createEnumIndex(e:Enum, index:Int, ?params:Array):T { var c = Type.getEnumConstructs(e)[index]; - if( c == null ) throw index+" is not a valid enum constructor index"; - return createEnum(e,c,params); + if (c == null) + throw index + " is not a valid enum constructor index"; + return createEnum(e, c, params); } - public static function getInstanceFields( c : Class ) : Array { + public static function getInstanceFields(c:Class):Array { return untyped c.GetInstanceFields(); } - public static function getClassFields( c : Class ) : Array { - return untyped c.GetClassFields(); + public static function getClassFields(c:Class):Array { + return untyped c.GetClassFields(); } - public static function getEnumConstructs( e : Enum ) : Array untyped { + public static function getEnumConstructs(e:Enum):Array + untyped { return untyped e.GetClassFields(); - } + } - public static function typeof( v : Dynamic ) : ValueType untyped { - if (v==null) return TNull; + public static function typeof(v:Dynamic):ValueType + untyped { + if (v == null) + return TNull; var t:Int = untyped v.__GetType(); - switch(t) - { - case 2 : return TBool; - case 0xFF : return TInt; - case 1 : return TFloat; - case 6 : return TFunction; - case 4 : return TObject; - case 7 : return TEnum(v.__GetClass()); + switch (t) { + case 2: + return TBool; + case 0xFF: + return TInt; + case 1: + return TFloat; + case 6: + return TFunction; + case 4: + return TObject; + case 7: + return TEnum(v.__GetClass()); default: return untyped TClass(v.__GetClass()); } - } + } - public static function enumEq( a : T, b : T ) : Bool untyped { - return a==b; - } + public static function enumEq(a:T, b:T):Bool + untyped { + return a == b; + } - public static function enumConstructor( e : EnumValue ) : String { - var value:cpp.EnumBase = cast e; - return value._hx_getTag(); + public static function enumConstructor(e:EnumValue):String { + var value:cpp.EnumBase = cast e; + return value._hx_getTag(); } - public static function enumParameters( e : EnumValue ) : Array { - var value:cpp.EnumBase = cast e; - return value._hx_getParameters(); + public static function enumParameters(e:EnumValue):Array { + var value:cpp.EnumBase = cast e; + return value._hx_getParameters(); } - @:extern @:native("_hx_getEnumValueIndex") - private static function getEnumValueIndex( e : EnumValue ) : Int return 0; + @:native("_hx_getEnumValueIndex") + extern private static function getEnumValueIndex(e:EnumValue):Int; - #if !cppia inline #end public static function enumIndex( e : EnumValue ) : Int { - return getEnumValueIndex(e); + #if !cppia inline #end public static function enumIndex(e:EnumValue):Int { + return getEnumValueIndex(e); } - public static function allEnums( e : Enum ) : Array { - var names:Array = untyped e.GetClassFields(); + public static function allEnums(e:Enum):Array { + var names:Array = untyped e.GetClassFields(); var enums = new Array(); - for(name in names) - { - try { - var result:T = untyped e.ConstructEnum(name,null); - if (result!=null) - enums.push( result ); - } catch ( invalidArgCount:String) { - } - } + for (name in names) { + try { + var result:T = untyped e.ConstructEnum(name, null); + if (result != null) + enums.push(result); + } catch (invalidArgCount:String) {} + } return enums; } - } - diff --git a/std/cpp/_std/haxe/Int64.hx b/std/cpp/_std/haxe/Int64.hx index 0e75eea5689..37f3da93081 100644 --- a/std/cpp/_std/haxe/Int64.hx +++ b/std/cpp/_std/haxe/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,446 +19,395 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; import haxe.Int64Helper; @:notNull - - @:include("cpp/Int64.h") @:native("cpp::Int64Struct") private extern class ___Int64 { - public function get():cpp.Int64; - - @:native("_hx_int64_make") - public static function make(high:Int32, low:Int32): __Int64 return null; + public function get():cpp.Int64; - @:native(" ::cpp::Int64Struct") - public static function ofInt(value:Int): __Int64 return null; + @:native("_hx_int64_make") + public static function make(high:Int32, low:Int32):__Int64; - @:native(" ::cpp::Int64Struct::is") - public static function is(d:Dynamic):Bool return false; + @:native(" ::cpp::Int64Struct") + public static function ofInt(value:Int):__Int64; - @:native("_hx_int64_is_neg") - public static function isNeg(a:__Int64):Bool return false; + @:native(" ::cpp::Int64Struct::is") + public static function is(d:Dynamic):Bool; - @:native("_hx_int64_is_zero") - public static function isZero(a:__Int64):Bool return false; + @:native("_hx_int64_is_neg") + public static function isNeg(a:__Int64):Bool; - @:native("_hx_int64_compare") - public static function compare(a:__Int64, b:__Int64):Int return 0; + @:native("_hx_int64_is_zero") + public static function isZero(a:__Int64):Bool; - @:native("_hx_int64_ucompare") - public static function ucompare(a:__Int64, b:__Int64):Int return 0; + @:native("_hx_int64_compare") + public static function compare(a:__Int64, b:__Int64):Int; - @:native("_hx_int64_to_string") - public static function toString(a:__Int64):String return null; + @:native("_hx_int64_ucompare") + public static function ucompare(a:__Int64, b:__Int64):Int; - @:native("_hx_int64_neg") - public static function neg(a:__Int64): __Int64 return null; + @:native("_hx_int64_to_string") + public static function toString(a:__Int64):String; - @:native("_hx_int64_pre_increment") - public static function preIncrement(a:__Int64): __Int64 return null; + @:native("_hx_int64_neg") + public static function neg(a:__Int64):__Int64; - @:native("_hx_int64_post_increment") - public static function postIncrement(a:__Int64): __Int64 return null; + @:native("_hx_int64_pre_increment") + public static function preIncrement(a:__Int64):__Int64; - @:native("_hx_int64_pre_decrement") - public static function preDecrement(a:__Int64): __Int64 return null; + @:native("_hx_int64_post_increment") + public static function postIncrement(a:__Int64):__Int64; - @:native("_hx_int64_post_decrement") - public static function postDecrement(a:__Int64): __Int64 return null; + @:native("_hx_int64_pre_decrement") + public static function preDecrement(a:__Int64):__Int64; - @:native("_hx_int64_add") - public static function add(a:__Int64, b:__Int64): __Int64 return null; + @:native("_hx_int64_post_decrement") + public static function postDecrement(a:__Int64):__Int64; - @:native("_hx_int64_add") - public static function addInt(a:__Int64, b:Int): __Int64 return null; + @:native("_hx_int64_add") + public static function add(a:__Int64, b:__Int64):__Int64; - @:native("_hx_int64_sub") - public static function sub(a:__Int64, b:__Int64): __Int64 return null; + @:native("_hx_int64_add") + public static function addInt(a:__Int64, b:Int):__Int64; - @:native("_hx_int64_sub") - public static function subInt(a:__Int64, b:Int): __Int64 return null; + @:native("_hx_int64_sub") + public static function sub(a:__Int64, b:__Int64):__Int64; - @:native("_hx_int64_sub") - public static function intSub(a:Int, b:__Int64): __Int64 return null; + @:native("_hx_int64_sub") + public static function subInt(a:__Int64, b:Int):__Int64; - @:native("_hx_int64_mul") - public static function mul(a:__Int64, b:__Int64): __Int64 return null; + @:native("_hx_int64_sub") + public static function intSub(a:Int, b:__Int64):__Int64; - @:native("_hx_int64_div") - public static function div(a:__Int64, b:__Int64): __Int64 return null; + @:native("_hx_int64_mul") + public static function mul(a:__Int64, b:__Int64):__Int64; - @:native("_hx_int64_mod") - public static function mod(a:__Int64, b:__Int64): __Int64 return null; + @:native("_hx_int64_div") + public static function div(a:__Int64, b:__Int64):__Int64; - @:native("_hx_int64_eq") - public static function eq(a:__Int64, b:__Int64): Bool return null; + @:native("_hx_int64_mod") + public static function mod(a:__Int64, b:__Int64):__Int64; - @:native("_hx_int64_eq") - public static function eqInt(a:__Int64, b:Int): Bool return null; + @:native("_hx_int64_eq") + public static function eq(a:__Int64, b:__Int64):Bool; - @:native("_hx_int64_neq") - public static function neq(a:__Int64, b:__Int64): Bool return null; + @:native("_hx_int64_eq") + public static function eqInt(a:__Int64, b:Int):Bool; - @:native("_hx_int64_neq") - public static function neqInt(a:__Int64, b:Int): Bool return null; + @:native("_hx_int64_neq") + public static function neq(a:__Int64, b:__Int64):Bool; - @:native("_hx_int64_complement") - public static function complement(a:__Int64): __Int64 return null; + @:native("_hx_int64_neq") + public static function neqInt(a:__Int64, b:Int):Bool; - @:native("_hx_int64_and") - public static function bitAnd(a:__Int64, b:__Int64): __Int64 return null; + @:native("_hx_int64_complement") + public static function complement(a:__Int64):__Int64; - @:native("_hx_int64_or") - public static function bitOr(a:__Int64, b:__Int64): __Int64 return null; + @:native("_hx_int64_and") + public static function bitAnd(a:__Int64, b:__Int64):__Int64; - @:native("_hx_int64_xor") - public static function bitXor(a:__Int64, b:__Int64): __Int64 return null; + @:native("_hx_int64_or") + public static function bitOr(a:__Int64, b:__Int64):__Int64; - @:native("_hx_int64_shl") - public static function shl(a:__Int64, b:Int): __Int64 return null; + @:native("_hx_int64_xor") + public static function bitXor(a:__Int64, b:__Int64):__Int64; - @:native("_hx_int64_shr") - public static function shr(a:__Int64, b:Int): __Int64 return null; + @:native("_hx_int64_shl") + public static function shl(a:__Int64, b:Int):__Int64; - @:native("_hx_int64_ushr") - public static function ushr(a:__Int64, b:Int): __Int64 return null; + @:native("_hx_int64_shr") + public static function shr(a:__Int64, b:Int):__Int64; - @:native("_hx_int64_high") - public static function high(a:__Int64):Int32 return 0; + @:native("_hx_int64_ushr") + public static function ushr(a:__Int64, b:Int):__Int64; - @:native("_hx_int64_low") - public static function low(a:__Int64):Int32 return 0; + @:native("_hx_int64_high") + public static function high(a:__Int64):Int32; + @:native("_hx_int64_low") + public static function low(a:__Int64):Int32; } private typedef __Int64 = ___Int64; @:coreApi -abstract Int64( __Int64 ) from __Int64 to __Int64 -{ - /** - Makes a copy of `this` Int64. - **/ - public #if !cppia inline #end function copy():Int64 return this; +abstract Int64(__Int64) from __Int64 to __Int64 { + public #if !cppia inline #end function copy():Int64 + return this; - - public static #if !cppia inline #end function make( high : Int32, low : Int32 ) : Int64 { - return __Int64.make(high,low); + public static #if !cppia inline #end function make(high:Int32, low:Int32):Int64 { + return __Int64.make(high, low); } - @:from public static #if !cppia inline #end function ofInt( x : Int ) : Int64 { - return __Int64.ofInt(x); + @:from + public static #if !cppia inline #end function ofInt(x:Int):Int64 { + return __Int64.ofInt(x); } - - /** - Returns an Int with the value of the Int64 `x`. - Throws an exception if `x` cannot be represented in 32 bits. - **/ - public static #if !cppia inline #end function toInt( x : Int64 ) : Int { - if( x.high != x.low >> 31 ) + public static #if !cppia inline #end function toInt(x:Int64):Int { + if (x.high != x.low >> 31) throw "Overflow"; return x.low; } - /** - Returns whether the value `val` is of type `haxe.Int64` - **/ - public static #if !cppia inline #end function is( val : Dynamic ) : Bool - return __Int64.is(val); + public static #if !cppia inline #end function is(val:Dynamic):Bool + return __Int64.is(val); - /** - Returns the high 32-bit word of `x`. - **/ @:deprecated("Use high instead") - public static #if !cppia inline #end function getHigh( x : Int64 ) : Int32 + public static #if !cppia inline #end function getHigh(x:Int64):Int32 return x.high; - /** - Returns the low 32-bit word of `x`. - **/ @:deprecated("Use low instead") - public static #if !cppia inline #end function getLow( x : Int64 ) : Int32 + public static #if !cppia inline #end function getLow(x:Int64):Int32 return x.low; - /** - Returns `true` if `x` is less than zero. - **/ - public static #if !cppia inline #end function isNeg( x : Int64) : Bool - return __Int64.isNeg(x); - - /** - Returns `true` if `x` is exactly zero. - **/ - public static #if !cppia inline #end function isZero( x : Int64 ) : Bool - return __Int64.isZero(x); - - /** - Compares `a` and `b` in signed mode. - Returns a negative value if `a < b`, positive if `a > b`, - or 0 if `a == b`. - **/ - public static #if !cppia inline #end function compare( a : Int64, b : Int64 ) : Int - return __Int64.compare(a,b); - - /** - Compares `a` and `b` in unsigned mode. - Returns a negative value if `a < b`, positive if `a > b`, - or 0 if `a == b`. - **/ - public static #if !cppia inline #end function ucompare( a : Int64, b : Int64 ) : Int - return __Int64.ucompare(a,b); - - /** - Returns a signed decimal `String` representation of `x`. - **/ - public static #if !cppia inline #end function toStr(x:Int64) : String + public static #if !cppia inline #end function isNeg(x:Int64):Bool + return __Int64.isNeg(x); + + public static #if !cppia inline #end function isZero(x:Int64):Bool + return __Int64.isZero(x); + + public static #if !cppia inline #end function compare(a:Int64, b:Int64):Int + return __Int64.compare(a, b); + + public static #if !cppia inline #end function ucompare(a:Int64, b:Int64):Int + return __Int64.ucompare(a, b); + + public static #if !cppia inline #end function toStr(x:Int64):String return x.toString(); - private #if !cppia inline #end function toString() : String - return __Int64.toString(this); + private #if !cppia inline #end function toString():String + return __Int64.toString(this); - public static function parseString( sParam : String ) : Int64 { - return Int64Helper.parseString( sParam ); + public static function parseString(sParam:String):Int64 { + return Int64Helper.parseString(sParam); } - public static function fromFloat( f : Float ) : Int64 { - return Int64Helper.fromFloat( f ); + public static function fromFloat(f:Float):Int64 { + return Int64Helper.fromFloat(f); } - /** - Performs signed integer divison of `dividend` by `divisor`. - Returns `{ quotient : Int64, modulus : Int64 }`. - **/ - public static function divMod( dividend : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 } - { - var q = dividend/divisor; + public static function divMod(dividend:Int64, divisor:Int64):{quotient:Int64, modulus:Int64} { + var q = dividend / divisor; - if (isZero(divisor)) - throw "divide by zero"; + if (isZero(divisor)) + throw "divide by zero"; - var m = dividend - q*divisor; + var m = dividend - q * divisor; - return { quotient : q, modulus : m }; + return {quotient: q, modulus: m}; } - /** - Returns the negative of `x`. - **/ - @:op(-A) public static #if !cppia inline #end function neg( x : Int64 ) : Int64 - return __Int64.neg(x); - - @:op(++A) private inline function preIncrement() : Int64 { - #if cppia - this = this + make(0,1); - return this; - #else + @:op(-A) + public static #if !cppia inline #end function neg(x:Int64):Int64 + return __Int64.neg(x); + + @:op(++A) private inline function preIncrement():Int64 { + #if cppia + this = this + make(0, 1); + return this; + #else return __Int64.preIncrement(this); - #end + #end } - @:op(A++) private inline function postIncrement() : Int64 { - #if cppia - var result = this; - this = this + make(0,1); - return result; - #else + @:op(A++) private inline function postIncrement():Int64 { + #if cppia + var result = this; + this = this + make(0, 1); + return result; + #else return __Int64.postIncrement(this); - #end + #end } - @:op(--A) private inline function preDecrement() : Int64 { - #if cppia - untyped this = this - make(0,1); - return this; - #else + @:op(--A) private inline function preDecrement():Int64 { + #if cppia + untyped this = this - make(0, 1); + return this; + #else return __Int64.preDecrement(this); - #end + #end } - @:op(A--) private inline function postDecrement() : Int64 { - #if cppia - var result = this; - this = this - make(0,1); - return result; - #else + @:op(A--) private inline function postDecrement():Int64 { + #if cppia + var result = this; + this = this - make(0, 1); + return result; + #else return __Int64.postDecrement(this); - #end + #end } - /** - Returns the sum of `a` and `b`. - **/ - @:op(A + B) public static #if !cppia inline #end function add( a : Int64, b : Int64 ) : Int64 - return __Int64.add(a,b); + @:op(A + B) + public static #if !cppia inline #end function add(a:Int64, b:Int64):Int64 + return __Int64.add(a, b); - @:op(A + B) @:commutative private static #if !cppia inline #end function addInt( a : Int64, b : Int ) : Int64 - return __Int64.addInt(a,b); + @:op(A + B) + @:commutative + private static #if !cppia inline #end function addInt(a:Int64, b:Int):Int64 + return __Int64.addInt(a, b); - /** - Returns `a` minus `b`. - **/ - @:op(A - B) public static #if !cppia inline #end function sub( a : Int64, b : Int64 ) : Int64 { - return __Int64.sub(a,b); + @:op(A - B) + public static #if !cppia inline #end function sub(a:Int64, b:Int64):Int64 { + return __Int64.sub(a, b); } - @:op(A - B) private static #if !cppia inline #end function subInt( a : Int64, b : Int ) : Int64 - return __Int64.subInt( a, b ); + @:op(A - B) + private static #if !cppia inline #end function subInt(a:Int64, b:Int):Int64 + return __Int64.subInt(a, b); - @:op(A - B) private static #if !cppia inline #end function intSub( a : Int, b : Int64 ) : Int64 - return __Int64.intSub( a, b ); + @:op(A - B) + private static #if !cppia inline #end function intSub(a:Int, b:Int64):Int64 + return __Int64.intSub(a, b); - /** - Returns the product of `a` and `b`. - **/ - @:op(A * B) public static #if !cppia inline #end function mul( a : Int64, b : Int64 ) : Int64 - return __Int64.mul( a, b ); + @:op(A * B) + public static #if !cppia inline #end function mul(a:Int64, b:Int64):Int64 + return __Int64.mul(a, b); - @:op(A * B) @:commutative private static #if !cppia inline #end function mulInt( a : Int64, b : Int ) : Int64 - return mul( a, b ); + @:op(A * B) + @:commutative + private static #if !cppia inline #end function mulInt(a:Int64, b:Int):Int64 + return mul(a, b); - /** - Returns the quotient of `a` divided by `b`. - **/ - @:op(A / B) public static #if !cppia inline #end function div( a : Int64, b : Int64 ) : Int64 { + @:op(A / B) + public static #if !cppia inline #end function div(a:Int64, b:Int64):Int64 { if (__Int64.isZero(b)) throw "divide by zero"; - return __Int64.div(a,b); + return __Int64.div(a, b); } + @:op(A / B) + private static #if !cppia inline #end function divInt(a:Int64, b:Int):Int64 + return div(a, b); - @:op(A / B) private static #if !cppia inline #end function divInt( a : Int64, b : Int ) : Int64 - return div( a, b ); - - @:op(A / B) private static #if !cppia inline #end function intDiv( a : Int, b : Int64 ) : Int64 - return toInt(div( a, b )); + @:op(A / B) + private static #if !cppia inline #end function intDiv(a:Int, b:Int64):Int64 + return toInt(div(a, b)); - /** - Returns the modulus of `a` divided by `b`. - **/ - @:op(A % B) public static #if !cppia inline #end function mod( a : Int64, b : Int64 ) : Int64 - { + @:op(A % B) + public static #if !cppia inline #end function mod(a:Int64, b:Int64):Int64 { if (__Int64.isZero(b)) throw "divide by zero"; return __Int64.mod(a, b); - } + } - @:op(A % B) private static #if !cppia inline #end function modInt( a : Int64, b : Int ) : Int64 - return toInt(mod( a, b )); + @:op(A % B) + private static #if !cppia inline #end function modInt(a:Int64, b:Int):Int64 + return toInt(mod(a, b)); - @:op(A % B) private static #if !cppia inline #end function intMod( a : Int, b : Int64 ) : Int64 - return toInt(mod( a, b )); + @:op(A % B) + private static #if !cppia inline #end function intMod(a:Int, b:Int64):Int64 + return toInt(mod(a, b)); - /** - Returns `true` if `a` is equal to `b`. - **/ - @:op(A == B) public static #if !cppia inline #end function eq( a : Int64, b : Int64 ) : Bool - return __Int64.eq(a,b); + @:op(A == B) + public static #if !cppia inline #end function eq(a:Int64, b:Int64):Bool + return __Int64.eq(a, b); - @:op(A == B) @:commutative private static #if !cppia inline #end function eqInt( a : Int64, b : Int ) : Bool - return __Int64.eqInt( a, b ); + @:op(A == B) + @:commutative + private static #if !cppia inline #end function eqInt(a:Int64, b:Int):Bool + return __Int64.eqInt(a, b); - /** - Returns `true` if `a` is not equal to `b`. - **/ - @:op(A != B) public static #if !cppia inline #end function neq( a : Int64, b : Int64 ) : Bool - return __Int64.neq( a, b ); + @:op(A != B) + public static #if !cppia inline #end function neq(a:Int64, b:Int64):Bool + return __Int64.neq(a, b); - @:op(A != B) @:commutative private static #if !cppia inline #end function neqInt( a : Int64, b : Int ) : Bool - return neq( a, b ); + @:op(A != B) + @:commutative + private static #if !cppia inline #end function neqInt(a:Int64, b:Int):Bool + return neq(a, b); - @:op(A < B) private static #if !cppia inline #end function lt( a : Int64, b : Int64 ) : Bool + @:op(A < B) + private static #if !cppia inline #end function lt(a:Int64, b:Int64):Bool return compare(a, b) < 0; - @:op(A < B) private static #if !cppia inline #end function ltInt( a : Int64, b : Int ) : Bool + @:op(A < B) + private static #if !cppia inline #end function ltInt(a:Int64, b:Int):Bool return lt(a, b); - @:op(A < B) private static #if !cppia inline #end function intLt( a : Int, b : Int64 ) : Bool + @:op(A < B) + private static #if !cppia inline #end function intLt(a:Int, b:Int64):Bool return lt(a, b); - @:op(A <= B) private static #if !cppia inline #end function lte( a : Int64, b : Int64 ) : Bool + @:op(A <= B) + private static #if !cppia inline #end function lte(a:Int64, b:Int64):Bool return compare(a, b) <= 0; - @:op(A <= B) private static #if !cppia inline #end function lteInt( a : Int64, b : Int ) : Bool + @:op(A <= B) + private static #if !cppia inline #end function lteInt(a:Int64, b:Int):Bool return lte(a, b); - @:op(A <= B) private static #if !cppia inline #end function intLte( a : Int, b : Int64 ) : Bool + @:op(A <= B) + private static #if !cppia inline #end function intLte(a:Int, b:Int64):Bool return lte(a, b); - @:op(A > B) private static #if !cppia inline #end function gt( a : Int64, b : Int64 ) : Bool + @:op(A > B) + private static #if !cppia inline #end function gt(a:Int64, b:Int64):Bool return compare(a, b) > 0; - @:op(A > B) private static #if !cppia inline #end function gtInt( a : Int64, b : Int ) : Bool + @:op(A > B) + private static #if !cppia inline #end function gtInt(a:Int64, b:Int):Bool return gt(a, b); - @:op(A > B) private static #if !cppia inline #end function intGt( a : Int, b : Int64 ) : Bool - return gt( a, b ); + @:op(A > B) + private static #if !cppia inline #end function intGt(a:Int, b:Int64):Bool + return gt(a, b); - @:op(A >= B) private static #if !cppia inline #end function gte( a : Int64, b : Int64 ) : Bool + @:op(A >= B) + private static #if !cppia inline #end function gte(a:Int64, b:Int64):Bool return compare(a, b) >= 0; - @:op(A >= B) private static #if !cppia inline #end function gteInt( a : Int64, b : Int ) : Bool + @:op(A >= B) + private static #if !cppia inline #end function gteInt(a:Int64, b:Int):Bool return gte(a, b); - @:op(A >= B) private static #if !cppia inline #end function intGte( a : Int, b : Int64 ) : Bool + @:op(A >= B) + private static #if !cppia inline #end function intGte(a:Int, b:Int64):Bool return gte(a, b); - /** - Returns the bitwise NOT of `a`. - **/ - @:op(~A) private static #if !cppia inline #end function complement( a : Int64 ) : Int64 - return __Int64.complement(a); - - /** - Returns the bitwise AND of `a` and `b`. - **/ - @:op(A & B) public static #if !cppia inline #end function and( a : Int64, b : Int64 ) : Int64 - return __Int64.bitAnd(a,b); - - /** - Returns the bitwise OR of `a` and `b`. - **/ - @:op(A | B) public static #if !cppia inline #end function or( a : Int64, b : Int64 ) : Int64 - return __Int64.bitOr(a,b); - - /** - Returns the bitwise XOR of `a` and `b`. - **/ - @:op(A ^ B) public static #if !cppia inline #end function xor( a : Int64, b : Int64 ) : Int64 - return __Int64.bitXor(a,b); - - /** - Returns `a` left-shifted by `b` bits. - **/ - @:op(A << B) public static #if !cppia inline #end function shl( a : Int64, b : Int ) : Int64 - return __Int64.shl(a,b); - - /** - Returns `a` right-shifted by `b` bits in signed mode. - `a` is sign-extended. - **/ - @:op(A >> B) public static #if !cppia inline #end function shr( a : Int64, b : Int) : Int64 - return __Int64.shr(a,b); - - /** - Returns `a` right-shifted by `b` bits in unsigned mode. - `a` is padded with zeroes. - **/ - @:op(A >>> B) public static #if !cppia inline #end function ushr( a : Int64, b : Int ) : Int64 - return __Int64.ushr(a,b); - - public var high(get, never) : Int32; - private #if !cppia inline #end function get_high() : Int32 - return __Int64.high(this); - - public var low(get, never) : Int32; - private #if !cppia inline #end function get_low() : Int32 - return __Int64.low(this); + @:op(~A) + private static #if !cppia inline #end function complement(a:Int64):Int64 + return __Int64.complement(a); -} + @:op(A & B) + public static #if !cppia inline #end function and(a:Int64, b:Int64):Int64 + return __Int64.bitAnd(a, b); + + @:op(A | B) + public static #if !cppia inline #end function or(a:Int64, b:Int64):Int64 + return __Int64.bitOr(a, b); + + @:op(A ^ B) + public static #if !cppia inline #end function xor(a:Int64, b:Int64):Int64 + return __Int64.bitXor(a, b); + + @:op(A << B) + public static #if !cppia inline #end function shl(a:Int64, b:Int):Int64 + return __Int64.shl(a, b); + @:op(A >> B) + public static #if !cppia inline #end function shr(a:Int64, b:Int):Int64 + return __Int64.shr(a, b); + + @:op(A >>> B) + public static #if !cppia inline #end function ushr(a:Int64, b:Int):Int64 + return __Int64.ushr(a, b); + + public var high(get, never):Int32; + + private #if !cppia inline #end function get_high():Int32 + return __Int64.high(this); + + public var low(get, never):Int32; + + private #if !cppia inline #end function get_low():Int32 + return __Int64.low(this); +} diff --git a/std/cpp/_std/haxe/Log.hx b/std/cpp/_std/haxe/Log.hx index f827f727466..c02376eaf03 100644 --- a/std/cpp/_std/haxe/Log.hx +++ b/std/cpp/_std/haxe/Log.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,31 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; @:coreApi class Log { + @:native("__trace") + extern private static function nativeTrace(message:String, posInfo:Dynamic):Void; - @:extern @:native("__trace") - private static function nativeTrace(message:String, posInfo:Dynamic) : Void { } - - public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { - if (infos!=null && infos.customParams!=null) { + public static dynamic function trace(v:Dynamic, ?infos:PosInfos):Void { + if (infos != null && infos.customParams != null) { var extra:String = ""; - for( v in infos.customParams ) + for (v in infos.customParams) extra += "," + v; - nativeTrace(v + extra,infos); - } - else - nativeTrace(v,infos); + nativeTrace(v + extra, infos); + } else + nativeTrace(v, infos); + } + + public static function formatOutput(v:Dynamic, infos:PosInfos):String { + var str = Std.string(v); + if (infos == null) + return str; + var pstr = infos.fileName + ":" + infos.lineNumber; + if (infos != null && infos.customParams != null) + for (v in infos.customParams) + str += ", " + Std.string(v); + return pstr + ": " + str; } } diff --git a/std/cpp/_std/haxe/Resource.hx b/std/cpp/_std/haxe/Resource.hx index e59d97a7468..6f574b3bd7d 100644 --- a/std/cpp/_std/haxe/Resource.hx +++ b/std/cpp/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; @:coreApi class Resource { - - public static function listNames() : Array { + public static function listNames():Array { return untyped __global__.__hxcpp_resource_names(); } - public static function getString(name:String) : String { + + public static function getString(name:String):String { return untyped __global__.__hxcpp_resource_string(name); } - public static function getBytes(name:String) : haxe.io.Bytes { + + public static function getBytes(name:String):haxe.io.Bytes { var array:haxe.io.BytesData = untyped __global__.__hxcpp_resource_bytes(name); - if (array==null) return null; + if (array == null) + return null; return haxe.io.Bytes.ofData(array); } - } diff --git a/std/cpp/_std/haxe/Utf8.hx b/std/cpp/_std/haxe/Utf8.hx index ff6e0501804..accd2da739c 100644 --- a/std/cpp/_std/haxe/Utf8.hx +++ b/std/cpp/_std/haxe/Utf8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,69 +19,67 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; using cpp.NativeString; @:coreApi -class Utf8 -{ - var __s:Array; - - public function new( ?size : Null ) : Void { - __s = new Array(); - if (size!=null && size>0) - cpp.NativeArray.reserve(__s,size); +@:deprecated('haxe.Utf8 is deprecated. Use UnicodeString instead.') +class Utf8 { + var __s:Array; + + public function new(?size:Null):Void { + __s = new Array(); + if (size != null && size > 0) + cpp.NativeArray.reserve(__s, size); } - public function addChar( c : Int ) : Void { - __s.push(c); + public function addChar(c:Int):Void { + __s.push(c); } - public function toString() : String { + public function toString():String { return untyped __global__.__hxcpp_char_array_to_utf8_string(__s); } - // Incoming string is array of bytes containing possibly invalid utf8 chars - // Result is the same string with the bytes expanded into utf8 sequences - public static function encode( s : String ) : String { + // Incoming string is array of bytes containing possibly invalid utf8 chars + // Result is the same string with the bytes expanded into utf8 sequences + public static function encode(s:String):String { return untyped __global__.__hxcpp_char_bytes_to_utf8_string(s); } - // Incoming string is array of bytes representing valid utf8 chars - // Result is a string containing the compressed bytes - public static function decode( s : String ) : String { + // Incoming string is array of bytes representing valid utf8 chars + // Result is a string containing the compressed bytes + public static function decode(s:String):String { return untyped __global__.__hxcpp_utf8_string_to_char_bytes(s); } - public #if !cppia inline #end static function iter( s : String, chars : Int -> Void ) : Void { - var src = s.c_str(); - var end = src.add( s.length ); + public #if !cppia inline #end static function iter(s:String, chars:Int->Void):Void { + var src = s.c_str(); + var end = src.add(s.length); - while(src.lt(end)) - chars(src.ptr.utf8DecodeAdvance()); + while (src.lt(end)) + chars(src.ptr.utf8DecodeAdvance()); } - public static function charCodeAt( s : String, index : Int ) : Int { - return s.utf8CharCodeAt(index); + public static function charCodeAt(s:String, index:Int):Int { + return s.utf8CharCodeAt(index); } - public static function validate( s : String ) : Bool { - return s.utf8IsValid(); + public static function validate(s:String):Bool { + return s.utf8IsValid(); } - public static function length( s : String ) : Int { - return s.utf8Length(); + public static function length(s:String):Int { + return s.utf8Length(); } - public static function compare( a : String, b : String ) : Int { - return a.compare(b); + public static function compare(a:String, b:String):Int { + return a.compare(b); } - public static function sub( s : String, pos : Int, len : Int ) : String { - return s.utf8Sub(pos,len); + public static function sub(s:String, pos:Int, len:Int):String { + return s.utf8Sub(pos, len); } - } - - diff --git a/std/cpp/_std/haxe/ds/IntMap.hx b/std/cpp/_std/haxe/ds/IntMap.hx index e6ce2acea25..b88735a3b03 100644 --- a/std/cpp/_std/haxe/ds/IntMap.hx +++ b/std/cpp/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; @:headerClassCode(" @@ -50,58 +51,84 @@ package haxe.ds; inline Float get_float(int key) { return __int_hash_get_float(h,key); } inline String get_string(int key) { return __int_hash_get_string(h,key); } ") -@:coreApi class IntMap implements haxe.Constraints.IMap { - +@:coreApi class IntMap implements haxe.Constraints.IMap { @:ifFeature("haxe.ds.IntMap.*") - private var h : Dynamic; + private var h:Dynamic; - public function new() : Void { } + public function new():Void {} - public function set( key : Int, value : T ) : Void { - untyped __global__.__int_hash_set(__cpp__("HX_MAP_THIS"),key,value); + public function set(key:Int, value:T):Void { + untyped __global__.__int_hash_set(__cpp__("HX_MAP_THIS"), key, value); } - public function get( key : Int ) : Null { - return untyped __global__.__int_hash_get(h,key); + public function get(key:Int):Null { + return untyped __global__.__int_hash_get(h, key); } - public function exists( key : Int ) : Bool { - return untyped __global__.__int_hash_exists(h,key); + public function exists(key:Int):Bool { + return untyped __global__.__int_hash_exists(h, key); } - public function remove( key : Int ) : Bool { - return untyped __global__.__int_hash_remove(h,key); + public function remove(key:Int):Bool { + return untyped __global__.__int_hash_remove(h, key); } - public function keys() : Iterator { + public function keys():Iterator { var a:Array = untyped __global__.__int_hash_keys(h); return a.iterator(); } - public function iterator() : Iterator { + public function iterator():Iterator { var a:Array = untyped __global__.__int_hash_values(h); return a.iterator(); } - - public function copy() : IntMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():IntMap { var copied = new IntMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { return untyped __global__.__int_hash_to_string(h); } - #if (scriptable) - private function setString(key:Int,val:String) : Void { untyped __int_hash_set_string(__cpp__("HX_MAP_THIS"),key,val); } - private function setInt(key:Int,val:Int) : Void { untyped __int_hash_set_int(__cpp__("HX_MAP_THIS"),key,val); } - private function setBool(key:Int,val:Bool) : Void { untyped __int_hash_set_int(__cpp__("HX_MAP_THIS"),key,val); } - private function setFloat(key:Int,val:Float) : Void { untyped __int_hash_set_float(__cpp__("HX_MAP_THIS"),key,val); } + #if (scriptable) + private function setString(key:Int, val:String):Void { + untyped __int_hash_set_string(__cpp__("HX_MAP_THIS"), key, val); + } + + private function setInt(key:Int, val:Int):Void { + untyped __int_hash_set_int(__cpp__("HX_MAP_THIS"), key, val); + } + + private function setBool(key:Int, val:Bool):Void { + untyped __int_hash_set_int(__cpp__("HX_MAP_THIS"), key, val); + } - private function getString(key:Int) : String { return untyped __int_hash_get_string(h,key); } - private function getInt(key:Int) : Int { return untyped __int_hash_get_int(h,key); } - private function getBool(key:Int) : Bool { return untyped __int_hash_get_bool(h,key); } - private function getFloat(key:Int) : Float { return untyped __int_hash_get_float(h,key); } - #end + private function setFloat(key:Int, val:Float):Void { + untyped __int_hash_set_float(__cpp__("HX_MAP_THIS"), key, val); + } + + private function getString(key:Int):String { + return untyped __int_hash_get_string(h, key); + } + + private function getInt(key:Int):Int { + return untyped __int_hash_get_int(h, key); + } + + private function getBool(key:Int):Bool { + return untyped __int_hash_get_bool(h, key); + } + + private function getFloat(key:Int):Float { + return untyped __int_hash_get_float(h, key); + } + #end } diff --git a/std/cpp/_std/haxe/ds/ObjectMap.hx b/std/cpp/_std/haxe/ds/ObjectMap.hx index 8745f6b91ab..2711709a2c0 100644 --- a/std/cpp/_std/haxe/ds/ObjectMap.hx +++ b/std/cpp/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; @:headerClassCode(" @@ -50,57 +51,84 @@ package haxe.ds; ") @:coreApi -class ObjectMap implements haxe.Constraints.IMap { +class ObjectMap implements haxe.Constraints.IMap { @:ifFeature("haxe.ds.ObjectMap.*") - private var h : Dynamic; + private var h:Dynamic; - public function new() : Void { } + public function new():Void {} - public function set( key : K, value : V ) : Void { - untyped __global__.__object_hash_set(__cpp__("HX_MAP_THIS"),key,value); + public function set(key:K, value:V):Void { + untyped __global__.__object_hash_set(__cpp__("HX_MAP_THIS"), key, value); } - public function get( key : K ) : Null { - return untyped __global__.__object_hash_get(h,key); + public function get(key:K):Null { + return untyped __global__.__object_hash_get(h, key); } - public function exists( key : K ) : Bool { - return untyped __global__.__object_hash_exists(h,key); + public function exists(key:K):Bool { + return untyped __global__.__object_hash_exists(h, key); } - public function remove( key : K ) : Bool { - return untyped __global__.__object_hash_remove(h,key); + public function remove(key:K):Bool { + return untyped __global__.__object_hash_remove(h, key); } - public function keys() : Iterator { + public function keys():Iterator { var a:Array = untyped __global__.__object_hash_keys(h); return a.iterator(); } - public function iterator() : Iterator { + public function iterator():Iterator { var a:Array = untyped __global__.__object_hash_values(h); return a.iterator(); } - - public function copy() : ObjectMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():ObjectMap { var copied = new ObjectMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { return untyped __global__.__object_hash_to_string(h); } - #if (scriptable) - private function setString(key:Dynamic,val:String) : Void { untyped __object_hash_set_string(__cpp__("HX_MAP_THIS"),key,val); } - private function setInt(key:Dynamic,val:Int) : Void { untyped __object_hash_set_int(__cpp__("HX_MAP_THIS"),key,val); } - private function setBool(key:Dynamic,val:Bool) : Void { untyped __object_hash_set_int(__cpp__("HX_MAP_THIS"),key,val); } - private function setFloat(key:Dynamic,val:Float) : Void { untyped __object_hash_set_float(__cpp__("HX_MAP_THIS"),key,val); } + #if (scriptable) + private function setString(key:Dynamic, val:String):Void { + untyped __object_hash_set_string(__cpp__("HX_MAP_THIS"), key, val); + } + + private function setInt(key:Dynamic, val:Int):Void { + untyped __object_hash_set_int(__cpp__("HX_MAP_THIS"), key, val); + } + + private function setBool(key:Dynamic, val:Bool):Void { + untyped __object_hash_set_int(__cpp__("HX_MAP_THIS"), key, val); + } + + private function setFloat(key:Dynamic, val:Float):Void { + untyped __object_hash_set_float(__cpp__("HX_MAP_THIS"), key, val); + } - private function getString(key:Dynamic) : String { return untyped __object_hash_get_string(h,key); } - private function getInt(key:Dynamic) : Int { return untyped __object_hash_get_int(h,key); } - private function getBool(key:Dynamic) : Bool { return untyped __object_hash_get_bool(h,key); } - private function getFloat(key:Dynamic) : Float { return untyped __object_hash_get_float(h,key); } - #end + private function getString(key:Dynamic):String { + return untyped __object_hash_get_string(h, key); + } + + private function getInt(key:Dynamic):Int { + return untyped __object_hash_get_int(h, key); + } + + private function getBool(key:Dynamic):Bool { + return untyped __object_hash_get_bool(h, key); + } + + private function getFloat(key:Dynamic):Float { + return untyped __object_hash_get_float(h, key); + } + #end } diff --git a/std/cpp/_std/haxe/ds/StringMap.hx b/std/cpp/_std/haxe/ds/StringMap.hx index 4a8fc95eddc..0734108340d 100644 --- a/std/cpp/_std/haxe/ds/StringMap.hx +++ b/std/cpp/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; @:headerClassCode(" @@ -50,57 +51,84 @@ package haxe.ds; inline Float get_float(String key) { return __string_hash_get_float(h,key); } inline String get_string(String key) { return __string_hash_get_string(h,key); } ") -@:coreApi class StringMap implements haxe.Constraints.IMap { +@:coreApi class StringMap implements haxe.Constraints.IMap { @:ifFeature("haxe.ds.StringMap.*") - private var h : Dynamic; + private var h:Dynamic; - public function new() : Void { } + public function new():Void {} - public function set( key : String, value : T ) : Void { - untyped __global__.__string_hash_set(__cpp__("HX_MAP_THIS"),key,value); + public function set(key:String, value:T):Void { + untyped __global__.__string_hash_set(__cpp__("HX_MAP_THIS"), key, value); } - public function get( key : String ) : Null { - return untyped __global__.__string_hash_get(h,key); + public function get(key:String):Null { + return untyped __global__.__string_hash_get(h, key); } - public function exists( key : String ) : Bool { - return untyped __global__.__string_hash_exists(h,key); + public function exists(key:String):Bool { + return untyped __global__.__string_hash_exists(h, key); } - public function remove( key : String ) : Bool { - return untyped __global__.__string_hash_remove(h,key); + public function remove(key:String):Bool { + return untyped __global__.__string_hash_remove(h, key); } - public function keys() : Iterator { + public function keys():Iterator { var a:Array = untyped __global__.__string_hash_keys(h); return a.iterator(); } - public function iterator() : Iterator { + public function iterator():Iterator { var a:Array = untyped __global__.__string_hash_values(h); return a.iterator(); } - - public function copy() : StringMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():StringMap { var copied = new StringMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { return untyped __global__.__string_hash_to_string(h); } - #if (scriptable) - private function setString(key:String,val:String) : Void { untyped __string_hash_set_string(__cpp__("HX_MAP_THIS"),key,val); } - private function setInt(key:String,val:Int) : Void { untyped __string_hash_set_int(__cpp__("HX_MAP_THIS"),key,val); } - private function setBool(key:String,val:Bool) : Void { untyped __string_hash_set_int(__cpp__("HX_MAP_THIS"),key,val); } - private function setFloat(key:String,val:Float) : Void { untyped __string_hash_set_float(__cpp__("HX_MAP_THIS"),key,val); } + #if (scriptable) + private function setString(key:String, val:String):Void { + untyped __string_hash_set_string(__cpp__("HX_MAP_THIS"), key, val); + } + + private function setInt(key:String, val:Int):Void { + untyped __string_hash_set_int(__cpp__("HX_MAP_THIS"), key, val); + } + + private function setBool(key:String, val:Bool):Void { + untyped __string_hash_set_int(__cpp__("HX_MAP_THIS"), key, val); + } + + private function setFloat(key:String, val:Float):Void { + untyped __string_hash_set_float(__cpp__("HX_MAP_THIS"), key, val); + } - private function getString(key:String) : String { return untyped __string_hash_get_string(h,key); } - private function getInt(key:String) : Int { return untyped __string_hash_get_int(h,key); } - private function getBool(key:String) : Bool { return untyped __string_hash_get_bool(h,key); } - private function getFloat(key:String) : Float { return untyped __string_hash_get_float(h,key); } - #end + private function getString(key:String):String { + return untyped __string_hash_get_string(h, key); + } + + private function getInt(key:String):Int { + return untyped __string_hash_get_int(h, key); + } + + private function getBool(key:String):Bool { + return untyped __string_hash_get_bool(h, key); + } + + private function getFloat(key:String):Float { + return untyped __string_hash_get_float(h, key); + } + #end } diff --git a/std/cpp/_std/haxe/ds/WeakMap.hx b/std/cpp/_std/haxe/ds/WeakMap.hx index 86ffe2527da..41d8259d09c 100644 --- a/std/cpp/_std/haxe/ds/WeakMap.hx +++ b/std/cpp/_std/haxe/ds/WeakMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; @:headerClassCode(" @@ -43,46 +44,50 @@ package haxe.ds; inline void set(Dynamic key, const ::cpp::Function &value) {__object_hash_set(HX_MAP_THIS,key,(Dynamic)value,true ); } ") @:coreApi -class WeakMap implements haxe.Constraints.IMap { +class WeakMap implements haxe.Constraints.IMap { @:ifFeature("haxe.ds.WeakMap.*") - private var h : Dynamic; + private var h:Dynamic; - public function new() : Void { } + public function new():Void {} - public function set( key : K, value : V ) : Void { - untyped __global__.__object_hash_set(__cpp__("HX_MAP_THIS"),key,value,true); + public function set(key:K, value:V):Void { + untyped __global__.__object_hash_set(__cpp__("HX_MAP_THIS"), key, value, true); } - public function get( key : K ) : Null { - return untyped __global__.__object_hash_get(h,key); + public function get(key:K):Null { + return untyped __global__.__object_hash_get(h, key); } - public function exists( key : K ) : Bool { - return untyped __global__.__object_hash_exists(h,key); + public function exists(key:K):Bool { + return untyped __global__.__object_hash_exists(h, key); } - public function remove( key : K ) : Bool { - return untyped __global__.__object_hash_remove(h,key); + public function remove(key:K):Bool { + return untyped __global__.__object_hash_remove(h, key); } - public function keys() : Iterator { + public function keys():Iterator { var a:Array = untyped __global__.__object_hash_keys(h); return a.iterator(); } - public function iterator() : Iterator { + public function iterator():Iterator { var a:Array = untyped __global__.__object_hash_values(h); return a.iterator(); } - - public function copy() : WeakMap { + + public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():WeakMap { var copied = new WeakMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - - public function toString() : String { + public function toString():String { return untyped __global__.__object_hash_to_string(h); } } diff --git a/std/cpp/_std/haxe/zip/Compress.hx b/std/cpp/_std/haxe/zip/Compress.hx index afa69eb3c3f..4d7ef850d11 100644 --- a/std/cpp/_std/haxe/zip/Compress.hx +++ b/std/cpp/_std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,53 +19,53 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; @:coreApi @:buildXml('') class Compress { + var s:Dynamic; - var s : Dynamic; - - public function new( level : Int ) : Void { + public function new(level:Int):Void { s = _deflate_init(level); } - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { - return _deflate_buffer(s,src.getData(),srcPos,dst.getData(),dstPos); + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { + return _deflate_buffer(s, src.getData(), srcPos, dst.getData(), dstPos); } - public function setFlushMode( f : FlushMode ) : Void { - _set_flush_mode(s,Std.string(f)); + public function setFlushMode(f:FlushMode):Void { + _set_flush_mode(s, Std.string(f)); } - public function close() : Void { + public function close():Void { _deflate_end(s); } - public static function run( s : haxe.io.Bytes, level : Int ) : haxe.io.Bytes { + public static function run(s:haxe.io.Bytes, level:Int):haxe.io.Bytes { var c = new Compress(level); c.setFlushMode(FlushMode.FINISH); - var out = haxe.io.Bytes.alloc(_deflate_bound(c.s,s.length)); - var r = c.execute(s,0,out,0); + var out = haxe.io.Bytes.alloc(_deflate_bound(c.s, s.length)); + var r = c.execute(s, 0, out, 0); c.close(); - if( !r.done || r.read != s.length ) + if (!r.done || r.read != s.length) throw "Compression failed"; - return out.sub(0,r.write); + return out.sub(0, r.write); } - @:extern @:native("_hx_deflate_init") - static function _deflate_init(level:Int) : Dynamic return null; - - @:extern @:native("_hx_deflate_bound") - static function _deflate_bound(handle:Dynamic,length:Int):Int return 0; + @:native("_hx_deflate_init") + extern static function _deflate_init(level:Int):Dynamic; - @:extern @:native("_hx_deflate_buffer") - static function _deflate_buffer(handle:Dynamic, src:haxe.io.BytesData, srcPos:Int, dest:haxe.io.BytesData, destPos:Int) : { done : Bool, read : Int, write : Int } return null; + @:native("_hx_deflate_bound") + extern static function _deflate_bound(handle:Dynamic, length:Int):Int; - @:extern @:native("_hx_deflate_end") - static function _deflate_end(handle:Dynamic) : Void { } + @:native("_hx_deflate_buffer") + extern static function _deflate_buffer(handle:Dynamic, src:haxe.io.BytesData, srcPos:Int, dest:haxe.io.BytesData, + destPos:Int):{done:Bool, read:Int, write:Int}; - @:extern @:native("_hx_zip_set_flush_mode") - static function _set_flush_mode(handle:Dynamic, flushMode:String):Void { } + @:native("_hx_deflate_end") + extern static function _deflate_end(handle:Dynamic):Void; + @:native("_hx_zip_set_flush_mode") + extern static function _set_flush_mode(handle:Dynamic, flushMode:String):Void; } diff --git a/std/cpp/_std/haxe/zip/Uncompress.hx b/std/cpp/_std/haxe/zip/Uncompress.hx index 8a6244f3888..1168ba32c94 100644 --- a/std/cpp/_std/haxe/zip/Uncompress.hx +++ b/std/cpp/_std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,56 +19,58 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; @:coreApi @:buildXml('') class Uncompress { - var s : Dynamic; + var s:Dynamic; - public function new( ?windowBits : Int ) : Void { + public function new(?windowBits:Int):Void { s = _inflate_init(windowBits); } - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { - return _inflate_buffer(s,src.getData(),srcPos,dst.getData(),dstPos); + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { + return _inflate_buffer(s, src.getData(), srcPos, dst.getData(), dstPos); } - public function setFlushMode( f : FlushMode ) : Void { - _set_flush_mode(s,untyped f.__Tag()); + public function setFlushMode(f:FlushMode):Void { + _set_flush_mode(s, untyped f.__Tag()); } - public function close() : Void { + public function close():Void { _inflate_end(s); } - public static function run( src : haxe.io.Bytes, ?bufsize : Int ) : haxe.io.Bytes { + public static function run(src:haxe.io.Bytes, ?bufsize:Int):haxe.io.Bytes { var u = new Uncompress(null); - if( bufsize == null ) bufsize = 1 << 16; // 64K + if (bufsize == null) + bufsize = 1 << 16; // 64K var tmp = haxe.io.Bytes.alloc(bufsize); var b = new haxe.io.BytesBuffer(); var pos = 0; u.setFlushMode(FlushMode.SYNC); - while( true ) { - var r = u.execute(src,pos,tmp,0); - b.addBytes(tmp,0,r.write); + while (true) { + var r = u.execute(src, pos, tmp, 0); + b.addBytes(tmp, 0, r.write); pos += r.read; - if( r.done ) + if (r.done) break; } u.close(); return b.getBytes(); } - @:extern @:native("_hx_inflate_init") - static function _inflate_init(windowBits:Dynamic) : Dynamic return null; - - @:extern @:native("_hx_inflate_buffer") - static function _inflate_buffer(handle:Dynamic, src:haxe.io.BytesData, srcPos:Int, dest:haxe.io.BytesData, destPos:Int) : { done : Bool, read : Int, write : Int } return null; + @:native("_hx_inflate_init") + extern static function _inflate_init(windowBits:Dynamic):Dynamic; - @:extern @:native("_hx_inflate_end") - static function _inflate_end(handle:Dynamic):Void { } + @:native("_hx_inflate_buffer") + extern static function _inflate_buffer(handle:Dynamic, src:haxe.io.BytesData, srcPos:Int, dest:haxe.io.BytesData, + destPos:Int):{done:Bool, read:Int, write:Int}; - @:extern @:native("_hx_zip_set_flush_mode") - static function _set_flush_mode(handle:Dynamic, flushMode:String):Void { } + @:native("_hx_inflate_end") + extern static function _inflate_end(handle:Dynamic):Void; + @:native("_hx_zip_set_flush_mode") + extern static function _set_flush_mode(handle:Dynamic, flushMode:String):Void; } diff --git a/std/cpp/_std/sys/FileSystem.hx b/std/cpp/_std/sys/FileSystem.hx index 959b42e8536..df101833e8b 100644 --- a/std/cpp/_std/sys/FileSystem.hx +++ b/std/cpp/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys; import cpp.NativeSys; @@ -26,43 +27,55 @@ import cpp.NativeSys; @:buildXml('') @:coreApi class FileSystem { - - public static function exists( path : String ) : Bool { + public static function exists(path:String):Bool { return NativeSys.sys_exists(makeCompatiblePath(path)); } - public static function rename( path : String, newPath : String ) : Void { - NativeSys.sys_rename(path,newPath); + public static function rename(path:String, newPath:String):Void { + NativeSys.sys_rename(path, newPath); } - public static function stat( path : String ) : FileStat { - var s : FileStat = NativeSys.sys_stat(makeCompatiblePath(path)); - if (s==null) - return { gid:0, uid:0, atime:Date.fromTime(0), mtime:Date.fromTime(0), ctime:Date.fromTime(0), dev:0, ino:0, nlink:0, rdev:0, size:0, mode:0 }; - s.atime = Date.fromTime(1000.0*(untyped s.atime)); - s.mtime = Date.fromTime(1000.0*(untyped s.mtime)); - s.ctime = Date.fromTime(1000.0*(untyped s.ctime)); + public static function stat(path:String):FileStat { + var s:FileStat = NativeSys.sys_stat(makeCompatiblePath(path)); + if (s == null) + return { + gid: 0, + uid: 0, + atime: Date.fromTime(0), + mtime: Date.fromTime(0), + ctime: Date.fromTime(0), + dev: 0, + ino: 0, + nlink: 0, + rdev: 0, + size: 0, + mode: 0 + }; + s.atime = Date.fromTime(1000.0 * (untyped s.atime)); + s.mtime = Date.fromTime(1000.0 * (untyped s.mtime)); + s.ctime = Date.fromTime(1000.0 * (untyped s.ctime)); return s; } - public static function fullPath( relPath : String ) : String { + public static function fullPath(relPath:String):String { return NativeSys.file_full_path(relPath); } - public static function absolutePath ( relPath : String ) : String { - if (haxe.io.Path.isAbsolute(relPath)) return relPath; + public static function absolutePath(relPath:String):String { + if (haxe.io.Path.isAbsolute(relPath)) + return relPath; return haxe.io.Path.join([Sys.getCwd(), relPath]); } - inline static function kind( path : String ) : String { - return NativeSys.sys_file_type(makeCompatiblePath(path)); + inline static function kind(path:String):String { + return NativeSys.sys_file_type(makeCompatiblePath(path)); } - public static function isDirectory( path : String ) : Bool { + public static function isDirectory(path:String):Bool { return kind(path) == "dir"; } - public static function createDirectory( path : String ) : Void { + public static function createDirectory(path:String):Void { var path = haxe.io.Path.addTrailingSlash(path); var _p = null; var parts = []; @@ -71,26 +84,28 @@ class FileSystem { path = _p; } for (part in parts) { - if (part.charCodeAt(part.length - 1) != ":".code && !exists(part) && !NativeSys.sys_create_dir( part, 493 )) + if (part.charCodeAt(part.length - 1) != ":".code && !exists(part) && !NativeSys.sys_create_dir(part, 493)) throw "Could not create directory:" + part; } } - public static function deleteFile( path : String ) : Void { + public static function deleteFile(path:String):Void { NativeSys.file_delete(path); } - public static function deleteDirectory( path : String ) : Void { + public static function deleteDirectory(path:String):Void { NativeSys.sys_remove_dir(path); } - public static function readDirectory( path : String ) : Array { + public static function readDirectory(path:String):Array { return NativeSys.sys_read_dir(path); } private static inline function makeCompatiblePath(path:String):String { return if (path.charCodeAt(1) == ":".code && path.length <= 3) { haxe.io.Path.addTrailingSlash(path); + } else if (path == "/") { + "/"; } else { haxe.io.Path.removeTrailingSlashes(path); } diff --git a/std/cpp/_std/sys/db/Mysql.hx b/std/cpp/_std/sys/db/Mysql.hx index 2af48d589d7..9ecdbecb90a 100644 --- a/std/cpp/_std/sys/db/Mysql.hx +++ b/std/cpp/_std/sys/db/Mysql.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,55 +19,63 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.db; @:keep private class D { + @:native("_hx_mysql_connect") + extern public static function connect(params:Dynamic):Dynamic; + + @:native("_hx_mysql_select_db") + extern public static function select_db(handle:Dynamic, db:String):Void; + + @:native("_hx_mysql_request") + extern public static function request(handle:Dynamic, req:String):Dynamic; + + @:native("_hx_mysql_close") + extern public static function close(handle:Dynamic):Dynamic; + + @:native("_hx_mysql_escape") + extern public static function escape(handle:Dynamic, str:String):String; + + @:native("_hx_mysql_result_get_length") + extern public static function result_get_length(handle:Dynamic):Int; + + @:native("_hx_mysql_result_get_nfields") + extern public static function result_get_nfields(handle:Dynamic):Int; + + @:native("_hx_mysql_result_next") + extern public static function result_next(handle:Dynamic):Dynamic; + + @:native("_hx_mysql_result_get") + extern public static function result_get(handle:Dynamic, i:Int):String; - @:extern @:native("_hx_mysql_connect") - public static function connect(params:Dynamic):Dynamic return null; - @:extern @:native("_hx_mysql_select_db") - public static function select_db(handle:Dynamic, db:String):Void { } - @:extern @:native("_hx_mysql_request") - public static function request(handle:Dynamic,req:String):Dynamic return null; - @:extern @:native("_hx_mysql_close") - public static function close(handle:Dynamic):Dynamic return null; - @:extern @:native("_hx_mysql_escape") - public static function escape(handle:Dynamic,str:String):String return null; - @:extern @:native("_hx_mysql_result_get_length") - public static function result_get_length(handle:Dynamic):Int return 0; - @:extern @:native("_hx_mysql_result_get_nfields") - public static function result_get_nfields(handle:Dynamic):Int return 0; - @:extern @:native("_hx_mysql_result_next") - public static function result_next(handle:Dynamic):Dynamic return null; - @:extern @:native("_hx_mysql_result_get") - public static function result_get(handle:Dynamic,i:Int) : String return null; - @:extern @:native("_hx_mysql_result_get_int") - public static function result_get_int(handle:Dynamic,i:Int) : Int return 0; - @:extern @:native("_hx_mysql_result_get_float") - public static function result_get_float(handle:Dynamic,i:Int):Float return 0.0; - @:extern @:native("_hx_mysql_result_get_fields_names") - public static function result_fields_names(handle:Dynamic):Array return null; - - @:extern @:native("_hx_mysql_set_conversion") - public static function set_conv_funs( - charsToBytes: cpp.Callable< Dynamic -> Dynamic >, - intToDate: cpp.Callable< Float -> Dynamic > ) : Void {} - - public static function charsToBytes(data:Dynamic) : Dynamic - return haxe.io.Bytes.ofData(data); - - public static function secondsToDate(seconds:Float) : Dynamic - return Date.fromTime(seconds * 1000); + @:native("_hx_mysql_result_get_int") + extern public static function result_get_int(handle:Dynamic, i:Int):Int; + @:native("_hx_mysql_result_get_float") + extern public static function result_get_float(handle:Dynamic, i:Int):Float; + + @:native("_hx_mysql_result_get_fields_names") + extern public static function result_fields_names(handle:Dynamic):Array; + + @:native("_hx_mysql_set_conversion") + extern public static function set_conv_funs(charsToBytes:cpp.CallableDynamic>, intToDate:cpp.CallableDynamic>):Void; + + public static function charsToBytes(data:Dynamic):Dynamic + return haxe.io.Bytes.ofData(data); + + public static function secondsToDate(seconds:Float):Dynamic + return Date.fromTime(seconds * 1000); } private class MysqlResultSet implements sys.db.ResultSet { + public var length(get, null):Int; + public var nfields(get, null):Int; - public var length(get,null) : Int; - public var nfields(get,null) : Int; - private var __r : Dynamic; - private var cache : Dynamic; + private var __r:Dynamic; + private var cache:Dynamic; public function new(r:Dynamic) { __r = r; @@ -82,14 +90,14 @@ private class MysqlResultSet implements sys.db.ResultSet { } public function hasNext() { - if( cache == null ) + if (cache == null) cache = next(); return (cache != null); } - public function next() : Dynamic { + public function next():Dynamic { var c = cache; - if( c != null ) { + if (c != null) { cache = null; return c; } @@ -97,72 +105,67 @@ private class MysqlResultSet implements sys.db.ResultSet { return c; } - public function results() : List { + public function results():List { var l = new List(); - while( hasNext() ) + while (hasNext()) l.add(next()); return l; } - public function getResult( n : Int ) { - return D.result_get(__r,n); + public function getResult(n:Int) { + return D.result_get(__r, n); } - public function getIntResult( n : Int ) : Int { - return D.result_get_int(__r,n); + public function getIntResult(n:Int):Int { + return D.result_get_int(__r, n); } - public function getFloatResult( n : Int ) : Float { - return D.result_get_float(__r,n); + public function getFloatResult(n:Int):Float { + return D.result_get_float(__r, n); } - public function getFieldsNames() : Array { + public function getFieldsNames():Array { var a = D.result_fields_names(__r); return a; } - } private class MysqlConnection implements sys.db.Connection { - - private var __c : Dynamic; + private var __c:Dynamic; public function new(c:Dynamic) { __c = c; - D.set_conv_funs( cpp.Function.fromStaticFunction(D.charsToBytes), - cpp.Function.fromStaticFunction(D.secondsToDate) ); - + D.set_conv_funs(cpp.Function.fromStaticFunction(D.charsToBytes), cpp.Function.fromStaticFunction(D.secondsToDate)); } - public function request( s : String ) : sys.db.ResultSet { - var r = D.request(this.__c, s); - return new MysqlResultSet(r); + public function request(s:String):sys.db.ResultSet { + var r = D.request(this.__c, s); + return new MysqlResultSet(r); } public function close() { D.close(__c); } - public function escape( s : String ) { - return D.escape(__c,s); + public function escape(s:String) { + return D.escape(__c, s); } - public function quote( s : String ) { - return "'"+escape(s)+"'"; + public function quote(s:String) { + return "'" + escape(s) + "'"; } - public function addValue( s : StringBuf, v : Dynamic ) { + public function addValue(s:StringBuf, v:Dynamic) { if (v == null) { s.add(v); - } - else if (Std.is(v,Bool)) { - s.add( v ? 1 : 0 ); - } else { + } else if (Std.is(v, Bool)) { + s.add(v ? 1 : 0); + } else { var t:Int = untyped v.__GetType(); - if( t == 0xff ) + if (t == 0xff) s.add(v); - else if( t == 2 ) - s.add( untyped v.__GetInt() ? "1".code : "0".code ); + else if (t == 2) + s.add(untyped v.__GetInt() ? "1".code : "0".code); else { s.addChar("'".code); s.add(escape(Std.string(v))); @@ -196,32 +199,30 @@ private class MysqlConnection implements sys.db.Connection { @:buildXml('') @:coreApi class Mysql { - - public static function connect( params : { - host : String, - ?port : Int, - user : String, - pass : String, - ?socket : String, - ?database : String - } ) : sys.db.Connection { + public static function connect(params:{ + host:String, + ?port:Int, + user:String, + pass:String, + ?socket:String, + ?database:String + }):sys.db.Connection { var o = { - host : params.host, - port : if( params.port == null ) 3306 else params.port, - user : params.user, - pass : params.pass, - socket : if( params.socket == null ) null else params.socket + host: params.host, + port: if (params.port == null) 3306 else params.port, + user: params.user, + pass: params.pass, + socket: if (params.socket == null) null else params.socket }; var c = D.connect(o); if (params.database != null) { try { - D.select_db(c,params.database); - } catch( e : Dynamic ) { + D.select_db(c, params.database); + } catch (e:Dynamic) { D.close(c); cpp.Lib.rethrow(e); } } return new MysqlConnection(c); } - } diff --git a/std/cpp/_std/sys/db/Sqlite.hx b/std/cpp/_std/sys/db/Sqlite.hx index f84d61047fe..d8f3b275680 100644 --- a/std/cpp/_std/sys/db/Sqlite.hx +++ b/std/cpp/_std/sys/db/Sqlite.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.db; private class SqliteConnection implements Connection { + var c:Dynamic; - var c : Dynamic; - - public function new( file : String ) { + public function new(file:String) { c = _connect(file); } @@ -33,47 +33,45 @@ private class SqliteConnection implements Connection { _close(c); } - public function request( s : String ) : ResultSet { + public function request(s:String):ResultSet { try { - return new SqliteResultSet(_request(c,s)); - } catch( e : String ) { - throw "Error while executing "+s+" ("+e+")"; + return new SqliteResultSet(_request(c, s)); + } catch (e:String) { + throw "Error while executing " + s + " (" + e + ")"; } } - public function escape( s : String ) { + public function escape(s:String) { return s.split("'").join("''"); } - public function quote( s : String ) { - if( s.indexOf("\000") >= 0 ) - { - var hexChars = new Array(); - for(i in 0...s.length) - hexChars.push( StringTools.hex( StringTools.fastCodeAt(s,i),2 ) ); - return "x'"+ hexChars.join("") +"'"; - } - return "'"+s.split("'").join("''")+"'"; + public function quote(s:String) { + if (s.indexOf("\000") >= 0) { + var hexChars = new Array(); + for (i in 0...s.length) + hexChars.push(StringTools.hex(StringTools.fastCodeAt(s, i), 2)); + return "x'" + hexChars.join("") + "'"; + } + return "'" + s.split("'").join("''") + "'"; } - public function addValue( s : StringBuf, v : Dynamic ) { + public function addValue(s:StringBuf, v:Dynamic) { if (v == null) { s.add(v); - } - else if (Std.is(v,Bool)) { - s.add( v ? 1 : 0 ); - } else { + } else if (Std.is(v, Bool)) { + s.add(v ? 1 : 0); + } else { var t:Int = untyped v.__GetType(); - if( t == 0xff ) + if (t == 0xff) s.add(v); - else if( t == 2 ) - s.add( untyped v.__GetInt() ); + else if (t == 2) + s.add(untyped v.__GetInt()); else s.add(quote(Std.string(v))); } } - public function lastInsertId() : Int{ + public function lastInsertId():Int { return _last_id(c); } @@ -95,37 +93,37 @@ private class SqliteConnection implements Connection { startTransaction(); // match mysql usage } + @:native("_hx_sqlite_connect") + extern public static function _connect(filename:String):Dynamic; - @:extern @:native("_hx_sqlite_connect") - public static function _connect(filename:String):Dynamic return null; - @:extern @:native("_hx_sqlite_request") - public static function _request(handle:Dynamic,req:String):Dynamic return null; - @:extern @:native("_hx_sqlite_close") - public static function _close(handle:Dynamic):Void { }; - @:extern @:native("_hx_sqlite_last_insert_id") - public static function _last_id(handle:Dynamic):Int return 0; + @:native("_hx_sqlite_request") + extern public static function _request(handle:Dynamic, req:String):Dynamic; -} + @:native("_hx_sqlite_close") + extern public static function _close(handle:Dynamic):Void; + @:native("_hx_sqlite_last_insert_id") + extern public static function _last_id(handle:Dynamic):Int; +} private class SqliteResultSet implements ResultSet { + public var length(get, null):Int; + public var nfields(get, null):Int; - public var length(get,null) : Int; - public var nfields(get,null) : Int; - var r : Dynamic; - var cache : List; + var r:Dynamic; + var cache:List; - public function new( r:Dynamic ) { + public function new(r:Dynamic) { cache = new List(); this.r = r; hasNext(); // execute the request } function get_length() { - if( nfields != 0 ) { - while( true ) { + if (nfields != 0) { + while (true) { var c = result_next(r); - if( c == null ) + if (c == null) break; cache.add(c); } @@ -140,68 +138,68 @@ private class SqliteResultSet implements ResultSet { public function hasNext() { var c = next(); - if( c == null ) + if (c == null) return false; cache.push(c); return true; } - public function next() : Dynamic { + public function next():Dynamic { var c = cache.pop(); - if( c != null ) + if (c != null) return c; return result_next(r); } - public function results() : List { + public function results():List { var l = new List(); - while( true ) { + while (true) { var c = next(); - if( c == null ) + if (c == null) break; l.add(c); } return l; } - public function getResult( n : Int ) { - return new String(result_get(r,n)); + public function getResult(n:Int) { + return new String(result_get(r, n)); } - public function getIntResult( n : Int ) : Int { - return result_get_int(r,n); + public function getIntResult(n:Int):Int { + return result_get_int(r, n); } - public function getFloatResult( n : Int ) : Float { - return result_get_float(r,n); + public function getFloatResult(n:Int):Float { + return result_get_float(r, n); } - public function getFieldsNames() : Array { + public function getFieldsNames():Array { return null; } + @:native("_hx_sqlite_result_next") + extern public static function result_next(handle:Dynamic):Dynamic; + @:native("_hx_sqlite_result_get_length") + extern public static function result_get_length(handle:Dynamic):Int; - @:extern @:native("_hx_sqlite_result_next") - public static function result_next(handle:Dynamic):Dynamic return null; - @:extern @:native("_hx_sqlite_result_get_length") - public static function result_get_length(handle:Dynamic):Int return 0; - @:extern @:native("_hx_sqlite_result_get_nfields") - public static function result_get_nfields(handle:Dynamic):Int return 0; - @:extern @:native("_hx_sqlite_result_get") - public static function result_get(handle:Dynamic,i:Int) : String return null; - @:extern @:native("_hx_sqlite_result_get_int") - public static function result_get_int(handle:Dynamic,i:Int) : Int return 0; - @:extern @:native("_hx_sqlite_result_get_float") - public static function result_get_float(handle:Dynamic,i:Int):Float return 0.0; + @:native("_hx_sqlite_result_get_nfields") + extern public static function result_get_nfields(handle:Dynamic):Int; + @:native("_hx_sqlite_result_get") + extern public static function result_get(handle:Dynamic, i:Int):String; + + @:native("_hx_sqlite_result_get_int") + extern public static function result_get_int(handle:Dynamic, i:Int):Int; + + @:native("_hx_sqlite_result_get_float") + extern public static function result_get_float(handle:Dynamic, i:Int):Float; } @:buildXml('') @:coreApi class Sqlite { - - public static function open( file : String ) : Connection { + public static function open(file:String):Connection { return new SqliteConnection(file); } - } diff --git a/std/cpp/_std/sys/io/File.hx b/std/cpp/_std/sys/io/File.hx index d193f9eef25..78fdebd596f 100644 --- a/std/cpp/_std/sys/io/File.hx +++ b/std/cpp/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,52 +19,58 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; import cpp.NativeFile; @:coreApi class File { - - public static function getContent( path : String ) : String { + public static function getContent(path:String):String { return NativeFile.file_contents_string(path); } - public static function getBytes( path : String ) : haxe.io.Bytes { + public static function getBytes(path:String):haxe.io.Bytes { var data = NativeFile.file_contents_bytes(path); return haxe.io.Bytes.ofData(data); } - public static function saveContent( path : String, content : String ) : Void { + public static function saveContent(path:String, content:String):Void { var f = write(path); f.writeString(content); f.close(); } - public static function saveBytes( path : String, bytes : haxe.io.Bytes ) : Void { + public static function saveBytes(path:String, bytes:haxe.io.Bytes):Void { var f = write(path); f.write(bytes); f.close(); } - public static function read( path : String, binary : Bool = true ) : FileInput { - return untyped new FileInput(NativeFile.file_open(path,(if( binary ) "rb" else "r"))); + public static function read(path:String, binary:Bool = true):FileInput { + return untyped new FileInput(NativeFile.file_open(path, (if (binary) "rb" else "r"))); } - public static function write( path : String, binary : Bool = true ) : FileOutput { - return untyped new FileOutput(NativeFile.file_open(path,(if( binary ) "wb" else "w"))); + public static function write(path:String, binary:Bool = true):FileOutput { + return untyped new FileOutput(NativeFile.file_open(path, (if (binary) "wb" else "w"))); } - public static function append( path : String, binary : Bool = true ) : FileOutput { - return untyped new FileOutput(NativeFile.file_open(path,(if( binary ) "ab" else "a"))); + public static function append(path:String, binary:Bool = true):FileOutput { + return untyped new FileOutput(NativeFile.file_open(path, (if (binary) "ab" else "a"))); } - public static function copy( srcPath : String, dstPath : String ) : Void { - var s = read(srcPath,true); - var d = write(dstPath,true); + public static function update(path:String, binary:Bool = true):FileOutput { + if (!FileSystem.exists(path)) { + write(path).close(); + } + return untyped new FileOutput(NativeFile.file_open(path, (if (binary) "rb+" else "r+"))); + } + + public static function copy(srcPath:String, dstPath:String):Void { + var s = read(srcPath, true); + var d = write(dstPath, true); d.writeInput(s); s.close(); d.close(); } - } diff --git a/std/cpp/_std/sys/io/FileInput.hx b/std/cpp/_std/sys/io/FileInput.hx index 086641580e9..df8aa1d7c4e 100644 --- a/std/cpp/_std/sys/io/FileInput.hx +++ b/std/cpp/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,57 +19,56 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; + import sys.io.FileSeek; import cpp.NativeFile; @:coreApi class FileInput extends haxe.io.Input { + private var __f:Dynamic; - private var __f : Dynamic; - - function new(f:Dynamic) : Void { + function new(f:Dynamic):Void { __f = f; } - public override function readByte() : Int { + public override function readByte():Int { return try { NativeFile.file_read_char(__f); - } catch( e : Dynamic ) { - if( untyped e.__IsArray() ) + } catch (e:Dynamic) { + if (untyped e.__IsArray()) throw new haxe.io.Eof(); else throw haxe.io.Error.Custom(e); } } - public override function readBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int { + public override function readBytes(s:haxe.io.Bytes, p:Int, l:Int):Int { return try { - NativeFile.file_read(__f,s.getData(),p,l); - } catch( e : Dynamic ) { - if( untyped e.__IsArray() ) + NativeFile.file_read(__f, s.getData(), p, l); + } catch (e:Dynamic) { + if (untyped e.__IsArray()) throw new haxe.io.Eof(); else throw haxe.io.Error.Custom(e); } } - public override function close() : Void { + public override function close():Void { super.close(); NativeFile.file_close(__f); } - public function seek( p : Int, pos : FileSeek ) : Void { - NativeFile.file_seek(__f,p,pos==SeekBegin ? 0 : pos==SeekCur ? 1 : 2 ); + public function seek(p:Int, pos:FileSeek):Void { + NativeFile.file_seek(__f, p, pos == SeekBegin ? 0 : pos == SeekCur ? 1 : 2); } - public function tell() : Int { + public function tell():Int { return NativeFile.file_tell(__f); } - - public function eof() : Bool { + public function eof():Bool { return NativeFile.file_eof(__f); } - } diff --git a/std/cpp/_std/sys/io/FileOutput.hx b/std/cpp/_std/sys/io/FileOutput.hx index e7ba92bccb0..19ea8761454 100644 --- a/std/cpp/_std/sys/io/FileOutput.hx +++ b/std/cpp/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,42 +19,45 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; + import sys.io.FileSeek; import cpp.NativeFile; @:coreApi class FileOutput extends haxe.io.Output { + private var __f:Dynamic; - private var __f : Dynamic; - - function new(f:Dynamic) : Void { + function new(f:Dynamic):Void { __f = f; } - public override function writeByte( c : Int ) : Void { - try NativeFile.file_write_char(__f,c) catch( e : Dynamic ) throw haxe.io.Error.Custom(e); + public override function writeByte(c:Int):Void { + try + NativeFile.file_write_char(__f, c) + catch (e:Dynamic) + throw haxe.io.Error.Custom(e); } - public override function writeBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int { - return try NativeFile.file_write(__f,s.getData(),p,l) catch( e : Dynamic ) throw haxe.io.Error.Custom(e); + public override function writeBytes(s:haxe.io.Bytes, p:Int, l:Int):Int { + return try NativeFile.file_write(__f, s.getData(), p, l) catch (e:Dynamic) throw haxe.io.Error.Custom(e); } - public override function flush() : Void { + public override function flush():Void { NativeFile.file_flush(__f); } - public override function close() : Void { + public override function close():Void { super.close(); NativeFile.file_close(__f); } - public function seek( p : Int, pos : FileSeek ) : Void { - NativeFile.file_seek(__f,p, pos == SeekBegin ? 0 : pos == SeekCur ? 1 : 2); + public function seek(p:Int, pos:FileSeek):Void { + NativeFile.file_seek(__f, p, pos == SeekBegin ? 0 : pos == SeekCur ? 1 : 2); } - public function tell() : Int { + public function tell():Int { return NativeFile.file_tell(__f); } - } diff --git a/std/cpp/_std/sys/io/Process.hx b/std/cpp/_std/sys/io/Process.hx index 7bdb4cb3100..59726154ba7 100644 --- a/std/cpp/_std/sys/io/Process.hx +++ b/std/cpp/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; import cpp.NativeProcess; private class Stdin extends haxe.io.Output { - - var p : Dynamic; - var buf : haxe.io.Bytes; + var p:Dynamic; + var buf:haxe.io.Bytes; public function new(p:Dynamic) { this.p = p; @@ -39,83 +39,82 @@ private class Stdin extends haxe.io.Output { } public override function writeByte(c) { - buf.set(0,c); - writeBytes(buf,0,1); + buf.set(0, c); + writeBytes(buf, 0, 1); } - public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { + public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { try { - return NativeProcess.process_stdin_write(p,buf.getData(),pos,len); - } catch( e : Dynamic ) { + return NativeProcess.process_stdin_write(p, buf.getData(), pos, len); + } catch (e:Dynamic) { throw new haxe.io.Eof(); } return 0; } - } private class Stdout extends haxe.io.Input { + var p:Dynamic; + var out:Bool; + var buf:haxe.io.Bytes; - var p : Dynamic; - var out : Bool; - var buf : haxe.io.Bytes; - - public function new(p:Dynamic,out) { + public function new(p:Dynamic, out) { this.p = p; this.out = out; buf = haxe.io.Bytes.alloc(1); } public override function readByte() { - if( readBytes(buf,0,1) == 0 ) + if (readBytes(buf, 0, 1) == 0) throw haxe.io.Error.Blocked; return buf.get(0); } - public override function readBytes( str : haxe.io.Bytes, pos : Int, len : Int ) : Int { + public override function readBytes(str:haxe.io.Bytes, pos:Int, len:Int):Int { var result:Int; try { - result = out? NativeProcess.process_stdout_read(p,str.getData(),pos,len) : - NativeProcess.process_stderr_read(p,str.getData(),pos,len); - } catch( e : Dynamic ) { + result = out ? NativeProcess.process_stdout_read(p, str.getData(), pos, len) : NativeProcess.process_stderr_read(p, str.getData(), pos, len); + } catch (e:Dynamic) { throw new haxe.io.Eof(); } - if (result==0)throw new haxe.io.Eof(); + if (result == 0) + throw new haxe.io.Eof(); return result; } } @:coreApi class Process { + var p:Dynamic; - var p : Dynamic; - public var stdout(default,null) : haxe.io.Input; - public var stderr(default,null) : haxe.io.Input; - public var stdin(default,null) : haxe.io.Output; + public var stdout(default, null):haxe.io.Input; + public var stderr(default, null):haxe.io.Input; + public var stdin(default, null):haxe.io.Output; - public function new( cmd : String, ?args : Array, ?detached : Bool ) : Void { - if( detached ) throw "Detached process is not supported on this platform"; - p = try NativeProcess.process_run(cmd,args) catch( e : Dynamic ) throw "Process creation failure : "+cmd; + public function new(cmd:String, ?args:Array, ?detached:Bool):Void { + if (detached) + throw "Detached process is not supported on this platform"; + p = try NativeProcess.process_run(cmd, args) catch (e:Dynamic) throw "Process creation failure : " + cmd; stdin = new Stdin(p); - stdout = new Stdout(p,true); - stderr = new Stdout(p,false); + stdout = new Stdout(p, true); + stderr = new Stdout(p, false); } - public function getPid() : Int { + public function getPid():Int { return NativeProcess.process_pid(p); } - public function exitCode( block : Bool = true ) : Null { - if( block == false ) throw "Non blocking exitCode() not supported on this platform"; + public function exitCode(block:Bool = true):Null { + if (block == false) + throw "Non blocking exitCode() not supported on this platform"; return NativeProcess.process_exit(p); } - public function close() : Void { + public function close():Void { NativeProcess.process_close(p); } - public function kill() : Void { - throw "Not implemented"; + public function kill():Void { + NativeProcess.process_kill(p); } - } diff --git a/std/cpp/_std/sys/net/Host.hx b/std/cpp/_std/sys/net/Host.hx index 1d1177f64a2..f403b96e0cc 100644 --- a/std/cpp/_std/sys/net/Host.hx +++ b/std/cpp/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,44 +19,41 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.net; import cpp.NativeSocket; @:coreApi class Host { + public var host(default, null):String; - public var host(default,null) : String; - - public var ip(default,null) : Int; + public var ip(default, null):Int; - private var ipv6(default,null) : haxe.io.BytesData; + private var ipv6(default, null):haxe.io.BytesData; - public function new( name : String ) : Void { + public function new(name:String):Void { host = name; - try { + try { ip = NativeSocket.host_resolve(name); - } - catch(e:Dynamic) - { - ipv6 = NativeSocket.host_resolve_ipv6(name); - } + } catch (e:Dynamic) { + ipv6 = NativeSocket.host_resolve_ipv6(name); + } } - public function toString() : String { - return ipv6==null ? NativeSocket.host_to_string(ip) : NativeSocket.host_to_string_ipv6(ipv6); + public function toString():String { + return ipv6 == null ? NativeSocket.host_to_string(ip) : NativeSocket.host_to_string_ipv6(ipv6); } - public function reverse() : String { - return ipv6==null ? NativeSocket.host_reverse(ip) : NativeSocket.host_reverse_ipv6(ipv6); + public function reverse():String { + return ipv6 == null ? NativeSocket.host_reverse(ip) : NativeSocket.host_reverse_ipv6(ipv6); } - public static function localhost() : String { + public static function localhost():String { return NativeSocket.host_local(); } - static function __init__() : Void { + static function __init__():Void { NativeSocket.socket_init(); } - } diff --git a/std/cpp/_std/sys/net/Socket.hx b/std/cpp/_std/sys/net/Socket.hx index f7a0271e196..4c297cd3f13 100644 --- a/std/cpp/_std/sys/net/Socket.hx +++ b/std/cpp/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,247 +19,255 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.net; import haxe.io.Error; import cpp.NativeSocket; +import cpp.NativeString; +import cpp.Pointer; private class SocketInput extends haxe.io.Input { - - var __s : Dynamic; - - public function new(s:Dynamic) { - __s = s; - } - - public override function readByte() { - return try { - NativeSocket.socket_recv_char(__s); - } catch( e : Dynamic ) { - if( e == "Blocking" ) - throw Blocked; - else if( __s == null ) - throw Custom(e); - else - throw new haxe.io.Eof(); - } - } - - public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { - var r; - if (__s==null) - throw "Invalid handle"; - try { - r = NativeSocket.socket_recv(__s,buf.getData(),pos,len); - } catch( e : Dynamic ) { - if( e == "Blocking" ) - throw Blocked; - else - throw Custom(e); - } - if( r == 0 ) - throw new haxe.io.Eof(); - return r; - } - - public override function close() { - super.close(); - if( __s != null ) NativeSocket.socket_close(__s); - } - + var __s:Dynamic; + + public function new(s:Dynamic) { + __s = s; + } + + public override function readByte() { + return try { + NativeSocket.socket_recv_char(__s); + } catch (e:Dynamic) { + if (e == "Blocking") + throw Blocked; + else if (__s == null) + throw Custom(e); + else + throw new haxe.io.Eof(); + } + } + + public override function readBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { + var r; + if (__s == null) + throw "Invalid handle"; + try { + r = NativeSocket.socket_recv(__s, buf.getData(), pos, len); + } catch (e:Dynamic) { + if (e == "Blocking") + throw Blocked; + else + throw Custom(e); + } + if (r == 0) + throw new haxe.io.Eof(); + return r; + } + + public override function close() { + super.close(); + if (__s != null) + NativeSocket.socket_close(__s); + } } private class SocketOutput extends haxe.io.Output { - - var __s : Dynamic; - - public function new(s:Dynamic) { - __s = s; - } - - public override function writeByte( c : Int ) { - if (__s==null) - throw "Invalid handle"; - try { - NativeSocket.socket_send_char(__s, c); - } catch( e : Dynamic ) { - if( e == "Blocking" ) - throw Blocked; - else - throw Custom(e); - } - } - - public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { - return try { - NativeSocket.socket_send(__s, buf.getData(), pos, len); - } catch( e : Dynamic ) { - if( e == "Blocking" ) - throw Blocked; - else if (e == "EOF") - throw new haxe.io.Eof(); - else - throw Custom(e); - } - } - - public override function close() { - super.close(); - if( __s != null ) NativeSocket.socket_close(__s); - } - + var __s:Dynamic; + + public function new(s:Dynamic) { + __s = s; + } + + public override function writeByte(c:Int) { + if (__s == null) + throw "Invalid handle"; + try { + NativeSocket.socket_send_char(__s, c); + } catch (e:Dynamic) { + if (e == "Blocking") + throw Blocked; + else + throw Custom(e); + } + } + + public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { + return try { + NativeSocket.socket_send(__s, buf.getData(), pos, len); + } catch (e:Dynamic) { + if (e == "Blocking") + throw Blocked; + else if (e == "EOF") + throw new haxe.io.Eof(); + else + throw Custom(e); + } + } + + public override function close() { + super.close(); + if (__s != null) + NativeSocket.socket_close(__s); + } } - @:coreApi class Socket { - - private var __s : Dynamic; - public var input(default,null) : haxe.io.Input; - public var output(default,null) : haxe.io.Output; - public var custom : Dynamic; - - public function new() : Void { - init(); - } - - private function init() : Void { - if( __s == null )__s = NativeSocket.socket_new(false); - input = new SocketInput(__s); - output = new SocketOutput(__s); - } - - public function close() : Void { - NativeSocket.socket_close(__s); - untyped { - var input : SocketInput = cast input; - var output : SocketOutput = cast output; - input.__s = null; - output.__s = null; - } - input.close(); - output.close(); - } - - public function read() : String { - var bytes:haxe.io.BytesData = NativeSocket.socket_read(__s); - if (bytes==null) return ""; - return bytes.toString(); - } - - public function write( content : String ) : Void { - NativeSocket.socket_write(__s, haxe.io.Bytes.ofString(content).getData() ); - } - - public function connect(host : Host, port : Int) : Void { - try { - if (host.ip==0 && host.host!="0.0.0.0") { - // hack, hack, hack - var ipv6:haxe.io.BytesData = Reflect.field(host,"ipv6"); - if (ipv6!=null) - { - close(); - __s = NativeSocket.socket_new_ip(false,true); - init(); - NativeSocket.socket_connect_ipv6(__s, ipv6, port); - } - else - throw "Unresolved host"; - } - else - NativeSocket.socket_connect(__s, host.ip, port); - } catch( s : String ) { - if( s == "Invalid socket handle" ) - throw "Failed to connect on "+host.toString()+":"+port; - else if (s == "Blocking") { - // Do nothing, this is not a real error, it simply indicates - // that a non-blocking connect is in progress - } - else - cpp.Lib.rethrow(s); - } - } - - public function listen(connections : Int) : Void { - NativeSocket.socket_listen(__s, connections); - } - - public function shutdown( read : Bool, write : Bool ) : Void { - NativeSocket.socket_shutdown(__s,read,write); - } - - public function bind(host : Host, port : Int) : Void { - if (host.ip==0 && host.host!="0.0.0.0") - { - var ipv6:haxe.io.BytesData = Reflect.field(host,"ipv6"); - if (ipv6!=null) - { - close(); - __s = NativeSocket.socket_new_ip(false,true); - init(); - NativeSocket.socket_bind_ipv6(__s, ipv6, port); - } - else - throw "Unresolved host"; - } - else - NativeSocket.socket_bind(__s, host.ip, port); - } - - public function accept() : Socket { - var c = NativeSocket.socket_accept(__s); - var s = Type.createEmptyInstance(Socket); - s.__s = c; - s.input = new SocketInput(c); - s.output = new SocketOutput(c); - return s; - } - - public function peer() : { host : Host, port : Int } { - var a : Dynamic = NativeSocket.socket_peer(__s); - if (a == null) { - return null; - } - var h = new Host("127.0.0.1"); - untyped h.ip = a[0]; - return { host : h, port : a[1] }; - } - - public function host() : { host : Host, port : Int } { - var a : Dynamic = NativeSocket.socket_host(__s); - if (a == null) { - return null; - } - var h = new Host("127.0.0.1"); - untyped h.ip = a[0]; - return { host : h, port : a[1] }; - } - - public function setTimeout( timeout : Float ) : Void { - NativeSocket.socket_set_timeout(__s, timeout); - } - - public function waitForRead() : Void { - select([this],null,null,null); - } - - public function setBlocking( b : Bool ) : Void { - NativeSocket.socket_set_blocking(__s,b); - } - - public function setFastSend( b : Bool ) : Void { - NativeSocket.socket_set_fast_send(__s,b); - } - - public static function select(read : Array, write : Array, others : Array, ?timeout : Float ) : {read: Array,write: Array,others: Array} { - var neko_array = NativeSocket.socket_select(read,write,others, timeout); - if (neko_array==null) - throw "Select error"; - return @:fixed { - read: neko_array[0], - write: neko_array[1], - others: neko_array[2] - }; - } - + private var __s:Dynamic; + + // We need to keep these values so that we can restore + // them if we re-create the socket for ipv6 as in + // connect() and bind() below. + private var __timeout:Float = 0.0; + private var __blocking:Bool = true; + private var __fastSend:Bool = false; + + public var input(default, null):haxe.io.Input; + public var output(default, null):haxe.io.Output; + public var custom:Dynamic; + + public function new():Void { + init(); + } + + private function init():Void { + if (__s == null) + __s = NativeSocket.socket_new(false); + // Restore these values if they changed. This can happen + // in connect() and bind() if using an ipv6 address. + setTimeout(__timeout); + setBlocking(__blocking); + setFastSend(__fastSend); + input = new SocketInput(__s); + output = new SocketOutput(__s); + } + + public function close():Void { + NativeSocket.socket_close(__s); + untyped { + var input:SocketInput = cast input; + var output:SocketOutput = cast output; + input.__s = null; + output.__s = null; + } + input.close(); + output.close(); + } + + public function read():String { + var bytes:haxe.io.BytesData = NativeSocket.socket_read(__s); + if (bytes == null) + return ""; + var arr:Array = cast bytes; + return NativeString.fromPointer(Pointer.ofArray(arr)); + } + + public function write(content:String):Void { + NativeSocket.socket_write(__s, haxe.io.Bytes.ofString(content).getData()); + } + + public function connect(host:Host, port:Int):Void { + try { + if (host.ip == 0 && host.host != "0.0.0.0") { + // hack, hack, hack + var ipv6:haxe.io.BytesData = Reflect.field(host, "ipv6"); + if (ipv6 != null) { + close(); + __s = NativeSocket.socket_new_ip(false, true); + init(); + NativeSocket.socket_connect_ipv6(__s, ipv6, port); + } else + throw "Unresolved host"; + } else + NativeSocket.socket_connect(__s, host.ip, port); + } catch (s:String) { + if (s == "Invalid socket handle") + throw "Failed to connect on " + host.toString() + ":" + port; + else if (s == "Blocking") { + // Do nothing, this is not a real error, it simply indicates + // that a non-blocking connect is in progress + } else + cpp.Lib.rethrow(s); + } + } + + public function listen(connections:Int):Void { + NativeSocket.socket_listen(__s, connections); + } + + public function shutdown(read:Bool, write:Bool):Void { + NativeSocket.socket_shutdown(__s, read, write); + } + + public function bind(host:Host, port:Int):Void { + if (host.ip == 0 && host.host != "0.0.0.0") { + var ipv6:haxe.io.BytesData = Reflect.field(host, "ipv6"); + if (ipv6 != null) { + close(); + __s = NativeSocket.socket_new_ip(false, true); + init(); + NativeSocket.socket_bind_ipv6(__s, ipv6, port); + } else + throw "Unresolved host"; + } else + NativeSocket.socket_bind(__s, host.ip, port); + } + + public function accept():Socket { + var c = NativeSocket.socket_accept(__s); + var s = Type.createEmptyInstance(Socket); + s.__s = c; + s.input = new SocketInput(c); + s.output = new SocketOutput(c); + return s; + } + + public function peer():{host:Host, port:Int} { + var a:Dynamic = NativeSocket.socket_peer(__s); + if (a == null) { + return null; + } + var h = new Host("127.0.0.1"); + untyped h.ip = a[0]; + return {host: h, port: a[1]}; + } + + public function host():{host:Host, port:Int} { + var a:Dynamic = NativeSocket.socket_host(__s); + if (a == null) { + return null; + } + var h = new Host("127.0.0.1"); + untyped h.ip = a[0]; + return {host: h, port: a[1]}; + } + + public function setTimeout(timeout:Float):Void { + __timeout = timeout; + NativeSocket.socket_set_timeout(__s, timeout); + } + + public function waitForRead():Void { + select([this], null, null, null); + } + + public function setBlocking(b:Bool):Void { + __blocking = b; + NativeSocket.socket_set_blocking(__s, b); + } + + public function setFastSend(b:Bool):Void { + __fastSend = b; + NativeSocket.socket_set_fast_send(__s, b); + } + + public static function select(read:Array, write:Array, others:Array, + ?timeout:Float):{read:Array, write:Array, others:Array} { + var neko_array = NativeSocket.socket_select(read, write, others, timeout); + if (neko_array == null) + throw "Select error"; + return @:fixed { + read:neko_array[0], write:neko_array[1], others:neko_array[2] + }; + } } diff --git a/std/cpp/_std/sys/net/UdpSocket.hx b/std/cpp/_std/sys/net/UdpSocket.hx index f3deae9f857..dc4728c4935 100644 --- a/std/cpp/_std/sys/net/UdpSocket.hx +++ b/std/cpp/_std/sys/net/UdpSocket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,42 +19,46 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.net; + import haxe.io.Error; import cpp.NativeSocket; @:coreApi class UdpSocket extends Socket { - - private override function init() : Void { + private override function init():Void { __s = NativeSocket.socket_new(true); super.init(); } - public function sendTo( buf : haxe.io.Bytes, pos : Int, len : Int, addr : Address ) : Int { + public function sendTo(buf:haxe.io.Bytes, pos:Int, len:Int, addr:Address):Int { return try { NativeSocket.socket_send_to(__s, buf.getData(), pos, len, addr); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + } catch (e:Dynamic) { + if (e == "Blocking") throw Blocked; else throw Custom(e); } } - public function readFrom( buf : haxe.io.Bytes, pos : Int, len : Int, addr : Address ) : Int { + public function readFrom(buf:haxe.io.Bytes, pos:Int, len:Int, addr:Address):Int { var r; try { - r = NativeSocket.socket_recv_from(__s,buf.getData(),pos,len,addr); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + r = NativeSocket.socket_recv_from(__s, buf.getData(), pos, len, addr); + } catch (e:Dynamic) { + if (e == "Blocking") throw Blocked; else throw Custom(e); } - if( r == 0 ) + if (r == 0) throw new haxe.io.Eof(); return r; } + public function setBroadcast(b:Bool):Void { + NativeSocket.socket_set_broadcast(__s, b); + } } diff --git a/std/cpp/_std/sys/ssl/Certificate.hx b/std/cpp/_std/sys/ssl/Certificate.hx index de676f4a53d..705f67324a7 100644 --- a/std/cpp/_std/sys/ssl/Certificate.hx +++ b/std/cpp/_std/sys/ssl/Certificate.hx @@ -1,60 +1,82 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package sys.ssl; + import cpp.NativeSsl; @:coreApi class Certificate { - - var __h : Null; - var __x : Dynamic; + var __h:Null; + var __x:Dynamic; @:allow(sys.ssl.Socket) - function new( x : Dynamic, ?h: Null ){ + function new(x:Dynamic, ?h:Null) { __x = x; __h = h; } - public static function loadFile( file : String ) : Certificate { - return new Certificate( NativeSsl.cert_load_file( file ) ); + public static function loadFile(file:String):Certificate { + return new Certificate(NativeSsl.cert_load_file(file)); } - - public static function loadPath( path : String ) : Certificate { - return new Certificate( NativeSsl.cert_load_path( path ) ); + + public static function loadPath(path:String):Certificate { + return new Certificate(NativeSsl.cert_load_path(path)); } - public static function fromString( str : String ) : Certificate { - return new Certificate( NativeSsl.cert_add_pem(null, str) ); + public static function fromString(str:String):Certificate { + return new Certificate(NativeSsl.cert_add_pem(null, str)); } - public static function loadDefaults() : Certificate { + public static function loadDefaults():Certificate { var x = NativeSsl.cert_load_defaults(); - if ( x != null ) - return new Certificate( x ); - + if (x != null) + return new Certificate(x); + var defPaths = null; - switch( Sys.systemName() ){ + switch (Sys.systemName()) { case "Linux": defPaths = [ "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. - "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL - "/etc/ssl/ca-bundle.pem", // OpenSUSE - "/etc/pki/tls/cacert.pem", // OpenELEC - "/etc/ssl/certs", // SLES10/SLES11 - "/system/etc/security/cacerts" // Android + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/ssl/certs", // SLES10/SLES11 + "/system/etc/security/cacerts" // Android ]; case "BSD": defPaths = [ "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly - "/etc/ssl/cert.pem", // OpenBSD - "/etc/openssl/certs/ca-certificates.crt", // NetBSD + "/etc/ssl/cert.pem", // OpenBSD + "/etc/openssl/certs/ca-certificates.crt", // NetBSD ]; case "Android": defPaths = ["/system/etc/security/cacerts"]; default: } - if( defPaths != null ){ - for ( path in defPaths ){ - if ( sys.FileSystem.exists(path) ){ - if( sys.FileSystem.isDirectory(path) ) + if (defPaths != null) { + for (path in defPaths) { + if (sys.FileSystem.exists(path)) { + if (sys.FileSystem.isDirectory(path)) return loadPath(path); else return loadFile(path); @@ -64,52 +86,51 @@ class Certificate { return null; } - public var commonName(get,null) : Null; - public var altNames(get, null) : Array; - public var notBefore(get,null) : Date; - public var notAfter(get,null) : Date; + public var commonName(get, null):Null; + public var altNames(get, null):Array; + public var notBefore(get, null):Date; + public var notAfter(get, null):Date; - function get_commonName() : Null { + function get_commonName():Null { return subject("CN"); } - function get_altNames() : Array { + function get_altNames():Array { return NativeSsl.cert_get_altnames(__x); } - - public function subject( field : String ) : Null { + + public function subject(field:String):Null { return NativeSsl.cert_get_subject(__x, field); } - - public function issuer( field : String ) : Null { + + public function issuer(field:String):Null { return NativeSsl.cert_get_issuer(__x, field); } - function get_notBefore() : Date { - var a = NativeSsl.cert_get_notbefore( __x ); - return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + function get_notBefore():Date { + var a = NativeSsl.cert_get_notbefore(__x); + return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]); } - function get_notAfter() : Date { - var a = NativeSsl.cert_get_notafter( __x ); - return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + function get_notAfter():Date { + var a = NativeSsl.cert_get_notafter(__x); + return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]); } - - public function next() : Null { + + public function next():Null { var n = NativeSsl.cert_get_next(__x); - return n == null ? null : new Certificate( n, __h==null ? this : __h ); + return n == null ? null : new Certificate(n, __h == null ? this : __h); } - public function add( pem : String ) : Void { - NativeSsl.cert_add_pem(__x,pem); + public function add(pem:String):Void { + NativeSsl.cert_add_pem(__x, pem); } - public function addDER( der : haxe.io.Bytes ) : Void { - NativeSsl.cert_add_der(__x,der.getData()); + public function addDER(der:haxe.io.Bytes):Void { + NativeSsl.cert_add_der(__x, der.getData()); } - static function __init__() : Void { + static function __init__():Void { NativeSsl.init(); } - } diff --git a/std/cpp/_std/sys/ssl/Digest.hx b/std/cpp/_std/sys/ssl/Digest.hx index ca6300b4e10..4130887d408 100644 --- a/std/cpp/_std/sys/ssl/Digest.hx +++ b/std/cpp/_std/sys/ssl/Digest.hx @@ -1,19 +1,40 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package sys.ssl; + import cpp.NativeSsl; @:coreApi class Digest { - - public static function make( data : haxe.io.Bytes, alg : DigestAlgorithm ) : haxe.io.Bytes { - return haxe.io.Bytes.ofData( NativeSsl.dgst_make( data.getData(), alg ) ); + public static function make(data:haxe.io.Bytes, alg:DigestAlgorithm):haxe.io.Bytes { + return haxe.io.Bytes.ofData(NativeSsl.dgst_make(data.getData(), alg)); } - - public static function sign( data : haxe.io.Bytes, privKey : Key, alg : DigestAlgorithm ) : haxe.io.Bytes { - return haxe.io.Bytes.ofData( NativeSsl.dgst_sign( data.getData(), @:privateAccess privKey.__k, alg ) ); - } - - public static function verify( data : haxe.io.Bytes, signature : haxe.io.Bytes, pubKey : Key, alg : DigestAlgorithm ) : Bool{ - return NativeSsl.dgst_verify( data.getData(), signature.getData(), @:privateAccess pubKey.__k, alg ); + + public static function sign(data:haxe.io.Bytes, privKey:Key, alg:DigestAlgorithm):haxe.io.Bytes { + return haxe.io.Bytes.ofData(NativeSsl.dgst_sign(data.getData(), @:privateAccess privKey.__k, alg)); } + public static function verify(data:haxe.io.Bytes, signature:haxe.io.Bytes, pubKey:Key, alg:DigestAlgorithm):Bool { + return NativeSsl.dgst_verify(data.getData(), signature.getData(), @:privateAccess pubKey.__k, alg); + } } diff --git a/std/cpp/_std/sys/ssl/Key.hx b/std/cpp/_std/sys/ssl/Key.hx index b078855df83..26c0beec891 100644 --- a/std/cpp/_std/sys/ssl/Key.hx +++ b/std/cpp/_std/sys/ssl/Key.hx @@ -1,36 +1,57 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package sys.ssl; + import cpp.NativeSsl; private typedef PKEY = Dynamic; @:coreApi class Key { - - private var __k : PKEY; + private var __k:PKEY; - private function new( k : PKEY ){ + private function new(k:PKEY) { __k = k; } - - public static function loadFile( file : String, ?isPublic : Bool, ?pass : String ) : Key { - var data = sys.io.File.getBytes( file ); + + public static function loadFile(file:String, ?isPublic:Bool, ?pass:String):Key { + var data = sys.io.File.getBytes(file); var str = cpp.Lib.stringReference(data); - if( str.indexOf("-----BEGIN ") >= 0 ) - return readPEM( str, isPublic==true, pass ); + if (str.indexOf("-----BEGIN ") >= 0) + return readPEM(str, isPublic == true, pass); else - return readDER( data, isPublic==true ); + return readDER(data, isPublic == true); } - - public static function readPEM( data : String, isPublic : Bool, ?pass : String ) : Key { - return new Key( NativeSsl.key_from_pem( data, isPublic, pass ) ); + + public static function readPEM(data:String, isPublic:Bool, ?pass:String):Key { + return new Key(NativeSsl.key_from_pem(data, isPublic, pass)); } - public static function readDER( data : haxe.io.Bytes, isPublic : Bool ) : Key { - return new Key( NativeSsl.key_from_der( data.getData(), isPublic ) ); + public static function readDER(data:haxe.io.Bytes, isPublic:Bool):Key { + return new Key(NativeSsl.key_from_der(data.getData(), isPublic)); } - static function __init__() : Void { + static function __init__():Void { NativeSsl.init(); } - } diff --git a/std/cpp/_std/sys/ssl/Socket.hx b/std/cpp/_std/sys/ssl/Socket.hx index 204ffc4130f..535787795cf 100644 --- a/std/cpp/_std/sys/ssl/Socket.hx +++ b/std/cpp/_std/sys/ssl/Socket.hx @@ -1,4 +1,27 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package sys.ssl; + import cpp.NativeSocket; import cpp.NativeSsl; @@ -7,78 +30,78 @@ private typedef CONF = Dynamic; private typedef SSL = Dynamic; private class SocketInput extends haxe.io.Input { - @:allow(sys.ssl.Socket) private var __s : Socket; + @:allow(sys.ssl.Socket) private var __s:Socket; - public function new( s : Socket ) { + public function new(s:Socket) { this.__s = s; } public override function readByte() { return try { __s.handshake(); - NativeSsl.ssl_recv_char( @:privateAccess __s.ssl ); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + NativeSsl.ssl_recv_char(@:privateAccess __s.ssl); + } catch (e:Dynamic) { + if (e == "Blocking") throw haxe.io.Error.Blocked; - else if( __s == null ) + else if (__s == null) throw haxe.io.Error.Custom(e); else throw new haxe.io.Eof(); } } - public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { - var r : Int; - if( __s == null ) + public override function readBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { + var r:Int; + if (__s == null) throw "Invalid handle"; try { __s.handshake(); - r = NativeSsl.ssl_recv( @:privateAccess __s.ssl, buf.getData(), pos, len ); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + r = NativeSsl.ssl_recv(@:privateAccess __s.ssl, buf.getData(), pos, len); + } catch (e:Dynamic) { + if (e == "Blocking") throw haxe.io.Error.Blocked; else throw haxe.io.Error.Custom(e); } - if( r == 0 ) + if (r == 0) throw new haxe.io.Eof(); return r; } public override function close() { super.close(); - if( __s != null ) __s.close(); + if (__s != null) + __s.close(); } - } private class SocketOutput extends haxe.io.Output { - @:allow(sys.ssl.Socket) private var __s : Socket; + @:allow(sys.ssl.Socket) private var __s:Socket; - public function new( s : Socket ) { + public function new(s:Socket) { this.__s = s; } - public override function writeByte( c : Int ) { - if( __s == null ) + public override function writeByte(c:Int) { + if (__s == null) throw "Invalid handle"; try { __s.handshake(); - NativeSsl.ssl_send_char( @:privateAccess __s.ssl, c ); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + NativeSsl.ssl_send_char(@:privateAccess __s.ssl, c); + } catch (e:Dynamic) { + if (e == "Blocking") throw haxe.io.Error.Blocked; else throw haxe.io.Error.Custom(e); } } - public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { + public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { return try { __s.handshake(); - NativeSsl.ssl_send( @:privateAccess __s.ssl, buf.getData(), pos, len ); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + NativeSsl.ssl_send(@:privateAccess __s.ssl, buf.getData(), pos, len); + } catch (e:Dynamic) { + if (e == "Blocking") throw haxe.io.Error.Blocked; else throw haxe.io.Error.Custom(e); @@ -87,137 +110,139 @@ private class SocketOutput extends haxe.io.Output { public override function close() { super.close(); - if( __s != null ) __s.close(); + if (__s != null) + __s.close(); } - } @:coreApi class Socket extends sys.net.Socket { - - public static var DEFAULT_VERIFY_CERT : Null = true; - - public static var DEFAULT_CA : Null; - - private var conf : CONF; - private var ssl : SSL; - - public var verifyCert : Null; - private var caCert : Null; - private var hostname : String; - - private var ownCert : Null; - private var ownKey : Null; - private var altSNIContexts : NullBool, key: Key, cert: Certificate}>>; - private var sniCallback : Dynamic; - private var handshakeDone : Bool; - - private override function init() : Void { - __s = NativeSocket.socket_new( false ); - input = new SocketInput( this ); - output = new SocketOutput( this ); - if( DEFAULT_VERIFY_CERT && DEFAULT_CA == null ){ + public static var DEFAULT_VERIFY_CERT:Null = true; + + public static var DEFAULT_CA:Null; + + private var conf:CONF; + private var ssl:SSL; + + public var verifyCert:Null; + + private var caCert:Null; + private var hostname:String; + + private var ownCert:Null; + private var ownKey:Null; + private var altSNIContexts:NullBool, key:Key, cert:Certificate}>>; + private var sniCallback:Dynamic; + private var handshakeDone:Bool; + + private override function init():Void { + __s = NativeSocket.socket_new(false); + input = new SocketInput(this); + output = new SocketOutput(this); + if (DEFAULT_VERIFY_CERT && DEFAULT_CA == null) { try { DEFAULT_CA = Certificate.loadDefaults(); - }catch( e : Dynamic ){} - } + } catch (e:Dynamic) {} + } caCert = DEFAULT_CA; verifyCert = DEFAULT_VERIFY_CERT; } - public override function connect(host : sys.net.Host, port : Int) : Void { + public override function connect(host:sys.net.Host, port:Int):Void { try { - conf = buildSSLConfig( false ); - ssl = NativeSsl.ssl_new( conf ); + conf = buildSSLConfig(false); + ssl = NativeSsl.ssl_new(conf); handshakeDone = false; - NativeSsl.ssl_set_socket( ssl, __s ); - if( hostname == null ) + NativeSsl.ssl_set_socket(ssl, __s); + if (hostname == null) hostname = host.host; - if( hostname != null ) - NativeSsl.ssl_set_hostname( ssl, hostname ); - NativeSocket.socket_connect( __s, host.ip, port ); + if (hostname != null) + NativeSsl.ssl_set_hostname(ssl, hostname); + NativeSocket.socket_connect(__s, host.ip, port); handshake(); - } catch( s : String ) { - if( s == "Invalid socket handle" ) - throw "Failed to connect on "+host.host+":"+port; + } catch (s:String) { + if (s == "Invalid socket handle") + throw "Failed to connect on " + host.host + ":" + port; else cpp.Lib.rethrow(s); - } catch( e : Dynamic ) { + } catch (e:Dynamic) { cpp.Lib.rethrow(e); } } - public function handshake() : Void { - if( !handshakeDone ){ + public function handshake():Void { + if (!handshakeDone) { try { - NativeSsl.ssl_handshake( ssl ); + NativeSsl.ssl_handshake(ssl); handshakeDone = true; - } catch( e : Dynamic ) { - if( e == "Blocking" ) + } catch (e:Dynamic) { + if (e == "Blocking") throw haxe.io.Error.Blocked; else - cpp.Lib.rethrow( e ); + cpp.Lib.rethrow(e); } } } - public function setCA( cert : Certificate ) : Void { + public function setCA(cert:Certificate):Void { caCert = cert; } - public function setHostname( name : String ) : Void { + public function setHostname(name:String):Void { hostname = name; } - public function setCertificate( cert : Certificate, key : Key ) : Void { + public function setCertificate(cert:Certificate, key:Key):Void { ownCert = cert; ownKey = key; } - public override function read() : String { + public override function read():String { handshake(); - var b = NativeSsl.ssl_read( ssl ); - if( b == null ) + var b = NativeSsl.ssl_read(ssl); + if (b == null) return ""; return haxe.io.Bytes.ofData(b).toString(); } - public override function write( content : String ) : Void { + public override function write(content:String):Void { handshake(); - NativeSsl.ssl_write( ssl, haxe.io.Bytes.ofString(content).getData() ); + NativeSsl.ssl_write(ssl, haxe.io.Bytes.ofString(content).getData()); } - public override function close() : Void { - if( ssl != null ) NativeSsl.ssl_close( ssl ); - if( conf != null ) NativeSsl.conf_close( conf ); - if( altSNIContexts != null ) + public override function close():Void { + if (ssl != null) + NativeSsl.ssl_close(ssl); + if (conf != null) + NativeSsl.conf_close(conf); + if (altSNIContexts != null) sniCallback = null; - NativeSocket.socket_close( __s ); - var input : SocketInput = cast input; - var output : SocketOutput = cast output; + NativeSocket.socket_close(__s); + var input:SocketInput = cast input; + var output:SocketOutput = cast output; @:privateAccess input.__s = output.__s = null; input.close(); output.close(); } - public function addSNICertificate( cbServernameMatch : String->Bool, cert : Certificate, key : Key ) : Void { - if( altSNIContexts == null ) + public function addSNICertificate(cbServernameMatch:String->Bool, cert:Certificate, key:Key):Void { + if (altSNIContexts == null) altSNIContexts = []; - altSNIContexts.push( {match: cbServernameMatch, cert: cert, key: key} ); + altSNIContexts.push({match: cbServernameMatch, cert: cert, key: key}); } - public override function bind( host : sys.net.Host, port : Int ) : Void { - conf = buildSSLConfig( true ); + public override function bind(host:sys.net.Host, port:Int):Void { + conf = buildSSLConfig(true); - NativeSocket.socket_bind( __s, host.ip, port ); + NativeSocket.socket_bind(__s, host.ip, port); } - public override function accept() : Socket { - var c = NativeSocket.socket_accept( __s ); - var ssl = NativeSsl.ssl_new( conf ); - NativeSsl.ssl_set_socket( ssl, c ); + public override function accept():Socket { + var c = NativeSocket.socket_accept(__s); + var ssl = NativeSsl.ssl_new(conf); + NativeSsl.ssl_set_socket(ssl, c); - var s = Type.createEmptyInstance( sys.ssl.Socket ); + var s = Type.createEmptyInstance(sys.ssl.Socket); s.__s = c; s.ssl = ssl; s.input = new SocketInput(s); @@ -227,42 +252,46 @@ class Socket extends sys.net.Socket { return s; } - public function peerCertificate() : sys.ssl.Certificate { - var x = NativeSsl.ssl_get_peer_certificate( ssl ); - return x==null ? null : new sys.ssl.Certificate( x ); + public function peerCertificate():sys.ssl.Certificate { + var x = NativeSsl.ssl_get_peer_certificate(ssl); + return x == null ? null : new sys.ssl.Certificate(x); } - private function buildSSLConfig( server : Bool ) : CONF { - var conf : CONF = NativeSsl.conf_new( server ); + private function buildSSLConfig(server:Bool):CONF { + var conf:CONF = NativeSsl.conf_new(server); - if( ownCert != null && ownKey != null ) - NativeSsl.conf_set_cert( conf, @:privateAccess ownCert.__x, @:privateAccess ownKey.__k ); + if (ownCert != null && ownKey != null) + NativeSsl.conf_set_cert(conf, @:privateAccess ownCert.__x, @:privateAccess ownKey.__k); - if ( altSNIContexts != null ) { + if (altSNIContexts != null) { sniCallback = function(servername) { var servername = new String(cast servername); - for( c in altSNIContexts ){ - if( c.match(servername) ) - return @:privateAccess {key: c.key.__k, cert: c.cert.__x}; + for (c in altSNIContexts) { + if (c.match(servername)) + return @:privateAccess { + key:c.key.__k, cert:c.cert.__x + }; } - if( ownKey != null && ownCert != null ) - return @:privateAccess { key: ownKey.__k, cert: ownCert.__x }; + if (ownKey != null && ownCert != null) + return @:privateAccess { + key:ownKey.__k, cert:ownCert.__x + }; return null; } - NativeSsl.conf_set_servername_callback( conf, sniCallback ); + NativeSsl.conf_set_servername_callback(conf, sniCallback); } - if ( caCert != null ) - NativeSsl.conf_set_ca( conf, caCert == null ? null : @:privateAccess caCert.__x ); - if( verifyCert == null ) - NativeSsl.conf_set_verify( conf, 2 ); + if (caCert != null) + NativeSsl.conf_set_ca(conf, caCert == null ? null : @:privateAccess caCert.__x); + if (verifyCert == null) + NativeSsl.conf_set_verify(conf, 2); else - NativeSsl.conf_set_verify( conf, verifyCert ? 1 : 0 ); - + NativeSsl.conf_set_verify(conf, verifyCert ? 1 : 0); + return conf; } - static function __init__() : Void { + static function __init__():Void { NativeSsl.init(); } } diff --git a/std/cpp/_std/sys/thread/Deque.hx b/std/cpp/_std/sys/thread/Deque.hx new file mode 100644 index 00000000000..36a6ed983f0 --- /dev/null +++ b/std/cpp/_std/sys/thread/Deque.hx @@ -0,0 +1,44 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +@:coreApi +class Deque { + var q:Dynamic; + + public function new() { + q = untyped __global__.__hxcpp_deque_create(); + } + + public function add(i:T):Void { + untyped __global__.__hxcpp_deque_add(q, i); + } + + public function push(i:T):Void { + untyped __global__.__hxcpp_deque_push(q, i); + } + + public function pop(block:Bool):Null { + return untyped __global__.__hxcpp_deque_pop(q, block); + } +} diff --git a/std/neko/_std/haxe/Log.hx b/std/cpp/_std/sys/thread/Lock.hx similarity index 74% rename from std/neko/_std/haxe/Log.hx rename to std/cpp/_std/sys/thread/Lock.hx index a8ac5e66e41..992d4d1ddf4 100644 --- a/std/neko/_std/haxe/Log.hx +++ b/std/cpp/_std/sys/thread/Lock.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,22 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe; -@:coreApi class Log { - public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { - untyped { - $print(infos.fileName + ":" + infos.lineNumber + ": ", v); - if( infos.customParams != null ) for( v in infos.customParams ) $print(",", v); - $print("\n"); - } +package sys.thread; + +@:coreApi +class Lock { + var l:Dynamic; + + public function new() { + l = untyped __global__.__hxcpp_lock_create(); + } + + public function wait(?timeout:Float = -1):Bool { + return untyped __global__.__hxcpp_lock_wait(l, timeout); + } + + public function release():Void { + untyped __global__.__hxcpp_lock_release(l); } } diff --git a/std/cpp/_std/sys/thread/Mutex.hx b/std/cpp/_std/sys/thread/Mutex.hx new file mode 100644 index 00000000000..8d10509df23 --- /dev/null +++ b/std/cpp/_std/sys/thread/Mutex.hx @@ -0,0 +1,44 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +@:coreApi +class Mutex { + var m:Dynamic; + + public function new() { + m = untyped __global__.__hxcpp_mutex_create(); + } + + public function acquire():Void { + untyped __global__.__hxcpp_mutex_acquire(m); + } + + public function tryAcquire():Bool { + return untyped __global__.__hxcpp_mutex_try(m); + } + + public function release():Void { + untyped __global__.__hxcpp_mutex_release(m); + } +} diff --git a/std/cpp/_std/sys/thread/Thread.hx b/std/cpp/_std/sys/thread/Thread.hx new file mode 100644 index 00000000000..44c9cedf75c --- /dev/null +++ b/std/cpp/_std/sys/thread/Thread.hx @@ -0,0 +1,58 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +@:callable +@:coreType +private abstract ThreadHandle {} + +abstract Thread(ThreadHandle) { + inline function new(h:ThreadHandle):Void { + this = h; + } + + public inline function sendMessage(msg:Dynamic):Void { + untyped __global__.__hxcpp_thread_send(this, msg); + } + + public static inline function current():Thread { + return new Thread(untyped __global__.__hxcpp_thread_current()); + } + + public static inline function create(callb:Void->Void):Thread { + return new Thread(untyped __global__.__hxcpp_thread_create(callb)); + } + + public static function readMessage(block:Bool):Dynamic { + return untyped __global__.__hxcpp_thread_read_message(block); + } + + @:op(A == B) + public inline function equals(other:Thread):Bool { + return getHandle() == other.getHandle(); + } + + private inline function getHandle():ThreadHandle { + return this; + } +} diff --git a/std/cpp/_std/sys/thread/Tls.hx b/std/cpp/_std/sys/thread/Tls.hx new file mode 100644 index 00000000000..7baad6ca4e2 --- /dev/null +++ b/std/cpp/_std/sys/thread/Tls.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +@:coreApi +class Tls { + static var sFreeSlot = 0; + + var mTLSID:Int; + + public var value(get, set):T; + + public function new() { + mTLSID = sFreeSlot++; + } + + function get_value():T { + return untyped __global__.__hxcpp_tls_get(mTLSID); + } + + function set_value(v:T):T { + untyped __global__.__hxcpp_tls_set(mTLSID, v); + return v; + } +} diff --git a/std/cpp/abi/Abi.hx b/std/cpp/abi/Abi.hx index c313080925c..ca9b182c9d5 100644 --- a/std/cpp/abi/Abi.hx +++ b/std/cpp/abi/Abi.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.abi; + +package cpp.abi; // Base case, for calling conventions - means "use default" -extern class Abi { } +extern class Abi {} diff --git a/std/cpp/abi/CDecl.hx b/std/cpp/abi/CDecl.hx index 8b8cf6f5f39..efecc84cc09 100644 --- a/std/cpp/abi/CDecl.hx +++ b/std/cpp/abi/CDecl.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.abi; + +package cpp.abi; @:abi("__cdecl") -extern class CDecl extends Abi { } +extern class CDecl extends Abi {} diff --git a/std/cpp/abi/FastCall.hx b/std/cpp/abi/FastCall.hx index 921bfa2ff4b..32b235e8422 100644 --- a/std/cpp/abi/FastCall.hx +++ b/std/cpp/abi/FastCall.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.abi; + +package cpp.abi; @:abi("__fastcall") -extern class FastCall extends Abi { } +extern class FastCall extends Abi {} diff --git a/std/cpp/abi/StdCall.hx b/std/cpp/abi/StdCall.hx index 271f3d79ac7..f966adf17dc 100644 --- a/std/cpp/abi/StdCall.hx +++ b/std/cpp/abi/StdCall.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.abi; + +package cpp.abi; @:abi("__stdcall") -extern class StdCall extends Abi { } +extern class StdCall extends Abi {} diff --git a/std/cpp/abi/ThisCall.hx b/std/cpp/abi/ThisCall.hx index 077f8294dd1..ce5f6e95101 100644 --- a/std/cpp/abi/ThisCall.hx +++ b/std/cpp/abi/ThisCall.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.abi; + +package cpp.abi; @:abi("__thiscall") -extern class ThisCall extends Abi { } +extern class ThisCall extends Abi {} diff --git a/std/cpp/abi/Winapi.hx b/std/cpp/abi/Winapi.hx index 1ad8dd7be97..36580f9e3e0 100644 --- a/std/cpp/abi/Winapi.hx +++ b/std/cpp/abi/Winapi.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.abi; + +package cpp.abi; @:abi("__stdcall") -extern class Winapi extends Abi { } +extern class Winapi extends Abi {} diff --git a/std/cpp/cppia/Host.hx b/std/cpp/cppia/Host.hx index c64955f8049..cc3081c7397 100644 --- a/std/cpp/cppia/Host.hx +++ b/std/cpp/cppia/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,49 +19,48 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.cppia; +package cpp.cppia; -class Host -{ - public static function run(source:String) - { - var module = Module.fromString(source); - module.boot(); - module.run(); - } +class Host { + #if utf16 + public static function run(source:haxe.io.Bytes) { + var module = Module.fromData(source.getData()); + module.boot(); + module.run(); + } + #else + public static function run(source:String) { + var module = Module.fromString(source); + module.boot(); + module.run(); + } + #end + @:native("hx::EnableJit") + extern public static function enableJit(enable:Bool):Void; - @:native("hx::EnableJit") - @:extern public static function enableJit(enable:Bool) : Void { } + public static function runFile(filename:String) { + var source = sys.io.File.getBytes(filename); + var module = Module.fromData(source.getData()); + module.boot(); + module.run(); + } - public static function runFile(filename:String) - { - run( sys.io.File.getContent(filename) ); - } + public static function main() { + var args = Sys.args(); + if (args.remove("-jit")) + enableJit(true); + var script = args[0]; - public static function main() - { - var args = Sys.args(); - if (args.remove("-jit")) - enableJit(true); - - var script = args[0]; - - #if (!scriptable && !doc_gen) - #error "Please define scriptable to use cppia" - #end - if (script==null) - { - Sys.println("Usage : Cppia scriptname"); - } - else - { - var source = sys.io.File.getContent(script); - var module = Module.fromString(source); - module.boot(); - module.run(); - } - } + #if (!scriptable && !doc_gen) + #error "Please define scriptable to use cppia" + #end + if (script == null) { + Sys.println("Usage : Cppia scriptname"); + } else { + runFile(script); + } + } } diff --git a/std/cpp/cppia/HostClasses.hx b/std/cpp/cppia/HostClasses.hx index e12000bbf36..f8ebbc25e97 100644 --- a/std/cpp/cppia/HostClasses.hx +++ b/std/cpp/cppia/HostClasses.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,250 +19,223 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.cppia; + +package cpp.cppia; import haxe.macro.Compiler; import haxe.macro.Context; import haxe.macro.Type; - #if !macro - #if cppia - @:build(cpp.cppia.HostClasses.exclude()) - #end -class HostClasses { } +#if cppia +@:build(cpp.cppia.HostClasses.exclude()) +#end +class HostClasses {} #else - import Sys; import haxe.Constraints; @:noPackageRestrict -class HostClasses -{ - static var classes = [ - "cpp.Lib", - "cpp.NativeArray", - "cpp.NativeString", - "cpp.vm.Debugger", - "cpp.vm.Deque", - "cpp.vm.ExecutionTrace", - "cpp.vm.Gc", - "cpp.vm.Lock", - "cpp.vm.Mutex", - "cpp.vm.Profiler", - "cpp.vm.Thread", - "cpp.vm.Tls", - "cpp.vm.Unsafe", - "cpp.vm.WeakRef", - "cpp.Object", - "cpp.Int64", - "cpp.Finalizable", - "Std", - "StringBuf", - "sys.db.Mysql", - "sys.db.Sqlite", - "sys.FileSystem", - "sys.io.File", - "sys.io.FileInput", - "sys.net.UdpSocket", - "sys.net.Socket", - "sys.ssl.Certificate", - "sys.ssl.Digest", - "sys.ssl.Key", - "sys.ssl.Socket", - "Enum", - "EnumValue", - //"Sys", - "Type", - "Xml", - "Date", - "Lambda", - "DateTools", - "List", - "Math", - "Reflect", - "StringBuf", - "StringTools", - - "haxe.ds.IntMap", - "haxe.ds.ObjectMap", - "haxe.ds.StringMap", - "haxe.ds.BalancedTree", - "haxe.CallStack", - "haxe.Serializer", - "haxe.Unserializer", - "haxe.Resource", - "haxe.Template", - "haxe.Utf8", - "haxe.Log", - "haxe.zip.Compress", - "haxe.zip.Uncompress", - - "haxe.crypto.BaseCode", - "haxe.crypto.Sha256", - "haxe.crypto.Hmac", - "haxe.crypto.Crc32", - "haxe.crypto.Base64", - "haxe.crypto.Adler32", - "haxe.crypto.Md5", - "haxe.crypto.Sha1", - - "haxe.io.BufferInput", - "haxe.io.Bytes", - "haxe.io.BytesBuffer", - "haxe.io.BytesData", - "haxe.io.BytesInput", - "haxe.io.BytesOutput", - "haxe.io.Eof", - "haxe.io.Error", - "haxe.io.FPHelper", - "haxe.io.Input", - "haxe.io.Output", - "haxe.io.Path", - "haxe.io.StringInput", - "haxe.xml.Parser", - "haxe.Json", - - "haxe.CallStack", - "haxe.Resource", - "haxe.Utf8", - "haxe.Int64", - "haxe.Int32", - "haxe.Serializer", - "haxe.Unserializer", - - - "haxe.ds.ArraySort", - "haxe.ds.GenericStack", - "haxe.ds.ObjectMap", - "haxe.ds.Vector", - "haxe.ds.BalancedTree", - "haxe.ds.HashMap", - "haxe.ds.Option", - "haxe.ds.WeakMap", - "haxe.ds.EnumValueMap", - "haxe.ds.IntMap", - "haxe.ds.StringMap", - - "StdTypes", - "Array", - "Class", - "Date", - "EReg", - "Enum", - "EnumValue", - // "IntIterator", - "List", - "Map", - "String", - - - ]; - - - static function parseClassInfo(externs:Map, filename:String) - { - if (sys.FileSystem.exists(filename)) - { - var file = sys.io.File.read(filename); - try - { - while(true) - { - var line = file.readLine(); - var parts = line.split(" "); - if (parts[0]=="class" || parts[0]=="interface" || parts[0]=="enum") - externs.set(parts[1],true); - } - } catch( e : Dynamic ) { } - if (file!=null) - file.close(); - } - } - - - static function onGenerateCppia(types:Array):Void - { - var externs = new Map(); - externs.set("Sys",true); - externs.set("haxe.IMap",true); - externs.set("haxe.crypto.HashMethod",true); - externs.set("haxe._Int64.Int64_Impl_",true); - externs.set("haxe._Int64.___Int64",true); - externs.set("haxe._Int32.Int32_Impl_",true); - externs.set("haxe._Int32.___Int32",true); - // Hidded in implementation classes - //externs.set("sys.db.RecordType",true); - externs.set("sys.db._Sqlite.SqliteConnection",true); - externs.set("sys.db._Sqlite.SqliteResultSet",true); - externs.set("sys.db._Mysql.MysqlConnection",true); - externs.set("sys.db._Mysql.MysqlResultSet",true); - externs.set("sys.net._Socket.SocketInput",true); - externs.set("sys.net._Socket.SocketOutput",true); - externs.set("sys.ssl._Socket.SocketInput",true); - externs.set("sys.ssl._Socket.SocketOutput",true); - externs.set("haxe.ds.TreeNode",true); - externs.set("haxe.xml.XmlParserException",true); - for(e in classes) - externs.set(e,true); - - - var define = Context.defined("dll_import") ? Context.definedValue("dll_import") : "1"; - if (define!="1") - parseClassInfo(externs,define); - else - { - var tried = new Map(); - for(path in Context.getClassPath()) - if (!tried.exists(path)) - { - tried.set(path,true); - parseClassInfo(externs,path + "/export_classes.info"); - } - } - - for(type in types) - { - switch(type) - { - case TInst(classRef, params): - if (externs.exists(classRef.toString())) - classRef.get().exclude(); - case TEnum(enumRef, params): - if (externs.exists(enumRef.toString())) - enumRef.get().exclude(); - default: - } - } - } - - // Exclude the standard classes, and any described in 'export_classes.info' files found in the classpath - public static function exclude() - { - if (Context.defined("cppia")) - Context.onGenerate(onGenerateCppia); - else - Context.error("cpp.cppia.excludeHostFiles is only for cppia code", Context.currentPos()); - return Context.getBuildFields(); - } - - - // Ensure that the standard classes are included in the host - public static function include() - { - Compiler.keep("haxe.IMap"); - Compiler.keep("haxe.crypto.HashMethod"); - Compiler.keep("haxe._Int64.Int64_Impl_"); - Compiler.keep("haxe._Int32.Int32_Impl_"); - Compiler.keep("haxe._Int64.___Int64"); - Compiler.keep("haxe._Int32.___Int32"); - for(cls in classes) - { - Context.getModule(cls); - Compiler.keep(cls); - } - return Context.getBuildFields(); - } +class HostClasses { + static var classes = [ + "cpp.Lib", + "cpp.NativeArray", + "cpp.NativeString", + "cpp.vm.Debugger", + "cpp.vm.Deque", + "cpp.vm.ExecutionTrace", + "cpp.vm.Gc", + "cpp.vm.Lock", + "cpp.vm.Mutex", + "cpp.vm.Profiler", + "cpp.vm.Thread", + "cpp.vm.Tls", + "cpp.vm.Unsafe", + "cpp.vm.WeakRef", + "cpp.Object", + "cpp.Int64", + "cpp.Finalizable", + "Std", + "StringBuf", + "sys.db.Mysql", + "sys.db.Sqlite", + "sys.FileSystem", + "sys.io.File", + "sys.io.FileInput", + "sys.io.Process", + "sys.net.UdpSocket", + "sys.net.Socket", + "sys.ssl.Certificate", + "sys.ssl.Digest", + "sys.ssl.Key", + "sys.ssl.Socket", + "Enum", + "EnumValue", + // "Sys", + "Type", + "Xml", + "Date", + "Lambda", + "DateTools", + "List", + "Math", + "Reflect", + "StringBuf", + "StringTools", + "haxe.ds.IntMap", + "haxe.ds.ObjectMap", + "haxe.ds.StringMap", + "haxe.ds.BalancedTree", + "haxe.CallStack", + "haxe.Serializer", + "haxe.Unserializer", + "haxe.Resource", + "haxe.Template", + "haxe.Utf8", + "haxe.Log", + "haxe.zip.Compress", + "haxe.zip.Uncompress", + "haxe.crypto.BaseCode", + "haxe.crypto.Sha256", + "haxe.crypto.Hmac", + "haxe.crypto.Crc32", + "haxe.crypto.Base64", + "haxe.crypto.Adler32", + "haxe.crypto.Md5", + "haxe.crypto.Sha1", + "haxe.io.BufferInput", + "haxe.io.Bytes", + "haxe.io.BytesBuffer", + "haxe.io.BytesData", + "haxe.io.BytesInput", + "haxe.io.BytesOutput", + "haxe.io.Eof", + "haxe.io.Error", + "haxe.io.FPHelper", + "haxe.io.Input", + "haxe.io.Output", + "haxe.io.Path", + "haxe.io.StringInput", + "haxe.xml.Parser", + "haxe.Json", + "haxe.CallStack", + "haxe.Resource", + "haxe.Utf8", + "haxe.Int64", + "haxe.Int32", + "haxe.Serializer", + "haxe.Unserializer", + "haxe.ds.ArraySort", + "haxe.ds.GenericStack", + "haxe.ds.ObjectMap", + "haxe.ds.Vector", + "haxe.ds.BalancedTree", + "haxe.ds.HashMap", + "haxe.ds.Option", + "haxe.ds.WeakMap", + "haxe.ds.EnumValueMap", + "haxe.ds.IntMap", + "haxe.ds.StringMap", + "haxe.iterators.MapKeyValueIterator", + "StdTypes", + "Array", + "Class", + "Date", + "EReg", + "Enum", + "EnumValue", + // "IntIterator", + "List", + "Map", + "String", + ]; + + static function parseClassInfo(externs:Map, filename:String) { + if (sys.FileSystem.exists(filename)) { + var file = sys.io.File.read(filename); + try { + while (true) { + var line = file.readLine(); + var parts = line.split(" "); + if (parts[0] == "class" || parts[0] == "interface" || parts[0] == "enum") + externs.set(parts[1], true); + } + } catch (e:Dynamic) {} + if (file != null) + file.close(); + } + } + + static function onGenerateCppia(types:Array):Void { + var externs = new Map(); + externs.set("Sys", true); + externs.set("haxe.IMap", true); + externs.set("haxe.crypto.HashMethod", true); + externs.set("haxe._Int64.Int64_Impl_", true); + externs.set("haxe._Int64.___Int64", true); + externs.set("haxe._Int32.Int32_Impl_", true); + externs.set("haxe._Int32.___Int32", true); + // Hidded in implementation classes + // externs.set("sys.db.RecordType",true); + externs.set("sys.db._Sqlite.SqliteConnection", true); + externs.set("sys.db._Sqlite.SqliteResultSet", true); + externs.set("sys.db._Mysql.MysqlConnection", true); + externs.set("sys.db._Mysql.MysqlResultSet", true); + externs.set("sys.net._Socket.SocketInput", true); + externs.set("sys.net._Socket.SocketOutput", true); + externs.set("sys.ssl._Socket.SocketInput", true); + externs.set("sys.ssl._Socket.SocketOutput", true); + externs.set("haxe.ds.TreeNode", true); + externs.set("haxe.xml.XmlParserException", true); + for (e in classes) + externs.set(e, true); + + var define = Context.defined("dll_import") ? Context.definedValue("dll_import") : "1"; + if (define != "1") + parseClassInfo(externs, define); + else { + var tried = new Map(); + for (path in Context.getClassPath()) + if (!tried.exists(path)) { + tried.set(path, true); + parseClassInfo(externs, path + "/export_classes.info"); + } + } + + for (type in types) { + switch (type) { + case TInst(classRef, params): + if (externs.exists(classRef.toString())) + classRef.get().exclude(); + case TEnum(enumRef, params): + if (externs.exists(enumRef.toString())) + enumRef.get().exclude(); + default: + } + } + } + + // Exclude the standard classes, and any described in 'export_classes.info' files found in the classpath + public static function exclude() { + if (Context.defined("cppia")) + Context.onGenerate(onGenerateCppia); + else + Context.error("cpp.cppia.excludeHostFiles is only for cppia code", Context.currentPos()); + return Context.getBuildFields(); + } + + // Ensure that the standard classes are included in the host + public static function include() { + Compiler.keep("haxe.IMap"); + Compiler.keep("haxe.crypto.HashMethod"); + Compiler.keep("haxe._Int64.Int64_Impl_"); + Compiler.keep("haxe._Int32.Int32_Impl_"); + Compiler.keep("haxe._Int64.___Int64"); + Compiler.keep("haxe._Int32.___Int32"); + for (cls in classes) { + Context.getModule(cls); + Compiler.keep(cls); + } + return Context.getBuildFields(); + } } #end - - diff --git a/std/cpp/cppia/Module.hx b/std/cpp/cppia/Module.hx index 8bcbee36d27..10e2abf642f 100644 --- a/std/cpp/cppia/Module.hx +++ b/std/cpp/cppia/Module.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.cppia; +package cpp.cppia; @:native("hx::CppiaLoadedModule") @:build(cpp.cppia.HostClasses.include()) -extern class Module -{ - @:native("__scriptable_cppia_from_string") - public static function fromString(sourceCode:String) : Module; - public function boot():Void; - public function run():Void; - public function resolveClass(inName:String):Class; -} +extern class Module { + @:native("__scriptable_cppia_from_string") + public static function fromString(sourceCode:String):Module; + @:native("__scriptable_cppia_from_data") + public static function fromData(data:haxe.io.BytesData):Module; + public function boot():Void; + public function run():Void; + public function resolveClass(inName:String):Class; +} diff --git a/std/cpp/link/StaticMysql.hx b/std/cpp/link/StaticMysql.hx index bf6a487f444..39c58742fde 100644 --- a/std/cpp/link/StaticMysql.hx +++ b/std/cpp/link/StaticMysql.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,25 +19,22 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.link; -#if (hxcpp_api_level>=330) -class StaticMysql { } +#if (hxcpp_api_level >= 330) +class StaticMysql {} #else - -@:cppFileCode( 'extern "C" int mysql_register_prims();') +@:cppFileCode('extern "C" int mysql_register_prims();') @:buildXml(" ") -@:keep class StaticMysql -{ - static function __init__() - { - untyped __cpp__("mysql_register_prims();"); - } +@:keep class StaticMysql { + static function __init__() { + untyped __cpp__("mysql_register_prims();"); + } } - #end diff --git a/std/cpp/link/StaticRegexp.hx b/std/cpp/link/StaticRegexp.hx index 9e470c188c9..e9a984d0b5e 100644 --- a/std/cpp/link/StaticRegexp.hx +++ b/std/cpp/link/StaticRegexp.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,24 +19,21 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.link; -#if (hxcpp_api_level>=330) -class StaticRegexp { } +#if (hxcpp_api_level >= 330) +class StaticRegexp {} #else - -@:cppFileCode( 'extern "C" int regexp_register_prims();') +@:cppFileCode('extern "C" int regexp_register_prims();') @:buildXml(" ") -@:keep class StaticRegexp -{ - static function __init__() - { - untyped __cpp__("regexp_register_prims();"); - } +@:keep class StaticRegexp { + static function __init__() { + untyped __cpp__("regexp_register_prims();"); + } } - #end diff --git a/std/cpp/link/StaticSqlite.hx b/std/cpp/link/StaticSqlite.hx index dcc34722e73..23e0ded09fd 100644 --- a/std/cpp/link/StaticSqlite.hx +++ b/std/cpp/link/StaticSqlite.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,25 +19,22 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.link; -#if (hxcpp_api_level>=330) -class StaticSqlite { } +#if (hxcpp_api_level >= 330) +class StaticSqlite {} #else - -@:cppFileCode( 'extern "C" int sqlite_register_prims();') +@:cppFileCode('extern "C" int sqlite_register_prims();') @:buildXml(" ") -@:keep class StaticSqlite -{ - static function __init__() - { - untyped __cpp__("sqlite_register_prims();"); - } +@:keep class StaticSqlite { + static function __init__() { + untyped __cpp__("sqlite_register_prims();"); + } } - #end diff --git a/std/cpp/link/StaticStd.hx b/std/cpp/link/StaticStd.hx index d65097c3d58..ca7b46fbb1e 100644 --- a/std/cpp/link/StaticStd.hx +++ b/std/cpp/link/StaticStd.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,25 +19,22 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.link; -#if (hxcpp_api_level>=330) -class StaticStd { } +#if (hxcpp_api_level >= 330) +class StaticStd {} #else - -@:cppFileCode( 'extern "C" int std_register_prims();') +@:cppFileCode('extern "C" int std_register_prims();') @:buildXml(" ") -@:keep class StaticStd -{ - static function __init__() - { - untyped __cpp__("std_register_prims();"); - } +@:keep class StaticStd { + static function __init__() { + untyped __cpp__("std_register_prims();"); + } } - #end diff --git a/std/cpp/link/StaticZlib.hx b/std/cpp/link/StaticZlib.hx index ef71a56818e..a47741f0d8f 100644 --- a/std/cpp/link/StaticZlib.hx +++ b/std/cpp/link/StaticZlib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,25 +19,21 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.link; -#if (hxcpp_api_level>=330) -class StaticZlib { } +#if (hxcpp_api_level >= 330) +class StaticZlib {} #else - -@:cppFileCode( 'extern "C" int zlib_register_prims();') +@:cppFileCode('extern "C" int zlib_register_prims();') @:buildXml(" ") -@:keep class StaticZlib -{ - static function __init__() - { - untyped __cpp__("zlib_register_prims();"); - } +@:keep class StaticZlib { + static function __init__() { + untyped __cpp__("zlib_register_prims();"); + } } - #end - diff --git a/std/cpp/net/Poll.hx b/std/cpp/net/Poll.hx index 58a502d4a84..fb7dbf70901 100644 --- a/std/cpp/net/Poll.hx +++ b/std/cpp/net/Poll.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,36 +19,39 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.net; + import sys.net.Socket; import cpp.NativeSocket; class Poll { + var mPollHandle:Dynamic; - var mPollHandle : Dynamic; - public var readIndexes : Array; - public var writeIndexes : Array; + public var readIndexes:Array; + public var writeIndexes:Array; - public function new( n : Int ) { + public function new(n:Int) { mPollHandle = NativeSocket.socket_poll_alloc(n); readIndexes = []; writeIndexes = []; } - public function prepare( read : Array, write : Array ) { - var k = NativeSocket.socket_poll_prepare(mPollHandle,read,write); + public function prepare(read:Array, write:Array) { + var k = NativeSocket.socket_poll_prepare(mPollHandle, read, write); readIndexes = k[0]; writeIndexes = k[1]; } - public function events( ?t : Float ) { - if (t==null) t=-1.0; - NativeSocket.socket_poll_events(mPollHandle,t); + public function events(?t:Float) { + if (t == null) + t = -1.0; + NativeSocket.socket_poll_events(mPollHandle, t); } - public function poll( a : Array, ?t : Float ) : Array { - if (t==null) t=-1.0; - return NativeSocket.socket_poll(a,mPollHandle,t); + public function poll(a:Array, ?t:Float):Array { + if (t == null) + t = -1.0; + return NativeSocket.socket_poll(a, mPollHandle, t); } - } diff --git a/std/cpp/net/ThreadServer.hx b/std/cpp/net/ThreadServer.hx index d7faee94562..cecdb5f3aa6 100644 --- a/std/cpp/net/ThreadServer.hx +++ b/std/cpp/net/ThreadServer.hx @@ -1,24 +1,25 @@ /* -* Copyright (C)2005-2017 Haxe Foundation -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -* DEALINGS IN THE SOFTWARE. -*/ + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package cpp.net; import cpp.vm.Thread; @@ -26,339 +27,337 @@ import cpp.net.Poll; import cpp.vm.Lock; private typedef ThreadInfos = { - var id : Int; - var t : Thread; - var p : Poll; - var socks : Array; + var id:Int; + var t:Thread; + var p:Poll; + var socks:Array; } private typedef ClientInfos = { - var client : Client; - var sock : sys.net.Socket; - var thread : ThreadInfos; - var buf : haxe.io.Bytes; - var bufpos : Int; + var client:Client; + var sock:sys.net.Socket; + var thread:ThreadInfos; + var buf:haxe.io.Bytes; + var bufpos:Int; } /** - The ThreadServer can be used to easily create a multithreaded server where each thread polls multiple connections. - To use it, at a minimum you must override or rebind clientConnected, readClientMessage, and clientMessage and you must define your Client and Message. + The ThreadServer can be used to easily create a multithreaded server where each thread polls multiple connections. + To use it, at a minimum you must override or rebind clientConnected, readClientMessage, and clientMessage and you must define your Client and Message. **/ -class ThreadServer { - - var threads : Array; - var sock : sys.net.Socket; - var worker : Thread; - var timer : Thread; - - /** - Number of total connections the server will accept. - **/ - public var listen : Int; - - /** - Number of server threads. - **/ - public var nthreads : Int; - - /** - Polling timeout. - **/ - public var connectLag : Float; - - /** - Stream to send error messages. - **/ - public var errorOutput : haxe.io.Output; - - /** - Space allocated to buffers when they are created. - **/ - public var initialBufferSize : Int; - - /** - Maximum size of buffered data read from a socket. An exception is thrown if the buffer exceeds this value. - **/ - public var maxBufferSize : Int; - - /** - Minimum message size. - **/ - public var messageHeaderSize : Int; - - /** - Time between calls to update. - **/ - public var updateTime : Float; - - /** - The most sockets a thread will handle. - **/ - public var maxSockPerThread : Int; - - /** - Creates a ThreadServer. - **/ - public function new() { - threads = new Array(); - nthreads = if( Sys.systemName() == "Windows" ) 150 else 10; - messageHeaderSize = 1; - listen = 10; - connectLag = 0.5; - errorOutput = Sys.stderr(); - initialBufferSize = (1 << 10); - maxBufferSize = (1 << 16); - maxSockPerThread = 64; - updateTime = 1; - } - - function runThread(t) { - while( true ) { - try { - loopThread(t); - } catch( e : Dynamic ) { - logError(e); - } - } - } - - function readClientData( c : ClientInfos ) { - var available = c.buf.length - c.bufpos; - if( available == 0 ) { - var newsize = c.buf.length * 2; - if( newsize > maxBufferSize ) { - newsize = maxBufferSize; - if( c.buf.length == maxBufferSize ) - throw "Max buffer size reached"; - } - var newbuf = haxe.io.Bytes.alloc(newsize); - newbuf.blit(0,c.buf,0,c.bufpos); - c.buf = newbuf; - available = newsize - c.bufpos; - } - var bytes = c.sock.input.readBytes(c.buf,c.bufpos,available); - var pos = 0; - var len = c.bufpos + bytes; - while( len >= messageHeaderSize ) { - var m = readClientMessage(c.client,c.buf,pos,len); - if( m == null ) - break; - pos += m.bytes; - len -= m.bytes; - work(clientMessage.bind(c.client,m.msg)); - } - if( pos > 0 ) - c.buf.blit(0,c.buf,pos,len); - c.bufpos = len; - } - - function loopThread( t : ThreadInfos ) { - if( t.socks.length > 0 ) - for( s in t.p.poll(t.socks,connectLag) ) { - var infos : ClientInfos = s.custom; - try { - readClientData(infos); - } catch( e : Dynamic ) { - t.socks.remove(s); - if( !Std.is(e,haxe.io.Eof) && !Std.is(e,haxe.io.Error) ) - logError(e); - work(doClientDisconnected.bind(s,infos.client)); - } - } - while( true ) { - var m : { s : sys.net.Socket, cnx : Bool } = Thread.readMessage(t.socks.length == 0); - if( m == null ) - break; - if( m.cnx ) - t.socks.push(m.s); - else if( t.socks.remove(m.s) ) { - var infos : ClientInfos = m.s.custom; - work(doClientDisconnected.bind(m.s,infos.client)); - } - } - } - - function doClientDisconnected(s:sys.net.Socket,c) { - try s.close() catch( e : Dynamic ) {}; - clientDisconnected(c); - } - - function runWorker() { - while( true ) { - var f = Thread.readMessage(true); - try { - f(); - } catch( e : Dynamic ) { - logError(e); - } - try { - afterEvent(); - } catch( e : Dynamic ) { - logError(e); - } - } - } - - /** - Internally used to delegate something to the worker thread. - **/ - public function work( f : Void -> Void ) { - worker.sendMessage(f); - } - - function logError( e : Dynamic ) { - var stack = haxe.CallStack.exceptionStack(); - if( Thread.current() == worker ) - onError(e,stack); - else - work(onError.bind(e,stack)); - } - - function addClient( sock : sys.net.Socket ) { - var start = Std.random(nthreads); - for( i in 0...nthreads ) { - var t = threads[(start + i)%nthreads]; - if( t.socks.length < maxSockPerThread ) { - var infos : ClientInfos = { - thread : t, - client : clientConnected(sock), - sock : sock, - buf : haxe.io.Bytes.alloc(initialBufferSize), - bufpos : 0, - }; - sock.custom = infos; - infos.thread.t.sendMessage({ s : sock, cnx : true }); - return; - } - } - refuseClient(sock); - } - - function refuseClient( sock : sys.net.Socket) { - // we have reached maximum number of active clients - sock.close(); - } - - function runTimer() { - var l = new Lock(); - while( true ) { - l.wait(updateTime); - work(update); - } - } - - function init() { - worker = Thread.create(runWorker); - timer = Thread.create(runTimer); - for( i in 0...nthreads ) { - var t = { - id : i, - t : null, - socks : new Array(), - p : new Poll(maxSockPerThread), - }; - threads.push(t); - t.t = Thread.create(runThread.bind(t)); - } - } - - /** - Called when the server gets a new connection. - **/ - public function addSocket( s : sys.net.Socket ) { - s.setBlocking(false); - work(addClient.bind(s)); - } - - /** - Start the server at the specified host and port. - **/ - public function run( host, port ) { - sock = new sys.net.Socket(); - sock.bind(new sys.net.Host(host),port); - sock.listen(listen); - init(); - while( true ) { - try { - addSocket(sock.accept()); - } catch( e : Dynamic ) { - logError(e); - } - } - } - - /** - Send data to a client. - **/ - public function sendData( s : sys.net.Socket, data : String ) { - try { - s.write(data); - } catch( e : Dynamic ) { - stopClient(s); - } - } - - /** - Shutdown a client's connection and remove them from the server. - **/ - public function stopClient( s : sys.net.Socket ) { - var infos : ClientInfos = s.custom; - try s.shutdown(true,true) catch( e : Dynamic ) { }; - infos.thread.t.sendMessage({ s : s, cnx : false }); - } - - // --- CUSTOMIZABLE API --- - - /** - Called when an error has ocurred. - **/ - public dynamic function onError( e : Dynamic, stack ) { - var estr = try Std.string(e) catch( e2 : Dynamic ) "???" + try "["+Std.string(e2)+"]" catch( e : Dynamic ) ""; - errorOutput.writeString( estr + "\n" + haxe.CallStack.toString(stack) ); - errorOutput.flush(); - } - - /** - Called when a client connects. Returns a client object. - **/ - public dynamic function clientConnected( s : sys.net.Socket ) : Client { - return null; - } - - /** - Called when a client disconnects or an error forces the connection to close. - **/ - public dynamic function clientDisconnected( c : Client ) { - } - - /** - Called when data has been read from a socket. This method should try to extract a message from the buffer. - The available data resides in buf, starts at pos, and is len bytes wide. Return the new message and the number of bytes read from the buffer. - If no message could be read, return null. - **/ - public dynamic function readClientMessage( c : Client, buf : haxe.io.Bytes, pos : Int, len : Int ) : { msg : Message, bytes : Int } { - return { - msg : null, - bytes : len, - }; - } - - /** - Called when a message has been recieved. Message handling code should go here. - **/ - public dynamic function clientMessage( c : Client, msg : Message ) { - } - - /** - This method is called periodically. It can be used to do server maintenance. - **/ - public dynamic function update() { - } - - /** - Called after a client connects, disconnects, a message is received, or an update is performed. - **/ - public dynamic function afterEvent() { - } - +class ThreadServer { + var threads:Array; + var sock:sys.net.Socket; + var worker:Thread; + var timer:Thread; + + /** + Number of total connections the server will accept. + **/ + public var listen:Int; + + /** + Number of server threads. + **/ + public var nthreads:Int; + + /** + Polling timeout. + **/ + public var connectLag:Float; + + /** + Stream to send error messages. + **/ + public var errorOutput:haxe.io.Output; + + /** + Space allocated to buffers when they are created. + **/ + public var initialBufferSize:Int; + + /** + Maximum size of buffered data read from a socket. An exception is thrown if the buffer exceeds this value. + **/ + public var maxBufferSize:Int; + + /** + Minimum message size. + **/ + public var messageHeaderSize:Int; + + /** + Time between calls to update. + **/ + public var updateTime:Float; + + /** + The most sockets a thread will handle. + **/ + public var maxSockPerThread:Int; + + /** + Creates a ThreadServer. + **/ + public function new() { + threads = new Array(); + nthreads = if (Sys.systemName() == "Windows") 150 else 10; + messageHeaderSize = 1; + listen = 10; + connectLag = 0.5; + errorOutput = Sys.stderr(); + initialBufferSize = (1 << 10); + maxBufferSize = (1 << 16); + maxSockPerThread = 64; + updateTime = 1; + } + + function runThread(t) { + while (true) { + try { + loopThread(t); + } catch (e:Dynamic) { + logError(e); + } + } + } + + function readClientData(c:ClientInfos) { + var available = c.buf.length - c.bufpos; + if (available == 0) { + var newsize = c.buf.length * 2; + if (newsize > maxBufferSize) { + newsize = maxBufferSize; + if (c.buf.length == maxBufferSize) + throw "Max buffer size reached"; + } + var newbuf = haxe.io.Bytes.alloc(newsize); + newbuf.blit(0, c.buf, 0, c.bufpos); + c.buf = newbuf; + available = newsize - c.bufpos; + } + var bytes = c.sock.input.readBytes(c.buf, c.bufpos, available); + var pos = 0; + var len = c.bufpos + bytes; + while (len >= messageHeaderSize) { + var m = readClientMessage(c.client, c.buf, pos, len); + if (m == null) + break; + pos += m.bytes; + len -= m.bytes; + work(clientMessage.bind(c.client, m.msg)); + } + if (pos > 0) + c.buf.blit(0, c.buf, pos, len); + c.bufpos = len; + } + + function loopThread(t:ThreadInfos) { + if (t.socks.length > 0) + for (s in t.p.poll(t.socks, connectLag)) { + var infos:ClientInfos = s.custom; + try { + readClientData(infos); + } catch (e:Dynamic) { + t.socks.remove(s); + if (!Std.is(e, haxe.io.Eof) && !Std.is(e, haxe.io.Error)) + logError(e); + work(doClientDisconnected.bind(s, infos.client)); + } + } + while (true) { + var m:{s:sys.net.Socket, cnx:Bool} = Thread.readMessage(t.socks.length == 0); + if (m == null) + break; + if (m.cnx) + t.socks.push(m.s); + else if (t.socks.remove(m.s)) { + var infos:ClientInfos = m.s.custom; + work(doClientDisconnected.bind(m.s, infos.client)); + } + } + } + + function doClientDisconnected(s:sys.net.Socket, c) { + try + s.close() + catch (e:Dynamic) {}; + clientDisconnected(c); + } + + function runWorker() { + while (true) { + var f = Thread.readMessage(true); + try { + f(); + } catch (e:Dynamic) { + logError(e); + } + try { + afterEvent(); + } catch (e:Dynamic) { + logError(e); + } + } + } + + /** + Internally used to delegate something to the worker thread. + **/ + public function work(f:Void->Void) { + worker.sendMessage(f); + } + + function logError(e:Dynamic) { + var stack = haxe.CallStack.exceptionStack(); + if (Thread.current() == worker) + onError(e, stack); + else + work(onError.bind(e, stack)); + } + + function addClient(sock:sys.net.Socket) { + var start = Std.random(nthreads); + for (i in 0...nthreads) { + var t = threads[(start + i) % nthreads]; + if (t.socks.length < maxSockPerThread) { + var infos:ClientInfos = { + thread: t, + client: clientConnected(sock), + sock: sock, + buf: haxe.io.Bytes.alloc(initialBufferSize), + bufpos: 0, + }; + sock.custom = infos; + infos.thread.t.sendMessage({s: sock, cnx: true}); + return; + } + } + refuseClient(sock); + } + + function refuseClient(sock:sys.net.Socket) { + // we have reached maximum number of active clients + sock.close(); + } + + function runTimer() { + var l = new Lock(); + while (true) { + l.wait(updateTime); + work(update); + } + } + + function init() { + worker = Thread.create(runWorker); + timer = Thread.create(runTimer); + for (i in 0...nthreads) { + var t = { + id: i, + t: null, + socks: new Array(), + p: new Poll(maxSockPerThread), + }; + threads.push(t); + t.t = Thread.create(runThread.bind(t)); + } + } + + /** + Called when the server gets a new connection. + **/ + public function addSocket(s:sys.net.Socket) { + s.setBlocking(false); + work(addClient.bind(s)); + } + + /** + Start the server at the specified host and port. + **/ + public function run(host, port) { + sock = new sys.net.Socket(); + sock.bind(new sys.net.Host(host), port); + sock.listen(listen); + init(); + while (true) { + try { + addSocket(sock.accept()); + } catch (e:Dynamic) { + logError(e); + } + } + } + + /** + Send data to a client. + **/ + public function sendData(s:sys.net.Socket, data:String) { + try { + s.write(data); + } catch (e:Dynamic) { + stopClient(s); + } + } + + /** + Shutdown a client's connection and remove them from the server. + **/ + public function stopClient(s:sys.net.Socket) { + var infos:ClientInfos = s.custom; + try + s.shutdown(true, true) + catch (e:Dynamic) {}; + infos.thread.t.sendMessage({s: s, cnx: false}); + } + + // --- CUSTOMIZABLE API --- + + /** + Called when an error has ocurred. + **/ + public dynamic function onError(e:Dynamic, stack) { + var estr = try Std.string(e) catch (e2:Dynamic) "???" + try "[" + Std.string(e2) + "]" catch (e:Dynamic) ""; + errorOutput.writeString(estr + "\n" + haxe.CallStack.toString(stack)); + errorOutput.flush(); + } + + /** + Called when a client connects. Returns a client object. + **/ + public dynamic function clientConnected(s:sys.net.Socket):Client { + return null; + } + + /** + Called when a client disconnects or an error forces the connection to close. + **/ + public dynamic function clientDisconnected(c:Client) {} + + /** + Called when data has been read from a socket. This method should try to extract a message from the buffer. + The available data resides in buf, starts at pos, and is len bytes wide. Return the new message and the number of bytes read from the buffer. + If no message could be read, return null. + **/ + public dynamic function readClientMessage(c:Client, buf:haxe.io.Bytes, pos:Int, len:Int):{msg:Message, bytes:Int} { + return { + msg: null, + bytes: len, + }; + } + + /** + Called when a message has been recieved. Message handling code should go here. + **/ + public dynamic function clientMessage(c:Client, msg:Message) {} + + /** + This method is called periodically. It can be used to do server maintenance. + **/ + public dynamic function update() {} + + /** + Called after a client connects, disconnects, a message is received, or an update is performed. + **/ + public dynamic function afterEvent() {} } diff --git a/std/cpp/objc/NSData.hx b/std/cpp/objc/NSData.hx index 9980c8bda6a..d73348cc3dd 100644 --- a/std/cpp/objc/NSData.hx +++ b/std/cpp/objc/NSData.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,33 +19,34 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.objc; -@:native("NSData") @:objc extern class NSDataData { } +@:native("NSData") @:objc extern class NSDataData {} @:objc -extern abstract NSData( NSDataData ) -{ - @:native("_hx_value_to_objc") @:extern static function to_data(b:haxe.io.BytesData) : NSData return null; - @:native("_hx_value_to_objc") @:extern static function to_data_data(b:haxe.io.BytesData) : NSDataData return null; - @:native("_hx_objc_to_bytes") @:extern static function NSDataDataToBytes(d:NSDataData) : haxe.io.BytesData return null; +extern abstract NSData(NSDataData) { + @:native("_hx_value_to_objc") extern static function to_data(b:haxe.io.BytesData):NSData; + @:native("_hx_value_to_objc") extern static function to_data_data(b:haxe.io.BytesData):NSDataData; - inline function new(d:NSDataData) this = d; + @:native("_hx_objc_to_bytes") extern static function NSDataDataToBytes(d:NSDataData):haxe.io.BytesData; - @:from @:extern - static public inline function fromBytesData(d:haxe.io.BytesData):NSData return new NSData( to_data_data(d) ); + inline function new(d:NSDataData) + this = d; - @:from @:extern - static public inline function fromBytes(d:haxe.io.Bytes):NSData return new NSData( to_data_data(d.getData()) ); + @:from extern static public inline function fromBytesData(d:haxe.io.BytesData):NSData + return new NSData(to_data_data(d)); - @:to @:extern - public inline function toBytesData():haxe.io.BytesData return NSDataDataToBytes(this); + @:from extern static public inline function fromBytes(d:haxe.io.Bytes):NSData + return new NSData(to_data_data(d.getData())); - @:to @:extern - public inline function toBytes():haxe.io.Bytes return haxe.io.Bytes.ofData(NSDataDataToBytes(this)); + @:to extern public inline function toBytesData():haxe.io.BytesData + return NSDataDataToBytes(this); - @:to @:extern public inline function toNSObject():NSObject return cast this; + @:to extern public inline function toBytes():haxe.io.Bytes + return haxe.io.Bytes.ofData(NSDataDataToBytes(this)); + @:to extern public inline function toNSObject():NSObject + return cast this; } - diff --git a/std/cpp/objc/NSDictionary.hx b/std/cpp/objc/NSDictionary.hx index a8dd97d6a15..e26ae98b656 100644 --- a/std/cpp/objc/NSDictionary.hx +++ b/std/cpp/objc/NSDictionary.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,26 +19,26 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.objc; -@:native("NSDictionary") @:objc extern class DictionaryData { } +@:native("NSDictionary") @:objc extern class DictionaryData {} @:objc -extern abstract NSDictionary( DictionaryData ) -{ - @:native("_hx_obj_to_nsdictionary") @:extern static function _hx_obj_to_nsdictionary(obj:Dynamic) : DictionaryData return null; - @:native("_hx_nsdictionary_to_obj") @:extern static function _hx_nsdictionary_to_obj(d:DictionaryData) : Dynamic return null; - +extern abstract NSDictionary(DictionaryData) { + @:native("_hx_obj_to_nsdictionary") extern static function _hx_obj_to_nsdictionary(obj:Dynamic):DictionaryData; - inline function new(dict:DictionaryData) this = dict; + @:native("_hx_nsdictionary_to_obj") extern static function _hx_nsdictionary_to_obj(d:DictionaryData):Dynamic; - @:from @:extern - static public inline function fromDynamic(o:Dynamic):NSDictionary return new NSDictionary( _hx_obj_to_nsdictionary(o) ); + inline function new(dict:DictionaryData) + this = dict; - @:to @:extern - public inline function toDynamic():Dynamic return _hx_nsdictionary_to_obj(this); + @:from extern static public inline function fromDynamic(o:Dynamic):NSDictionary + return new NSDictionary(_hx_obj_to_nsdictionary(o)); - @:to @:extern public inline function toNSObject():NSObject return cast this; + @:to extern public inline function toDynamic():Dynamic + return _hx_nsdictionary_to_obj(this); + @:to extern public inline function toNSObject():NSObject + return cast this; } - diff --git a/std/cpp/objc/NSError.hx b/std/cpp/objc/NSError.hx index 2510d66d96d..0cea993a368 100644 --- a/std/cpp/objc/NSError.hx +++ b/std/cpp/objc/NSError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,12 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.objc; @:objc @:native("NSError") -extern class NSError -{ - public var localizedDescription(default,null):NSString; +extern class NSError { + public var localizedDescription(default, null):NSString; } - diff --git a/std/cpp/objc/NSLog.hx b/std/cpp/objc/NSLog.hx index 9bba4c32737..19b792dfa3e 100644 --- a/std/cpp/objc/NSLog.hx +++ b/std/cpp/objc/NSLog.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,15 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.objc; -extern class NSLog -{ - @:native("NSLog") - @:overload(function(format:NSString,a0:NSObject):Void { }) - @:overload(function(format:NSString,a0:NSObject,a1:NSObject):Void { }) - public static function log(format:NSString):Void; +package cpp.objc; +extern class NSLog { + @:native("NSLog") + @:overload(function(format:NSString, a0:NSObject):Void {}) + @:overload(function(format:NSString, a0:NSObject, a1:NSObject):Void {}) + public static function log(format:NSString):Void; } - - diff --git a/std/cpp/objc/NSObject.hx b/std/cpp/objc/NSObject.hx index 9c8398d8500..6055999db02 100644 --- a/std/cpp/objc/NSObject.hx +++ b/std/cpp/objc/NSObject.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,26 +19,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.objc; -@:native("id") @:objc extern class NSObjectData { } +@:native("id") @:objc extern class NSObjectData {} @:objc -extern abstract NSObject( NSObjectData ) -{ - @:native("_hx_value_to_objc") @:extern static function _hx_value_to_objc(obj:Dynamic) : NSObject return null; - @:native("_hx_objc_to_dynamic") @:extern static function _hx_objc_to_dynamic(d:NSObjectData) : Dynamic return null; - - - inline function new(d:NSObjectData) this = d; +extern abstract NSObject(NSObjectData) { + @:native("_hx_value_to_objc") extern static function _hx_value_to_objc(obj:Dynamic):NSObject; + @:native("_hx_objc_to_dynamic") extern static function _hx_objc_to_dynamic(d:NSObjectData):Dynamic; - @:from @:extern - static public inline function fromHaxe(d:Dynamic):NSObject return _hx_value_to_objc(d); + inline function new(d:NSObjectData) + this = d; + @:from extern static public inline function fromHaxe(d:Dynamic):NSObject + return _hx_value_to_objc(d); - @:to @:extern - public inline function toHaxe():Dynamic return _hx_objc_to_dynamic(this); + @:to extern public inline function toHaxe():Dynamic + return _hx_objc_to_dynamic(this); } - - diff --git a/std/cpp/objc/NSString.hx b/std/cpp/objc/NSString.hx index c82e228bbf7..49c84878279 100644 --- a/std/cpp/objc/NSString.hx +++ b/std/cpp/objc/NSString.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,27 +19,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.objc; -@:native("NSString") @:objc extern class NSStringData { } +@:native("NSString") @:objc extern class NSStringData {} @:objc -extern abstract NSString( NSStringData ) -{ - inline function new(s:NSStringData) this = s; - @:native("(id)") @:extern static function toObject(d:NSStringData) : NSObject return null; +extern abstract NSString(NSStringData) { + inline function new(s:NSStringData) + this = s; - @:native("(NSString *)") @:extern static function castFromString(s:String) : NSString return null; - @:native("String") @:extern static function castToString(s:NSStringData) : String return null; + @:native("(id)") extern static function toObject(d:NSStringData):NSObject; + @:native("(NSString *)") extern static function castFromString(s:String):NSString; - @:from @:extern - static public inline function fromString(s:String):NSString return castFromString(s); + @:native("String") extern static function castToString(s:NSStringData):String; + @:from extern static public inline function fromString(s:String):NSString + return castFromString(s); - @:to @:extern - public inline function toString():String return castToString(this); + @:to extern public inline function toString():String + return castToString(this); - @:to @:extern public inline function toNSObject():NSObject return toObject(this); + @:to extern public inline function toNSObject():NSObject + return toObject(this); } - diff --git a/std/cpp/objc/ObjcBlock.hx b/std/cpp/objc/ObjcBlock.hx index 4075faaaa20..0b252cc3a7c 100644 --- a/std/cpp/objc/ObjcBlock.hx +++ b/std/cpp/objc/ObjcBlock.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,9 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.objc; @:objc typedef ObjcBlock = T; - - diff --git a/std/cpp/objc/Protocol.hx b/std/cpp/objc/Protocol.hx index 1c5c4d92b53..1469a0875ef 100644 --- a/std/cpp/objc/Protocol.hx +++ b/std/cpp/objc/Protocol.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,9 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.objc; @:objc -typedef Protocol = T; - - +typedef Protocol = T; diff --git a/std/cpp/rtti/FieldIntegerLookup.hx b/std/cpp/rtti/FieldIntegerLookup.hx index 86908b8c98e..c90fbae0c1d 100644 --- a/std/cpp/rtti/FieldIntegerLookup.hx +++ b/std/cpp/rtti/FieldIntegerLookup.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.rtti; /** If you implement this interface, then the backend will generate code that allows fast dynamic access to fields by integer id. This should speed up the CFFI. **/ -interface FieldIntegerLookup { -} +interface FieldIntegerLookup {} diff --git a/std/cpp/rtti/FieldNumericIntegerLookup.hx b/std/cpp/rtti/FieldNumericIntegerLookup.hx index bc04b1d30cb..3efa4443437 100644 --- a/std/cpp/rtti/FieldNumericIntegerLookup.hx +++ b/std/cpp/rtti/FieldNumericIntegerLookup.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.rtti; /** If you implement this interface, then the backend will generate code that allows fast numeric access to fields by integer id. This should speed up the CFFI. **/ -interface FieldNumericIntegerLookup { -} +interface FieldNumericIntegerLookup {} diff --git a/std/cpp/vm/Debugger.hx b/std/cpp/vm/Debugger.hx index 1a250e86425..d1411892bbc 100644 --- a/std/cpp/vm/Debugger.hx +++ b/std/cpp/vm/Debugger.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,401 +19,325 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.vm; +package cpp.vm; /** * Parameter describes a function parameter. Instances of this class are * embedded in stack frame objects to describe the function parameters that * were used in the invocation of the function that defines that stack frame. - **/ -class Parameter -{ - public var name(default, null) : String; - public var value(default, null) : Dynamic; - - public function new(name : String, value : Dynamic) - { - this.name = name; - this.value = value; - } - } +**/ +class Parameter { + public var name(default, null):String; + public var value(default, null):Dynamic; + + public function new(name:String, value:Dynamic) { + this.name = name; + this.value = value; + } +} /** * StackFrame describes one call stack frame. - **/ -class StackFrame - { - public var fileName(default, null) : String; - public var lineNumber(default, null) : Int; - public var className(default, null) : String; - public var functionName(default, null) : String; - public var parameters(default, null) : Array; - - public function new(fileName : String, lineNumber : Int, - className : String, functionName : String) - { - this.fileName = fileName; - this.lineNumber = lineNumber; - this.className = className; - this.functionName = functionName; - this.parameters = new Array(); - } - } +**/ +class StackFrame { + public var fileName(default, null):String; + public var lineNumber(default, null):Int; + public var className(default, null):String; + public var functionName(default, null):String; + public var parameters(default, null):Array; + + public function new(fileName:String, lineNumber:Int, className:String, functionName:String) { + this.fileName = fileName; + this.lineNumber = lineNumber; + this.className = className; + this.functionName = functionName; + this.parameters = new Array(); + } +} /** * ThreadInfo describes the state of a single thread. - **/ -class ThreadInfo - { - public static inline var STATUS_RUNNING = 1; - public static inline var STATUS_STOPPED_BREAK_IMMEDIATE = 2; - public static inline var STATUS_STOPPED_BREAKPOINT = 3; - public static inline var STATUS_STOPPED_UNCAUGHT_EXCEPTION = 4; - public static inline var STATUS_STOPPED_CRITICAL_ERROR = 5; - - // 0 is never a valid thread number - public var number(default, null) : Int; - public var status(default, null) : Int; - // If status is "stopped breakpoint", this is the breakpoint number - public var breakpoint(default, null) : Int; - // If status is "critical error", this describes the error - public var criticalErrorDescription(default, null) : String; - // Stack will be listed with the lowest frame first - public var stack(default, null) : Array; - - public function new(number : Int, status : Int, breakpoint : Int = -1, - criticalErrorDescription : String = null) - { - this.number = number; - this.status = status; - this.breakpoint = breakpoint; - this.criticalErrorDescription = criticalErrorDescription; - this.stack = new Array(); - } - } +**/ +class ThreadInfo { + public static inline var STATUS_RUNNING = 1; + public static inline var STATUS_STOPPED_BREAK_IMMEDIATE = 2; + public static inline var STATUS_STOPPED_BREAKPOINT = 3; + public static inline var STATUS_STOPPED_UNCAUGHT_EXCEPTION = 4; + public static inline var STATUS_STOPPED_CRITICAL_ERROR = 5; + + // 0 is never a valid thread number + public var number(default, null):Int; + public var status(default, null):Int; + // If status is "stopped breakpoint", this is the breakpoint number + public var breakpoint(default, null):Int; + // If status is "critical error", this describes the error + public var criticalErrorDescription(default, null):String; + // Stack will be listed with the lowest frame first + public var stack(default, null):Array; + + public function new(number:Int, status:Int, breakpoint:Int = -1, criticalErrorDescription:String = null) { + this.number = number; + this.status = status; + this.breakpoint = breakpoint; + this.criticalErrorDescription = criticalErrorDescription; + this.stack = new Array(); + } +} /** * This class wraps the hxcpp C++ implementation to provide a Haxe interface * to the low level debugging features - **/ -class Debugger - { - public static inline var THREAD_CREATED = 1; - public static inline var THREAD_TERMINATED = 2; - public static inline var THREAD_STARTED = 3; - public static inline var THREAD_STOPPED = 4; - - public static inline var STEP_INTO = 1; - public static inline var STEP_OVER = 2; - public static inline var STEP_OUT = 3; - - // This tagging value is returned by getStackVariableValue() and - // setStackVariableValue if the requested value does not exist at the - // requested stack frame - public static var NONEXISTENT_VALUE = new String("NONEXISTENT_VALUE"); - // This tagging value is returned by getStackVariableValue and - // setStackVariableValue if the stack variable that is being set is on a - // thread that is running, in which case the set does not take place. - public static var THREAD_NOT_STOPPED = new String("THREAD_NOT_STOPPED"); - - /** - * Sets the handler callback to be made when asynchronous events occur, - * specifically, when threads are created, terminated, started, or - * stopped. The calling thread becomes the "debugger" thread, which means - * that it will be discluded from any breakpoints and will not be reported - * on by any thread reporting requests. - * - * Be aware that this callback is made asynchronously and possibly by - * multiple threads simultaneously. - * - * Setting this to null prevents further callbacks. - * - * Throws a string exception if the program does not support debugging - * because it was not compiled with the HXCPP_DEBUGGER flag set. - * - * @param handler is a function that will be called back by asynchronous - * thread events. Note that this function is called directly from - * the thread experiencing the event and the handler should return - * quickly to avoid blocking the calling thread unnecessarily. - * The parameters to handler are: - * - threadNumber, the thread number of the event - * - event, one of THREAD_CREATED, THREAD_TERMINATED, - * 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, - * undefined if event is not THREAD_STOPPED - * - functionName, the function name at which the thread is - * stopped, undefined if event is not THREAD_STOPPED - * - fileName, the file name at which the thread is stopped, - * undefined if event is not THREAD_STOPPED - * - lineNumber, the line number at which the thread is stopped, - * undefined if event is not THREAD_STOPPED - **/ - public static function setEventNotificationHandler( - handler : Int -> Int -> Int -> String -> String -> String -> Int -> Void) - { - untyped __global__.__hxcpp_dbg_setEventNotificationHandler(handler); - } - - /** - * This can be called to turn off (and then back on) all stopping of - * debugged threads temporarily. It should only be used by classes that - * actually implement the debugger to hide themselves from the debugger as - * necessary. - **/ - public static function enableCurrentThreadDebugging(enabled : Bool) - { - untyped __global__.__hxcpp_dbg_enableCurrentThreadDebugging(enabled); - } - - /** - * Returns the thread number of the calling thread. - * - * @return the thread number of the calling thread. - **/ - public static function getCurrentThreadNumber() : Int - { - return untyped __global__.__hxcpp_dbg_getCurrentThreadNumber(); +**/ +class Debugger { + public static inline var THREAD_CREATED = 1; + public static inline var THREAD_TERMINATED = 2; + public static inline var THREAD_STARTED = 3; + public static inline var THREAD_STOPPED = 4; + + public static inline var STEP_INTO = 1; + public static inline var STEP_OVER = 2; + public static inline var STEP_OUT = 3; + + // This tagging value is returned by getStackVariableValue() and + // setStackVariableValue if the requested value does not exist at the + // requested stack frame + public static var NONEXISTENT_VALUE = new String("NONEXISTENT_VALUE"); + // This tagging value is returned by getStackVariableValue and + // setStackVariableValue if the stack variable that is being set is on a + // thread that is running, in which case the set does not take place. + public static var THREAD_NOT_STOPPED = new String("THREAD_NOT_STOPPED"); + + /** + * Sets the handler callback to be made when asynchronous events occur, + * specifically, when threads are created, terminated, started, or + * stopped. The calling thread becomes the "debugger" thread, which means + * that it will be discluded from any breakpoints and will not be reported + * on by any thread reporting requests. + * + * Be aware that this callback is made asynchronously and possibly by + * multiple threads simultaneously. + * + * Setting this to null prevents further callbacks. + * + * Throws a string exception if the program does not support debugging + * because it was not compiled with the HXCPP_DEBUGGER flag set. + * + * @param handler is a function that will be called back by asynchronous + * thread events. Note that this function is called directly from + * the thread experiencing the event and the handler should return + * quickly to avoid blocking the calling thread unnecessarily. + * The parameters to handler are: + * - threadNumber, the thread number of the event + * - event, one of THREAD_CREATED, THREAD_TERMINATED, + * 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, + * undefined if event is not THREAD_STOPPED + * - functionName, the function name at which the thread is + * stopped, undefined if event is not THREAD_STOPPED + * - fileName, the file name at which the thread is stopped, + * undefined if event is not THREAD_STOPPED + * - lineNumber, the line number at which the thread is stopped, + * undefined if event is not THREAD_STOPPED + **/ + public static function setEventNotificationHandler(handler:Int->Int->Int->String->String->String->Int->Void) { + untyped __global__.__hxcpp_dbg_setEventNotificationHandler(handler); } - /** - * Returns the set of source files known to the debugger. This is a copy - * of the original array and could be quite large. The caller should - * cache this value to avoid multiple copies needing to be made. - * - * @return the set of source files known to the debugger. - **/ - public static function getFiles() : Array - { - return untyped __global__.__hxcpp_dbg_getFiles(); - } - - - /** - * Returns the full paths of the set of source files known to the debugger. - * This is a copy of the original array and could be quite large. - * It is possible that this set will be empty, in which case the full paths are not known. - * The index of these files matches the index from "getFiles", so the full path for - * a given short path can be calculated. - * - * @return the known full paths of the set of source files - **/ - public static function getFilesFullPath() : Array - { - return untyped __global__.__hxcpp_dbg_getFilesFullPath(); - } - - /** - * Returns the set of class names of all classes known to the debugger. - * This is a copy of the original array and could be quite large. The - * caller should cache this value to avoid multiple copies needing to be - * made. - * - * @return the set of class names of all classes known to the debugger. - **/ - public static function getClasses() : Array - { - return untyped __global__.__hxcpp_dbg_getClasses(); - } - - /** - * Returns a ThreadInfo object describing every thread that existed at the - * moment that the call was made, except for the debugger thread. - **/ - public static function getThreadInfos() : Array - { - return untyped __global__.__hxcpp_dbg_getThreadInfos(); - } - - /** - * Returns a ThreadInfo object describing a single thread, or null if - * there is no such thread or the thread queried about was the debugger - * thread and unsafe was not true. - **/ - public static function getThreadInfo(threadNumber : Int, - unsafe : Bool) : ThreadInfo - { - return untyped __global__.__hxcpp_dbg_getThreadInfo - (threadNumber, unsafe); - } - - /** - * Adds a new file:line breakpoint. The breakpoint number of the newly - * added breakpoint is returned. - **/ - public static function addFileLineBreakpoint(file : String, - line : Int) : Int - { - return untyped __global__.__hxcpp_dbg_addFileLineBreakpoint - (file, line); - } - - /** - * Adds a new class:function breakpoint. The breakpoint number of the - * newly added breakpoint is returned. - **/ - public static function addClassFunctionBreakpoint(className : String, - functionName : String) : Int - { - return untyped __global__.__hxcpp_dbg_addClassFunctionBreakpoint - (className, functionName); - } - - /** - * Deletes a breakpoint, or all breakpoints. - **/ - public static function deleteBreakpoint(number : Null) - { - if (number == null) { - untyped __global__.__hxcpp_dbg_deleteAllBreakpoints(); - } - else { - untyped __global__.__hxcpp_dbg_deleteBreakpoint - (cast (number, Int)); - } - } - - /** - * Breaks all threads except the debugger thread (which should be the same - * as the calling thread!). - * - * If `wait` is true, waits up to 2 seconds for all threads to be broken. - * Threads which are in blocking system calls and cannot break after 2 - * seconds remain running when this function returns. - **/ - public static function breakNow(wait : Bool = true) - { - untyped __global__.__hxcpp_dbg_breakNow(wait); - } - - /** - * Continue execution of all stopped threads. If specialThreadNumber - * is a valid thread number, then it will be continued past - * `continueCount` breakpoints instead of just 1 like all of the other - * threads. - **/ - public static function continueThreads(specialThreadNumber : Int, - continueCount : Int) - { - untyped __global__.__hxcpp_dbg_continueThreads - (specialThreadNumber, continueCount); - } - - /** - * Single steps the given thread. - **/ - public static function stepThread(threadNumber : Int, - stepType : Int, - stepCount : Int = 1) - { - untyped __global__.__hxcpp_dbg_stepThread - (threadNumber, stepType, stepCount); - } - - /** - * Returns the list of local variables (including "this", function - * arguments, and local variables) visible to the given thread at the - * given stack frame. - * - * Returns a list with a single entry, THREAD_NOT_STOPPED, if the - * thread is not stopped and thus variables cannot be fetched and - * unsafe is not true. - * - * @return the list of local variables (including "this", function - * arguments, and local variables) visible to the given thread at - * the given stack frame. - **/ - public static function getStackVariables(threadNumber : Int, - stackFrameNumber : Int, - unsafe : Bool) : Array - { - return untyped __global__.__hxcpp_dbg_getStackVariables - (threadNumber, stackFrameNumber, unsafe, THREAD_NOT_STOPPED); - } - - /** - * Returns the value of a stack variable, or NONEXISTENT_VALUE if the - * requested value does not exist. If the thread is actively running - * and unsafe is not true, returns THREAD_NOT_STOPPED. - **/ - public static function getStackVariableValue(threadNumber : Int, - stackFrameNumber : Int, - name : String, - unsafe : Bool) : Dynamic - { - return untyped __global__.__hxcpp_dbg_getStackVariableValue - (threadNumber, stackFrameNumber, name, unsafe, NONEXISTENT_VALUE, - THREAD_NOT_STOPPED); - } - - /** - * Sets the value of a stack variable and returns that value. If the - * variable does not exist, on the stack, this function returns - * NONEXISTENT_VALUE. If the thread is actively running and unsafe is not - * true, returns THREAD_NOT_STOPPED, and the value is not set. - **/ - public static function setStackVariableValue(threadNumber : Int, - stackFrameNumber : Int, - name : String, - value : Dynamic, - unsafe : Bool) : Dynamic - { - return untyped __global__.__hxcpp_dbg_setStackVariableValue - (threadNumber, stackFrameNumber, name, value, unsafe, - NONEXISTENT_VALUE, THREAD_NOT_STOPPED); - } - - // The hxcpp runtime calls back through these functions to create Haxe - // objects as needed, which allows the C++ implementation code to create - // Haxe objects without having to actually know the structure of those - // objects - private static function __init__() - { - untyped __global__.__hxcpp_dbg_setNewParameterFunction - ( - function (name : String, value : Dynamic) : Dynamic { - return new Parameter(name, value); - } - ); - - untyped __global__.__hxcpp_dbg_setNewStackFrameFunction - ( - function (fileName : String, lineNumber : Int, - className : String, functionName : String) - { - return new StackFrame(fileName, lineNumber, - className, functionName); - } - ); - - untyped __global__.__hxcpp_dbg_setNewThreadInfoFunction - ( - function (number : Int, status : Int, breakpoint : Int, - criticalErrorDescription : String) : Dynamic { - return new ThreadInfo(number, status, breakpoint, - criticalErrorDescription); - } - ); - - untyped __global__.__hxcpp_dbg_setAddParameterToStackFrameFunction - ( - function(inStackFrame : Dynamic, inParameter : Dynamic) { - var stackFrame : StackFrame = cast inStackFrame; - var parameter : Parameter = cast inParameter; - stackFrame.parameters.push(parameter); - } - ); - - untyped __global__.__hxcpp_dbg_setAddStackFrameToThreadInfoFunction - ( - function(inThreadInfo : Dynamic, inStackFrame : Dynamic) { - var threadInfo : ThreadInfo = cast inThreadInfo; - var stackFrame : StackFrame = cast inStackFrame; - threadInfo.stack.push(stackFrame); - } - ); - } -} + /** + * This can be called to turn off (and then back on) all stopping of + * debugged threads temporarily. It should only be used by classes that + * actually implement the debugger to hide themselves from the debugger as + * necessary. + **/ + public static function enableCurrentThreadDebugging(enabled:Bool) { + untyped __global__.__hxcpp_dbg_enableCurrentThreadDebugging(enabled); + } + + /** + * Returns the thread number of the calling thread. + * + * @return the thread number of the calling thread. + **/ + public static function getCurrentThreadNumber():Int { + return untyped __global__.__hxcpp_dbg_getCurrentThreadNumber(); + } + + /** + * Returns the set of source files known to the debugger. This is a copy + * of the original array and could be quite large. The caller should + * cache this value to avoid multiple copies needing to be made. + * + * @return the set of source files known to the debugger. + **/ + public static function getFiles():Array { + return untyped __global__.__hxcpp_dbg_getFiles(); + } + + /** + * Returns the full paths of the set of source files known to the debugger. + * This is a copy of the original array and could be quite large. + * It is possible that this set will be empty, in which case the full paths are not known. + * The index of these files matches the index from "getFiles", so the full path for + * a given short path can be calculated. + * + * @return the known full paths of the set of source files + **/ + public static function getFilesFullPath():Array { + return untyped __global__.__hxcpp_dbg_getFilesFullPath(); + } + + /** + * Returns the set of class names of all classes known to the debugger. + * This is a copy of the original array and could be quite large. The + * caller should cache this value to avoid multiple copies needing to be + * made. + * + * @return the set of class names of all classes known to the debugger. + **/ + public static function getClasses():Array { + return untyped __global__.__hxcpp_dbg_getClasses(); + } + + /** + * Returns a ThreadInfo object describing every thread that existed at the + * moment that the call was made, except for the debugger thread. + **/ + public static function getThreadInfos():Array { + return untyped __global__.__hxcpp_dbg_getThreadInfos(); + } + + /** + * Returns a ThreadInfo object describing a single thread, or null if + * there is no such thread or the thread queried about was the debugger + * thread and unsafe was not true. + **/ + public static function getThreadInfo(threadNumber:Int, unsafe:Bool):ThreadInfo { + return untyped __global__.__hxcpp_dbg_getThreadInfo(threadNumber, unsafe); + } + + /** + * Adds a new file:line breakpoint. The breakpoint number of the newly + * added breakpoint is returned. + **/ + public static function addFileLineBreakpoint(file:String, line:Int):Int { + return untyped __global__.__hxcpp_dbg_addFileLineBreakpoint(file, line); + } + + /** + * Adds a new class:function breakpoint. The breakpoint number of the + * newly added breakpoint is returned. + **/ + public static function addClassFunctionBreakpoint(className:String, functionName:String):Int { + return untyped __global__.__hxcpp_dbg_addClassFunctionBreakpoint(className, functionName); + } + + /** + * Deletes a breakpoint, or all breakpoints. + **/ + public static function deleteBreakpoint(number:Null) { + if (number == null) { + untyped __global__.__hxcpp_dbg_deleteAllBreakpoints(); + } else { + untyped __global__.__hxcpp_dbg_deleteBreakpoint(cast(number, Int)); + } + } + + /** + * Breaks all threads except the debugger thread (which should be the same + * as the calling thread!). + * + * If `wait` is true, waits up to 2 seconds for all threads to be broken. + * Threads which are in blocking system calls and cannot break after 2 + * seconds remain running when this function returns. + **/ + public static function breakNow(wait:Bool = true) { + untyped __global__.__hxcpp_dbg_breakNow(wait); + } + + /** + * Continue execution of all stopped threads. If specialThreadNumber + * is a valid thread number, then it will be continued past + * `continueCount` breakpoints instead of just 1 like all of the other + * threads. + **/ + public static function continueThreads(specialThreadNumber:Int, continueCount:Int) { + untyped __global__.__hxcpp_dbg_continueThreads(specialThreadNumber, continueCount); + } + /** + * Single steps the given thread. + **/ + public static function stepThread(threadNumber:Int, stepType:Int, stepCount:Int = 1) { + untyped __global__.__hxcpp_dbg_stepThread(threadNumber, stepType, stepCount); + } + + /** + * Returns the list of local variables (including "this", function + * arguments, and local variables) visible to the given thread at the + * given stack frame. + * + * Returns a list with a single entry, THREAD_NOT_STOPPED, if the + * thread is not stopped and thus variables cannot be fetched and + * unsafe is not true. + * + * @return the list of local variables (including "this", function + * arguments, and local variables) visible to the given thread at + * the given stack frame. + **/ + public static function getStackVariables(threadNumber:Int, stackFrameNumber:Int, unsafe:Bool):Array { + return untyped __global__.__hxcpp_dbg_getStackVariables(threadNumber, stackFrameNumber, unsafe, THREAD_NOT_STOPPED); + } + + /** + * Returns the value of a stack variable, or NONEXISTENT_VALUE if the + * requested value does not exist. If the thread is actively running + * and unsafe is not true, returns THREAD_NOT_STOPPED. + **/ + public static function getStackVariableValue(threadNumber:Int, stackFrameNumber:Int, name:String, unsafe:Bool):Dynamic { + return untyped __global__.__hxcpp_dbg_getStackVariableValue(threadNumber, stackFrameNumber, name, unsafe, NONEXISTENT_VALUE, THREAD_NOT_STOPPED); + } + + /** + * Sets the value of a stack variable and returns that value. If the + * variable does not exist, on the stack, this function returns + * NONEXISTENT_VALUE. If the thread is actively running and unsafe is not + * true, returns THREAD_NOT_STOPPED, and the value is not set. + **/ + public static function setStackVariableValue(threadNumber:Int, stackFrameNumber:Int, name:String, value:Dynamic, unsafe:Bool):Dynamic { + return untyped __global__.__hxcpp_dbg_setStackVariableValue(threadNumber, stackFrameNumber, name, value, unsafe, NONEXISTENT_VALUE, + THREAD_NOT_STOPPED); + } + + // The hxcpp runtime calls back through these functions to create Haxe + // objects as needed, which allows the C++ implementation code to create + // Haxe objects without having to actually know the structure of those + // objects + private static function __init__() { + untyped __global__.__hxcpp_dbg_setNewParameterFunction(function(name:String, value:Dynamic):Dynamic { + return new Parameter(name, value); + }); + + untyped __global__.__hxcpp_dbg_setNewStackFrameFunction(function(fileName:String, lineNumber:Int, className:String, functionName:String) { + return new StackFrame(fileName, lineNumber, className, functionName); + }); + + untyped __global__.__hxcpp_dbg_setNewThreadInfoFunction(function(number:Int, status:Int, breakpoint:Int, criticalErrorDescription:String):Dynamic { + return new ThreadInfo(number, status, breakpoint, criticalErrorDescription); + }); + + untyped __global__.__hxcpp_dbg_setAddParameterToStackFrameFunction(function(inStackFrame:Dynamic, inParameter:Dynamic) { + var stackFrame:StackFrame = cast inStackFrame; + var parameter:Parameter = cast inParameter; + stackFrame.parameters.push(parameter); + }); + + untyped __global__.__hxcpp_dbg_setAddStackFrameToThreadInfoFunction(function(inThreadInfo:Dynamic, inStackFrame:Dynamic) { + var threadInfo:ThreadInfo = cast inThreadInfo; + var stackFrame:StackFrame = cast inStackFrame; + threadInfo.stack.push(stackFrame); + }); + } +} diff --git a/std/cpp/vm/Deque.hx b/std/cpp/vm/Deque.hx index df6859f8581..6858dffa1bb 100644 --- a/std/cpp/vm/Deque.hx +++ b/std/cpp/vm/Deque.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,22 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.vm; - -class Deque { - var q : Dynamic; - public function new() { - q = untyped __global__.__hxcpp_deque_create(); - } - public function add( i : T ) { - untyped __global__.__hxcpp_deque_add(q,i); - } - public function push( i : T ) { - untyped __global__.__hxcpp_deque_push(q,i); - } - public function pop( block : Bool ) : Null { - return untyped __global__.__hxcpp_deque_pop(q,block); - } -} +package cpp.vm; +@:deprecated typedef Deque = sys.thread.Deque; diff --git a/std/cpp/vm/ExecutionTrace.hx b/std/cpp/vm/ExecutionTrace.hx index a9a9e579b8d..61e52b97156 100644 --- a/std/cpp/vm/ExecutionTrace.hx +++ b/std/cpp/vm/ExecutionTrace.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,20 +19,19 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.vm; -class ExecutionTrace -{ - public static function traceOff() - { - untyped __hxcpp_execution_trace(0); - } - public static function traceFunctions() - { - untyped __hxcpp_execution_trace(1); - } - public static function traceLines() - { - untyped __hxcpp_execution_trace(2); - } +package cpp.vm; + +class ExecutionTrace { + public static function traceOff() { + untyped __hxcpp_execution_trace(0); + } + + public static function traceFunctions() { + untyped __hxcpp_execution_trace(1); + } + + public static function traceLines() { + untyped __hxcpp_execution_trace(2); + } } diff --git a/std/cpp/vm/Gc.hx b/std/cpp/vm/Gc.hx index 6d5350a01f6..ce7ce885928 100644 --- a/std/cpp/vm/Gc.hx +++ b/std/cpp/vm/Gc.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,94 +19,113 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cpp.vm; -class Gc -{ - public static inline var MEM_INFO_USAGE = 0; - public static inline var MEM_INFO_RESERVED = 1; - public static inline var MEM_INFO_CURRENT = 2; - public static inline var MEM_INFO_LARGE = 3; - - - // Introduced hxcpp_api_level 310 - // Returns stats on memory usage: - // MEM_INFO_USAGE - estimate of how much is needed by program (at last collect) - // MEM_INFO_RESERVED - memory allocated for possible use - // MEM_INFO_CURRENT - memory in use, includes uncollected garbage. - // This will generally saw-tooth between USAGE and RESERVED - // MEM_INFO_LARGE - Size of separate pool used for large allocs. Included in all the above. - static public function memInfo(inWhatInfo:Int) : Int - { - return Std.int(NativeGc.memInfo(inWhatInfo)); - } - - // Returns Float - static public function memInfo64(inWhatInfo:Int) : Float - { - return NativeGc.memInfo(inWhatInfo); - } - - static public function memUsage() : Int - { - return Std.int(NativeGc.memInfo(MEM_INFO_USAGE)); - } - - static public function versionCheck() { return true; } - - static public function trace(sought:Class,printInstances:Bool=true) : Int - { - return cpp.NativeGc.nativeTrace(sought,printInstances); - } - - - #if !cppia inline #end - static public function enable(inEnable:Bool) : Void - cpp.NativeGc.enable(inEnable); - - #if !cppia inline #end - static public function run(major:Bool) : Void - cpp.NativeGc.run(major); - - #if !cppia inline #end - static public function compact() : Void - cpp.NativeGc.compact(); - - #if !cppia inline #end - static public function doNotKill(inObject:Dynamic) : Void - cpp.NativeGc.doNotKill(inObject); - - #if !cppia inline #end - static public function getNextZombie() : Dynamic - return cpp.NativeGc.getNextZombie(); - - #if !cppia inline #end - static public function safePoint() : Void - cpp.NativeGc.safePoint(); - - #if !cppia inline #end - static public function enterGCFreeZone() : Void - cpp.NativeGc.enterGCFreeZone(); - - #if !cppia inline #end - static public function exitGCFreeZone() : Void - cpp.NativeGc.exitGCFreeZone(); - - #if !cppia inline #end - static public function setMinimumFreeSpace(inBytes:Int) : Void - cpp.NativeGc.setMinimumFreeSpace(inBytes); - - #if !cppia inline #end - static public function setTargetFreeSpacePercentage(inPercentage:Int) : Void - cpp.NativeGc.setTargetFreeSpacePercentage(inPercentage); - - #if !cppia inline #end - static public function setMinimumWorkingMemory(inBytes:Int) : Void - cpp.NativeGc.setMinimumWorkingMemory(inBytes); - - #if !cppia - @:native("__hxcpp_set_finalizer") @:extern - static public function setFinalizer(inObject:T, inFinalizer:cpp.CallableVoid> ) : Void { } - #end +class Gc { + public static inline var MEM_INFO_USAGE = 0; + public static inline var MEM_INFO_RESERVED = 1; + public static inline var MEM_INFO_CURRENT = 2; + public static inline var MEM_INFO_LARGE = 3; + + /** + Introduced hxcpp_api_level 310 + + Returns stats on memory usage: + - `MEM_INFO_USAGE` - estimate of how much is needed by program (at last collect) + - `MEM_INFO_RESERVED` - memory allocated for possible use + - `MEM_INFO_CURRENT` - memory in use, includes uncollected garbage. + This will generally saw-tooth between USAGE and RESERVED + - `MEM_INFO_LARGE` - Size of separate pool used for large allocs. Included in all the above. + **/ + static public function memInfo(inWhatInfo:Int):Int { + return Std.int(NativeGc.memInfo(inWhatInfo)); + } + + // Returns Float + static public function memInfo64(inWhatInfo:Int):Float { + return NativeGc.memInfo(inWhatInfo); + } + + static public function memUsage():Int { + return Std.int(NativeGc.memInfo(MEM_INFO_USAGE)); + } + + static public function versionCheck() { + return true; + } + + static public function trace(sought:Class, printInstances:Bool = true):Int { + return cpp.NativeGc.nativeTrace(sought, printInstances); + } + + #if !cppia + inline + #end + static public function enable(inEnable:Bool):Void + cpp.NativeGc.enable(inEnable); + + #if !cppia + inline + #end + static public function run(major:Bool):Void + cpp.NativeGc.run(major); + + #if !cppia + inline + #end + static public function compact():Void + cpp.NativeGc.compact(); + + #if !cppia + inline + #end + static public function doNotKill(inObject:Dynamic):Void + cpp.NativeGc.doNotKill(inObject); + + #if !cppia + inline + #end + static public function getNextZombie():Dynamic + return cpp.NativeGc.getNextZombie(); + + #if !cppia + inline + #end + static public function safePoint():Void + cpp.NativeGc.safePoint(); + + #if !cppia + inline + #end + static public function enterGCFreeZone():Void + cpp.NativeGc.enterGCFreeZone(); + + #if !cppia + inline + #end + static public function exitGCFreeZone():Void + cpp.NativeGc.exitGCFreeZone(); + + #if !cppia + inline + #end + static public function setMinimumFreeSpace(inBytes:Int):Void + cpp.NativeGc.setMinimumFreeSpace(inBytes); + + #if !cppia + inline + #end + static public function setTargetFreeSpacePercentage(inPercentage:Int):Void + cpp.NativeGc.setTargetFreeSpacePercentage(inPercentage); + + #if !cppia + inline + #end + static public function setMinimumWorkingMemory(inBytes:Int):Void + cpp.NativeGc.setMinimumWorkingMemory(inBytes); + + #if !cppia + @:native("__hxcpp_set_finalizer") extern static public function setFinalizer(inObject:T, inFinalizer:cpp.CallableVoid>):Void; + #end } - diff --git a/std/cpp/vm/Lock.hx b/std/cpp/vm/Lock.hx index bcde565ec16..9aa46bfea77 100644 --- a/std/cpp/vm/Lock.hx +++ b/std/cpp/vm/Lock.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,19 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.vm; - -class Lock { - var l : Dynamic; - public function new() { - l = untyped __global__.__hxcpp_lock_create(); - } - public function wait( ?timeout : Float = -1) : Bool { - return untyped __global__.__hxcpp_lock_wait(l,timeout); - } - public function release() { - untyped __global__.__hxcpp_lock_release(l); - } -} +package cpp.vm; +@:deprecated typedef Lock = sys.thread.Lock; diff --git a/std/cpp/vm/Mutex.hx b/std/cpp/vm/Mutex.hx index 926e0992f9a..de23e91f291 100644 --- a/std/cpp/vm/Mutex.hx +++ b/std/cpp/vm/Mutex.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,22 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.vm; - -class Mutex { - var m : Dynamic; - public function new() { - m = untyped __global__.__hxcpp_mutex_create(); - } - public function acquire() { - untyped __global__.__hxcpp_mutex_acquire(m); - } - public function tryAcquire() : Bool { - return untyped __global__.__hxcpp_mutex_try(m); - } - public function release() { - untyped __global__.__hxcpp_mutex_release(m); - } -} +package cpp.vm; +@:deprecated typedef Mutex = sys.thread.Mutex; diff --git a/std/cpp/vm/Profiler.hx b/std/cpp/vm/Profiler.hx index 256ff70d594..8cd4e40fee3 100644 --- a/std/cpp/vm/Profiler.hx +++ b/std/cpp/vm/Profiler.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.vm; - -class Profiler -{ - static public function start(?inDumpFile:String) : Void - { - untyped __global__.__hxcpp_start_profiler(inDumpFile); - } +package cpp.vm; - static public function stop() : Void - { - untyped __global__.__hxcpp_stop_profiler(); - } +class Profiler { + static public function start(?inDumpFile:String):Void { + untyped __global__.__hxcpp_start_profiler(inDumpFile); + } + static public function stop():Void { + untyped __global__.__hxcpp_stop_profiler(); + } } - - diff --git a/std/cpp/vm/Thread.hx b/std/cpp/vm/Thread.hx index 1c23f1d1b5f..39093773162 100644 --- a/std/cpp/vm/Thread.hx +++ b/std/cpp/vm/Thread.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,52 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.vm; - -typedef ThreadHandle = Dynamic; - -class Thread { - - public var handle(default,null) : ThreadHandle; - - function new(h) { - handle = h; - } - - /** - Send a message to the thread queue. This message can be read by using `readMessage`. - **/ - public function sendMessage( msg : Dynamic ) { - untyped __global__.__hxcpp_thread_send(handle,msg); - } +package cpp.vm; - /** - Returns the current thread. - **/ - public static function current() { - return new Thread(untyped __global__.__hxcpp_thread_current()); - } - - /** - Creates a new thread that will execute the `callb` function, then exit. - **/ - public static function create( callb : Void -> Void ) { - return new Thread(untyped __global__.__hxcpp_thread_create(callb)); - } - - /** - Reads a message from the thread queue. If `block` is true, the function - blocks until a message is available. If `block` is false, the function - returns `null` if no message is available. - **/ - public static function readMessage( block : Bool ) : Dynamic { - return untyped __global__.__hxcpp_thread_read_message(block); - } - - @:keep function __compare(t) : Int { - return handle == t.handle ? 0 : 1; - } - -} - +@:deprecated typedef Thread = sys.thread.Thread; diff --git a/std/cpp/vm/Tls.hx b/std/cpp/vm/Tls.hx index 7b04453eb3b..e75d6a14fca 100644 --- a/std/cpp/vm/Tls.hx +++ b/std/cpp/vm/Tls.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,26 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.vm; - -class Tls { - - static var sFreeSlot = 0; - var mTLSID : Int; - public var value(get,set) : T; - - public function new() { - mTLSID = sFreeSlot++; - } - function get_value() : T { - return untyped __global__.__hxcpp_tls_get(mTLSID); - } - - function set_value( v : T ) { - untyped __global__.__hxcpp_tls_set(mTLSID,v); - return v; - } - -} +package cpp.vm; +@:deprecated typedef Tls = sys.thread.Tls; diff --git a/std/cpp/vm/Unsafe.hx b/std/cpp/vm/Unsafe.hx index c6a969755b1..984fd945f39 100644 --- a/std/cpp/vm/Unsafe.hx +++ b/std/cpp/vm/Unsafe.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.vm; -class Unsafe -{ - public static inline function unsafeSet(outForced:Dynamic,inValue:Dynamic) : Void - { - untyped __global__.__hxcpp_unsafe_set(outForced,inValue); - } -} +package cpp.vm; +class Unsafe { + public static inline function unsafeSet(outForced:Dynamic, inValue:Dynamic):Void { + untyped __global__.__hxcpp_unsafe_set(outForced, inValue); + } +} diff --git a/std/cpp/vm/WeakRef.hx b/std/cpp/vm/WeakRef.hx index 5f94877abc8..d61ba8cc93c 100644 --- a/std/cpp/vm/WeakRef.hx +++ b/std/cpp/vm/WeakRef.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,35 +19,29 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package cpp.vm; - -class WeakRef -{ - var ref:Dynamic; - var hardRef:Bool; +package cpp.vm; +class WeakRef { + var ref:Dynamic; + var hardRef:Bool; - public function new(inObject:T, inHard:Bool = false) - { + public function new(inObject:T, inHard:Bool = false) { hardRef = inHard; if (hardRef) - ref = inObject; - else + ref = inObject; + else ref = untyped __global__.__hxcpp_weak_ref_create(inObject); } - - public function get():T - { + public function get():T { if (hardRef) return ref; - return untyped __global__.__hxcpp_weak_ref_get(ref); + return untyped __global__.__hxcpp_weak_ref_get(ref); } - public function set(inObject:T):T - { + public function set(inObject:T):T { if (hardRef) ref = inObject; else @@ -55,9 +49,7 @@ class WeakRef return inObject; } - public function toString():String - { + public function toString():String { return "WeakRef(" + get() + ")"; } } - diff --git a/std/cpp/zip/Compress.hx b/std/cpp/zip/Compress.hx index 2316140fe2b..295337a3871 100644 --- a/std/cpp/zip/Compress.hx +++ b/std/cpp/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,8 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.zip; -#if (haxe_ver < 9000.0) +package cpp.zip; + typedef Compress = haxe.zip.Compress; -#end \ No newline at end of file diff --git a/std/cpp/zip/Flush.hx b/std/cpp/zip/Flush.hx index 71440e2bccb..f65f0146fcb 100644 --- a/std/cpp/zip/Flush.hx +++ b/std/cpp/zip/Flush.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,8 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.zip; -#if (haxe_ver < 9000.0) +package cpp.zip; + typedef Flush = haxe.zip.FlushMode; -#end \ No newline at end of file diff --git a/std/cpp/zip/Uncompress.hx b/std/cpp/zip/Uncompress.hx index 205f292aad0..6f5d3cb348a 100644 --- a/std/cpp/zip/Uncompress.hx +++ b/std/cpp/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,8 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cpp.zip; -#if (haxe_ver < 9000.0) +package cpp.zip; + typedef Uncompress = haxe.zip.Uncompress; -#end \ No newline at end of file diff --git a/std/cs/Boot.hx b/std/cs/Boot.hx index 52f6faa6dca..710c3b93f5a 100644 --- a/std/cs/Boot.hx +++ b/std/cs/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs; + import cs.internal.Exceptions; import cs.internal.FieldLookup; import cs.internal.Function; @@ -37,12 +39,10 @@ import haxe.ds.StringMap; import Reflect; @:dox(hide) -class Boot -{ - - @:keep public static function init():Void - { +class Boot { + @:keep public static function init():Void { + cs.system.Console.InputEncoding = new cs.system.text.UTF8Encoding(); + cs.system.Console.OutputEncoding = new cs.system.text.UTF8Encoding(); cs.Lib.applyCultureChanges(); } - } diff --git a/std/cs/Constraints.hx b/std/cs/Constraints.hx new file mode 100644 index 00000000000..c1caed8059d --- /dev/null +++ b/std/cs/Constraints.hx @@ -0,0 +1,55 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package cs; + +/** + The type argument must be a value type. Any value type except Nullable_1 + can be specified. + + It is intended to be used as a native cs type parameter constraint, when + using `@:nativeGen`. This constraint won't have any effect on Haxe code. + If used as a real type, the underlying type will be `Dynamic`. +**/ +@:coreType abstract CsStruct from Dynamic {} + +/** + The type argument must be a reference type. This constraint applies also to + any class, interface, delegate, or array type. + + It is intended to be used as a native cs type parameter constraint, when + using `@:nativeGen`. This constraint won't have any effect on Haxe code. + If used as a real type, the underlying type will be `Dynamic`. +**/ +@:coreType abstract CsClass from Dynamic {} + +#if (cs_ver >= "7.3") +/** + The type argument must not be a reference type and must not contain any + reference type members at any level of nesting. + + It is intended to be used as a native cs type parameter constraint, when + using `@:nativeGen`. This constraint won't have any effect on Haxe code. + If used as a real type, the underlying type will be `Dynamic`. +**/ +@:coreType abstract CsUnmanaged from Dynamic {} +#end diff --git a/std/cs/Flags.hx b/std/cs/Flags.hx index 2dcbddac117..864cc466293 100644 --- a/std/cs/Flags.hx +++ b/std/cs/Flags.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cs; + +package cs; /** Use this type to have access to the bitwise operators of C# enums that have a `cs.system.FlagsAttribute` attribute. @@ -27,95 +28,87 @@ Usage example: ```haxe - import cs.system.reflection.BindingFlags; - var binding = new Flags(BindingFlags.Public) | BindingFlags.Static | BindingFlags.NonPublic; + import cs.system.reflection.BindingFlags; + var binding = new Flags(BindingFlags.Public) | BindingFlags.Static | BindingFlags.NonPublic; ``` - **/ -abstract Flags(T) from T to T -{ - +**/ +abstract Flags(T) from T to T { /** Creates a new `Flags` type with an optional initial value. If no initial value was specified, the default enum value for an empty flags attribute is specified - **/ - @:extern inline public function new(?initial:T) + **/ + extern inline public function new(?initial:T) this = initial; /** Accessible through the bitwise OR operator (`|`). Returns a new `Flags` type with the flags passed at `flags` added to it. - **/ - @:op(A|B) @:extern inline public function add(flags:Flags):Flags - { + **/ + @:op(A | B) extern inline public function add(flags:Flags):Flags { return new Flags(underlying() | flags.underlying()); } /** Accessible through the bitwise AND operator (`&`). Returns a new `Flags` type with the flags that are set on both `this` and `flags` - **/ - @:op(A&B) @:extern inline public function bitAnd(flags:Flags):Flags - { + **/ + @:op(A & B) extern inline public function bitAnd(flags:Flags):Flags { return new Flags(underlying() & flags.underlying()); } /** Accessible through the bitwise XOR operator (`^`). - **/ - @:op(A^B) @:extern inline public function bitXor(flags:Flags):Flags - { + **/ + @:op(A ^ B) extern inline public function bitXor(flags:Flags):Flags { return new Flags(underlying() & flags.underlying()); } /** Accesible through the bitwise negation operator (`~`). Returns a new `Flags` type with all unset flags as set - but the ones that are set already. - **/ - @:op(~A) @:extern inline public function bitNeg():Flags - { + **/ + @:op(~A) extern inline public function bitNeg():Flags { return new Flags(~underlying()); } /** Returns a new `Flags` type with all flags set by `flags` unset - **/ - @:extern inline public function remove(flags:Flags):Flags - { + **/ + extern inline public function remove(flags:Flags):Flags { return new Flags(underlying() & ~flags.underlying()); } /** Returns whether `flag` is present on `this` type - **/ - @:extern inline public function has(flag:T):Bool - { + **/ + extern inline public function has(flag:T):Bool { return underlying() & new Flags(flag).underlying() != null; } /** Returns whether `this` type has any flag set by `flags` also set - **/ - @:extern inline public function hasAny(flags:Flags):Bool - { + **/ + extern inline public function hasAny(flags:Flags):Bool { return underlying() & flags.underlying() != null; } /** Returns whether `this` type has all flags set by `flags` also set - **/ - @:extern inline public function hasAll(flags:Flags):Bool - { + **/ + extern inline public function hasAll(flags:Flags):Bool { return underlying() & flags.underlying() == flags.underlying(); } - @:extern inline private function underlying():EnumUnderlying + extern inline private function underlying():EnumUnderlying return this; } -@:coreType private abstract EnumUnderlying from T to T -{ - @:op(A|B) public static function or(lhs:EnumUnderlying, rhs:EnumUnderlying):T; - @:op(A^B) public static function xor(lhs:EnumUnderlying, rhs:EnumUnderlying):T; - @:op(A&B) public static function and(lhs:EnumUnderlying, rhs:EnumUnderlying):T; +@:coreType private abstract EnumUnderlying from T to T { + @:op(A | B) public static function or(lhs:EnumUnderlying, rhs:EnumUnderlying):T; + + @:op(A ^ B) public static function xor(lhs:EnumUnderlying, rhs:EnumUnderlying):T; + + @:op(A & B) public static function and(lhs:EnumUnderlying, rhs:EnumUnderlying):T; + @:op(~A) public static function bneg(t:EnumUnderlying):T; } diff --git a/std/cs/Lib.hx b/std/cs/Lib.hx index 1e2005fc8e2..a1bfe415754 100644 --- a/std/cs/Lib.hx +++ b/std/cs/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,23 +19,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs; + import cs.system.Type; /** Platform-specific C# Library. Provides some platform-specific functions for the C# target, such as conversion from haxe types to native types and vice-versa. **/ -class Lib -{ +class Lib { private static var decimalSeparator:String; /** Changes the current culture settings to allow a consistent cross-target behavior. Currently the only change made is in regard to the decimal separator, which is always set to "." **/ - public static function applyCultureChanges():Void - { + public static function applyCultureChanges():Void { var ci = new cs.system.globalization.CultureInfo(cs.system.threading.Thread.CurrentThread.CurrentCulture.Name, true); decimalSeparator = ci.NumberFormat.NumberDecimalSeparator; ci.NumberFormat.NumberDecimalSeparator = "."; @@ -45,8 +45,7 @@ class Lib /** Reverts the culture changes to the default settings. **/ - public static function revertDefaultCulture():Void - { + public static function revertDefaultCulture():Void { var ci = new cs.system.globalization.CultureInfo(cs.system.threading.Thread.CurrentThread.CurrentCulture.Name, true); cs.system.threading.Thread.CurrentThread.CurrentCulture = ci; } @@ -57,26 +56,24 @@ class Lib If equalLengthRequired is true, the result might be a copy of an array with the correct size. **/ - @:extern inline public static function nativeArray(arr:Array, equalLengthRequired:Bool):NativeArray - { + extern inline public static function nativeArray(arr:Array, equalLengthRequired:Bool):NativeArray { var ret = new cs.NativeArray(arr.length); -#if erase_generics + #if erase_generics for (i in 0...arr.length) ret[i] = arr[i]; -#else - p_nativeArray(arr,ret); -#end + #else + p_nativeArray(arr, ret); + #end return ret; } -#if !erase_generics - static function p_nativeArray(arr:Array, ret:cs.system.Array):Void - { + #if !erase_generics + static function p_nativeArray(arr:Array, ret:cs.system.Array):Void { var native:NativeArray = untyped arr.__a; var len = arr.length; cs.system.Array.Copy(native, 0, ret, 0, len); } -#end + #end /** Provides support for the "as" keyword in C#. @@ -85,8 +82,7 @@ class Lib This function will not work with Value Types (such as Int, Float, Bool...) **/ @:pure - @:extern public static inline function as(obj:Dynamic, cl:Class):T - { + extern public static inline function as(obj:Dynamic, cl:Class):T { return untyped __as__(obj); } @@ -96,8 +92,7 @@ class Lib Currently Haxe's Class<> is equivalent to System.Type, but this is an implementation detail. This may change in the future, so use this function whenever you need to perform such conversion. **/ - public static inline function fromNativeType(t:cs.system.Type):Class - { + public static inline function fromNativeType(t:cs.system.Type):Class { return untyped t; } @@ -107,16 +102,14 @@ class Lib Currently Haxe's Class<> is equivalent to System.Type, but this is an implementation detail. This may change in the future, so use this function whenever you need to perform such conversion. **/ - public static inline function toNativeType(cl:Class):Type - { + public static inline function toNativeType(cl:Class):Type { return untyped cl; } /** Returns a System.Type equivalent to the Haxe Enum<> type. **/ - public static inline function toNativeEnum(cl:Enum):Type - { + public static inline function toNativeEnum(cl:Enum):Type { return untyped cl; } @@ -125,28 +118,25 @@ class Lib [deprecated] - use `getNativeType` instead **/ @:deprecated('The function `nativeType` is deprecated and will be removed in later versions. Please use `getNativeType` instead') - public static inline function nativeType(obj:Dynamic):Type - { + public static inline function nativeType(obj:Dynamic):Type { return untyped obj.GetType(); } /** Gets the native System.Type from the supplied object. Will throw an exception in case of null being passed. **/ - public static inline function getNativeType(obj:Dynamic):Type - { + public static inline function getNativeType(obj:Dynamic):Type { return untyped obj.GetType(); } -#if erase_generics - inline private static function mkDynamic(native:NativeArray):NativeArray - { + #if erase_generics + inline private static function mkDynamic(native:NativeArray):NativeArray { var ret = new cs.NativeArray(native.Length); for (i in 0...native.Length) ret[i] = native[i]; return ret; } -#end + #end /** Returns a Haxe Array of a native Array. @@ -154,21 +144,19 @@ class Lib so unless any operation triggers an array resize, all changes made to the Haxe array will affect the native array argument. **/ - inline public static function array(native:cs.NativeArray):Array - { -#if erase_generics + inline public static function array(native:cs.NativeArray):Array { + #if erase_generics var dyn:NativeArray = mkDynamic(native); return @:privateAccess Array.ofNative(dyn); -#else + #else return @:privateAccess Array.ofNative(native); -#end + #end } /** Allocates a new Haxe Array with a predetermined size **/ - inline public static function arrayAlloc(size:Int):Array - { + inline public static function arrayAlloc(size:Int):Array { return @:privateAccess Array.alloc(size); } @@ -176,8 +164,7 @@ class Lib Rethrow an exception. This is useful when manually filtering an exception in order to keep the previous exception stack. **/ - @:extern inline public static function rethrow(e:Dynamic):Void - { + extern inline public static function rethrow(e:Dynamic):Void { throw untyped __rethrow__; } @@ -194,8 +181,7 @@ class Lib }); This method only exists at compile-time, so it can't be called via reflection. **/ - @:extern public static inline function checked(block:V):Void - { + extern public static inline function checked(block:V):Void { untyped __checked__(block); } @@ -206,12 +192,12 @@ class Lib This method only exists at compile-time, so it can't be called via reflection. **/ - @:extern public static inline function lock(obj:O, block:V):Void - { + extern public static inline function lock(obj:O, block:V):Void { untyped __lock__(obj, block); } - //Unsafe code manipulation + // Unsafe code manipulation + #if unsafe /** Marks its parameters as fixed objects inside the defined block. @@ -228,8 +214,7 @@ class Lib This method only exists at compile-time, so it can't be called via reflection. **/ - @:extern public static inline function fixed(block:V):Void - { + extern public static inline function fixed(block:V):Void { untyped __fixed__(block); } @@ -242,8 +227,7 @@ class Lib This method only exists at compile-time, so it can't be called via reflection. **/ - @:extern public static inline function unsafe(block:V):Void - { + extern public static inline function unsafe(block:V):Void { untyped __unsafe__(block); } @@ -260,8 +244,7 @@ class Lib This method only exists at compile-time, so it can't be called via reflection. Warning: This method will only work if a local variable is passed as an argument. **/ - @:extern public static inline function addressOf(variable:T):cs.Pointer - { + extern public static inline function addressOf(variable:T):cs.Pointer { return untyped __addressOf__(variable); } @@ -279,8 +262,7 @@ class Lib This method only exists at compile-time, so it can't be called via reflection. **/ - @:extern public static inline function valueOf(pointer:cs.Pointer):T - { + extern public static inline function valueOf(pointer:cs.Pointer):T { return untyped __valueOf__(pointer); } @@ -300,16 +282,14 @@ class Lib This method only exists at compile-time, so it can't be called via reflection. **/ - @:extern public static inline function pointerOfArray(array:cs.NativeArray):cs.Pointer - { + extern public static inline function pointerOfArray(array:cs.NativeArray):cs.Pointer { return untyped __ptr__(array); } /** Returns the byte size of the given struct. Only works with structs and basic types. **/ - @:extern public static inline function sizeof(struct:Class):Int - { + extern public static inline function sizeof(struct:Class):Int { return untyped __sizeof__(struct); } #end diff --git a/std/cs/NativeArray.hx b/std/cs/NativeArray.hx index 478cbe3b03e..7f92f1ad70b 100644 --- a/std/cs/NativeArray.hx +++ b/std/cs/NativeArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs; import haxe.extern.Rest; @@ -26,8 +27,7 @@ import haxe.extern.Rest; /** Represents a C# fixed-size Array (`T[]`) **/ -extern class NativeArray extends cs.system.Array implements ArrayAccess -{ +extern class NativeArray extends cs.system.Array implements ArrayAccess { /** Creates a new array with the specified elements. @@ -35,37 +35,36 @@ extern class NativeArray extends cs.system.Array implements ArrayAccess ```haxe var elements = NativeArray.make(1,2,3,4,5,6); ``` - **/ + **/ public static function make(elements:Rest):NativeArray; /** Allocates a new array with size `len` - **/ + **/ public function new(len:Int):Void; /** Alias to array's `Length` property. Returns the size of the array - **/ - public var length(get,never):Int; + **/ + public var length(get, never):Int; - @:extern inline private function get_length():Int return this.Length; + extern inline private function get_length():Int + return this.Length; static function Reverse(arr:cs.system.Array):Void; /** Returns an iterator so it's possible to use `for` with C#'s `NativeArray` - **/ - @:extern inline public function iterator():NativeArrayIterator + **/ + extern inline public function iterator():NativeArrayIterator return new NativeArrayIterator(this); } -@:dce private class NativeArrayIterator -{ - public var arr(default,null):NativeArray; - public var idx(default,null):UInt; +@:dce private class NativeArrayIterator { + public var arr(default, null):NativeArray; + public var idx(default, null):UInt; - inline public function new(arr) - { + inline public function new(arr) { this.arr = arr; this.idx = 0; } @@ -73,8 +72,7 @@ extern class NativeArray extends cs.system.Array implements ArrayAccess inline public function hasNext():Bool return this.idx < this.arr.Length; - inline public function next():T - { + inline public function next():T { return this.arr[this.idx++]; } } diff --git a/std/cs/Out.hx b/std/cs/Out.hx index 587097667e2..c4e78ad8e7f 100644 --- a/std/cs/Out.hx +++ b/std/cs/Out.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs; /** @@ -27,6 +28,6 @@ package cs; Note: Using this type should be considered a bad practice unless overriding a native function is needed. **/ -@:analyzer(no_simplification) @:analyzer(no_local_dce) -typedef Out = T; \ No newline at end of file +@:semantics(reference) +typedef Out = T; diff --git a/std/cs/Pointer.hx b/std/cs/Pointer.hx index b71af6b484a..5d18c665369 100644 --- a/std/cs/Pointer.hx +++ b/std/cs/Pointer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs; + import cs.StdTypes.Int64; /** @@ -43,63 +45,89 @@ import cs.StdTypes.Int64; #if !unsafe #error "You need to define 'unsafe' to be able to use unsafe code in hxcs" #else -@:runtimeValue @:coreType abstract Pointer from Int64 from PointerAccess to PointerAccess -{ - @:op(A+B) public static function addIp(lhs:Pointer, rhs:Int):Pointer; - @:op(A+B) public static function addp(lhs:Pointer, rhs:Int64):Pointer; - @:op(A*B) public static function mulIp(lhs:Pointer, rhs:Int):Pointer; - @:op(A*B) public static function mulp(lhs:Pointer, rhs:Int64):Pointer; - @:op(A%B) public static function modIp(lhs:Pointer, rhs:Int):Pointer; - @:op(A%B) public static function modp(lhs:Pointer, rhs:Int64):Pointer; - @:op(A-B) public static function subIp(lhs:Pointer, rhs:Int):Pointer; - @:op(A-B) public static function subp(lhs:Pointer, rhs:Int64):Pointer; - @:op(A/B) public static function divIp(lhs:Pointer, rhs:Int):Pointer; - @:op(A/B) public static function divp(lhs:Pointer, rhs:Int64):Pointer; - @:op(A|B) public static function orIp(lhs:Pointer, rhs:Int):Pointer; - @:op(A|B) public static function orp(lhs:Pointer, rhs:Int64):Pointer; - @:op(A^B) public static function xorIp(lhs:Pointer, rhs:Int):Pointer; - @:op(A^B) public static function xorp(lhs:Pointer, rhs:Int64):Pointer; - @:op(A&B) public static function andIp(lhs:Pointer, rhs:Int):Pointer; - @:op(A&B) public static function andp(lhs:Pointer, rhs:Int64):Pointer; - @:op(A<(lhs:Pointer, rhs:Int):Pointer; - @:op(A<(lhs:Pointer, rhs:Int64):Pointer; - @:op(A>>B) public static function shrIp(lhs:Pointer, rhs:Int):Pointer; - @:op(A>>B) public static function shrp(lhs:Pointer, rhs:Int64):Pointer; - - @:op(A>B) public static function gtp(lhs:Pointer, rhs:Pointer):Bool; - @:op(A>=B) public static function gtep(lhs:Pointer, rhs:Pointer):Bool; - @:op(A(lhs:Pointer, rhs:Pointer):Bool; - @:op(A<=B) public static function ltep(lhs:Pointer, rhs:Pointer):Bool; +@:runtimeValue @:coreType abstract Pointer from Int64 from PointerAccess to PointerAccess { + @:op(A + B) public static function addIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A + B) public static function addp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A * B) public static function mulIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A * B) public static function mulp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A % B) public static function modIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A % B) public static function modp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A - B) public static function subIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A - B) public static function subp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A / B) public static function divIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A / B) public static function divp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A | B) public static function orIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A | B) public static function orp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A ^ B) public static function xorIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A ^ B) public static function xorp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A & B) public static function andIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A & B) public static function andp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A << B) public static function shlIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A << B) public static function shlp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A >> B) public static function shrIp(lhs:Pointer, rhs:Int):Pointer; + + @:op(A >> B) public static function shrp(lhs:Pointer, rhs:Int64):Pointer; + + @:op(A > B) public static function gtp(lhs:Pointer, rhs:Pointer):Bool; + + @:op(A >= B) public static function gtep(lhs:Pointer, rhs:Pointer):Bool; + + @:op(A < B) public static function ltp(lhs:Pointer, rhs:Pointer):Bool; + + @:op(A <= B) public static function ltep(lhs:Pointer, rhs:Pointer):Bool; @:op(~A) public static function bnegp(t:Pointer):Pointer; + @:op(A++) public static function prepp(t:Pointer):Pointer; + @:op(A--) public static function prenn(t:Pointer):Pointer; + @:op(++A) public static function postpp(t:Pointer):Pointer; + @:op(--A) public static function postnn(t:Pointer):Pointer; /** Returns a `cs.PointerAccess` type, which in turn allows the underlying Pointer's fields to be accessed. - **/ + **/ // @:analyzer(no_simplification) - public var acc(get,never):PointerAccess; + public var acc(get, never):PointerAccess; // @:analyzer(no_simplification) - @:extern inline private function get_acc():PointerAccess return (cast this : PointerAccess); + extern inline private function get_acc():PointerAccess + return (cast this : PointerAccess); // backwards compatibility - inline public function add(i:Int):Pointer - { + inline public function add(i:Int):Pointer { return this + i; } @:arrayAccess public static function getIp(p:Pointer, at:Int):T; + @:arrayAccess public static function setIp(p:Pointer, at:Int, val:T):T; + @:arrayAccess public static function getp(p:Pointer, at:Int64):T; + @:arrayAccess public static function setp(p:Pointer, at:Int64, val:T):T; } -@:forward abstract PointerAccess(T) -{ -} +@:forward abstract PointerAccess(T) {} #end diff --git a/std/cs/Ref.hx b/std/cs/Ref.hx index 024d5da8a3f..609bd2aa5dd 100644 --- a/std/cs/Ref.hx +++ b/std/cs/Ref.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs; /** @@ -27,5 +28,5 @@ package cs; Note: Using this type should be considered a bad practice unless overriding a native function is needed. **/ -@:analyzer(no_simplification) -typedef Ref = T; \ No newline at end of file +@:semantics(reference) +typedef Ref = T; diff --git a/std/cs/StdTypes.hx b/std/cs/StdTypes.hx index 05cef4bc506..d2d72e90d89 100644 --- a/std/cs/StdTypes.hx +++ b/std/cs/StdTypes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs; @:notNull @:runtimeValue @:coreType extern abstract Int8 to Int {} @@ -26,75 +27,127 @@ package cs; @:notNull @:runtimeValue @:coreType extern abstract Char16 from Int {} @:notNull @:runtimeValue @:coreType extern abstract UInt8 to Int from Int {} @:notNull @:runtimeValue @:coreType extern abstract UInt16 to Int {} -@:notNull @:runtimeValue @:coreType extern abstract Int64 from Int from Float -{ - @:op(A+B) public static function addI(lhs:Int64, rhs:Int):Int64; - @:op(A+B) public static function add(lhs:Int64, rhs:Int64):Int64; - @:op(A*B) public static function mulI(lhs:Int64, rhs:Int):Int64; - @:op(A*B) public static function mul(lhs:Int64, rhs:Int64):Int64; - @:op(A%B) public static function modI(lhs:Int64, rhs:Int):Int64; - @:op(A%B) public static function mod(lhs:Int64, rhs:Int64):Int64; - @:op(A-B) public static function subI(lhs:Int64, rhs:Int):Int64; - @:op(A-B) public static function sub(lhs:Int64, rhs:Int64):Int64; - @:op(A/B) public static function divI(lhs:Int64, rhs:Int):Int64; - @:op(A/B) public static function div(lhs:Int64, rhs:Int64):Int64; - @:op(A|B) public static function orI(lhs:Int64, rhs:Int):Int64; - @:op(A|B) public static function or(lhs:Int64, rhs:Int64):Int64; - @:op(A^B) public static function xorI(lhs:Int64, rhs:Int):Int64; - @:op(A^B) public static function xor(lhs:Int64, rhs:Int64):Int64; - @:op(A&B) public static function andI(lhs:Int64, rhs:Int):Int64; - @:op(A&B) public static function and(lhs:Int64, rhs:Int64):Int64; - @:op(A<>B) public static function shrI(lhs:Int64, rhs:Int):Int64; - @:op(A>>B) public static function shr(lhs:Int64, rhs:Int64):Int64; - - @:op(A>B) public static function gt(lhs:Int64, rhs:Int64):Bool; - @:op(A>=B) public static function gte(lhs:Int64, rhs:Int64):Bool; - @:op(A> B) public static function shrI(lhs:Int64, rhs:Int):Int64; + + @:op(A >> B) public static function shr(lhs:Int64, rhs:Int64):Int64; + + @:op(A > B) public static function gt(lhs:Int64, rhs:Int64):Bool; + + @:op(A >= B) public static function gte(lhs:Int64, rhs:Int64):Bool; + + @:op(A < B) public static function lt(lhs:Int64, rhs:Int64):Bool; + + @:op(A <= B) public static function lte(lhs:Int64, rhs:Int64):Bool; @:op(~A) public static function bneg(t:Int64):Int64; + @:op(-A) public static function neg(t:Int64):Int64; @:op(++A) public static function preIncrement(t:Int64):Int64; + @:op(A++) public static function postIncrement(t:Int64):Int64; + @:op(--A) public static function preDecrement(t:Int64):Int64; + @:op(A--) public static function postDecrement(t:Int64):Int64; } -@:notNull @:runtimeValue @:coreType extern abstract UInt64 from Int from Int64 from Float from haxe.Int64 -{ - @:op(A+B) public static function addI(lhs:UInt64, rhs:Int):UInt64; - @:op(A+B) public static function add(lhs:UInt64, rhs:UInt64):UInt64; - @:op(A*B) public static function mulI(lhs:UInt64, rhs:Int):UInt64; - @:op(A*B) public static function mul(lhs:UInt64, rhs:UInt64):UInt64; - @:op(A%B) public static function modI(lhs:UInt64, rhs:Int):UInt64; - @:op(A%B) public static function mod(lhs:UInt64, rhs:UInt64):UInt64; - @:op(A-B) public static function subI(lhs:UInt64, rhs:Int):UInt64; - @:op(A-B) public static function sub(lhs:UInt64, rhs:UInt64):UInt64; - @:op(A/B) public static function divI(lhs:UInt64, rhs:Int):UInt64; - @:op(A/B) public static function div(lhs:UInt64, rhs:UInt64):UInt64; - @:op(A|B) public static function orI(lhs:UInt64, rhs:Int):UInt64; - @:op(A|B) public static function or(lhs:UInt64, rhs:UInt64):UInt64; - @:op(A^B) public static function xorI(lhs:UInt64, rhs:Int):UInt64; - @:op(A^B) public static function xor(lhs:UInt64, rhs:UInt64):UInt64; - @:op(A&B) public static function andI(lhs:UInt64, rhs:Int):UInt64; - @:op(A&B) public static function and(lhs:UInt64, rhs:UInt64):UInt64; - @:op(A<>B) public static function shrI(lhs:UInt64, rhs:Int):UInt64; - @:op(A>>B) public static function shr(lhs:UInt64, rhs:UInt64):UInt64; - - @:op(A>B) public static function gt(lhs:UInt64, rhs:UInt64):Bool; - @:op(A>=B) public static function gte(lhs:UInt64, rhs:UInt64):Bool; - @:op(A> B) public static function shrI(lhs:UInt64, rhs:Int):UInt64; + + @:op(A >> B) public static function shr(lhs:UInt64, rhs:UInt64):UInt64; + + @:op(A > B) public static function gt(lhs:UInt64, rhs:UInt64):Bool; + + @:op(A >= B) public static function gte(lhs:UInt64, rhs:UInt64):Bool; + + @:op(A < B) public static function lt(lhs:UInt64, rhs:UInt64):Bool; + + @:op(A <= B) public static function lte(lhs:UInt64, rhs:UInt64):Bool; @:op(~A) public static function bneg(t:UInt64):UInt64; + @:op(-A) public static function neg(t:UInt64):UInt64; @:op(++A) public static function preIncrement(t:UInt64):UInt64; + @:op(A++) public static function postIncrement(t:UInt64):UInt64; + @:op(--A) public static function preDecrement(t:UInt64):UInt64; + @:op(A--) public static function postDecrement(t:UInt64):UInt64; } diff --git a/std/cs/_std/Array.hx b/std/cs/_std/Array.hx index d593ec5f80f..929b65373c6 100644 --- a/std/cs/_std/Array.hx +++ b/std/cs/_std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,56 +19,52 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import cs.NativeArray; #if core_api_serialize @:meta(System.Serializable) #end -@:final class Array implements ArrayAccess { - - public var length(default,null) : Int; +final class Array implements ArrayAccess { + public var length(default, null):Int; private var __a:NativeArray; -#if erase_generics - inline private static function ofNative(native:NativeArray):Array - { + @:skipReflection static var __hx_toString_depth = 0; + @:skipReflection static inline final __hx_defaultCapacity = 4; + + #if erase_generics + inline private static function ofNative(native:NativeArray):Array { return new Array(native); } -#else - inline private static function ofNative(native:NativeArray):Array - { + #else + inline private static function ofNative(native:NativeArray):Array { return new Array(native); } -#end + #end - inline private static function alloc(size:Int):Array - { + inline private static function alloc(size:Int):Array { return new Array(new NativeArray(size)); } - @:overload public function new() : Void - { + @:overload public function new():Void { this.length = 0; this.__a = new NativeArray(0); } -#if erase_generics - @:overload private function new(native:NativeArray) - { + #if erase_generics + @:overload private function new(native:NativeArray) { this.length = native.Length; this.__a = untyped native; } -#else - @:overload private function new(native:NativeArray) - { + #else + @:overload private function new(native:NativeArray) { this.length = native.Length; this.__a = native; } -#end + #end - public function concat( a : Array ) : Array - { + public function concat(a:Array):Array { var len = length + a.length; var retarr = new NativeArray(len); cs.system.Array.Copy(__a, 0, retarr, 0, length); @@ -77,12 +73,10 @@ import cs.NativeArray; return ofNative(retarr); } - private function concatNative( a : NativeArray ) : Void - { + private function concatNative(a:NativeArray):Void { var __a = __a; var len = length + a.Length; - if (__a.Length >= len) - { + if (__a.Length >= len) { cs.system.Array.Copy(a, 0, __a, length, length); } else { var newarr = new NativeArray(len); @@ -95,45 +89,37 @@ import cs.NativeArray; this.length = len; } - public function indexOf( x : T, ?fromIndex:Int ) : Int - { + public function indexOf(x:T, ?fromIndex:Int):Int { var len = length, i:Int = (fromIndex == null) ? 0 : fromIndex; - if (i < 0) - { + if (i < 0) { i += len; - if (i < 0) i = 0; - } - else if (i >= len) - { + if (i < 0) + i = 0; + } else if (i >= len) { return -1; } return cs.system.Array.IndexOf(__a, x, i, len - i); } - public function lastIndexOf( x : T, ?fromIndex:Int ) : Int - { + public function lastIndexOf(x:T, ?fromIndex:Int):Int { var len = length, i:Int = (fromIndex == null) ? len - 1 : fromIndex; - if (i >= len) - { + if (i >= len) { i = len - 1; - } - else if (i < 0) - { + } else if (i < 0) { i += len; - if (i < 0) return -1; + if (i < 0) + return -1; } return cs.system.Array.LastIndexOf(__a, x, i, i + 1); } - public function join( sep : String ) : String - { + public function join(sep:String):String { var buf = new StringBuf(); var i = -1; var first = true; var length = length; - while (++i < length) - { + while (++i < length) { if (first) first = false; else @@ -144,12 +130,10 @@ import cs.NativeArray; return buf.toString(); } - public function pop() : Null - { + public function pop():Null { var __a = __a; var length = length; - if (length > 0) - { + if (length > 0) { var val = __a[--length]; __a[length] = null; this.length = length; @@ -160,11 +144,9 @@ import cs.NativeArray; } } - public function push(x : T) : Int - { - if (length >= __a.Length) - { - var newLen = (length << 1) + 1; + public function push(x:T):Int { + if (length >= __a.Length) { + var newLen = length == 0 ? __hx_defaultCapacity : (length << 1); var newarr = new NativeArray(newLen); __a.CopyTo(newarr, 0); @@ -175,53 +157,50 @@ import cs.NativeArray; return ++length; } - public function reverse() : Void - { + public function reverse():Void { var i = 0; var l = this.length; var a = this.__a; var half = l >> 1; l -= 1; - while ( i < half ) - { + while (i < half) { var tmp = a[i]; - a[i] = a[l-i]; - a[l-i] = tmp; + a[i] = a[l - i]; + a[l - i] = tmp; i += 1; } } - public function shift() : Null - { + public function shift():Null { var l = this.length; - if( l == 0 ) + if (l == 0) return null; var a = this.__a; var x = a[0]; l -= 1; - cs.system.Array.Copy(a, 1, a, 0, length-1); + cs.system.Array.Copy(a, 1, a, 0, length - 1); a[l] = null; this.length = l; return x; } - public function slice( pos : Int, ?end : Int ) : Array - { - if( pos < 0 ){ + public function slice(pos:Int, ?end:Int):Array { + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) + if (pos < 0) pos = 0; } - if( end == null ) + if (end == null) end = this.length; - else if( end < 0 ) + else if (end < 0) end = this.length + end; - if( end > this.length ) + if (end > this.length) end = this.length; var len = end - pos; - if ( len < 0 ) return new Array(); + if (len < 0) + return new Array(); var newarr = new NativeArray(len); cs.system.Array.Copy(__a, pos, newarr, 0, len); @@ -229,47 +208,49 @@ import cs.NativeArray; return ofNative(newarr); } - public function sort( f : T -> T -> Int ) : Void - { + public function sort(f:T->T->Int):Void { if (length == 0) return; quicksort(0, length - 1, f); } - private function quicksort( lo : Int, hi : Int, f : T -> T -> Int ) : Void - { + private function quicksort(lo:Int, hi:Int, f:T->T->Int):Void { var buf = __a; var i = lo, j = hi; var p = buf[(i + j) >> 1]; - while ( i <= j ) - { - while ( i < hi && f(buf[i], p) < 0 ) i++; - while ( j > lo && f(buf[j], p) > 0 ) j--; - if ( i <= j ) - { + while (i <= j) { + while (i < hi && f(buf[i], p) < 0) + i++; + while (j > lo && f(buf[j], p) > 0) + j--; + if (i <= j) { var t = buf[i]; buf[i++] = buf[j]; buf[j--] = t; } } - if( lo < j ) quicksort( lo, j, f ); - if( i < hi ) quicksort( i, hi, f ); + if (lo < j) + quicksort(lo, j, f); + if (i < hi) + quicksort(i, hi, f); } - public function splice( pos : Int, len : Int ) : Array - { - if( len < 0 ) return new Array(); - if( pos < 0 ) { + public function splice(pos:Int, len:Int):Array { + if (len < 0) + return new Array(); + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) pos = 0; + if (pos < 0) + pos = 0; } - if( pos > this.length ) { + if (pos > this.length) { pos = 0; len = 0; - } else if( pos + len > this.length ) { + } else if (pos + len > this.length) { len = this.length - pos; - if( len < 0 ) len = 0; + if (len < 0) + len = 0; } var a = this.__a; @@ -280,42 +261,58 @@ import cs.NativeArray; var end = pos + len; cs.system.Array.Copy(a, end, a, pos, this.length - end); this.length -= len; - while( --len >= 0 ) + while (--len >= 0) a[this.length + len] = null; return ret; } - private function spliceVoid( pos : Int, len : Int ) : Void - { - if( len < 0 ) return; - if( pos < 0 ) { + private function spliceVoid(pos:Int, len:Int):Void { + if (len < 0) + return; + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) pos = 0; + if (pos < 0) + pos = 0; } - if( pos > this.length ) { + if (pos > this.length) { pos = 0; len = 0; - } else if( pos + len > this.length ) { + } else if (pos + len > this.length) { len = this.length - pos; - if( len < 0 ) len = 0; + if (len < 0) + len = 0; } var a = this.__a; var end = pos + len; cs.system.Array.Copy(a, end, a, pos, this.length - end); this.length -= len; - while( --len >= 0 ) + while (--len >= 0) a[this.length + len] = null; } - public function toString() : String - { + public function toString():String { + if (__hx_toString_depth >= 5) { + return "..."; + } + ++__hx_toString_depth; + try { + var s = __hx_toString(); + --__hx_toString_depth; + return s; + } catch (e:Dynamic) { + --__hx_toString_depth; + throw(e); + } + } + + @:skipReflection + function __hx_toString():String { var ret = new StringBuf(); var a = __a; ret.add("["); var first = true; - for (i in 0...length) - { + for (i in 0...length) { if (first) first = false; else @@ -327,12 +324,10 @@ import cs.NativeArray; return ret.toString(); } - public function unshift( x : T ) : Void - { + public function unshift(x:T):Void { var __a = __a; var length = length; - if (length >= __a.Length) - { + if (length >= __a.Length) { var newLen = (length << 1) + 1; var newarr = new NativeArray(newLen); cs.system.Array.Copy(__a, 0, newarr, 1, length); @@ -346,14 +341,14 @@ import cs.NativeArray; ++this.length; } - public function insert( pos : Int, x : T ) : Void - { + public function insert(pos:Int, x:T):Void { var l = this.length; - if( pos < 0 ) { + if (pos < 0) { pos = l + pos; - if( pos < 0 ) pos = 0; + if (pos < 0) + pos = 0; } - if ( pos >= l ) { + if (pos >= l) { this.push(x); return; } else if (pos == 0) { @@ -361,8 +356,7 @@ import cs.NativeArray; return; } - if (l >= __a.Length) - { + if (l >= __a.Length) { var newLen = (length << 1) + 1; var newarr = new NativeArray(newLen); cs.system.Array.Copy(__a, 0, newarr, 0, pos); @@ -380,15 +374,12 @@ import cs.NativeArray; } } - public function remove( x : T ) : Bool - { + public function remove(x:T):Bool { var __a = __a; var i = -1; var length = length; - while (++i < length) - { - if (__a[i] == x) - { + while (++i < length) { + if (__a[i] == x) { cs.system.Array.Copy(__a, i + 1, __a, i, length - i - 1); __a[--this.length] = null; @@ -399,14 +390,14 @@ import cs.NativeArray; return false; } - public inline function map( f : T -> S ) : Array { + public inline function map(f:T->S):Array { var ret = alloc(length); for (i in 0...length) ret.__unsafe_set(i, f(__unsafe_get(i))); return ret; } - public inline function filter( f : T -> Bool ) : Array { + public inline function filter(f:T->Bool):Array { var ret = []; for (i in 0...length) { var elt = __unsafe_get(i); @@ -416,8 +407,7 @@ import cs.NativeArray; return ret; } - public function copy() : Array - { + public function copy():Array { var len = length; var __a = __a; var newarr = new NativeArray(len); @@ -425,22 +415,29 @@ import cs.NativeArray; return ofNative(newarr); } - public inline function iterator() : Iterator - { + public inline function iterator():Iterator { return new ArrayIterator(this); } - private function __get(idx:Int):T - { + public function resize(len:Int):Void { + if (length < len) { + if (__a.length < len) { + cs.system.Array.Resize(__a, len); + } + this.length = len; + } else if (length > len) { + spliceVoid(len, length - len); + } + } + + private function __get(idx:Int):T { return if ((cast idx : UInt) >= length) null else __a[idx]; } - private function __set(idx:Int, v:T):T - { + private function __set(idx:Int, v:T):T { var idx:UInt = idx; var __a = __a; - if (idx >= __a.Length) - { + if (idx >= __a.Length) { var len = idx + 1; if (idx == __a.Length) len = (idx << 1) + 1; @@ -455,31 +452,29 @@ import cs.NativeArray; return __a[idx] = v; } - private inline function __unsafe_get(idx:Int):T - { + private inline function __unsafe_get(idx:Int):T { return __a[idx]; } - private inline function __unsafe_set(idx:Int, val:T):T - { + private inline function __unsafe_set(idx:Int, val:T):T { return __a[idx] = val; } } -@:final -private class ArrayIterator -{ +private final class ArrayIterator { var arr:Array; var len:Int; var i:Int; - public inline function new(a:Array) - { + public inline function new(a:Array) { arr = a; len = a.length; i = 0; } - public inline function hasNext():Bool return i < len; - public inline function next():T return arr[i++]; + public inline function hasNext():Bool + return i < len; + + public inline function next():T + return arr[i++]; } diff --git a/std/cs/_std/Date.hx b/std/cs/_std/Date.hx index 1f94ac2ae21..49b0f126db5 100644 --- a/std/cs/_std/Date.hx +++ b/std/cs/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,119 +19,144 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package; + import cs.system.DateTime; +import cs.system.DateTimeKind; import cs.system.TimeSpan; import haxe.Int64; #if core_api_serialize @:meta(System.Serializable) #end -@:coreApi class Date -{ +@:coreApi class Date { @:readOnly private static var epochTicks:Int64 = new DateTime(1970, 1, 1).Ticks; - private var date:DateTime; - @:overload public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void - { - if (day <= 0) day = 1; - if (year <= 0) year = 1; - date = new DateTime(year, month + 1, day, hour, min, sec); + private var date:DateTime; + private var dateUTC:DateTime; + + @:overload public function new(year:Int, month:Int, day:Int, hour:Int, min:Int, sec:Int):Void { + if (day <= 0) + day = 1; + if (year <= 0) + year = 1; + date = new DateTime(year, month + 1, day, hour, min, sec, DateTimeKind.Local); + dateUTC = date.ToUniversalTime(); } - @:overload private function new(native:DateTime) - { - date = native; + @:overload private function new(native:DateTime) { + if (native.Kind == DateTimeKind.Utc) { + dateUTC = native; + date = dateUTC.ToLocalTime(); + } else { + date = native; + dateUTC = date.ToUniversalTime(); + } } - public inline function getTime() : Float - { + public inline function getTime():Float { + #if (net_ver < 35) return cast(cs.system.TimeZone.CurrentTimeZone.ToUniversalTime(date).Ticks - epochTicks, Float) / cast(TimeSpan.TicksPerMillisecond, Float); + #else + return cast(cs.system.TimeZoneInfo.ConvertTimeToUtc(date).Ticks - epochTicks, Float) / cast(TimeSpan.TicksPerMillisecond, Float); + #end } - public inline function getHours() : Int - { + public inline function getHours():Int { return date.Hour; } - public inline function getMinutes() : Int - { + public inline function getMinutes():Int { return date.Minute; } - public inline function getSeconds() : Int - { + public inline function getSeconds():Int { return date.Second; } - public inline function getFullYear() : Int - { + public inline function getFullYear():Int { return date.Year; } - public inline function getMonth() : Int - { + public inline function getMonth():Int { return date.Month - 1; } - public inline function getDate() : Int - { + public inline function getDate():Int { return date.Day; } - public inline function getDay() : Int - { + public inline function getDay():Int { return cast(date.DayOfWeek, Int); } - public function toString():String - { - var m = getMonth() + 1; - var d = getDate(); - var h = getHours(); - var mi = getMinutes(); - var s = getSeconds(); - return (getFullYear()) - +"-"+(if( m < 10 ) "0"+m else ""+m) - +"-"+(if( d < 10 ) "0"+d else ""+d) - +" "+(if( h < 10 ) "0"+h else ""+h) - +":"+(if( mi < 10 ) "0"+mi else ""+mi) - +":"+(if( s < 10 ) "0"+s else ""+s); + public inline function getUTCHours():Int { + return dateUTC.Hour; + } + + public inline function getUTCMinutes():Int { + return dateUTC.Minute; + } + + public inline function getUTCSeconds():Int { + return dateUTC.Second; + } + + public inline function getUTCFullYear():Int { + return dateUTC.Year; + } + + public inline function getUTCMonth():Int { + return dateUTC.Month - 1; + } + + public inline function getUTCDate():Int { + return dateUTC.Day; + } + + public inline function getUTCDay():Int { + return cast(dateUTC.DayOfWeek, Int); + } + + public inline function getTimezoneOffset():Int { + return Std.int((cast(dateUTC.Ticks - date.Ticks, Float) / cast(TimeSpan.TicksPerMillisecond, Float)) / 60000.); + } + + public function toString():String { + return date.ToString("yyyy-MM-dd HH\\:mm\\:ss"); } - static public inline function now() : Date - { + static public inline function now():Date { return new Date(DateTime.Now); } - static public inline function fromTime( t : Float ) : Date - { + static public inline function fromTime(t:Float):Date { + #if (net_ver < 35) return new Date(cs.system.TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(cast(t * cast(TimeSpan.TicksPerMillisecond, Float), Int64) + epochTicks))); + #else + return new Date(cs.system.TimeZoneInfo.ConvertTimeFromUtc(new DateTime(cast(t * cast(TimeSpan.TicksPerMillisecond, Float), Int64) + epochTicks), + cs.system.TimeZoneInfo.Local)); + #end } - static public function fromString( s : String ) : Date - { - switch( s.length ) - { + static public function fromString(s:String):Date { + switch (s.length) { case 8: // hh:mm:ss var k = s.split(":"); - var d : Date = new Date(1, 1, 1, Std.parseInt(k[0]), Std.parseInt(k[1]), Std.parseInt(k[2])); - return d; + return new Date(new DateTime(1970, 1, 1, Std.parseInt(k[0]), Std.parseInt(k[1]), Std.parseInt(k[2]), DateTimeKind.Utc)); case 10: // YYYY-MM-DD var k = s.split("-"); - return new Date(Std.parseInt(k[0]),Std.parseInt(k[1]) - 1,Std.parseInt(k[2]),0,0,0); + return new Date(new DateTime(Std.parseInt(k[0]), Std.parseInt(k[1]), Std.parseInt(k[2]), 0, 0, 0, DateTimeKind.Local)); case 19: // YYYY-MM-DD hh:mm:ss var k = s.split(" "); var y = k[0].split("-"); var t = k[1].split(":"); - return new Date(Std.parseInt(y[0]),Std.parseInt(y[1]) - 1,Std.parseInt(y[2]),Std.parseInt(t[0]),Std.parseInt(t[1]),Std.parseInt(t[2])); + return new Date(new DateTime(Std.parseInt(y[0]), Std.parseInt(y[1]), Std.parseInt(y[2]), Std.parseInt(t[0]), Std.parseInt(t[1]), Std.parseInt(t[2]), DateTimeKind.Local)); default: throw "Invalid date format : " + s; } } - private static inline function fromNative( d : cs.system.DateTime ) : Date - { + private static inline function fromNative(d:cs.system.DateTime):Date { return new Date(d); } } diff --git a/std/cs/_std/EReg.hx b/std/cs/_std/EReg.hx index 1a517c1a41e..4b6bcea0789 100644 --- a/std/cs/_std/EReg.hx +++ b/std/cs/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,94 +19,93 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import cs.system.text.regularexpressions.Regex; import cs.system.text.regularexpressions.Match; import cs.system.text.regularexpressions.RegexOptions; import cs.system.text.regularexpressions.*; -@:coreApi @:final class EReg { - - private var regex : Regex; - private var m : Match; - private var isGlobal : Bool; - private var cur : String; +@:coreApi final class EReg { + private var regex:Regex; + private var m:Match; + private var isGlobal:Bool; + private var cur:String; - public function new( r : String, opt : String ) : Void { + public function new(r:String, opt:String):Void { var opts:Int = cast CultureInvariant; - for (i in 0...opt.length) untyped { - switch(cast(opt[i], Int)) - { - case 'i'.code: - opts |= cast(IgnoreCase, Int); - case 'g'.code: - isGlobal = true; - case 'm'.code: - opts |= cast(Multiline, Int); -#if (!unity && !unity_std_target) - case 'c'.code: - opts |= cast(Compiled, Int); -#end + for (i in 0...opt.length) + untyped { + switch (cast(opt[i], Int)) { + case 'i'.code: + opts |= cast(IgnoreCase, Int); + case 'g'.code: + isGlobal = true; + case 'm'.code: + opts |= cast(Multiline, Int); + #if (!unity && !unity_std_target) + case 'c'.code: + opts |= cast(Compiled, Int); + #end + } } - } this.regex = new Regex(r, cast(opts, RegexOptions)); } - public function match( s : String ) : Bool { + public function match(s:String):Bool { m = regex.Match(s); cur = s; return m.Success; } - public function matched( n : Int ) : String { + public function matched(n:Int):String { if (m == null || cast(n, UInt) > m.Groups.Count) throw "EReg::matched"; - if (!m.Groups[n].Success) return null; + if (!m.Groups[n].Success) + return null; return m.Groups[n].Value; } - public function matchedLeft() : String { + public function matchedLeft():String { return untyped cur.Substring(0, m.Index); } - public function matchedRight() : String { + public function matchedRight():String { return untyped cur.Substring(m.Index + m.Length); } - public function matchedPos() : { pos : Int, len : Int } { - return { pos : m.Index, len : m.Length }; + public function matchedPos():{pos:Int, len:Int} { + return {pos: m.Index, len: m.Length}; } - public function matchSub( s : String, pos : Int, len : Int = -1):Bool { - m= if (len<0) regex.Match(s,pos) else regex.Match(s, pos, len); + public function matchSub(s:String, pos:Int, len:Int = -1):Bool { + m = if (len < 0) regex.Match(s, pos) else regex.Match(s, pos, len); cur = s; return m.Success; } - public function split( s : String ) : Array { + public function split(s:String):Array { if (isGlobal) return cs.Lib.array(regex.Split(s)); var m = regex.Match(s); - if (!m.Success) return [s]; + if (!m.Success) + return [s]; return untyped [s.Substring(0, m.Index), s.Substring(m.Index + m.Length)]; } - inline function start(group:Int) : Int - { + inline function start(group:Int):Int { return m.Groups[group].Index; } - inline function len(group:Int) : Int - { + inline function len(group:Int):Int { return m.Groups[group].Length; } - public function replace( s : String, by : String ) : String - { - return (isGlobal) ? regex.Replace(s, by): regex.Replace(s,by,1); + public function replace(s:String, by:String):String { + return (isGlobal) ? regex.Replace(s, by) : regex.Replace(s, by, 1); } - public function map( s : String, f : EReg -> String ) : String { + public function map(s:String, f:EReg->String):String { var offset = 0; var buf = new StringBuf(); do { @@ -122,8 +121,7 @@ import cs.system.text.regularexpressions.*; if (p.len == 0) { buf.add(s.substr(p.pos, 1)); offset = p.pos + 1; - } - else + } else offset = p.pos + p.len; } while (isGlobal); if (!isGlobal && offset > 0 && offset < s.length) @@ -131,7 +129,7 @@ import cs.system.text.regularexpressions.*; return buf.toString(); } - public static inline function escape( s : String ) : String { + public static inline function escape(s:String):String { return Regex.Escape(s); } } diff --git a/std/cs/_std/Math.hx b/std/cs/_std/Math.hx index 3b867070bcb..0bc15157ed7 100644 --- a/std/cs/_std/Math.hx +++ b/std/cs/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,91 +19,76 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -@:coreApi @:nativeGen class Math -{ +@:coreApi @:nativeGen class Math { @:readOnly private static var rand = new cs.system.Random(); @:readOnly - public static var PI(default,null) = cs.system.Math.PI; + public static var PI(default, null) = cs.system.Math.PI; @:readOnly - public static var NaN(default,null) = cs.system.Double.NaN; + public static var NaN(default, null) = cs.system.Double.NaN; @:readOnly - public static var NEGATIVE_INFINITY(default,null) = cs.system.Double.NegativeInfinity; + public static var NEGATIVE_INFINITY(default, null) = cs.system.Double.NegativeInfinity; @:readOnly - public static var POSITIVE_INFINITY(default,null) = cs.system.Double.PositiveInfinity; + public static var POSITIVE_INFINITY(default, null) = cs.system.Double.PositiveInfinity; - public static inline function abs(v:Float):Float - { + public static inline function abs(v:Float):Float { return cs.system.Math.Abs(v); } - public static inline function min(a:Float, b:Float):Float - { - return cs.system.Math.Min(a,b); + public static inline function min(a:Float, b:Float):Float { + return cs.system.Math.Min(a, b); } - public static inline function max(a:Float, b:Float):Float - { - return cs.system.Math.Max(a,b); + public static inline function max(a:Float, b:Float):Float { + return cs.system.Math.Max(a, b); } - public static inline function sin(v:Float):Float - { + public static inline function sin(v:Float):Float { return cs.system.Math.Sin(v); } - public static inline function cos(v:Float):Float - { + public static inline function cos(v:Float):Float { return cs.system.Math.Cos(v); } - public static inline function atan2(y:Float, x:Float):Float - { + public static inline function atan2(y:Float, x:Float):Float { return cs.system.Math.Atan2(y, x); } - public static inline function tan(v:Float):Float - { + public static inline function tan(v:Float):Float { return cs.system.Math.Tan(v); } - public static inline function exp(v:Float):Float - { + public static inline function exp(v:Float):Float { return cs.system.Math.Exp(v); } - public static inline function log(v:Float):Float - { + public static inline function log(v:Float):Float { return cs.system.Math.Log(v); } - public static inline function sqrt(v:Float):Float - { + public static inline function sqrt(v:Float):Float { return cs.system.Math.Sqrt(v); } - public static inline function fround(v:Float):Float - { + public static inline function fround(v:Float):Float { return cs.system.Math.Floor(v + 0.5); } - public static inline function ffloor(v:Float):Float - { + public static inline function ffloor(v:Float):Float { return cs.system.Math.Floor(v); } - public static inline function fceil(v:Float):Float - { + public static inline function fceil(v:Float):Float { return cs.system.Math.Ceiling(v); } - public static function round(v:Float):Int - { + public static function round(v:Float):Int { var vint = Std.int(v); var dec = v - vint; if (dec >= 1 || dec <= -1) - return vint; //overflow + return vint; // overflow if (dec >= .5) return vint + 1; if (dec < -.5) @@ -111,48 +96,39 @@ return vint; } - public static inline function floor(v:Float):Int - { + public static inline function floor(v:Float):Int { return Std.int(cs.system.Math.Floor(v)); } - public static inline function ceil(v:Float):Int - { + public static inline function ceil(v:Float):Int { return Std.int(cs.system.Math.Ceiling(v)); } - public static inline function atan(v:Float):Float - { + public static inline function atan(v:Float):Float { return cs.system.Math.Atan(v); } - public static inline function asin(v:Float):Float - { + public static inline function asin(v:Float):Float { return cs.system.Math.Asin(v); } - public static inline function acos(v:Float):Float - { + public static inline function acos(v:Float):Float { return cs.system.Math.Acos(v); } - public static inline function pow(v:Float, exp:Float):Float - { + public static inline function pow(v:Float, exp:Float):Float { return cs.system.Math.Pow(v, exp); } - public static inline function random() : Float - { + public static inline function random():Float { return rand.NextDouble(); } - public static inline function isFinite( f : Float ) : Bool - { + public static inline function isFinite(f:Float):Bool { return !cs.system.Double.IsInfinity(f) && !cs.system.Double.IsNaN(f); } - public static inline function isNaN( f : Float ) : Bool - { + public static inline function isNaN(f:Float):Bool { return cs.system.Double.IsNaN(f); } } diff --git a/std/cs/_std/Reflect.hx b/std/cs/_std/Reflect.hx index f8f93a3a9eb..c02c7e46646 100644 --- a/std/cs/_std/Reflect.hx +++ b/std/cs/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,9 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import cs.internal.Function; import cs.system.reflection.*; - import cs.internal.*; import cs.internal.HxObject; import cs.internal.Runtime; @@ -31,38 +31,36 @@ import cs.system.Object; import cs.system.reflection.*; @:coreApi class Reflect { + public static function hasField(o:Dynamic, field:String):Bool { + var ihx:IHxObject = Lib.as(o, IHxObject); + if (ihx != null) + return untyped ihx.__hx_getField(field, FieldLookup.hash(field), false, true, false) != Runtime.undefined; - public static function hasField( o : Dynamic, field : String ) : Bool - { - var ihx:IHxObject = Lib.as(o,IHxObject); - if (ihx != null) return untyped ihx.__hx_getField(field, FieldLookup.hash(field), false, true, false) != Runtime.undefined; - - return Runtime.slowHasField(o,field); + return Runtime.slowHasField(o, field); } @:keep - public static function field( o : Dynamic, field : String ) : Dynamic - { - var ihx:IHxObject = Lib.as(o,IHxObject); - if (ihx != null) return untyped ihx.__hx_getField(field, FieldLookup.hash(field), false, false, false); + public static function field(o:Dynamic, field:String):Dynamic { + var ihx:IHxObject = Lib.as(o, IHxObject); + if (ihx != null) + return untyped ihx.__hx_getField(field, FieldLookup.hash(field), false, false, false); - return Runtime.slowGetField(o,field,false); + return Runtime.slowGetField(o, field, false); } @:keep - public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void - { - var ihx:IHxObject = Lib.as(o,IHxObject); + public static function setField(o:Dynamic, field:String, value:Dynamic):Void { + var ihx:IHxObject = Lib.as(o, IHxObject); if (ihx != null) untyped ihx.__hx_setField(field, FieldLookup.hash(field), value, false); else - Runtime.slowSetField(o,field,value); + Runtime.slowSetField(o, field, value); } - public static function getProperty( o : Dynamic, field : String ) : Dynamic - { - var ihx:IHxObject = Lib.as(o,IHxObject); - if (ihx != null) return untyped ihx.__hx_getField(field, FieldLookup.hash(field), false, false, true); + public static function getProperty(o:Dynamic, field:String):Dynamic { + var ihx:IHxObject = Lib.as(o, IHxObject); + if (ihx != null) + return untyped ihx.__hx_getField(field, FieldLookup.hash(field), false, false, true); if (Runtime.slowHasField(o, "get_" + field)) return Runtime.slowCallField(o, "get_" + field, null); @@ -70,70 +68,60 @@ import cs.system.reflection.*; return Runtime.slowGetField(o, field, false); } - public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void - { - var ihx:IHxObject = Lib.as(o,IHxObject); + public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void { + var ihx:IHxObject = Lib.as(o, IHxObject); if (ihx != null) untyped ihx.__hx_setField(field, FieldLookup.hash(field), value, true); else if (Runtime.slowHasField(o, 'set_$field')) Runtime.slowCallField(o, 'set_$field', cs.NativeArray.make(value)); else - Runtime.slowSetField(o,field,value); + Runtime.slowSetField(o, field, value); } - public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic - { - var args = cs.Lib.nativeArray(args,true); + public static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array):Dynamic { + var args = cs.Lib.nativeArray(args, true); return untyped cast(func, Function).__hx_invokeDynamic(args); } @:keep - public static function fields( o : Dynamic ) : Array - { - var ihx = Lib.as(o,IHxObject); - if (ihx != null) - { + public static function fields(o:Dynamic):Array { + var ihx = Lib.as(o, IHxObject); + if (ihx != null) { var ret = []; untyped ihx.__hx_getFields(ret); return ret; } else if (Std.is(o, cs.system.Type)) { return Type.getClassFields(o); } else { - return instanceFields( untyped o.GetType() ); + return instanceFields(untyped o.GetType()); } } - private static function instanceFields( c : Class ) : Array - { + private static function instanceFields(c:Class):Array { var c = cs.Lib.toNativeType(c); var ret = []; var mis = c.GetFields(new cs.Flags(BindingFlags.Public) | BindingFlags.Instance | BindingFlags.FlattenHierarchy); - for (i in 0...mis.Length) - { + for (i in 0...mis.Length) { var i = mis[i]; ret.push(i.Name); } return ret; } - inline public static function isFunction( f : Dynamic ) : Bool - { + inline public static function isFunction(f:Dynamic):Bool { return Std.is(f, Function); } - public static function compare( a : T, b : T ) : Int - { + public static function compare(a:T, b:T):Int { return cs.internal.Runtime.compare(a, b); } @:access(cs.internal.Closure) - public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool - { + public static function compareMethods(f1:Dynamic, f2:Dynamic):Bool { if (f1 == f2) return true; - if (Std.is(f1, Closure) && Std.is(f2, Closure)) - { + if (Std.is(f1, Closure) && Std.is(f2, Closure)) { var f1c:Closure = cast f1; var f2c:Closure = cast f2; @@ -143,35 +131,32 @@ import cs.system.reflection.*; return false; } - public static function isObject( v : Dynamic ) : Bool - { + public static function isObject(v:Dynamic):Bool { return v != null && !(Std.is(v, HxEnum) || Std.is(v, Function) || Std.is(v, cs.system.ValueType)); } - public static function isEnumValue( v : Dynamic ) : Bool { + public static function isEnumValue(v:Dynamic):Bool { return v != null && (Std.is(v, HxEnum) || Std.is(v, cs.system.Enum)); } - public static function deleteField( o : Dynamic, field : String ) : Bool - { - var ihx = Lib.as(o,DynamicObject); + public static function deleteField(o:Dynamic, field:String):Bool { + var ihx = Lib.as(o, DynamicObject); if (ihx != null) return untyped ihx.__hx_deleteField(field, FieldLookup.hash(field)); return false; } - public static function copy( o : T ) : T - { - var o2 : Dynamic = {}; - for( f in Reflect.fields(o) ) - Reflect.setField(o2,f,Reflect.field(o,f)); + public static function copy(o:Null):Null { + if (o == null) + return null; + var o2:Dynamic = {}; + for (f in Reflect.fields(o)) + Reflect.setField(o2, f, Reflect.field(o, f)); return cast o2; } - @:overload(function( f : Array -> Void ) : Dynamic {}) - public static function makeVarArgs( f : Array -> Dynamic ) : Dynamic - { + @:overload(function(f:Array->Void):Dynamic {}) + public static function makeVarArgs(f:Array->Dynamic):Dynamic { return new VarArgsFunction(f); } - } diff --git a/std/cs/_std/Std.hx b/std/cs/_std/Std.hx index 9a1349d40ea..6d700fde3f7 100644 --- a/std/cs/_std/Std.hx +++ b/std/cs/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,23 +19,22 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import cs.Boot; import cs.Lib; import cs.internal.Exceptions; @:coreApi @:nativeGen class Std { - public static function is( v : Dynamic, t : Dynamic ) : Bool - { + public static function is(v:Dynamic, t:Dynamic):Bool { if (v == null) - return t == Dynamic; + return false; if (t == null) return false; var clt = cs.Lib.as(t, cs.system.Type); if (clt == null) return false; - switch(clt.ToString()) - { + switch (clt.ToString()) { case "System.Double": return untyped __cs__('{0} is double || {0} is int', v); case "System.Int32": @@ -63,7 +62,7 @@ import cs.internal.Exceptions; return false; } - public static function string( s : Dynamic ) : String { + public static function string(s:Dynamic):String { if (s == null) return "null"; if (Std.is(s, Bool)) @@ -72,23 +71,22 @@ import cs.internal.Exceptions; return s.ToString(); } - public static function int( x : Float ) : Int { + public static function int(x:Float):Int { return cast x; } - public static function parseInt( x : String ) : Null { - if (x == null) return null; + public static function parseInt(x:String):Null { + if (x == null) + return null; var ret = 0; var base = 10; var i = -1; var len = x.length; - if (StringTools.startsWith(x, "0") && len > 2) - { + if (StringTools.startsWith(x, "0") && len > 2) { var c:Int = cast untyped x[1]; - if (c == 'x'.code || c == 'X'.code) - { + if (c == 'x'.code || c == 'X'.code) { i = 1; base = 16; } @@ -96,13 +94,10 @@ import cs.internal.Exceptions; var foundAny = i != -1; var isNeg = false; - while (++i < len) - { - var c = cast(untyped x[i], Int); //fastCodeAt - if (!foundAny) - { - switch(c) - { + while (++i < len) { + var c = cast(untyped x[i], Int); // fastCodeAt + if (!foundAny) { + switch (c) { case '-'.code: isNeg = true; continue; @@ -113,22 +108,23 @@ import cs.internal.Exceptions; } } - if (c >= '0'.code && c <= '9'.code) - { - if (!foundAny && c == '0'.code) - { + if (c >= '0'.code && c <= '9'.code) { + if (!foundAny && c == '0'.code) { foundAny = true; continue; } - ret *= base; foundAny = true; + ret *= base; + foundAny = true; ret += c - '0'.code; } else if (base == 16) { if (c >= 'a'.code && c <= 'f'.code) { - ret *= base; foundAny = true; + ret *= base; + foundAny = true; ret += c - 'a'.code + 10; } else if (c >= 'A'.code && c <= 'F'.code) { - ret *= base; foundAny = true; + ret *= base; + foundAny = true; ret += c - 'A'.code + 10; } else { break; @@ -144,59 +140,64 @@ import cs.internal.Exceptions; return null; } - public static function parseFloat( x : String ) : Float { - if (x == null) return Math.NaN; + public static function parseFloat(x:String):Float { + if (x == null) + return Math.NaN; x = StringTools.ltrim(x); - var found = false, hasDot = false, hasSign = false, - hasE = false, hasESign = false, hasEData = false; + var found = false, + hasDot = false, + hasSign = false, + hasE = false, + hasESign = false, + hasEData = false; var i = -1; - inline function getch(i:Int):Int return cast ((untyped x : cs.system.String)[i]); + inline function getch(i:Int):Int + return cast((untyped x : cs.system.String)[i]); - while (++i < x.length) - { + while (++i < x.length) { var chr = getch(i); - if (chr >= '0'.code && chr <= '9'.code) - { - if (hasE) - { + if (chr >= '0'.code && chr <= '9'.code) { + if (hasE) { hasEData = true; } found = true; - } else switch (chr) { - case 'e'.code | 'E'.code if(!hasE): - hasE = true; - case '.'.code if (!hasDot): - hasDot = true; - case '-'.code, '+'.code if (!found && !hasSign): - hasSign = true; - case '-'.code | '+'.code if (found && !hasESign && hasE && !hasEData): - hasESign = true; - case _: - break; - } + } else + switch (chr) { + case 'e'.code | 'E'.code if (!hasE): + hasE = true; + case '.'.code if (!hasDot): + hasDot = true; + case '-'.code, '+'.code if (!found && !hasSign): + hasSign = true; + case '-'.code | '+'.code if (found && !hasESign && hasE && !hasEData): + hasESign = true; + case _: + break; + } } - if (hasE && !hasEData) - { + if (hasE && !hasEData) { i--; if (hasESign) i--; } - if (i != x.length) - { - x = x.substr(0,i); + if (i != x.length) { + x = x.substr(0, i); } - return try - cs.system.Double.Parse(x, cs.system.globalization.CultureInfo.InvariantCulture) - catch(e:Dynamic) - Math.NaN; + return try cs.system.Double.Parse(x, cs.system.globalization.CultureInfo.InvariantCulture) catch (e:Dynamic) Math.NaN; + } + + extern inline public static function downcast(value:T, c:Class):S { + return cs.Lib.as(value, c); } - @:extern inline public static function instance( value : T, c : Class ) : S { - return cs.Lib.as(value,c); + @:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.') + extern inline public static function instance(value:T, c:Class):S { + return downcast(value, c); } - public static function random( x : Int ) : Int { - if (x <= 0) return 0; + public static function random(x:Int):Int { + if (x <= 0) + return 0; return untyped Math.rand.Next(x); } } diff --git a/std/cs/_std/String.hx b/std/cs/_std/String.hx index f4af89a28e0..af78337d21c 100644 --- a/std/cs/_std/String.hx +++ b/std/cs/_std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,38 +19,40 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import cs.StdTypes; @:coreApi extern class String implements ArrayAccess { - @:overload private static function Compare(s1:String, s2:String):Int; @:overload private static function Compare(s1:String, s2:String, kind:cs.system.StringComparison):Int; - var length(default,null) : Int; + private static function CompareOrdinal(s1:String, s2:String):Int; - function new(string:String) : Void; + var length(default, null):Int; - function toUpperCase() : String; + function new(string:String):Void; - function toLowerCase() : String; + function toUpperCase():String; - function charAt( index : Int) : String; + function toLowerCase():String; - function charCodeAt( index : Int) : Null; + function charAt(index:Int):String; - function indexOf( str : String, ?startIndex : Int ) : Int; + function charCodeAt(index:Int):Null; - function lastIndexOf( str : String, ?startIndex : Int ) : Int; + function indexOf(str:String, ?startIndex:Int):Int; - function split( delimiter : String ) : Array; + function lastIndexOf(str:String, ?startIndex:Int):Int; - function substr( pos : Int, ?len : Int ) : String; + function split(delimiter:String):Array; - function substring( startIndex : Int, ?endIndex : Int ) : String; + function substr(pos:Int, ?len:Int):String; - function toString() : String; + function substring(startIndex:Int, ?endIndex:Int):String; - static function fromCharCode( code : Int ) : String; + function toString():String; + + static function fromCharCode(code:Int):String; private function IndexOf(value:String, startIndex:Int, comparisonType:cs.system.StringComparison):Int; private function Replace(oldValue:String, newValue:String):String; @@ -62,5 +64,4 @@ import cs.StdTypes; private function CompareTo(obj:Dynamic):Int; @:overload(function(startIndex:Int):String {}) private function Substring(startIndex:Int, length:Int):String; - } diff --git a/std/cs/_std/StringBuf.hx b/std/cs/_std/StringBuf.hx index 2fadac9bb2b..b46bb5cb9eb 100644 --- a/std/cs/_std/StringBuf.hx +++ b/std/cs/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,37 +19,42 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import cs.system.text.StringBuilder; @:coreApi class StringBuf { + private var b:StringBuilder; - private var b : StringBuilder; - - public var length(get,never) : Int; + public var length(get, never):Int; - public inline function new() : Void { + public inline function new():Void { b = new StringBuilder(); } - inline function get_length() : Int { + inline function get_length():Int { return b.Length; } - public inline function add( x : T ) : Void { + public inline function add(x:T):Void { b.Append(Std.string(x)); } - public inline function addSub( s : String, pos : Int, ?len : Int ) : Void { + public inline function addSub(s:String, pos:Int, ?len:Int):Void { b.Append(s, pos, (len == null) ? (s.length - pos) : len); } - public inline function addChar( c : Int ) : Void untyped { - b.Append(cast(c, cs.StdTypes.Char16)); - } - - public inline function toString() : String { + public function addChar(c:Int):Void + untyped { + if (c >= 0x10000) { + b.Append(cast((c >> 10) + 0xD7C0, cs.StdTypes.Char16)); + b.Append(cast((c & 0x3FF) + 0xDC00, cs.StdTypes.Char16)); + } else { + b.Append(cast(c, cs.StdTypes.Char16)); + } + } + + public inline function toString():String { return b.ToString(); } - -} \ No newline at end of file +} diff --git a/std/cs/_std/Sys.hx b/std/cs/_std/Sys.hx index edb583bd52c..7cf8d55cf0d 100644 --- a/std/cs/_std/Sys.hx +++ b/std/cs/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import sys.io.Process; import cs.system.Environment; import cs.system.threading.Thread; @@ -28,20 +29,16 @@ class Sys { private static var _env:haxe.ds.StringMap; private static var _args:Array; - public static inline function print( v : Dynamic ) : Void - { + public static inline function print(v:Dynamic):Void { cs.system.Console.Write(v); } - public static inline function println( v : Dynamic ) : Void - { + public static inline function println(v:Dynamic):Void { cs.system.Console.WriteLine(v); } - public static function args() : Array - { - if (_args == null) - { + public static function args():Array { + if (_args == null) { var ret = cs.Lib.array(Environment.GetCommandLineArgs()); ret.shift(); _args = ret; @@ -49,26 +46,21 @@ class Sys { return _args.copy(); } - public static inline function getEnv( s : String ) : String - { + public static inline function getEnv(s:String):String { return Environment.GetEnvironmentVariable(s); } - public static function putEnv( s : String, v : String ) : Void - { + public static function putEnv(s:String, v:String):Void { Environment.SetEnvironmentVariable(s, v); if (_env != null) _env.set(s, v); } - public static function environment() : Map - { - if (_env == null) - { + public static function environment():Map { + if (_env == null) { var e = _env = new haxe.ds.StringMap(); var nenv = Environment.GetEnvironmentVariables().GetEnumerator(); - while (nenv.MoveNext()) - { + while (nenv.MoveNext()) { e.set(nenv.Key, nenv.Value); } } @@ -76,35 +68,32 @@ class Sys { return _env; } - public static inline function sleep( seconds : Float ) : Void - { - Thread.Sleep( Std.int(seconds * 1000) ); + public static inline function sleep(seconds:Float):Void { + Thread.Sleep(Std.int(seconds * 1000)); } - public static function setTimeLocale( loc : String ) : Bool - { - //TODO C# + public static function setTimeLocale(loc:String):Bool { + // TODO C# return false; } - public static inline function getCwd() : String - { + public static inline function getCwd():String { return cs.system.io.Directory.GetCurrentDirectory(); } - public static inline function setCwd( s : String ) : Void - { + public static inline function setCwd(s:String):Void { cs.system.io.Directory.SetCurrentDirectory(s); } - public static function systemName() : String - { - //doing a switch with strings since MacOS might not be available - switch(Environment.OSVersion.Platform + "") - { - case "Unix": return "Linux"; - case "Xbox": return "Xbox"; - case "MacOSX": return "Mac"; + public static function systemName():String { + // doing a switch with strings since MacOS might not be available + switch (Environment.OSVersion.Platform + "") { + case "Unix": + return "Linux"; + case "Xbox": + return "Xbox"; + case "MacOSX": + return "Mac"; default: var ver = cast(Environment.OSVersion.Platform, Int); if (ver == 4 || ver == 6 || ver == 128) @@ -113,24 +102,19 @@ class Sys { } } - public static function command( cmd : String, ?args : Array ) : Int - { + public static function command(cmd:String, ?args:Array):Int { var proc = Process.createNativeProcess(cmd, args); - proc.add_OutputDataReceived(new cs.system.diagnostics.DataReceivedEventHandler( - function(p, evtArgs) { - var data = evtArgs.Data; - if (data != null && data != "") - println(data); - } - )); + proc.add_OutputDataReceived(new cs.system.diagnostics.DataReceivedEventHandler(function(p, evtArgs) { + var data = evtArgs.Data; + if (data != null && data != "") + println(data); + })); var stderr = stderr(); - proc.add_ErrorDataReceived(new cs.system.diagnostics.DataReceivedEventHandler( - function(p, evtArgs) { - var data = evtArgs.Data; - if (data != null && data != "") - stderr.writeString(data + "\n"); - } - )); + proc.add_ErrorDataReceived(new cs.system.diagnostics.DataReceivedEventHandler(function(p, evtArgs) { + var data = evtArgs.Data; + if (data != null && data != "") + stderr.writeString(data + "\n"); + })); proc.Start(); proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); @@ -140,65 +124,57 @@ class Sys { return exitCode; } - public static inline function exit( code : Int ) : Void - { + public static inline function exit(code:Int):Void { Environment.Exit(code); } @:readOnly static var epochTicks = new cs.system.DateTime(1970, 1, 1).Ticks; - public static function time() : Float - { + + public static function time():Float { return cast((cs.system.DateTime.UtcNow.Ticks - epochTicks), Float) / cast(cs.system.TimeSpan.TicksPerSecond, Float); } - public static inline function cpuTime() : Float - { + public static inline function cpuTime():Float { return Environment.TickCount / 1000; } - @:deprecated("Use programPath instead") public static inline function executablePath() : String - { + @:deprecated("Use programPath instead") public static inline function executablePath():String { return cs.system.reflection.Assembly.GetExecutingAssembly().GetName().CodeBase; } - public static function programPath() : String { + public static function programPath():String { return cs.system.reflection.Assembly.GetExecutingAssembly().Location; } - public static function getChar( echo : Bool ) : Int - { - #if !(Xbox || CF || MF) //Xbox, Compact Framework, Micro Framework + public static function getChar(echo:Bool):Int { + #if !(Xbox || CF || MF) // Xbox, Compact Framework, Micro Framework return cast(cs.system.Console.ReadKey(!echo).KeyChar, Int); #else return -1; #end } - public static inline function stdin() : haxe.io.Input - { -#if !(Xbox || CF || MF) + public static inline function stdin():haxe.io.Input { + #if !(Xbox || CF || MF) return new cs.io.NativeInput(cs.system.Console.OpenStandardInput()); -#else + #else return null; -#end + #end } - public static inline function stdout() : haxe.io.Output - { -#if !(Xbox || CF || MF) + public static inline function stdout():haxe.io.Output { + #if !(Xbox || CF || MF) return new cs.io.NativeOutput(cs.system.Console.OpenStandardOutput()); -#else + #else return null; -#end + #end } - public static inline function stderr() : haxe.io.Output - { -#if !(Xbox || CF || MF) + public static inline function stderr():haxe.io.Output { + #if !(Xbox || CF || MF) return new cs.io.NativeOutput(cs.system.Console.OpenStandardError()); -#else + #else return null; -#end + #end } - } diff --git a/std/cs/_std/Type.hx b/std/cs/_std/Type.hx index 87dd5b1fb00..1bad536289b 100644 --- a/std/cs/_std/Type.hx +++ b/std/cs/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import cs.Lib; import cs.internal.HxObject; import cs.internal.Runtime; @@ -26,6 +27,7 @@ import cs.internal.Function; import cs.Flags; import cs.system.Object; import cs.system.reflection.*; + using StringTools; enum ValueType { @@ -35,94 +37,99 @@ enum ValueType { TBool; TObject; TFunction; - TClass( c : Class ); - TEnum( e : Enum ); + TClass(c:Class); + TEnum(e:Enum); TUnknown; } @:coreApi class Type { - - public static function getClass( o : T ) : Class { - if (Object.ReferenceEquals(o,null) || Std.is(o,DynamicObject) || Std.is(o,cs.system.Type)) + public static function getClass(o:T):Class { + if (Object.ReferenceEquals(o, null) || Std.is(o, DynamicObject) || Std.is(o, cs.system.Type)) return null; return cast cs.Lib.getNativeType(o); } - public static function getEnum( o : EnumValue ) : Enum { - if (Std.is(o,HxEnum)) + public static function getEnum(o:EnumValue):Enum { + if (Std.is(o, HxEnum)) return cast cs.Lib.getNativeType(o).BaseType; // enum constructors are subclasses of an enum type else if (Std.is(o, cs.system.Enum)) return cast cs.Lib.getNativeType(o); return null; } - public static function getSuperClass( c : Class ) : Class { + public static function getSuperClass(c:Class):Class { var base = Lib.toNativeType(c).BaseType; if (Object.ReferenceEquals(base, null) || base.ToString() == "haxe.lang.HxObject" || base.ToString() == "System.Object") return null; return Lib.fromNativeType(base); } - public static function getClassName( c : Class ) : String { + public static function getClassName(c:Class):String { var ret = Lib.toNativeType(c).ToString(); -#if no_root + #if no_root if (ret.length > 10 && StringTools.startsWith(ret, "haxe.root.")) ret = ret.substr(10); -#end + #end return switch (ret) { // TODO: are those really needed? case "System.Int32": "Int"; case "System.Double": "Float"; case "System.String": "String"; + case "System.Boolean": "Bool"; case "System.Object": "Dynamic"; case "System.Type": "Class"; - default: cast(ret,cs.system.String).Split(cs.NativeArray.make(("`".code : cs.StdTypes.Char16)))[0]; + default: cast(ret, cs.system.String).Split(cs.NativeArray.make(("`".code : cs.StdTypes.Char16)))[0]; } } - public static function getEnumName( e : Enum ) : String { + public static function getEnumName(e:Enum):String { var ret = Lib.toNativeType(cast e).ToString(); -#if no_root + #if no_root if (ret.length > 10 && StringTools.startsWith(ret, "haxe.root.")) ret = ret.substr(10); -#end + #end return ret; } - public static function resolveClass( name : String ) : Class { -#if no_root + public static function resolveClass(name:String):Class { + #if no_root if (name.indexOf(".") == -1) name = "haxe.root." + name; -#end + #end var t = cs.system.Type._GetType(name); -#if !CF - if (Object.ReferenceEquals(t,null)) - { + #if !CF + if (Object.ReferenceEquals(t, null)) { var all = cs.system.AppDomain.CurrentDomain.GetAssemblies().GetEnumerator(); - while (all.MoveNext()) - { + while (all.MoveNext()) { var t2:cs.system.reflection.Assembly = all.Current; t = t2.GetType(name); if (!Object.ReferenceEquals(t, null)) break; } } -#end - if (Object.ReferenceEquals(t,null)) - { - switch(name) - { - case #if no_root "haxe.root.Int" #else "Int" #end: return cast Int; - case #if no_root "haxe.root.Float" #else "Float" #end: return cast Float; - case #if no_root "haxe.root.Class" #else "Class" #end: return cast Class; - case #if no_root "haxe.root.Dynamic" #else "Dynamic" #end: return cast Dynamic; - case #if no_root "haxe.root.String" #else "String" #end: return cast String; - default: return null; + #end + if (Object.ReferenceEquals(t, null)) { + switch (name) { + case #if no_root "haxe.root.Int" #else "Int" #end: + return cast Int; + case #if no_root "haxe.root.Float" #else "Float" #end: + return cast Float; + case #if no_root "haxe.root.Class" #else "Class" #end: + return cast Class; + case #if no_root "haxe.root.Dynamic" #else "Dynamic" #end: + return cast Dynamic; + case #if no_root "haxe.root.String" #else "String" #end: + return cast String; + case #if no_root "haxe.root.Bool" #else "Bool" #end: + return cast Bool; + default: + return null; } -#if !erase_generics - } else if (t.IsInterface && cast(IGenericObject, cs.system.Type).IsAssignableFrom(t)) { + #if !erase_generics + } + else if (t.IsInterface && cast(IGenericObject, cs.system.Type).IsAssignableFrom(t)) { for (attr in t.GetCustomAttributes(true)) { var g = cs.Lib.as(attr, cs.internal.HxObject.GenericInterface); if (g != null) @@ -130,37 +137,36 @@ enum ValueType { } return Lib.fromNativeType(t); -#end + #end } else { return Lib.fromNativeType(t); } } - public static function resolveEnum( name : String ) : Enum - { + public static function resolveEnum(name:String):Enum { var t = Lib.toNativeType(resolveClass(name)); - if (!Object.ReferenceEquals(t,null) && untyped t.BaseType.Equals( Lib.toNativeType(cs.system.Enum) ) || Lib.toNativeType(HxEnum).IsAssignableFrom(t)) + if (!Object.ReferenceEquals(t, null) + && untyped t.BaseType.Equals(Lib.toNativeType(cs.system.Enum)) || Lib.toNativeType(HxEnum).IsAssignableFrom(t)) return cast t; return null; } - public static function createInstance( cl : Class, args : Array ) : T - { + public static function createInstance(cl:Class, args:Array):T { if (Object.ReferenceEquals(cl, String)) return args[0]; var t = Lib.toNativeType(cl); if (t.IsInterface) { - //may be generic + // may be generic t = Lib.toNativeType(resolveClass(getClassName(cl))); } var ctors = t.GetConstructors(); - return Runtime.callMethod(null, cast ctors, ctors.Length, cs.Lib.nativeArray(args,true)); + return Runtime.callMethod(null, cast ctors, ctors.Length, cs.Lib.nativeArray(args, true)); } // cache empty constructor arguments so we don't allocate it on each createEmptyInstance call @:protected @:readOnly static var __createEmptyInstance_EMPTY_ARGS = cs.NativeArray.make((cs.internal.Runtime.EmptyObject.EMPTY : Any)); - public static function createEmptyInstance( cl : Class ) : T { + public static function createEmptyInstance(cl:Class):T { var t = Lib.toNativeType(cl); if (cs.system.Object.ReferenceEquals(t, String)) @@ -170,10 +176,8 @@ enum ValueType { return untyped __cs__("(T)(object){0}", ""); #end - var res = try - cs.system.Activator.CreateInstance(t, __createEmptyInstance_EMPTY_ARGS) - catch (_:cs.system.MissingMemberException) - cs.system.Activator.CreateInstance(t); + var res = try cs.system.Activator.CreateInstance(t, + __createEmptyInstance_EMPTY_ARGS) catch (_:cs.system.MissingMemberException) cs.system.Activator.CreateInstance(t); #if erase_generics return res; @@ -182,42 +186,36 @@ enum ValueType { #end } - public static function createEnum( e : Enum, constr : String, ?params : Array ) : T - { - if (params == null || params.length == 0) - { + public static function createEnum(e:Enum, constr:String, ?params:Array):T { + if (params == null || params.length == 0) { var ret = cs.internal.Runtime.slowGetField(e, constr, true); if (Reflect.isFunction(ret)) throw 'Constructor $constr needs parameters'; return ret; } else { - return cs.internal.Runtime.slowCallField(e,constr,cs.Lib.nativeArray(params,true)); + return cs.internal.Runtime.slowCallField(e, constr, cs.Lib.nativeArray(params, true)); } } - public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T { + public static function createEnumIndex(e:Enum, index:Int, ?params:Array):T { var constr = getEnumConstructs(e); return createEnum(e, constr[index], params); } - public static function getInstanceFields( c : Class ) : Array - { + public static function getInstanceFields(c:Class):Array { if (c == String) return cs.internal.StringExt.StringRefl.fields; var c = cs.Lib.toNativeType(c); var ret = []; var mis = c.GetMembers(new cs.Flags(BindingFlags.Public) | BindingFlags.Instance | BindingFlags.FlattenHierarchy); - for (i in 0...mis.Length) - { + for (i in 0...mis.Length) { var i = mis[i]; if (Std.is(i, PropertyInfo)) continue; var n = i.Name; - if (!n.startsWith('__hx_') && n.fastCodeAt(0) != '.'.code) - { - switch(n) - { + if (!n.startsWith('__hx_') && n.fastCodeAt(0) != '.'.code) { + switch (n) { case 'Equals' | 'ToString' | 'GetHashCode' | 'GetType': case _: ret.push(n); @@ -227,26 +225,23 @@ enum ValueType { return ret; } - public static function getClassFields( c : Class ) : Array { - if (Object.ReferenceEquals(c, String)) - { + public static function getClassFields(c:Class):Array { + if (Object.ReferenceEquals(c, String)) { return ['fromCharCode']; } var ret = []; var infos = Lib.toNativeType(c).GetMembers(new Flags(BindingFlags.Public) | BindingFlags.Static); - for (i in 0...infos.Length) - { + for (i in 0...infos.Length) { var name = infos[i].Name; - if (!name.startsWith('__hx_')) - { + if (!name.startsWith('__hx_')) { ret.push(name); } } return ret; } - public static function getEnumConstructs( e : Enum ) : Array { + public static function getEnumConstructs(e:Enum):Array { var t = cs.Lib.as(e, cs.system.Type); var f = t.GetField("__hx_constructs", new cs.Flags(BindingFlags.Static) | BindingFlags.NonPublic); if (f != null) { @@ -258,12 +253,13 @@ enum ValueType { return cs.Lib.array(cs.system.Enum.GetNames(t)); } - public static function typeof( v : Dynamic ) : ValueType { - if (v == null) return ValueType.TNull; + public static function typeof(v:Dynamic):ValueType { + if (v == null) + return ValueType.TNull; var t = cs.Lib.as(v, cs.system.Type); if (!Object.ReferenceEquals(t, null)) { - //class type + // class type return ValueType.TObject; } @@ -276,7 +272,8 @@ enum ValueType { var vc:cs.system.IConvertible = cast v; if (vc != null) { switch (vc.GetTypeCode()) { - case cs.system.TypeCode.Boolean: return ValueType.TBool; + case cs.system.TypeCode.Boolean: + return ValueType.TBool; case cs.system.TypeCode.Double: var d:Float = vc.ToDouble(null); if (d >= cs.system.Int32.MinValue && d <= cs.system.Int32.MaxValue && d == vc.ToInt32(null)) @@ -305,8 +302,7 @@ enum ValueType { } @:ifFeature("has_enum") - public static function enumEq( a : T, b : T ) : Bool - { + public static function enumEq(a:T, b:T):Bool { if (a == null) return b == null; else if (b == null) @@ -315,22 +311,18 @@ enum ValueType { return untyped a.Equals(b); } - public static function enumConstructor( e : EnumValue ) : String - { - return Std.is(e, cs.system.Enum) ? cast(e,cs.system.Enum).ToString() : cast(e,HxEnum).getTag(); + public static function enumConstructor(e:EnumValue):String { + return Std.is(e, cs.system.Enum) ? cast(e, cs.system.Enum).ToString() : cast(e, HxEnum).getTag(); } - public static function enumParameters( e : EnumValue ) : Array - { - return Std.is(e, cs.system.Enum) ? [] : cast(e,HxEnum).getParams(); + public static function enumParameters(e:EnumValue):Array { + return Std.is(e, cs.system.Enum) ? [] : cast(e, HxEnum).getParams(); } @:ifFeature("has_enum") @:pure - public static function enumIndex( e : EnumValue ) : Int - { - if (Std.is(e, cs.system.Enum)) - { + public static function enumIndex(e:EnumValue):Int { + if (Std.is(e, cs.system.Enum)) { var values = cs.system.Enum.GetValues(Lib.getNativeType(e)); return cs.system.Array.IndexOf(values, e); } else { @@ -338,12 +330,10 @@ enum ValueType { } } - public static function allEnums( e : Enum ) : Array - { + public static function allEnums(e:Enum):Array { var ctors = getEnumConstructs(e); var ret = []; - for (ctor in ctors) - { + for (ctor in ctors) { var v = Reflect.field(e, ctor); if (Std.is(v, e)) ret.push(v); @@ -351,6 +341,4 @@ enum ValueType { return ret; } - } - diff --git a/std/cs/_std/haxe/Int64.hx b/std/cs/_std/haxe/Int64.hx index 7f441fbb523..7121df24126 100644 --- a/std/cs/_std/haxe/Int64.hx +++ b/std/cs/_std/haxe/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; + using haxe.Int64; import haxe.Int64Helper; @@ -27,202 +29,209 @@ import haxe.Int64Helper; private typedef __Int64 = cs.StdTypes.Int64; @:coreApi -abstract Int64(__Int64) from __Int64 to __Int64 -{ +abstract Int64(__Int64) from __Int64 to __Int64 { + public static inline function make(high:Int32, low:Int32):Int64 + return new Int64((cast(high, __Int64) << 32) | (cast(low, __Int64) & (untyped __cs__('0xffffffffL') : Int64))); - public static inline function make( high : Int32, low : Int32 ) : Int64 - return new Int64( (cast(high, __Int64) << 32) | (cast(low, __Int64)& (untyped __cs__('0xffffffffL') : Int64)) ); - - private inline function new(x : __Int64) + private inline function new(x:__Int64) this = x; - private var val( get, set ) : __Int64; - inline function get_val() : __Int64 return this; - inline function set_val( x : __Int64 ) : __Int64 return this = x; + private var val(get, set):__Int64; + + inline function get_val():__Int64 + return this; + + inline function set_val(x:__Int64):__Int64 + return this = x; + + public var high(get, never):Int32; + + public inline function get_high():Int32 + return cast(this >> 32); - public var high( get, never ):Int32; - public inline function get_high():Int32 return cast(this >> 32); + public var low(get, never):Int32; - public var low( get, never ):Int32; - public inline function get_low():Int32 return cast this; + public inline function get_low():Int32 + return cast this; public inline function copy():Int64 - return new Int64( this ); + return new Int64(this); - @:from public static inline function ofInt( x : Int ) : Int64 + @:from public static inline function ofInt(x:Int):Int64 return cast x; - public static inline function toInt( x : Int64 ) : Int { - if( x.val < 0x80000000 || x.val > 0x7FFFFFFF ) + public static inline function toInt(x:Int64):Int { + if (x.val < 0x80000000 || x.val > 0x7FFFFFFF) throw "Overflow"; return cast x.val; } - inline public static function is( val : Dynamic ) : Bool - return Std.is(val,cs.system.Int64); + inline public static function is(val:Dynamic):Bool + return Std.is(val, cs.system.Int64); - public static inline function getHigh( x : Int64 ) : Int32 - return cast( x.val >> 32 ); + public static inline function getHigh(x:Int64):Int32 + return cast(x.val >> 32); - public static inline function getLow( x : Int64 ) : Int32 - return cast( x.val ); + public static inline function getLow(x:Int64):Int32 + return cast(x.val); - public static inline function isNeg( x : Int64 ) : Bool + public static inline function isNeg(x:Int64):Bool return x.val < 0; - public static inline function isZero( x : Int64 ) : Bool + public static inline function isZero(x:Int64):Bool return x.val == 0; - public static inline function compare( a : Int64, b : Int64 ) : Int - { - if( a.val < b.val ) return -1; - if( a.val > b.val ) return 1; + public static inline function compare(a:Int64, b:Int64):Int { + if (a.val < b.val) + return -1; + if (a.val > b.val) + return 1; return 0; } - public static inline function ucompare( a : Int64, b : Int64 ) : Int { - if( a.val < 0 ) - return ( b.val < 0 ) ? compare( a, b ) : 1; - return ( b.val < 0 ) ? -1 : compare( a, b ); + public static inline function ucompare(a:Int64, b:Int64):Int { + if (a.val < 0) + return (b.val < 0) ? compare(a, b) : 1; + return (b.val < 0) ? -1 : compare(a, b); } - public static inline function toStr( x : Int64 ) : String + public static inline function toStr(x:Int64):String return '${x.val}'; - public static inline function divMod( dividend : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 } - return { quotient: dividend / divisor, modulus: dividend % divisor }; + public static inline function divMod(dividend:Int64, divisor:Int64):{quotient:Int64, modulus:Int64} + return {quotient: dividend / divisor, modulus: dividend % divisor}; - private inline function toString() : String + private inline function toString():String return '$this'; - public static function parseString( sParam : String ) : Int64 { - return Int64Helper.parseString( sParam ); + public static function parseString(sParam:String):Int64 { + return Int64Helper.parseString(sParam); } - public static function fromFloat( f : Float ) : Int64 { - return Int64Helper.fromFloat( f ); + public static function fromFloat(f:Float):Int64 { + return Int64Helper.fromFloat(f); } - @:op(-A) public static function neg( x : Int64 ) : Int64 + @:op(-A) public static function neg(x:Int64):Int64 return -x.val; - @:op(++A) private inline function preIncrement() : Int64 + @:op(++A) private inline function preIncrement():Int64 return ++this; - @:op(A++) private inline function postIncrement() : Int64 + @:op(A++) private inline function postIncrement():Int64 return this++; - @:op(--A) private inline function preDecrement() : Int64 + @:op(--A) private inline function preDecrement():Int64 return --this; - @:op(A--) private inline function postDecrement() : Int64 + @:op(A--) private inline function postDecrement():Int64 return this--; - @:op(A + B) public static inline function add( a : Int64, b : Int64 ) : Int64 + @:op(A + B) public static inline function add(a:Int64, b:Int64):Int64 return a.val + b.val; - @:op(A + B) @:commutative private static inline function addInt( a : Int64, b : Int ) : Int64 + @:op(A + B) @:commutative private static inline function addInt(a:Int64, b:Int):Int64 return a.val + b; - @:op(A - B) public static inline function sub( a : Int64, b : Int64 ) : Int64 + @:op(A - B) public static inline function sub(a:Int64, b:Int64):Int64 return a.val - b.val; - @:op(A - B) private static inline function subInt( a : Int64, b : Int ) : Int64 + @:op(A - B) private static inline function subInt(a:Int64, b:Int):Int64 return a.val - b; - @:op(A - B) private static inline function intSub( a : Int, b : Int64 ) : Int64 + @:op(A - B) private static inline function intSub(a:Int, b:Int64):Int64 return a - b.val; - @:op(A * B) public static inline function mul( a : Int64, b : Int64 ) : Int64 + @:op(A * B) public static inline function mul(a:Int64, b:Int64):Int64 return a.val * b.val; - @:op(A * B) @:commutative private static inline function mulInt( a : Int64, b : Int ) : Int64 + @:op(A * B) @:commutative private static inline function mulInt(a:Int64, b:Int):Int64 return a.val * b; - @:op(A / B) public static inline function div( a : Int64, b : Int64 ) : Int64 + @:op(A / B) public static inline function div(a:Int64, b:Int64):Int64 return a.val / b.val; - @:op(A / B) private static inline function divInt( a : Int64, b : Int ) : Int64 + @:op(A / B) private static inline function divInt(a:Int64, b:Int):Int64 return a.val / b; - @:op(A / B) private static inline function intDiv( a : Int, b : Int64 ) : Int64 + @:op(A / B) private static inline function intDiv(a:Int, b:Int64):Int64 return a / b.val; - @:op(A % B) public static inline function mod( a : Int64, b : Int64 ) : Int64 + @:op(A % B) public static inline function mod(a:Int64, b:Int64):Int64 return a.val % b.val; - @:op(A % B) private static inline function modInt( a : Int64, b : Int ) : Int64 + @:op(A % B) private static inline function modInt(a:Int64, b:Int):Int64 return a.val % b; - @:op(A % B) private static inline function intMod( a : Int, b : Int64 ) : Int64 + @:op(A % B) private static inline function intMod(a:Int, b:Int64):Int64 return a % b.val; - @:op(A == B) public static inline function eq( a : Int64, b : Int64 ) : Bool + @:op(A == B) public static inline function eq(a:Int64, b:Int64):Bool return a.val == b.val; - @:op(A == B) @:commutative private static inline function eqInt( a : Int64, b : Int ) : Bool + @:op(A == B) @:commutative private static inline function eqInt(a:Int64, b:Int):Bool return a.val == b; - @:op(A != B) public static inline function neq( a : Int64, b : Int64 ) : Bool + @:op(A != B) public static inline function neq(a:Int64, b:Int64):Bool return a.val != b.val; - @:op(A != B) @:commutative private static inline function neqInt( a : Int64, b : Int ) : Bool + @:op(A != B) @:commutative private static inline function neqInt(a:Int64, b:Int):Bool return a.val != b; - @:op(A < B) private static inline function lt( a : Int64, b : Int64 ) : Bool + @:op(A < B) private static inline function lt(a:Int64, b:Int64):Bool return a.val < b.val; - @:op(A < B) private static inline function ltInt( a : Int64, b : Int ) : Bool + @:op(A < B) private static inline function ltInt(a:Int64, b:Int):Bool return a.val < b; - @:op(A < B) private static inline function intLt( a : Int, b : Int64 ) : Bool + @:op(A < B) private static inline function intLt(a:Int, b:Int64):Bool return a < b.val; - @:op(A <= B) private static inline function lte( a : Int64, b : Int64 ) : Bool + @:op(A <= B) private static inline function lte(a:Int64, b:Int64):Bool return a.val <= b.val; - @:op(A <= B) private static inline function lteInt( a : Int64, b : Int ) : Bool + @:op(A <= B) private static inline function lteInt(a:Int64, b:Int):Bool return a.val <= b; - @:op(A <= B) private static inline function intLte( a : Int, b : Int64 ) : Bool + @:op(A <= B) private static inline function intLte(a:Int, b:Int64):Bool return a <= b.val; - @:op(A > B) private static inline function gt( a : Int64, b : Int64 ) : Bool + @:op(A > B) private static inline function gt(a:Int64, b:Int64):Bool return a.val > b.val; - @:op(A > B) private static inline function gtInt( a : Int64, b : Int ) : Bool + @:op(A > B) private static inline function gtInt(a:Int64, b:Int):Bool return a.val > b; - @:op(A > B) private static inline function intGt( a : Int, b : Int64 ) : Bool + @:op(A > B) private static inline function intGt(a:Int, b:Int64):Bool return a > b.val; - @:op(A >= B) private static inline function gte( a : Int64, b : Int64 ) : Bool + @:op(A >= B) private static inline function gte(a:Int64, b:Int64):Bool return a.val >= b.val; - @:op(A >= B) private static inline function gteInt( a : Int64, b : Int ) : Bool + @:op(A >= B) private static inline function gteInt(a:Int64, b:Int):Bool return a.val >= b; - @:op(A >= B) private static inline function intGte( a : Int, b : Int64 ) : Bool + @:op(A >= B) private static inline function intGte(a:Int, b:Int64):Bool return a >= b.val; - @:op(~A) private static inline function complement( x : Int64 ) : Int64 + @:op(~A) private static inline function complement(x:Int64):Int64 return ~x.val; - @:op(A & B) public static inline function and( a : Int64, b : Int64 ) : Int64 + @:op(A & B) public static inline function and(a:Int64, b:Int64):Int64 return a.val & b.val; - @:op(A | B) public static inline function or( a : Int64, b : Int64 ) : Int64 + @:op(A | B) public static inline function or(a:Int64, b:Int64):Int64 return a.val | b.val; - @:op(A ^ B) public static inline function xor( a : Int64, b : Int64 ) : Int64 + @:op(A ^ B) public static inline function xor(a:Int64, b:Int64):Int64 return a.val ^ b.val; - @:op(A << B) public static inline function shl( a : Int64, b : Int ) : Int64 + @:op(A << B) public static inline function shl(a:Int64, b:Int):Int64 return a.val << b; - @:op(A >> B) public static inline function shr( a : Int64, b : Int ) : Int64 + @:op(A >> B) public static inline function shr(a:Int64, b:Int):Int64 return a.val >> b; - @:op(A >>> B) public static inline function ushr( a : Int64, b : Int ) : Int64 - return cast ( (a.val : cs.StdTypes.UInt64) >> b ); + @:op(A >>> B) public static inline function ushr(a:Int64, b:Int):Int64 + return cast((a.val : cs.StdTypes.UInt64) >> b); } diff --git a/std/cs/_std/haxe/Resource.hx b/std/cs/_std/haxe/Resource.hx index 958040cc796..bbf50909096 100644 --- a/std/cs/_std/haxe/Resource.hx +++ b/std/cs/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; @:coreApi class Resource { + @:keep static var content:Array; + static var paths:Map; - @:keep static var content : Array; - static var paths : Map; - - @:keep static function getPaths():Map { + @:keep static function getPaths():Map { if (paths != null) return paths; @@ -40,12 +40,12 @@ package haxe; return paths = p; } - public static inline function listNames() : Array { + public static inline function listNames():Array { return content.copy(); } @:access(haxe.io.Path.escape) - public static function getString( name : String ) : String { + public static function getString(name:String):String { name = haxe.io.Path.escape(name, true); var path = getPaths().get(name); if (path == null) @@ -57,7 +57,7 @@ package haxe; } @:access(haxe.io.Path.escape) - public static function getBytes( name : String ) : haxe.io.Bytes { + public static function getBytes(name:String):haxe.io.Bytes { name = haxe.io.Path.escape(name, true); var path = getPaths().get(name); if (path == null) diff --git a/std/cs/_std/haxe/ds/IntMap.hx b/std/cs/_std/haxe/ds/IntMap.hx index 12a3fb1dcfd..2100f78132a 100644 --- a/std/cs/_std/haxe/ds/IntMap.hx +++ b/std/cs/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,6 +21,7 @@ */ package haxe.ds; + import cs.NativeArray; /* @@ -30,8 +31,7 @@ import cs.NativeArray; * Thanks also to Jonas Malaco Filho for his Haxe-written IntMap code inspired by Python tables. * (https://jonasmalaco.com/fossil/test/jonas-haxe/artifact/887b53126e237d6c68951111d594033403889304) */ -@:coreApi class IntMap implements haxe.Constraints.IMap -{ +@:coreApi class IntMap implements haxe.Constraints.IMap { private static inline var HASH_UPPER = 0.7; private var flags:NativeArray; @@ -43,26 +43,22 @@ import cs.NativeArray; private var nOccupied:Int; private var upperBound:Int; -#if !no_map_cache + #if !no_map_cache private var cachedKey:Int; private var cachedIndex:Int; -#end + #end - public function new() : Void - { -#if !no_map_cache + public function new():Void { + #if !no_map_cache cachedIndex = -1; -#end + #end } - public function set( key : Int, value : T ) : Void - { + public function set(key:Int, value:T):Void { var targetIndex:Int; - if (nOccupied >= upperBound) - { - if (nBuckets > (size << 1)) - { - resize(nBuckets - 1); //clear "deleted" elements + if (nOccupied >= upperBound) { + if (nBuckets > (size << 1)) { + resize(nBuckets - 1); // clear "deleted" elements } else { resize(nBuckets + 1); } @@ -71,27 +67,23 @@ import cs.NativeArray; var flags = flags, _keys = _keys; { var mask = nBuckets - 1, - hashedKey = hash(key), - curIndex = hashedKey & mask; + hashedKey = hash(key), + curIndex = hashedKey & mask; - var delKey = -1, - curFlag = 0; + var delKey = -1, curFlag = 0; // to speed things up, don't loop if the first bucket is already free if (isEmpty(getFlag(flags, curIndex))) { targetIndex = curIndex; } else { - var inc = getInc(hashedKey, mask), - last = curIndex; - while (! (_keys[curIndex] == key || isEmpty(curFlag = getFlag(flags, curIndex))) ) - { - if (delKey == -1 && isDel(curFlag)) - { + var inc = getInc(hashedKey, mask), last = curIndex; + while (!(_keys[curIndex] == key || isEmpty(curFlag = getFlag(flags, curIndex)))) { + if (delKey == -1 && isDel(curFlag)) { delKey = curIndex; } curIndex = (curIndex + inc) & mask; -#if debug + #if debug assert(curIndex != last); -#end + #end } if (delKey != -1 && isEmpty(getFlag(flags, curIndex))) { @@ -103,8 +95,7 @@ import cs.NativeArray; } var flag = getFlag(flags, targetIndex); - if (isEmpty(flag)) - { + if (isEmpty(flag)) { _keys[targetIndex] = key; vals[targetIndex] = value; setIsBothFalse(flags, targetIndex); @@ -116,30 +107,26 @@ import cs.NativeArray; setIsBothFalse(flags, targetIndex); size++; } else { -#if debug + #if debug assert(_keys[targetIndex] == key); -#end + #end vals[targetIndex] = value; } } - @:final private function lookup( key : Int ) : Int - { - if (nBuckets != 0) - { + final private function lookup(key:Int):Int { + if (nBuckets != 0) { var flags = flags, _keys = _keys; var mask = nBuckets - 1, - k = hash(key), - index = k & mask, - curFlag = -1, - inc = getInc(k, mask), /* inc == 1 for linear probing */ - last = index; - do - { + k = hash(key), + index = k & mask, + curFlag = -1, + inc = getInc(k, mask), /* inc == 1 for linear probing */ + last = index; + do { if (_keys[index] == key) { - if (isEmpty(curFlag = getFlag(flags, index))) - { + if (isEmpty(curFlag = getFlag(flags, index))) { index = (index + inc) & mask; continue; } else if (isDel(curFlag)) { @@ -156,69 +143,60 @@ import cs.NativeArray; return -1; } - public function get( key : Int ) : Null - { + public function get(key:Int):Null { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } return null; } - private function getDefault( key : Int, def : T ) : T - { + private function getDefault(key:Int, def:T):T { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } return def; } - public function exists( key : Int ) : Bool - { + public function exists(key:Int):Bool { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return true; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return true; } @@ -226,28 +204,24 @@ import cs.NativeArray; return false; } - public function remove( key : Int ) : Bool - { + public function remove(key:Int):Bool { var idx = -1; -#if !no_map_cache - if (! (cachedKey == key && ( (idx = cachedIndex) != -1 ))) -#end + #if !no_map_cache + if (!(cachedKey == key && ((idx = cachedIndex) != -1))) + #end { idx = lookup(key); } - if (idx == -1) - { + if (idx == -1) { return false; } else { -#if !no_map_cache - if (cachedKey == key) - { + #if !no_map_cache + if (cachedKey == key) { cachedIndex = -1; } -#end - if (!isEither(getFlag(flags, idx))) - { + #end + if (!isEither(getFlag(flags, idx))) { setIsDelTrue(flags, idx); --size; @@ -263,59 +237,53 @@ import cs.NativeArray; } } - @:final private function resize(newNBuckets:Int) : Void - { - //This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. + final private function resize(newNBuckets:Int):Void { + // This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. var newFlags = null; var j = 1; { newNBuckets = roundUp(newNBuckets); - if (newNBuckets < 4) newNBuckets = 4; - if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */ - { + if (newNBuckets < 4) + newNBuckets = 4; + if (size >= (newNBuckets * HASH_UPPER + 0.5)) + /* requested size is too small */ { j = 0; } else { /* hash table size to be changed (shrink or expand); rehash */ var nfSize = flagsSize(newNBuckets); - newFlags = new NativeArray( nfSize ); - for (i in 0...nfSize) - { + newFlags = new NativeArray(nfSize); + for (i in 0...nfSize) { newFlags[i] = 0xaaaaaaaa; // isEmpty = true; isDel = false } - if (nBuckets < newNBuckets) //expand + if (nBuckets < newNBuckets) // expand { var k = new NativeArray(newNBuckets); - if (_keys != null) - { + if (_keys != null) { arrayCopy(_keys, 0, k, 0, nBuckets); } _keys = k; var v = new NativeArray(newNBuckets); - if (vals != null) - { + if (vals != null) { arrayCopy(vals, 0, v, 0, nBuckets); } vals = v; - } //otherwise shrink + } // otherwise shrink } } - if (j != 0) - { //rehashing is required -#if !no_map_cache - //resetting cache + if (j != 0) { // rehashing is required + #if !no_map_cache + // resetting cache cachedKey = 0; cachedIndex = -1; -#end + #end j = -1; var nBuckets = nBuckets, _keys = _keys, vals = vals, flags = flags; var newMask = newNBuckets - 1; - while (++j < nBuckets) - { - if (!isEither(getFlag(flags, j))) - { + while (++j < nBuckets) { + if (!isEither(getFlag(flags, j))) { var key = _keys[j]; var val = vals[j]; @@ -323,25 +291,23 @@ import cs.NativeArray; // _keys[j] = 0; vals[j] = cast null; setIsDelTrue(flags, j); - while (true) /* kick-out process; sort of like in Cuckoo hashing */ - { + while (true) + /* kick-out process; sort of like in Cuckoo hashing */ { var k = hash(key); var inc = getInc(k, newMask); var i = k & newMask; - while (!isEmpty(getFlag(newFlags, i))) - { + while (!isEmpty(getFlag(newFlags, i))) { i = (i + inc) & newMask; } setIsEmptyFalse(newFlags, i); - if (i < nBuckets && !isEither(getFlag(flags, i))) /* kick out the existing element */ - { + if (i < nBuckets && !isEither(getFlag(flags, i))) + /* kick out the existing element */ { { var tmp = _keys[i]; _keys[i] = key; key = tmp; - } - { + } { var tmp = vals[i]; vals[i] = val; val = tmp; @@ -357,14 +323,13 @@ import cs.NativeArray; } } - if (nBuckets > newNBuckets) /* shrink the hash table */ - { + if (nBuckets > newNBuckets) + /* shrink the hash table */ { { var k = new NativeArray(newNBuckets); arrayCopy(_keys, 0, k, 0, newNBuckets); this._keys = k; - } - { + } { var v = new NativeArray(newNBuckets); arrayCopy(vals, 0, v, 0, newNBuckets); this.vals = v; @@ -378,70 +343,60 @@ import cs.NativeArray; } } - /** - Returns an iterator of all keys in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function keys() : Iterator - { + public inline function keys():Iterator { return new IntMapKeyIterator(this); } - /** - Returns an iterator of all values in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function iterator() : Iterator - { + public inline function iterator():Iterator { return new IntMapValueIterator(this); } - public function copy() : IntMap { + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():IntMap { var copied = new IntMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - /** - Returns an displayable representation of the hashtable content. - **/ - - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(i); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - private static inline function assert(x:Bool):Void - { + private static inline function assert(x:Bool):Void { #if debug - if (!x) throw "assert failed"; + if (!x) + throw "assert failed"; #end } - private static inline function defaultK():Int return 0; + private static inline function defaultK():Int + return 0; - private static inline function arrayCopy(sourceArray:cs.system.Array, sourceIndex:Int, destinationArray:cs.system.Array, destinationIndex:Int, length:Int):Void - { + private static inline function arrayCopy(sourceArray:cs.system.Array, sourceIndex:Int, destinationArray:cs.system.Array, destinationIndex:Int, + length:Int):Void { cs.system.Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length); } - private static inline function getInc(k:Int, mask:Int):Int - { + private static inline function getInc(k:Int, mask:Int):Int { return (((k) >> 3 ^ (k) << 3) | 1) & (mask); } - private static inline function hash(i:Int):Int - { + private static inline function hash(i:Int):Int { return i; } @@ -451,18 +406,15 @@ import cs.NativeArray; // * gets the integer with (flags / 16) // * shifts those bits to the right ((flags % 16) * 2) places // * masks it with 0b11 - private static inline function getFlag(flags:NativeArray, i:Int):Int - { - return ( (flags[i >> 4] >>> ((i & 0xf) << 1)) & 3 ); + private static inline function getFlag(flags:NativeArray, i:Int):Int { + return ((flags[i >> 4] >>> ((i & 0xf) << 1)) & 3); } - private static inline function isDel(flag:Int):Bool - { + private static inline function isDel(flag:Int):Bool { return (flag & 1) != 0; } - private static inline function isEmpty(flag:Int):Bool - { + private static inline function isEmpty(flag:Int):Bool { return (flag & 2) != 0; } @@ -470,28 +422,23 @@ import cs.NativeArray; return flag != 0; } - private static inline function setIsDelFalse(flags:NativeArray, i:Int):Void - { + private static inline function setIsDelFalse(flags:NativeArray, i:Int):Void { flags[i >> 4] &= ~(1 << ((i & 0xf) << 1)); } - private static inline function setIsEmptyFalse(flags:NativeArray, i:Int):Void - { + private static inline function setIsEmptyFalse(flags:NativeArray, i:Int):Void { flags[i >> 4] &= ~(2 << ((i & 0xf) << 1)); } - private static inline function setIsBothFalse(flags:NativeArray, i:Int):Void - { + private static inline function setIsBothFalse(flags:NativeArray, i:Int):Void { flags[i >> 4] &= ~(3 << ((i & 0xf) << 1)); } - private static inline function setIsDelTrue(flags:NativeArray, i:Int):Void - { + private static inline function setIsDelTrue(flags:NativeArray, i:Int):Void { flags[i >> 4] |= 1 << ((i & 0xf) << 1); } - private static inline function roundUp(x:Int):Int - { + private static inline function roundUp(x:Int):Int { --x; x |= (x) >>> 1; x |= (x) >>> 2; @@ -501,33 +448,26 @@ import cs.NativeArray; return ++x; } - private static inline function flagsSize(m:Int):Int - { - return ((m) < 16? 1 : (m) >> 4); + private static inline function flagsSize(m:Int):Int { + return ((m) < 16 ? 1 : (m) >> 4); } } @:access(haxe.ds.IntMap) -@:final -private class IntMapKeyIterator -{ +private final class IntMapKeyIterator { var m:IntMap; var i:Int; var len:Int; - public function new(m:IntMap) - { + public function new(m:IntMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } - public function hasNext():Bool - { - for (j in i...len) - { - if (!IntMap.isEither(IntMap.getFlag(m.flags, j))) - { + public function hasNext():Bool { + for (j in i...len) { + if (!IntMap.isEither(IntMap.getFlag(m.flags, j))) { i = j; return true; } @@ -535,38 +475,32 @@ private class IntMapKeyIterator return false; } - public function next():Int - { + public function next():Int { var ret = m._keys[i]; -#if !no_map_cache + #if !no_map_cache m.cachedIndex = i; m.cachedKey = ret; -#end + #end i++; return ret; } } @:access(haxe.ds.IntMap) -@:final -private class IntMapValueIterator -{ +private final class IntMapValueIterator { var m:IntMap; var i:Int; var len:Int; - public function new(m:IntMap) - { + public function new(m:IntMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } public function hasNext():Bool { - for (j in i...len) - { - if (!IntMap.isEither(IntMap.getFlag(m.flags, j))) - { + for (j in i...len) { + if (!IntMap.isEither(IntMap.getFlag(m.flags, j))) { i = j; return true; } @@ -574,8 +508,7 @@ private class IntMapValueIterator return false; } - public inline function next():T - { + public inline function next():T { return m.vals[i++]; } } diff --git a/std/cs/_std/haxe/ds/ObjectMap.hx b/std/cs/_std/haxe/ds/ObjectMap.hx index f3f85afd0c2..f6d83a3620a 100644 --- a/std/cs/_std/haxe/ds/ObjectMap.hx +++ b/std/cs/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,15 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; import cs.NativeArray; -@:coreApi class ObjectMap implements haxe.Constraints.IMap -{ - @:extern private static inline var HASH_UPPER = 0.77; - @:extern private static inline var FLAG_EMPTY = 0; - @:extern private static inline var FLAG_DEL = 1; +@:coreApi class ObjectMap implements haxe.Constraints.IMap { + extern private static inline var HASH_UPPER = 0.77; + extern private static inline var FLAG_EMPTY = 0; + extern private static inline var FLAG_DEL = 1; /** * This is the most important structure here and the reason why it's so fast. @@ -38,6 +38,7 @@ import cs.NativeArray; * The insertion algorithm will do the same but will also break when FLAG_DEL is found; */ private var hashes:NativeArray; + private var _keys:NativeArray; private var vals:NativeArray; @@ -46,32 +47,29 @@ import cs.NativeArray; private var nOccupied:Int; private var upperBound:Int; -#if !no_map_cache + #if !no_map_cache private var cachedKey:K; private var cachedIndex:Int; -#end + #end -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL private var totalProbes:Int; private var probeTimes:Int; private var sameHash:Int; private var maxProbe:Int; -#end + #end - public function new() : Void - { -#if !no_map_cache + public function new():Void { + #if !no_map_cache cachedIndex = -1; -#end + #end } - public function set( key : K, value : V ) : Void - { + public function set(key:K, value:V):Void { var x:Int, k:Int; - if (nOccupied >= upperBound) - { + if (nOccupied >= upperBound) { if (nBuckets > (size << 1)) - resize(nBuckets - 1); //clear "deleted" elements + resize(nBuckets - 1); // clear "deleted" elements else resize(nBuckets + 2); } @@ -84,22 +82,21 @@ import cs.NativeArray; var i = k & mask, nProbes = 0; var delKey = -1; - //for speed up + // for speed up if (isEmpty(hashes[i])) { x = i; } else { - //var inc = getInc(k, mask); + // var inc = getInc(k, mask); var last = i, flag; - while(! (isEmpty(flag = hashes[i]) || (flag == k && _keys[i] == key)) ) - { + while (!(isEmpty(flag = hashes[i]) || (flag == k && _keys[i] == key))) { if (isDel(flag) && delKey == -1) delKey = i; i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } if (isEmpty(flag) && delKey != -1) @@ -108,16 +105,15 @@ import cs.NativeArray; x = i; } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end } var flag = hashes[x]; - if (isEmpty(flag)) - { + if (isEmpty(flag)) { keys[x] = key; vals[x] = value; hashes[x] = k; @@ -133,58 +129,55 @@ import cs.NativeArray; vals[x] = value; } -#if !no_map_cache + #if !no_map_cache cachedIndex = x; cachedKey = key; -#end + #end } - @:final private function lookup( key : K ) : Int - { - if (nBuckets != 0) - { + private final function lookup(key:K):Int { + if (nBuckets != 0) { var hashes = hashes, keys = _keys; var mask = nBuckets - 1, hash = hash(key), k = hash, nProbes = 0; var i = k & mask; var last = i, flag; - //var inc = getInc(k, mask); - while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || keys[i] != key)) - { + // var inc = getInc(k, mask); + while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || keys[i] != key)) { i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end return isEither(flag) ? -1 : i; } return -1; } - @:final @:private function resize(newNBuckets:Int) : Void - { - //This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. + final function resize(newNBuckets:Int):Void { + // This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. var newHash = null; var j = 1; { newNBuckets = roundUp(newNBuckets); - if (newNBuckets < 4) newNBuckets = 4; - if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */ - { + if (newNBuckets < 4) + newNBuckets = 4; + if (size >= (newNBuckets * HASH_UPPER + 0.5)) + /* requested size is too small */ { j = 0; } else { /* hash table size to be changed (shrink or expand); rehash */ var nfSize = newNBuckets; - newHash = new NativeArray( nfSize ); - if (nBuckets < newNBuckets) //expand + newHash = new NativeArray(nfSize); + if (nBuckets < newNBuckets) // expand { var k = new NativeArray(newNBuckets); if (_keys != null) @@ -195,37 +188,37 @@ import cs.NativeArray; if (vals != null) arrayCopy(vals, 0, v, 0, nBuckets); vals = v; - } //otherwise shrink + } // otherwise shrink } } - if (j != 0) - { //rehashing is required -#if !no_map_cache - //resetting cache + if (j != 0) { // rehashing is required + #if !no_map_cache + // resetting cache cachedKey = null; cachedIndex = -1; -#end + #end j = -1; - var nBuckets = nBuckets, _keys = _keys, vals = vals, hashes = hashes; + var nBuckets = nBuckets, + _keys = _keys, + vals = vals, + hashes = hashes; var newMask = newNBuckets - 1; - while (++j < nBuckets) - { + while (++j < nBuckets) { var k; - if (!isEither(k = hashes[j])) - { + if (!isEither(k = hashes[j])) { var key = _keys[j]; var val = vals[j]; _keys[j] = null; vals[j] = cast null; hashes[j] = FLAG_DEL; - while (true) /* kick-out process; sort of like in Cuckoo hashing */ - { + while (true) + /* kick-out process; sort of like in Cuckoo hashing */ { var nProbes = 0; - //var inc = getInc(k, newMask); + // var inc = getInc(k, newMask); var i = k & newMask; while (!isEmpty(newHash[i])) @@ -233,14 +226,13 @@ import cs.NativeArray; newHash[i] = k; - if (i < nBuckets && !isEither(k = hashes[i])) /* kick out the existing element */ - { + if (i < nBuckets && !isEither(k = hashes[i])) + /* kick out the existing element */ { { var tmp = _keys[i]; _keys[i] = key; key = tmp; - } - { + } { var tmp = vals[i]; vals[i] = val; val = tmp; @@ -256,14 +248,13 @@ import cs.NativeArray; } } - if (nBuckets > newNBuckets) /* shrink the hash table */ - { + if (nBuckets > newNBuckets) + /* shrink the hash table */ { { var k = new NativeArray(newNBuckets); arrayCopy(_keys, 0, k, 0, newNBuckets); this._keys = k; - } - { + } { var v = new NativeArray(newNBuckets); arrayCopy(vals, 0, v, 0, newNBuckets); this.vals = v; @@ -277,23 +268,20 @@ import cs.NativeArray; } } - public function get( key : K ) : Null - { + public function get(key:K):Null { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } @@ -301,23 +289,20 @@ import cs.NativeArray; return null; } - private function getDefault( key : K, def : V ) : V - { + private function getDefault(key:K, def:V):V { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } @@ -325,23 +310,20 @@ import cs.NativeArray; return def; } - public function exists( key : K ) : Bool - { + public function exists(key:K):Bool { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return true; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return true; } @@ -349,24 +331,22 @@ import cs.NativeArray; return false; } - public function remove( key : K ) : Bool - { + public function remove(key:K):Bool { var idx = -1; -#if !no_map_cache - if (! (cachedKey == key && ( (idx = cachedIndex) != -1 ))) -#end + #if !no_map_cache + if (!(cachedKey == key && ((idx = cachedIndex) != -1))) + #end { idx = lookup(key); } - if (idx == -1) - { + if (idx == -1) { return false; } else { -#if !no_map_cache + #if !no_map_cache if (cachedKey == key) cachedIndex = -1; -#end + #end hashes[idx] = FLAG_DEL; _keys[idx] = null; @@ -377,51 +357,41 @@ import cs.NativeArray; } } - /** - Returns an iterator of all keys in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public function keys() : Iterator - { + public function keys():Iterator { return new ObjectMapKeyIterator(this); } - /** - Returns an iterator of all values in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public function iterator() : Iterator - { + public function iterator():Iterator { return new ObjectMapValueIterator(this); } - public function copy() : ObjectMap { + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():ObjectMap { var copied = new ObjectMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - /** - Returns an displayable representation of the hashtable content. - **/ - - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(Std.string(i)); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - @:extern private static inline function roundUp(x:Int):Int - { + extern private static inline function roundUp(x:Int):Int { --x; x |= (x) >>> 1; x |= (x) >>> 2; @@ -431,38 +401,36 @@ import cs.NativeArray; return ++x; } - @:extern private static inline function getInc(k:Int, mask:Int):Int //return 1 for linear probing + extern private static inline function getInc(k:Int, mask:Int):Int // return 1 for linear probing return (((k) >> 3 ^ (k) << 3) | 1) & (mask); - @:extern private static inline function isEither(v:HashType):Bool + extern private static inline function isEither(v:HashType):Bool return (v & 0xFFFFFFFE) == 0; - @:extern private static inline function isEmpty(v:HashType):Bool + extern private static inline function isEmpty(v:HashType):Bool return v == FLAG_EMPTY; - @:extern private static inline function isDel(v:HashType):Bool + extern private static inline function isDel(v:HashType):Bool return v == FLAG_DEL; - //guarantee: Whatever this function is, it will never return 0 nor 1 - @:extern private static inline function hash(s:K):HashType - { + // guarantee: Whatever this function is, it will never return 0 nor 1 + extern private static inline function hash(s:K):HashType { var k:Int = untyped s.GetHashCode(); - //k *= 357913941; - //k ^= k << 24; - //k += ~357913941; - //k ^= k >> 31; - //k ^= k << 31; - - k = (k+0x7ed55d16) + (k<<12); - k = (k^0xc761c23c) ^ (k>>19); - k = (k+0x165667b1) + (k<<5); - k = (k+0xd3a2646c) ^ (k<<9); - k = (k+0xfd7046c5) + (k<<3); - k = (k^0xb55a4f09) ^ (k>>16); + // k *= 357913941; + // k ^= k << 24; + // k += ~357913941; + // k ^= k >> 31; + // k ^= k << 31; + + k = (k + 0x7ed55d16) + (k << 12); + k = (k ^ 0xc761c23c) ^ (k >> 19); + k = (k + 0x165667b1) + (k << 5); + k = (k + 0xd3a2646c) ^ (k << 9); + k = (k + 0xfd7046c5) + (k << 3); + k = (k ^ 0xb55a4f09) ^ (k >> 16); var ret = k; - if (isEither(ret)) - { + if (isEither(ret)) { if (ret == 0) ret = 2; else @@ -472,35 +440,33 @@ import cs.NativeArray; return ret; } - @:extern private static inline function arrayCopy(sourceArray:cs.system.Array, sourceIndex:Int, destinationArray:cs.system.Array, destinationIndex:Int, length:Int):Void + extern private static inline function arrayCopy(sourceArray:cs.system.Array, sourceIndex:Int, destinationArray:cs.system.Array, destinationIndex:Int, + length:Int):Void cs.system.Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length); - @:extern private static inline function assert(x:Bool):Void - { -#if DEBUG_HASHTBL - if (!x) throw "assert failed"; -#end + extern private static inline function assert(x:Bool):Void { + #if DEBUG_HASHTBL + if (!x) + throw "assert failed"; + #end } } @:access(haxe.ds.ObjectMap) -@:final -private class ObjectMapKeyIterator { - var m:ObjectMap; +private final class ObjectMapKeyIterator { + var m:ObjectMap; var i:Int; var len:Int; - public function new(m:ObjectMap) { + public function new(m:ObjectMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } public function hasNext():Bool { - for (j in i...len) - { - if (!ObjectMap.isEither(m.hashes[j])) - { + for (j in i...len) { + if (!ObjectMap.isEither(m.hashes[j])) { i = j; return true; } @@ -508,13 +474,13 @@ private class ObjectMapKeyIterator { return false; } - public function next() : T { + public function next():T { var ret = m._keys[i]; -#if !no_map_cache + #if !no_map_cache m.cachedIndex = i; m.cachedKey = ret; -#end + #end i = i + 1; return ret; @@ -522,24 +488,20 @@ private class ObjectMapKeyIterator { } @:access(haxe.ds.ObjectMap) -@:final -private class ObjectMapValueIterator { - var m:ObjectMap; +private final class ObjectMapValueIterator { + var m:ObjectMap; var i:Int; var len:Int; - public function new(m:ObjectMap) - { + public function new(m:ObjectMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } - public function hasNext() : Bool { - for (j in i...len) - { - if (!ObjectMap.isEither(m.hashes[j])) - { + public function hasNext():Bool { + for (j in i...len) { + if (!ObjectMap.isEither(m.hashes[j])) { i = j; return true; } diff --git a/std/cs/_std/haxe/ds/StringMap.hx b/std/cs/_std/haxe/ds/StringMap.hx index 1de835c2a2f..41ab60e6352 100644 --- a/std/cs/_std/haxe/ds/StringMap.hx +++ b/std/cs/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,15 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; import cs.NativeArray; -@:coreApi class StringMap implements haxe.Constraints.IMap -{ - @:extern private static inline var HASH_UPPER = 0.77; - @:extern private static inline var FLAG_EMPTY = 0; - @:extern private static inline var FLAG_DEL = 1; +@:coreApi class StringMap implements haxe.Constraints.IMap { + extern private static inline var HASH_UPPER = 0.77; + extern private static inline var FLAG_EMPTY = 0; + extern private static inline var FLAG_DEL = 1; /** * This is the most important structure here and the reason why it's so fast. @@ -38,6 +38,7 @@ import cs.NativeArray; * The insertion algorithm will do the same but will also break when FLAG_DEL is found; */ private var hashes:NativeArray; + private var _keys:NativeArray; private var vals:NativeArray; @@ -46,33 +47,29 @@ import cs.NativeArray; private var nOccupied:Int; private var upperBound:Int; -#if !no_map_cache + #if !no_map_cache private var cachedKey:String; private var cachedIndex:Int; -#end + #end -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL private var totalProbes:Int; private var probeTimes:Int; private var sameHash:Int; private var maxProbe:Int; -#end + #end - public function new() : Void - { -#if !no_map_cache + public function new():Void { + #if !no_map_cache cachedIndex = -1; -#end + #end } - public function set( key : String, value : T ) : Void - { + public function set(key:String, value:T):Void { var x:Int, k:Int; - if (nOccupied >= upperBound) - { - if (nBuckets > (size << 1)) - { - resize(nBuckets - 1); //clear "deleted" elements + if (nOccupied >= upperBound) { + if (nBuckets > (size << 1)) { + resize(nBuckets - 1); // clear "deleted" elements } else { resize(nBuckets + 2); } @@ -91,38 +88,34 @@ import cs.NativeArray; x = i; } else { var last = i, flag; - while(! (isEmpty(flag = hashes[i]) || (flag == k && _keys[i] == key)) ) - { - if (isDel(flag) && delKey == -1) - { + while (!(isEmpty(flag = hashes[i]) || (flag == k && _keys[i] == key))) { + if (isDel(flag) && delKey == -1) { delKey = i; } i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } - if (isEmpty(flag) && delKey != -1) - { + if (isEmpty(flag) && delKey != -1) { x = delKey; } else { x = i; } } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end } var flag = hashes[x]; - if (isEmpty(flag)) - { + if (isEmpty(flag)) { keys[x] = key; vals[x] = value; hashes[x] = k; @@ -138,58 +131,55 @@ import cs.NativeArray; vals[x] = value; } -#if !no_map_cache + #if !no_map_cache cachedIndex = x; cachedKey = key; -#end + #end } - @:final private function lookup( key : String ) : Int - { - if (nBuckets != 0) - { + private final function lookup(key:String):Int { + if (nBuckets != 0) { var hashes = hashes, keys = _keys; var mask = nBuckets - 1, hash = hash(key), k = hash, nProbes = 0; var i = k & mask; var last = i, flag; // if we hit an empty bucket, it means we're done - while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || keys[i] != key)) - { + while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || keys[i] != key)) { i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end return isEither(flag) ? -1 : i; } return -1; } - @:final @:private function resize(newNBuckets:Int) : Void - { - //This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. + final function resize(newNBuckets:Int):Void { + // This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. var newHash = null; var j = 1; { newNBuckets = roundUp(newNBuckets); - if (newNBuckets < 4) newNBuckets = 4; - if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */ - { + if (newNBuckets < 4) + newNBuckets = 4; + if (size >= (newNBuckets * HASH_UPPER + 0.5)) + /* requested size is too small */ { j = 0; } else { /* hash table size to be changed (shrink or expand); rehash */ var nfSize = newNBuckets; - newHash = new NativeArray( nfSize ); - if (nBuckets < newNBuckets) //expand + newHash = new NativeArray(nfSize); + if (nBuckets < newNBuckets) // expand { var k = new NativeArray(newNBuckets); if (_keys != null) @@ -200,53 +190,51 @@ import cs.NativeArray; if (vals != null) arrayCopy(vals, 0, v, 0, nBuckets); vals = v; - } //otherwise shrink + } // otherwise shrink } } - if (j != 0) - { //rehashing is required - //resetting cache -#if !no_map_cache + if (j != 0) { // rehashing is required + // resetting cache + #if !no_map_cache cachedKey = null; cachedIndex = -1; -#end + #end j = -1; - var nBuckets = nBuckets, _keys = _keys, vals = vals, hashes = hashes; + var nBuckets = nBuckets, + _keys = _keys, + vals = vals, + hashes = hashes; var newMask = newNBuckets - 1; - while (++j < nBuckets) - { + while (++j < nBuckets) { var k; - if (!isEither(k = hashes[j])) - { + if (!isEither(k = hashes[j])) { var key = _keys[j]; var val = vals[j]; _keys[j] = null; vals[j] = cast null; hashes[j] = FLAG_DEL; - while (true) /* kick-out process; sort of like in Cuckoo hashing */ - { + while (true) + /* kick-out process; sort of like in Cuckoo hashing */ { var nProbes = 0; var i = k & newMask; - while (!isEmpty(newHash[i])) - { + while (!isEmpty(newHash[i])) { i = (i + ++nProbes) & newMask; } newHash[i] = k; - if (i < nBuckets && !isEither(k = hashes[i])) /* kick out the existing element */ - { + if (i < nBuckets && !isEither(k = hashes[i])) + /* kick out the existing element */ { { // inlined swap var tmp = _keys[i]; _keys[i] = key; key = tmp; - } - { // inlined swap + } { // inlined swap var tmp = vals[i]; vals[i] = val; val = tmp; @@ -262,14 +250,13 @@ import cs.NativeArray; } } - if (nBuckets > newNBuckets) /* shrink the hash table */ - { + if (nBuckets > newNBuckets) + /* shrink the hash table */ { { // inlined swap var k = new NativeArray(newNBuckets); arrayCopy(_keys, 0, k, 0, newNBuckets); this._keys = k; - } - { // inlined swap + } { // inlined swap var v = new NativeArray(newNBuckets); arrayCopy(vals, 0, v, 0, newNBuckets); this.vals = v; @@ -283,45 +270,39 @@ import cs.NativeArray; } } - public function get( key : String ) : Null - { + public function get(key:String):Null { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } return null; } - private function getDefault( key : String, def : T ) : T - { + private function getDefault(key:String, def:T):T { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } @@ -329,49 +310,43 @@ import cs.NativeArray; return def; } - public function exists( key : String ) : Bool - { + public function exists(key:String):Bool { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return true; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return true; } return false; } - public function remove( key : String ) : Bool - { + public function remove(key:String):Bool { var idx = -1; -#if !no_map_cache - if (! (cachedKey == key && ( (idx = cachedIndex) != -1 ))) -#end + #if !no_map_cache + if (!(cachedKey == key && ((idx = cachedIndex) != -1))) + #end { idx = lookup(key); } - if (idx == -1) - { + if (idx == -1) { return false; } else { -#if !no_map_cache - if (cachedKey == key) - { + #if !no_map_cache + if (cachedKey == key) { cachedIndex = -1; } -#end + #end hashes[idx] = FLAG_DEL; _keys[idx] = null; vals[idx] = null; @@ -381,51 +356,41 @@ import cs.NativeArray; } } - /** - Returns an iterator of all keys in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function keys() : Iterator - { + public inline function keys():Iterator { return new StringMapKeyIterator(this); } - /** - Returns an iterator of all values in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function iterator() : Iterator - { + public inline function iterator():Iterator { return new StringMapValueIterator(this); } - public function copy() : StringMap { + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():StringMap { var copied = new StringMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - /** - Returns an displayable representation of the hashtable content. - **/ - - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(i); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - @:extern private static inline function roundUp(x:Int):Int - { + extern private static inline function roundUp(x:Int):Int { --x; x |= (x) >>> 1; x |= (x) >>> 2; @@ -435,35 +400,33 @@ import cs.NativeArray; return ++x; } - @:extern private static inline function isEither(v:HashType):Bool + extern private static inline function isEither(v:HashType):Bool return (v & 0xFFFFFFFE) == 0; - @:extern private static inline function isEmpty(v:HashType):Bool + extern private static inline function isEmpty(v:HashType):Bool return v == FLAG_EMPTY; - @:extern private static inline function isDel(v:HashType):Bool + extern private static inline function isDel(v:HashType):Bool return v == FLAG_DEL; // guarantee: Whatever this function is, it will never return 0 nor 1 - @:extern private static inline function hash(s:String):HashType - { + extern private static inline function hash(s:String):HashType { var k:Int = untyped s.GetHashCode(); - //k *= 357913941; - //k ^= k << 24; - //k += ~357913941; - //k ^= k >> 31; - //k ^= k << 31; - - k = (k+0x7ed55d16) + (k<<12); - k = (k^0xc761c23c) ^ (k>>19); - k = (k+0x165667b1) + (k<<5); - k = (k+0xd3a2646c) ^ (k<<9); - k = (k+0xfd7046c5) + (k<<3); - k = (k^0xb55a4f09) ^ (k>>16); + // k *= 357913941; + // k ^= k << 24; + // k += ~357913941; + // k ^= k >> 31; + // k ^= k << 31; + + k = (k + 0x7ed55d16) + (k << 12); + k = (k ^ 0xc761c23c) ^ (k >> 19); + k = (k + 0x165667b1) + (k << 5); + k = (k + 0xd3a2646c) ^ (k << 9); + k = (k + 0xfd7046c5) + (k << 3); + k = (k ^ 0xb55a4f09) ^ (k >> 16); var ret = k; - if (isEither(ret)) - { + if (isEither(ret)) { if (ret == 0) ret = 2; else @@ -473,40 +436,35 @@ import cs.NativeArray; return ret; } - @:extern private static inline function arrayCopy(sourceArray:cs.system.Array, sourceIndex:Int, destinationArray:cs.system.Array, destinationIndex:Int, length:Int):Void + extern private static inline function arrayCopy(sourceArray:cs.system.Array, sourceIndex:Int, destinationArray:cs.system.Array, destinationIndex:Int, + length:Int):Void cs.system.Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length); - @:extern private static inline function assert(x:Bool):Void - { -#if DEBUG_HASHTBL - if (!x) throw "assert failed"; -#end + extern private static inline function assert(x:Bool):Void { + #if DEBUG_HASHTBL + if (!x) + throw "assert failed"; + #end } } private typedef HashType = Int; -@:final @:access(haxe.ds.StringMap) -private class StringMapKeyIterator -{ +private final class StringMapKeyIterator { var m:StringMap; var i:Int; var len:Int; - public function new(m:StringMap) - { + public function new(m:StringMap) { this.m = m; this.i = 0; this.len = m.nBuckets; } - public function hasNext():Bool - { - for (j in i...len) - { - if (!StringMap.isEither(m.hashes[j])) - { + public function hasNext():Bool { + for (j in i...len) { + if (!StringMap.isEither(m.hashes[j])) { i = j; return true; } @@ -514,39 +472,32 @@ private class StringMapKeyIterator return false; } - public function next():String - { + public function next():String { var ret = m._keys[i]; -#if !no_map_cache + #if !no_map_cache m.cachedIndex = i; m.cachedKey = ret; -#end + #end i++; return ret; } } -@:final @:access(haxe.ds.StringMap) -private class StringMapValueIterator -{ +private final class StringMapValueIterator { var m:StringMap; var i:Int; var len:Int; - public function new(m:StringMap) - { + public function new(m:StringMap) { this.m = m; this.i = 0; this.len = m.nBuckets; } - public function hasNext():Bool - { - for (j in i...len) - { - if (!StringMap.isEither(m.hashes[j])) - { + public function hasNext():Bool { + for (j in i...len) { + if (!StringMap.isEither(m.hashes[j])) { i = j; return true; } @@ -554,8 +505,7 @@ private class StringMapValueIterator return false; } - public inline function next():T - { + public inline function next():T { return m.vals[i++]; } } diff --git a/std/cs/_std/haxe/ds/WeakMap.hx2 b/std/cs/_std/haxe/ds/WeakMap.hx2 deleted file mode 100644 index 53f00172d41..00000000000 --- a/std/cs/_std/haxe/ds/WeakMap.hx2 +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (C)2005-2012 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.ds; - -import cs.NativeArray; -import cs.system.WeakReference; - -// This implementation works by lazily evaluating the weak references, and only cleaning them up when needed. -@:coreApi class WeakMap implements haxe.Constraints.IMap -{ - @:extern private static inline var HASH_UPPER = 0.77; - @:extern private static inline var FLAG_EMPTY = 0; - @:extern private static inline var FLAG_DEL = 1; - - /** - * This is the most important structure here and the reason why it's so fast. - * It's an array of all the hashes contained in the table. These hashes cannot be 0 nor 1, - * which stand for "empty" and "deleted" states. - * - * The lookup algorithm will keep looking until a 0 or the key wanted is found; - * The insertion algorithm will do the same but will also break when FLAG_DEL is found; - */ - private var hashes:NativeArray; - private var entries:NativeArray>; - - private var nBuckets:Int; - private var size:Int; - private var nOccupied:Int; - private var upperBound:Int; - - private var cachedEntry:Entry; - private var cachedIndex:Int; - -#if DEBUG_HASHTBL - private var totalProbes:Int; - private var probeTimes:Int; - private var sameHash:Int; - private var maxProbe:Int; -#end - - public function new() : Void - { - cachedIndex = -1; - } - - @:final private function checkSize():Void - { - //iterate over the hashes and remove dead references - var size = size, entries = entries, hashes = hashes; - if (entries == null) - return; - for (i in 0...entries.Length) - { - var e = entries[i]; - if (e != null && e.Target == null) - { - --size; - hashes[i] = FLAG_DEL; - entries[i] = null; - } - } - this.size = size; - } - - public function set( key : K, value : V ) : Void - { - var x:Int, k:Int; - - if (nOccupied >= upperBound) - { - if (nBuckets > (size << 1)) - resize(nBuckets - 1); //clear "deleted" elements - else - resize(nBuckets + 2); - } - - k = hash(key); - var hashes = hashes, entries = entries; - { - var mask = (nBuckets == 0) ? 0 : nBuckets - 1; - var site = x = nBuckets; - var i = k & mask, nProbes = 0; - - //for speed up - var delKey = -1; - if (isEmpty(hashes[i])) { - x = i; - } else { - //var inc = getInc(k, mask); - var last = i, flag; - while(! (isEmpty(flag = hashes[i]) || (flag == k && entries[i].keyEquals(key) )) ) - { - if (delKey == -1 && isDel(flag)) - delKey = i; - - var entry = entries[i]; - if (entry.Target == null) - { - hashes[i] = FLAG_DEL; - entries[i] = null; - --size; - if (delKey == -1) - delKey = i; - } - - i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL - probeTimes++; - if (i == last) - throw "assert"; -#end - } - - if (isEmpty(flag) && delKey != -1) - x = delKey; - else - x = i; - } - -#if DEBUG_HASHTBL - if (nProbes > maxProbe) - maxProbe = nProbes; - totalProbes++; -#end - } - - var flag = hashes[x], entry = new Entry(key,value,k); - if (isEmpty(flag)) - { - entries[x] = entry; - hashes[x] = k; - size++; - nOccupied++; - } else if (isDel(flag)) { - entries[x] = entry; - hashes[x] = k; - size++; - } else { - assert(entries[x].keyEquals(key)); - entries[x] = entry; - } - - cachedIndex = x; - cachedEntry = entry; - } - - @:final private function lookup( key : K ) : Int - { - if (nBuckets != 0) - { - var hashes = hashes, entries = entries; - - var mask = nBuckets - 1, hash = hash(key), k = hash, nProbes = 0; - var i = k & mask; - var last = i, flag; - //var inc = getInc(k, mask); - while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || !entries[i].keyEquals(key))) - { - if (!isDel(flag)) - { - var entry = entries[i]; - if (entry.Target == null) - { - entries[i] = null; - hashes[i] = FLAG_DEL; - --size; - } - } - i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL - probeTimes++; - if (i == last) - throw "assert"; -#end - } - -#if DEBUG_HASHTBL - if (nProbes > maxProbe) - maxProbe = nProbes; - totalProbes++; -#end - return isEither(flag) ? -1 : i; - } - - return -1; - } - - @:final @:private function resize(newNBuckets:Int) : Void - { - //This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. - var newHash = null; - var j = 1; - { - newNBuckets = roundUp(newNBuckets); - if (newNBuckets < 4) newNBuckets = 4; - if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */ - { - j = 0; - } else { /* hash table size to be changed (shrink or expand); rehash */ - var nfSize = newNBuckets; - newHash = new NativeArray( nfSize ); - if (nBuckets < newNBuckets) //expand - { - var e = new NativeArray(newNBuckets); - if (entries != null) - arrayCopy(entries, 0, e, 0, nBuckets); - entries = e; - } //otherwise shrink - } - } - - if (j != 0) - { //rehashing is required - //resetting cache - cachedEntry = null; - cachedIndex = -1; - - j = -1; - var nBuckets = nBuckets, entries = entries, hashes = hashes; - - var newMask = newNBuckets - 1; - while (++j < nBuckets) - { - var k; - if (!isEither(k = hashes[j])) - { - var entry = entries[j]; - if (entry.Target != null) - { - hashes[j] = FLAG_DEL; - while (true) /* kick-out process; sort of like in Cuckoo hashing */ - { - var nProbes = 0; - var i = k & newMask; - - while (!isEmpty(newHash[i])) - i = (i + ++nProbes) & newMask; - - newHash[i] = k; - - if (i < nBuckets && !isEither(k = hashes[i])) /* kick out the existing element */ - { - { - var tmp = entries[i]; - entries[i] = entry; - entry = tmp; - } - - hashes[i] = FLAG_DEL; /* mark it as deleted in the old hash table */ - } else { /* write the element and jump out of the loop */ - entries[i] = entry; - break; - } - } - } - } - } - - if (nBuckets > newNBuckets) /* shrink the hash table */ - { - { - var e = new NativeArray(newNBuckets); - arrayCopy(entries, 0, e, 0, newNBuckets); - this.entries = e; - } - } - - this.hashes = newHash; - this.nBuckets = newNBuckets; - this.nOccupied = size; - this.upperBound = Std.int(newNBuckets * HASH_UPPER + .5); - } - } - - public function get( key : K ) : Null - { - var idx = -1; - if (cachedEntry != null && cachedEntry.keyEquals(key) && ( (idx = cachedIndex) != -1 )) - { - return cachedEntry.value; - } - - idx = lookup(key); - if (idx != -1) - { - var entry = entries[idx]; - cachedEntry = entry; - cachedIndex = idx; - - return entry.value; - } - - return null; - } - - private function getDefault( key : K, def : V ) : V - { - var idx = -1; - if (cachedEntry != null && cachedEntry.keyEquals(key) && ( (idx = cachedIndex) != -1 )) - { - return cachedEntry.value; - } - - idx = lookup(key); - if (idx != -1) - { - var entry = entries[idx]; - cachedEntry = entry; - cachedIndex = idx; - - return entry.value; - } - - return def; - } - - public function exists( key : K ) : Bool - { - var idx = -1; - if (cachedEntry != null && cachedEntry.keyEquals(key) && ( (idx = cachedIndex) != -1 )) - { - return true; - } - - idx = lookup(key); - if (idx != -1) - { - var entry = entries[idx]; - cachedEntry = entry; - cachedIndex = idx; - - return true; - } - - return false; - } - - public function remove( key : K ) : Bool - { - var idx = -1; - if ( !(cachedEntry != null && cachedEntry.keyEquals(key) && ( (idx = cachedIndex) != -1 )) ) - { - idx = lookup(key); - } - - if (idx == -1) - { - return false; - } else { - if (cachedEntry != null && cachedEntry.keyEquals(key)) - { - cachedIndex = -1; - cachedEntry = null; - } - - hashes[idx] = FLAG_DEL; - entries[idx] = null; - --size; - - return true; - } - } - - /** - Returns an iterator of all keys in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public function keys() : Iterator - { - var i = 0; - var len = nBuckets; - var lastKey = null; //keep a strong reference to the key while iterating, so it can't be collected while iterating - return { - hasNext: function() { - for (j in i...len) - { - if (!isEither(hashes[j])) - { - var entry = entries[j]; - var last = entry.Target; - if (last != null) - { - lastKey = last; - cachedIndex = i; - cachedEntry = entry; - i = j; - return true; - } else { - --size; - hashes[j] = FLAG_DEL; - entries[j] = null; - } - } - } - return false; - }, - next: function() { - i = i + 1; - return lastKey; - } - }; - } - - /** - Returns an iterator of all values in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public function iterator() : Iterator - { - var i = 0; - var len = nBuckets; - var lastKey = null; //keep a strong reference to the key while iterating, so it can't be collected while iterating - return { - hasNext: function() { - for (j in i...len) - { - if (!isEither(hashes[j])) - { - var entry = entries[j]; - var last = entry.Target; - if (last != null) - { - lastKey = last; - cachedIndex = i; - cachedEntry = entry; - i = j; - return true; - } else { - --size; - hashes[j] = FLAG_DEL; - entries[j] = null; - } - } - } - return false; - }, - next: function() { - var ret = entries[i].value; - i = i + 1; - return ret; - } - }; - } - - /** - Returns an displayable representation of the hashtable content. - **/ - - public function toString() : String { - var s = new StringBuf(); - s.add("{"); - var it = keys(); - for( i in it ) { - s.add(Std.string(i)); - s.add(" => "); - s.add(Std.string(get(i))); - if( it.hasNext() ) - s.add(", "); - } - s.add("}"); - return s.toString(); - } - - @:extern private static inline function roundUp(x:Int):Int - { - --x; - x |= (x) >>> 1; - x |= (x) >>> 2; - x |= (x) >>> 4; - x |= (x) >>> 8; - x |= (x) >>> 16; - return ++x; - } - - @:extern private static inline function getInc(k:Int, mask:Int):Int //return 1 for linear probing - return (((k) >> 3 ^ (k) << 3) | 1) & (mask); - - @:extern private static inline function isEither(v:HashType):Bool - return (v & 0xFFFFFFFE) == 0; - - @:extern private static inline function isEmpty(v:HashType):Bool - return v == FLAG_EMPTY; - - @:extern private static inline function isDel(v:HashType):Bool - return v == FLAG_DEL; - - //guarantee: Whatever this function is, it will never return 0 nor 1 - @:extern private static inline function hash(s:Dynamic):HashType - { - var k:Int = untyped s.GetHashCode(); - //k *= 357913941; - //k ^= k << 24; - //k += ~357913941; - //k ^= k >> 31; - //k ^= k << 31; - - // k = (k+0x7ed55d16) + (k<<12); - // k = (k^0xc761c23c) ^ (k>>19); - // k = (k+0x165667b1) + (k<<5); - // k = (k+0xd3a2646c) ^ (k<<9); - // k = (k+0xfd7046c5) + (k<<3); - // k = (k^0xb55a4f09) ^ (k>>16); - - var ret = k; - if (isEither(ret)) - { - if (ret == 0) - ret = 2; - else - ret = 0xFFFFFFFF; - } - - return ret; - } - - @:extern private static inline function arrayCopy(sourceArray:cs.system.Array, sourceIndex:Int, destinationArray:cs.system.Array, destinationIndex:Int, length:Int):Void - cs.system.Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length); - - @:extern private static inline function assert(x:Bool):Void - { -#if DEBUG_HASHTBL - if (!x) throw "assert failed"; -#end - } -} - -private class Entry extends WeakReference -{ - public var value:V; - public var hash(default, null):Int; - public function new(key:K, value:V, hash:Int) - { - super(key, false); - this.value = value; - this.hash = hash; - } - - public function reuse(key,hash) - { - this.Target = key; - this.hash = hash; - } - - @:final inline public function keyEquals(k:K):Bool - { - return k != null && untyped k.Equals(Target); - } -} - -private typedef HashType = Int; diff --git a/std/cs/_std/sys/FileSystem.hx b/std/cs/_std/sys/FileSystem.hx index 52ef590eaf9..8b079654bb5 100644 --- a/std/cs/_std/sys/FileSystem.hx +++ b/std/cs/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys; + import cs.system.io.DirectoryInfo; import cs.system.io.File; import cs.system.io.Directory; @@ -27,109 +29,97 @@ import cs.system.io.FileInfo; @:coreApi class FileSystem { - - public static function exists( path : String ) : Bool - { + public static function exists(path:String):Bool { return (File.Exists(path) || Directory.Exists(path)); } - public static function rename( path : String, newPath : String ) : Void - { + public static function rename(path:String, newPath:String):Void { Directory.Move(path, newPath); } @:access(Date.fromNative) - public static function stat( path : String ) : FileStat - { - if (File.Exists(path)) - { + public static function stat(path:String):FileStat { + if (File.Exists(path)) { var fi = new FileInfo(path); return { - gid: 0, //C# doesn't let you get this info - uid: 0, //same + gid: 0, // C# doesn't let you get this info + uid: 0, // same atime: Date.fromNative(fi.LastAccessTime), mtime: Date.fromNative(fi.LastWriteTime), ctime: Date.fromNative(fi.CreationTime), - size: cast(fi.Length, Int), //TODO: maybe change to Int64 for Haxe 3? - dev: 0, //FIXME: not sure what that is - ino: 0, //FIXME: not sure what that is - nlink: 0, //FIXME: not sure what that is - rdev: 0, //FIXME: not sure what that is - mode: 0 //FIXME: not sure what that is + size: cast(fi.Length, Int), // TODO: maybe change to Int64 for Haxe 3? + dev: 0, // FIXME: not sure what that is + ino: 0, // FIXME: not sure what that is + nlink: 0, // FIXME: not sure what that is + rdev: 0, // FIXME: not sure what that is + mode: 0 // FIXME: not sure what that is }; } else if (Directory.Exists(path)) { var fi = new DirectoryInfo(path); return { - gid: 0, //C# doesn't let you get this info - uid: 0, //same + gid: 0, // C# doesn't let you get this info + uid: 0, // same atime: Date.fromNative(fi.LastAccessTime), mtime: Date.fromNative(fi.LastWriteTime), ctime: Date.fromNative(fi.CreationTime), - size: 0, //TODO: maybe change to Int64 for Haxe 3? - dev: 0, //FIXME: not sure what that is - ino: 0, //FIXME: not sure what that is - nlink: 0, //FIXME: not sure what that is - rdev: 0, //FIXME: not sure what that is - mode: 0 //FIXME: not sure what that is + size: 0, // TODO: maybe change to Int64 for Haxe 3? + dev: 0, // FIXME: not sure what that is + ino: 0, // FIXME: not sure what that is + nlink: 0, // FIXME: not sure what that is + rdev: 0, // FIXME: not sure what that is + mode: 0 // FIXME: not sure what that is }; } else { throw "Path '" + path + "' doesn't exist"; } - } - public static function fullPath( relPath : String ) : String - { + public static function fullPath(relPath:String):String { return new FileInfo(relPath).FullName; } - public static function absolutePath ( relPath : String ) : String { - if (haxe.io.Path.isAbsolute(relPath)) return relPath; + public static function absolutePath(relPath:String):String { + if (haxe.io.Path.isAbsolute(relPath)) + return relPath; return haxe.io.Path.join([Sys.getCwd(), relPath]); } - public static function isDirectory( path : String ) : Bool - { + public static function isDirectory(path:String):Bool { var isdir = Directory.Exists(path); if (isdir != File.Exists(path)) return isdir; throw "Path '" + path + "' doesn't exist"; } - public static function createDirectory( path : String ) : Void - { + public static function createDirectory(path:String):Void { Directory.CreateDirectory(path); } - public static function deleteFile( path : String ) : Void - { - if (!File.Exists(path)) throw "Path '" + path + "' doesn't exist"; + public static function deleteFile(path:String):Void { + if (!File.Exists(path)) + throw "Path '" + path + "' doesn't exist"; File.Delete(path); } - public static function deleteDirectory( path : String ) : Void - { - if (!Directory.Exists(path)) throw "Path '" + path + "' doesn't exist"; + public static function deleteDirectory(path:String):Void { + if (!Directory.Exists(path)) + throw "Path '" + path + "' doesn't exist"; Directory.Delete(path); } - public static function readDirectory( path : String ) : Array - { + public static function readDirectory(path:String):Array { var ret = Directory.GetFileSystemEntries(path); - if (ret.Length > 0) - { + if (ret.Length > 0) { var fst = ret[0]; var sep = "/"; if (fst.lastIndexOf(sep) < fst.lastIndexOf("\\")) sep = "\\"; - for (i in 0...ret.Length) - { + for (i in 0...ret.Length) { var path = ret[i]; ret[i] = path.substr(path.lastIndexOf(sep) + 1); } } - return cs.Lib.array( ret ); + return cs.Lib.array(ret); } - } diff --git a/std/cs/_std/sys/db/Sqlite.hx b/std/cs/_std/sys/db/Sqlite.hx index ae41d4f7a3d..52d496bdf17 100644 --- a/std/cs/_std/sys/db/Sqlite.hx +++ b/std/cs/_std/sys/db/Sqlite.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,37 +19,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package sys.db; -class Sqlite -{ +package sys.db; + +class Sqlite { static var type:Class; - /** - Opens a new SQLite connection on the specified path. - Note that you will need a SQLite ADO.NET Provider (see http://www.mono-project.com/docs/database-access/providers/sqlite/). - Also note that this will try to open an assembly named `Mono.Data.Sqlite` if it wasn't loaded yet. - **/ - public static function open(file:String):sys.db.Connection - { + + public static function open(file:String):sys.db.Connection { var cnxString = 'Data Source=$file'; - if (type == null) - { + if (type == null) { var t = null; var assemblies = cs.system.AppDomain.CurrentDomain.GetAssemblies(); - for (i in 0...assemblies.Length) - { + for (i in 0...assemblies.Length) { var a = assemblies[i]; t = a.GetType('Mono.Data.Sqlite.SqliteConnection'); if (t == null) t = a.GetType('System.Data.SQLite.SQLiteConnection'); - if (t != null) - { + if (t != null) { break; } } - if (t == null) - { + if (t == null) { var asm = cs.system.reflection.Assembly.Load('Mono.Data.Sqlite'); t = asm.GetType('Mono.Data.Sqlite.SqliteConnection'); } @@ -58,12 +49,11 @@ class Sqlite type = cast cs.Lib.fromNativeType(t); } - if (type == null) - { + if (type == null) { throw "No ADO.NET SQLite provider was found!"; } - var ret = Type.createInstance(type,[cnxString]); + var ret = Type.createInstance(type, [cnxString]); ret.Open(); - return cs.db.AdoNet.create(ret,'SQLite'); + return cs.db.AdoNet.create(ret, 'SQLite'); } } diff --git a/std/cs/_std/sys/io/File.hx b/std/cs/_std/sys/io/File.hx index 378394de09a..6736085bd65 100644 --- a/std/cs/_std/sys/io/File.hx +++ b/std/cs/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,44 +19,39 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; @:coreApi class File { - - public static function getContent( path : String ) : String - { + public static function getContent(path:String):String { var f = read(path, false); var ret = f.readAll().toString(); f.close(); return ret; } - public static function saveContent( path : String, content : String ) : Void - { + public static function saveContent(path:String, content:String):Void { var f = write(path, false); f.writeString(content); f.close(); } - public static function getBytes( path : String ) : haxe.io.Bytes - { + public static function getBytes(path:String):haxe.io.Bytes { var f = read(path, true); var ret = f.readAll(); f.close(); return ret; } - public static function saveBytes( path : String, bytes : haxe.io.Bytes ) : Void - { + public static function saveBytes(path:String, bytes:haxe.io.Bytes):Void { var f = write(path, true); f.writeBytes(bytes, 0, bytes.length); f.close(); } - public static function read( path : String, binary : Bool = true ) : FileInput - { - #if std_buffer //standardize 4kb buffers + public static function read(path:String, binary:Bool = true):FileInput { + #if std_buffer // standardize 4kb buffers var stream = new cs.system.io.FileStream(path, Open, Read, ReadWrite, 4096); #else var stream = new cs.system.io.FileStream(path, Open, Read, ReadWrite); @@ -64,9 +59,8 @@ class File { return new FileInput(stream); } - public static function write( path : String, binary : Bool = true ) : FileOutput - { - #if std_buffer //standardize 4kb buffers + public static function write(path:String, binary:Bool = true):FileOutput { + #if std_buffer // standardize 4kb buffers var stream = new cs.system.io.FileStream(path, Create, Write, ReadWrite, 4096); #else var stream = new cs.system.io.FileStream(path, Create, Write, ReadWrite); @@ -74,9 +68,8 @@ class File { return new FileOutput(stream); } - public static function append( path : String, binary : Bool = true ) : FileOutput - { - #if std_buffer //standardize 4kb buffers + public static function append(path:String, binary:Bool = true):FileOutput { + #if std_buffer // standardize 4kb buffers var stream = new cs.system.io.FileStream(path, Append, Write, ReadWrite, 4096); #else var stream = new cs.system.io.FileStream(path, Append, Write, ReadWrite); @@ -84,8 +77,19 @@ class File { return new FileOutput(stream); } - public static function copy( srcPath : String, dstPath : String ) : Void - { + public static function update(path:String, binary:Bool = true):FileOutput { + if (!FileSystem.exists(path)) { + write(path).close(); + } + #if std_buffer // standardize 4kb buffers + var stream = new cs.system.io.FileStream(path, OpenOrCreate, Write, ReadWrite, 4096); + #else + var stream = new cs.system.io.FileStream(path, OpenOrCreate, Write, ReadWrite); + #end + return new FileOutput(stream); + } + + public static function copy(srcPath:String, dstPath:String):Void { cs.system.io.File.Copy(srcPath, dstPath, true); } } diff --git a/std/cs/_std/sys/io/FileInput.hx b/std/cs/_std/sys/io/FileInput.hx index 51c1d1a5af2..1d87218a08a 100644 --- a/std/cs/_std/sys/io/FileInput.hx +++ b/std/cs/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; class FileInput extends cs.io.NativeInput { - public function new(stream:cs.system.io.FileStream) - { + public function new(stream:cs.system.io.FileStream) { super(stream); } } diff --git a/std/cs/_std/sys/io/FileOutput.hx b/std/cs/_std/sys/io/FileOutput.hx index b58bdb21409..400e749a973 100644 --- a/std/cs/_std/sys/io/FileOutput.hx +++ b/std/cs/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; class FileOutput extends cs.io.NativeOutput { - public function new(stream:cs.system.io.FileStream) - { + public function new(stream:cs.system.io.FileStream) { super(stream); } } diff --git a/std/cs/_std/sys/io/Process.hx b/std/cs/_std/sys/io/Process.hx index fccb855551d..63e473e3e5a 100644 --- a/std/cs/_std/sys/io/Process.hx +++ b/std/cs/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; + import haxe.io.BytesInput; import cs.system.io.StreamReader; import cs.system.io.StreamWriter; @@ -28,16 +30,15 @@ import cs.system.diagnostics.ProcessStartInfo as NativeStartInfo; @:coreApi class Process { - - public var stdout(default,null) : haxe.io.Input; - public var stderr(default,null) : haxe.io.Input; - public var stdin(default, null) : haxe.io.Output; + public var stdout(default, null):haxe.io.Input; + public var stderr(default, null):haxe.io.Input; + public var stdin(default, null):haxe.io.Output; private var native:NativeProcess; - public function new( cmd : String, ?args : Array, ?detached : Bool ) : Void - { - if( detached ) throw "Detached process is not supported on this platform"; + public function new(cmd:String, ?args:Array, ?detached:Bool):Void { + if (detached) + throw "Detached process is not supported on this platform"; this.native = createNativeProcess(cmd, args); native.Start(); @@ -47,7 +48,7 @@ class Process { } @:allow(Sys) - private static function createNativeProcess( cmd : String, ?args : Array ) : NativeProcess { + private static function createNativeProcess(cmd:String, ?args:Array):NativeProcess { var native = new NativeProcess(); native.StartInfo.CreateNoWindow = true; native.StartInfo.RedirectStandardError = native.StartInfo.RedirectStandardInput = native.StartInfo.RedirectStandardOutput = true; @@ -80,7 +81,7 @@ class Process { case "Windows": [ for (a in args) - StringTools.quoteWinArg(a, false) + haxe.SysTools.quoteWinArg(a, false) ].join(" "); case _: // mono uses a slightly different quoting/escaping rule... @@ -94,7 +95,7 @@ class Process { switch (c) { case '"'.code | '\\'.code: b.addChar('\\'.code); - case _: //pass + case _: // pass } b.addChar(c); } @@ -105,27 +106,22 @@ class Process { } } - public function getPid() : Int - { + public function getPid():Int { return native.Id; } - public function exitCode( block : Bool = true ) : Null - { - if( block == false && !native.HasExited ) + public function exitCode(block:Bool = true):Null { + if (block == false && !native.HasExited) return null; native.WaitForExit(); return native.ExitCode; } - public function close() : Void - { + public function close():Void { native.Close(); } - public function kill() : Void - { + public function kill():Void { native.Kill(); } - } diff --git a/std/cs/_std/sys/net/Host.hx b/std/cs/_std/sys/net/Host.hx index 6e02ef9f421..fc2b10e3873 100644 --- a/std/cs/_std/sys/net/Host.hx +++ b/std/cs/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package sys.net; import cs.system.Array; @@ -30,32 +30,20 @@ import cs.system.net.sockets.AddressFamily; import haxe.io.Bytes; import haxe.io.BytesInput; -/** - A given IP host name. -**/ @:coreapi class Host { - public var hostEntry(default, null) : IPHostEntry; - public var ipAddress(default, null) : IPAddress; + public var hostEntry(default, null):IPHostEntry; + public var ipAddress(default, null):IPAddress; + + public var host(default, null):String; - /** - The provided host string. - **/ - var host(default,null) : String; + public var ip(get, null):Int; - /** - The actual IP corresponding to the host. - **/ - public var ip(get, null) : Int; - private function get_ip() : Int { - return new BytesInput(Bytes.ofData( ipAddress.GetAddressBytes() )).readInt32(); + private function get_ip():Int { + return new BytesInput(Bytes.ofData(ipAddress.GetAddressBytes())).readInt32(); } - /** - Creates a new Host : the name can be an IP in the form "127.0.0.1" or an host name such as "google.com", in which case - the corresponding IP address is resolved using DNS. An exception occur if the host name could not be found. - **/ - public function new( name : String ) : Void { + public function new(name:String):Void { host = name; hostEntry = Dns.GetHostEntry(name); for (i in 0...hostEntry.AddressList.Length) { @@ -66,25 +54,15 @@ class Host { } } - /** - Returns the IP representation of the host - **/ - public function toString() : String { + public function toString():String { return ipAddress.ToString(); } - /** - Perform a reverse-DNS query to resolve a host name from an IP. - **/ - public function reverse() : String { + public function reverse():String { return hostEntry.HostName; } - /** - Returns the local computer host name - **/ - static public function localhost() : String { + static public function localhost():String { return Dns.GetHostName(); } - } diff --git a/std/cs/_std/sys/net/Socket.hx b/std/cs/_std/sys/net/Socket.hx index 03e5630172b..f3e24f9add9 100644 --- a/std/cs/_std/sys/net/Socket.hx +++ b/std/cs/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,9 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package sys.net; +import cs.NativeArray; +import cs.system.collections.ArrayList; import cs.system.net.IPEndPoint; import cs.system.net.sockets.AddressFamily; import cs.system.net.sockets.NetworkStream; @@ -30,179 +32,151 @@ import cs.system.net.sockets.SocketFlags; import cs.system.net.sockets.SocketShutdown; import cs.system.net.sockets.SocketType; import cs.system.threading.Thread; +import cs.system.net.sockets.Socket in NativeSocket; import haxe.io.Bytes; import haxe.io.Error; import haxe.io.Input; import haxe.io.Output; -/** - A TCP socket class : allow you to both connect to a given server and exchange messages or start your own server and wait for connections. -**/ -@:coreapi +@:coreApi class Socket { - private var sock : cs.system.net.sockets.Socket = null; - - /** - The stream on which you can read available data. By default the stream is blocking until the requested data is available, - use `setBlocking(false)` or `setTimeout` to prevent infinite waiting. - **/ - public var input(default,null) : haxe.io.Input; - - /** - The stream on which you can send data. Please note that in case the output buffer you will block while writing the data, use `setBlocking(false)` or `setTimeout` to prevent that. - **/ - public var output(default,null) : haxe.io.Output; - - /** - A custom value that can be associated with the socket. Can be used to retrieve your custom infos after a `select`. - ***/ - public var custom : Dynamic; - - /** - Creates a new unconnected socket. - **/ - public function new() : Void { - sock = new cs.system.net.sockets.Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); + private var sock:NativeSocket = null; + + public var input(default, null):haxe.io.Input; + + public var output(default, null):haxe.io.Output; + + public var custom:Dynamic; + + public function new():Void { + sock = new NativeSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sock.Blocking = true; } - /** - Closes the socket : make sure to properly close all your sockets or you will crash when you run out of file descriptors. - **/ - public function close() : Void { + public function close():Void { sock.Close(); input = null; output = null; } - /** - Read the whole data available on the socket. - **/ - public function read() : String { + public function read():String { return input.readAll().toString(); } - /** - Write the whole data to the socket output. - **/ - public function write( content : String ) : Void { - output.writeString( content ); + public function write(content:String):Void { + output.writeString(content); } - /** - Connect to the given server host/port. Throw an exception in case we couldn't successfully connect. - **/ - public function connect( host : Host, port : Int ) : Void { - sock.Connect( host.ipAddress, port ); + public function connect(host:Host, port:Int):Void { + sock.Connect(host.ipAddress, port); if (sock.Connected) { - this.output = new cs.io.NativeOutput( new NetworkStream(sock) ); - this.input = new cs.io.NativeInput( new NetworkStream(sock) ); + this.output = new cs.io.NativeOutput(new NetworkStream(sock)); + this.input = new cs.io.NativeInput(new NetworkStream(sock)); } else { throw "Connection failed."; } } - /** - Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use `accept()` to accept incoming connections. - **/ - public function listen( connections : Int ) : Void { - sock.Listen( connections ); + public function listen(connections:Int):Void { + sock.Listen(connections); } - /** - Shutdown the socket, either for reading or writing. - **/ - public function shutdown( read : Bool, write : Bool ) : Void { - if ( read && write ) { - sock.Shutdown( SocketShutdown.Both ); + public function shutdown(read:Bool, write:Bool):Void { + if (read && write) { + sock.Shutdown(SocketShutdown.Both); input = null; output = null; - } else if ( read ) { - sock.Shutdown( SocketShutdown.Receive ); + } else if (read) { + sock.Shutdown(SocketShutdown.Receive); input = null; - } else if ( write ) { - sock.Shutdown( SocketShutdown.Send ); + } else if (write) { + sock.Shutdown(SocketShutdown.Send); output = null; } } - /** - Bind the socket to the given host/port so it can afterwards listen for connections there. - **/ - public function bind( host : Host, port : Int ) : Void { - sock = new cs.system.net.sockets.Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); - sock.Bind( new IPEndPoint(host.ipAddress, port) ); + public function bind(host:Host, port:Int):Void { + sock = new NativeSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + sock.Bind(new IPEndPoint(host.ipAddress, port)); } - /** - Accept a new connected client. This will return a connected socket on which you can read/write some data. - **/ - public function accept() : Socket { + public function accept():Socket { var r = new Socket(); r.sock = sock.Accept(); - r.output = new cs.io.NativeOutput( new NetworkStream(r.sock) ); - r.input = new cs.io.NativeInput( new NetworkStream(r.sock) ); + r.output = new cs.io.NativeOutput(new NetworkStream(r.sock)); + r.input = new cs.io.NativeInput(new NetworkStream(r.sock)); return r; } - /** - Return the information about the other side of a connected socket. - **/ - public function peer() : { host : Host, port : Int } { + public function peer():{host:Host, port:Int} { var remoteIP = cast(sock.RemoteEndPoint, IPEndPoint); - return { host: new Host(remoteIP.Address.ToString()), port: remoteIP.Port }; + return {host: new Host(remoteIP.Address.ToString()), port: remoteIP.Port}; } - /** - Return the information about our side of a connected socket. - **/ - public function host() : { host : Host, port : Int } { + public function host():{host:Host, port:Int} { var localIP = cast(sock.LocalEndPoint, IPEndPoint); - return { host: new Host(localIP.Address.ToString()), port: localIP.Port }; + return {host: new Host(localIP.Address.ToString()), port: localIP.Port}; } - /** - Gives a timeout after which blocking socket operations (such as reading and writing) will abort and throw an exception. - **/ - public function setTimeout( timeout : Float ) : Void { + public function setTimeout(timeout:Float):Void { sock.ReceiveTimeout = sock.SendTimeout = Math.round(timeout * 1000); } - /** - Block until some data is available for read on the socket. - **/ - public function waitForRead() : Void { + public function waitForRead():Void { var end = Date.now().getTime() + ((sock.ReceiveTimeout <= 0) ? Math.POSITIVE_INFINITY : sock.ReceiveTimeout); - while ( sock.Available == 0 && Date.now().getTime() < end) { + while (sock.Available == 0 && Date.now().getTime() < end) { Thread.Sleep(5); } } - /** - Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediately by throwing a haxe.io.Error.Blocked value. - **/ - public function setBlocking( b : Bool ) : Void { + public function setBlocking(b:Bool):Void { sock.Blocking = b; } - /** - Allows the socket to immediately send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes. - **/ - public function setFastSend( b : Bool ) : Void { + public function setFastSend(b:Bool):Void { sock.NoDelay = b; } - /** - Wait until one of the sockets groups is ready for the given operation : - * `read` contains sockets on which we want to wait for available data to be read, - * `write` contains sockets on which we want to wait until we are allowed to write some data to their output buffers, - * `others` contains sockets on which we want to wait for exceptional conditions. - * `select` will block until one of the condition is met, in which case it will return the sockets for which the condition was true. - In case a `timeout` (in seconds) is specified, select might wait at worse until the timeout expires. - **/ - static public function select(read : Array, write : Array, others : Array, ?timeout : Float) : { read: Array,write: Array,others: Array } { - throw "Not implemented yet."; - return null; - } + static public function select(read:Array, write:Array, others:Array, + ?timeout:Float):{read:Array, write:Array, others:Array} { + var map:Map = new Map(); + inline function addSockets(sockets:Array) { + if (sockets != null) + for (s in sockets) + map[s.sock.Handle.ToInt32()] = s; + } + inline function getRaw(sockets:Array):ArrayList { + var a = new ArrayList(sockets == null ? 0 : sockets.length); + if (sockets != null) + for (s in sockets) { + a.Add(s.sock); + } + return a; + } + inline function getOriginal(result:ArrayList) { + var a:Array = []; + for (i in 0...result.Count) { + var s:NativeSocket = result[i]; + a.push(map[s.Handle.ToInt32()]); + } + return a; + } + addSockets(read); + addSockets(write); + addSockets(others); + + // unwrap Sockets into native sockets + var rawRead:ArrayList = getRaw(read), + rawWrite:ArrayList = getRaw(write), + rawOthers:ArrayList = getRaw(others); + var microsec = timeout == null ? -1 : Std.int(timeout * 1000000); + NativeSocket.Select(rawRead, rawWrite, rawOthers, microsec); + // convert native sockets back to Socket objects + return { + read: getOriginal(rawRead), + write: getOriginal(rawWrite), + others: getOriginal(rawOthers), + } + } } diff --git a/std/cs/_std/sys/thread/Deque.hx b/std/cs/_std/sys/thread/Deque.hx new file mode 100644 index 00000000000..09f1b59fd68 --- /dev/null +++ b/std/cs/_std/sys/thread/Deque.hx @@ -0,0 +1,60 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +import cs.system.threading.ManualResetEvent; +import cs.Lib; + +@:coreApi class Deque { + final storage:Array = []; + final lockObj = {}; + final addEvent = new ManualResetEvent(false); + + public function new():Void {} + + public function add(i:T):Void { + Lib.lock(lockObj, { + storage.push(i); + addEvent.Set(); + }); + } + + public function push(i:T):Void { + Lib.lock(lockObj, { + storage.unshift(i); + addEvent.Set(); + }); + } + + public function pop(block:Bool):Null { + do { + Lib.lock(lockObj, { + if (storage.length > 0) { + return storage.shift(); + } + addEvent.Reset(); + }); + } while (block && addEvent.WaitOne()); + return null; + } +} diff --git a/std/cs/_std/sys/thread/Lock.hx b/std/cs/_std/sys/thread/Lock.hx new file mode 100644 index 00000000000..e7c79d7f9e4 --- /dev/null +++ b/std/cs/_std/sys/thread/Lock.hx @@ -0,0 +1,79 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +import haxe.Timer; +import cs.Lib; +import cs.system.threading.ManualResetEvent; + +class Lock { + final lockObj = {}; + final releaseEvent = new ManualResetEvent(false); + + var waitCount = 1; // initially locked + var releaseCount = 0; + + public function new():Void {} + + public function wait(?timeout:Float):Bool { + var myTicket; + // Get a ticket in queue + Lib.lock(lockObj, { + myTicket = waitCount; + waitCount++; + if (myTicket <= releaseCount) { + return true; + } + releaseEvent.Reset(); + }); + + if (timeout == null) { + do { + releaseEvent.WaitOne(); + if (myTicket <= releaseCount) { + return true; + } + } while (true); + } else { + var timeoutStamp = Timer.stamp() + timeout; + do { + var secondsLeft = timeoutStamp - Timer.stamp(); + if (secondsLeft <= 0 || !releaseEvent.WaitOne(Std.int(secondsLeft * 1000))) { + // Timeout. Do not occupy a place in queue anymore + release(); + return false; + } + if (myTicket <= releaseCount) { + return true; + } + } while (true); + } + } + + public function release():Void { + Lib.lock(lockObj, { + releaseCount++; + releaseEvent.Set(); + }); + } +} diff --git a/std/cs/_std/sys/thread/Mutex.hx b/std/cs/_std/sys/thread/Mutex.hx new file mode 100644 index 00000000000..184f9d837e5 --- /dev/null +++ b/std/cs/_std/sys/thread/Mutex.hx @@ -0,0 +1,43 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +import cs.system.threading.Mutex as NativeMutex; + +class Mutex { + final native = new NativeMutex(); + + public function new():Void {} + + public function acquire():Void { + native.WaitOne(); + } + + public function tryAcquire():Bool { + return native.WaitOne(0); + } + + public function release():Void { + native.ReleaseMutex(); + } +} diff --git a/std/cs/_std/sys/thread/Thread.hx b/std/cs/_std/sys/thread/Thread.hx new file mode 100644 index 00000000000..d2765a1a087 --- /dev/null +++ b/std/cs/_std/sys/thread/Thread.hx @@ -0,0 +1,112 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +import cs.system.threading.Thread as NativeThread; +import cs.system.WeakReference; +import cs.Lib; + +abstract Thread(HaxeThread) { + inline function new(thread:HaxeThread) { + this = thread; + } + + public static function create(cb:Void->Void):Thread { + var native = new NativeThread(cb); + native.IsBackground = true; + var hx = HaxeThread.allocate(native); + native.Start(); + + return new Thread(hx); + } + + public static inline function current():Thread { + return new Thread(HaxeThread.get(NativeThread.CurrentThread)); + } + + public static function readMessage(block:Bool):Dynamic { + return current().readMessageImpl(block); + } + + public inline function sendMessage(msg:Dynamic):Void { + this.sendMessage(msg); + } + + inline function readMessageImpl(block:Bool):Dynamic { + return this.readMessage(block); + } +} + +private class HaxeThread { + static final threads = new Map(); + static var allocateCount = 0; + + public final native:NativeThread; + + final messages = new Deque(); + + public static function get(native:NativeThread):HaxeThread { + var native = NativeThread.CurrentThread; + var ref:Null = null; + Lib.lock(threads, { + var key = native.ManagedThreadId; + ref = threads.get(key); + }); + if (ref == null || !ref.IsAlive) { + return allocate(native); + } + return ref.Target; + } + + public static function allocate(native:NativeThread):HaxeThread { + allocateCount++; + inline function cleanup() { + if (allocateCount % 100 == 0) { + for (key => ref in threads) { + if (!ref.IsAlive) { + threads.remove(key); + } + } + } + } + var hx = new HaxeThread(native); + var ref = new WeakReference(hx); + Lib.lock(threads, { + cleanup(); + threads.set(native.ManagedThreadId, ref); + }); + return hx; + } + + public function new(native:NativeThread) { + this.native = native; + } + + public inline function readMessage(block:Bool):Dynamic { + return messages.pop(block); + } + + public function sendMessage(msg:Dynamic):Void { + messages.add(msg); + } +} diff --git a/std/cs/_std/sys/thread/Tls.hx b/std/cs/_std/sys/thread/Tls.hx new file mode 100644 index 00000000000..13c77a1bd29 --- /dev/null +++ b/std/cs/_std/sys/thread/Tls.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +import cs.system.threading.Thread as NativeThread; +import cs.system.LocalDataStoreSlot; + +class Tls { + public var value(get, set):T; + + final slot:LocalDataStoreSlot; + + public function new():Void { + slot = NativeThread.GetNamedDataSlot('__hx__Tls'); + } + + function get_value():T { + return NativeThread.GetData(slot); + } + + function set_value(value:T):T { + NativeThread.SetData(slot, value); + return value; + } +} diff --git a/std/cs/db/AdoNet.hx b/std/cs/db/AdoNet.hx index 0d32b25b257..98fbdb3bdb2 100644 --- a/std/cs/db/AdoNet.hx +++ b/std/cs/db/AdoNet.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,33 +19,32 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cs.db; + +package cs.db; + import sys.db.*; import cs.system.data.*; -class AdoNet -{ - public static function create(cnx:IDbConnection, dbName:String):Connection - { - return new AdoConnection(cnx,dbName); +class AdoNet { + public static function create(cnx:IDbConnection, dbName:String):Connection { + return new AdoConnection(cnx, dbName); } } -private class AdoConnection implements Connection -{ +private class AdoConnection implements Connection { private static var ids = 0; + private var id:Int; private var cnx:IDbConnection; - //escape handling + // escape handling private var escapeRegex:EReg; private var escapes:Array; private var name:String; private var command:IDbCommand; private var transaction:IDbTransaction; - public function new(cnx,name:String) - { + public function new(cnx, name:String) { this.id = cs.system.threading.Interlocked.Increment(ids); this.cnx = cnx; this.name = name; @@ -54,49 +53,43 @@ private class AdoConnection implements Connection this.escapeRegex = ~/@HX_ESCAPE(\d+)_(\d+)/; } - public function close() : Void - { + public function close():Void { cnx.Close(); } - public function escape(s:String):String - { + public function escape(s:String):String { var param = command.CreateParameter(); - var name = "@HX_ESCAPE" + id + "_" +escapes.push(param) + ""; + var name = "@HX_ESCAPE" + id + "_" + escapes.push(param) + ""; param.ParameterName = name; param.Value = s; return name; } - public function quote(s:String):String - { + public function quote(s:String):String { var param = command.CreateParameter(); - var name = "@HX_ESCAPE" + id + "_" +escapes.push(param) + ""; + var name = "@HX_ESCAPE" + id + "_" + escapes.push(param) + ""; param.ParameterName = name; param.Value = s; return name; } - public function addValue(s:StringBuf, v:Dynamic) - { - if (Std.is(v, Date)) - { + public function addValue(s:StringBuf, v:Dynamic) { + if (Std.is(v, Date)) { v = Std.string(v); } else if (Std.is(v, haxe.io.Bytes)) { var bt:haxe.io.Bytes = v; v = bt.getData(); } var param = command.CreateParameter(); - var name = "@HX_ESCAPE" + id + "_" +escapes.push(param) + ""; + var name = "@HX_ESCAPE" + id + "_" + escapes.push(param) + ""; param.ParameterName = name; param.Value = v; s.add(name); } - public function lastInsertId():Int - { + public function lastInsertId():Int { var ret = cnx.CreateCommand(); - ret.CommandText = switch(name) { + ret.CommandText = switch (name) { case 'SQLite': 'SELECT last_insert_rowid()'; case _: @@ -109,69 +102,65 @@ private class AdoConnection implements Connection return r; } - public function dbName() : String - { + public function dbName():String { return name; } - public function startTransaction() : Void - { + public function startTransaction():Void { if (this.transaction != null) throw 'Transaction already active'; this.transaction = cnx.BeginTransaction(); } - public function commit() : Void - { + public function commit():Void { if (this.transaction == null) throw 'No transaction was initiated'; this.transaction.Commit(); } - public function rollback() : Void - { + public function rollback():Void { if (this.transaction == null) throw 'No transaction was initiated'; this.transaction.Rollback(); } - private static function getFirstStatement(s:String) - { + private static function getFirstStatement(s:String) { var buf = new StringBuf(); var hasData = false; - var chr = 0, - i = 0; - inline function getch() return chr = StringTools.fastCodeAt(s,i++); - while ( !StringTools.isEof(getch()) ) - { - inline function peek() { var c = StringTools.fastCodeAt(s,i); if (StringTools.isEof(c)) break; return c; } - switch(chr) - { + var chr = 0, i = 0; + inline function getch() + return chr = StringTools.fastCodeAt(s, i++); + while (!StringTools.isEof(getch())) { + inline function peek() { + var c = StringTools.fastCodeAt(s, i); + if (StringTools.isEof(c)) + break; + return c; + } + switch (chr) { case ' '.code | '\t'.code | '\n'.code: if (hasData) return buf.toString(); case '-'.code if (peek() == '-'.code): if (hasData) return buf.toString(); - while (!StringTools.isEof(getch())) - { - if (chr == '\n'.code) break; + while (!StringTools.isEof(getch())) { + if (chr == '\n'.code) + break; } case '#'.code: if (hasData) return buf.toString(); - while (!StringTools.isEof(getch())) - { - if (chr == '\n'.code) break; + while (!StringTools.isEof(getch())) { + if (chr == '\n'.code) + break; } case '/'.code if (peek() == '*'.code): i++; if (hasData) return buf.toString(); - while (!StringTools.isEof(getch())) - { - if (chr == '*'.code && peek() == '/'.code) - { + while (!StringTools.isEof(getch())) { + if (chr == '*'.code && peek() == '/'.code) { i++; break; } @@ -184,31 +173,29 @@ private class AdoConnection implements Connection return buf.toString(); } - public function request( s : String ) : ResultSet - { + public function request(s:String):ResultSet { var newst = new StringBuf(); - //cycle through the request string, adding any @HX_ESCAPE reference to the command + // cycle through the request string, adding any @HX_ESCAPE reference to the command var ret:ResultSet = null; var r = escapeRegex; var myid = id + "", escapes = escapes, elen = escapes.length; var cmd = this.command; - try - { - while (r.match(s)) - { + try { + while (r.match(s)) { var id = r.matched(1); -#if debug - if (id != myid) throw "Request quotes are only valid for one single request; They can't be cached."; -#end + #if debug + if (id != myid) + throw "Request quotes are only valid for one single request; They can't be cached."; + #end newst.add(r.matchedLeft()); var eid = Std.parseInt(r.matched(2)); -#if debug + #if debug if (eid == null || eid > elen) throw "Invalid request quote ID " + eid; -#end + #end cmd.Parameters.Add(escapes[eid - 1]); - newst.add(escapes[eid-1].ParameterName); + newst.add(escapes[eid - 1].ParameterName); s = r.matchedRight(); } newst.add(s); @@ -217,9 +204,8 @@ private class AdoConnection implements Connection cmd.CommandText = s; var stmt = getFirstStatement(s).toLowerCase(); - if (stmt == 'select') - { - ret = new AdoResultSet( cmd.ExecuteReader() ); + if (stmt == 'select') { + ret = new AdoResultSet(cmd.ExecuteReader()); } else { cmd.ExecuteNonQuery(); ret = EmptyResultSet.empty; @@ -231,13 +217,13 @@ private class AdoConnection implements Connection cmd.Dispose(); this.command = cnx.CreateCommand(); return ret; - } - catch(e:Dynamic) - { + } catch (e:Dynamic) { if (escapes.length != 0) this.escapes = []; this.id = cs.system.threading.Interlocked.Increment(ids); - try { cmd.Dispose(); } catch(e:Dynamic) {} + try { + cmd.Dispose(); + } catch (e:Dynamic) {} this.command = cnx.CreateCommand(); cs.Lib.rethrow(e); } @@ -245,47 +231,40 @@ private class AdoConnection implements Connection } } -private class AdoResultSet implements ResultSet -{ - public var length(get,null) : Int; - public var nfields(get,null) : Int; +private class AdoResultSet implements ResultSet { + public var length(get, null):Int; + public var nfields(get, null):Int; private var reader:IDataReader; private var didNext:Bool; private var names:Array; private var types:Array>; - public function new(reader) - { + public function new(reader) { this.reader = reader; - this.names = [ for (i in 0...reader.FieldCount) reader.GetName(i) ]; - this.types = [ for (i in 0...names.length) cs.Lib.fromNativeType(reader.GetFieldType(i)) ]; + this.names = [for (i in 0...reader.FieldCount) reader.GetName(i)]; + this.types = [for (i in 0...names.length) cs.Lib.fromNativeType(reader.GetFieldType(i))]; } - private function get_length() - { + private function get_length() { return reader.Depth; } - private function get_nfields() - { + private function get_nfields() { return names.length; } - public function hasNext() : Bool - { + public function hasNext():Bool { didNext = true; return reader.Read(); } - public function next() : Dynamic - { + public function next():Dynamic { if (!didNext && !hasNext()) return null; didNext = false; var ret = {}, names = names, types = types; - for (i in 0...names.length) - { + for (i in 0...names.length) { var name = names[i], t = types[i], val:Dynamic = null; if (reader.IsDBNull(i)) { val = null; @@ -299,74 +278,77 @@ private class AdoResultSet implements ResultSet val = null; } else if (t == cs.system.Byte) { var v2:cs.StdTypes.UInt8 = reader.GetValue(i); - val = cast(v2,Int); + val = cast(v2, Int); } else if (Std.string(t) == 'System.Byte[]') { val = haxe.io.Bytes.ofData(reader.GetValue(i)); } else { val = reader.GetValue(i); } - if (Std.is(val,cs.system.DBNull)) + if (Std.is(val, cs.system.DBNull)) val = null; Reflect.setField(ret, name, val); } return ret; } - public function results() : List - { + public function results():List { var l = new List(); while (hasNext()) l.add(next()); return l; } - public function getResult( n : Int ) : String - { + public function getResult(n:Int):String { return reader.GetString(n); } - public function getIntResult( n : Int ) : Int - { + public function getIntResult(n:Int):Int { return reader.GetInt32(n); } - public function getFloatResult( n : Int ) : Float - { + public function getFloatResult(n:Int):Float { return reader.GetDouble(n); } - public function getFieldsNames() : Null> - { + public function getFieldsNames():Null> { return names; } - } -private class EmptyResultSet implements ResultSet -{ +private class EmptyResultSet implements ResultSet { public static var empty = new EmptyResultSet(); - public function new() - { - } - public var length(get,null) : Int; - public var nfields(get,null) : Int; + public function new() {} - private function get_length() - { + public var length(get, null):Int; + public var nfields(get, null):Int; + + private function get_length() { return 0; } - private function get_nfields() - { + private function get_nfields() { return 0; } - public function hasNext() : Bool return false; - public function next() : Dynamic return null; - public function results() : List return new List(); - public function getResult( n : Int ) : String return null; - public function getIntResult( n : Int ) : Int return 0; - public function getFloatResult( n : Int ) : Float return 0; - public function getFieldsNames() : Null> return null; + public function hasNext():Bool + return false; + + public function next():Dynamic + return null; + + public function results():List + return new List(); + + public function getResult(n:Int):String + return null; + + public function getIntResult(n:Int):Int + return 0; + + public function getFloatResult(n:Int):Float + return 0; + + public function getFieldsNames():Null> + return null; } diff --git a/std/cs/internal/BoxedPointer.hx b/std/cs/internal/BoxedPointer.hx index 3c9d7c3ba2f..2b94161ff0b 100644 --- a/std/cs/internal/BoxedPointer.hx +++ b/std/cs/internal/BoxedPointer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,15 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package cs.internal; -@:unsafe @:keep @:native('haxe.lang.BoxedPointer') @:nativeGen class BoxedPointer -{ - @:readonly public var value(default,null):Pointer; +package cs.internal; - public function new(val) - { +@:unsafe @:keep @:native('haxe.lang.BoxedPointer') @:nativeGen class BoxedPointer { + @:readonly public var value(default, null):Pointer; + + public function new(val) { this.value = val; } - } diff --git a/std/cs/internal/Exceptions.hx b/std/cs/internal/Exceptions.hx index 5ac0df5b5d4..318bf2a6cfb 100644 --- a/std/cs/internal/Exceptions.hx +++ b/std/cs/internal/Exceptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,47 +19,44 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.internal; + import cs.system.Exception; @:nativeGen @:keep @:native("haxe.lang.Exceptions") class Exceptions { - @:allow(haxe.CallStack) @:meta(System.ThreadStaticAttribute) static var exception:cs.system.Exception; } -//should NOT be usable inside Haxe code +// should NOT be usable inside Haxe code + @:classCode('override public string Message { get { return this.toString(); } }\n\n') -@:nativeGen @:keep @:native("haxe.lang.HaxeException") private class HaxeException extends Exception -{ +@:nativeGen @:keep @:native("haxe.lang.HaxeException") private class HaxeException extends Exception { private var obj:Dynamic; - public function new(obj:Dynamic) - { + public function new(obj:Dynamic) { super(); - if (Std.is(obj, HaxeException)) - { + if (Std.is(obj, HaxeException)) { var _obj:HaxeException = cast obj; obj = _obj.getObject(); } this.obj = obj; } - public function getObject():Dynamic - { + public function getObject():Dynamic { return obj; } - public function toString():String - { + public function toString():String { return Std.string(obj); } - public static function wrap(obj:Dynamic):Exception - { - if (Std.is(obj, Exception)) return obj; + public static function wrap(obj:Dynamic):Exception { + if (Std.is(obj, Exception)) + return obj; return new HaxeException(obj); } diff --git a/std/cs/internal/FieldLookup.hx b/std/cs/internal/FieldLookup.hx index f5a7fba81fa..59739d8f391 100644 --- a/std/cs/internal/FieldLookup.hx +++ b/std/cs/internal/FieldLookup.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,15 +19,17 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.internal; @:native('haxe.lang.FieldHashConflict') -@:final @:nativeGen -@:keep class FieldHashConflict { - @:readOnly public var hash(default,never):Int; - @:readOnly public var name(default,never):String; +@:nativeGen @:keep +final class FieldHashConflict { + @:readOnly public var hash(default, never):Int; + @:readOnly public var name(default, never):String; public var value:Dynamic; public var next:FieldHashConflict; + public function new(hash, name, value:Dynamic, next) { untyped this.hash = hash; untyped this.name = name; @@ -37,51 +39,43 @@ package cs.internal; } @:native('haxe.lang.FieldLookup') -@:final @:nativeGen @:classCode("#pragma warning disable 628\n") -@:keep @:static class FieldLookup -{ +@:nativeGen @:keep @:static +final class FieldLookup { @:protected private static var fieldIds:cs.NativeArray; @:protected private static var fields:cs.NativeArray; @:protected private static var length:Int; - static function __init__() - { + static function __init__() { length = fieldIds.Length; } - private static function addFields(nids:cs.NativeArray, nfields:cs.NativeArray):Void - { + private static function addFields(nids:cs.NativeArray, nfields:cs.NativeArray):Void { // first see if we need to add anything - var cids = fieldIds, - cfields = fields; + var cids = fieldIds, cfields = fields; var nlen = nids.Length; var clen = length; - if (nfields.Length != nlen) throw 'Different fields length: $nlen and ${nfields.Length}'; + if (nfields.Length != nlen) + throw 'Different fields length: $nlen and ${nfields.Length}'; - //TODO optimize + // TODO optimize var needsChange = false; - for (i in nids) - { - if (findHash(i, cids, clen) < 0) - { + for (i in nids) { + if (findHash(i, cids, clen) < 0) { needsChange = true; break; } } // if we do, lock and merge - if (needsChange) - { + if (needsChange) { cs.Lib.lock(FieldLookup, { // trace(cs.Lib.array(nids), cs.Lib.array(cids)); var ansIds = new cs.NativeArray(clen + nlen), - ansFields = new cs.NativeArray(clen + nlen); + ansFields = new cs.NativeArray(clen + nlen); var ci = 0, ni = 0, ansi = 0; - while (ci < clen && ni < nlen) - { - if (cids[ci] < nids[ni]) - { + while (ci < clen && ni < nlen) { + if (cids[ci] < nids[ni]) { ansIds[ansi] = cids[ci]; ansFields[ansi] = cfields[ci]; ++ci; @@ -93,15 +87,13 @@ package cs.internal; ++ansi; } - if (ci < clen) - { + if (ci < clen) { cs.system.Array.Copy(cids, ci, ansIds, ansi, clen - ci); cs.system.Array.Copy(cfields, ci, ansFields, ansi, clen - ci); ansi += clen - ci; } - if (ni < nlen) - { + if (ni < nlen) { cs.system.Array.Copy(nids, ni, ansIds, ansi, nlen - ni); cs.system.Array.Copy(nfields, ni, ansFields, ansi, nlen - ni); ansi += nlen - ni; @@ -115,31 +107,25 @@ package cs.internal; } } - //s cannot be null here - private static inline function doHash(s:String):Int - { - var acc = 0; //alloc_int - for (i in 0...s.length) - { - acc = (( 223 * (acc >> 1) + cast(s[i], Int)) << 1); + // s cannot be null here + private static inline function doHash(s:String):Int { + var acc = 0; // alloc_int + for (i in 0...s.length) { + acc = ((223 * (acc >> 1) + cast(s[i], Int)) << 1); } - return acc >>> 1; //always positive + return acc >>> 1; // always positive } - public static function lookupHash(key:Int):String - { - //start of binary search algorithm + public static function lookupHash(key:Int):String { var ids = fieldIds; var min = 0; var max = length; - while (min < max) - { + while (min < max) { var mid = min + Std.int((max - min) / 2); var imid = ids[mid]; - if (key < imid) - { + if (key < imid) { max = mid; } else if (key > imid) { min = mid + 1; @@ -147,72 +133,58 @@ package cs.internal; return fields[mid]; } } - //if not found, it's definitely an error + // if not found, it's definitely an error throw "Field not found for hash " + key; } - public static function hash(s:String):Int - { - if (s == null) return 0; + public static function hash(s:String):Int { + if (s == null) + return 0; var key = doHash(s); - //start of binary search algorithm - var ids = fieldIds, - fld = fields; + var ids = fieldIds, fld = fields; var min = 0; var max = length; var len = length; - while (min < max) - { - var mid = Std.int(min + (max - min) / 2); //overflow safe + while (min < max) { + var mid = Std.int(min + (max - min) / 2); // overflow safe var imid = ids[mid]; - if (key < imid) - { + if (key < imid) { max = mid; } else if (key > imid) { min = mid + 1; } else { var field = fld[mid]; if (field != s) - return ~key; //special case + return ~key; // special case return key; } } - //if not found, min holds the value where we should insert the key - //ensure thread safety: + // if not found, min holds the value where we should insert the key + // ensure thread safety: cs.Lib.lock(FieldLookup, { - if (len != length) //race condition which will very rarely happen - other thread modified sooner. - return hash(s); //since we already own the lock, this second try will always succeed + if (len != length) // race condition which will very rarely happen - other thread modified sooner. + return hash(s); // since we already own the lock, this second try will always succeed -#if erase_generics fieldIds = insertInt(fieldIds, length, min, key); fields = insertString(fields, length, min, s); -#else - insert(fieldIds, length, min, key); - insert(fields, length, min, s); - // ids.insert(min, key); - // fields.insert(min, s); -#end ++length; }); return key; } - public static function findHash(hash:Int, hashs:cs.NativeArray, length:Int):Int - { + public static function findHash(hash:Int, hashs:cs.NativeArray, length:Int):Int { var min = 0; var max = length; - while (min < max) - { - var mid = Std.int((max + min) / 2); //overflow safe + while (min < max) { + var mid = Std.int((max + min) / 2); var imid = hashs[mid]; - if (hash < imid) - { + if (hash < imid) { max = mid; } else if (hash > imid) { min = mid + 1; @@ -220,113 +192,48 @@ package cs.internal; return mid; } } - //if not found, return a negative value of where it should be inserted + // if not found, return a negative value of where it should be inserted return ~min; } - #if !erase_generics - static function remove(a:cs.NativeArray, length:Int, pos:Int) - { - cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1); - a[length - 1] = null; - } - - static function insert(a:cs.Ref>, length:Int, pos:Int, x:T) - { - var capacity = a.Length; - if (pos == length) - { - if (capacity == length) - { - var newarr = new NativeArray((length << 1) + 1); - a.CopyTo(newarr, 0); - a = newarr; - } - } - else if (pos == 0) - { - if (capacity == length) - { - var newarr = new NativeArray((length << 1) + 1); - cs.system.Array.Copy(a, 0, newarr, 1, length); - a = newarr; - } - else - { - cs.system.Array.Copy(a, 0, a, 1, length); - } - } - else - { - if (capacity == length) - { - var newarr = new NativeArray((length << 1) + 1); - cs.system.Array.Copy(a, 0, newarr, 0, pos); - cs.system.Array.Copy(a, pos, newarr, pos + 1, length - pos); - a = newarr; - } - else - { - cs.system.Array.Copy(a, pos, a, pos + 1, length - pos); - cs.system.Array.Copy(a, 0, a, 0, pos); - } - } - a[pos] = x; - } - #else - static function removeInt(a:cs.NativeArray, length:Int, pos:Int) - { + public static function removeInt(a:cs.NativeArray, length:Int, pos:Int) { cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1); a[length - 1] = 0; } - static function removeFloat(a:cs.NativeArray, length:Int, pos:Int) - { + + public static function removeFloat(a:cs.NativeArray, length:Int, pos:Int) { cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1); a[length - 1] = 0; } - static function removeDynamic(a:cs.NativeArray, length:Int, pos:Int) - { + + public static function removeDynamic(a:cs.NativeArray, length:Int, pos:Int) { cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1); a[length - 1] = null; } - @:extern - static inline function __insert(a:cs.NativeArray, length:Int, pos:Int, x:T):cs.NativeArray - { + extern static inline function __insert(a:cs.NativeArray, length:Int, pos:Int, x:T):cs.NativeArray { var capacity = a.Length; - if (pos == length) - { - if (capacity == length) - { + if (pos == length) { + if (capacity == length) { var newarr = new NativeArray((length << 1) + 1); a.CopyTo(newarr, 0); a = newarr; } - } - else if (pos == 0) - { - if (capacity == length) - { + } else if (pos == 0) { + if (capacity == length) { var newarr = new NativeArray((length << 1) + 1); cs.system.Array.Copy(a, 0, newarr, 1, length); a = newarr; - } - else - { + } else { cs.system.Array.Copy(a, 0, a, 1, length); } - } - else - { - if (capacity == length) - { + } else { + if (capacity == length) { var newarr = new NativeArray((length << 1) + 1); cs.system.Array.Copy(a, 0, newarr, 0, pos); cs.system.Array.Copy(a, pos, newarr, pos + 1, length - pos); a = newarr; - } - else - { + } else { cs.system.Array.Copy(a, pos, a, pos + 1, length - pos); cs.system.Array.Copy(a, 0, a, 0, pos); } @@ -335,13 +242,19 @@ package cs.internal; return a; } - static function insertInt(a:cs.NativeArray, length:Int, pos:Int, x:Int):cs.NativeArray return __insert(a, length, pos, x); - static function insertFloat(a:cs.NativeArray, length:Int, pos:Int, x:Float):cs.NativeArray return __insert(a, length, pos, x); - static function insertDynamic(a:cs.NativeArray, length:Int, pos:Int, x:Dynamic):cs.NativeArray return __insert(a, length, pos, x); - static function insertString(a:cs.NativeArray, length:Int, pos:Int, x:Dynamic):cs.NativeArray return __insert(a, length, pos, x); - #end + public static function insertInt(a:cs.NativeArray, length:Int, pos:Int, x:Int):cs.NativeArray + return __insert(a, length, pos, x); + + public static function insertFloat(a:cs.NativeArray, length:Int, pos:Int, x:Float):cs.NativeArray + return __insert(a, length, pos, x); + + public static function insertDynamic(a:cs.NativeArray, length:Int, pos:Int, x:Dynamic):cs.NativeArray + return __insert(a, length, pos, x); + + public static function insertString(a:cs.NativeArray, length:Int, pos:Int, x:String):cs.NativeArray + return __insert(a, length, pos, x); - static function getHashConflict(head:FieldHashConflict, hash:Int, name:String):FieldHashConflict { + public static function getHashConflict(head:FieldHashConflict, hash:Int, name:String):FieldHashConflict { while (head != null) { if (head.hash == hash && head.name == name) { return head; @@ -351,7 +264,7 @@ package cs.internal; return null; } - static function setHashConflict(head:cs.Ref, hash:Int, name:String, value:Dynamic):Void { + public static function setHashConflict(head:cs.Ref, hash:Int, name:String, value:Dynamic):Void { var node = head; while (node != null) { if (node.hash == hash && node.name == name) { @@ -363,7 +276,7 @@ package cs.internal; head = new FieldHashConflict(hash, name, value, head); } - static function deleteHashConflict(head:cs.Ref, hash:Int, name:String):Bool { + public static function deleteHashConflict(head:cs.Ref, hash:Int, name:String):Bool { // no conflicting fields at all if (head == null) { return false; @@ -389,7 +302,7 @@ package cs.internal; return false; } - static function addHashConflictNames(head:FieldHashConflict, arr:Array):Void { + public static function addHashConflictNames(head:FieldHashConflict, arr:Array):Void { while (head != null) { arr.push(head.name); head = head.next; diff --git a/std/cs/internal/Function.hx b/std/cs/internal/Function.hx index 7fe08686e31..d64f11da4a8 100644 --- a/std/cs/internal/Function.hx +++ b/std/cs/internal/Function.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,75 +19,61 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.internal; /** - These classes are automatically generated by the compiler. They are only - here so there is an option for e.g. defining them as externs if you are compiling - in modules (untested). + These classes are automatically generated by the compiler. They are only + here so there is an option for e.g. defining them as externs if you are compiling + in modules (untested). **/ - -@:keep @:abstract @:nativeGen @:native("haxe.lang.Function") class Function -{ - function new(arity:Int, type:Int) - { - - } +@:keep @:abstract @:nativeGen @:native("haxe.lang.Function") class Function { + function new(arity:Int, type:Int) {} } -@:keep @:nativeGen @:native("haxe.lang.VarArgsBase") private class VarArgsBase extends Function -{ - public function __hx_invokeDynamic(dynArgs:cs.NativeArray):Dynamic - { +@:keep @:nativeGen @:native("haxe.lang.VarArgsBase") private class VarArgsBase extends Function { + public function __hx_invokeDynamic(dynArgs:cs.NativeArray):Dynamic { throw "Abstract implementation"; } } -@:keep @:nativeGen @:native('haxe.lang.VarArgsFunction') class VarArgsFunction extends VarArgsBase -{ +@:keep @:nativeGen @:native('haxe.lang.VarArgsFunction') class VarArgsFunction extends VarArgsBase { private var fun:Array->Dynamic; - public function new(fun) - { + public function new(fun) { super(-1, -1); this.fun = fun; } - override public function __hx_invokeDynamic(dynArgs:cs.NativeArray):Dynamic - { + override public function __hx_invokeDynamic(dynArgs:cs.NativeArray):Dynamic { return fun(cs.Lib.array(dynArgs)); } } -@:keep @:nativeGen @:native('haxe.lang.Closure') class Closure extends VarArgsBase -{ +@:keep @:nativeGen @:native('haxe.lang.Closure') class Closure extends VarArgsBase { private var obj:Dynamic; private var field:String; private var hash:Int; - public function new(obj:Dynamic, field, hash) - { + public function new(obj:Dynamic, field, hash) { super(-1, -1); this.obj = obj; this.field = field; this.hash = hash; } - override public function __hx_invokeDynamic(dynArgs:cs.NativeArray):Dynamic - { + override public function __hx_invokeDynamic(dynArgs:cs.NativeArray):Dynamic { return Runtime.callField(obj, field, hash, dynArgs); } - public function Equals(obj:Dynamic):Bool - { + public function Equals(obj:Dynamic):Bool { var c = cs.Lib.as(obj, Closure); if (c == null) return false; return (c.obj == this.obj && c.field == this.field); } - public function GetHashCode():Int - { + public function GetHashCode():Int { return obj.GetHashCode() ^ untyped field.GetHashCode(); } } diff --git a/std/cs/internal/HxObject.hx b/std/cs/internal/HxObject.hx index 703ea6b2cc1..f1197e4046c 100644 --- a/std/cs/internal/HxObject.hx +++ b/std/cs/internal/HxObject.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,74 +19,257 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.internal; + import cs.system.Type; import haxe.ds.Vector; +import cs.internal.FieldLookup; + private typedef StdType = std.Type; @:keep @:native('haxe.lang.HxObject') -class HxObject implements IHxObject -{ +class HxObject implements IHxObject { + public function __hx_deleteField(field:String, hash:Int):Bool { + return false; + } } @:keep @:native('haxe.lang.IHxObject') -interface IHxObject -{ -} +interface IHxObject {} #if core_api_serialize @:meta(System.Serializable) #end @:keep @:native('haxe.lang.DynamicObject') -class DynamicObject extends HxObject implements Dynamic -{ - @:skipReflection public function toString():String - { +class DynamicObject extends HxObject { + @:skipReflection var __hx_hashes:NativeArray; + @:skipReflection var __hx_dynamics:NativeArray; + + @:skipReflection var __hx_hashes_f:NativeArray; + @:skipReflection var __hx_dynamics_f:NativeArray; + + @:skipReflection var __hx_length:Int; + @:skipReflection var __hx_length_f:Int; + @:skipReflection var __hx_conflicts:FieldHashConflict; + + @:skipReflection static var __hx_toString_depth = 0; + + @:overload public function new() { + this.__hx_hashes = new NativeArray(0); + this.__hx_dynamics = new NativeArray(0); + this.__hx_hashes_f = new NativeArray(0); + this.__hx_dynamics_f = new NativeArray(0); + this.__hx_conflicts = null; + } + + @:overload public function new(hashes:NativeArray, dynamics:NativeArray, hashes_f:NativeArray, dynamics_f:NativeArray) { + this.__hx_hashes = hashes; + this.__hx_dynamics = dynamics; + this.__hx_hashes_f = hashes_f; + this.__hx_dynamics_f = dynamics_f; + this.__hx_length = hashes.length; + this.__hx_length_f = hashes_f.length; + this.__hx_conflicts = null; + } + + override public function __hx_deleteField(field:String, hash:Int):Bool { + if (hash < 0) { + return FieldLookup.deleteHashConflict(this.__hx_conflicts, hash, field); + } + + var res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length); + if (res >= 0) { + FieldLookup.removeInt(this.__hx_hashes, this.__hx_length, res); + FieldLookup.removeDynamic(this.__hx_dynamics, this.__hx_length, res); + this.__hx_length--; + return true; + } + res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f); + if (res >= 0) { + FieldLookup.removeInt(this.__hx_hashes_f, this.__hx_length_f, res); + FieldLookup.removeFloat(this.__hx_dynamics_f, this.__hx_length_f, res); + this.__hx_length_f--; + return true; + } + return false; + } + + public function __hx_getField(field:String, hash:Int, throwErrors:Bool, isCheck:Bool, handleProperties:Bool):Dynamic { + if (hash < 0) { + var conflict = FieldLookup.getHashConflict(this.__hx_conflicts, hash, field); + if (conflict != null) { + return conflict.value; + } + } + + var res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length); + if (res >= 0) { + return this.__hx_dynamics[res]; + } + res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f); + if (res >= 0) { + return this.__hx_dynamics_f[res]; + } + + return isCheck ? Runtime.undefined : null; + } + + public function __hx_setField(field:String, hash:Int, value:Dynamic, handleProperties:Bool):Dynamic { + if (hash < 0) { + FieldLookup.setHashConflict(this.__hx_conflicts, hash, field, value); + return value; + } + + var res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length); + if (res >= 0) { + return this.__hx_dynamics[res] = value; + } else { + var res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f); + if (res >= 0) { + if (Std.is(value, Float)) { + return this.__hx_dynamics_f[res] = value; + } + + FieldLookup.removeInt(this.__hx_hashes_f, this.__hx_length_f, res); + FieldLookup.removeFloat(this.__hx_dynamics_f, this.__hx_length_f, res); + this.__hx_length_f--; + } + } + + this.__hx_hashes = FieldLookup.insertInt(this.__hx_hashes, this.__hx_length, ~(res), hash); + this.__hx_dynamics = FieldLookup.insertDynamic(this.__hx_dynamics, this.__hx_length, ~(res), value); + this.__hx_length++; + return value; + } + + public function __hx_getField_f(field:String, hash:Int, throwErrors:Bool, handleProperties:Bool):Float { + if (hash < 0) { + var conflict = FieldLookup.getHashConflict(this.__hx_conflicts, hash, field); + if (conflict != null) { + return conflict.value; + } + } + + var res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f); + if (res >= 0) { + return this.__hx_dynamics_f[res]; + } + res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length); + if (res >= 0) { + return this.__hx_dynamics[res]; + } + + return 0.0; + } + + public function __hx_setField_f(field:String, hash:Int, value:Float, handleProperties:Bool):Float { + if (hash < 0) { + FieldLookup.setHashConflict(this.__hx_conflicts, hash, field, value); + return value; + } + + var res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f); + if (res >= 0) { + return this.__hx_dynamics_f[res] = value; + } else { + var res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length); + if (res >= 0) { + // return this.__hx_dynamics[res] = value; + FieldLookup.removeInt(this.__hx_hashes, this.__hx_length, res); + FieldLookup.removeDynamic(this.__hx_dynamics, this.__hx_length, res); + this.__hx_length--; + } + } + + this.__hx_hashes_f = FieldLookup.insertInt(this.__hx_hashes_f, this.__hx_length_f, ~(res), hash); + this.__hx_dynamics_f = FieldLookup.insertFloat(this.__hx_dynamics_f, this.__hx_length_f, ~(res), value); + this.__hx_length_f++; + return value; + } + + public function __hx_getFields(baseArr:Array):Void { + for (i in 0...this.__hx_length) { + baseArr.push(FieldLookup.lookupHash(this.__hx_hashes[i])); + } + for (i in 0...this.__hx_length_f) { + baseArr.push(FieldLookup.lookupHash(this.__hx_hashes_f[i])); + } + FieldLookup.addHashConflictNames(this.__hx_conflicts, baseArr); + } + + public function __hx_invokeField(field:String, hash:Int, dynargs:NativeArray):Dynamic { + if (field == "toString") { + return this.toString(); + } + var fn:Function = this.__hx_getField(field, hash, false, false, false); + if (fn == null) { + throw 'Cannot invoke field $field: It does not exist'; + } + + return untyped fn.__hx_invokeDynamic(dynargs); + } + + @:skipReflection public function toString() { + if (__hx_toString_depth >= 5) { + return "..."; + } + ++__hx_toString_depth; + try { + var s = __hx_toString(); + --__hx_toString_depth; + return s; + } catch (e:Dynamic) { + --__hx_toString_depth; + throw(e); + } + } + + @:skipReflection public function __hx_toString():String { var ts = Reflect.field(this, "toString"); if (ts != null) return ts(); var ret = new StringBuf(); ret.add("{"); var first = true; - for (f in Reflect.fields(this)) - { - if( first ) + for (f in Reflect.fields(this)) { + if (first) first = false; else ret.add(","); - ret.add(" "); ret.add(f); + ret.add(" "); + ret.add(f); ret.add(" : "); ret.add(Reflect.field(this, f)); } - if (!first) ret.add(" "); + if (!first) + ret.add(" "); ret.add("}"); return ret.toString(); } } #if !erase_generics -@:keep @:native('haxe.lang.IGenericObject') interface IGenericObject -{ -} +@:keep @:native('haxe.lang.IGenericObject') interface IGenericObject {} -@:nativeGen @:keep @:native('haxe.lang.GenericInterface') class GenericInterface extends cs.system.Attribute -{ - @:readOnly public var generic(default,never):cs.system.Type; +@:nativeGen @:keep @:native('haxe.lang.GenericInterface') class GenericInterface extends cs.system.Attribute { + @:readOnly public var generic(default, never):cs.system.Type; - public function new(generic) - { + public function new(generic) { super(); untyped this.generic = generic; } } #end -@:keep @:native('haxe.lang.Enum') @:nativeGen +@:keep +@:native('haxe.lang.Enum') +@:nativeGen #if core_api_serialize @:meta(System.Serializable) #end class HxEnum { - @:readOnly var _hx_index(default,never):Int; + @:readOnly var _hx_index(default, never):Int; @:protected function new(index:Int) { untyped this._hx_index = index; @@ -109,8 +292,7 @@ class HxEnum { ret.add(tag); ret.add("("); var first = true; - for (p in params) - { + for (p in params) { if (first) first = false; else @@ -123,12 +305,12 @@ class HxEnum { @:protected static function paramsGetHashCode(index:Int, params:Vector):Int { var h:Int = 19; - if (params != null) for (p in params) - { - h = h * 31; - if (p != null) - untyped h += p.GetHashCode(); - } + if (params != null) + for (p in params) { + h = h * 31; + if (p != null) + untyped h += p.GetHashCode(); + } h += index; return h; } diff --git a/std/cs/internal/Null.hx b/std/cs/internal/Null.hx index 92fd1eb18e8..57213d4b49f 100644 --- a/std/cs/internal/Null.hx +++ b/std/cs/internal/Null.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.internal; @:classCode('//This function is here to be used with Reflection, when the haxe.lang.Null type is known @@ -46,20 +47,20 @@ package cs.internal; private __NoValue__() {} } + override public string ToString() { + if (!hasValue) return "null"; + else return value.ToString(); + } ') #if core_api_serialize @:meta(System.Serializable) #end -@:keep @:struct @:nativeGen @:native("haxe.lang.Null") private class Nullable -{ - - @:readOnly public var value(default,never):T; - @:readOnly public var hasValue(default,never):Bool; +@:keep @:struct @:nativeGen @:native("haxe.lang.Null") private class Nullable { + @:readOnly public var value(default, never):T; + @:readOnly public var hasValue(default, never):Bool; - public function new(v:T, hasValue:Bool) - { - if (hasValue && cs.system.Object.ReferenceEquals(v, null)) - { + public function new(v:T, hasValue:Bool) { + if (hasValue && cs.system.Object.ReferenceEquals(v, null)) { hasValue = false; } untyped this.value = v; @@ -75,13 +76,11 @@ package cs.internal; } else { return new haxe.lang.Null((D) obj, true); }') - public static function ofDynamic(obj:Dynamic):Nullable - { + public static function ofDynamic(obj:Dynamic):Nullable { return null; } - public function toDynamic():Dynamic - { + public function toDynamic():Dynamic { if (this.hasValue) return value; return null; diff --git a/std/cs/internal/Runtime.hx b/std/cs/internal/Runtime.hx index 2acec64ba23..a5b2855dcf0 100644 --- a/std/cs/internal/Runtime.hx +++ b/std/cs/internal/Runtime.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.internal; + import cs.Lib; import cs.Lib.*; import cs.NativeArray; @@ -34,10 +36,9 @@ import cs.system.Type; import cs.system.Object; /** - This class is meant for internal compiler use only. It provides the Haxe runtime - compatibility to the host language. + This class is meant for internal compiler use only. It provides the Haxe runtime + compatibility to the host language. **/ - @:nativeGen @:native('haxe.lang.Runtime') @:access(String) @@ -69,41 +70,34 @@ import cs.system.Object; return obj.__hx_invokeField(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, args); } ') -@:keep class Runtime -{ +@:keep class Runtime { @:readOnly public static var undefined(default, never):Dynamic = new cs.system.Object(); - public static function closure(obj:Dynamic, hash:Int, field:String):Dynamic - { + public static function closure(obj:Dynamic, hash:Int, field:String):Dynamic { return new cs.internal.Function.Closure(obj, field, hash); } - public static function eq(v1:Dynamic, v2:Dynamic):Bool - { + public static function eq(v1:Dynamic, v2:Dynamic):Bool { if (Object.ReferenceEquals(v1, v2)) return true; - if (Object.ReferenceEquals(v1,null) || Object.ReferenceEquals(v2,null)) + if (Object.ReferenceEquals(v1, null) || Object.ReferenceEquals(v2, null)) return false; var v1c = Lib.as(v1, IConvertible); - if (v1c != null) - { + if (v1c != null) { var v2c = Lib.as(v2, IConvertible); - if (v2c == null) - { + if (v2c == null) { return false; } - var t1 = v1c.GetTypeCode(), - t2 = v2c.GetTypeCode(); + var t1 = v1c.GetTypeCode(), t2 = v2c.GetTypeCode(); if (t1 == t2) - return Object._Equals(v1c,v2c); + return Object._Equals(v1c, v2c); if (t1 == cs.system.TypeCode.String || t2 == cs.system.TypeCode.String) return false; - switch [t1,t2] - { + switch [t1, t2] { case [Decimal, _] | [_, Decimal]: return v1c.ToDecimal(null) == v2c.ToDecimal(null); case [Int64, _] | [_, Int64]: @@ -118,61 +112,53 @@ import cs.system.Object; } var v1v = Lib.as(v1, cs.system.ValueType); - if (v1v != null) - { + if (v1v != null) { return v1.Equals(v2); -#if !erase_generics - } else { + #if !erase_generics + } + else { var v1t = Lib.as(v1, Type); - if (v1t != null) - { + if (v1t != null) { var v2t = Lib.as(v2, Type); if (v2t != null) return typeEq(v1t, v2t); return false; } -#end + #end } return false; } - public static function refEq(v1: { }, v2: { } ):Bool - { -#if !erase_generics + public static function refEq(v1:{}, v2:{}):Bool { + #if !erase_generics if (Std.is(v1, Type)) - return typeEq(Lib.as(v1,Type), Lib.as(v2,Type)); -#end - return Object.ReferenceEquals(v1,v2); + return typeEq(Lib.as(v1, Type), Lib.as(v2, Type)); + #end + return Object.ReferenceEquals(v1, v2); } - public static function toDouble(obj:Dynamic):Float - { - return (obj == null) ? .0 : Std.is(obj,Float) ? cast obj : Lib.as(obj,IConvertible).ToDouble(null); + public static function toDouble(obj:Dynamic):Float { + return (obj == null) ? .0 : Std.is(obj, Float) ? cast obj : Lib.as(obj, IConvertible).ToDouble(null); } - public static function toInt(obj:Dynamic):Int - { - return (obj == null) ? 0 : Std.is(obj,Int) ? cast obj : Lib.as(obj,IConvertible).ToInt32(null); + public static function toInt(obj:Dynamic):Int { + return (obj == null) ? 0 : Std.is(obj, Int) ? cast obj : Lib.as(obj, IConvertible).ToInt32(null); } -#if erase_generics - public static function toLong(obj:Dynamic):Int64 - { - return (obj == null) ? 0 : Std.is(obj,Int64) ? cast obj : Lib.as(obj,IConvertible).ToInt64(null); + #if erase_generics + public static function toLong(obj:Dynamic):Int64 { + return (obj == null) ? 0 : Std.is(obj, Int64) ? cast obj : Lib.as(obj, IConvertible).ToInt64(null); } -#end + #end - public static function isInt(obj:Dynamic):Bool - { + public static function isInt(obj:Dynamic):Bool { var cv1 = Lib.as(obj, IConvertible); - if (cv1 != null) - { - switch (cv1.GetTypeCode()) - { + if (cv1 != null) { + switch (cv1.GetTypeCode()) { case Double: var d:Float = cast obj; - return d >= cs.system.Int32.MinValue && d <= cs.system.Int32.MaxValue && d == ( cast(d,Int) ); + return d >= cs.system.Int32.MinValue && d <= cs.system.Int32.MaxValue && d == (cast(d, Int)); case UInt32, Int32: return true; default: @@ -182,53 +168,47 @@ import cs.system.Object; return false; } - public static function isUInt(obj:Dynamic):Bool - { + public static function isUInt(obj:Dynamic):Bool { var cv1 = Lib.as(obj, IConvertible); - if (cv1 != null) - { - switch (cv1.GetTypeCode()) - { + if (cv1 != null) { + switch (cv1.GetTypeCode()) { case Double: var d:Float = cast obj; - return d >= cs.system.UInt32.MinValue && d <= cs.system.UInt32.MaxValue && d == ( cast(d,UInt) ); + return d >= cs.system.UInt32.MinValue && d <= cs.system.UInt32.MaxValue && d == (cast(d, UInt)); case UInt32: return true; default: return false; } - } return false; } - public static function compare(v1:Dynamic, v2:Dynamic):Int - { - if (Object.ReferenceEquals(v1,v2)) return 0; - if (Object.ReferenceEquals(v1,null)) return -1; - if (Object.ReferenceEquals(v2,null)) return 1; + public static function compare(v1:Dynamic, v2:Dynamic):Int { + if (Object.ReferenceEquals(v1, v2)) + return 0; + if (Object.ReferenceEquals(v1, null)) + return -1; + if (Object.ReferenceEquals(v2, null)) + return 1; var cv1 = Lib.as(v1, IConvertible); - if (cv1 != null) - { + if (cv1 != null) { var cv2 = Lib.as(v2, IConvertible); - if (cv2 == null) - { + if (cv2 == null) { throw new cs.system.ArgumentException("Cannot compare " + getNativeType(v1).ToString() + " and " + getNativeType(v2).ToString()); } - switch(cv1.GetTypeCode()) - { + switch (cv1.GetTypeCode()) { case cs.system.TypeCode.String: if (cv2.GetTypeCode() != cs.system.TypeCode.String) throw new cs.system.ArgumentException("Cannot compare " + getNativeType(v1).ToString() + " and " + getNativeType(v2).ToString()); - var s1 = Lib.as(v1,String); - var s2 = Lib.as(v2,String); - return String.Compare(s1,s2, cs.system.StringComparison.Ordinal); + var s1 = Lib.as(v1, String); + var s2 = Lib.as(v2, String); + return String.Compare(s1, s2, cs.system.StringComparison.Ordinal); case cs.system.TypeCode.Double: - var d1:Float = cast v1, - d2:Float = cv2.ToDouble(null); + var d1:Float = cast v1, d2:Float = cv2.ToDouble(null); return (d1 < d2) ? -1 : (d1 > d2) ? 1 : 0; default: var d1d = cv1.ToDouble(null); @@ -240,32 +220,30 @@ import cs.system.Object; var c1 = Lib.as(v1, IComparable); var c2 = Lib.as(v2, IComparable); - if (c1 == null || c2 == null) - { + if (c1 == null || c2 == null) { throw new cs.system.ArgumentException("Cannot compare " + getNativeType(v1).ToString() + " and " + getNativeType(v2).ToString()); } return c1.CompareTo(c2); } - public static function plus(v1:Dynamic, v2:Dynamic):Dynamic - { - if (Std.is(v1,String) || Std.is(v2,String)) + public static function plus(v1:Dynamic, v2:Dynamic):Dynamic { + if (Std.is(v1, String) || Std.is(v2, String)) return Std.string(v1) + Std.string(v2); - if (v1 == null) - { - if (v2 == null) return null; + if (v1 == null) { + if (v2 == null) + return null; v1 = 0; - } else if (v2 == null) v2 = 0; + } else if (v2 == null) + v2 = 0; var cv1 = Lib.as(v1, IConvertible); - if (cv1 != null) - { + if (cv1 != null) { var cv2 = Lib.as(v2, IConvertible); - if (cv2 == null) - { - throw new cs.system.ArgumentException("Cannot dynamically add " + cs.Lib.getNativeType(v1).ToString() + " and " + cs.Lib.getNativeType(v2).ToString()); + if (cv2 == null) { + throw new cs.system.ArgumentException("Cannot dynamically add " + cs.Lib.getNativeType(v1).ToString() + " and " + + cs.Lib.getNativeType(v2).ToString()); } return cv1.ToDouble(null) + cv2.ToDouble(null); } @@ -273,8 +251,7 @@ import cs.system.Object; throw new cs.system.ArgumentException("Cannot dynamically add " + v1 + " and " + v2); } - public static function slowGetField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic - { + public static function slowGetField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic { if (obj == null) if (throwErrors) throw new cs.system.NullReferenceException("Cannot access field \'" + field + "\' of null."); @@ -282,52 +259,39 @@ import cs.system.Object; return null; var t = Lib.as(obj, cs.system.Type); - var bf = - if (t == null) - { - var s = Lib.as(obj, String); - if (s != null) - return cs.internal.StringExt.StringRefl.handleGetField(s, field, throwErrors); - t = obj.GetType(); - new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy; - } else { - if (t == Lib.toNativeType(String) && field == "fromCharCode") - return new cs.internal.Function.Closure(StringExt, field, 0); + var bf = if (t == null) { + var s = Lib.as(obj, String); + if (s != null) + return cs.internal.StringExt.StringRefl.handleGetField(s, field, throwErrors); + t = obj.GetType(); + new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy; + } else { + if (t == Lib.toNativeType(String) && field == "fromCharCode") + return new cs.internal.Function.Closure(StringExt, field, 0); - obj = null; - new cs.Flags(BindingFlags.Static) | BindingFlags.Public; - } + obj = null; + new cs.Flags(BindingFlags.Static) | BindingFlags.Public; + } var f = t.GetField(field, bf); - if (f != null) - { + if (f != null) { return unbox(f.GetValue(obj)); - } - else - { + } else { var prop = t.GetProperty(field, bf); - if (prop == null) - { + if (prop == null) { var m = t.GetMember(field, bf); if (m.length == 0 && (field == "__get" || field == "__set")) m = t.GetMember(field == "__get" ? "get_Item" : "set_Item", bf); - if (m.Length > 0) - { + if (m.Length > 0) { return new cs.internal.Function.Closure(obj != null ? obj : t, field, 0); - } - else - { + } else { // COM object handling - if (t.IsCOMObject) - { - try - { + if (t.IsCOMObject) { + try { return t.InvokeMember(field, BindingFlags.GetProperty, null, obj, new cs.NativeArray(0)); - } - catch (e:cs.system.Exception) - { - //Closures of COM objects not supported currently + } catch (e:cs.system.Exception) { + // Closures of COM objects not supported currently } } @@ -341,85 +305,72 @@ import cs.system.Object; } } - public static function slowHasField(obj:Dynamic, field:String):Bool - { - if (obj == null) return false; + public static function slowHasField(obj:Dynamic, field:String):Bool { + if (obj == null) + return false; var t = Lib.as(obj, cs.system.Type); - var bf = - if (t == null) { - var s = Lib.as(obj, String); - if (s != null) - return cs.internal.StringExt.StringRefl.handleGetField(s, field, false) != null; - t = obj.GetType(); - new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy; - } else { - if (t == Lib.toNativeType(String)) - return field == "fromCharCode"; - obj = null; - new cs.Flags(BindingFlags.Static) | BindingFlags.Public; - } + var bf = if (t == null) { + var s = Lib.as(obj, String); + if (s != null) + return cs.internal.StringExt.StringRefl.handleGetField(s, field, false) != null; + t = obj.GetType(); + new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy; + } else { + if (t == Lib.toNativeType(String)) + return field == "fromCharCode"; + obj = null; + new cs.Flags(BindingFlags.Static) | BindingFlags.Public; + } var mi = t.GetMember(field, bf); return mi != null && mi.length > 0; } - public static function slowSetField(obj:Dynamic, field:String, value:Dynamic):Dynamic - { + public static function slowSetField(obj:Dynamic, field:String, value:Dynamic):Dynamic { if (obj == null) throw new cs.system.NullReferenceException("Cannot access field \'" + field + "\' of null."); var t = Lib.as(obj, cs.system.Type); - var bf = - if (t == null) - { - t = obj.GetType(); - new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy; - } else { - obj = null; - new cs.Flags(BindingFlags.Static) | BindingFlags.Public; - } + var bf = if (t == null) { + t = obj.GetType(); + new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy; + } else { + obj = null; + new cs.Flags(BindingFlags.Static) | BindingFlags.Public; + } var f = t.GetField(field, bf); - if (f != null) - { - if (f.FieldType.ToString().StartsWith("haxe.lang.Null")) - { + if (f != null) { + if (f.FieldType.ToString().StartsWith("haxe.lang.Null")) { value = mkNullable(value, f.FieldType); } - if (value != null && Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value)) && !Object.ReferenceEquals(t, f.FieldType)) - { + if (value != null + && Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value)) + && !Object.ReferenceEquals(t, f.FieldType)) { var ic = Lib.as(value, IConvertible); value = ic.ToType(f.FieldType, null); } f.SetValue(obj, value); return value; - } - else - { + } else { var prop = t.GetProperty(field, bf); - if (prop == null) - { + if (prop == null) { // COM object handling - if (t.IsCOMObject) - { - try - { + if (t.IsCOMObject) { + try { return t.InvokeMember(field, BindingFlags.SetProperty, null, obj, cs.NativeArray.make(value)); - } - catch (e:cs.system.Exception) - { - //Closures of COM objects not supported currently + } catch (e:cs.system.Exception) { + // Closures of COM objects not supported currently } } throw "Field \'" + field + "\' not found for writing from Class " + t; } - if (prop.PropertyType.ToString().StartsWith("haxe.lang.Null")) - { + if (prop.PropertyType.ToString().StartsWith("haxe.lang.Null")) { value = mkNullable(value, prop.PropertyType); } - if (Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value)) && !Object.ReferenceEquals(t, f.FieldType)) - { + if (Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value)) + && !Object.ReferenceEquals(t, f.FieldType)) { var ic = Lib.as(value, IConvertible); value = ic.ToType(f.FieldType, null); } @@ -429,16 +380,15 @@ import cs.system.Object; } } - public static function callMethod(obj:Dynamic, methods:NativeArray, methodLength:Int, args:cs.NativeArray):Dynamic - { - if (methodLength == 0) throw "No available methods"; + public static function callMethod(obj:Dynamic, methods:NativeArray, methodLength:Int, args:cs.NativeArray):Dynamic { + if (methodLength == 0) + throw "No available methods"; var length = args.length; var oargs:NativeArray = new NativeArray(length); var ts:NativeArray = new NativeArray(length); var rates:NativeArray = new NativeArray(methods.Length); - for (i in 0...length) - { + for (i in 0...length) { oargs[i] = args[i]; if (args[i] != null) ts[i] = Lib.getNativeType(args[i]); @@ -446,37 +396,33 @@ import cs.system.Object; var last = 0; - //first filter by number of parameters and if it is assignable - if (methodLength > 1) - { - for (i in 0...methodLength) - { + // first filter by number of parameters and if it is assignable + if (methodLength > 1) { + for (i in 0...methodLength) { var params = methods[i].GetParameters(); if (params.Length != length) { continue; } else { var fits = true, crate = 0; - for (i in 0...params.Length) - { + for (i in 0...params.Length) { var param = params[i].ParameterType; var strParam = param + ""; - if (param.IsAssignableFrom(ts[i]) || (ts[i] == null && !param.IsValueType)) - { - //if it is directly assignable, we'll give it top rate + if (param.IsAssignableFrom(ts[i]) || (ts[i] == null && !param.IsValueType)) { + // if it is directly assignable, we'll give it top rate continue; - } else if (untyped strParam.StartsWith("haxe.lang.Null") || ( (oargs[i] == null || Std.is(oargs[i], IConvertible) ) && cast(untyped __typeof__(IConvertible), Type).IsAssignableFrom(param) )) - { - //if it needs conversion, give a penalty. TODO rate penalty + } else if (untyped strParam.StartsWith("haxe.lang.Null") + || ((oargs[i] == null || Std.is(oargs[i], IConvertible)) + && cast(untyped __typeof__(IConvertible), Type).IsAssignableFrom(param))) { + // if it needs conversion, give a penalty. TODO rate penalty crate++; continue; - } else if (!param.ContainsGenericParameters) { //generics don't appear as assignable, but may be in the end. no rate there. + } else if (!param.ContainsGenericParameters) { // generics don't appear as assignable, but may be in the end. no rate there. fits = false; break; } } - if (fits) - { + if (fits) { rates[last] = crate; methods[last++] = methods[i]; } @@ -488,20 +434,18 @@ import cs.system.Object; methodLength = 0; } - //At this time, we should be left with only one method. - //Of course, realistically, we can be left with plenty of methods, if there are lots of variants with IConvertible - //But at this time we still aren't rating the best methods - //FIXME rate best methods + // At this time, we should be left with only one method. + // Of course, realistically, we can be left with plenty of methods, if there are lots of variants with IConvertible + // But at this time we still aren't rating the best methods + // FIXME rate best methods if (methodLength == 0) throw "Invalid calling parameters for method " + methods[0].Name; var best = cs.system.Double.PositiveInfinity; var bestMethod = 0; - for(i in 0...methodLength) - { - if (rates[i] < best) - { + for (i in 0...methodLength) { + if (rates[i] < best) { bestMethod = i; best = rates[i]; } @@ -509,13 +453,10 @@ import cs.system.Object; methods[0] = methods[bestMethod]; var params = methods[0].GetParameters(); - for (i in 0...params.Length) - { + for (i in 0...params.Length) { var param = params[i].ParameterType; - var strParam = param + "", - arg = oargs[i]; - if (StringTools.startsWith(strParam, "haxe.lang.Null")) - { + var strParam = param + "", arg = oargs[i]; + if (StringTools.startsWith(strParam, "haxe.lang.Null")) { oargs[i] = mkNullable(arg, param); } else if (cast(untyped __typeof__(IConvertible), Type).IsAssignableFrom(param)) { if (arg == null) { @@ -527,12 +468,10 @@ import cs.system.Object; } } - if (methods[0].ContainsGenericParameters && Std.is(methods[0], cs.system.reflection.MethodInfo)) - { + if (methods[0].ContainsGenericParameters && Std.is(methods[0], cs.system.reflection.MethodInfo)) { var m:MethodInfo = cast methods[0]; var tgs = m.GetGenericArguments(); - for (i in 0...tgs.Length) - { + for (i in 0...tgs.Length) { tgs[i] = untyped __typeof__(Dynamic); } m = m.MakeGenericMethod(tgs); @@ -541,8 +480,7 @@ import cs.system.Object; } var m = methods[0]; - if (obj == null && Std.is(m, cs.system.reflection.ConstructorInfo)) - { + if (obj == null && Std.is(m, cs.system.reflection.ConstructorInfo)) { var ret = cast(m, cs.system.reflection.ConstructorInfo).Invoke(oargs); return unbox(ret); } @@ -551,46 +489,40 @@ import cs.system.Object; return unbox(ret); } - public static function unbox(dyn:Dynamic):Dynamic - { - if (dyn != null && untyped (Lib.getNativeType(dyn) + "").StartsWith("haxe.lang.Null")) - { + public static function unbox(dyn:Dynamic):Dynamic { + if (dyn != null && untyped (Lib.getNativeType(dyn) + "").StartsWith("haxe.lang.Null")) { return dyn.toDynamic(); } else { return dyn; } } -#if !erase_generics + #if !erase_generics @:functionCode(' if (nullableType.ContainsGenericParameters) return haxe.lang.Null.ofDynamic(obj); return nullableType.GetMethod("_ofDynamic").Invoke(null, new object[] { obj }); ') - public static function mkNullable(obj:Dynamic, nullableType:Type):Dynamic - { + public static function mkNullable(obj:Dynamic, nullableType:Type):Dynamic { return null; } -#else - public static function mkNullable(obj:Dynamic, nullable:Type):Dynamic - { - return obj; //do nothing + #else + public static function mkNullable(obj:Dynamic, nullable:Type):Dynamic { + return obj; // do nothing } -#end + #end - public static function slowCallField(obj:Dynamic, field:String, args:cs.NativeArray):Dynamic - { - if (field == "toString" && (args == null || args.length == 0)) - { + public static function slowCallField(obj:Dynamic, field:String, args:cs.NativeArray):Dynamic { + if (field == "toString" && (args == null || args.length == 0)) { return obj.ToString(); } - if (args == null) args = new cs.NativeArray(0); + if (args == null) + args = new cs.NativeArray(0); var bf:BindingFlags; - var t = Lib.as(obj,cs.system.Type); - if (t == null) - { - var s = Lib.as(obj,String); + var t = Lib.as(obj, cs.system.Type); + if (t == null) { + var s = Lib.as(obj, String); if (s != null) return cs.internal.StringExt.StringRefl.handleCallField(untyped s, untyped field, args); t = untyped obj.GetType(); @@ -604,21 +536,17 @@ import cs.system.Object; var mis:NativeArray = untyped t.GetMethods(bf); var last = 0; - for (i in 0...mis.Length) - { + for (i in 0...mis.Length) { var name = mis[i].Name; if (name == field) mis[last++] = mis[i]; } - if (last == 0 && (field == "__get" || field == "__set")) - { + if (last == 0 && (field == "__get" || field == "__set")) { field = field == "__get" ? "get_Item" : "set_Item"; - for (i in 0...mis.Length) - { + for (i in 0...mis.Length) { var name = mis[i].Name; - if (name == field) - { + if (name == field) { mis[last++] = mis[i]; } } @@ -627,24 +555,21 @@ import cs.system.Object; if (last == 0 && t.IsCOMObject) return t.InvokeMember(field, BindingFlags.InvokeMethod, null, obj, args); - if (last == 0) - { + if (last == 0) { throw 'Method "$field" not found on type $t'; } return Runtime.callMethod(obj, mis, last, args); } - public static function callField(obj:Dynamic, field:String, fieldHash:Int, args:cs.NativeArray):Dynamic - { + public static function callField(obj:Dynamic, field:String, fieldHash:Int, args:cs.NativeArray):Dynamic { var hxObj = Lib.as(obj, HxObject); if (hxObj != null) return untyped hxObj.__hx_invokeField(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, args); return slowCallField(obj, field, args); } - public static function getField(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Dynamic - { + public static function getField(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Dynamic { var hxObj = Lib.as(obj, HxObject); if (hxObj != null) return untyped hxObj.__hx_getField(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, throwErrors, false, false); @@ -652,8 +577,7 @@ import cs.system.Object; return slowGetField(obj, field, throwErrors); } - public static function getField_f(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Float - { + public static function getField_f(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Float { var hxObj = Lib.as(obj, HxObject); if (hxObj != null) return untyped hxObj.__hx_getField_f(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, throwErrors, false); @@ -661,8 +585,7 @@ import cs.system.Object; return toDouble(slowGetField(obj, field, throwErrors)); } - public static function setField(obj:Dynamic, field:String, fieldHash:Int, value:Dynamic):Dynamic - { + public static function setField(obj:Dynamic, field:String, fieldHash:Int, value:Dynamic):Dynamic { var hxObj = Lib.as(obj, HxObject); if (hxObj != null) return untyped hxObj.__hx_setField(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, value, false); @@ -670,8 +593,7 @@ import cs.system.Object; return slowSetField(obj, field, value); } - public static function setField_f(obj:Dynamic, field:String, fieldHash:Int, value:Float):Float - { + public static function setField_f(obj:Dynamic, field:String, fieldHash:Int, value:Float):Float { var hxObj = Lib.as(obj, HxObject); if (hxObj != null) return untyped hxObj.__hx_setField_f(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, value, false); @@ -679,12 +601,11 @@ import cs.system.Object; return toDouble(slowSetField(obj, field, value)); } - public static function toString(obj:Dynamic):String - { + public static function toString(obj:Dynamic):String { if (obj == null) return null; if (Std.is(obj, Bool)) - if(obj) + if (obj) return "true"; else return "false"; @@ -692,20 +613,16 @@ import cs.system.Object; return untyped obj.ToString(); } -#if erase_generics + #if erase_generics inline -#end - public static function typeEq(t1:Type, t2:Type):Bool - { + #end + public static function typeEq(t1:Type, t2:Type):Bool { if (t1 == null || t2 == null) return t1 == t2; -#if !erase_generics - var t1i = t1.IsInterface, - t2i = t2.IsInterface; - if (t1i != t2i) - { - if (t1i) - { + #if !erase_generics + var t1i = t1.IsInterface, t2i = t2.IsInterface; + if (t1i != t2i) { + if (t1i) { var g = getGenericAttr(t1); if (g != null) t1 = g.generic; @@ -715,25 +632,24 @@ import cs.system.Object; t2 = g.generic; } } - -#end - if (t1.GetGenericArguments().Length > 0) t1 = t1.GetGenericTypeDefinition(); - if (t2.GetGenericArguments().Length > 0) t2 = t2.GetGenericTypeDefinition(); - return Object.ReferenceEquals(t1,t2); + #end + if (t1.GetGenericArguments().Length > 0) + t1 = t1.GetGenericTypeDefinition(); + if (t2.GetGenericArguments().Length > 0) + t2 = t2.GetGenericTypeDefinition(); + return Object.ReferenceEquals(t1, t2); } - -#if !erase_generics - public static function getGenericAttr(t:cs.system.Type):cs.internal.HxObject.GenericInterface - { + #if !erase_generics + public static function getGenericAttr(t:cs.system.Type):cs.internal.HxObject.GenericInterface { for (attr in t.GetCustomAttributes(true)) - if (Std.is(attr,cs.internal.HxObject.GenericInterface)) + if (Std.is(attr, cs.internal.HxObject.GenericInterface)) return cast attr; return null; } -#end + #end -#if !erase_generics + #if !erase_generics @:functionCode(' if (obj is To) return (To) obj; @@ -750,43 +666,38 @@ import cs.system.Object; else return (To) obj; ') - public static function genericCast(obj:Dynamic):To - { + public static function genericCast(obj:Dynamic):To { return null; } -#end + #end @:functionCode(' return (s1 == null ? "null" : s1) + (s2 == null ? "null" : s2); ') - public static function concat(s1:String, s2:String):String - { + public static function concat(s1:String, s2:String):String { return null; } - public static function toBool(dyn:Dynamic):Bool - { + public static function toBool(dyn:Dynamic):Bool { return if (dyn == null) false else untyped __cs__("(bool){0}", dyn); } - - //TODO: change from genericCast to getConverter, so we don't need to handle extra boxing associated with it + // TODO: change from genericCast to getConverter, so we don't need to handle extra boxing associated with it /*@:functionCode(' - if (typeof(To).TypeHandle == typeof(double).TypeHandle) - return (System.Converter) new System.Converter(toDouble); - else if (typeof(To).TypeHandle == typeof(double).TypeHandle) - return (System.Converter) new System.Converter(toDouble); - else - return (System.Converter) delegate(object obj) { return (To) obj; }; - ') - public static function getConverter():cs.system.Converter - { - return null; + if (typeof(To).TypeHandle == typeof(double).TypeHandle) + return (System.Converter) new System.Converter(toDouble); + else if (typeof(To).TypeHandle == typeof(double).TypeHandle) + return (System.Converter) new System.Converter(toDouble); + else + return (System.Converter) delegate(object obj) { return (To) obj; }; + ') + public static function getConverter():cs.system.Converter + { + return null; }*/ } @:nativeGen -@:keep @:native("haxe.lang.EmptyObject") enum EmptyObject -{ +@:keep @:native("haxe.lang.EmptyObject") enum EmptyObject { EMPTY; } diff --git a/std/cs/internal/StringExt.hx b/std/cs/internal/StringExt.hx index e486079d04b..f742198fb8d 100644 --- a/std/cs/internal/StringExt.hx +++ b/std/cs/internal/StringExt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,57 +19,59 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.internal; + import cs.internal.Function; + private typedef NativeString = cs.system.String; -@:keep @:nativeGen @:native("haxe.lang.StringExt") class StringExt -{ - @:readOnly static var empty(default,never) = new NativeString(cast 0,0); +@:keep @:nativeGen @:native("haxe.lang.StringExt") class StringExt { + @:readOnly static var empty(default, never) = new NativeString(cast 0, 0); - public static function charAt(me:NativeString, index:Int):NativeString - { - if (cast(index,UInt) >= me.Length) + public static function charAt(me:NativeString, index:Int):NativeString { + if (cast(index, UInt) >= me.Length) return empty; else return new NativeString(me[index], 1); } - public static function charCodeAt(me:NativeString, index:Int):Null - { - if (cast(index,UInt) >= me.Length) + public static function charCodeAt(me:NativeString, index:Int):Null { + if (cast(index, UInt) >= me.Length) return null; else return cast(me[index], Int); } - public static function indexOf(me:NativeString, str:String, ?startIndex:Int):Int - { + public static function indexOf(me:NativeString, str:String, ?startIndex:Int):Int { var sIndex:Int = startIndex != null ? startIndex : 0; if (sIndex >= me.Length) return -1; return @:privateAccess me.IndexOf(str, sIndex, cs.system.StringComparison.Ordinal); } - public static function lastIndexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int - { + public static function lastIndexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int { var sIndex:Int = startIndex == null ? me.Length - 1 : startIndex; if (sIndex >= me.Length) sIndex = me.Length - 1; else if (sIndex < 0) return -1; - //TestBaseTypes.hx@133 fix - if (startIndex != null) - { + // TestBaseTypes.hx@133 fix + if (startIndex != null) { + // if the number of letters between start index and the length of the string + // is less than the length of a searched substring - shift start index to the + // left by the difference to avoid OOB access later and save some work + var d = me.Length - sIndex - str.Length; + if (d < 0) { + sIndex += d; + } + var i = sIndex + 1; - while (i --> 0) - { + while (i-- > 0) { var found = true; - for (j in 0...str.Length) - { - if(me[i + j] != str[j]) - { + for (j in 0...str.Length) { + if (me[i + j] != str[j]) { found = false; break; } @@ -86,15 +88,13 @@ private typedef NativeString = cs.system.String; return -1; } - public static function split(me:NativeString, delimiter:NativeString):Array - { + public static function split(me:NativeString, delimiter:NativeString):Array { var native:NativeArray; - if (delimiter.Length == 0) - { + if (delimiter.Length == 0) { var len = me.Length; native = new NativeArray(len); for (i in 0...len) - native[i] = untyped new NativeString(me[i],1); + native[i] = untyped new NativeString(me[i], 1); } else { var str = new NativeArray(1); str[0] = cast delimiter; @@ -105,42 +105,39 @@ private typedef NativeString = cs.system.String; return cs.Lib.array(native); } - public static function substr(me:NativeString, pos:Int, ?len:Int):String - { + public static function substr(me:NativeString, pos:Int, ?len:Int):String { var meLen = me.Length; var targetLen = meLen; - if (len != null) - { + if (len != null) { targetLen = len; if (targetLen == 0 || (pos != 0 && targetLen < 0)) return ""; } - if (pos < 0) - { + if (pos < 0) { pos = meLen + pos; - if (pos < 0) pos = 0; + if (pos < 0) + pos = 0; } else if (targetLen < 0) { targetLen = meLen + targetLen - pos; } - if (pos + targetLen > meLen) - { + if (pos + targetLen > meLen) { targetLen = meLen - pos; } - if (pos < 0 || targetLen <= 0) return ""; + if (pos < 0 || targetLen <= 0) + return ""; return me.Substring(pos, targetLen); } - public static function substring(me:NativeString, startIndex:Int, ?endIndex:Int):String - { + public static function substring(me:NativeString, startIndex:Int, ?endIndex:Int):String { var len = me.Length; var endIdx:Int; if (endIndex == null) endIdx = len; - else if ( (endIdx = endIndex) < 0 ) + else if ((endIdx = endIndex) < 0) endIdx = 0; else if (endIdx > len) endIdx = len; @@ -150,8 +147,7 @@ private typedef NativeString = cs.system.String; else if (startIndex > len) startIndex = len; - if (startIndex > endIdx) - { + if (startIndex > endIdx) { var tmp = startIndex; startIndex = endIdx; endIdx = tmp; @@ -160,41 +156,37 @@ private typedef NativeString = cs.system.String; return me.Substring(startIndex, endIdx - startIndex); } - public static function toString(me:NativeString):NativeString - { + public static function toString(me:NativeString):NativeString { return me; } - public static function toLowerCase(me:NativeString):String - { + public static function toLowerCase(me:NativeString):String { return me.ToLowerInvariant(); } - public static function toUpperCase(me:NativeString):String - { + public static function toUpperCase(me:NativeString):String { return me.ToUpperInvariant(); } - public static function toNativeString(me:NativeString):NativeString - { + public static function toNativeString(me:NativeString):NativeString { return me; } - public static function fromCharCode(code:Int):NativeString - { - return new NativeString( cast(code,cs.StdTypes.Char16), 1 ); + public static function fromCharCode(code:Int):String { + return cs.system.Char.ConvertFromUtf32(code); + // return new NativeString( cast(code,cs.StdTypes.Char16), 1 ); } } -@:keep @:nativeGen @:native('haxe.lang.StringRefl') class StringRefl -{ - public static var fields = ["length", "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring"]; +@:keep @:nativeGen @:native('haxe.lang.StringRefl') class StringRefl { + public static var fields = [ + "length", "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring" + ]; - public static function handleGetField(str:String, f:String, throwErrors:Bool):Dynamic - { - switch(f) - { - case "length": return str.length; + public static function handleGetField(str:String, f:String, throwErrors:Bool):Dynamic { + switch (f) { + case "length": + return str.length; case "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring": return new Closure(str, f, 0); default: @@ -205,8 +197,7 @@ private typedef NativeString = cs.system.String; } } - public static function handleCallField(str:NativeString, f:String, args:cs.NativeArray):Dynamic - { + public static function handleCallField(str:NativeString, f:String, args:cs.NativeArray):Dynamic { var _args:cs.NativeArray; if (args == null) { _args = cs.NativeArray.make(str); diff --git a/std/cs/io/NativeInput.hx b/std/cs/io/NativeInput.hx index 782e58d65df..c0e6eae7eae 100644 --- a/std/cs/io/NativeInput.hx +++ b/std/cs/io/NativeInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,29 +19,29 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.io; + import haxe.Int64; import haxe.io.Bytes; import haxe.io.Eof; import haxe.io.Error; import haxe.io.Input; -class NativeInput extends Input -{ - public var canSeek(get,never):Bool; +class NativeInput extends Input { + public var canSeek(get, never):Bool; var stream:cs.system.io.Stream; var _eof:Bool; - public function new(stream) - { + public function new(stream) { this.stream = stream; this._eof = false; - if (!stream.CanRead) throw "Write-only stream"; + if (!stream.CanRead) + throw "Write-only stream"; } - override public function readByte():Int - { + override public function readByte():Int { var ret = stream.ReadByte(); if (ret == -1) { _eof = true; @@ -50,9 +50,8 @@ class NativeInput extends Input return ret; } - override public function readBytes(s:Bytes, pos:Int, len:Int):Int - { - if( pos < 0 || len < 0 || pos + len > s.length ) + override public function readBytes(s:Bytes, pos:Int, len:Int):Int { + if (pos < 0 || len < 0 || pos + len > s.length) throw Error.OutsideBounds; var ret = stream.Read(s.getData(), pos, len); if (ret == 0) { @@ -62,21 +61,17 @@ class NativeInput extends Input return ret; } - override public function close():Void - { + override public function close():Void { stream.Close(); } - private inline function get_canSeek():Bool - { + private inline function get_canSeek():Bool { return stream.CanSeek; } - public function seek( p : Int, pos : sys.io.FileSeek ) : Void - { + public function seek(p:Int, pos:sys.io.FileSeek):Void { _eof = false; - var pos = switch(pos) - { + var pos = switch (pos) { case SeekBegin: cs.system.io.SeekOrigin.Begin; case SeekCur: cs.system.io.SeekOrigin.Current; case SeekEnd: cs.system.io.SeekOrigin.End; @@ -85,13 +80,11 @@ class NativeInput extends Input stream.Seek(cast(p, Int64), pos); } - public function tell() : Int - { + public function tell():Int { return cast(stream.Position, Int); } - public inline function eof() : Bool - { + public inline function eof():Bool { return _eof; } -} \ No newline at end of file +} diff --git a/std/cs/io/NativeOutput.hx b/std/cs/io/NativeOutput.hx index a78dd707ad3..4221e02ecff 100644 --- a/std/cs/io/NativeOutput.hx +++ b/std/cs/io/NativeOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,62 +19,56 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.io; + import haxe.Int64; import haxe.io.Bytes; import haxe.io.Output; -class NativeOutput extends Output -{ - var canSeek(get,never):Bool; +class NativeOutput extends Output { + var canSeek(get, never):Bool; var stream:cs.system.io.Stream; - public function new(stream) - { + + public function new(stream) { this.stream = stream; - if (!stream.CanWrite) throw "Read-only stream"; + if (!stream.CanWrite) + throw "Read-only stream"; } - override public function writeByte(c:Int):Void - { + override public function writeByte(c:Int):Void { stream.WriteByte(cast c); } - override public function close():Void - { + override public function close():Void { stream.Close(); } - override public function flush():Void - { + override public function flush():Void { stream.Flush(); } - override public function prepare(nbytes:Int):Void - { - //TODO see if implementation is correct + override public function prepare(nbytes:Int):Void { + // TODO see if implementation is correct stream.SetLength(haxe.Int64.add(stream.Length, cast(nbytes, Int64))); } - private inline function get_canSeek():Bool - { + private inline function get_canSeek():Bool { return stream.CanSeek; } - public function seek( p : Int, pos : sys.io.FileSeek ) : Void - { - var p = switch(pos) - { + public function seek(p:Int, pos:sys.io.FileSeek):Void { + var pos = switch (pos) { case SeekBegin: cs.system.io.SeekOrigin.Begin; case SeekCur: cs.system.io.SeekOrigin.Current; case SeekEnd: cs.system.io.SeekOrigin.End; }; - stream.Seek(cast(p, Int64), p); + stream.Seek(cast(p, Int64), pos); } - public function tell() : Int - { + public function tell():Int { return cast(stream.Position, Int); } } diff --git a/std/cs/types/Char16.hx b/std/cs/types/Char16.hx index eb8fc1da76d..23060aecf55 100644 --- a/std/cs/types/Char16.hx +++ b/std/cs/types/Char16.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.types; typedef Char16 = cs.StdTypes.Char16; diff --git a/std/cs/types/Int16.hx b/std/cs/types/Int16.hx index 9a4fcd507b9..bb1ba494d05 100644 --- a/std/cs/types/Int16.hx +++ b/std/cs/types/Int16.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.types; typedef Int16 = cs.StdTypes.Int16; diff --git a/std/cs/types/Int64.hx b/std/cs/types/Int64.hx index d8d7b8d9140..5bd867a80aa 100644 --- a/std/cs/types/Int64.hx +++ b/std/cs/types/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.types; typedef Int64 = cs.StdTypes.Int64; - diff --git a/std/cs/types/Int8.hx b/std/cs/types/Int8.hx index 5120c71bd5b..d0309f1a8fb 100644 --- a/std/cs/types/Int8.hx +++ b/std/cs/types/Int8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.types; typedef Int8 = cs.StdTypes.Int8; diff --git a/std/cs/types/UInt16.hx b/std/cs/types/UInt16.hx index ef037e5243e..fc8de77c3c1 100644 --- a/std/cs/types/UInt16.hx +++ b/std/cs/types/UInt16.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.types; typedef UInt16 = cs.StdTypes.UInt16; diff --git a/std/cs/types/UInt64.hx b/std/cs/types/UInt64.hx index c8d864b271f..62f4b585e83 100644 --- a/std/cs/types/UInt64.hx +++ b/std/cs/types/UInt64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.types; typedef UInt64 = cs.StdTypes.UInt64; diff --git a/std/cs/types/UInt8.hx b/std/cs/types/UInt8.hx index befa2e1cc5c..e3c9961dc38 100644 --- a/std/cs/types/UInt8.hx +++ b/std/cs/types/UInt8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package cs.types; typedef UInt8 = cs.StdTypes.UInt8; diff --git a/std/eval/Vector.hx b/std/eval/Vector.hx index a1d9919c1f9..b5dc38666a6 100644 --- a/std/eval/Vector.hx +++ b/std/eval/Vector.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,10 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package eval; extern class Vector implements ArrayAccess { - public function new(size:Int) : Void; + public function new(size:Int):Void; public var length(default, null):Int; public function blit(srcPos:Int, dest:Vector, destPos:Int, len:Int):Void; public function toArray():Array; @@ -30,4 +31,4 @@ extern class Vector implements ArrayAccess { public function copy():Vector; public function join(sep:String):String; public function map(f:T->S):Vector; -} \ No newline at end of file +} diff --git a/std/eval/_std/EReg.hx b/std/eval/_std/EReg.hx index 9673f9b0475..d542debf9ad 100644 --- a/std/eval/_std/EReg.hx +++ b/std/eval/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,19 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - // We need this class so that calls to the empty standard implementations // don't get optimized away. - @:coreApi extern class EReg { - public function new( r : String, opt : String ):Void; - public function match( s : String ) : Bool; - public function matched( n : Int ) : String; - public function matchedLeft() : String; - public function matchedRight() : String; - public function matchedPos() : { pos : Int, len : Int }; - public function matchSub( s : String, pos : Int, len : Int = -1):Bool; - public function split( s : String ) : Array; - public function replace( s : String, by : String ) : String; - public function map( s : String, f : EReg -> String ) : String; - public static function escape( s : String ) : String; -} \ No newline at end of file + public function new(r:String, opt:String):Void; + public function match(s:String):Bool; + public function matched(n:Int):String; + public function matchedLeft():String; + public function matchedRight():String; + public function matchedPos():{pos:Int, len:Int}; + public function matchSub(s:String, pos:Int, len:Int = -1):Bool; + public function split(s:String):Array; + public function replace(s:String, by:String):String; + public function map(s:String, f:EReg->String):String; + public static function escape(s:String):String; +} diff --git a/std/eval/_std/StringBuf.hx b/std/eval/_std/StringBuf.hx index 3ab072a11e2..66f4f3999d3 100644 --- a/std/eval/_std/StringBuf.hx +++ b/std/eval/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - @:coreApi extern class StringBuf { - public var length(get,never) : Int; + public var length(get, never):Int; public function new():Void; - function get_length() : Int; - public function add( x : T ) : Void; - public function addChar( c : Int ) : Void; - public function addSub( s : String, pos : Int, ?len : Int) : Void; - public function toString() : String; -} \ No newline at end of file + private function get_length():Int; + public function add(x:T):Void; + public function addChar(c:Int):Void; + public function addSub(s:String, pos:Int, ?len:Int):Void; + public function toString():String; +} diff --git a/std/eval/_std/Sys.hx b/std/eval/_std/Sys.hx index 99f4a607795..30561e3dea5 100644 --- a/std/eval/_std/Sys.hx +++ b/std/eval/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,22 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ +import haxe.SysTools; + @:require(sys) @:coreApi class Sys { - @:extern static public function print(v:Dynamic):Void { } - @:extern static public function println(v:Dynamic):Void { } - @:extern static public function args():Array { return []; } - @:extern static public function getEnv(s:String):String { return ""; } - @:extern static public function putEnv(s:String, v:String):Void { } - @:extern static public function environment():Map { return null; } - @:extern static public function sleep(seconds:Float):Void { } - @:extern static public function setTimeLocale(loc:String):Bool { return false; } - @:extern static public function getCwd():String { return ""; } - @:extern static public function setCwd(s:String):Void { } - @:extern static public function systemName():String { return ""; } - - @:extern static function _command(cmd:String):Int { return 0; } + extern static public function print(v:Dynamic):Void; + + extern static public function println(v:Dynamic):Void; + + extern static public function args():Array; + + extern static public function getEnv(s:String):String; + + extern static public function putEnv(s:String, v:String):Void; + + extern static public function environment():Map; + + extern static public function sleep(seconds:Float):Void; + + extern static public function setTimeLocale(loc:String):Bool; + + extern static public function getCwd():String; + + extern static public function setCwd(s:String):Void; + + extern static public function systemName():String; + + extern static function _command(cmd:String):Int; static public function command(cmd:String, ?args:Array):Int { if (args == null) { @@ -45,24 +57,40 @@ class Sys { case "Windows": cmd = [ for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) - StringTools.quoteWinArg(a, true) + SysTools.quoteWinArg(a, true) ].join(" "); return _command(cmd); case _: - cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + cmd = [cmd].concat(args).map(SysTools.quoteUnixArg).join(" "); return _command(cmd); } } } - static public function executablePath():String { return programPath(); } - - @:extern static public function exit(code:Int):Void { } - @:extern static public function time():Float { return 0.; } - @:extern static public function cpuTime():Float { return 0.; } - @:extern static public function programPath():String { return ""; } - @:extern static public function getChar(echo:Bool):Int { return 0; } - @:extern static public function stdin():haxe.io.Input { return (null : sys.io.FileInput); } - @:extern static public function stdout():haxe.io.Output { return (null : sys.io.FileOutput); } - @:extern static public function stderr():haxe.io.Output { return (null : sys.io.FileOutput); } -} \ No newline at end of file + static public function executablePath():String { + return programPath(); + } + + extern static public function exit(code:Int):Void; + + extern static public function time():Float; + + extern static public function cpuTime():Float; + + extern static public function programPath():String; + + extern static public function getChar(echo:Bool):Int; + + extern static public function stdin():haxe.io.Input; + + extern static public function stdout():haxe.io.Output; + + extern static public function stderr():haxe.io.Output; + + static function __init__():Void { + // This nonsense causes the classes to be loaded. Otherwise they might not make + // it into the interpreter, and then stderr() et. al. don't work. + var _ = (null : sys.io.FileOutput); + var _ = (null : sys.io.FileInput); + } +} diff --git a/std/eval/_std/haxe/Resource.hx b/std/eval/_std/haxe/Resource.hx index 3ab2977c0d0..314699673f9 100644 --- a/std/eval/_std/haxe/Resource.hx +++ b/std/eval/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; @:coreApi extern class Resource { - public static function listNames() : Array; - public static function getString( name : String ) : String; - public static function getBytes( name : String ) : haxe.io.Bytes; + public static function listNames():Array; + public static function getString(name:String):String; + public static function getBytes(name:String):haxe.io.Bytes; } diff --git a/std/eval/_std/haxe/Utf8.hx b/std/eval/_std/haxe/Utf8.hx index d24904ae2c8..b5e26c6d296 100644 --- a/std/eval/_std/haxe/Utf8.hx +++ b/std/eval/_std/haxe/Utf8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,19 +19,21 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; @:coreApi +@:deprecated('haxe.Utf8 is deprecated. Use UnicodeString instead.') extern class Utf8 { - public function new( ?size : Int ):Void; - public function addChar( c : Int ) : Void; - public function toString() : String; - public static function iter( s : String, chars : Int -> Void ):Void; - public static function encode( s : String ) : String; - public static function decode( s : String ) : String; - public static function charCodeAt( s : String, index : Int ) : Int; - public static function validate( s : String ) : Bool; - public static function length( s : String ) : Int; - public static function compare( a : String, b : String ) : Int; - public static function sub( s : String, pos : Int, len : Int ) : String; -} \ No newline at end of file + public function new(?size:Int):Void; + public function addChar(c:Int):Void; + public function toString():String; + public static function iter(s:String, chars:Int->Void):Void; + public static function encode(s:String):String; + public static function decode(s:String):String; + public static function charCodeAt(s:String, index:Int):Int; + public static function validate(s:String):Bool; + public static function length(s:String):Int; + public static function compare(a:String, b:String):Int; + public static function sub(s:String, pos:Int, len:Int):String; +} diff --git a/std/eval/_std/haxe/io/Bytes.hx b/std/eval/_std/haxe/io/Bytes.hx index 4ebc1b13a6a..75489c6ab04 100644 --- a/std/eval/_std/haxe/io/Bytes.hx +++ b/std/eval/_std/haxe/io/Bytes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,36 +19,39 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; +// @:coreApi extern class Bytes { - function new(length:Int,b:BytesData):Void; - public var length(default,null):Int; - public function get( pos : Int ) : Int; - public function set( pos : Int, v : Int ) : Void; - public function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void; - public function fill( pos : Int, len : Int, value : Int ):Void; - public function sub( pos : Int, len : Int ) : Bytes; - public function compare( other : Bytes ) : Int; - public function getDouble( pos : Int ) : Float; - public function getFloat( pos : Int ) : Float; - public function setDouble( pos : Int, v : Float ) : Void; - public function setFloat( pos : Int, v : Float ) : Void; - public function getUInt16( pos : Int ) : Int; - public function setUInt16( pos : Int, v : Int ) : Void; - public function getInt32( pos : Int ) : Int; - public function getInt64( pos : Int ) : haxe.Int64; - public function setInt32( pos : Int, v : Int ) : Void; - public function setInt64( pos : Int, v : haxe.Int64 ) : Void; - public function getString( pos : Int, len : Int ) : String; - public function toString() : String; - public function toHex() : String; - public function getData() : BytesData; - public static function alloc( length : Int ) : Bytes; + function new(length:Int, b:BytesData):Void; + public var length(default, null):Int; + public function get(pos:Int):Int; + public function set(pos:Int, v:Int):Void; + public function blit(pos:Int, src:Bytes, srcpos:Int, len:Int):Void; + public function fill(pos:Int, len:Int, value:Int):Void; + public function sub(pos:Int, len:Int):Bytes; + public function compare(other:Bytes):Int; + public function getDouble(pos:Int):Float; + public function getFloat(pos:Int):Float; + public function setDouble(pos:Int, v:Float):Void; + public function setFloat(pos:Int, v:Float):Void; + public function getUInt16(pos:Int):Int; + public function setUInt16(pos:Int, v:Int):Void; + public function getInt32(pos:Int):Int; + public function getInt64(pos:Int):haxe.Int64; + public function setInt32(pos:Int, v:Int):Void; + public function setInt64(pos:Int, v:haxe.Int64):Void; + public function getString(pos:Int, len:Int, ?encoding:Encoding):String; + public function toString():String; + public function toHex():String; + public function getData():BytesData; + public static function alloc(length:Int):Bytes; @:pure - public static function ofString( s : String ) : Bytes; - public static function ofData( b : BytesData ) : Bytes; - public static function fastGet( b : BytesData, pos : Int ) : Int; + public static function ofString(s:String, ?encoding:Encoding):Bytes; + public static function ofData(b:BytesData):Bytes; + public static function ofHex(s:String):Bytes; + public static function fastGet(b:BytesData, pos:Int):Int; static function __init__():Void { haxe.io.Error; } diff --git a/std/eval/_std/haxe/io/BytesBuffer.hx b/std/eval/_std/haxe/io/BytesBuffer.hx index 313da9f81f3..328784fa68e 100644 --- a/std/eval/_std/haxe/io/BytesBuffer.hx +++ b/std/eval/_std/haxe/io/BytesBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,16 +19,17 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; @:coreApi extern class BytesBuffer { public var length(get, never):Int; public function new():Void; - function get_length():Int; + private function get_length():Int; public function addByte(byte:Int):Void; public function add(src:Bytes):Void; - public function addString(v:String):Void; + public function addString(v:String, ?encoding:Encoding):Void; public function addInt32(v:Int):Void; public function addInt64(v:haxe.Int64):Void; public function addFloat(v:Float):Void; diff --git a/std/eval/_std/haxe/io/BytesData.hx b/std/eval/_std/haxe/io/BytesData.hx index 33ab6df2cfc..3bce2385f3f 100644 --- a/std/eval/_std/haxe/io/BytesData.hx +++ b/std/eval/_std/haxe/io/BytesData.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,12 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; @:forward private abstract NativeBytesDataAbstract(Bytes) from Bytes to Bytes { - @:arrayAccess public inline function get(i:Int) return this.get(i); - @:arrayAccess public inline function set(i:Int, v:Dynamic) this.set(i, v); + @:arrayAccess public inline function get(i:Int) + return this.get(i); + + @:arrayAccess public inline function set(i:Int, v:Dynamic) + this.set(i, v); } -typedef BytesData = NativeBytesDataAbstract; \ No newline at end of file +typedef BytesData = NativeBytesDataAbstract; diff --git a/std/eval/_std/haxe/zip/Compress.hx b/std/eval/_std/haxe/zip/Compress.hx index 72977216a47..6e0f793de98 100644 --- a/std/eval/_std/haxe/zip/Compress.hx +++ b/std/eval/_std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,12 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; extern class Compress { public function new(level:Int):Void; - public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{ done:Bool, read:Int, wriet:Int }; + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, wriet:Int}; public function setFlushMode(f:FlushMode):Void; public function close():Void; public static function run(s:haxe.io.Bytes, level:Int):haxe.io.Bytes; -} \ No newline at end of file +} diff --git a/std/eval/_std/haxe/zip/Uncompress.hx b/std/eval/_std/haxe/zip/Uncompress.hx index 73fdada4943..73adbec46b3 100644 --- a/std/eval/_std/haxe/zip/Uncompress.hx +++ b/std/eval/_std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; extern class Uncompress { public function new(?windowBits:Int):Void; - public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{ done:Bool, read:Int, write:Int }; + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int}; public function setFlushMode(f:FlushMode):Void; public function close():Void; public static function run(src:haxe.io.Bytes, ?bufsize:Int):haxe.io.Bytes; diff --git a/std/eval/_std/sys/FileSystem.hx b/std/eval/_std/sys/FileSystem.hx index 6139a6b71c2..ed3b4e1c59e 100644 --- a/std/eval/_std/sys/FileSystem.hx +++ b/std/eval/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,34 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys; // This class is here so it re-shadows other FileSystem classes in macros, // e.g. from hxnodejs. - @:coreApi -extern class FileSystem { - static function exists(path:String):Bool; - static function rename(path:String, newPath:String):Void; - static function stat(path:String):FileStat; - static function fullPath(relPath:String):String; - static function absolutePath(relPath:String):String; - static function isDirectory(path:String):Bool; - static function createDirectory(path:String):Void; - static function deleteFile(path:String):Void; - static function deleteDirectory(path:String):Void; - static function readDirectory(path:String):Array; +class FileSystem { + extern static public function exists(path:String):Bool; + + extern static public function rename(path:String, newPath:String):Void; + + extern static public function stat(path:String):FileStat; + + extern static public function fullPath(relPath:String):String; + + static public function absolutePath(relPath:String):String { + if (haxe.io.Path.isAbsolute(relPath)) + return relPath; + return haxe.io.Path.join([Sys.getCwd(), relPath]); + } + + extern static public function isDirectory(path:String):Bool; + + extern static public function createDirectory(path:String):Void; + + extern static public function deleteFile(path:String):Void; + + extern static public function deleteDirectory(path:String):Void; + + extern static public function readDirectory(path:String):Array; } diff --git a/std/eval/_std/sys/io/File.hx b/std/eval/_std/sys/io/File.hx index c85826ee6f1..d3570b5bb7c 100644 --- a/std/eval/_std/sys/io/File.hx +++ b/std/eval/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,26 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; @:coreApi class File { - @:extern static public function getContent(path:String):String { return ""; } - @:extern static public function saveContent(path:String, content:String):Void { } - @:extern static public function getBytes(path:String):haxe.io.Bytes { return haxe.io.Bytes.alloc(0); } - @:extern static public function saveBytes(path:String, bytes:haxe.io.Bytes):Void { } - @:extern static public function read(path:String, binary:Bool = true):FileInput { return null; } - @:extern static public function write(path:String, binary:Bool = true):FileOutput { return null; } - @:extern static public function append(path:String, binary:Bool = true):FileOutput { return null; } + extern static public function getContent(path:String):String; + + extern static public function saveContent(path:String, content:String):Void; + + extern static public function getBytes(path:String):haxe.io.Bytes; + + extern static public function saveBytes(path:String, bytes:haxe.io.Bytes):Void; + + extern static public function read(path:String, binary:Bool = true):FileInput; + + extern static public function write(path:String, binary:Bool = true):FileOutput; + + extern static public function append(path:String, binary:Bool = true):FileOutput; + + extern static public function update(path:String, binary:Bool = true):FileOutput; static public function copy(srcPath:String, dstPath:String):Void { var s = read(srcPath, true); diff --git a/std/eval/_std/sys/io/FileInput.hx b/std/eval/_std/sys/io/FileInput.hx index f98ae199565..1df7f0ad724 100644 --- a/std/eval/_std/sys/io/FileInput.hx +++ b/std/eval/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,16 +19,21 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; // This class is not extern because externs overriding non-externs messes with DCE - @:coreApi class FileInput extends haxe.io.Input { - @:extern public override function close():Void { } - @:extern public function eof():Bool { return false; } - @:extern public function seek(p:Int, pos:FileSeek):Void { } - @:extern public function tell():Int { return 0; } - @:extern public override function readByte():Int { return 0; } - @:extern public override function readBytes(bytes:haxe.io.Bytes, pos:Int, len:Int):Int { return 0; } + extern public override function close():Void; + + extern public function eof():Bool; + + extern public function seek(p:Int, pos:FileSeek):Void; + + extern public function tell():Int; + + extern public override function readByte():Int; + + extern public override function readBytes(bytes:haxe.io.Bytes, pos:Int, len:Int):Int; } diff --git a/std/eval/_std/sys/io/FileOutput.hx b/std/eval/_std/sys/io/FileOutput.hx index 64bb0606f61..4e9705521ed 100644 --- a/std/eval/_std/sys/io/FileOutput.hx +++ b/std/eval/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,16 +19,21 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; // This class is not extern because externs overriding non-externs messes with DCE - @:coreApi class FileOutput extends haxe.io.Output { - @:extern public override function close():Void { } - @:extern public override function flush():Void { } - @:extern public function seek(p:Int, pos:FileSeek):Void { } - @:extern public function tell():Int { return 0; } - @:extern public override function writeByte(c:Int):Void { } - @:extern public override function writeBytes(bytes:haxe.io.Bytes, pos:Int, len:Int):Int { return 0; } + extern public override function close():Void; + + extern public override function flush():Void; + + extern public function seek(p:Int, pos:FileSeek):Void; + + extern public function tell():Int; + + extern public override function writeByte(c:Int):Void; + + extern public override function writeBytes(bytes:haxe.io.Bytes, pos:Int, len:Int):Int; } diff --git a/std/eval/_std/sys/io/Process.hx b/std/eval/_std/sys/io/Process.hx index f0ad764b774..255411d436b 100644 --- a/std/eval/_std/sys/io/Process.hx +++ b/std/eval/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,10 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; private extern class NativeProcess { - function new (cmd:String, ?args:Array):Void; + function new(cmd:String, ?args:Array):Void; function close():Void; function exitCode():Int; @@ -51,14 +52,14 @@ private class Stdin extends haxe.io.Output { } public override function writeByte(c:Int) { - buf.set(0,c); - writeBytes(buf,0,1); + buf.set(0, c); + writeBytes(buf, 0, 1); } public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int) { try { return proc.writeStdin(buf, pos, len); - } catch( e:Dynamic ) { + } catch (e:Dynamic) { throw new haxe.io.Eof(); } } @@ -76,7 +77,7 @@ private class Stdout extends haxe.io.Input { } public override function readByte() { - if(readBytes(buf,0,1) == 0) + if (readBytes(buf, 0, 1) == 0) throw haxe.io.Error.Blocked; return buf.get(0); } @@ -88,7 +89,7 @@ private class Stdout extends haxe.io.Input { } else { return proc.readStderr(bytes, pos, len); } - } catch( e:Dynamic ) { + } catch (e:Dynamic) { throw new haxe.io.Eof(); } } @@ -117,7 +118,8 @@ class Process { } public function exitCode(block:Bool = true):Null { - if( block == false ) throw "Non blocking exitCode() not supported on this platform"; + if (block == false) + throw "Non blocking exitCode() not supported on this platform"; return proc.exitCode(); } @@ -128,4 +130,4 @@ class Process { public inline function kill():Void { proc.kill(); } -} \ No newline at end of file +} diff --git a/std/eval/_std/sys/net/Host.hx b/std/eval/_std/sys/net/Host.hx index b7452210d60..3a73c052ef1 100644 --- a/std/eval/_std/sys/net/Host.hx +++ b/std/eval/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.net; class Host { - public var host(default,null):String; - public var ip(default,null):Int; + public var host(default, null):String; + public var ip(default, null):Int; public function new(name:String) { host = name; @@ -42,8 +43,11 @@ class Host { this.ip = ip; } - @:extern static public function localhost() { return ""; } - @:extern static function hostReverse(ip:Int) { return ""; } - @:extern static function hostToString(ip:Int) { return ""; } - @:extern static function resolve(name:String) { return 0; } -} \ No newline at end of file + extern static public function localhost(); + + extern static function hostReverse(ip:Int); + + extern static function hostToString(ip:Int); + + extern static function resolve(name:String); +} diff --git a/std/eval/_std/sys/net/Socket.hx b/std/eval/_std/sys/net/Socket.hx index 29b0261aacd..629943ff940 100644 --- a/std/eval/_std/sys/net/Socket.hx +++ b/std/eval/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.net; import haxe.io.Error; @@ -40,7 +41,8 @@ extern private class NativeSocket { function setTimeout(timeout:Float):Void; function shutdown(read:Bool, write:Bool):Void; - public static function select(read:Array, write:Array, others:Array, ?timeout:Float):{ read: Array,write: Array,others: Array }; + public static function select(read:Array, write:Array, others:Array, + ?timeout:Float):{read:Array, write:Array, others:Array}; } private class SocketOutput extends haxe.io.Output { @@ -53,10 +55,10 @@ private class SocketOutput extends haxe.io.Output { public override function writeByte(c:Int) { try { socket.sendChar(c); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + } catch (e:Dynamic) { + if (e == "Blocking") throw Blocked; - else if ( e == "EOF" ) + else if (e == "EOF") throw new haxe.io.Eof(); else throw Custom(e); @@ -66,8 +68,8 @@ private class SocketOutput extends haxe.io.Output { public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int) { return try { socket.send(buf, pos, len); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + } catch (e:Dynamic) { + if (e == "Blocking") throw Blocked; else throw Custom(e); @@ -90,8 +92,8 @@ private class SocketInput extends haxe.io.Input { public override function readByte() { return try { socket.receiveChar(); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + } catch (e:Dynamic) { + if (e == "Blocking") throw Blocked; else throw new haxe.io.Eof(); @@ -102,13 +104,13 @@ private class SocketInput extends haxe.io.Input { var r; try { r = socket.receive(buf, pos, len); - } catch( e : Dynamic ) { - if( e == "Blocking" ) + } catch (e:Dynamic) { + if (e == "Blocking") throw Blocked; else throw Custom(e); } - if( r == 0 ) + if (r == 0) throw new haxe.io.Eof(); return r; } @@ -121,8 +123,8 @@ private class SocketInput extends haxe.io.Input { @:coreApi class Socket { - public var input(default,null):haxe.io.Input; - public var output(default,null):haxe.io.Output; + public var input(default, null):haxe.io.Input; + public var output(default, null):haxe.io.Output; public var custom:Dynamic; @:ifFeature("sys.net.Socket.select") var socket:NativeSocket; @@ -177,7 +179,7 @@ class Socket { var info = socket.peer(); var host:Host = Type.createEmptyInstance(Host); host.init(info.ip); - return { host: host, port: info.port }; + return {host: host, port: info.port}; } @:access(sys.net.Host.init) @@ -185,7 +187,7 @@ class Socket { var info = socket.host(); var host:Host = Type.createEmptyInstance(Host); host.init(info.ip); - return { host: host, port: info.port }; + return {host: host, port: info.port}; } public function setTimeout(timeout:Float):Void { @@ -196,13 +198,14 @@ class Socket { select([this], null, null, -1); } - public function setBlocking(b:Bool):Void { } // TODO: Don't know how to implement this... + public function setBlocking(b:Bool):Void {} // TODO: Don't know how to implement this... public function setFastSend(b:Bool):Void { socket.setFastSend(b); } - public static function select(read:Array, write:Array, others:Array, ?timeout:Float):{ read: Array,write: Array,others: Array } { + public static function select(read:Array, write:Array, others:Array, + ?timeout:Float):{read:Array, write:Array, others:Array} { return NativeSocket.select(read, write, others, timeout); } } diff --git a/std/haxe/remoting/AsyncAdapter.hx b/std/eval/_std/sys/thread/Thread.hx similarity index 56% rename from std/haxe/remoting/AsyncAdapter.hx rename to std/eval/_std/sys/thread/Thread.hx index abbd2eada5a..eb93020cb82 100644 --- a/std/haxe/remoting/AsyncAdapter.hx +++ b/std/eval/_std/sys/thread/Thread.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,42 +19,42 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe.remoting; -/** - Build an AsyncConnection from a synchronized Connection. -**/ -class AsyncAdapter implements AsyncConnection { +package sys.thread; - var __cnx : Connection; - var __error : { ref : Dynamic -> Void }; +import eval.vm.NativeThread; - function new(cnx,error) { - __cnx = cnx; - __error = error; +abstract Thread(NativeThread) { + inline function new(h:NativeThread):Void { + this = h; } - public function resolve( name ) : AsyncConnection { - return new AsyncAdapter(__cnx.resolve(name),__error); + public inline function sendMessage(msg:Dynamic):Void { + this.sendMessage(msg); } - public function setErrorHandler(h) { - __error.ref = h; + public static inline function current():Thread { + return new Thread(NativeThread.self()); } - public function call( params : Array, ?onResult : Dynamic -> Void ) { - var ret; - try { - ret = __cnx.call(params); - } catch( e : Dynamic ) { - __error.ref(e); - return; - } - if( onResult != null ) onResult(ret); + public static inline function create(callb:Void->Void):Thread { + return new Thread(new NativeThread(callb)); } - public static function create( cnx : Connection ) : AsyncConnection { - return new AsyncAdapter(cnx,{ ref : function(e) throw e }); + public static inline function readMessage(block:Bool):Dynamic { + return NativeThread.readMessage(block); } + public static inline function yield():Void { + NativeThread.yield(); + } + + @:op(A == B) + public inline function equals(other:Thread):Bool { + return getHandle().id() == other.getHandle().id(); + } + + private inline function getHandle():NativeThread { + return this; + } } diff --git a/std/eval/vm/Context.hx b/std/eval/vm/Context.hx index 53ac32cdd56..b5f7b36135d 100644 --- a/std/eval/vm/Context.hx +++ b/std/eval/vm/Context.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package eval.vm; extern class Context { @@ -35,27 +36,29 @@ extern class Context { Sample plugin: - ```open EvalValue -open EvalContext -open EvalEncode + ```ocaml + open EvalValue + open EvalContext + open EvalEncode -let add_int = vfun2 (fun v1 v2 -> match v1,v2 with - | VInt32 i1,VInt32 i2 -> vint32 (Int32.add i1 i2) - | _ -> exc_string "Expected int + int" -) -;; -EvalStdLib.StdContext.register ["add_int",add_int] -``` + let add_int = vfun2 (fun v1 v2 -> match v1,v2 with + | VInt32 i1,VInt32 i2 -> vint32 (Int32.add i1 i2) + | _ -> exc_string "Expected int + int" + ) + ;; + EvalStdLib.StdContext.register ["add_int",add_int] + ``` Usage from Haxe: - ```var module:TestPlugin = eval.vm.Context.loadPlugin("testPlugin.cmo"); -trace(module.add_int(4, 3)); -``` + ```haxe + var module:TestPlugin = eval.vm.Context.loadPlugin("testPlugin.cmo"); + trace(module.add_int(4, 3)); + ``` Plugins have to be compiled with the same OCaml version as the Haxe compiler and using the same Haxe version. If a plugin cannot be loaded, an exception of type `String` is thrown. **/ static function loadPlugin(filePath:String):T; -} \ No newline at end of file +} diff --git a/std/eval/vm/Gc.hx b/std/eval/vm/Gc.hx index 52f79d13b0b..b52842b1439 100644 --- a/std/eval/vm/Gc.hx +++ b/std/eval/vm/Gc.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,214 +19,215 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package eval.vm; /** -The memory management counters are returned in a stat record. -The total amount of memory allocated by the program since it was started is (in words) minor_words + major_words - promoted_words. Multiply by the word size (4 on a 32-bit machine, 8 on a 64-bit machine) to get the number of bytes. + The memory management counters are returned in a stat record. + The total amount of memory allocated by the program since it was started is (in words) minor_words + major_words - promoted_words. Multiply by the word size (4 on a 32-bit machine, 8 on a 64-bit machine) to get the number of bytes. **/ typedef Stat = { /** - Number of words allocated in the minor heap since the program was started. This number is accurate in byte-code programs, but only an approximation in programs compiled to native code. + Number of words allocated in the minor heap since the program was started. This number is accurate in byte-code programs, but only an approximation in programs compiled to native code. **/ var minor_words:Float; /** - Number of words allocated in the minor heap that survived a minor collection and were moved to the major heap since the program was started. + Number of words allocated in the minor heap that survived a minor collection and were moved to the major heap since the program was started. **/ var promoted_words:Float; /** - Number of words allocated in the major heap, including the promoted words, since the program was started. + Number of words allocated in the major heap, including the promoted words, since the program was started. **/ var major_words:Float; /** - Number of minor collections since the program was started. + Number of minor collections since the program was started. **/ var minor_collections:Float; /** - Number of major collection cycles completed since the program was started. + Number of major collection cycles completed since the program was started. **/ var major_collections:Float; /** - Total size of the major heap, in words. + Total size of the major heap, in words. **/ var heap_words:Int; /** - Number of contiguous pieces of memory that make up the major heap. + Number of contiguous pieces of memory that make up the major heap. **/ var heap_chunks:Int; /** - Number of words of live data in the major heap, including the header words. + Number of words of live data in the major heap, including the header words. **/ var live_words:Int; /** - Number of live blocks in the major heap. + Number of live blocks in the major heap. **/ var live_blocks:Int; /** - Number of words in the free list. + Number of words in the free list. **/ var free_words:Int; /** - Number of blocks in the free list. + Number of blocks in the free list. **/ var free_blocks:Int; /** - Size (in words) of the largest block in the free list. + Size (in words) of the largest block in the free list. **/ var largest_free:Int; /** - Number of wasted words due to fragmentation. These are 1-words free blocks placed between two live blocks. They are not available for allocation. + Number of wasted words due to fragmentation. These are 1-words free blocks placed between two live blocks. They are not available for allocation. **/ var fragments:Int; /** - Number of heap compactions since the program was started. + Number of heap compactions since the program was started. **/ var compactions:Int; /** - Maximum size reached by the major heap, in words. + Maximum size reached by the major heap, in words. **/ var top_heap_words:Int; /** - Current size of the stack, in words. + Current size of the stack, in words. **/ var stack_size:Int; } /** -The GC parameters are given as a control record. Note that these parameters can also be initialised by setting the OCAMLRUNPARAM environment variable. See the documentation of ocamlrun. + The GC parameters are given as a control record. Note that these parameters can also be initialised by setting the OCAMLRUNPARAM environment variable. See the documentation of ocamlrun. **/ typedef Control = { /** - The size (in words) of the minor heap. Changing this parameter will trigger a minor collection. Default: 256k. + The size (in words) of the minor heap. Changing this parameter will trigger a minor collection. Default: 256k. **/ var minor_heap_size:Int; /** - How much to add to the major heap when increasing it. If this number is less than or equal to 1000, it is a percentage of the current heap size (i.e. setting it to 100 will double the heap size at each increase). If it is more than 1000, it is a fixed number of words that will be added to the heap. Default: 15. + How much to add to the major heap when increasing it. If this number is less than or equal to 1000, it is a percentage of the current heap size (i.e. setting it to 100 will double the heap size at each increase). If it is more than 1000, it is a fixed number of words that will be added to the heap. Default: 15. **/ var major_heap_increment:Int; /** - The major GC speed is computed from this parameter. This is the memory that will be "wasted" because the GC does not immediatly collect unreachable blocks. It is expressed as a percentage of the memory used for live data. The GC will work more (use more CPU time and collect blocks more eagerly) if space_overhead is smaller. Default: 80. + The major GC speed is computed from this parameter. This is the memory that will be "wasted" because the GC does not immediatly collect unreachable blocks. It is expressed as a percentage of the memory used for live data. The GC will work more (use more CPU time and collect blocks more eagerly) if space_overhead is smaller. Default: 80. **/ var space_overhead:Int; /** - This value controls the GC messages on standard error output. It is a sum of some of the following flags, to print messages on the corresponding events: - * 0x001 Start of major GC cycle. - * 0x002 Minor collection and major GC slice. - * 0x004 Growing and shrinking of the heap. - * 0x008 Resizing of stacks and memory manager tables. - * 0x010 Heap compaction. - * 0x020 Change of GC parameters. - * 0x040 Computation of major GC slice size. - * 0x080 Calling of finalisation functions. - * 0x100 Bytecode executable and shared library search at start-up. - * 0x200 Computation of compaction-triggering condition. - * 0x400 Output GC statistics at program exit. Default: 0. + This value controls the GC messages on standard error output. It is a sum of some of the following flags, to print messages on the corresponding events: + * 0x001 Start of major GC cycle. + * 0x002 Minor collection and major GC slice. + * 0x004 Growing and shrinking of the heap. + * 0x008 Resizing of stacks and memory manager tables. + * 0x010 Heap compaction. + * 0x020 Change of GC parameters. + * 0x040 Computation of major GC slice size. + * 0x080 Calling of finalisation functions. + * 0x100 Bytecode executable and shared library search at start-up. + * 0x200 Computation of compaction-triggering condition. + * 0x400 Output GC statistics at program exit. Default: 0. **/ var verbose:Int; /** - Heap compaction is triggered when the estimated amount of "wasted" memory is more than max_overhead percent of the amount of live data. If max_overhead is set to 0, heap compaction is triggered at the end of each major GC cycle (this setting is intended for testing purposes only). If max_overhead >= 1000000, compaction is never triggered. If compaction is permanently disabled, it is strongly suggested to set allocation_policy to 1. Default: 500. + Heap compaction is triggered when the estimated amount of "wasted" memory is more than max_overhead percent of the amount of live data. If max_overhead is set to 0, heap compaction is triggered at the end of each major GC cycle (this setting is intended for testing purposes only). If max_overhead >= 1000000, compaction is never triggered. If compaction is permanently disabled, it is strongly suggested to set allocation_policy to 1. Default: 500. **/ var max_overhead:Int; /** - The maximum size of the stack (in words). This is only relevant to the byte-code runtime, as the native code runtime uses the operating system's stack. Default: 1024k. + The maximum size of the stack (in words). This is only relevant to the byte-code runtime, as the native code runtime uses the operating system's stack. Default: 1024k. **/ var stack_limit:Int; /** - The policy used for allocating in the heap. Possible values are 0 and 1. 0 is the next-fit policy, which is quite fast but can result in fragmentation. 1 is the first-fit policy, which can be slower in some cases but can be better for programs with fragmentation problems. Default: 0. + The policy used for allocating in the heap. Possible values are 0 and 1. 0 is the next-fit policy, which is quite fast but can result in fragmentation. 1 is the first-fit policy, which can be slower in some cases but can be better for programs with fragmentation problems. Default: 0. **/ var allocation_policy:Int; } /** -Memory management control and statistics; finalised values. + Memory management control and statistics; finalised values. **/ extern class Gc { /** - Return the total number of bytes allocated since the program was started. It is returned as a float to avoid overflow problems with int on 32-bit machines. + Return the total number of bytes allocated since the program was started. It is returned as a float to avoid overflow problems with int on 32-bit machines. **/ static function allocated_bytes():Float; /** - Perform a full major collection and compact the heap. Note that heap compaction is a lengthy operation. + Perform a full major collection and compact the heap. Note that heap compaction is a lengthy operation. **/ static function compact():Void; /** - Return (minor_words, promoted_words, major_words). This function is as fast as quick_stat. + Return (minor_words, promoted_words, major_words). This function is as fast as quick_stat. **/ static function counters():{minor_words:Float, promoted_words:Float, major_words:Float}; /** - Registers f as a finalisation function for v. v must be heap-allocated. f will be called with v as argument at some point between the first time v becomes unreachable (including through weak pointers) and the time v is collected by the GC. Several functions can be registered for the same value, or even several instances of the same function. Each instance will be called once (or never, if the program terminates before v becomes unreachable). - The GC will call the finalisation functions in the order of deallocation. When several values become unreachable at the same time (i.e. during the same GC cycle), the finalisation functions will be called in the reverse order of the corresponding calls to finalise. If finalise is called in the same order as the values are allocated, that means each value is finalised before the values it depends upon. Of course, this becomes false if additional dependencies are introduced by assignments. + Registers f as a finalisation function for v. v must be heap-allocated. f will be called with v as argument at some point between the first time v becomes unreachable (including through weak pointers) and the time v is collected by the GC. Several functions can be registered for the same value, or even several instances of the same function. Each instance will be called once (or never, if the program terminates before v becomes unreachable). + The GC will call the finalisation functions in the order of deallocation. When several values become unreachable at the same time (i.e. during the same GC cycle), the finalisation functions will be called in the reverse order of the corresponding calls to finalise. If finalise is called in the same order as the values are allocated, that means each value is finalised before the values it depends upon. Of course, this becomes false if additional dependencies are introduced by assignments. - In the presence of multiple OCaml threads it should be assumed that any particular finaliser may be executed in any of the threads. + In the presence of multiple OCaml threads it should be assumed that any particular finaliser may be executed in any of the threads. **/ - static function finalise(f:T -> Void, v:T):Void; + static function finalise(f:T->Void, v:T):Void; /** - Do a minor collection, finish the current major collection cycle, and perform a complete new cycle. This will collect all currently unreachable blocks. + Do a minor collection, finish the current major collection cycle, and perform a complete new cycle. This will collect all currently unreachable blocks. **/ static function full_major():Void; /** - Return the current values of the GC parameters in a control record. + Return the current values of the GC parameters in a control record. **/ static function get():Control; /** - Do a minor collection and finish the current major collection cycle. + Do a minor collection and finish the current major collection cycle. **/ static function major():Void; /** - Do a minor collection and a slice of major collection. n is the size of the slice: the GC will do enough work to free (on average) n words of memory. If n = 0, the GC will try to do enough work to ensure that the next automatic slice has no work to do. This function returns an unspecified integer (currently: 0). + Do a minor collection and a slice of major collection. n is the size of the slice: the GC will do enough work to free (on average) n words of memory. If n = 0, the GC will try to do enough work to ensure that the next automatic slice has no work to do. This function returns an unspecified integer (currently: 0). **/ static function major_slice():Void; /** - Trigger a minor collection. + Trigger a minor collection. **/ static function minor():Void; /** - Print the current values of the memory management counters (in human-readable form) into the channel argument. + Print the current values of the memory management counters (in human-readable form) into the channel argument. **/ static function print_stat(out_channel:haxe.io.Output):Void; /** - Same as stat except that live_words, live_blocks, free_words, free_blocks, largest_free, and fragments are set to 0. This function is much faster than stat because it does not need to go through the heap. + Same as stat except that live_words, live_blocks, free_words, free_blocks, largest_free, and fragments are set to 0. This function is much faster than stat because it does not need to go through the heap. **/ static function quick_stat():Stat; /** - Changes the GC parameters according to the control record r. + Changes the GC parameters according to the control record r. **/ static function set(r:Control):Void; /** - Return the current values of the memory management counters in a stat record. This function examines every heap block to get the statistics. + Return the current values of the memory management counters in a stat record. This function examines every heap block to get the statistics. **/ static function stat():Stat; -} \ No newline at end of file +} diff --git a/std/eval/vm/NativeThread.hx b/std/eval/vm/NativeThread.hx new file mode 100644 index 00000000000..6640f4a5b73 --- /dev/null +++ b/std/eval/vm/NativeThread.hx @@ -0,0 +1,79 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package eval.vm; + +extern class NativeThread { + /** + Creates a new thread that executes function `f`. + + Exceptions caused while executing `f` are printed to stderr and are not + propagated to the parent thread. + **/ + function new(f:Void->Void):Void; + + /** + Return the identifier of the given thread. A thread identifier is an integer + that identifies uniquely the thread. It can be used to build data structures + indexed by threads. + **/ + function id():Int; + + /** + Terminate prematurely the thread whose handle is given. This functionality is + available only with bytecode-level threads. + **/ + function kill():Int; + + /** + Suspends the execution of the calling thread for `f` seconds. The other program + threads continue to run during this time. + **/ + static function delay(f:Float):Void; + + /** + Terminate prematurely the currently executing thread. + **/ + static function exit():Void; + + /** + Suspends the execution of the calling thread until the thread `thread` has + terminated. + **/ + static function join(thread:NativeThread):Void; + + /** + Return the thread currently executing. + **/ + static function self():NativeThread; + + /** + Re-schedule the calling thread without suspending it. This function can be used + to give scheduling hints, telling the scheduler that now is a good time to switch + to other threads. + **/ + static function yield():Void; + + static function readMessage(block:Bool):T; + + function sendMessage(msg:T):Void; +} diff --git a/std/flash/AnyType.hx b/std/flash/AnyType.hx new file mode 100644 index 00000000000..0e35c323cef --- /dev/null +++ b/std/flash/AnyType.hx @@ -0,0 +1,9 @@ +package flash; + +/** + This type represents the Flash `*` type, which is + actually the absense of type. It can be used as a + type parameter for `flash.Vector` to represent the + native `Vector.<*>` type. +**/ +@:coreType abstract AnyType from Dynamic to Dynamic {} diff --git a/std/flash/Boot.hx b/std/flash/Boot.hx index c19a7d0074e..95ed3b9d3e2 100644 --- a/std/flash/Boot.hx +++ b/std/flash/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package flash; #if !as3 -@:keep private class RealBoot extends Boot implements Dynamic { +@:keep private class RealBoot extends Boot { #if swc public function new() { super(); } + public static function initSwc(mc) { flash.Lib.current = mc; new RealBoot().init(); @@ -34,7 +36,8 @@ package flash; #else function new() { super(); - if( flash.Lib.current == null ) flash.Lib.current = this; + if (flash.Lib.current == null) + flash.Lib.current = this; start(); } #end @@ -44,30 +47,29 @@ package flash; @:dox(hide) @:keep class Boot extends flash.display.MovieClip { - - static var tf : flash.text.TextField; - static var lines : Array; - static var lastError : flash.errors.Error; + static var tf:flash.text.TextField; + static var lines:Array; + static var lastError:flash.errors.Error; public static var skip_constructor = false; function start() { #if dontWaitStage - init(); + init(); #else - var c = flash.Lib.current; - try { - untyped if( c == this && c.stage != null && c.stage.align == "" ) - c.stage.align = "TOP_LEFT"; - } catch( e : Dynamic ) { - // security error when loading from different domain - } - if( c.stage == null ) - c.addEventListener(flash.events.Event.ADDED_TO_STAGE, doInitDelay); - else if( c.stage.stageWidth == 0 || c.stage.stageHeight == 0 ) - untyped __global__["flash.utils.setTimeout"](start,1); - else - init(); + var c = flash.Lib.current; + try { + untyped if (c == this && c.stage != null && c.stage.align == "") + c.stage.align = "TOP_LEFT"; + } catch (e:Dynamic) { + // security error when loading from different domain + } + if (c.stage == null) + c.addEventListener(flash.events.Event.ADDED_TO_STAGE, doInitDelay); + else if (c.stage.stageWidth == 0 || c.stage.stageHeight == 0) + untyped __global__["flash.utils.setTimeout"](start, 1); + else + init(); #end } @@ -81,33 +83,33 @@ class Boot extends flash.display.MovieClip { } static var IN_E = 0; - public static function enum_to_string( e : { tag : String, params : Array } ) { - if( e.params == null ) + + public static function enum_to_string(e:{tag:String, params:Array}) { + if (e.params == null) return e.tag; var pstr = []; - if( IN_E > 15 ) { + if (IN_E > 15) { pstr.push("..."); } else { IN_E++; - for( p in e.params ) + for (p in e.params) pstr.push(__string_rec(p, "")); IN_E--; } - return e.tag+"("+pstr.join(",")+")"; + return e.tag + "(" + pstr.join(",") + ")"; } - public static function __instanceof( v : Dynamic, t : Dynamic ) { + public static function __instanceof(v:Dynamic, t:Dynamic) { try { - if( t == Dynamic ) - return true; - return untyped __is__(v,t); - } catch( e : Dynamic ) { - } + if (t == Dynamic) + return v != null; + return untyped __is__(v, t); + } catch (e:Dynamic) {} return false; } public static function __clear_trace() { - if( tf == null ) + if (tf == null) return; tf.parent.removeChild(tf); tf = null; @@ -122,11 +124,11 @@ class Boot extends flash.display.MovieClip { public static function getTrace() { var mc = flash.Lib.current; - if( tf == null ) { + if (tf == null) { tf = new flash.text.TextField(); #if flash10_2 var color = 0xFFFFFF, glow = 0; - if( mc.stage != null ) { + if (mc.stage != null) { glow = mc.stage.color; color = 0xFFFFFF - glow; } @@ -137,82 +139,97 @@ class Boot extends flash.display.MovieClip { format.font = "_sans"; tf.defaultTextFormat = format; tf.selectable = false; - tf.width = if( mc.stage == null ) 800 else mc.stage.stageWidth; + tf.width = if (mc.stage == null) 800 else mc.stage.stageWidth; tf.autoSize = flash.text.TextFieldAutoSize.LEFT; tf.mouseEnabled = false; } - if( mc.stage == null ) + if (mc.stage == null) mc.addChild(tf); else mc.stage.addChild(tf); // on top return tf; } - public static function __trace( v : Dynamic, pos : haxe.PosInfos ) { + public static function __trace(v:Dynamic, pos:haxe.PosInfos) { var tf = getTrace(); - var pstr = if( pos == null ) "(null)" else pos.fileName+":"+pos.lineNumber; - if( lines == null ) lines = []; - var str = pstr +": "+__string_rec(v, ""); - if( pos != null && pos.customParams != null ) - for( v in pos.customParams ) - str += ","+__string_rec(v, ""); + var pstr = if (pos == null) "(null)" else pos.fileName + ":" + pos.lineNumber; + if (lines == null) + lines = []; + var str = pstr + ": " + __string_rec(v, ""); + if (pos != null && pos.customParams != null) + for (v in pos.customParams) + str += "," + __string_rec(v, ""); lines = lines.concat(str.split("\n")); tf.text = lines.join("\n"); var stage = flash.Lib.current.stage; - if( stage == null ) + if (stage == null) return; - while( lines.length > 1 && tf.height > stage.stageHeight ) { + while (lines.length > 1 && tf.height > stage.stageHeight) { lines.shift(); tf.text = lines.join("\n"); } } - public static function __string_rec( v : Dynamic, str : String ) { + public static function __string_rec(v:Dynamic, str:String, maxRecursion:Int = 5) { + if (maxRecursion <= 0) { + return "<...>"; + } var cname = untyped __global__["flash.utils.getQualifiedClassName"](v); - switch( cname ) { - case "Object": - var k : Array = untyped __keys__(v); - var s = "{"; - var first = true; - for( i in 0...k.length ) { - var key = k[i]; - if( key == "toString" ) - try return v.toString() catch( e : Dynamic ) {} - if( first ) - first = false; - else - s += ","; - s += " "+key+" : "+__string_rec(v[untyped key],str); - } - if( !first ) - s += " "; - s += "}"; - return s; - case "Array": - if( v == Array ) - return "#Array"; - var s = "["; - var i; - var first = true; - var a : Array = v; - for( i in 0...a.length ) { - if( first ) - first = false; - else - s += ","; - s += __string_rec(a[i],str); - } - return s + "]"; - default: - switch( untyped __typeof__(v) ) { - case "function": return ""; - case "undefined": return "null"; - } + switch (cname) { + case "Object": + var k:Array = untyped __keys__(v); + var s = "{"; + var first = true; + for (i in 0...k.length) { + var key = k[i]; + if (key == "toString") + try + return v.toString() + catch (e:Dynamic) {} + if (first) + first = false; + else + s += ","; + s += " " + key + " : " + __string_rec(v[untyped key], str, maxRecursion - 1); + } + if (!first) + s += " "; + s += "}"; + return s; + case "Array": + if (v == Array) + return "#Array"; + var s = "["; + var i; + var first = true; + var a:Array = v; + for (i in 0...a.length) { + if (first) + first = false; + else + s += ","; + s += __string_rec(a[i], str, maxRecursion - 1); + } + return s + "]"; + default: + switch (untyped __typeof__(v)) { + case "function": return ""; + case "undefined": return "null"; + } } return new String(v); } - static function __unprotect__( s : String ) { + static public function fromCodePoint(code:Int) { + var o = new flash.utils.ByteArray(); + o.endian = LITTLE_ENDIAN; + o.writeShort((code >> 10) + 0xD7C0); + o.writeShort((code & 0x3FF) + 0xDC00); + o.position = 0; + return o.readMultiByte(4, "unicode"); + } + + static function __unprotect__(s:String) { return s; } @@ -232,97 +249,145 @@ class Boot extends flash.display.MovieClip { } } - static function __init__() untyped { - var aproto = Array.prototype; - aproto.copy = function() { - return __this__.slice(); - }; - aproto.insert = function(i,x) { - __this__.splice(i,0,x); - }; - aproto.remove = function(obj) { - var idx = __this__.indexOf(obj); - if( idx == -1 ) return false; - #if flash19 - __this__.removeAt(idx); - #else - __this__.splice(idx,1); - #end - return true; - } - aproto.iterator = function() { - var cur = 0; - var arr : Array = __this__; - return { - hasNext : function() { - return cur < arr.length; - }, - next : function() { - return arr[cur++]; + static function __init__() + untyped { + var d:Dynamic = Date; + d.now = function() { + return __new__(Date); + }; + d.fromTime = function(t) { + var d:Date = __new__(Date); + d.setTime(t); + return d; + }; + d.fromString = function(s:String) { + switch (s.length) { + case 8: // hh:mm:ss + var k = s.split(":"); + var d:Date = __new__(Date); + d.setTime(0); + d.setUTCHours(k[0]); + d.setUTCMinutes(k[1]); + d.setUTCSeconds(k[2]); + return d; + case 10: // YYYY-MM-DD + var k = s.split("-"); + return new Date(cast k[0], cast k[1] - 1, cast k[2], 0, 0, 0); + case 19: // YYYY-MM-DD hh:mm:ss + var k = s.split(" "); + var y = k[0].split("-"); + var t = k[1].split(":"); + return new Date(cast y[0], cast y[1] - 1, cast y[2], cast t[0], cast t[1], cast t[2]); + default: + throw "Invalid date format : " + s; } + }; + d.prototype[#if (as3 || no_flash_override) "toStringHX" #else "toString" #end] = function() { + var date:Date = __this__; + var m = date.getMonth() + 1; + var d = date.getDate(); + var h = date.getHours(); + var mi = date.getMinutes(); + var s = date.getSeconds(); + return date.getFullYear() + "-" + (if (m < 10) "0" + m else "" + m) + "-" + (if (d < 10) "0" + d else "" + d) + " " + + (if (h < 10) "0" + h else "" + h) + ":" + (if (mi < 10) "0" + mi else "" + mi) + ":" + (if (s < 10) "0" + s else "" + s); + }; + var aproto = Array.prototype; + aproto.copy = function() { + return __this__.slice(); + }; + aproto.insert = function(i, x) { + __this__.splice(i, 0, x); + }; + aproto.remove = function(obj) { + var idx = __this__.indexOf(obj); + if (idx == -1) + return false; + #if flash19 + // removeAt is only available through as3 namespace and genswf9 will only generate it for a known Array, + // so we have to type it properly (thus the typecheck). See https://github.com/HaxeFoundation/haxe/issues/8612 + (__this__:Array).removeAt(idx); + #else + __this__.splice(idx, 1); + #end + return true; } - }; - aproto.setPropertyIsEnumerable("copy", false); - aproto.setPropertyIsEnumerable("insert", false); - aproto.setPropertyIsEnumerable("remove", false); - aproto.setPropertyIsEnumerable("iterator", false); - #if (as3 || no_flash_override) - aproto.filterHX = function(f) { - var ret = []; - var i = 0; - var l = __this__.length; - while ( i < l ) { - if (f(__this__[i])) - ret.push(__this__[i]); - i++; - } - return ret; - }; - aproto.mapHX = function(f) { - var ret = []; - var i = 0; - var l = __this__.length; - while( i < l ) { - ret.push(f(__this__[i])); - i++; - } - return ret; - }; - aproto.setPropertyIsEnumerable("mapHX", false); - aproto.setPropertyIsEnumerable("filterHX", false); - String.prototype.charCodeAtHX = function(i) : Null { - #else - aproto["filter"] = function(f) { - var ret = []; - var i = 0; - var l = __this__.length; - while ( i < l ) { - if (f(__this__[i])) - ret.push(__this__[i]); - i++; - } - return ret; - }; - aproto["map"] = function(f) { - var ret = []; - var i = 0; - var l = __this__.length; - while( i < l ) { - ret.push(f(__this__[i])); - i++; - } - return ret; - }; - aproto.setPropertyIsEnumerable("map", false); - aproto.setPropertyIsEnumerable("filter", false); - String.prototype.charCodeAt = function(i) : Null { - #end - var s : String = __this__; - var x : Float = s.cca(i); - if( __global__["isNaN"](x) ) - return null; - return Std.int(x); - }; + aproto.iterator = function() { + var cur = 0; + var arr:Array = __this__; + return { + hasNext: function() { + return cur < arr.length; + }, + next: function() { + return arr[cur++]; + } + } + }; + aproto.resize = function(len) { + __this__.length = len; + }; + aproto.setPropertyIsEnumerable("copy", false); + aproto.setPropertyIsEnumerable("insert", false); + aproto.setPropertyIsEnumerable("remove", false); + aproto.setPropertyIsEnumerable("iterator", false); + aproto.setPropertyIsEnumerable("resize", false); + #if (as3 || no_flash_override) + aproto.filterHX = function(f) { + var ret = []; + var i = 0; + var l = __this__.length; + while (i < l) { + if (f(__this__[i])) + ret.push(__this__[i]); + i++; + } + return ret; + }; + aproto.mapHX = function(f) { + var ret = []; + var i = 0; + var l = __this__.length; + while (i < l) { + ret.push(f(__this__[i])); + i++; + } + return ret; + }; + aproto.setPropertyIsEnumerable("mapHX", false); + aproto.setPropertyIsEnumerable("filterHX", false); + String.prototype.charCodeAtHX = function(i):Null { + #else + aproto["filter"] = function(f) { + var ret = []; + var i = 0; + var l = __this__.length; + while (i < l) { + if (f(__this__[i])) + ret.push(__this__[i]); + i++; + } + return ret; + }; + aproto["map"] = function(f) { + var ret = []; + var i = 0; + var l = __this__.length; + while (i < l) { + ret.push(f(__this__[i])); + i++; + } + return ret; + }; + aproto.setPropertyIsEnumerable("map", false); + aproto.setPropertyIsEnumerable("filter", false); + String.prototype.charCodeAt = function(i):Null { + #end + var s:String = __this__; + var x:Float = s.cca(i); + if (__global__["isNaN"](x)) + return null; + return Std.int(x); + }; } - } diff --git a/std/flash/Lib.hx b/std/flash/Lib.hx index 5dd355a3eb7..06b631a5651 100644 --- a/std/flash/Lib.hx +++ b/std/flash/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,67 +19,68 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package flash; /** - Platform-specific Flash Library. Provides some platform-specific + Platform-specific Flash Library. Provides some platform-specific functions for the Flash target. **/ class Lib { + public static var current:flash.display.MovieClip; - public static var current : flash.display.MovieClip; - - public inline static function getTimer() : Int { + public inline static function getTimer():Int { return untyped __global__["flash.utils.getTimer"](); } - public static function eval( path : String ) : Dynamic { + public static function eval(path:String):Dynamic { var p = path.split("."); var fields = new Array(); - var o : Dynamic = null; - while( p.length > 0 ) { + var o:Dynamic = null; + while (p.length > 0) { try { o = untyped __global__["flash.utils.getDefinitionByName"](p.join(".")); - } catch( e : Dynamic ) { + } catch (e:Dynamic) { fields.unshift(p.pop()); } - if( o != null ) + if (o != null) break; } - for( f in fields ) { - if( o == null ) return null; + for (f in fields) { + if (o == null) + return null; o = untyped o[f]; } return o; } - public static function getURL( url : flash.net.URLRequest, ?target : String ) { + public static function getURL(url:flash.net.URLRequest, ?target:String) { var f = untyped __global__["flash.net.navigateToURL"]; - if( target == null ) + if (target == null) f(url); else - (cast f)(url,target); + (cast f)(url, target); } - public static function fscommand( cmd : String, ?param : String ) { - untyped __global__["flash.system.fscommand"](cmd,if( param == null ) "" else param); + public static function fscommand(cmd:String, ?param:String) { + untyped __global__["flash.system.fscommand"](cmd, if (param == null) "" else param); } - public static function trace( arg : Dynamic ) { + public static function trace(arg:Dynamic) { untyped __global__["trace"](arg); } - - public static function describeType( value : Dynamic ) : flash.xml.XML { + + public static function describeType(value:Dynamic):flash.xml.XML { return untyped __global__["flash.utils.describeType"](value); } - public static function attach( name : String ) : flash.display.MovieClip { - var cl = untyped __as__(__global__["flash.utils.getDefinitionByName"](name),Class); + public static function attach(name:String):flash.display.MovieClip { + var cl = untyped __as__(__global__["flash.utils.getDefinitionByName"](name), Class); return untyped __new__(cl); } - public inline static function as( v : Dynamic, c : Class ) : Null { - return untyped __as__(v,c); + public inline static function as(v:Dynamic, c:Class):Null { + return untyped __as__(v, c); } public static function redirectTraces() { @@ -87,15 +88,16 @@ class Lib { haxe.Log.trace = traceToConsole; } - static function traceToConsole(v : Dynamic, ?inf : haxe.PosInfos ) { - var type = if( inf != null && inf.customParams != null ) inf.customParams[0] else null; - if( type != "warn" && type != "info" && type != "debug" && type != "error" ) - type = if( inf == null ) "error" else "log"; - var str = if( inf == null ) "" else inf.fileName + ":" + inf.lineNumber + " : "; - try str += Std.string(v) catch( e : Dynamic ) str += "????"; + static function traceToConsole(v:Dynamic, ?inf:haxe.PosInfos) { + var type = if (inf != null && inf.customParams != null) inf.customParams[0] else null; + if (type != "warn" && type != "info" && type != "debug" && type != "error") + type = if (inf == null) "error" else "log"; + var str = if (inf == null) "" else inf.fileName + ":" + inf.lineNumber + " : "; + try + str += Std.string(v) + catch (e:Dynamic) + str += "????"; str = str.split("\\").join("\\\\"); - flash.external.ExternalInterface.call("console."+type,str); + flash.external.ExternalInterface.call("console." + type, str); } } - - diff --git a/std/flash/Memory.hx b/std/flash/Memory.hx index 4d20d19d5ea..88a27cf4b85 100644 --- a/std/flash/Memory.hx +++ b/std/flash/Memory.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,64 +19,63 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package flash; extern class Memory { - - public static inline function select( b : flash.utils.ByteArray ) : Void { + public static inline function select(b:flash.utils.ByteArray):Void { flash.system.ApplicationDomain.currentDomain.domainMemory = b; } - public static inline function setByte( addr : Int, v : Int ) : Void { - untyped __vmem_set__(0,addr,v); + public static inline function setByte(addr:Int, v:Int):Void { + untyped __vmem_set__(0, addr, v); } - public static inline function setI16( addr : Int, v : Int ) : Void { - untyped __vmem_set__(1,addr,v); + public static inline function setI16(addr:Int, v:Int):Void { + untyped __vmem_set__(1, addr, v); } - public static inline function setI32( addr : Int, v : Int ) : Void { - untyped __vmem_set__(2,addr,v); + public static inline function setI32(addr:Int, v:Int):Void { + untyped __vmem_set__(2, addr, v); } - public static inline function setFloat( addr : Int, v : Float ) : Void { - untyped __vmem_set__(3,addr,v); + public static inline function setFloat(addr:Int, v:Float):Void { + untyped __vmem_set__(3, addr, v); } - public static inline function setDouble( addr : Int, v : Float ) : Void { - untyped __vmem_set__(4,addr,v); + public static inline function setDouble(addr:Int, v:Float):Void { + untyped __vmem_set__(4, addr, v); } - public static inline function getByte( addr : Int ) : Int { - return untyped __vmem_get__(0,addr); + public static inline function getByte(addr:Int):Int { + return untyped __vmem_get__(0, addr); } - public static inline function getUI16( addr : Int ) : Int { - return untyped __vmem_get__(1,addr); + public static inline function getUI16(addr:Int):Int { + return untyped __vmem_get__(1, addr); } - public static inline function getI32( addr : Int ) : Int { - return untyped __vmem_get__(2,addr); + public static inline function getI32(addr:Int):Int { + return untyped __vmem_get__(2, addr); } - public static inline function getFloat( addr : Int ) : Float { - return untyped __vmem_get__(3,addr); + public static inline function getFloat(addr:Int):Float { + return untyped __vmem_get__(3, addr); } - public static inline function getDouble( addr : Int ) : Float { - return untyped __vmem_get__(4,addr); + public static inline function getDouble(addr:Int):Float { + return untyped __vmem_get__(4, addr); } - public static inline function signExtend1( v : Int ) : Int { - return untyped __vmem_sign__(0,v); + public static inline function signExtend1(v:Int):Int { + return untyped __vmem_sign__(0, v); } - public static inline function signExtend8( v : Int ) : Int { - return untyped __vmem_sign__(1,v); + public static inline function signExtend8(v:Int):Int { + return untyped __vmem_sign__(1, v); } - public static inline function signExtend16( v : Int ) : Int { - return untyped __vmem_sign__(2,v); + public static inline function signExtend16(v:Int):Int { + return untyped __vmem_sign__(2, v); } - -} \ No newline at end of file +} diff --git a/std/flash/NativeXml.hx b/std/flash/NativeXml.hx index dfb090f3b8c..309e2248269 100644 --- a/std/flash/NativeXml.hx +++ b/std/flash/NativeXml.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,119 +19,118 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package flash; import flash.xml.XML; import flash.xml.XMLList; -extern enum XmlType { -} - +extern enum XmlType {} typedef NativeXml = Xml; class Xml { - - public static var Element(default,null) : XmlType; - public static var PCData(default,null) : XmlType; - public static var CData(default,null) : XmlType; - public static var Comment(default,null) : XmlType; - public static var DocType(default,null) : XmlType; - public static var ProcessingInstruction(default,null) : XmlType; - public static var Document(default,null) : XmlType; - - public var nodeType(default,null) : XmlType; - public var nodeName(get,set) : String; - public var nodeValue(get,set) : String; - public var parent(get,null) : Xml; - - var _node : flash.xml.XML; - - public static function parse( str : String ) : Xml { + public static var Element(default, null):XmlType; + public static var PCData(default, null):XmlType; + public static var CData(default, null):XmlType; + public static var Comment(default, null):XmlType; + public static var DocType(default, null):XmlType; + public static var ProcessingInstruction(default, null):XmlType; + public static var Document(default, null):XmlType; + + public var nodeType(default, null):XmlType; + public var nodeName(get, set):String; + public var nodeValue(get, set):String; + public var parent(get, null):Xml; + + var _node:flash.xml.XML; + + public static function parse(str:String):Xml { XML.ignoreWhitespace = false; XML.ignoreProcessingInstructions = false; XML.ignoreComments = false; var prefix = "<__document"; var root = null; - while( root == null ) { + while (root == null) { try { - root = new flash.xml.XML(prefix+">" + str + ""); - } catch( e : flash.errors.TypeError ) { + root = new flash.xml.XML(prefix + ">" + str + ""); + } catch (e:flash.errors.TypeError) { // if we miss a namespace, let's add it ! - var r = ~/"([^"]+)"/; //" - if( e.errorID == 1083 && r.match(e.message) ) { + var r = ~/"([^"]+)"/; // " + if (e.errorID == 1083 && r.match(e.message)) { var ns = r.matched(1); prefix += " xmlns:" + ns + '="@' + ns + '"'; } else throw e; } } - return wrap( root, Xml.Document ); + return wrap(root, Xml.Document); } - @:keep #if as3 @:hack public #end static function compare( a : Xml, b : Xml ) : Bool { + @:keep #if as3 @:hack + public #end static function compare(a:Xml, b:Xml):Bool { return a == null ? b == null : (b == null ? false : a._node == b._node); } - private function new() : Void {} + private function new():Void {} - public static function createElement( name : String ) : Xml { - return wrap( new flash.xml.XML("<"+name+"/>"), Xml.Element ); + public static function createElement(name:String):Xml { + return wrap(new flash.xml.XML("<" + name + "/>"), Xml.Element); } - public static function createPCData( data : String ) : Xml { + public static function createPCData(data:String):Xml { XML.ignoreWhitespace = false; - return wrap( new flash.xml.XML(data), Xml.PCData ); + return wrap(new flash.xml.XML(data), Xml.PCData); } - public static function createCData( data : String ) : Xml { - return wrap( new flash.xml.XML(""), Xml.CData ); + public static function createCData(data:String):Xml { + return wrap(new flash.xml.XML(""), Xml.CData); } - public static function createComment( data : String ) : Xml { + public static function createComment(data:String):Xml { XML.ignoreComments = false; - return wrap( new flash.xml.XML(""), Xml.Comment ); + return wrap(new flash.xml.XML(""), Xml.Comment); } - public static function createDocType( data : String ) : Xml { - return wrap( new flash.xml.XML(""), Xml.DocType ); + public static function createDocType(data:String):Xml { + return wrap(new flash.xml.XML(""), Xml.DocType); } - public static function createProcessingInstruction( data : String ) : Xml { + public static function createProcessingInstruction(data:String):Xml { XML.ignoreProcessingInstructions = false; - return wrap( new flash.xml.XML(""), Xml.ProcessingInstruction ); + return wrap(new flash.xml.XML(""), Xml.ProcessingInstruction); } - public static function createDocument() : Xml { - return wrap( new flash.xml.XML("<__document/>"), Xml.Document ); + public static function createDocument():Xml { + return wrap(new flash.xml.XML("<__document/>"), Xml.Document); } - private static function getNodeType( node : flash.xml.XML ) : XmlType { - switch( node.nodeKind() ) { - case "element": - return Xml.Element; - case "text": - return Xml.PCData; - case "processing-instruction": - return Xml.ProcessingInstruction; - case "comment": - return Xml.Comment; - default : - throw "unimplemented node type: " + node.nodeType; + private static function getNodeType(node:flash.xml.XML):XmlType { + switch (node.nodeKind()) { + case "element": + return Xml.Element; + case "text": + return Xml.PCData; + case "processing-instruction": + return Xml.ProcessingInstruction; + case "comment": + return Xml.Comment; + default: + throw "unimplemented node type: " + node.nodeType; } } - private function get_nodeName() : String { - if( nodeType != Xml.Element ) + private function get_nodeName():String { + if (nodeType != Xml.Element) throw "bad nodeType"; var ns = _node.namespace(); - return (ns.prefix == "") ? _node.localName() : ns.prefix+":"+_node.localName(); + return (ns.prefix == "") ? _node.localName() : ns.prefix + ":" + _node.localName(); } - private function set_nodeName( n : String ) : String { - if( nodeType != Xml.Element ) + private function set_nodeName(n:String):String { + if (nodeType != Xml.Element) throw "bad nodeType"; var ns = n.split(":"); - if( ns.length == 1 ) + if (ns.length == 1) _node.setLocalName(n); else { _node.setLocalName(ns[1]); @@ -140,32 +139,32 @@ class Xml { return n; } - private function get_nodeValue() : String { + private function get_nodeValue():String { var nodeType = nodeType; - if( nodeType == Xml.Element || nodeType == Xml.Document ) + if (nodeType == Xml.Element || nodeType == Xml.Document) throw "bad nodeType"; - if( nodeType == Xml.Comment ) - return _node.toString().substr(4,-7); + if (nodeType == Xml.Comment) + return _node.toString().substr(4, -7); return _node.toString(); } - private function set_nodeValue( v : String ) : String { + private function set_nodeValue(v:String):String { var nodeType = nodeType; var x = null; - if( nodeType == Xml.Element || nodeType == Xml.Document ) + if (nodeType == Xml.Element || nodeType == Xml.Document) throw "bad nodeType"; - else if( nodeType == Xml.PCData ) + else if (nodeType == Xml.PCData) x = createPCData(v); - else if( nodeType == Xml.CData ) + else if (nodeType == Xml.CData) x = createCData(v); - else if( nodeType == Xml.Comment ) + else if (nodeType == Xml.Comment) x = createComment(v); - else if( nodeType == Xml.DocType ) + else if (nodeType == Xml.DocType) x = createDocType(v); else x = createProcessingInstruction(v); var p = _node.parent(); - if( p != null ) { + if (p != null) { p.insertChildAfter(_node, x._node); var i = _node.childIndex(); var children = p.children(); @@ -175,196 +174,196 @@ class Xml { return v; } - private function get_parent() :Xml { + private function get_parent():Xml { var p = _node.parent(); - return p == null ? null : wrap( p ); + return p == null ? null : wrap(p); } - private static function wrap( node : XML, ?type : XmlType ) : Xml { + private static function wrap(node:XML, ?type:XmlType):Xml { var x = new Xml(); x._node = node; - x.nodeType = (type != null) ? type : getNodeType( node ); + x.nodeType = (type != null) ? type : getNodeType(node); return x; } - private function wraps( xList : XMLList ) : Array { + private function wraps(xList:XMLList):Array { var out = new Array(); - for( i in 0...xList.length() ) - out.push( wrap(xList[i]) ); + for (i in 0...xList.length()) + out.push(wrap(xList[i])); return out; } - function getAttribNS( cur : XML, ns : Array ) : XMLList { + function getAttribNS(cur:XML, ns:Array):XMLList { var n = cur.namespace(ns[0]); - if( n == null ) { + if (n == null) { var parent = cur.parent(); - if( parent == null ) { - n = new flash.utils.Namespace(ns[0], "@"+ns[0]); + if (parent == null) { + n = new flash.utils.Namespace(ns[0], "@" + ns[0]); cur.addNamespace(n); } else return getAttribNS(parent, ns); } - return _node.attribute(new flash.utils.QName(n,ns[1])); + return _node.attribute(new flash.utils.QName(n, ns[1])); } - public function get( att : String ) : String { - if( nodeType != Xml.Element ) + public function get(att:String):String { + if (nodeType != Xml.Element) throw "bad nodeType"; var ns = att.split(":"); - if( ns[0] == "xmlns" ) { + if (ns[0] == "xmlns") { var n = _node.namespace((ns[1] == null) ? "" : ns[1]); return (n == null) ? null : n.uri; } - if( ns.length == 1 ) { - if( !Reflect.hasField(_node,"@"+att) ) + if (ns.length == 1) { + if (!Reflect.hasField(_node, "@" + att)) return null; - return Reflect.field(_node, "@"+att); + return Reflect.field(_node, "@" + att); } - var a = getAttribNS(_node,ns); + var a = getAttribNS(_node, ns); return (a.length() == 0) ? null : a.toString(); } - public function set( att : String, value : String ) : Void { - if( nodeType != Xml.Element ) + public function set(att:String, value:String):Void { + if (nodeType != Xml.Element) throw "bad nodeType"; var ns = att.split(":"); - if( ns[0] == "xmlns" ) { + if (ns[0] == "xmlns") { var n = _node.namespace((ns[1] == null) ? "" : ns[1]); - if( n != null ) + if (n != null) throw "Can't modify namespace"; - if( ns[1] == null ) + if (ns[1] == null) throw "Can't set default namespace"; _node.addNamespace(new flash.utils.Namespace(ns[1], value)); return; } - if( ns.length == 1 ) - Reflect.setField(_node, "@"+att, value); + if (ns.length == 1) + Reflect.setField(_node, "@" + att, value); else { - var a = getAttribNS(_node,ns); + var a = getAttribNS(_node, ns); untyped a[0] = value; } } - public function remove( att : String ) : Void{ - if( nodeType != Xml.Element ) + public function remove(att:String):Void { + if (nodeType != Xml.Element) throw "bad nodeType"; var ns = att.split(":"); - if( ns.length == 1 ) - Reflect.deleteField(_node, "@"+att); + if (ns.length == 1) + Reflect.deleteField(_node, "@" + att); else - untyped __delete__(getAttribNS(_node,ns),0); + untyped __delete__(getAttribNS(_node, ns), 0); } - public function exists( att : String ) : Bool { - if( nodeType != Xml.Element ) + public function exists(att:String):Bool { + if (nodeType != Xml.Element) throw "bad nodeType"; var ns = att.split(":"); - if( ns[0] == "xmlns" ) + if (ns[0] == "xmlns") return _node.namespace((ns[1] == null) ? "" : ns[1]) != null; - if( ns.length == 1 ) - return Reflect.hasField(_node, "@"+att); - return getAttribNS(_node,ns).length() > 0; - } - - public function attributes() : Iterator { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - var attributes :XMLList = _node.attributes(); - var names = Reflect.fields(attributes); - var cur = 0; - var nss = _node.namespaceDeclarations(); - return { - hasNext : function(){ - return cur < names.length + nss.length; - }, - next : function() { - if(cur { - if( nodeType != Xml.Element && nodeType != Xml.Document ) + if (ns.length == 1) + return Reflect.hasField(_node, "@" + att); + return getAttribNS(_node, ns).length() > 0; + } + + public function attributes():Iterator { + if (nodeType != Xml.Element) + throw "bad nodeType"; + var attributes:XMLList = _node.attributes(); + var names = Reflect.fields(attributes); + var cur = 0; + var nss = _node.namespaceDeclarations(); + return { + hasNext: function() { + return cur < names.length + nss.length; + }, + next: function() { + if (cur < names.length) { + return attributes[Std.parseInt(names[cur++])].name(); + } else { + var ns:flash.utils.Namespace = nss[cur++ - names.length]; + return "xmlns:" + ns.prefix; + } + } + } + } + + public function iterator():Iterator { + if (nodeType != Xml.Element && nodeType != Xml.Document) throw "bad nodeType"; var children:XMLList = _node.children(); - var wrappers :Array = wraps(children); + var wrappers:Array = wraps(children); var cur = 0; return { - hasNext : function(){ + hasNext: function() { return cur < wrappers.length; }, - next : function(){ + next: function() { return wrappers[cur++]; } }; } - public function elements() : Iterator { - if( nodeType != Xml.Element && nodeType != Xml.Document ) + public function elements():Iterator { + if (nodeType != Xml.Element && nodeType != Xml.Document) throw "bad nodeType"; var elements:XMLList = _node.elements(); - var wrappers :Array = wraps(elements); + var wrappers:Array = wraps(elements); var cur = 0; return { - hasNext : function(){ + hasNext: function() { return cur < wrappers.length; }, - next : function(){ + next: function() { return wrappers[cur++]; } }; } - public function elementsNamed( name : String ) : Iterator { - if( nodeType != Xml.Element && nodeType != Xml.Document ) + public function elementsNamed(name:String):Iterator { + if (nodeType != Xml.Element && nodeType != Xml.Document) throw "bad nodeType"; var ns = name.split(":"); var elements:XMLList; - if( ns.length == 1 ) + if (ns.length == 1) elements = _node.elements(name); else elements = _node.elements(); - var wrappers :Array = wraps(elements); - if( ns.length != 1 ) - for( w in wrappers.copy() ) - if( w._node.localName() != ns[1] || w._node.namespace().prefix != ns[0] ) + var wrappers:Array = wraps(elements); + if (ns.length != 1) + for (w in wrappers.copy()) + if (w._node.localName() != ns[1] || w._node.namespace().prefix != ns[0]) wrappers.remove(w); var cur = 0; return { - hasNext : function(){ + hasNext: function() { return cur < wrappers.length; }, - next : function(){ + next: function() { return wrappers[cur++]; } }; } - public function firstChild() : Xml { - if( nodeType != Xml.Element && nodeType != Xml.Document ) + public function firstChild():Xml { + if (nodeType != Xml.Element && nodeType != Xml.Document) throw "bad nodeType"; var children:XMLList = _node.children(); - if( children.length() == 0 ) + if (children.length() == 0) return null; - return wrap( children[0] ); + return wrap(children[0]); } - public function firstElement() : Xml { - if( nodeType != Xml.Element && nodeType != Xml.Document ) + public function firstElement():Xml { + if (nodeType != Xml.Element && nodeType != Xml.Document) throw "bad nodeType"; var elements:XMLList = _node.elements(); - if( elements.length() == 0 ) + if (elements.length() == 0) return null; - return wrap( elements[0] ); + return wrap(elements[0]); } - public function addChild( x : Xml ) : Void { - if( nodeType != Xml.Element && nodeType != Xml.Document ) + public function addChild(x:Xml):Void { + if (nodeType != Xml.Element && nodeType != Xml.Document) throw "bad nodeType"; if (x.parent != null) x.parent.removeChild(x); @@ -372,32 +371,32 @@ class Xml { _node.appendChild(x._node); } - public function removeChild( x : Xml ) : Bool { - if( nodeType != Xml.Element && nodeType != Xml.Document ) + public function removeChild(x:Xml):Bool { + if (nodeType != Xml.Element && nodeType != Xml.Document) throw "bad nodeType"; var children:XMLList = _node.children(); - if( _node != x._node.parent() ) + if (_node != x._node.parent()) return false; var i = x._node.childIndex(); untyped __delete__(children, Reflect.fields(children)[i]); return true; } - public function insertChild( x : Xml, pos : Int ) : Void { - if( nodeType != Xml.Element && nodeType != Xml.Document ) + public function insertChild(x:Xml, pos:Int):Void { + if (nodeType != Xml.Element && nodeType != Xml.Document) throw "bad nodeType"; if (x.parent != null) x.parent.removeChild(x); var children:XMLList = _node.children(); - if( pos < children.length() ) + if (pos < children.length()) _node.insertChildBefore(children[pos], x._node); else _node.appendChild(x._node); } - public function toString() : String { + public function toString():String { XML.prettyPrinting = false; - if( nodeType == Xml.Document ) { + if (nodeType == Xml.Document) { var str = _node.toXMLString(); // remove <__document xmlns....>STR wrapper str = str.substr(str.indexOf(">") + 1); @@ -407,15 +406,14 @@ class Xml { return _node.toXMLString(); } - static function __init__() : Void untyped { - Element = "element"; - PCData = "pcdata"; - CData = "cdata"; - Comment = "comment"; - DocType = "doctype"; - ProcessingInstruction = "processingInstruction"; - Document = "document"; - } - - -} \ No newline at end of file + static function __init__():Void + untyped { + Element = "element"; + PCData = "pcdata"; + CData = "cdata"; + Comment = "comment"; + DocType = "doctype"; + ProcessingInstruction = "processingInstruction"; + Document = "document"; + } +} diff --git a/std/flash/Vector.hx b/std/flash/Vector.hx index b841ae7e89b..3892edf3b6f 100644 --- a/std/flash/Vector.hx +++ b/std/flash/Vector.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,37 +19,76 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package flash; /** The Vector class is very similar to Array but is only supported by the Flash Player 10+ **/ @:require(flash10) extern class Vector implements ArrayAccess { + var length:Int; + var fixed:Bool; + + function new(?length:UInt, ?fixed:Bool):Void; + function concat(?a:Vector):Vector; + function join(sep:String):String; + function pop():Null; + function push(x:T):Int; + function reverse():Void; + function shift():Null; + function unshift(x:T):Void; + function slice(?pos:Int, ?end:Int):Vector; + function sort(f:T->T->Int):Void; + function splice(pos:Int, len:Int):Vector; + function toString():String; + function indexOf(x:T, ?from:Int):Int; + function lastIndexOf(x:T, ?from:Int):Int; - var length : Int; - var fixed : Bool; - - function new( ?length : UInt, ?fixed : Bool ) : Void; - function concat( ?a : Vector ) : Vector; - function join( sep : String ) : String; - function pop() : Null; - function push(x : T) : Int; - function reverse() : Void; - function shift() : Null; - function unshift( x : T ) : Void; - function slice( ?pos : Int, ?end : Int ) : Vector; - function sort( f : T -> T -> Int ) : Void; - function splice( pos : Int, len : Int ) : Vector; - function toString() : String; - function indexOf( x : T, ?from : Int ) : Int; - function lastIndexOf( x : T, ?from : Int ) : Int; - - public inline static function ofArray( v : Array ) : Vector { + #if flash19 + function insertAt(index:Int, element:T):Void; + #else + inline function insertAt(index:Int, element:T):Void { + (cast this).splice(index, 0, element); + } + #end + @:require(flash19) function removeAt(index:Int):T; + + public inline static function ofArray(v:Array):Vector { return untyped __vector__(v); } - public inline static function convert( v : Vector ) : Vector { + public inline static function convert(v:Vector):Vector { return untyped __vector__(v); } + /** + Get a run-time value referencing the `Vector` class with concrete type parameters. + + Normally in Haxe, for most of the types, type parameters are eliminated at run-time, + so there is no way to check if a value is of a type with specific type parameters. + + However, on the Flash target, the `flash.Vector` values carry type parameter + information at run-time all the type-checks (such as `Std.is` and `Std.downcast`) on them + must be done using a `Class` value that also carries the type parameters. However, + Haxe syntax does not allow creating such values and this function exists to mitigate + this limitation. + + It should be used as such: + ```haxe + var specificVectorType:Class> = Vector.typeReference(); + trace(Std.is(vec, specificVectorType)); + ``` + or using the type-check syntax: + ```haxe + trace(Std.is(vec, (Vector.typeReference() : Class>))); + ``` + + It's also helpful when working with native Flash libraries, that receive Class instances: + ```haxe + new Signal((Vector.typeReference() : Class>)); + ``` + **/ + public inline static function typeReference():Class> { + return untyped __vector__(); + } } diff --git a/std/flash/_std/EReg.hx b/std/flash/_std/EReg.hx index 9658231e20f..fd7e37cafec 100644 --- a/std/flash/_std/EReg.hx +++ b/std/flash/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,73 +20,76 @@ * DEALINGS IN THE SOFTWARE. */ @:coreApi class EReg { + var r:flash.utils.RegExp; + var result:Dynamic; - var r : flash.utils.RegExp; - var result : Dynamic; - - public function new( r : String, opt : String ) : Void { - this.r = new flash.utils.RegExp(r,opt); + public function new(r:String, opt:String):Void { + this.r = new flash.utils.RegExp(r, opt); } - public function match( s : String ) : Bool { - if( r.global ) r.lastIndex = 0; + public function match(s:String):Bool { + if (r.global) + r.lastIndex = 0; result = r.exec(s); return (result != null); } - public function matched( n : Int ) : String { - return if( result != null && n >= 0 && n < (result : Array).length ) result[n] else throw "EReg::matched"; + public function matched(n:Int):String { + return if (result != null && n >= 0 && n < (result:Array).length) result[n] else throw "EReg::matched"; } - public function matchedLeft() : String { - if( result == null ) throw "No string matched"; - var s : String = untyped result.input; - return s.substr(0,untyped result["index"]); + public function matchedLeft():String { + if (result == null) + throw "No string matched"; + var s:String = result.input; + return s.substr(0, result.index); } - public function matchedRight() : String { - if( result == null ) throw "No string matched"; - var rl = (result[untyped "index"] : Int) + (result[0] : String).length; - var s : String = untyped result.input; - return s.substr(rl,s.length - rl); + public function matchedRight():String { + if (result == null) + throw "No string matched"; + var rl = (result.index : Int) + (result[0] : String).length; + var s:String = result.input; + return s.substr(rl, s.length - rl); } - public function matchedPos() : { pos : Int, len : Int } { - if( result == null ) throw "No string matched"; - return { pos : result[untyped "index"], len : (result[0] : String).length }; + public function matchedPos():{pos:Int, len:Int} { + if (result == null) + throw "No string matched"; + return {pos: result.index, len: (result[0] : String).length}; } - public function matchSub( s : String, pos : Int, len : Int = -1):Bool { + public function matchSub(s:String, pos:Int, len:Int = -1):Bool { return if (r.global) { r.lastIndex = pos; result = r.exec(len < 0 ? s : s.substr(0, pos + len)); var b = result != null; if (b) { - untyped result.input = s; + result.input = s; } b; } else { - var b = match( len < 0 ? s.substr(pos) : s.substr(pos,len) ); + var b = match(len < 0 ? s.substr(pos) : s.substr(pos, len)); if (b) { - untyped result.input = s; - untyped result["index"] += pos; + result.input = s; + result.index += pos; } b; } } - public function split( s : String ) : Array { + public function split(s:String):Array { // we can't use directly s.split because it's ignoring the 'g' flag var d = "#__delim__#"; - var s : String = untyped s.replace(r, d); + var s:String = (s : Dynamic).replace(r, d); return s.split(d); } - public function replace( s : String, by : String ) : String { - return untyped s.replace(r,by); + public function replace(s:String, by:String):String { + return (s : Dynamic).replace(r, by); } - public function map( s : String, f : EReg -> String ) : String { + public function map(s:String, f:EReg->String):String { var offset = 0; var buf = new StringBuf(); var first = true; @@ -103,8 +106,7 @@ if (p.len == 0) { buf.add(s.substr(p.pos, 1)); offset = p.pos + 1; - } - else + } else offset = p.pos + p.len; first = false; } while (r.global); @@ -113,8 +115,9 @@ return buf.toString(); } - public static inline function escape( s : String ) : String { + public static inline function escape(s:String):String { return (cast s).replace(escapeRe, "\\$&"); } + static var escapeRe = new flash.utils.RegExp("[.*+?^${}()|[\\]\\\\]", "g"); } diff --git a/std/flash/_std/Reflect.hx b/std/flash/_std/Reflect.hx index e5b1dd82c4c..88b7c2789c6 100644 --- a/std/flash/_std/Reflect.hx +++ b/std/flash/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,113 +20,127 @@ * DEALINGS IN THE SOFTWARE. */ @:coreApi class Reflect { + public static function hasField(o:Dynamic, field:String):Bool + untyped { + return o.hasOwnProperty(field); + } - public static function hasField( o : Dynamic, field : String ) : Bool untyped { - return o.hasOwnProperty( field ); - } - - public static function field( o : Dynamic, field : String ) : Dynamic untyped { - // sealed classes will throw an exception - return try o[field] catch( e : Dynamic ) null; - } - - public inline static function setField( o : Dynamic, field : String, value : Dynamic ) : Void untyped { - o[field] = value; - } - - public static function getProperty( o : Dynamic, field : String ) : Dynamic untyped { - try { - return o["get_" + field](); - } catch( e : Dynamic ) try { - return o[field]; - } catch( e : Dynamic ) { - return null; + public static function field(o:Dynamic, field:String):Dynamic + untyped { + return o != null && __in__(field, o) ? o[field] : null; } - } - public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void untyped { - try { - o["set_" + field](value); - } catch( e : Dynamic ) { + public inline static function setField(o:Dynamic, field:String, value:Dynamic):Void + untyped { o[field] = value; } - } - public inline static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic untyped { - return func.apply(o,args); - } + public static function getProperty(o:Dynamic, field:String):Dynamic + untyped { + if (o == null) + return null; + var getter = 'get_$field'; + if (__in__(getter, o)) { + return o[getter](); + } + return __in__(field, o) ? o[field] : null; + } - public static function fields( o : Dynamic ) : Array untyped { - if( o == null ) return new Array(); - #if as3 - var a : Array = __keys__(o); - var i = 0; - while( i < a.length ){ - if( !o.hasOwnProperty(a[i]) ) - a.splice(i,1); - else - ++i; + public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void + untyped { + var setter = 'set_$field'; + if (__in__(setter, o)) { + o[setter](value); + } else { + o[field] = value; + } } - #else - var i = 0; - var a = []; - while( untyped __has_next__(o,i) ) { - var prop = untyped __forin__(o,i); - if( o.hasOwnProperty(prop) ) - a.push(prop); + + public inline static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array):Dynamic + untyped { + return func.apply(o, args); } - #end - return a; - } - public static function isFunction( f : Dynamic ) : Bool untyped { - return __typeof__(f) == "function"; - } + public static function fields(o:Dynamic):Array + untyped { + if (o == null) + return new Array(); + #if as3 + var a:Array = __keys__(o); + var i = 0; + while (i < a.length) { + if (!o.hasOwnProperty(a[i])) + a.splice(i, 1); + else + ++i; + } + #else + var i = 0; + var a = []; + while (untyped __has_next__(o, i)) { + var prop = untyped __forin__(o, i); + if (o.hasOwnProperty(prop)) + a.push(prop); + } + #end + return a; + } - public static function compare( a : T, b : T ) : Int { - var a : Dynamic = a; - var b : Dynamic = b; - return ( a == b ) ? 0 : ((a > b) ? 1 : -1); + public static function isFunction(f:Dynamic):Bool + untyped { + return __typeof__(f) == "function"; + } + + public static function compare(a:T, b:T):Int { + var a:Dynamic = a; + var b:Dynamic = b; + return (a == b) ? 0 : ((a > b) ? 1 : -1); } - public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool { + public static function compareMethods(f1:Dynamic, f2:Dynamic):Bool { return f1 == f2; // VM-level closures } - public static function isObject( v : Dynamic ) : Bool untyped { - if( v == null ) - return false; - var t = __typeof__(v); - if ( t == "object" ) { - return !isEnumValue(v); + public static function isObject(v:Dynamic):Bool + untyped { + if (v == null) + return false; + var t = __typeof__(v); + if (t == "object") { + return !isEnumValue(v); + } + return (t == "string"); } - return (t == "string"); - } - public static function isEnumValue( v : Dynamic ) : Bool { + public static function isEnumValue(v:Dynamic):Bool { #if as3 - return try Type.getEnum(v) != null catch ( e: Dynamic) false; + return try Type.getEnum(v) != null catch (e:Dynamic) false; #else - return try v.__enum__ == true catch ( e : Dynamic) false; + return try v.__enum__ == true catch (e:Dynamic) false; #end } - public static function deleteField( o : Dynamic, field : String ) : Bool untyped { - if( o.hasOwnProperty(field) != true ) return false; - __delete__(o,field); - return true; - } + public static function deleteField(o:Dynamic, field:String):Bool + untyped { + if (o.hasOwnProperty(field) != true) + return false; + __delete__(o, field); + return true; + } - public static function copy( o : T ) : T { - var o2 : Dynamic = {}; - for( f in Reflect.fields(o) ) - Reflect.setField(o2,f,Reflect.field(o,f)); + public static function copy(o:Null):Null { + if (o == null) + return null; + var o2:Dynamic = {}; + for (f in Reflect.fields(o)) + Reflect.setField(o2, f, Reflect.field(o, f)); return o2; } - @:overload(function( f : Array -> Void ) : Dynamic {}) - public static function makeVarArgs( f : Array -> Dynamic ) : Dynamic { - return function(__arguments__) { return f(__arguments__); }; + @:overload(function(f:Array->Void):Dynamic {}) + public static function makeVarArgs(f:Array->Dynamic):Dynamic { + return function(__arguments__) { + return f(__arguments__); + }; } - } diff --git a/std/flash/_std/Std.hx b/std/flash/_std/Std.hx index 361f24f841d..ca34930d8be 100644 --- a/std/flash/_std/Std.hx +++ b/std/flash/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,38 +19,44 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import flash.Boot; @:coreApi class Std { - - public static function is( v : Dynamic, t : Dynamic ) : Bool { - return untyped flash.Boot.__instanceof(v,t); + public static function is(v:Dynamic, t:Dynamic):Bool { + return flash.Boot.__instanceof(v, t); } - public static inline function instance( value : T, c : Class ) : S { + public static inline function downcast(value:T, c:Class):S { return flash.Lib.as(value, c); } - public static function string( s : Dynamic ) : String { - return untyped flash.Boot.__string_rec(s,""); + @:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.') + public static inline function instance(value:T, c:Class):S { + return downcast(value, c); } - public inline static function int( x : Float ) : Int { - return untyped __int__(x); + public static function string(s:Dynamic):String { + return flash.Boot.__string_rec(s, ""); } - public static function parseInt( x : String ) : Null untyped { - var v = __global__["parseInt"](x); - if( __global__["isNaN"](v) ) - return null; - return v; + public inline static function int(x:Float):Int { + return untyped __int__(x); } - public static function parseFloat( x : String ) : Float { + public static function parseInt(x:String):Null + untyped { + var v = __global__["parseInt"](x); + if (__global__["isNaN"](v)) + return null; + return v; + } + + public static function parseFloat(x:String):Float { return untyped __global__["parseFloat"](x); } - public static function random( x : Int ) : Int { - return untyped x <= 0 ? 0 : Math.floor(Math.random()*x); + public static function random(x:Int):Int { + return x <= 0 ? 0 : Math.floor(Math.random() * x); } } diff --git a/std/flash/_std/String.hx b/std/flash/_std/String.hx new file mode 100644 index 00000000000..6893eb0664a --- /dev/null +++ b/std/flash/_std/String.hx @@ -0,0 +1,41 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +@:coreApi +extern class String { + var length(default, null):Int; + function new(string:String):Void; + function toUpperCase():String; + function toLowerCase():String; + function charAt(index:Int):String; + function charCodeAt(index:Int):Null; + function indexOf(str:String, ?startIndex:Int):Int; + function lastIndexOf(str:String, ?startIndex:Int):Int; + function split(delimiter:String):Array; + function substr(pos:Int, ?len:Int):String; + function substring(startIndex:Int, ?endIndex:Int):String; + function toString():String; + + @:pure static inline function fromCharCode(code:Int):String + untyped { + return code < 0x10000 ? String["fromCharCode"](code) : flash.Boot.fromCodePoint(code); + } +} diff --git a/std/flash/_std/Type.hx b/std/flash/_std/Type.hx index f5c836940d8..4585e97d4d4 100644 --- a/std/flash/_std/Type.hx +++ b/std/flash/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,6 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - enum ValueType { TNull; TInt; @@ -27,264 +26,292 @@ enum ValueType { TBool; TObject; TFunction; - TClass( c : Class ); - TEnum( e : Enum ); + TClass(c:Class); + TEnum(e:Enum); TUnknown; } @:coreApi class Type { + public static function getClass(o:T):Class + untyped { + var cname = __global__["flash.utils.getQualifiedClassName"](o); + if (cname == "null" || cname == "Object" || cname == "int" || cname == "Number" || cname == "Boolean") + return null; + if (o.hasOwnProperty("prototype")) + return null; + var c = __as__(__global__["flash.utils.getDefinitionByName"](cname), Class); + if (c.__isenum) + return null; + return c; + } - public static function getClass( o : T ) : Class untyped { - var cname = __global__["flash.utils.getQualifiedClassName"](o); - if( cname == "null" || cname == "Object" || cname == "int" || cname == "Number" || cname == "Boolean" ) - return null; - if( o.hasOwnProperty("prototype") ) - return null; - var c = __as__(__global__["flash.utils.getDefinitionByName"](cname),Class); - if( c.__isenum ) - return null; - return c; - } - - public static function getEnum( o : EnumValue ) : Enum untyped { - var cname = __global__["flash.utils.getQualifiedClassName"](o); - if( cname == "null" || cname.substr(0,8) == "builtin." ) - return null; - // getEnum(Enum) should be null - if( o.hasOwnProperty("prototype") ) - return null; - var c = __as__(__global__["flash.utils.getDefinitionByName"](cname),Class); - if( !c.__isenum ) - return null; - return c; - } - + public static function getEnum(o:EnumValue):Enum + untyped { + var cname = __global__["flash.utils.getQualifiedClassName"](o); + if (cname == "null" || cname.substr(0, 8) == "builtin.") + return null; + // getEnum(Enum) should be null + if (o.hasOwnProperty("prototype")) + return null; + var c = __as__(__global__["flash.utils.getDefinitionByName"](cname), Class); + if (!c.__isenum) + return null; + return c; + } - public static function getSuperClass( c : Class ) : Class untyped { - var cname = __global__["flash.utils.getQualifiedSuperclassName"](c); - if( cname == null || cname == "Object" ) - return null; - return __as__(__global__["flash.utils.getDefinitionByName"](cname),Class); - } + public static function getSuperClass(c:Class):Class + untyped { + var cname = __global__["flash.utils.getQualifiedSuperclassName"](c); + if (cname == null || cname == "Object") + return null; + return __as__(__global__["flash.utils.getDefinitionByName"](cname), Class); + } - public static function getClassName( c : Class ) : String { - if( c == null ) + public static function getClassName(c:Class):String { + if (c == null) return null; - var str : String = untyped __global__["flash.utils.getQualifiedClassName"](c); - switch( str ) { - case "int": return "Int"; - case "Number": return "Float"; - case "Boolean": return "Bool"; + var str:String = untyped __global__["flash.utils.getQualifiedClassName"](c); + switch (str) { + case "int": + return "Int"; + case "Number": + return "Float"; + case "Boolean": + return "Bool"; + #if as3 + case "Object": + return "Dynamic"; + #end + default: + } + var parts = str.split("::"); #if as3 - case "Object": return "Dynamic"; - #end - default: + if (parts[parts.length - 1] == "_Object") { + parts[parts.length - 1] = "Object"; } - return str.split("::").join("."); + #end + return parts.join("."); } - public static function getEnumName( e : Enum ) : String { + public static function getEnumName(e:Enum):String { return getClassName(cast e); } - public static function resolveClass( name : String ) : Class untyped { - var cl : Class; - try { - cl = __as__(__global__["flash.utils.getDefinitionByName"](name),Class); - if( cl.__isenum ) + public static function resolveClass(name:String):Class + untyped { + var cl:Class; + try { + cl = __as__(__global__["flash.utils.getDefinitionByName"](name), Class); + if (cl.__isenum) + return null; + return cl; // skip test below + } catch (e:Dynamic) { + switch (name) { + case "Int": + return Int; + case "Float": + return Float; + #if as3 + case "Dynamic": + return Dynamic; + #end + } return null; - return cl; // skip test below - } catch( e : Dynamic ) { - switch( name ) { - case "Int": return Int; - case "Float": return Float; - #if as3 - case "Dynamic": return Dynamic; - #end } - return null; + // ensure that this is a class + if (cl == null || cl.__name__ == null) + return null; + return cl; } - // ensure that this is a class - if( cl == null || cl.__name__ == null ) - return null; - return cl; - } - - public static function resolveEnum( name : String ) : Enum untyped { - var e : Dynamic; - try { - e = __global__["flash.utils.getDefinitionByName"](name); - if( !e.__isenum ) + public static function resolveEnum(name:String):Enum + untyped { + var e:Dynamic; + try { + e = __global__["flash.utils.getDefinitionByName"](name); + if (!e.__isenum) + return null; + return e; + } catch (e:Dynamic) { + if (name == "Bool") + return Bool; + return null; + } + // ensure that this is an enum + if (e == null || e.__ename__ == null) return null; return e; - } catch( e : Dynamic ) { - if( name == "Bool" ) return Bool; - return null; } - // ensure that this is an enum - if( e == null || e.__ename__ == null ) - return null; - return e; - } - public static function createInstance( cl : Class, args : Array ) : T untyped { - return switch( args.length ) { - case 0: __new__(cl); - case 1: __new__(cl,args[0]); - case 2: __new__(cl,args[0],args[1]); - case 3: __new__(cl,args[0],args[1],args[2]); - case 4: __new__(cl,args[0],args[1],args[2],args[3]); - case 5: __new__(cl,args[0],args[1],args[2],args[3],args[4]); - case 6: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5]); - case 7: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6]); - case 8: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]); - case 9: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); - case 10: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]); - case 11: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]); - case 12: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]); - case 13: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]); - case 14: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]); - default: throw "Too many arguments"; + public static function createInstance(cl:Class, args:Array):T + untyped { + return switch (args.length) { + case 0: __new__(cl); + case 1: __new__(cl, args[0]); + case 2: __new__(cl, args[0], args[1]); + case 3: __new__(cl, args[0], args[1], args[2]); + case 4: __new__(cl, args[0], args[1], args[2], args[3]); + case 5: __new__(cl, args[0], args[1], args[2], args[3], args[4]); + case 6: __new__(cl, args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: __new__(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + case 8: __new__(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); + case 9: __new__(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + case 10: __new__(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); + case 11: __new__(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]); + case 12: __new__(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]); + case 13: __new__(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]); + case 14: __new__(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], + args[13]); + default: throw "Too many arguments"; + } } - } - public static function createEmptyInstance( cl : Class ) : T untyped { - try { - flash.Boot.skip_constructor = true; - var i = __new__(cl); - flash.Boot.skip_constructor = false; - return i; - } catch( e : Dynamic ) { - flash.Boot.skip_constructor = false; - throw e; + public static function createEmptyInstance(cl:Class):T + untyped { + try { + flash.Boot.skip_constructor = true; + var i = __new__(cl); + flash.Boot.skip_constructor = false; + return i; + } catch (e:Dynamic) { + flash.Boot.skip_constructor = false; + throw e; + } + return null; } - return null; - } - public static function createEnum( e : Enum, constr : String, ?params : Array ) : T { + public static function createEnum(e:Enum, constr:String, ?params:Array):T { var f:Dynamic = untyped e[constr]; - if( f == null ) throw "No such constructor "+constr; - if( Reflect.isFunction(f) ) { - if( params == null ) throw "Constructor "+constr+" need parameters"; - return Reflect.callMethod(e,f,params); + if (f == null) + throw "No such constructor " + constr; + if (Reflect.isFunction(f)) { + if (params == null) + throw "Constructor " + constr + " need parameters"; + return Reflect.callMethod(e, f, params); } - if( params != null && params.length != 0 ) - throw "Constructor "+constr+" does not need parameters"; + if (params != null && params.length != 0) + throw "Constructor " + constr + " does not need parameters"; return f; } - public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T { - var c : String = (untyped e.__constructs__)[index]; - if( c == null ) throw index+" is not a valid enum constructor index"; - return createEnum(e,c,params); + public static function createEnumIndex(e:Enum, index:Int, ?params:Array):T { + var c:String = (untyped e.__constructs__)[index]; + if (c == null) + throw index + " is not a valid enum constructor index"; + return createEnum(e, c, params); } - static function describe( t : Dynamic, fact : Bool ) : Array untyped { - var fields = new Array(); - var xml : flash.xml.XML = __global__["flash.utils.describeType"](t); - if( fact ) - xml = xml.factory[0]; - var methods = xml.child("method"); - for( i in 0...methods.length() ) - fields.push( Std.string(methods[i].attribute("name")) ); - var vars = xml.child("variable"); - for( i in 0...vars.length() ) - fields.push( Std.string(vars[i].attribute("name")) ); - var accs = xml.child("accessor"); - for( i in 0...accs.length() ) - fields.push( Std.string(accs[i].attribute("name")) ); - return fields; - } + static function describe(t:Dynamic, fact:Bool):Array + untyped { + var fields = new Array(); + var xml:flash.xml.XML = __global__["flash.utils.describeType"](t); + if (fact) + xml = xml.factory[0]; + var methods = xml.child("method"); + for (i in 0...methods.length()) + fields.push(Std.string(methods[i].attribute("name"))); + var vars = xml.child("variable"); + for (i in 0...vars.length()) + fields.push(Std.string(vars[i].attribute("name"))); + var accs = xml.child("accessor"); + for (i in 0...accs.length()) + fields.push(Std.string(accs[i].attribute("name"))); + return fields; + } - public static function getInstanceFields( c : Class ) : Array { - return describe(c,true); + public static function getInstanceFields(c:Class):Array { + return describe(c, true); } - public static function getClassFields( c : Class ) : Array { - var a = describe(c,false); + public static function getClassFields(c:Class):Array { + var a = describe(c, false); a.remove("__construct__"); a.remove("prototype"); return a; } - public static function getEnumConstructs( e : Enum ) : Array { - var a : Array = untyped e.__constructs__; + public static function getEnumConstructs(e:Enum):Array { + var a:Array = untyped e.__constructs__; return a.copy(); } - public static function typeof( v : Dynamic ) : ValueType untyped { - var cname = __global__["flash.utils.getQualifiedClassName"](v); - switch(cname) { - case "null": return TNull; - case "void": return TNull; // undefined - case "int": return TInt; - case "Number": - // integers >28 bits are stored as Numbers in avm2 - if( (v < -0x10000000 || v >= 0x10000000) && Std.int(v) == v ) - return TInt; - return TFloat; - case "Boolean": return TBool; - case "Object": return TObject; - case "Function": return TFunction; - default: - var c : Dynamic = null; - try { - c = __global__["flash.utils.getDefinitionByName"](cname); - if( v.hasOwnProperty("prototype") ) + public static function typeof(v:Dynamic):ValueType + untyped { + var cname = __global__["flash.utils.getQualifiedClassName"](v); + switch (cname) { + case "null": + return TNull; + case "void": + return TNull; // undefined + case "int": + return TInt; + case "Number": + // integers >28 bits are stored as Numbers in avm2 + if ((v < -0x10000000 || v >= 0x10000000) && Std.int(v) == v) + return TInt; + return TFloat; + case "Boolean": + return TBool; + case "Object": return TObject; - if( c.__isenum ) - return TEnum(c); - return TClass(c); - } catch( e : Dynamic ) { - if( cname == "builtin.as$0::MethodClosure" || cname.indexOf("-") != -1 ) + case "Function": return TFunction; - return if( c == null ) TFunction else TClass(c); + default: + var c:Dynamic = null; + try { + c = __global__["flash.utils.getDefinitionByName"](cname); + if (v.hasOwnProperty("prototype")) + return TObject; + if (c.__isenum) + return TEnum(c); + return TClass(c); + } catch (e:Dynamic) { + if (cname == "builtin.as$0::MethodClosure" || cname.indexOf("-") != -1) + return TFunction; + return if (c == null) TFunction else TClass(c); + } } + return null; } - return null; - } - public static function enumEq( a : T, b : T ) : Bool untyped { - if( a == b ) - return true; - try { - if( a.index != b.index ) - return false; - var ap : Array = a.params; - var bp : Array = b.params; - for( i in 0...ap.length ) - if( !enumEq(ap[i],bp[i]) ) + public static function enumEq(a:T, b:T):Bool + untyped { + if (a == b) + return true; + try { + if (a.index != b.index) return false; - } catch( e : Dynamic ) { - return false; + var ap:Array = a.params; + var bp:Array = b.params; + for (i in 0...ap.length) + if (!enumEq(ap[i], bp[i])) + return false; + } catch (e:Dynamic) { + return false; + } + return true; } - return true; - } - public static function enumConstructor( e : EnumValue ) : String { + public static function enumConstructor(e:EnumValue):String { return untyped e.tag; } - public static function enumParameters( e : EnumValue ) : Array { - return untyped if( e.params == null ) [] else e.params; + public static function enumParameters(e:EnumValue):Array { + return untyped if (e.params == null) [] else e.params; } - @:extern - public inline static function enumIndex( e : EnumValue ) : Int { + extern public inline static function enumIndex(e:EnumValue):Int { return untyped e.index; } - public static function allEnums( e : Enum ) : Array { + public static function allEnums(e:Enum):Array { var all = []; - var cst : Array = untyped e.__constructs__; - for( c in cst ) { - var v = Reflect.field(e,c); - if( !Reflect.isFunction(v) ) + var cst:Array = untyped e.__constructs__; + for (c in cst) { + var v = Reflect.field(e, c); + if (!Reflect.isFunction(v)) all.push(v); } return all; } - } - diff --git a/std/flash/_std/haxe/Http.hx b/std/flash/_std/haxe/Http.hx new file mode 100644 index 00000000000..d147f175883 --- /dev/null +++ b/std/flash/_std/haxe/Http.hx @@ -0,0 +1,106 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe; + +import haxe.io.Bytes; + +typedef Http = HttpFlash; + +class HttpFlash extends haxe.http.HttpBase { + var req:flash.net.URLLoader; + + /** + Cancels `this` Http request if `request` has been called and a response + has not yet been received. + **/ + public function cancel() { + if (req == null) + return; + req.close(); + req = null; + } + + public override function request(?post:Bool) { + responseBytes = null; + var loader = req = new flash.net.URLLoader(); + loader.dataFormat = BINARY; + loader.addEventListener("complete", function(e) { + req = null; + success(Bytes.ofData(loader.data)); + }); + loader.addEventListener("httpStatus", function(e:flash.events.HTTPStatusEvent) { + // on Firefox 1.5, Flash calls onHTTPStatus with 0 (!??) + if (e.status != 0) + onStatus(e.status); + }); + loader.addEventListener("ioError", function(e:flash.events.IOErrorEvent) { + req = null; + responseBytes = Bytes.ofData(loader.data); + onError(e.text); + }); + loader.addEventListener("securityError", function(e:flash.events.SecurityErrorEvent) { + req = null; + onError(e.text); + }); + + // headers + var param = false; + var vars = new flash.net.URLVariables(); + for (p in params) { + param = true; + Reflect.setField(vars, p.name, p.value); + } + var small_url = url; + if (param && !post) { + var k = url.split("?"); + if (k.length > 1) { + small_url = k.shift(); + vars.decode(k.join("?")); + } + } + // Bug in flash player 9 ??? + small_url.split("xxx"); + + var request = new flash.net.URLRequest(small_url); + for (h in headers) + request.requestHeaders.push(new flash.net.URLRequestHeader(h.name, h.value)); + + if (postData != null) { + request.data = postData; + request.method = "POST"; + } else if (postBytes != null) { + request.data = postBytes.getData(); + request.method = "POST"; + } else { + request.data = vars; + request.method = if (post) "POST" else "GET"; + } + + try { + loader.load(request); + } catch (e:Dynamic) { + req = null; + onError("Exception: " + Std.string(e)); + } + } +} diff --git a/std/flash/_std/haxe/Json.hx b/std/flash/_std/haxe/Json.hx index 39a32f42930..c56160ab775 100644 --- a/std/flash/_std/haxe/Json.hx +++ b/std/flash/_std/haxe/Json.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; @:coreApi #if (!haxeJSON && flash11) -@:native("JSON") extern +@:native("JSON") +extern #end class Json { + #if (haxeJSON || !flash11) + inline + #end + public static function parse(text:String):Dynamic + #if (!haxeJSON && flash11); #else { + return haxe.format.JsonParser.parse(text); + } #end - #if (haxeJSON || !flash11) inline #end - public static function parse( text : String ) : Dynamic { - return haxe.format.JsonParser.parse(text); - } - - #if (haxeJSON || !flash11) inline #end - public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String { - return haxe.format.JsonPrinter.print(value, replacer, space); - } + #if (haxeJSON || !flash11) + inline + #end + public static function stringify(value:Dynamic, ?replacer:(key:Dynamic, value:Dynamic) -> Dynamic, ?space:String):String + #if (!haxeJSON && flash11); #else { + return haxe.format.JsonPrinter.print(value, replacer, space); + } #end } diff --git a/std/flash/_std/haxe/Log.hx b/std/flash/_std/haxe/Log.hx index 8369a1bdf58..7f32e7de966 100644 --- a/std/flash/_std/haxe/Log.hx +++ b/std/flash/_std/haxe/Log.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,27 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; @:coreApi class Log { - public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { + public static function formatOutput(v:Dynamic, infos:PosInfos):String { + var str = Std.string(v); + if (infos == null) + return str; + var pstr = infos.fileName + ":" + infos.lineNumber; + if (infos != null && infos.customParams != null) + for (v in infos.customParams) + str += ", " + Std.string(v); + return pstr + ": " + str; + } + + public static dynamic function trace(v:Dynamic, ?infos:PosInfos):Void { #if (fdb || native_trace) - var pstr = infos == null ? "(null)" : infos.fileName + ":" + infos.lineNumber; - var str = flash.Boot.__string_rec(v, ""); - if( infos != null && infos.customParams != null ) for( v in infos.customParams ) str += "," + flash.Boot.__string_rec(v, ""); - untyped __global__["trace"](pstr+": "+str); + var str = formatOutput(v, infos); + untyped __global__["trace"](str); #else - flash.Boot.__trace(v,infos); + flash.Boot.__trace(v, infos); #end } @@ -37,7 +47,7 @@ package haxe; Clears the trace output. **/ @:hack - public static dynamic function clear() : Void { + public static dynamic function clear():Void { flash.Boot.__clear_trace(); } @@ -45,7 +55,7 @@ package haxe; Sets the color of the trace output to `rgb`. **/ @:hack - public static dynamic function setColor( rgb : Int ) : Void { + public static dynamic function setColor(rgb:Int):Void { flash.Boot.__set_trace_color(rgb); } } diff --git a/std/flash/_std/haxe/Resource.hx b/std/flash/_std/haxe/Resource.hx index dd4ebd42002..263aaad6f82 100644 --- a/std/flash/_std/haxe/Resource.hx +++ b/std/flash/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,69 +19,73 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; #if as3 @:coreApi class Resource { - public static function listNames() : Array untyped { - return __keys__(__resources__.list); - } + public static function listNames():Array + untyped { + return __keys__(__resources__.list); + } - public static function getString( name : String ) : String { + public static function getString(name:String):String { var b = resolve(name); return b == null ? null : b.readUTFBytes(b.length); } - public static function getBytes( name : String ) : haxe.io.Bytes { + public static function getBytes(name:String):haxe.io.Bytes { var b = resolve(name); return b == null ? null : haxe.io.Bytes.ofData(b); } - static function resolve( name : String) :flash.utils.ByteArray untyped { - var n = __resources__.list[name]; - if (n == null) return null; - return untyped __new__(n); - } + static function resolve(name:String):flash.utils.ByteArray + untyped { + var n = __resources__.list[name]; + if (n == null) + return null; + return untyped __new__(n); + } - static function __init__() : Void { + static function __init__():Void { untyped __resources__.__init__(); } } #else @:coreApi class Resource { + static var content:Array<{name:String}>; - static var content : Array<{ name : String }>; - - public static function listNames() : Array { + public static function listNames():Array { var names = new Array(); - for( x in content ) + for (x in content) names.push(x.name); return names; } - public static function getString( name : String ) : String { + public static function getString(name:String):String { var b = resolve(name); return b == null ? null : b.readUTFBytes(b.length); } - public static function getBytes( name : String ) : haxe.io.Bytes { + public static function getBytes(name:String):haxe.io.Bytes { var b = resolve(name); return b == null ? null : haxe.io.Bytes.ofData(b); } - static function resolve( name : String ) : flash.utils.ByteArray { - try untyped { - var c = __as__(__global__["flash.utils.getDefinitionByName"]("_res._"+name.split(".").join("_")),Class); - return __new__(c); - } catch( e : Dynamic ) { + static function resolve(name:String):flash.utils.ByteArray { + try + untyped { + var c = __as__(__global__["flash.utils.getDefinitionByName"]("_res._" + name.split(".").join("_")), Class); + return __new__(c); + } catch (e:Dynamic) { return null; } } - static function __init__() : Void { + static function __init__():Void { content = untyped __resources__(); } } -#end \ No newline at end of file +#end diff --git a/std/flash/_std/haxe/ds/IntMap.hx b/std/flash/_std/haxe/ds/IntMap.hx index e5944df4fbe..29c9f843126 100644 --- a/std/flash/_std/haxe/ds/IntMap.hx +++ b/std/flash/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,78 +19,85 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe.ds; -@:coreApi class IntMap implements haxe.Constraints.IMap { +package haxe.ds; - private var h : flash.utils.Dictionary; +@:coreApi class IntMap implements haxe.Constraints.IMap { + private var h:flash.utils.Dictionary; - public function new() : Void { + public function new():Void { h = new flash.utils.Dictionary(); } - public inline function set( key : Int, value : T ) : Void { + public inline function set(key:Int, value:T):Void { untyped h[key] = value; } - public inline function get( key : Int ) : Null { + public inline function get(key:Int):Null { return untyped h[key]; } - public inline function exists( key : Int ) : Bool { - return untyped __in__(key,h); + public inline function exists(key:Int):Bool { + return untyped __in__(key, h); } - public function remove( key : Int ) : Bool { - if( !exists(key) ) return false; - untyped __delete__(h,key); + public function remove(key:Int):Bool { + if (!exists(key)) + return false; + untyped __delete__(h, key); return true; } #if as3 - // unoptimized version - - public function keys() : Iterator { + + public function keys():Iterator { return untyped (__keys__(h)).iterator(); } - @:analyzer(ignore) public function iterator() : Iterator { + @:analyzer(ignore) public function iterator():Iterator { return untyped { - ref : h, - it : keys(), - hasNext : function() { return __this__.it.hasNext(); }, - next : function() { var i = __this__.it.next(); return __this__.ref[i]; } + ref: h, + it: keys(), + hasNext: function() { + return __this__.it.hasNext(); + }, + next: function() { + var i = __this__.it.next(); + return __this__.ref[i]; + } }; } - #else - - public inline function keys() : Iterator { + public inline function keys():Iterator { return new IntMapKeysIterator(h); } - public inline function iterator() : Iterator { + public inline function iterator():Iterator { return new IntMapValuesIterator(h); } - #end - - public function copy() : IntMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():IntMap { var copied = new IntMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - - public function toString() : String { + + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(i); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); @@ -99,14 +106,13 @@ package haxe.ds; } #if !as3 - // this version uses __has_next__/__forin__ special SWF opcodes for iteration with no allocation @:allow(haxe.ds.IntMap) private class IntMapKeysIterator { var h:flash.utils.Dictionary; - var index : Int; - var nextIndex : Int; + var index:Int; + var nextIndex:Int; inline function new(h:flash.utils.Dictionary):Void { this.h = h; @@ -122,18 +128,17 @@ private class IntMapKeysIterator { } public inline function next():Int { - var r : Int = untyped __forin__(h, nextIndex); + var r:Int = untyped __forin__(h, nextIndex); index = nextIndex; return r; } - } @:allow(haxe.ds.IntMap) private class IntMapValuesIterator { var h:flash.utils.Dictionary; - var index : Int; - var nextIndex : Int; + var index:Int; + var nextIndex:Int; inline function new(h:flash.utils.Dictionary):Void { this.h = h; @@ -153,6 +158,5 @@ private class IntMapValuesIterator { index = nextIndex; return r; } - } #end diff --git a/std/flash/_std/haxe/ds/ObjectMap.hx b/std/flash/_std/haxe/ds/ObjectMap.hx index bdb88234720..2785869d2b7 100644 --- a/std/flash/_std/haxe/ds/ObjectMap.hx +++ b/std/flash/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,67 +19,69 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package haxe.ds; -@:coreApi -class ObjectMap extends flash.utils.Dictionary implements haxe.Constraints.IMap { +package haxe.ds; +@:coreApi +class ObjectMap extends flash.utils.Dictionary implements haxe.Constraints.IMap { public function new() { super(false); } - public inline function get( key : K ) : Null { + public inline function get(key:K):Null { return untyped this[key]; } - public inline function set( key : K, value : V ):Void { + public inline function set(key:K, value:V):Void { untyped this[key] = value; } - public inline function exists( key : K ) : Bool { + public inline function exists(key:K):Bool { return untyped this[key] != null; } - public function remove( key : K ):Bool { + public function remove(key:K):Bool { var has = exists(key); untyped __delete__(this, key); return has; } #if as3 - - public function keys() : Iterator { + public function keys():Iterator { return untyped __keys__(this).iterator(); - } + } - public function iterator() : Iterator { + public function iterator():Iterator { var ret = []; for (i in keys()) ret.push(get(i)); return ret.iterator(); - } + } #else - - public function keys() : Iterator { + public function keys():Iterator { return NativePropertyIterator.iterator(this); } - public function iterator() : Iterator { + public function iterator():Iterator { return NativeValueIterator.iterator(this); } - #end - - public function copy() : ObjectMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():ObjectMap { var copied = new ObjectMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = ""; var it = keys(); - for( i in it ) { + for (i in it) { s += (s == "" ? "" : ",") + Std.string(i); s += " => "; s += Std.string(get(i)); @@ -87,6 +89,7 @@ class ObjectMap extends flash.utils.Dictionary implements haxe.Constrain return s + "}"; } } + #if !as3 private class NativePropertyIterator { var collection:Dynamic; diff --git a/std/flash/_std/haxe/ds/StringMap.hx b/std/flash/_std/haxe/ds/StringMap.hx index 235a858178b..94e6deccced 100644 --- a/std/flash/_std/haxe/ds/StringMap.hx +++ b/std/flash/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,133 +19,141 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; -@:coreApi class StringMap implements haxe.Constraints.IMap { +@:coreApi class StringMap implements haxe.Constraints.IMap { + private var h:Dynamic; + private var rh:Dynamic; - private var h : Dynamic; - private var rh : Dynamic; - static var reserved = { }; + static var reserved = {}; - public function new() : Void { + public function new():Void { h = {}; } - inline function isReserved(key:String) : Bool { - return untyped __in__(key,reserved); + inline function isReserved(key:String):Bool { + return untyped __in__(key, reserved); } - public inline function set( key : String, value : T ) : Void { - if( isReserved(key) ) + public inline function set(key:String, value:T):Void { + if (isReserved(key)) setReserved(key, value); else untyped h[key] = value; } - public inline function get( key : String ) : Null { - if( isReserved(key) ) + public inline function get(key:String):Null { + if (isReserved(key)) return getReserved(key); return untyped h[key]; } - public inline function exists( key : String ) : Bool { - if( isReserved(key) ) + public inline function exists(key:String):Bool { + if (isReserved(key)) return existsReserved(key); - return untyped __in__(key,h); + return untyped __in__(key, h); } - function setReserved( key : String, value : T ) : Void { - if( rh == null ) rh = {}; - untyped rh["$"+key] = value; + function setReserved(key:String, value:T):Void { + if (rh == null) + rh = {}; + untyped rh["$" + key] = value; } - function getReserved( key : String ) : Null { - return rh == null ? null : untyped rh["$"+key]; + function getReserved(key:String):Null { + return rh == null ? null : untyped rh["$" + key]; } - function existsReserved( key : String ) : Bool { - if( rh == null ) return false; - return untyped __in__("$"+key,rh); + function existsReserved(key:String):Bool { + if (rh == null) + return false; + return untyped __in__("$" + key, rh); } - public function remove( key : String ) : Bool { - if( isReserved(key) ) { + public function remove(key:String):Bool { + if (isReserved(key)) { key = "$" + key; - if( rh == null || !untyped __in__(key,rh) ) return false; - untyped __delete__(rh,key); + if (rh == null || !untyped __in__(key, rh)) + return false; + untyped __delete__(rh, key); return true; } else { - if( !untyped __in__(key,h) ) + if (!untyped __in__(key, h)) return false; - untyped __delete__(h,key); + untyped __delete__(h, key); return true; } } #if as3 - // unoptimized version - public function keys() : Iterator { - var out : Array = untyped __keys__(h); - if( rh != null ) out = out.concat(untyped __hkeys__(rh)); + public function keys():Iterator { + var out:Array = untyped __keys__(h); + if (rh != null) + out = out.concat(untyped __hkeys__(rh)); return out.iterator(); } - public function iterator() : Iterator { + public function iterator():Iterator { return untyped { - it : keys(), - hasNext : function() { return __this__.it.hasNext(); }, - next : function() { return get(__this__.it.next()); } + it: keys(), + hasNext: function() { + return __this__.it.hasNext(); + }, + next: function() { + return get(__this__.it.next()); + } }; } - #else - - public inline function keys() : Iterator { + public inline function keys():Iterator { return new StringMapKeysIterator(h, rh); } - public inline function iterator() : Iterator { + public inline function iterator():Iterator { return new StringMapValuesIterator(h, rh); } - #end - - public function copy() : StringMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():StringMap { var copied = new StringMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(i); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - } #if !as3 - // this version uses __has_next__/__forin__ special SWF opcodes for iteration with no allocation @:allow(haxe.ds.StringMap) private class StringMapKeysIterator { var h:Dynamic; var rh:Dynamic; - var index : Int; - var nextIndex : Int; - var isReserved : Bool; + var index:Int; + var nextIndex:Int; + var isReserved:Bool; inline function new(h:Dynamic, rh:Dynamic):Void { this.h = h; @@ -158,7 +166,7 @@ private class StringMapKeysIterator { public inline function hasNext():Bool { var h = h, index = index; // tmp vars required for __has_next var n = untyped __has_next__(h, index); - if( !n && rh != null ) { + if (!n && rh != null) { h = this.h = rh; index = this.index = 0; rh = null; @@ -170,20 +178,20 @@ private class StringMapKeysIterator { } public inline function next():String { - var r : String = untyped __forin__(h, nextIndex); + var r:String = untyped __forin__(h, nextIndex); index = nextIndex; - if( isReserved ) r = r.substr(1); + if (isReserved) + r = r.substr(1); return r; } - } @:allow(haxe.ds.StringMap) private class StringMapValuesIterator { var h:Dynamic; var rh:Dynamic; - var index : Int; - var nextIndex : Int; + var index:Int; + var nextIndex:Int; inline function new(h:Dynamic, rh:Dynamic):Void { this.h = h; @@ -195,7 +203,7 @@ private class StringMapValuesIterator { public inline function hasNext():Bool { var h = h, index = index; // tmp vars required for __has_next var n = untyped __has_next__(h, index); - if( !n && rh != null ) { + if (!n && rh != null) { h = this.h = rh; index = this.index = 0; rh = null; @@ -210,6 +218,5 @@ private class StringMapValuesIterator { index = nextIndex; return r; } - } #end diff --git a/std/flash/_std/haxe/ds/UnsafeStringMap.hx b/std/flash/_std/haxe/ds/UnsafeStringMap.hx index ead45139002..beec70259cc 100644 --- a/std/flash/_std/haxe/ds/UnsafeStringMap.hx +++ b/std/flash/_std/haxe/ds/UnsafeStringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; /** @@ -26,93 +27,97 @@ package haxe.ds; As a result, it will be faster to access the map for reading, but it might fail with some reserved keys such as `constructor` or `prototype`. **/ -class UnsafeStringMap implements haxe.Constraints.IMap { - - private var h : flash.utils.Dictionary; +class UnsafeStringMap implements haxe.Constraints.IMap { + private var h:flash.utils.Dictionary; - public function new() : Void { + public function new():Void { h = new flash.utils.Dictionary(); } - public inline function set( key : String, value : T ) : Void { + public inline function set(key:String, value:T):Void { untyped h[key] = value; } - public inline function get( key : String ) : Null { + public inline function get(key:String):Null { return untyped h[key]; } - public inline function exists( key : String ) : Bool { - return untyped __in__(key,h); + public inline function exists(key:String):Bool { + return untyped __in__(key, h); } - public function remove( key : String ) : Bool { - if( untyped !h.hasOwnProperty(key) ) return false; - untyped __delete__(h,key); + public function remove(key:String):Bool { + if (untyped !h.hasOwnProperty(key)) + return false; + untyped __delete__(h, key); return true; } #if as3 - // unoptimized version - - public function keys() : Iterator { + + public function keys():Iterator { return untyped (__keys__(h)).iterator(); } - public function iterator() : Iterator { + public function iterator():Iterator { return untyped { - ref : h, - it : __keys__(h).iterator(), - hasNext : function() { return __this__.it.hasNext(); }, - next : function() { var i : Dynamic = __this__.it.next(); return __this__.ref[i]; } + ref: h, + it: __keys__(h).iterator(), + hasNext: function() { + return __this__.it.hasNext(); + }, + next: function() { + var i:Dynamic = __this__.it.next(); + return __this__.ref[i]; + } }; } - #else - - public inline function keys() : Iterator { + public inline function keys():Iterator { return new UnsafeStringMapKeysIterator(h); } - public inline function iterator() : Iterator { + public inline function iterator():Iterator { return new UnsafeStringMapValuesIterator(h); } - #end - - public function copy() : UnsafeStringMap { + + public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():UnsafeStringMap { var copied = new UnsafeStringMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(i); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - } #if !as3 - // this version uses __has_next__/__forin__ special SWF opcodes for iteration with no allocation @:allow(haxe.ds.UnsafeStringMap) private class UnsafeStringMapKeysIterator { var h:flash.utils.Dictionary; - var index : Int; - var nextIndex : Int; + var index:Int; + var nextIndex:Int; inline function new(h:flash.utils.Dictionary):Void { this.h = h; @@ -128,18 +133,17 @@ private class UnsafeStringMapKeysIterator { } public inline function next():String { - var r : String = untyped __forin__(h, nextIndex); + var r:String = untyped __forin__(h, nextIndex); index = nextIndex; return r; } - } @:allow(haxe.ds.UnsafeStringMap) private class UnsafeStringMapValuesIterator { var h:flash.utils.Dictionary; - var index : Int; - var nextIndex : Int; + var index:Int; + var nextIndex:Int; inline function new(h:flash.utils.Dictionary):Void { this.h = h; @@ -159,6 +163,5 @@ private class UnsafeStringMapValuesIterator { index = nextIndex; return r; } - } #end diff --git a/std/flash/_std/haxe/ds/WeakMap.hx b/std/flash/_std/haxe/ds/WeakMap.hx index 7b5a205e119..6321af5edc9 100644 --- a/std/flash/_std/haxe/ds/WeakMap.hx +++ b/std/flash/_std/haxe/ds/WeakMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,67 +19,69 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package haxe.ds; -@:coreApi -class WeakMap extends flash.utils.Dictionary implements haxe.Constraints.IMap { +package haxe.ds; +@:coreApi +class WeakMap extends flash.utils.Dictionary implements haxe.Constraints.IMap { public function new() { super(true); } - public inline function get( key : K ) : Null { + public inline function get(key:K):Null { return untyped this[key]; } - public inline function set( key : K, value : V ):Void { + public inline function set(key:K, value:V):Void { untyped this[key] = value; } - public inline function exists( key : K ) : Bool { + public inline function exists(key:K):Bool { return untyped this[key] != null; } - public function remove( key : K ):Bool { + public function remove(key:K):Bool { var has = exists(key); untyped __delete__(this, key); return has; } #if as3 - - public function keys() : Iterator { + public function keys():Iterator { return untyped __keys__(this).iterator(); - } + } - public function iterator() : Iterator { + public function iterator():Iterator { var ret = []; for (i in keys()) ret.push(get(i)); return ret.iterator(); - } + } #else - - public function keys() : Iterator { + public function keys():Iterator { return NativePropertyIterator.iterator(this); } - public function iterator() : Iterator { + public function iterator():Iterator { return NativeValueIterator.iterator(this); } - #end - - public function copy() : WeakMap { + + public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():WeakMap { var copied = new WeakMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = ""; var it = keys(); - for( i in it ) { + for (i in it) { s += (s == "" ? "" : ",") + Std.string(i); s += " => "; s += Std.string(get(i)); @@ -87,6 +89,7 @@ class WeakMap extends flash.utils.Dictionary implements haxe.Constraints return s + "}"; } } + #if !as3 private class NativePropertyIterator { var collection:Dynamic; diff --git a/std/flash/_std/haxe/zip/Compress.hx b/std/flash/_std/haxe/zip/Compress.hx index 0efc61f610c..e706d9cb830 100644 --- a/std/flash/_std/haxe/zip/Compress.hx +++ b/std/flash/_std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,37 +19,36 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; @:coreApi class Compress { - - public function new( level : Int ) : Void { + public function new(level:Int):Void { throw "Not implemented for this platform"; } - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { return null; } - public function setFlushMode( f : FlushMode ) : Void { - } + public function setFlushMode(f:FlushMode):Void {} - public function close() : Void { - } + public function close():Void {} - public static function run( s : haxe.io.Bytes, level : Int ) : haxe.io.Bytes { - if( s.length == 0 ) { + public static function run(s:haxe.io.Bytes, level:Int):haxe.io.Bytes { + if (s.length == 0) { // Flash returns 0 bytes for 0 length compress (which can't be decoded on other platforms...) var b = haxe.io.Bytes.alloc(8); - b.set(0,0x78);b.set(1,0xDA);b.set(2,0x03); - b.set(7,0x01); + b.set(0, 0x78); + b.set(1, 0xDA); + b.set(2, 0x03); + b.set(7, 0x01); return b; } var tmp = new flash.utils.ByteArray(); - tmp.writeBytes(s.getData(),0,s.length); + tmp.writeBytes(s.getData(), 0, s.length); tmp.compress(); return haxe.io.Bytes.ofData(tmp); } - } diff --git a/std/flash/_std/haxe/zip/Uncompress.hx b/std/flash/_std/haxe/zip/Uncompress.hx index 2332fe9fbbb..4beec60143c 100644 --- a/std/flash/_std/haxe/zip/Uncompress.hx +++ b/std/flash/_std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,30 +19,27 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; @:coreApi class Uncompress { - - public function new( ?windowBits : Int ) : Void { + public function new(?windowBits:Int):Void { throw "Not implemented for this platform"; } - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { return null; } - public function setFlushMode( f : FlushMode ) : Void { - } + public function setFlushMode(f:FlushMode):Void {} - public function close() : Void { - } + public function close():Void {} - public static function run( src : haxe.io.Bytes, ?bufsize : Int ) : haxe.io.Bytes { + public static function run(src:haxe.io.Bytes, ?bufsize:Int):haxe.io.Bytes { var tmp = new flash.utils.ByteArray(); - tmp.writeBytes(src.getData(),0,src.length); + tmp.writeBytes(src.getData(), 0, src.length); tmp.uncompress(); return haxe.io.Bytes.ofData(tmp); } - } diff --git a/std/flash/accessibility/Accessibility.hx b/std/flash/accessibility/Accessibility.hx index 6df721c36bc..e7e67e54db1 100644 --- a/std/flash/accessibility/Accessibility.hx +++ b/std/flash/accessibility/Accessibility.hx @@ -1,7 +1,8 @@ package flash.accessibility; extern class Accessibility { - static var active(default,never) : Bool; + @:flash.property static var active(get,never) : Bool; + private static function get_active() : Bool; static function sendEvent(source : flash.display.DisplayObject, childID : UInt, eventType : UInt, nonHTML : Bool = false) : Void; static function updateProperties() : Void; } diff --git a/std/flash/accessibility/ISearchableText.hx b/std/flash/accessibility/ISearchableText.hx index 474dee6469c..976eca43203 100644 --- a/std/flash/accessibility/ISearchableText.hx +++ b/std/flash/accessibility/ISearchableText.hx @@ -1,5 +1,6 @@ package flash.accessibility; @:require(flash10_1) extern interface ISearchableText { - var searchText(default,never) : String; + @:flash.property var searchText(get,never) : String; + private function get_searchText() : String; } diff --git a/std/flash/accessibility/ISimpleTextSelection.hx b/std/flash/accessibility/ISimpleTextSelection.hx index 01b8c890d1c..3f32d93831b 100644 --- a/std/flash/accessibility/ISimpleTextSelection.hx +++ b/std/flash/accessibility/ISimpleTextSelection.hx @@ -1,6 +1,8 @@ package flash.accessibility; @:require(flash10_1) extern interface ISimpleTextSelection { - var selectionActiveIndex(default,never) : Int; - var selectionAnchorIndex(default,never) : Int; + @:flash.property var selectionActiveIndex(get,never) : Int; + @:flash.property var selectionAnchorIndex(get,never) : Int; + private function get_selectionActiveIndex() : Int; + private function get_selectionAnchorIndex() : Int; } diff --git a/std/flash/automation/AutomationAction.hx b/std/flash/automation/AutomationAction.hx index b7168866d7f..31e68d56fce 100644 --- a/std/flash/automation/AutomationAction.hx +++ b/std/flash/automation/AutomationAction.hx @@ -1,6 +1,8 @@ package flash.automation; @:require(flash10_1) extern class AutomationAction { - var type : String; + @:flash.property var type(get,set) : String; function new() : Void; + private function get_type() : String; + private function set_type(value : String) : String; } diff --git a/std/flash/automation/Configuration.hx b/std/flash/automation/Configuration.hx index 3bd1b84b205..dbc6a2a4d6b 100644 --- a/std/flash/automation/Configuration.hx +++ b/std/flash/automation/Configuration.hx @@ -1,6 +1,9 @@ package flash.automation; @:require(flash10_1) extern class Configuration { - static var deviceConfiguration : String; - static var testAutomationConfiguration(default,never) : String; + @:flash.property static var deviceConfiguration(get,set) : String; + @:flash.property static var testAutomationConfiguration(get,never) : String; + private static function get_deviceConfiguration() : String; + private static function get_testAutomationConfiguration() : String; + private static function set_deviceConfiguration(value : String) : String; } diff --git a/std/flash/automation/KeyboardAutomationAction.hx b/std/flash/automation/KeyboardAutomationAction.hx index ed5ca7b999b..4042474d7bf 100644 --- a/std/flash/automation/KeyboardAutomationAction.hx +++ b/std/flash/automation/KeyboardAutomationAction.hx @@ -1,8 +1,10 @@ package flash.automation; @:require(flash10_1) extern class KeyboardAutomationAction extends AutomationAction { - var keyCode : UInt; + @:flash.property var keyCode(get,set) : UInt; function new(type : String, keyCode : UInt = 0) : Void; - static var KEY_DOWN(default,never) : String; - static var KEY_UP(default,never) : String; + private function get_keyCode() : UInt; + private function set_keyCode(value : UInt) : UInt; + static final KEY_DOWN : String; + static final KEY_UP : String; } diff --git a/std/flash/automation/MouseAutomationAction.hx b/std/flash/automation/MouseAutomationAction.hx index 518b3520d70..260a7352c23 100644 --- a/std/flash/automation/MouseAutomationAction.hx +++ b/std/flash/automation/MouseAutomationAction.hx @@ -1,16 +1,22 @@ package flash.automation; @:require(flash10_1) extern class MouseAutomationAction extends AutomationAction { - var delta : Int; - var stageX : Float; - var stageY : Float; + @:flash.property var delta(get,set) : Int; + @:flash.property var stageX(get,set) : Float; + @:flash.property var stageY(get,set) : Float; function new(type : String, stageX : Float = 0, stageY : Float = 0, delta : Int = 0) : Void; - static var MIDDLE_MOUSE_DOWN(default,never) : String; - static var MIDDLE_MOUSE_UP(default,never) : String; - static var MOUSE_DOWN(default,never) : String; - static var MOUSE_MOVE(default,never) : String; - static var MOUSE_UP(default,never) : String; - static var MOUSE_WHEEL(default,never) : String; - static var RIGHT_MOUSE_DOWN(default,never) : String; - static var RIGHT_MOUSE_UP(default,never) : String; + private function get_delta() : Int; + private function get_stageX() : Float; + private function get_stageY() : Float; + private function set_delta(value : Int) : Int; + private function set_stageX(value : Float) : Float; + private function set_stageY(value : Float) : Float; + static final MIDDLE_MOUSE_DOWN : String; + static final MIDDLE_MOUSE_UP : String; + static final MOUSE_DOWN : String; + static final MOUSE_MOVE : String; + static final MOUSE_UP : String; + static final MOUSE_WHEEL : String; + static final RIGHT_MOUSE_DOWN : String; + static final RIGHT_MOUSE_UP : String; } diff --git a/std/flash/automation/StageCapture.hx b/std/flash/automation/StageCapture.hx index dfd58f2ac99..81aca8213cb 100644 --- a/std/flash/automation/StageCapture.hx +++ b/std/flash/automation/StageCapture.hx @@ -1,18 +1,26 @@ package flash.automation; @:require(flash10_1) extern class StageCapture extends flash.events.EventDispatcher { - var capturePTS : Float; - var captureSource : String; - var clipRect : flash.geom.Rectangle; - var fileNameBase : String; + @:flash.property var capturePTS(get,set) : Float; + @:flash.property var captureSource(get,set) : String; + @:flash.property var clipRect(get,set) : flash.geom.Rectangle; + @:flash.property var fileNameBase(get,set) : String; function new() : Void; function cancel() : Void; function capture(type : String) : Void; function captureBitmapData() : flash.display.BitmapData; - static var CURRENT(default,never) : String; - static var MULTIPLE(default,never) : String; - static var NEXT(default,never) : String; - static var RASTER(default,never) : String; - static var SCREEN(default,never) : String; - static var STAGE(default,never) : String; + private function get_capturePTS() : Float; + private function get_captureSource() : String; + private function get_clipRect() : flash.geom.Rectangle; + private function get_fileNameBase() : String; + private function set_capturePTS(value : Float) : Float; + private function set_captureSource(value : String) : String; + private function set_clipRect(value : flash.geom.Rectangle) : flash.geom.Rectangle; + private function set_fileNameBase(value : String) : String; + static final CURRENT : String; + static final MULTIPLE : String; + static final NEXT : String; + static final RASTER : String; + static final SCREEN : String; + static final STAGE : String; } diff --git a/std/flash/automation/StageCaptureEvent.hx b/std/flash/automation/StageCaptureEvent.hx index c02222660ac..dd0158ac347 100644 --- a/std/flash/automation/StageCaptureEvent.hx +++ b/std/flash/automation/StageCaptureEvent.hx @@ -1,9 +1,12 @@ package flash.automation; @:require(flash10_1) extern class StageCaptureEvent extends flash.events.Event { - var checksum(default,never) : UInt; - var pts(default,never) : Float; - var url(default,never) : String; + @:flash.property var checksum(get,never) : UInt; + @:flash.property var pts(get,never) : Float; + @:flash.property var url(get,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?url : String, checksum : UInt = 0, pts : Float = 0) : Void; - static var CAPTURE(default,never) : String; + private function get_checksum() : UInt; + private function get_pts() : Float; + private function get_url() : String; + static final CAPTURE : String; } diff --git a/std/flash/concurrent/Condition.hx b/std/flash/concurrent/Condition.hx index 66316fcbbca..3d9dcda8087 100644 --- a/std/flash/concurrent/Condition.hx +++ b/std/flash/concurrent/Condition.hx @@ -1,10 +1,12 @@ package flash.concurrent; -@:final @:require(flash11_4) extern class Condition { - var mutex(default,never) : Mutex; +@:require(flash11_4) extern final class Condition { + @:flash.property var mutex(get,never) : Mutex; function new(mutex : Mutex) : Void; + private function get_mutex() : Mutex; function notify() : Void; function notifyAll() : Void; function wait(timeout : Float = -1) : Bool; - static var isSupported(default,never) : Bool; + @:flash.property static var isSupported(get,never) : Bool; + private static function get_isSupported() : Bool; } diff --git a/std/flash/concurrent/Mutex.hx b/std/flash/concurrent/Mutex.hx index 45fed1f6a90..db500056600 100644 --- a/std/flash/concurrent/Mutex.hx +++ b/std/flash/concurrent/Mutex.hx @@ -1,9 +1,10 @@ package flash.concurrent; -@:final @:require(flash11_4) extern class Mutex { +@:require(flash11_4) extern final class Mutex { function new() : Void; function lock() : Void; function tryLock() : Bool; function unlock() : Void; - static var isSupported(default,never) : Bool; + @:flash.property static var isSupported(get,never) : Bool; + private static function get_isSupported() : Bool; } diff --git a/std/flash/desktop/Clipboard.hx b/std/flash/desktop/Clipboard.hx index 1b5dad0d841..6fba4c517d4 100644 --- a/std/flash/desktop/Clipboard.hx +++ b/std/flash/desktop/Clipboard.hx @@ -1,12 +1,14 @@ package flash.desktop; @:require(flash10) extern class Clipboard { - var formats(default,never) : Array; + @:flash.property var formats(get,never) : Array; function clear() : Void; function clearData(format : ClipboardFormats) : Void; function getData(format : ClipboardFormats, ?transferMode : ClipboardTransferMode) : flash.utils.Object; + private function get_formats() : Array; function hasFormat(format : ClipboardFormats) : Bool; function setData(format : ClipboardFormats, data : flash.utils.Object, serializable : Bool = true) : Bool; function setDataHandler(format : ClipboardFormats, handler : flash.utils.Function, serializable : Bool = true) : Bool; - static var generalClipboard(default,never) : Clipboard; + @:flash.property static var generalClipboard(get,never) : Clipboard; + private static function get_generalClipboard() : Clipboard; } diff --git a/std/flash/desktop/ClipboardFormats.hx b/std/flash/desktop/ClipboardFormats.hx index f5f715fa10f..3f6e0b1aff7 100644 --- a/std/flash/desktop/ClipboardFormats.hx +++ b/std/flash/desktop/ClipboardFormats.hx @@ -1,15 +1,15 @@ package flash.desktop; -@:fakeEnum(String) @:require(flash10) extern enum ClipboardFormats { - AIR_PREFIX; - BITMAP_FORMAT; - FILE_LIST_FORMAT; - FILE_PROMISE_LIST_FORMAT; - FLASH_PREFIX; - HTML_FORMAT; - REFERENCE_PREFIX; - RICH_TEXT_FORMAT; - SERIALIZATION_PREFIX; - TEXT_FORMAT; - URL_FORMAT; +@:native("flash.desktop.ClipboardFormats") @:require(flash10) extern enum abstract ClipboardFormats(String) { + var AIR_PREFIX; + var BITMAP_FORMAT; + var FILE_LIST_FORMAT; + var FILE_PROMISE_LIST_FORMAT; + var FLASH_PREFIX; + var HTML_FORMAT; + var REFERENCE_PREFIX; + var RICH_TEXT_FORMAT; + var SERIALIZATION_PREFIX; + var TEXT_FORMAT; + var URL_FORMAT; } diff --git a/std/flash/desktop/ClipboardTransferMode.hx b/std/flash/desktop/ClipboardTransferMode.hx index c76f81bd568..52c05ddb691 100644 --- a/std/flash/desktop/ClipboardTransferMode.hx +++ b/std/flash/desktop/ClipboardTransferMode.hx @@ -1,8 +1,8 @@ package flash.desktop; -@:fakeEnum(String) @:require(flash10) extern enum ClipboardTransferMode { - CLONE_ONLY; - CLONE_PREFERRED; - ORIGINAL_ONLY; - ORIGINAL_PREFERRED; +@:native("flash.desktop.ClipboardTransferMode") @:require(flash10) extern enum abstract ClipboardTransferMode(String) { + var CLONE_ONLY; + var CLONE_PREFERRED; + var ORIGINAL_ONLY; + var ORIGINAL_PREFERRED; } diff --git a/std/flash/display/AVM1Movie.hx b/std/flash/display/AVM1Movie.hx index 32944ad0ebb..f035bb6eb70 100644 --- a/std/flash/display/AVM1Movie.hx +++ b/std/flash/display/AVM1Movie.hx @@ -3,5 +3,5 @@ package flash.display; extern class AVM1Movie extends DisplayObject { function new() : Void; function addCallback(functionName : String, closure : flash.utils.Function) : Void; - function call(functionName : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Dynamic; + function call(functionName : String, restArgs : haxe.extern.Rest) : Dynamic; } diff --git a/std/flash/display/ActionScriptVersion.hx b/std/flash/display/ActionScriptVersion.hx index 02e538336a1..497b372835b 100644 --- a/std/flash/display/ActionScriptVersion.hx +++ b/std/flash/display/ActionScriptVersion.hx @@ -1,6 +1,6 @@ package flash.display; -@:fakeEnum(UInt) extern enum ActionScriptVersion { - ACTIONSCRIPT2; - ACTIONSCRIPT3; +@:native("flash.display.ActionScriptVersion") extern enum abstract ActionScriptVersion(UInt) { + var ACTIONSCRIPT2; + var ACTIONSCRIPT3; } diff --git a/std/flash/display/Bitmap.hx b/std/flash/display/Bitmap.hx index ff8101a474b..b32e9aad7ac 100644 --- a/std/flash/display/Bitmap.hx +++ b/std/flash/display/Bitmap.hx @@ -1,8 +1,14 @@ package flash.display; extern class Bitmap extends DisplayObject { - var bitmapData : BitmapData; - var pixelSnapping : PixelSnapping; - var smoothing : Bool; + @:flash.property var bitmapData(get,set) : BitmapData; + @:flash.property var pixelSnapping(get,set) : PixelSnapping; + @:flash.property var smoothing(get,set) : Bool; function new(?bitmapData : BitmapData, ?pixelSnapping : PixelSnapping, smoothing : Bool = false) : Void; + private function get_bitmapData() : BitmapData; + private function get_pixelSnapping() : PixelSnapping; + private function get_smoothing() : Bool; + private function set_bitmapData(value : BitmapData) : BitmapData; + private function set_pixelSnapping(value : PixelSnapping) : PixelSnapping; + private function set_smoothing(value : Bool) : Bool; } diff --git a/std/flash/display/BitmapCompressColorSpace.hx b/std/flash/display/BitmapCompressColorSpace.hx index 6d0252c159b..956e78f2a06 100644 --- a/std/flash/display/BitmapCompressColorSpace.hx +++ b/std/flash/display/BitmapCompressColorSpace.hx @@ -1,9 +1,8 @@ package flash.display; -@:fakeEnum(String) -enum BitmapCompressColorSpace { - COLORSPACE_4_2_0; - COLORSPACE_4_2_2; - COLORSPACE_4_4_4; - COLORSPACE_AUTO; +@:native("flash.display.BitmapCompressColorSpace") extern enum abstract BitmapCompressColorSpace(String) { + var COLORSPACE_4_2_0; + var COLORSPACE_4_2_2; + var COLORSPACE_4_4_4; + var COLORSPACE_AUTO; } diff --git a/std/flash/display/BitmapData.hx b/std/flash/display/BitmapData.hx index 2f100402640..3b7788f0290 100644 --- a/std/flash/display/BitmapData.hx +++ b/std/flash/display/BitmapData.hx @@ -1,10 +1,10 @@ package flash.display; extern class BitmapData implements IBitmapDrawable { - var height(default,never) : Int; - var rect(default,never) : flash.geom.Rectangle; - var transparent(default,never) : Bool; - var width(default,never) : Int; + @:flash.property var height(get,never) : Int; + @:flash.property var rect(get,never) : flash.geom.Rectangle; + @:flash.property var transparent(get,never) : Bool; + @:flash.property var width(get,never) : Int; function new(width : Int, height : Int, transparent : Bool = true, fillColor : UInt = 0xFFFFFFFF) : Void; function applyFilter(sourceBitmapData : BitmapData, sourceRect : flash.geom.Rectangle, destPoint : flash.geom.Point, filter : flash.filters.BitmapFilter) : Void; function clone() : BitmapData; @@ -25,6 +25,10 @@ extern class BitmapData implements IBitmapDrawable { function getPixel32(x : Int, y : Int) : UInt; function getPixels(rect : flash.geom.Rectangle) : flash.utils.ByteArray; @:require(flash10) function getVector(rect : flash.geom.Rectangle) : flash.Vector; + private function get_height() : Int; + private function get_rect() : flash.geom.Rectangle; + private function get_transparent() : Bool; + private function get_width() : Int; @:require(flash10) function histogram(?hRect : flash.geom.Rectangle) : flash.Vector>; function hitTest(firstPoint : flash.geom.Point, firstAlphaThreshold : UInt, secondObject : flash.utils.Object, ?secondBitmapDataPoint : flash.geom.Point, secondAlphaThreshold : UInt = 1) : Bool; function lock() : Void; diff --git a/std/flash/display/BitmapEncodingColorSpace.hx b/std/flash/display/BitmapEncodingColorSpace.hx index d6e53276901..5090d839236 100644 --- a/std/flash/display/BitmapEncodingColorSpace.hx +++ b/std/flash/display/BitmapEncodingColorSpace.hx @@ -1,8 +1,8 @@ package flash.display; -@:fakeEnum(String) extern enum BitmapEncodingColorSpace { - COLORSPACE_4_2_0; - COLORSPACE_4_2_2; - COLORSPACE_4_4_4; - COLORSPACE_AUTO; +@:native("flash.display.BitmapEncodingColorSpace") extern enum abstract BitmapEncodingColorSpace(String) { + var COLORSPACE_4_2_0; + var COLORSPACE_4_2_2; + var COLORSPACE_4_4_4; + var COLORSPACE_AUTO; } diff --git a/std/flash/display/BlendMode.hx b/std/flash/display/BlendMode.hx index 61ef16414f2..d1b0031fbce 100644 --- a/std/flash/display/BlendMode.hx +++ b/std/flash/display/BlendMode.hx @@ -1,19 +1,19 @@ package flash.display; -@:fakeEnum(String) extern enum BlendMode { - ADD; - ALPHA; - DARKEN; - DIFFERENCE; - ERASE; - HARDLIGHT; - INVERT; - LAYER; - LIGHTEN; - MULTIPLY; - NORMAL; - OVERLAY; - SCREEN; - SHADER; - SUBTRACT; +@:native("flash.display.BlendMode") extern enum abstract BlendMode(String) { + var ADD; + var ALPHA; + var DARKEN; + var DIFFERENCE; + var ERASE; + var HARDLIGHT; + var INVERT; + var LAYER; + var LIGHTEN; + var MULTIPLY; + var NORMAL; + var OVERLAY; + var SCREEN; + var SHADER; + var SUBTRACT; } diff --git a/std/flash/display/CapsStyle.hx b/std/flash/display/CapsStyle.hx index 1b67b499d78..e173e1791dc 100644 --- a/std/flash/display/CapsStyle.hx +++ b/std/flash/display/CapsStyle.hx @@ -1,7 +1,7 @@ package flash.display; -@:fakeEnum(String) extern enum CapsStyle { - NONE; - ROUND; - SQUARE; +@:native("flash.display.CapsStyle") extern enum abstract CapsStyle(String) { + var NONE; + var ROUND; + var SQUARE; } diff --git a/std/flash/display/ColorCorrection.hx b/std/flash/display/ColorCorrection.hx index 57b7f30fe16..6c48b6279d1 100644 --- a/std/flash/display/ColorCorrection.hx +++ b/std/flash/display/ColorCorrection.hx @@ -1,7 +1,7 @@ package flash.display; -@:fakeEnum(String) @:require(flash10_1) extern enum ColorCorrection { - DEFAULT; - OFF; - ON; +@:native("flash.display.ColorCorrection") @:require(flash10_1) extern enum abstract ColorCorrection(String) { + var DEFAULT; + var OFF; + var ON; } diff --git a/std/flash/display/ColorCorrectionSupport.hx b/std/flash/display/ColorCorrectionSupport.hx index 173712f1c10..f4aa3acbc84 100644 --- a/std/flash/display/ColorCorrectionSupport.hx +++ b/std/flash/display/ColorCorrectionSupport.hx @@ -1,7 +1,7 @@ package flash.display; -@:fakeEnum(String) @:require(flash10_1) extern enum ColorCorrectionSupport { - DEFAULT_OFF; - DEFAULT_ON; - UNSUPPORTED; +@:native("flash.display.ColorCorrectionSupport") @:require(flash10_1) extern enum abstract ColorCorrectionSupport(String) { + var DEFAULT_OFF; + var DEFAULT_ON; + var UNSUPPORTED; } diff --git a/std/flash/display/DisplayObject.hx b/std/flash/display/DisplayObject.hx index 639e08a65cb..b140f2a2dd2 100644 --- a/std/flash/display/DisplayObject.hx +++ b/std/flash/display/DisplayObject.hx @@ -1,43 +1,100 @@ package flash.display; extern class DisplayObject extends flash.events.EventDispatcher implements IBitmapDrawable { - var accessibilityProperties : flash.accessibility.AccessibilityProperties; - var alpha : Float; - var blendMode : BlendMode; - @:require(flash10) var blendShader(never,default) : Shader; - var cacheAsBitmap : Bool; - var filters : Array; - var height : Float; - var loaderInfo(default,never) : LoaderInfo; - var mask : DisplayObject; - var mouseX(default,never) : Float; - var mouseY(default,never) : Float; - var name : String; - var opaqueBackground : Null; - var parent(default,never) : DisplayObjectContainer; - var root(default,never) : DisplayObject; - var rotation : Float; - @:require(flash10) var rotationX : Float; - @:require(flash10) var rotationY : Float; - @:require(flash10) var rotationZ : Float; - var scale9Grid : flash.geom.Rectangle; - var scaleX : Float; - var scaleY : Float; - @:require(flash10) var scaleZ : Float; - var scrollRect : flash.geom.Rectangle; - var stage(default,never) : Stage; - var transform : flash.geom.Transform; - var visible : Bool; - var width : Float; - var x : Float; - var y : Float; - @:require(flash10) var z : Float; + @:flash.property var accessibilityProperties(get,set) : flash.accessibility.AccessibilityProperties; + @:flash.property var alpha(get,set) : Float; + @:flash.property var blendMode(get,set) : BlendMode; + @:flash.property @:require(flash10) var blendShader(never,set) : Shader; + @:flash.property var cacheAsBitmap(get,set) : Bool; + @:flash.property var filters(get,set) : Array; + @:flash.property var height(get,set) : Float; + @:flash.property var loaderInfo(get,never) : LoaderInfo; + @:flash.property var mask(get,set) : DisplayObject; + @:flash.property var mouseX(get,never) : Float; + @:flash.property var mouseY(get,never) : Float; + @:flash.property var name(get,set) : String; + @:flash.property var opaqueBackground(get,set) : Null; + @:flash.property var parent(get,never) : DisplayObjectContainer; + @:flash.property var root(get,never) : DisplayObject; + @:flash.property var rotation(get,set) : Float; + @:flash.property @:require(flash10) var rotationX(get,set) : Float; + @:flash.property @:require(flash10) var rotationY(get,set) : Float; + @:flash.property @:require(flash10) var rotationZ(get,set) : Float; + @:flash.property var scale9Grid(get,set) : flash.geom.Rectangle; + @:flash.property var scaleX(get,set) : Float; + @:flash.property var scaleY(get,set) : Float; + @:flash.property @:require(flash10) var scaleZ(get,set) : Float; + @:flash.property var scrollRect(get,set) : flash.geom.Rectangle; + @:flash.property var stage(get,never) : Stage; + @:flash.property var transform(get,set) : flash.geom.Transform; + @:flash.property var visible(get,set) : Bool; + @:flash.property var width(get,set) : Float; + @:flash.property var x(get,set) : Float; + @:flash.property var y(get,set) : Float; + @:flash.property @:require(flash10) var z(get,set) : Float; function getBounds(targetCoordinateSpace : DisplayObject) : flash.geom.Rectangle; function getRect(targetCoordinateSpace : DisplayObject) : flash.geom.Rectangle; + private function get_accessibilityProperties() : flash.accessibility.AccessibilityProperties; + private function get_alpha() : Float; + private function get_blendMode() : BlendMode; + private function get_cacheAsBitmap() : Bool; + private function get_filters() : Array; + private function get_height() : Float; + private function get_loaderInfo() : LoaderInfo; + private function get_mask() : DisplayObject; + private function get_metaData() : Dynamic; + private function get_mouseX() : Float; + private function get_mouseY() : Float; + private function get_name() : String; + private function get_opaqueBackground() : Null; + private function get_parent() : DisplayObjectContainer; + private function get_root() : DisplayObject; + private function get_rotation() : Float; + private function get_rotationX() : Float; + private function get_rotationY() : Float; + private function get_rotationZ() : Float; + private function get_scale9Grid() : flash.geom.Rectangle; + private function get_scaleX() : Float; + private function get_scaleY() : Float; + private function get_scaleZ() : Float; + private function get_scrollRect() : flash.geom.Rectangle; + private function get_stage() : Stage; + private function get_transform() : flash.geom.Transform; + private function get_visible() : Bool; + private function get_width() : Float; + private function get_x() : Float; + private function get_y() : Float; + private function get_z() : Float; function globalToLocal(point : flash.geom.Point) : flash.geom.Point; @:require(flash10) function globalToLocal3D(point : flash.geom.Point) : flash.geom.Vector3D; function hitTestObject(obj : DisplayObject) : Bool; function hitTestPoint(x : Float, y : Float, shapeFlag : Bool = false) : Bool; @:require(flash10) function local3DToGlobal(point3d : flash.geom.Vector3D) : flash.geom.Point; function localToGlobal(point : flash.geom.Point) : flash.geom.Point; + private function set_accessibilityProperties(value : flash.accessibility.AccessibilityProperties) : flash.accessibility.AccessibilityProperties; + private function set_alpha(value : Float) : Float; + private function set_blendMode(value : BlendMode) : BlendMode; + private function set_blendShader(value : Shader) : Shader; + private function set_cacheAsBitmap(value : Bool) : Bool; + private function set_filters(value : Array) : Array; + private function set_height(value : Float) : Float; + private function set_mask(value : DisplayObject) : DisplayObject; + private function set_metaData(value : Dynamic) : Dynamic; + private function set_name(value : String) : String; + private function set_opaqueBackground(value : Null) : Null; + private function set_rotation(value : Float) : Float; + private function set_rotationX(value : Float) : Float; + private function set_rotationY(value : Float) : Float; + private function set_rotationZ(value : Float) : Float; + private function set_scale9Grid(value : flash.geom.Rectangle) : flash.geom.Rectangle; + private function set_scaleX(value : Float) : Float; + private function set_scaleY(value : Float) : Float; + private function set_scaleZ(value : Float) : Float; + private function set_scrollRect(value : flash.geom.Rectangle) : flash.geom.Rectangle; + private function set_transform(value : flash.geom.Transform) : flash.geom.Transform; + private function set_visible(value : Bool) : Bool; + private function set_width(value : Float) : Float; + private function set_x(value : Float) : Float; + private function set_y(value : Float) : Float; + private function set_z(value : Float) : Float; } diff --git a/std/flash/display/DisplayObjectContainer.hx b/std/flash/display/DisplayObjectContainer.hx index deb49ed2832..cd11f78eb71 100644 --- a/std/flash/display/DisplayObjectContainer.hx +++ b/std/flash/display/DisplayObjectContainer.hx @@ -1,10 +1,10 @@ package flash.display; extern class DisplayObjectContainer extends InteractiveObject { - var mouseChildren : Bool; - var numChildren(default,never) : Int; - var tabChildren : Bool; - var textSnapshot(default,never) : flash.text.TextSnapshot; + @:flash.property var mouseChildren(get,set) : Bool; + @:flash.property var numChildren(get,never) : Int; + @:flash.property var tabChildren(get,set) : Bool; + @:flash.property var textSnapshot(get,never) : flash.text.TextSnapshot; function new() : Void; function addChild(child : DisplayObject) : DisplayObject; function addChildAt(child : DisplayObject, index : Int) : DisplayObject; @@ -14,10 +14,16 @@ extern class DisplayObjectContainer extends InteractiveObject { function getChildByName(name : String) : DisplayObject; function getChildIndex(child : DisplayObject) : Int; function getObjectsUnderPoint(point : flash.geom.Point) : Array; + private function get_mouseChildren() : Bool; + private function get_numChildren() : Int; + private function get_tabChildren() : Bool; + private function get_textSnapshot() : flash.text.TextSnapshot; function removeChild(child : DisplayObject) : DisplayObject; function removeChildAt(index : Int) : DisplayObject; @:require(flash11) function removeChildren(beginIndex : Int = 0, endIndex : Int = 2147483647) : Void; function setChildIndex(child : DisplayObject, index : Int) : Void; + private function set_mouseChildren(value : Bool) : Bool; + private function set_tabChildren(value : Bool) : Bool; @:require(flash11_8) function stopAllMovieClips() : Void; function swapChildren(child1 : DisplayObject, child2 : DisplayObject) : Void; function swapChildrenAt(index1 : Int, index2 : Int) : Void; diff --git a/std/flash/display/FocusDirection.hx b/std/flash/display/FocusDirection.hx index ee490e3a2c7..b36d567cd56 100644 --- a/std/flash/display/FocusDirection.hx +++ b/std/flash/display/FocusDirection.hx @@ -1,7 +1,7 @@ package flash.display; -@:fakeEnum(String) @:require(flash10_1) extern enum FocusDirection { - BOTTOM; - NONE; - TOP; +@:native("flash.display.FocusDirection") @:require(flash10_1) extern enum abstract FocusDirection(String) { + var BOTTOM; + var NONE; + var TOP; } diff --git a/std/flash/display/FrameLabel.hx b/std/flash/display/FrameLabel.hx index 605633657d3..bf56c1903d5 100644 --- a/std/flash/display/FrameLabel.hx +++ b/std/flash/display/FrameLabel.hx @@ -1,7 +1,9 @@ package flash.display; -@:final extern class FrameLabel extends flash.events.EventDispatcher { - var frame(default,never) : Int; - var name(default,never) : String; +extern final class FrameLabel extends flash.events.EventDispatcher { + @:flash.property var frame(get,never) : Int; + @:flash.property var name(get,never) : String; function new(name : String, frame : Int) : Void; + private function get_frame() : Int; + private function get_name() : String; } diff --git a/std/flash/display/GradientType.hx b/std/flash/display/GradientType.hx index 12bd8362903..d488c60643e 100644 --- a/std/flash/display/GradientType.hx +++ b/std/flash/display/GradientType.hx @@ -1,6 +1,6 @@ package flash.display; -@:fakeEnum(String) extern enum GradientType { - LINEAR; - RADIAL; +@:native("flash.display.GradientType") extern enum abstract GradientType(String) { + var LINEAR; + var RADIAL; } diff --git a/std/flash/display/Graphics.hx b/std/flash/display/Graphics.hx index eaa237b370a..23d3ac29106 100644 --- a/std/flash/display/Graphics.hx +++ b/std/flash/display/Graphics.hx @@ -1,6 +1,6 @@ package flash.display; -@:final extern class Graphics { +extern final class Graphics { function new() : Void; function beginBitmapFill(bitmap : BitmapData, ?matrix : flash.geom.Matrix, repeat : Bool = true, smooth : Bool = false) : Void; function beginFill(color : UInt, alpha : Float = 1) : Void; diff --git a/std/flash/display/GraphicsBitmapFill.hx b/std/flash/display/GraphicsBitmapFill.hx index 11213bb27cd..b42a39f983b 100644 --- a/std/flash/display/GraphicsBitmapFill.hx +++ b/std/flash/display/GraphicsBitmapFill.hx @@ -1,6 +1,6 @@ package flash.display; -@:final extern class GraphicsBitmapFill implements IGraphicsData implements IGraphicsFill { +extern final class GraphicsBitmapFill implements IGraphicsData implements IGraphicsFill { var bitmapData : BitmapData; var matrix : flash.geom.Matrix; var repeat : Bool; diff --git a/std/flash/display/GraphicsGradientFill.hx b/std/flash/display/GraphicsGradientFill.hx index 9c19c9a11c1..fa87f8c41ad 100644 --- a/std/flash/display/GraphicsGradientFill.hx +++ b/std/flash/display/GraphicsGradientFill.hx @@ -1,13 +1,19 @@ package flash.display; -@:final extern class GraphicsGradientFill implements IGraphicsData implements IGraphicsFill { +extern final class GraphicsGradientFill implements IGraphicsData implements IGraphicsFill { var alphas : Array; var colors : Array; var focalPointRatio : Float; - var interpolationMethod : InterpolationMethod; + @:flash.property var interpolationMethod(get,set) : InterpolationMethod; var matrix : flash.geom.Matrix; var ratios : Array; - var spreadMethod : SpreadMethod; - var type : GradientType; + @:flash.property var spreadMethod(get,set) : SpreadMethod; + @:flash.property var type(get,set) : GradientType; function new(?type : GradientType, ?colors : Array, ?alphas : Array, ?ratios : Array, ?matrix : flash.geom.Matrix, ?spreadMethod : SpreadMethod, ?interpolationMethod : InterpolationMethod, focalPointRatio : Float = 0) : Void; + private function get_interpolationMethod() : InterpolationMethod; + private function get_spreadMethod() : SpreadMethod; + private function get_type() : GradientType; + private function set_interpolationMethod(value : InterpolationMethod) : InterpolationMethod; + private function set_spreadMethod(value : SpreadMethod) : SpreadMethod; + private function set_type(value : GradientType) : GradientType; } diff --git a/std/flash/display/GraphicsPath.hx b/std/flash/display/GraphicsPath.hx index 7d016f25d27..568c2d28830 100644 --- a/std/flash/display/GraphicsPath.hx +++ b/std/flash/display/GraphicsPath.hx @@ -1,14 +1,16 @@ package flash.display; -@:final extern class GraphicsPath implements IGraphicsData implements IGraphicsPath { +extern final class GraphicsPath implements IGraphicsData implements IGraphicsPath { var commands : flash.Vector; var data : flash.Vector; - var winding : GraphicsPathWinding; + @:flash.property var winding(get,set) : GraphicsPathWinding; function new(?commands : flash.Vector, ?data : flash.Vector, ?winding : GraphicsPathWinding) : Void; @:require(flash11) function cubicCurveTo(controlX1 : Float, controlY1 : Float, controlX2 : Float, controlY2 : Float, anchorX : Float, anchorY : Float) : Void; function curveTo(controlX : Float, controlY : Float, anchorX : Float, anchorY : Float) : Void; + private function get_winding() : GraphicsPathWinding; function lineTo(x : Float, y : Float) : Void; function moveTo(x : Float, y : Float) : Void; + private function set_winding(value : GraphicsPathWinding) : GraphicsPathWinding; function wideLineTo(x : Float, y : Float) : Void; function wideMoveTo(x : Float, y : Float) : Void; } diff --git a/std/flash/display/GraphicsPathWinding.hx b/std/flash/display/GraphicsPathWinding.hx index 05295d58d77..ec3eb013aa4 100644 --- a/std/flash/display/GraphicsPathWinding.hx +++ b/std/flash/display/GraphicsPathWinding.hx @@ -1,6 +1,6 @@ package flash.display; -@:fakeEnum(String) extern enum GraphicsPathWinding { - EVEN_ODD; - NON_ZERO; +@:native("flash.display.GraphicsPathWinding") extern enum abstract GraphicsPathWinding(String) { + var EVEN_ODD; + var NON_ZERO; } diff --git a/std/flash/display/GraphicsShaderFill.hx b/std/flash/display/GraphicsShaderFill.hx index e715f8d8047..7878a00fc33 100644 --- a/std/flash/display/GraphicsShaderFill.hx +++ b/std/flash/display/GraphicsShaderFill.hx @@ -1,6 +1,6 @@ package flash.display; -@:final extern class GraphicsShaderFill implements IGraphicsData implements IGraphicsFill { +extern final class GraphicsShaderFill implements IGraphicsData implements IGraphicsFill { var matrix : flash.geom.Matrix; var shader : Shader; function new(?shader : Shader, ?matrix : flash.geom.Matrix) : Void; diff --git a/std/flash/display/GraphicsSolidFill.hx b/std/flash/display/GraphicsSolidFill.hx index e59208bd7e3..462f7c66d8a 100644 --- a/std/flash/display/GraphicsSolidFill.hx +++ b/std/flash/display/GraphicsSolidFill.hx @@ -1,6 +1,6 @@ package flash.display; -@:final extern class GraphicsSolidFill implements IGraphicsData implements IGraphicsFill { +extern final class GraphicsSolidFill implements IGraphicsData implements IGraphicsFill { var alpha : Float; var color : UInt; function new(color : UInt = 0, alpha : Float = 1) : Void; diff --git a/std/flash/display/GraphicsStroke.hx b/std/flash/display/GraphicsStroke.hx index fe0c7fde1f4..4ca9edab295 100644 --- a/std/flash/display/GraphicsStroke.hx +++ b/std/flash/display/GraphicsStroke.hx @@ -1,12 +1,18 @@ package flash.display; -@:final extern class GraphicsStroke implements IGraphicsData implements IGraphicsStroke { - var caps : CapsStyle; +extern final class GraphicsStroke implements IGraphicsData implements IGraphicsStroke { + @:flash.property var caps(get,set) : CapsStyle; var fill : IGraphicsFill; - var joints : JointStyle; + @:flash.property var joints(get,set) : JointStyle; var miterLimit : Float; var pixelHinting : Bool; - var scaleMode : LineScaleMode; + @:flash.property var scaleMode(get,set) : LineScaleMode; var thickness : Float; function new(thickness : Float = 0./*NaN*/, pixelHinting : Bool = false, ?scaleMode : LineScaleMode, ?caps : CapsStyle, ?joints : JointStyle, miterLimit : Float = 3, ?fill : IGraphicsFill) : Void; + private function get_caps() : CapsStyle; + private function get_joints() : JointStyle; + private function get_scaleMode() : LineScaleMode; + private function set_caps(value : CapsStyle) : CapsStyle; + private function set_joints(value : JointStyle) : JointStyle; + private function set_scaleMode(value : LineScaleMode) : LineScaleMode; } diff --git a/std/flash/display/GraphicsTrianglePath.hx b/std/flash/display/GraphicsTrianglePath.hx index 9bc48048903..39a56b06cd1 100644 --- a/std/flash/display/GraphicsTrianglePath.hx +++ b/std/flash/display/GraphicsTrianglePath.hx @@ -1,9 +1,11 @@ package flash.display; -@:final extern class GraphicsTrianglePath implements IGraphicsData implements IGraphicsPath { - var culling : TriangleCulling; +extern final class GraphicsTrianglePath implements IGraphicsData implements IGraphicsPath { + @:flash.property var culling(get,set) : TriangleCulling; var indices : flash.Vector; var uvtData : flash.Vector; var vertices : flash.Vector; function new(?vertices : flash.Vector, ?indices : flash.Vector, ?uvtData : flash.Vector, ?culling : TriangleCulling) : Void; + private function get_culling() : TriangleCulling; + private function set_culling(value : TriangleCulling) : TriangleCulling; } diff --git a/std/flash/display/InteractiveObject.hx b/std/flash/display/InteractiveObject.hx index 6218ae86194..8ab1f7177ba 100644 --- a/std/flash/display/InteractiveObject.hx +++ b/std/flash/display/InteractiveObject.hx @@ -1,15 +1,33 @@ package flash.display; extern class InteractiveObject extends DisplayObject { - var accessibilityImplementation : flash.accessibility.AccessibilityImplementation; - var contextMenu : flash.ui.ContextMenu; - var doubleClickEnabled : Bool; - var focusRect : Dynamic; - var mouseEnabled : Bool; - @:require(flash11) var needsSoftKeyboard : Bool; - @:require(flash11) var softKeyboardInputAreaOfInterest : flash.geom.Rectangle; - var tabEnabled : Bool; - var tabIndex : Int; + @:flash.property var accessibilityImplementation(get,set) : flash.accessibility.AccessibilityImplementation; + @:flash.property var contextMenu(get,set) : flash.ui.ContextMenu; + @:flash.property var doubleClickEnabled(get,set) : Bool; + @:flash.property var focusRect(get,set) : Dynamic; + @:flash.property var mouseEnabled(get,set) : Bool; + @:flash.property @:require(flash11) var needsSoftKeyboard(get,set) : Bool; + @:flash.property @:require(flash11) var softKeyboardInputAreaOfInterest(get,set) : flash.geom.Rectangle; + @:flash.property var tabEnabled(get,set) : Bool; + @:flash.property var tabIndex(get,set) : Int; function new() : Void; + private function get_accessibilityImplementation() : flash.accessibility.AccessibilityImplementation; + private function get_contextMenu() : flash.ui.ContextMenu; + private function get_doubleClickEnabled() : Bool; + private function get_focusRect() : Dynamic; + private function get_mouseEnabled() : Bool; + private function get_needsSoftKeyboard() : Bool; + private function get_softKeyboardInputAreaOfInterest() : flash.geom.Rectangle; + private function get_tabEnabled() : Bool; + private function get_tabIndex() : Int; @:require(flash11) function requestSoftKeyboard() : Bool; + private function set_accessibilityImplementation(value : flash.accessibility.AccessibilityImplementation) : flash.accessibility.AccessibilityImplementation; + private function set_contextMenu(value : flash.ui.ContextMenu) : flash.ui.ContextMenu; + private function set_doubleClickEnabled(value : Bool) : Bool; + private function set_focusRect(value : Dynamic) : Dynamic; + private function set_mouseEnabled(value : Bool) : Bool; + private function set_needsSoftKeyboard(value : Bool) : Bool; + private function set_softKeyboardInputAreaOfInterest(value : flash.geom.Rectangle) : flash.geom.Rectangle; + private function set_tabEnabled(value : Bool) : Bool; + private function set_tabIndex(value : Int) : Int; } diff --git a/std/flash/display/InterpolationMethod.hx b/std/flash/display/InterpolationMethod.hx index a617d78f6ea..58f14c255b3 100644 --- a/std/flash/display/InterpolationMethod.hx +++ b/std/flash/display/InterpolationMethod.hx @@ -1,6 +1,6 @@ package flash.display; -@:fakeEnum(String) extern enum InterpolationMethod { - LINEAR_RGB; - RGB; +@:native("flash.display.InterpolationMethod") extern enum abstract InterpolationMethod(String) { + var LINEAR_RGB; + var RGB; } diff --git a/std/flash/display/JPEGCompressOptions.hx b/std/flash/display/JPEGCompressOptions.hx index 85f4c7e4ca7..f4db4f28c79 100644 --- a/std/flash/display/JPEGCompressOptions.hx +++ b/std/flash/display/JPEGCompressOptions.hx @@ -1,6 +1,6 @@ package flash.display; -@:final extern class JPEGCompressOptions implements IBitmapCompressOptions { +extern final class JPEGCompressOptions implements IBitmapCompressOptions { var quality : UInt; function new(quality : UInt = 80) : Void; } diff --git a/std/flash/display/JPEGEncoderOptions.hx b/std/flash/display/JPEGEncoderOptions.hx index 53b2d996879..a861b7cd093 100644 --- a/std/flash/display/JPEGEncoderOptions.hx +++ b/std/flash/display/JPEGEncoderOptions.hx @@ -1,6 +1,6 @@ package flash.display; -@:final extern class JPEGEncoderOptions { +extern final class JPEGEncoderOptions { var quality : UInt; function new(quality : UInt = 80) : Void; } diff --git a/std/flash/display/JPEGXRCompressOptions.hx b/std/flash/display/JPEGXRCompressOptions.hx index b6a7883ca71..a605a96a0b4 100644 --- a/std/flash/display/JPEGXRCompressOptions.hx +++ b/std/flash/display/JPEGXRCompressOptions.hx @@ -1,6 +1,6 @@ package flash.display; -@:final extern class JPEGXRCompressOptions implements IBitmapCompressOptions { +extern final class JPEGXRCompressOptions implements IBitmapCompressOptions { var colorSpace : String; var quantization : UInt; var trimFlexBits : UInt; diff --git a/std/flash/display/JPEGXREncoderOptions.hx b/std/flash/display/JPEGXREncoderOptions.hx index a75840461c8..3c0162858e3 100644 --- a/std/flash/display/JPEGXREncoderOptions.hx +++ b/std/flash/display/JPEGXREncoderOptions.hx @@ -1,6 +1,6 @@ package flash.display; -@:final extern class JPEGXREncoderOptions { +extern final class JPEGXREncoderOptions { var colorSpace : BitmapEncodingColorSpace; var quantization : UInt; var trimFlexBits : UInt; diff --git a/std/flash/display/JointStyle.hx b/std/flash/display/JointStyle.hx index 7480b6ccdb3..981f7c9be37 100644 --- a/std/flash/display/JointStyle.hx +++ b/std/flash/display/JointStyle.hx @@ -1,7 +1,7 @@ package flash.display; -@:fakeEnum(String) extern enum JointStyle { - BEVEL; - MITER; - ROUND; +@:native("flash.display.JointStyle") extern enum abstract JointStyle(String) { + var BEVEL; + var MITER; + var ROUND; } diff --git a/std/flash/display/LineScaleMode.hx b/std/flash/display/LineScaleMode.hx index 93b655a7e25..5c5f35a308f 100644 --- a/std/flash/display/LineScaleMode.hx +++ b/std/flash/display/LineScaleMode.hx @@ -1,8 +1,8 @@ package flash.display; -@:fakeEnum(String) extern enum LineScaleMode { - HORIZONTAL; - NONE; - NORMAL; - VERTICAL; +@:native("flash.display.LineScaleMode") extern enum abstract LineScaleMode(String) { + var HORIZONTAL; + var NONE; + var NORMAL; + var VERTICAL; } diff --git a/std/flash/display/Loader.hx b/std/flash/display/Loader.hx index 3264fd6ab23..0dc6ac3879b 100644 --- a/std/flash/display/Loader.hx +++ b/std/flash/display/Loader.hx @@ -1,11 +1,14 @@ package flash.display; extern class Loader extends DisplayObjectContainer { - var content(default,never) : DisplayObject; - var contentLoaderInfo(default,never) : LoaderInfo; - @:require(flash10_1) var uncaughtErrorEvents(default,never) : flash.events.UncaughtErrorEvents; + @:flash.property var content(get,never) : DisplayObject; + @:flash.property var contentLoaderInfo(get,never) : LoaderInfo; + @:flash.property @:require(flash10_1) var uncaughtErrorEvents(get,never) : flash.events.UncaughtErrorEvents; function new() : Void; function close() : Void; + private function get_content() : DisplayObject; + private function get_contentLoaderInfo() : LoaderInfo; + private function get_uncaughtErrorEvents() : flash.events.UncaughtErrorEvents; function load(request : flash.net.URLRequest, ?context : flash.system.LoaderContext) : Void; function loadBytes(bytes : flash.utils.ByteArray, ?context : flash.system.LoaderContext) : Void; function unload() : Void; diff --git a/std/flash/display/LoaderInfo.hx b/std/flash/display/LoaderInfo.hx index eeaacb898f4..a741b431a64 100644 --- a/std/flash/display/LoaderInfo.hx +++ b/std/flash/display/LoaderInfo.hx @@ -1,28 +1,53 @@ package flash.display; extern class LoaderInfo extends flash.events.EventDispatcher { - var actionScriptVersion(default,never) : ActionScriptVersion; - var applicationDomain(default,never) : flash.system.ApplicationDomain; - var bytes(default,never) : flash.utils.ByteArray; - var bytesLoaded(default,never) : UInt; - var bytesTotal(default,never) : UInt; - var childAllowsParent(default,never) : Bool; - @:require(flash11_4) var childSandboxBridge : Dynamic; - var content(default,never) : DisplayObject; - var contentType(default,never) : String; - var frameRate(default,never) : Float; - var height(default,never) : Int; - @:require(flash10_1) var isURLInaccessible(default,never) : Bool; - var loader(default,never) : Loader; - var loaderURL(default,never) : String; - var parameters(default,never) : Dynamic; - var parentAllowsChild(default,never) : Bool; - @:require(flash11_4) var parentSandboxBridge : Dynamic; - var sameDomain(default,never) : Bool; - var sharedEvents(default,never) : flash.events.EventDispatcher; - var swfVersion(default,never) : UInt; - @:require(flash10_1) var uncaughtErrorEvents(default,never) : flash.events.UncaughtErrorEvents; - var url(default,never) : String; - var width(default,never) : Int; + @:flash.property var actionScriptVersion(get,never) : ActionScriptVersion; + @:flash.property var applicationDomain(get,never) : flash.system.ApplicationDomain; + @:flash.property var bytes(get,never) : flash.utils.ByteArray; + @:flash.property var bytesLoaded(get,never) : UInt; + @:flash.property var bytesTotal(get,never) : UInt; + @:flash.property var childAllowsParent(get,never) : Bool; + @:flash.property @:require(flash11_4) var childSandboxBridge(get,set) : Dynamic; + @:flash.property var content(get,never) : DisplayObject; + @:flash.property var contentType(get,never) : String; + @:flash.property var frameRate(get,never) : Float; + @:flash.property var height(get,never) : Int; + @:flash.property @:require(flash10_1) var isURLInaccessible(get,never) : Bool; + @:flash.property var loader(get,never) : Loader; + @:flash.property var loaderURL(get,never) : String; + @:flash.property var parameters(get,never) : Dynamic; + @:flash.property var parentAllowsChild(get,never) : Bool; + @:flash.property @:require(flash11_4) var parentSandboxBridge(get,set) : Dynamic; + @:flash.property var sameDomain(get,never) : Bool; + @:flash.property var sharedEvents(get,never) : flash.events.EventDispatcher; + @:flash.property var swfVersion(get,never) : UInt; + @:flash.property @:require(flash10_1) var uncaughtErrorEvents(get,never) : flash.events.UncaughtErrorEvents; + @:flash.property var url(get,never) : String; + @:flash.property var width(get,never) : Int; + private function get_actionScriptVersion() : ActionScriptVersion; + private function get_applicationDomain() : flash.system.ApplicationDomain; + private function get_bytes() : flash.utils.ByteArray; + private function get_bytesLoaded() : UInt; + private function get_bytesTotal() : UInt; + private function get_childAllowsParent() : Bool; + private function get_childSandboxBridge() : Dynamic; + private function get_content() : DisplayObject; + private function get_contentType() : String; + private function get_frameRate() : Float; + private function get_height() : Int; + private function get_isURLInaccessible() : Bool; + private function get_loader() : Loader; + private function get_loaderURL() : String; + private function get_parameters() : Dynamic; + private function get_parentAllowsChild() : Bool; + private function get_parentSandboxBridge() : Dynamic; + private function get_sameDomain() : Bool; + private function get_sharedEvents() : flash.events.EventDispatcher; + private function get_swfVersion() : UInt; + private function get_uncaughtErrorEvents() : flash.events.UncaughtErrorEvents; + private function get_url() : String; + private function get_width() : Int; + private function set_childSandboxBridge(value : Dynamic) : Dynamic; + private function set_parentSandboxBridge(value : Dynamic) : Dynamic; static function getLoaderInfoByDefinition(object : Dynamic) : LoaderInfo; } diff --git a/std/flash/display/MovieClip.hx b/std/flash/display/MovieClip.hx index 10ba642a406..0f20402e32e 100644 --- a/std/flash/display/MovieClip.hx +++ b/std/flash/display/MovieClip.hx @@ -1,19 +1,30 @@ package flash.display; extern class MovieClip extends Sprite #if !flash_strict implements Dynamic #end { - var currentFrame(default,never) : Int; - @:require(flash10) var currentFrameLabel(default,never) : String; - var currentLabel(default,never) : String; - var currentLabels(default,never) : Array; - var currentScene(default,never) : Scene; - var enabled : Bool; - var framesLoaded(default,never) : Int; - @:require(flash11) var isPlaying(default,never) : Bool; - var scenes(default,never) : Array; - var totalFrames(default,never) : Int; - var trackAsMenu : Bool; + @:flash.property var currentFrame(get,never) : Int; + @:flash.property @:require(flash10) var currentFrameLabel(get,never) : String; + @:flash.property var currentLabel(get,never) : String; + @:flash.property var currentLabels(get,never) : Array; + @:flash.property var currentScene(get,never) : Scene; + @:flash.property var enabled(get,set) : Bool; + @:flash.property var framesLoaded(get,never) : Int; + @:flash.property @:require(flash11) var isPlaying(get,never) : Bool; + @:flash.property var scenes(get,never) : Array; + @:flash.property var totalFrames(get,never) : Int; + @:flash.property var trackAsMenu(get,set) : Bool; function new() : Void; - function addFrameScript(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; + function addFrameScript(restArgs : haxe.extern.Rest) : Void; + private function get_currentFrame() : Int; + private function get_currentFrameLabel() : String; + private function get_currentLabel() : String; + private function get_currentLabels() : Array; + private function get_currentScene() : Scene; + private function get_enabled() : Bool; + private function get_framesLoaded() : Int; + private function get_isPlaying() : Bool; + private function get_scenes() : Array; + private function get_totalFrames() : Int; + private function get_trackAsMenu() : Bool; function gotoAndPlay(frame : flash.utils.Object, ?scene : String) : Void; function gotoAndStop(frame : flash.utils.Object, ?scene : String) : Void; function nextFrame() : Void; @@ -21,5 +32,7 @@ extern class MovieClip extends Sprite #if !flash_strict implements Dynamic #end function play() : Void; function prevFrame() : Void; function prevScene() : Void; + private function set_enabled(value : Bool) : Bool; + private function set_trackAsMenu(value : Bool) : Bool; function stop() : Void; } diff --git a/std/flash/display/NativeMenuItem.hx b/std/flash/display/NativeMenuItem.hx index 3f238805994..d484f96364e 100644 --- a/std/flash/display/NativeMenuItem.hx +++ b/std/flash/display/NativeMenuItem.hx @@ -1,6 +1,8 @@ package flash.display; @:require(flash10_1) extern class NativeMenuItem extends flash.events.EventDispatcher { - var enabled : Bool; + @:flash.property var enabled(get,set) : Bool; function new() : Void; + private function get_enabled() : Bool; + private function set_enabled(value : Bool) : Bool; } diff --git a/std/flash/display/PNGEncoderOptions.hx b/std/flash/display/PNGEncoderOptions.hx index 642a917acbd..3d315ade64b 100644 --- a/std/flash/display/PNGEncoderOptions.hx +++ b/std/flash/display/PNGEncoderOptions.hx @@ -1,6 +1,6 @@ package flash.display; -@:final extern class PNGEncoderOptions { +extern final class PNGEncoderOptions { var fastCompression : Bool; function new(fastCompression : Bool = false) : Void; } diff --git a/std/flash/display/PixelSnapping.hx b/std/flash/display/PixelSnapping.hx index a830eb0143b..c83ea307556 100644 --- a/std/flash/display/PixelSnapping.hx +++ b/std/flash/display/PixelSnapping.hx @@ -1,7 +1,7 @@ package flash.display; -@:fakeEnum(String) extern enum PixelSnapping { - ALWAYS; - AUTO; - NEVER; +@:native("flash.display.PixelSnapping") extern enum abstract PixelSnapping(String) { + var ALWAYS; + var AUTO; + var NEVER; } diff --git a/std/flash/display/SWFVersion.hx b/std/flash/display/SWFVersion.hx index 9912de01704..969368a41c0 100644 --- a/std/flash/display/SWFVersion.hx +++ b/std/flash/display/SWFVersion.hx @@ -1,16 +1,16 @@ package flash.display; extern class SWFVersion { - static var FLASH1(default,never) : UInt; - static var FLASH10(default,never) : UInt; - static var FLASH11(default,never) : UInt; - static var FLASH12(default,never) : UInt; - static var FLASH2(default,never) : UInt; - static var FLASH3(default,never) : UInt; - static var FLASH4(default,never) : UInt; - static var FLASH5(default,never) : UInt; - static var FLASH6(default,never) : UInt; - static var FLASH7(default,never) : UInt; - static var FLASH8(default,never) : UInt; - static var FLASH9(default,never) : UInt; + static final FLASH1 : UInt; + static final FLASH10 : UInt; + static final FLASH11 : UInt; + static final FLASH12 : UInt; + static final FLASH2 : UInt; + static final FLASH3 : UInt; + static final FLASH4 : UInt; + static final FLASH5 : UInt; + static final FLASH6 : UInt; + static final FLASH7 : UInt; + static final FLASH8 : UInt; + static final FLASH9 : UInt; } diff --git a/std/flash/display/Scene.hx b/std/flash/display/Scene.hx index 4fa352135a4..42d9b91238a 100644 --- a/std/flash/display/Scene.hx +++ b/std/flash/display/Scene.hx @@ -1,8 +1,11 @@ package flash.display; -@:final extern class Scene { - var labels(default,never) : Array; - var name(default,never) : String; - var numFrames(default,never) : Int; +extern final class Scene { + @:flash.property var labels(get,never) : Array; + @:flash.property var name(get,never) : String; + @:flash.property var numFrames(get,never) : Int; function new(name : String, labels : Array, numFrames : Int) : Void; + private function get_labels() : Array; + private function get_name() : String; + private function get_numFrames() : Int; } diff --git a/std/flash/display/Shader.hx b/std/flash/display/Shader.hx index 59a70c4daad..e35cf92636e 100644 --- a/std/flash/display/Shader.hx +++ b/std/flash/display/Shader.hx @@ -1,8 +1,13 @@ package flash.display; @:require(flash10) extern class Shader { - var byteCode(never,default) : flash.utils.ByteArray; - var data : ShaderData; - var precisionHint : ShaderPrecision; + @:flash.property var byteCode(never,set) : flash.utils.ByteArray; + @:flash.property var data(get,set) : ShaderData; + @:flash.property var precisionHint(get,set) : ShaderPrecision; function new(?code : flash.utils.ByteArray) : Void; + private function get_data() : ShaderData; + private function get_precisionHint() : ShaderPrecision; + private function set_byteCode(value : flash.utils.ByteArray) : flash.utils.ByteArray; + private function set_data(value : ShaderData) : ShaderData; + private function set_precisionHint(value : ShaderPrecision) : ShaderPrecision; } diff --git a/std/flash/display/ShaderInput.hx b/std/flash/display/ShaderInput.hx index 5ce1686dc2a..abff29a3326 100644 --- a/std/flash/display/ShaderInput.hx +++ b/std/flash/display/ShaderInput.hx @@ -1,10 +1,18 @@ package flash.display; -@:final extern class ShaderInput implements Dynamic { - var channels(default,never) : Int; - var height : Int; - var index(default,never) : Int; - var input : Dynamic; - var width : Int; +extern final class ShaderInput implements Dynamic { + @:flash.property var channels(get,never) : Int; + @:flash.property var height(get,set) : Int; + @:flash.property var index(get,never) : Int; + @:flash.property var input(get,set) : Dynamic; + @:flash.property var width(get,set) : Int; function new() : Void; + private function get_channels() : Int; + private function get_height() : Int; + private function get_index() : Int; + private function get_input() : Dynamic; + private function get_width() : Int; + private function set_height(value : Int) : Int; + private function set_input(value : Dynamic) : Dynamic; + private function set_width(value : Int) : Int; } diff --git a/std/flash/display/ShaderJob.hx b/std/flash/display/ShaderJob.hx index f5108222806..cfe57702043 100644 --- a/std/flash/display/ShaderJob.hx +++ b/std/flash/display/ShaderJob.hx @@ -1,12 +1,21 @@ package flash.display; extern class ShaderJob extends flash.events.EventDispatcher { - var height : Int; - var progress(default,never) : Float; - var shader : Shader; - var target : Dynamic; - var width : Int; + @:flash.property var height(get,set) : Int; + @:flash.property var progress(get,never) : Float; + @:flash.property var shader(get,set) : Shader; + @:flash.property var target(get,set) : Dynamic; + @:flash.property var width(get,set) : Int; function new(?shader : Shader, ?target : Dynamic, width : Int = 0, height : Int = 0) : Void; function cancel() : Void; + private function get_height() : Int; + private function get_progress() : Float; + private function get_shader() : Shader; + private function get_target() : Dynamic; + private function get_width() : Int; + private function set_height(value : Int) : Int; + private function set_shader(value : Shader) : Shader; + private function set_target(value : Dynamic) : Dynamic; + private function set_width(value : Int) : Int; function start(waitForCompletion : Bool = false) : Void; } diff --git a/std/flash/display/ShaderParameter.hx b/std/flash/display/ShaderParameter.hx index 4b02ccb8981..b7dcae69ab1 100644 --- a/std/flash/display/ShaderParameter.hx +++ b/std/flash/display/ShaderParameter.hx @@ -1,7 +1,11 @@ package flash.display; -@:final extern class ShaderParameter implements Dynamic { - var index(default,never) : Int; - var type(default,never) : ShaderParameterType; - var value : Array; +extern final class ShaderParameter implements Dynamic { + @:flash.property var index(get,never) : Int; + @:flash.property var type(get,never) : ShaderParameterType; + @:flash.property var value(get,set) : Array; + private function get_index() : Int; + private function get_type() : ShaderParameterType; + private function get_value() : Array; + private function set_value(value : Array) : Array; } diff --git a/std/flash/display/ShaderParameterType.hx b/std/flash/display/ShaderParameterType.hx index 6758d3f5f4e..78d867b6736 100644 --- a/std/flash/display/ShaderParameterType.hx +++ b/std/flash/display/ShaderParameterType.hx @@ -1,19 +1,19 @@ package flash.display; -@:fakeEnum(String) extern enum ShaderParameterType { - BOOL; - BOOL2; - BOOL3; - BOOL4; - FLOAT; - FLOAT2; - FLOAT3; - FLOAT4; - INT; - INT2; - INT3; - INT4; - MATRIX2X2; - MATRIX3X3; - MATRIX4X4; +@:native("flash.display.ShaderParameterType") extern enum abstract ShaderParameterType(String) { + var BOOL; + var BOOL2; + var BOOL3; + var BOOL4; + var FLOAT; + var FLOAT2; + var FLOAT3; + var FLOAT4; + var INT; + var INT2; + var INT3; + var INT4; + var MATRIX2X2; + var MATRIX3X3; + var MATRIX4X4; } diff --git a/std/flash/display/ShaderPrecision.hx b/std/flash/display/ShaderPrecision.hx index 8a276c96c2d..941642b7f9e 100644 --- a/std/flash/display/ShaderPrecision.hx +++ b/std/flash/display/ShaderPrecision.hx @@ -1,6 +1,6 @@ package flash.display; -@:fakeEnum(String) extern enum ShaderPrecision { - FAST; - FULL; +@:native("flash.display.ShaderPrecision") extern enum abstract ShaderPrecision(String) { + var FAST; + var FULL; } diff --git a/std/flash/display/Shape.hx b/std/flash/display/Shape.hx index fb13285c781..605fa9aa3dc 100644 --- a/std/flash/display/Shape.hx +++ b/std/flash/display/Shape.hx @@ -1,6 +1,7 @@ package flash.display; extern class Shape extends DisplayObject { - var graphics(default,never) : Graphics; + @:flash.property var graphics(get,never) : Graphics; function new() : Void; + private function get_graphics() : Graphics; } diff --git a/std/flash/display/SimpleButton.hx b/std/flash/display/SimpleButton.hx index bedb0e8bcb3..fde09d2fd1b 100644 --- a/std/flash/display/SimpleButton.hx +++ b/std/flash/display/SimpleButton.hx @@ -1,13 +1,29 @@ package flash.display; extern class SimpleButton extends InteractiveObject { - var downState : DisplayObject; - var enabled : Bool; - var hitTestState : DisplayObject; - var overState : DisplayObject; - var soundTransform : flash.media.SoundTransform; - var trackAsMenu : Bool; - var upState : DisplayObject; - var useHandCursor : Bool; + @:flash.property var downState(get,set) : DisplayObject; + @:flash.property var enabled(get,set) : Bool; + @:flash.property var hitTestState(get,set) : DisplayObject; + @:flash.property var overState(get,set) : DisplayObject; + @:flash.property var soundTransform(get,set) : flash.media.SoundTransform; + @:flash.property var trackAsMenu(get,set) : Bool; + @:flash.property var upState(get,set) : DisplayObject; + @:flash.property var useHandCursor(get,set) : Bool; function new(?upState : DisplayObject, ?overState : DisplayObject, ?downState : DisplayObject, ?hitTestState : DisplayObject) : Void; + private function get_downState() : DisplayObject; + private function get_enabled() : Bool; + private function get_hitTestState() : DisplayObject; + private function get_overState() : DisplayObject; + private function get_soundTransform() : flash.media.SoundTransform; + private function get_trackAsMenu() : Bool; + private function get_upState() : DisplayObject; + private function get_useHandCursor() : Bool; + private function set_downState(value : DisplayObject) : DisplayObject; + private function set_enabled(value : Bool) : Bool; + private function set_hitTestState(value : DisplayObject) : DisplayObject; + private function set_overState(value : DisplayObject) : DisplayObject; + private function set_soundTransform(value : flash.media.SoundTransform) : flash.media.SoundTransform; + private function set_trackAsMenu(value : Bool) : Bool; + private function set_upState(value : DisplayObject) : DisplayObject; + private function set_useHandCursor(value : Bool) : Bool; } diff --git a/std/flash/display/SpreadMethod.hx b/std/flash/display/SpreadMethod.hx index 7b65ba75bfe..d2f8a18f427 100644 --- a/std/flash/display/SpreadMethod.hx +++ b/std/flash/display/SpreadMethod.hx @@ -1,7 +1,7 @@ package flash.display; -@:fakeEnum(String) extern enum SpreadMethod { - PAD; - REFLECT; - REPEAT; +@:native("flash.display.SpreadMethod") extern enum abstract SpreadMethod(String) { + var PAD; + var REFLECT; + var REPEAT; } diff --git a/std/flash/display/Sprite.hx b/std/flash/display/Sprite.hx index aad8eeb98d1..b238ae842cf 100644 --- a/std/flash/display/Sprite.hx +++ b/std/flash/display/Sprite.hx @@ -1,13 +1,23 @@ package flash.display; extern class Sprite extends DisplayObjectContainer { - var buttonMode : Bool; - var dropTarget(default,never) : DisplayObject; - var graphics(default,never) : Graphics; - var hitArea : Sprite; - var soundTransform : flash.media.SoundTransform; - var useHandCursor : Bool; + @:flash.property var buttonMode(get,set) : Bool; + @:flash.property var dropTarget(get,never) : DisplayObject; + @:flash.property var graphics(get,never) : Graphics; + @:flash.property var hitArea(get,set) : Sprite; + @:flash.property var soundTransform(get,set) : flash.media.SoundTransform; + @:flash.property var useHandCursor(get,set) : Bool; function new() : Void; + private function get_buttonMode() : Bool; + private function get_dropTarget() : DisplayObject; + private function get_graphics() : Graphics; + private function get_hitArea() : Sprite; + private function get_soundTransform() : flash.media.SoundTransform; + private function get_useHandCursor() : Bool; + private function set_buttonMode(value : Bool) : Bool; + private function set_hitArea(value : Sprite) : Sprite; + private function set_soundTransform(value : flash.media.SoundTransform) : flash.media.SoundTransform; + private function set_useHandCursor(value : Bool) : Bool; function startDrag(lockCenter : Bool = false, ?bounds : flash.geom.Rectangle) : Void; @:require(flash10_1) function startTouchDrag(touchPointID : Int, lockCenter : Bool = false, ?bounds : flash.geom.Rectangle) : Void; function stopDrag() : Void; diff --git a/std/flash/display/Stage.hx b/std/flash/display/Stage.hx index 6bdc2aaa60c..0edf295dc7a 100644 --- a/std/flash/display/Stage.hx +++ b/std/flash/display/Stage.hx @@ -1,32 +1,74 @@ package flash.display; extern class Stage extends DisplayObjectContainer { - var align : StageAlign; - var allowsFullScreen(default,never) : Bool; - @:require(flash11_3) var allowsFullScreenInteractive(default,never) : Bool; - var browserZoomFactor(default,never) : Float; - @:require(flash10_2) var color : UInt; - @:require(flash10) var colorCorrection : ColorCorrection; - @:require(flash10) var colorCorrectionSupport(default,never) : ColorCorrectionSupport; - @:require(flash11_4) var contentsScaleFactor(default,never) : Float; - @:require(flash11) var displayContextInfo(default,never) : String; - var displayState : StageDisplayState; - var focus : InteractiveObject; - var frameRate : Float; - var fullScreenHeight(default,never) : UInt; - var fullScreenSourceRect : flash.geom.Rectangle; - var fullScreenWidth(default,never) : UInt; - @:require(flash11_2) var mouseLock : Bool; - var quality : StageQuality; - var scaleMode : StageScaleMode; - var showDefaultContextMenu : Bool; - @:require(flash11) var softKeyboardRect(default,never) : flash.geom.Rectangle; - @:require(flash11) var stage3Ds(default,never) : flash.Vector; - var stageFocusRect : Bool; - var stageHeight : Int; - @:require(flash10_2) var stageVideos(default,never) : flash.Vector; - var stageWidth : Int; - @:require(flash10_1) var wmodeGPU(default,never) : Bool; + @:flash.property var align(get,set) : StageAlign; + @:flash.property var allowsFullScreen(get,never) : Bool; + @:flash.property @:require(flash11_3) var allowsFullScreenInteractive(get,never) : Bool; + @:flash.property var browserZoomFactor(get,never) : Float; + @:flash.property @:require(flash10_2) var color(get,set) : UInt; + @:flash.property @:require(flash10) var colorCorrection(get,set) : ColorCorrection; + @:flash.property @:require(flash10) var colorCorrectionSupport(get,never) : ColorCorrectionSupport; + @:flash.property @:require(flash11_4) var contentsScaleFactor(get,never) : Float; + @:flash.property @:require(flash11) var displayContextInfo(get,never) : String; + @:flash.property var displayState(get,set) : StageDisplayState; + @:flash.property var focus(get,set) : InteractiveObject; + @:flash.property var frameRate(get,set) : Float; + @:flash.property var fullScreenHeight(get,never) : UInt; + @:flash.property var fullScreenSourceRect(get,set) : flash.geom.Rectangle; + @:flash.property var fullScreenWidth(get,never) : UInt; + @:flash.property @:require(flash11_2) var mouseLock(get,set) : Bool; + @:flash.property var quality(get,set) : StageQuality; + @:flash.property var scaleMode(get,set) : StageScaleMode; + @:flash.property var showDefaultContextMenu(get,set) : Bool; + @:flash.property @:require(flash11) var softKeyboardRect(get,never) : flash.geom.Rectangle; + @:flash.property @:require(flash11) var stage3Ds(get,never) : flash.Vector; + @:flash.property var stageFocusRect(get,set) : Bool; + @:flash.property var stageHeight(get,set) : Int; + @:flash.property @:require(flash10_2) var stageVideos(get,never) : flash.Vector; + @:flash.property var stageWidth(get,set) : Int; + @:flash.property @:require(flash10_1) var wmodeGPU(get,never) : Bool; + private function get_align() : StageAlign; + private function get_allowsFullScreen() : Bool; + private function get_allowsFullScreenInteractive() : Bool; + private function get_browserZoomFactor() : Float; + private function get_color() : UInt; + private function get_colorCorrection() : ColorCorrection; + private function get_colorCorrectionSupport() : ColorCorrectionSupport; + private function get_constructor() : Dynamic; + private function get_contentsScaleFactor() : Float; + private function get_displayContextInfo() : String; + private function get_displayState() : StageDisplayState; + private function get_focus() : InteractiveObject; + private function get_frameRate() : Float; + private function get_fullScreenHeight() : UInt; + private function get_fullScreenSourceRect() : flash.geom.Rectangle; + private function get_fullScreenWidth() : UInt; + private function get_mouseLock() : Bool; + private function get_quality() : StageQuality; + private function get_scaleMode() : StageScaleMode; + private function get_showDefaultContextMenu() : Bool; + private function get_softKeyboardRect() : flash.geom.Rectangle; + private function get_stage3Ds() : flash.Vector; + private function get_stageFocusRect() : Bool; + private function get_stageHeight() : Int; + private function get_stageVideos() : flash.Vector; + private function get_stageWidth() : Int; + private function get_wmodeGPU() : Bool; function invalidate() : Void; function isFocusInaccessible() : Bool; + private function set_align(value : StageAlign) : StageAlign; + private function set_color(value : UInt) : UInt; + private function set_colorCorrection(value : ColorCorrection) : ColorCorrection; + private function set_constructor(value : Dynamic) : Dynamic; + private function set_displayState(value : StageDisplayState) : StageDisplayState; + private function set_focus(value : InteractiveObject) : InteractiveObject; + private function set_frameRate(value : Float) : Float; + private function set_fullScreenSourceRect(value : flash.geom.Rectangle) : flash.geom.Rectangle; + private function set_mouseLock(value : Bool) : Bool; + private function set_quality(value : StageQuality) : StageQuality; + private function set_scaleMode(value : StageScaleMode) : StageScaleMode; + private function set_showDefaultContextMenu(value : Bool) : Bool; + private function set_stageFocusRect(value : Bool) : Bool; + private function set_stageHeight(value : Int) : Int; + private function set_stageWidth(value : Int) : Int; } diff --git a/std/flash/display/Stage3D.hx b/std/flash/display/Stage3D.hx index 09784dc1115..30abb2fb803 100644 --- a/std/flash/display/Stage3D.hx +++ b/std/flash/display/Stage3D.hx @@ -1,10 +1,17 @@ package flash.display; @:require(flash11) extern class Stage3D extends flash.events.EventDispatcher { - var context3D(default,never) : flash.display3D.Context3D; - var visible : Bool; - var x : Float; - var y : Float; + @:flash.property var context3D(get,never) : flash.display3D.Context3D; + @:flash.property var visible(get,set) : Bool; + @:flash.property var x(get,set) : Float; + @:flash.property var y(get,set) : Float; + private function get_context3D() : flash.display3D.Context3D; + private function get_visible() : Bool; + private function get_x() : Float; + private function get_y() : Float; function requestContext3D(?context3DRenderMode : String, ?profile : flash.display3D.Context3DProfile) : Void; @:require(flash12) function requestContext3DMatchingProfiles(profiles : flash.Vector) : Void; + private function set_visible(value : Bool) : Bool; + private function set_x(value : Float) : Float; + private function set_y(value : Float) : Float; } diff --git a/std/flash/display/StageAlign.hx b/std/flash/display/StageAlign.hx index a505c0e211d..b23699182f6 100644 --- a/std/flash/display/StageAlign.hx +++ b/std/flash/display/StageAlign.hx @@ -1,12 +1,12 @@ package flash.display; -@:fakeEnum(String) extern enum StageAlign { - BOTTOM; - BOTTOM_LEFT; - BOTTOM_RIGHT; - LEFT; - RIGHT; - TOP; - TOP_LEFT; - TOP_RIGHT; +@:native("flash.display.StageAlign") extern enum abstract StageAlign(String) { + var BOTTOM; + var BOTTOM_LEFT; + var BOTTOM_RIGHT; + var LEFT; + var RIGHT; + var TOP; + var TOP_LEFT; + var TOP_RIGHT; } diff --git a/std/flash/display/StageDisplayState.hx b/std/flash/display/StageDisplayState.hx index 1c0fef9a019..12311c7dde5 100644 --- a/std/flash/display/StageDisplayState.hx +++ b/std/flash/display/StageDisplayState.hx @@ -1,7 +1,7 @@ package flash.display; -@:fakeEnum(String) extern enum StageDisplayState { - FULL_SCREEN; - FULL_SCREEN_INTERACTIVE; - NORMAL; +@:native("flash.display.StageDisplayState") extern enum abstract StageDisplayState(String) { + var FULL_SCREEN; + var FULL_SCREEN_INTERACTIVE; + var NORMAL; } diff --git a/std/flash/display/StageQuality.hx b/std/flash/display/StageQuality.hx index 901c866d179..5237a4ad807 100644 --- a/std/flash/display/StageQuality.hx +++ b/std/flash/display/StageQuality.hx @@ -1,12 +1,12 @@ package flash.display; -@:fakeEnum(String) extern enum StageQuality { - BEST; - HIGH; - HIGH_16X16; - HIGH_16X16_LINEAR; - HIGH_8X8; - HIGH_8X8_LINEAR; - LOW; - MEDIUM; +@:native("flash.display.StageQuality") extern enum abstract StageQuality(String) { + var BEST; + var HIGH; + var HIGH_16X16; + var HIGH_16X16_LINEAR; + var HIGH_8X8; + var HIGH_8X8_LINEAR; + var LOW; + var MEDIUM; } diff --git a/std/flash/display/StageScaleMode.hx b/std/flash/display/StageScaleMode.hx index eee9aee9d00..027fcbe2b25 100644 --- a/std/flash/display/StageScaleMode.hx +++ b/std/flash/display/StageScaleMode.hx @@ -1,8 +1,8 @@ package flash.display; -@:fakeEnum(String) extern enum StageScaleMode { - EXACT_FIT; - NO_BORDER; - NO_SCALE; - SHOW_ALL; +@:native("flash.display.StageScaleMode") extern enum abstract StageScaleMode(String) { + var EXACT_FIT; + var NO_BORDER; + var NO_SCALE; + var SHOW_ALL; } diff --git a/std/flash/display/StageWorker.hx b/std/flash/display/StageWorker.hx index 6bfae848424..164675f7a17 100644 --- a/std/flash/display/StageWorker.hx +++ b/std/flash/display/StageWorker.hx @@ -1,6 +1,6 @@ package flash.display; -@:require(flash11_2) @:final extern class StageWorker extends Sprite { +@:require(flash11_2) extern final class StageWorker extends Sprite { var scaleMode : String; var viewport : flash.geom.Rectangle; function new() : Void; diff --git a/std/flash/display/TriangleCulling.hx b/std/flash/display/TriangleCulling.hx index 395297cf359..01a23940037 100644 --- a/std/flash/display/TriangleCulling.hx +++ b/std/flash/display/TriangleCulling.hx @@ -1,7 +1,7 @@ package flash.display; -@:fakeEnum(String) extern enum TriangleCulling { - NEGATIVE; - NONE; - POSITIVE; +@:native("flash.display.TriangleCulling") extern enum abstract TriangleCulling(String) { + var NEGATIVE; + var NONE; + var POSITIVE; } diff --git a/std/flash/display/Worker.hx b/std/flash/display/Worker.hx index 63a4ba2818f..71cdc282960 100644 --- a/std/flash/display/Worker.hx +++ b/std/flash/display/Worker.hx @@ -1,6 +1,6 @@ package flash.display; -@:require(flash11_2) @:final extern class Worker extends flash.events.EventDispatcher { +@:require(flash11_2) extern final class Worker extends flash.events.EventDispatcher { var running(default,null) : Bool; var view(default,null) : StageWorker; function new() : Void; diff --git a/std/flash/display3D/Context3D.hx b/std/flash/display3D/Context3D.hx index 7d355ad78ce..549f13ab817 100644 --- a/std/flash/display3D/Context3D.hx +++ b/std/flash/display3D/Context3D.hx @@ -1,14 +1,14 @@ package flash.display3D; -@:final extern class Context3D extends flash.events.EventDispatcher { - var backBufferHeight(default,never) : Int; - var backBufferWidth(default,never) : Int; - var driverInfo(default,never) : String; - var enableErrorChecking : Bool; - var maxBackBufferHeight : Int; - var maxBackBufferWidth : Int; - @:require(flash12) var profile(default,never) : String; - var totalGPUMemory(default,never) : Float; +extern final class Context3D extends flash.events.EventDispatcher { + @:flash.property var backBufferHeight(get,never) : Int; + @:flash.property var backBufferWidth(get,never) : Int; + @:flash.property var driverInfo(get,never) : String; + @:flash.property var enableErrorChecking(get,set) : Bool; + @:flash.property var maxBackBufferHeight(get,set) : Int; + @:flash.property var maxBackBufferWidth(get,set) : Int; + @:flash.property @:require(flash12) var profile(get,never) : String; + @:flash.property var totalGPUMemory(get,never) : Float; function clear(red : Float = 0, green : Float = 0, blue : Float = 0, alpha : Float = 1, depth : Float = 1, stencil : UInt = 0, mask : UInt = 0xFFFFFFFF) : Void; function configureBackBuffer(width : Int, height : Int, antiAlias : Int, enableDepthAndStencil : Bool = true, wantsBestResolution : Bool = false, wantsBestResolutionOnBrowserZoom : Bool = false) : Void; function createCubeTexture(size : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool, streamingLevels : Int = 0) : flash.display3D.textures.CubeTexture; @@ -21,6 +21,14 @@ package flash.display3D; function dispose(recreate : Bool = true) : Void; function drawToBitmapData(destination : flash.display.BitmapData) : Void; function drawTriangles(indexBuffer : IndexBuffer3D, firstIndex : Int = 0, numTriangles : Int = -1) : Void; + private function get_backBufferHeight() : Int; + private function get_backBufferWidth() : Int; + private function get_driverInfo() : String; + private function get_enableErrorChecking() : Bool; + private function get_maxBackBufferHeight() : Int; + private function get_maxBackBufferWidth() : Int; + private function get_profile() : String; + private function get_totalGPUMemory() : Float; function present() : Void; function setBlendFactors(sourceFactor : Context3DBlendFactor, destinationFactor : Context3DBlendFactor) : Void; function setColorMask(red : Bool, green : Bool, blue : Bool, alpha : Bool) : Void; @@ -38,5 +46,9 @@ package flash.display3D; function setStencilReferenceValue(referenceValue : UInt, readMask : UInt = 255, writeMask : UInt = 255) : Void; function setTextureAt(sampler : Int, texture : flash.display3D.textures.TextureBase) : Void; function setVertexBufferAt(index : Int, buffer : VertexBuffer3D, bufferOffset : Int = 0, ?format : Context3DVertexBufferFormat) : Void; - static var supportsVideoTexture(default,never) : Bool; + private function set_enableErrorChecking(value : Bool) : Bool; + private function set_maxBackBufferHeight(value : Int) : Int; + private function set_maxBackBufferWidth(value : Int) : Int; + @:flash.property static var supportsVideoTexture(get,never) : Bool; + private static function get_supportsVideoTexture() : Bool; } diff --git a/std/flash/display3D/Context3DBlendFactor.hx b/std/flash/display3D/Context3DBlendFactor.hx index 23535f9c3ac..225a678d961 100644 --- a/std/flash/display3D/Context3DBlendFactor.hx +++ b/std/flash/display3D/Context3DBlendFactor.hx @@ -1,14 +1,14 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DBlendFactor { - DESTINATION_ALPHA; - DESTINATION_COLOR; - ONE; - ONE_MINUS_DESTINATION_ALPHA; - ONE_MINUS_DESTINATION_COLOR; - ONE_MINUS_SOURCE_ALPHA; - ONE_MINUS_SOURCE_COLOR; - SOURCE_ALPHA; - SOURCE_COLOR; - ZERO; +@:native("flash.display3D.Context3DBlendFactor") extern enum abstract Context3DBlendFactor(String) { + var DESTINATION_ALPHA; + var DESTINATION_COLOR; + var ONE; + var ONE_MINUS_DESTINATION_ALPHA; + var ONE_MINUS_DESTINATION_COLOR; + var ONE_MINUS_SOURCE_ALPHA; + var ONE_MINUS_SOURCE_COLOR; + var SOURCE_ALPHA; + var SOURCE_COLOR; + var ZERO; } diff --git a/std/flash/display3D/Context3DBufferUsage.hx b/std/flash/display3D/Context3DBufferUsage.hx index 96a4dca1e17..f01b2ca3987 100644 --- a/std/flash/display3D/Context3DBufferUsage.hx +++ b/std/flash/display3D/Context3DBufferUsage.hx @@ -1,6 +1,6 @@ package flash.display3D; -@:fakeEnum(String) @:require(flash12) extern enum Context3DBufferUsage { - DYNAMIC_DRAW; - STATIC_DRAW; +@:native("flash.display3D.Context3DBufferUsage") @:require(flash12) extern enum abstract Context3DBufferUsage(String) { + var DYNAMIC_DRAW; + var STATIC_DRAW; } diff --git a/std/flash/display3D/Context3DClearMask.hx b/std/flash/display3D/Context3DClearMask.hx index c66f3122a1c..c20e86ef435 100644 --- a/std/flash/display3D/Context3DClearMask.hx +++ b/std/flash/display3D/Context3DClearMask.hx @@ -1,8 +1,8 @@ package flash.display3D; extern class Context3DClearMask { - static var ALL(default,never) : Int; - static var COLOR(default,never) : Int; - static var DEPTH(default,never) : Int; - static var STENCIL(default,never) : Int; + static final ALL : Int; + static final COLOR : Int; + static final DEPTH : Int; + static final STENCIL : Int; } diff --git a/std/flash/display3D/Context3DCompareMode.hx b/std/flash/display3D/Context3DCompareMode.hx index ff3b992f9c6..7bca910a06a 100644 --- a/std/flash/display3D/Context3DCompareMode.hx +++ b/std/flash/display3D/Context3DCompareMode.hx @@ -1,12 +1,12 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DCompareMode { - ALWAYS; - EQUAL; - GREATER; - GREATER_EQUAL; - LESS; - LESS_EQUAL; - NEVER; - NOT_EQUAL; +@:native("flash.display3D.Context3DCompareMode") extern enum abstract Context3DCompareMode(String) { + var ALWAYS; + var EQUAL; + var GREATER; + var GREATER_EQUAL; + var LESS; + var LESS_EQUAL; + var NEVER; + var NOT_EQUAL; } diff --git a/std/flash/display3D/Context3DFillMode.hx b/std/flash/display3D/Context3DFillMode.hx index 2d17d05aef3..5c44208d640 100644 --- a/std/flash/display3D/Context3DFillMode.hx +++ b/std/flash/display3D/Context3DFillMode.hx @@ -1,6 +1,6 @@ package flash.display3D; -@:fakeEnum(String) @:require(flash16) extern enum Context3DFillMode { - SOLID; - WIREFRAME; +@:native("flash.display3D.Context3DFillMode") @:require(flash16) extern enum abstract Context3DFillMode(String) { + var SOLID; + var WIREFRAME; } diff --git a/std/flash/display3D/Context3DMipFilter.hx b/std/flash/display3D/Context3DMipFilter.hx index 795a2442dfd..6f10e9c7437 100644 --- a/std/flash/display3D/Context3DMipFilter.hx +++ b/std/flash/display3D/Context3DMipFilter.hx @@ -1,7 +1,7 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DMipFilter { - MIPLINEAR; - MIPNEAREST; - MIPNONE; +@:native("flash.display3D.Context3DMipFilter") extern enum abstract Context3DMipFilter(String) { + var MIPLINEAR; + var MIPNEAREST; + var MIPNONE; } diff --git a/std/flash/display3D/Context3DProfile.hx b/std/flash/display3D/Context3DProfile.hx index a90ea9c6eae..6ff113f44f6 100644 --- a/std/flash/display3D/Context3DProfile.hx +++ b/std/flash/display3D/Context3DProfile.hx @@ -1,10 +1,10 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DProfile { - BASELINE; - BASELINE_CONSTRAINED; - BASELINE_EXTENDED; - STANDARD; - STANDARD_CONSTRAINED; - STANDARD_EXTENDED; +@:native("flash.display3D.Context3DProfile") extern enum abstract Context3DProfile(String) { + var BASELINE; + var BASELINE_CONSTRAINED; + var BASELINE_EXTENDED; + var STANDARD; + var STANDARD_CONSTRAINED; + var STANDARD_EXTENDED; } diff --git a/std/flash/display3D/Context3DProgramType.hx b/std/flash/display3D/Context3DProgramType.hx index 877f058377c..e1447e3e984 100644 --- a/std/flash/display3D/Context3DProgramType.hx +++ b/std/flash/display3D/Context3DProgramType.hx @@ -1,6 +1,6 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DProgramType { - FRAGMENT; - VERTEX; +@:native("flash.display3D.Context3DProgramType") extern enum abstract Context3DProgramType(String) { + var FRAGMENT; + var VERTEX; } diff --git a/std/flash/display3D/Context3DRenderMode.hx b/std/flash/display3D/Context3DRenderMode.hx index 8da47959a59..286cc6729dc 100644 --- a/std/flash/display3D/Context3DRenderMode.hx +++ b/std/flash/display3D/Context3DRenderMode.hx @@ -1,6 +1,6 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DRenderMode { - AUTO; - SOFTWARE; +@:native("flash.display3D.Context3DRenderMode") extern enum abstract Context3DRenderMode(String) { + var AUTO; + var SOFTWARE; } diff --git a/std/flash/display3D/Context3DStencilAction.hx b/std/flash/display3D/Context3DStencilAction.hx index 23efe419b38..6b29fc8ac92 100644 --- a/std/flash/display3D/Context3DStencilAction.hx +++ b/std/flash/display3D/Context3DStencilAction.hx @@ -1,12 +1,12 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DStencilAction { - DECREMENT_SATURATE; - DECREMENT_WRAP; - INCREMENT_SATURATE; - INCREMENT_WRAP; - INVERT; - KEEP; - SET; - ZERO; +@:native("flash.display3D.Context3DStencilAction") extern enum abstract Context3DStencilAction(String) { + var DECREMENT_SATURATE; + var DECREMENT_WRAP; + var INCREMENT_SATURATE; + var INCREMENT_WRAP; + var INVERT; + var KEEP; + var SET; + var ZERO; } diff --git a/std/flash/display3D/Context3DTextureFilter.hx b/std/flash/display3D/Context3DTextureFilter.hx index e47af2833d2..2e3e23180ea 100644 --- a/std/flash/display3D/Context3DTextureFilter.hx +++ b/std/flash/display3D/Context3DTextureFilter.hx @@ -1,10 +1,10 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DTextureFilter { - ANISOTROPIC16X; - ANISOTROPIC2X; - ANISOTROPIC4X; - ANISOTROPIC8X; - LINEAR; - NEAREST; +@:native("flash.display3D.Context3DTextureFilter") extern enum abstract Context3DTextureFilter(String) { + var ANISOTROPIC16X; + var ANISOTROPIC2X; + var ANISOTROPIC4X; + var ANISOTROPIC8X; + var LINEAR; + var NEAREST; } diff --git a/std/flash/display3D/Context3DTextureFormat.hx b/std/flash/display3D/Context3DTextureFormat.hx index 0833a8560b5..32f57476821 100644 --- a/std/flash/display3D/Context3DTextureFormat.hx +++ b/std/flash/display3D/Context3DTextureFormat.hx @@ -1,10 +1,10 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DTextureFormat { - BGRA; - BGRA_PACKED; - BGR_PACKED; - COMPRESSED; - COMPRESSED_ALPHA; - RGBA_HALF_FLOAT; +@:native("flash.display3D.Context3DTextureFormat") extern enum abstract Context3DTextureFormat(String) { + var BGRA; + var BGRA_PACKED; + var BGR_PACKED; + var COMPRESSED; + var COMPRESSED_ALPHA; + var RGBA_HALF_FLOAT; } diff --git a/std/flash/display3D/Context3DTriangleFace.hx b/std/flash/display3D/Context3DTriangleFace.hx index 7d8e8e8456b..5bf25be46b1 100644 --- a/std/flash/display3D/Context3DTriangleFace.hx +++ b/std/flash/display3D/Context3DTriangleFace.hx @@ -1,8 +1,8 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DTriangleFace { - BACK; - FRONT; - FRONT_AND_BACK; - NONE; +@:native("flash.display3D.Context3DTriangleFace") extern enum abstract Context3DTriangleFace(String) { + var BACK; + var FRONT; + var FRONT_AND_BACK; + var NONE; } diff --git a/std/flash/display3D/Context3DVertexBufferFormat.hx b/std/flash/display3D/Context3DVertexBufferFormat.hx index 0cba74ee12a..743b927ec17 100644 --- a/std/flash/display3D/Context3DVertexBufferFormat.hx +++ b/std/flash/display3D/Context3DVertexBufferFormat.hx @@ -1,9 +1,9 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DVertexBufferFormat { - BYTES_4; - FLOAT_1; - FLOAT_2; - FLOAT_3; - FLOAT_4; +@:native("flash.display3D.Context3DVertexBufferFormat") extern enum abstract Context3DVertexBufferFormat(String) { + var BYTES_4; + var FLOAT_1; + var FLOAT_2; + var FLOAT_3; + var FLOAT_4; } diff --git a/std/flash/display3D/Context3DWrapMode.hx b/std/flash/display3D/Context3DWrapMode.hx index 38999f3fb46..0af6e59c885 100644 --- a/std/flash/display3D/Context3DWrapMode.hx +++ b/std/flash/display3D/Context3DWrapMode.hx @@ -1,8 +1,8 @@ package flash.display3D; -@:fakeEnum(String) extern enum Context3DWrapMode { - CLAMP; - CLAMP_U_REPEAT_V; - REPEAT; - REPEAT_U_CLAMP_V; +@:native("flash.display3D.Context3DWrapMode") extern enum abstract Context3DWrapMode(String) { + var CLAMP; + var CLAMP_U_REPEAT_V; + var REPEAT; + var REPEAT_U_CLAMP_V; } diff --git a/std/flash/display3D/IndexBuffer3D.hx b/std/flash/display3D/IndexBuffer3D.hx index 851025798fc..fc41aed2259 100644 --- a/std/flash/display3D/IndexBuffer3D.hx +++ b/std/flash/display3D/IndexBuffer3D.hx @@ -1,6 +1,6 @@ package flash.display3D; -@:final extern class IndexBuffer3D { +extern final class IndexBuffer3D { function dispose() : Void; function uploadFromByteArray(data : flash.utils.ByteArray, byteArrayOffset : Int, startOffset : Int, count : Int) : Void; function uploadFromVector(data : flash.Vector, startOffset : Int, count : Int) : Void; diff --git a/std/flash/display3D/Program3D.hx b/std/flash/display3D/Program3D.hx index 5cc9d6b166c..8ac34a4ba7b 100644 --- a/std/flash/display3D/Program3D.hx +++ b/std/flash/display3D/Program3D.hx @@ -1,6 +1,6 @@ package flash.display3D; -@:final extern class Program3D { +extern final class Program3D { function dispose() : Void; function upload(vertexProgram : flash.utils.ByteArray, fragmentProgram : flash.utils.ByteArray) : Void; } diff --git a/std/flash/display3D/textures/CubeTexture.hx b/std/flash/display3D/textures/CubeTexture.hx index 5d334a73b1f..1d93b40dde2 100644 --- a/std/flash/display3D/textures/CubeTexture.hx +++ b/std/flash/display3D/textures/CubeTexture.hx @@ -1,6 +1,6 @@ package flash.display3D.textures; -@:final extern class CubeTexture extends TextureBase { +extern final class CubeTexture extends TextureBase { function uploadCompressedTextureFromByteArray(data : flash.utils.ByteArray, byteArrayOffset : UInt, async : Bool = false) : Void; function uploadFromBitmapData(source : flash.display.BitmapData, side : UInt, miplevel : UInt = 0) : Void; function uploadFromByteArray(data : flash.utils.ByteArray, byteArrayOffset : UInt, side : UInt, miplevel : UInt = 0) : Void; diff --git a/std/flash/display3D/textures/RectangleTexture.hx b/std/flash/display3D/textures/RectangleTexture.hx index 1f4316c47a4..01a34acd141 100644 --- a/std/flash/display3D/textures/RectangleTexture.hx +++ b/std/flash/display3D/textures/RectangleTexture.hx @@ -1,6 +1,6 @@ package flash.display3D.textures; -@:final extern class RectangleTexture extends TextureBase { +extern final class RectangleTexture extends TextureBase { function new() : Void; function uploadFromBitmapData(source : flash.display.BitmapData) : Void; function uploadFromByteArray(data : flash.utils.ByteArray, byteArrayOffset : UInt) : Void; diff --git a/std/flash/display3D/textures/Texture.hx b/std/flash/display3D/textures/Texture.hx index 9f3fea38103..b47e2e81b38 100644 --- a/std/flash/display3D/textures/Texture.hx +++ b/std/flash/display3D/textures/Texture.hx @@ -1,6 +1,6 @@ package flash.display3D.textures; -@:final extern class Texture extends TextureBase { +extern final class Texture extends TextureBase { function uploadCompressedTextureFromByteArray(data : flash.utils.ByteArray, byteArrayOffset : UInt, async : Bool = false) : Void; function uploadFromBitmapData(source : flash.display.BitmapData, miplevel : UInt = 0) : Void; function uploadFromByteArray(data : flash.utils.ByteArray, byteArrayOffset : UInt, miplevel : UInt = 0) : Void; diff --git a/std/flash/display3D/textures/VideoTexture.hx b/std/flash/display3D/textures/VideoTexture.hx index ae3175e9069..3955c75d83c 100644 --- a/std/flash/display3D/textures/VideoTexture.hx +++ b/std/flash/display3D/textures/VideoTexture.hx @@ -1,9 +1,11 @@ package flash.display3D.textures; -@:final extern class VideoTexture extends TextureBase { - var videoHeight(default,never) : Int; - var videoWidth(default,never) : Int; +extern final class VideoTexture extends TextureBase { + @:flash.property var videoHeight(get,never) : Int; + @:flash.property var videoWidth(get,never) : Int; function new() : Void; function attachCamera(theCamera : flash.media.Camera) : Void; function attachNetStream(netStream : flash.net.NetStream) : Void; + private function get_videoHeight() : Int; + private function get_videoWidth() : Int; } diff --git a/std/flash/errors/DRMManagerError.hx b/std/flash/errors/DRMManagerError.hx index 573d73c1a46..357bb4f75cd 100644 --- a/std/flash/errors/DRMManagerError.hx +++ b/std/flash/errors/DRMManagerError.hx @@ -1,7 +1,8 @@ package flash.errors; @:require(flash10_1) extern class DRMManagerError extends Error { - var subErrorID(default,never) : Int; + @:flash.property var subErrorID(get,never) : Int; function new(message : String, id : Int, subErrorID : Int) : Void; + private function get_subErrorID() : Int; function toString() : String; } diff --git a/std/flash/errors/Error.hx b/std/flash/errors/Error.hx index b5bd7281040..4711f68e82c 100644 --- a/std/flash/errors/Error.hx +++ b/std/flash/errors/Error.hx @@ -1,12 +1,13 @@ package flash.errors; extern class Error #if !flash_strict implements Dynamic #end { - var errorID(default,never) : Int; + @:flash.property var errorID(get,never) : Int; var message : Dynamic; var name : Dynamic; function new(?message : Dynamic, id : Dynamic = 0) : Void; function getStackTrace() : String; - static var length(default,never) : Int; + private function get_errorID() : Int; + static final length : Int; static function getErrorMessage(index : Int) : String; - static function throwError(type : Class, index : UInt, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Dynamic; + static function throwError(type : Class, index : UInt, restArgs : haxe.extern.Rest) : Dynamic; } diff --git a/std/flash/events/AVDictionaryDataEvent.hx b/std/flash/events/AVDictionaryDataEvent.hx index 98e41dbef99..c5d2c5914f1 100644 --- a/std/flash/events/AVDictionaryDataEvent.hx +++ b/std/flash/events/AVDictionaryDataEvent.hx @@ -1,8 +1,10 @@ package flash.events; extern class AVDictionaryDataEvent extends Event { - var dictionary(default,never) : flash.utils.Dictionary; - var time(default,never) : Float; + @:flash.property var dictionary(get,never) : flash.utils.Dictionary; + @:flash.property var time(get,never) : Float; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?init_dictionary : flash.utils.Dictionary, init_dataTime : Float = 0) : Void; - static var AV_DICTIONARY_DATA(default,never) : String; + private function get_dictionary() : flash.utils.Dictionary; + private function get_time() : Float; + static final AV_DICTIONARY_DATA : String; } diff --git a/std/flash/events/AVHTTPStatusEvent.hx b/std/flash/events/AVHTTPStatusEvent.hx index a0f02831467..cea61c44708 100644 --- a/std/flash/events/AVHTTPStatusEvent.hx +++ b/std/flash/events/AVHTTPStatusEvent.hx @@ -1,9 +1,14 @@ package flash.events; extern class AVHTTPStatusEvent extends Event { - var responseHeaders : Array; - var responseURL : String; - var status(default,never) : Int; + @:flash.property var responseHeaders(get,set) : Array; + @:flash.property var responseURL(get,set) : String; + @:flash.property var status(get,never) : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, status : Int = 0, ?responseUrl : String, ?responseHeaders : Array) : Void; - static var AV_HTTP_RESPONSE_STATUS(default,never) : String; + private function get_responseHeaders() : Array; + private function get_responseURL() : String; + private function get_status() : Int; + private function set_responseHeaders(value : Array) : Array; + private function set_responseURL(value : String) : String; + static final AV_HTTP_RESPONSE_STATUS : String; } diff --git a/std/flash/events/AVLoadInfoEvent.hx b/std/flash/events/AVLoadInfoEvent.hx index 2415b32f5a5..cd23ef46267 100644 --- a/std/flash/events/AVLoadInfoEvent.hx +++ b/std/flash/events/AVLoadInfoEvent.hx @@ -1,7 +1,8 @@ package flash.events; extern class AVLoadInfoEvent extends Event { - var loadInfo(default,never) : flash.utils.Dictionary; + @:flash.property var loadInfo(get,never) : flash.utils.Dictionary; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inLoadInfo : flash.utils.Dictionary) : Void; - static var AV_LOAD_INFO(default,never) : Dynamic; + private function get_loadInfo() : flash.utils.Dictionary; + static final AV_LOAD_INFO : Dynamic; } diff --git a/std/flash/events/AVManifestLoadEvent.hx b/std/flash/events/AVManifestLoadEvent.hx index 5a168b6e138..be53c47b959 100644 --- a/std/flash/events/AVManifestLoadEvent.hx +++ b/std/flash/events/AVManifestLoadEvent.hx @@ -1,10 +1,14 @@ package flash.events; extern class AVManifestLoadEvent extends Event { - var duration(default,never) : Float; - var handle(default,never) : Int; - var result(default,never) : flash.media.AVResult; - var userData(default,never) : Int; + @:flash.property var duration(get,never) : Float; + @:flash.property var handle(get,never) : Int; + @:flash.property var result(get,never) : flash.media.AVResult; + @:flash.property var userData(get,never) : Int; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, inResult : Int = 0, inUserData : Int = 0, inHandle : Int = 0, inDuration : Float = 0) : Void; - static var AV_MANIFEST_LOAD(default,never) : String; + private function get_duration() : Float; + private function get_handle() : Int; + private function get_result() : flash.media.AVResult; + private function get_userData() : Int; + static final AV_MANIFEST_LOAD : String; } diff --git a/std/flash/events/AVPauseAtPeriodEndEvent.hx b/std/flash/events/AVPauseAtPeriodEndEvent.hx index 2a577c888ce..cbf9fa5af96 100644 --- a/std/flash/events/AVPauseAtPeriodEndEvent.hx +++ b/std/flash/events/AVPauseAtPeriodEndEvent.hx @@ -1,7 +1,8 @@ package flash.events; extern class AVPauseAtPeriodEndEvent extends Event { - var userData(default,never) : Int; + @:flash.property var userData(get,never) : Int; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, userData : Int = 0) : Void; - static var AV_PAUSE_AT_PERIOD_END(default,never) : String; + private function get_userData() : Int; + static final AV_PAUSE_AT_PERIOD_END : String; } diff --git a/std/flash/events/AVPlayStateEvent.hx b/std/flash/events/AVPlayStateEvent.hx index f5c6d2174bd..6613ac6ded4 100644 --- a/std/flash/events/AVPlayStateEvent.hx +++ b/std/flash/events/AVPlayStateEvent.hx @@ -1,7 +1,8 @@ package flash.events; extern class AVPlayStateEvent extends Event { - var playState(default,never) : flash.media.AVPlayState; + @:flash.property var playState(get,never) : flash.media.AVPlayState; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, inState : Int = 0) : Void; - static var AV_PLAY_STATE(default,never) : String; + private function get_playState() : flash.media.AVPlayState; + static final AV_PLAY_STATE : String; } diff --git a/std/flash/events/AVStatusEvent.hx b/std/flash/events/AVStatusEvent.hx index 99a2a806fb1..5a3a270d254 100644 --- a/std/flash/events/AVStatusEvent.hx +++ b/std/flash/events/AVStatusEvent.hx @@ -1,25 +1,28 @@ package flash.events; extern class AVStatusEvent extends Event { - var description(default,never) : String; - var notificationType(default,never) : String; - var result(default,never) : flash.media.AVResult; + @:flash.property var description(get,never) : String; + @:flash.property var notificationType(get,never) : String; + @:flash.property var result(get,never) : flash.media.AVResult; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inNotificationType : String, inResult : Int = 0, ?inDescription : String) : Void; - static var AV_STATUS(default,never) : String; - static var BACKGROUND_MANIFEST_ERROR(default,never) : String; - static var BACKGROUND_MANIFEST_WARNING(default,never) : String; - static var BUFFER_STATE(default,never) : String; - static var DECODER_TYPE(default,never) : String; - static var DIMENSION_CHANGE(default,never) : String; - static var ERROR(default,never) : String; - static var INSERTION_COMPLETE(default,never) : String; - static var LOAD_COMPLETE(default,never) : String; - static var MANIFEST_UPDATE(default,never) : String; - static var PLAY_STATE(default,never) : String; - static var RENDER_TYPE(default,never) : String; - static var SEEK_COMPLETE(default,never) : String; - static var STEP_COMPLETE(default,never) : String; - static var STREAM_SWITCH(default,never) : String; - static var TRICKPLAY_ENDED(default,never) : String; - static var WARNING(default,never) : String; + private function get_description() : String; + private function get_notificationType() : String; + private function get_result() : flash.media.AVResult; + static final AV_STATUS : String; + static final BACKGROUND_MANIFEST_ERROR : String; + static final BACKGROUND_MANIFEST_WARNING : String; + static final BUFFER_STATE : String; + static final DECODER_TYPE : String; + static final DIMENSION_CHANGE : String; + static final ERROR : String; + static final INSERTION_COMPLETE : String; + static final LOAD_COMPLETE : String; + static final MANIFEST_UPDATE : String; + static final PLAY_STATE : String; + static final RENDER_TYPE : String; + static final SEEK_COMPLETE : String; + static final STEP_COMPLETE : String; + static final STREAM_SWITCH : String; + static final TRICKPLAY_ENDED : String; + static final WARNING : String; } diff --git a/std/flash/events/AVStreamSwitchEvent.hx b/std/flash/events/AVStreamSwitchEvent.hx index e216a7af216..3ffc530e063 100644 --- a/std/flash/events/AVStreamSwitchEvent.hx +++ b/std/flash/events/AVStreamSwitchEvent.hx @@ -1,13 +1,18 @@ package flash.events; extern class AVStreamSwitchEvent extends Event { - var bitrate(default,never) : Int; - var description(default,never) : String; - var switchType(default,never) : Int; - var time(default,never) : Float; - var userData(default,never) : Int; + @:flash.property var bitrate(get,never) : Int; + @:flash.property var description(get,never) : String; + @:flash.property var switchType(get,never) : Int; + @:flash.property var time(get,never) : Float; + @:flash.property var userData(get,never) : Int; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, time : Float = 0, switchType : Int = 0, bitrate : Int = 0, ?description : String, userData : Int = 0) : Void; - static var ABR_SWITCH(default,never) : Int; - static var AV_STREAM_SWITCH(default,never) : String; - static var PERIOD_SWITCH(default,never) : Int; + private function get_bitrate() : Int; + private function get_description() : String; + private function get_switchType() : Int; + private function get_time() : Float; + private function get_userData() : Int; + static final ABR_SWITCH : Int; + static final AV_STREAM_SWITCH : String; + static final PERIOD_SWITCH : Int; } diff --git a/std/flash/events/AccelerometerEvent.hx b/std/flash/events/AccelerometerEvent.hx index 08997c6d0a9..430d1d796ab 100644 --- a/std/flash/events/AccelerometerEvent.hx +++ b/std/flash/events/AccelerometerEvent.hx @@ -1,10 +1,18 @@ package flash.events; @:require(flash10_1) extern class AccelerometerEvent extends Event { - var accelerationX : Float; - var accelerationY : Float; - var accelerationZ : Float; - var timestamp : Float; + @:flash.property var accelerationX(get,set) : Float; + @:flash.property var accelerationY(get,set) : Float; + @:flash.property var accelerationZ(get,set) : Float; + @:flash.property var timestamp(get,set) : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, timestamp : Float = 0, accelerationX : Float = 0, accelerationY : Float = 0, accelerationZ : Float = 0) : Void; - static var UPDATE(default,never) : String; + private function get_accelerationX() : Float; + private function get_accelerationY() : Float; + private function get_accelerationZ() : Float; + private function get_timestamp() : Float; + private function set_accelerationX(value : Float) : Float; + private function set_accelerationY(value : Float) : Float; + private function set_accelerationZ(value : Float) : Float; + private function set_timestamp(value : Float) : Float; + static final UPDATE : String; } diff --git a/std/flash/events/ActivityEvent.hx b/std/flash/events/ActivityEvent.hx index c569a3da740..a746a513261 100644 --- a/std/flash/events/ActivityEvent.hx +++ b/std/flash/events/ActivityEvent.hx @@ -1,7 +1,9 @@ package flash.events; extern class ActivityEvent extends Event { - var activating : Bool; + @:flash.property var activating(get,set) : Bool; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, activating : Bool = false) : Void; - static var ACTIVITY(default,never) : String; + private function get_activating() : Bool; + private function set_activating(value : Bool) : Bool; + static final ACTIVITY : String; } diff --git a/std/flash/events/AsyncErrorEvent.hx b/std/flash/events/AsyncErrorEvent.hx index 00e8def810c..f80c605430c 100644 --- a/std/flash/events/AsyncErrorEvent.hx +++ b/std/flash/events/AsyncErrorEvent.hx @@ -3,5 +3,5 @@ package flash.events; extern class AsyncErrorEvent extends ErrorEvent { var error : flash.errors.Error; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, ?error : flash.errors.Error) : Void; - static var ASYNC_ERROR(default,never) : String; + static final ASYNC_ERROR : String; } diff --git a/std/flash/events/AudioOutputChangeEvent.hx b/std/flash/events/AudioOutputChangeEvent.hx new file mode 100644 index 00000000000..e0aab746632 --- /dev/null +++ b/std/flash/events/AudioOutputChangeEvent.hx @@ -0,0 +1,8 @@ +package flash.events; + +extern class AudioOutputChangeEvent extends Event { + @:flash.property var reason(get,never) : String; + function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?reason : String) : Void; + private function get_reason() : String; + static final AUDIO_OUTPUT_CHANGE : String; +} diff --git a/std/flash/events/ContextMenuEvent.hx b/std/flash/events/ContextMenuEvent.hx index 35cc0959ca7..be2bc27074d 100644 --- a/std/flash/events/ContextMenuEvent.hx +++ b/std/flash/events/ContextMenuEvent.hx @@ -1,10 +1,16 @@ package flash.events; extern class ContextMenuEvent extends Event { - var contextMenuOwner : flash.display.InteractiveObject; - @:require(flash10) var isMouseTargetInaccessible : Bool; - var mouseTarget : flash.display.InteractiveObject; + @:flash.property var contextMenuOwner(get,set) : flash.display.InteractiveObject; + @:flash.property @:require(flash10) var isMouseTargetInaccessible(get,set) : Bool; + @:flash.property var mouseTarget(get,set) : flash.display.InteractiveObject; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?mouseTarget : flash.display.InteractiveObject, ?contextMenuOwner : flash.display.InteractiveObject) : Void; - static var MENU_ITEM_SELECT(default,never) : String; - static var MENU_SELECT(default,never) : String; + private function get_contextMenuOwner() : flash.display.InteractiveObject; + private function get_isMouseTargetInaccessible() : Bool; + private function get_mouseTarget() : flash.display.InteractiveObject; + private function set_contextMenuOwner(value : flash.display.InteractiveObject) : flash.display.InteractiveObject; + private function set_isMouseTargetInaccessible(value : Bool) : Bool; + private function set_mouseTarget(value : flash.display.InteractiveObject) : flash.display.InteractiveObject; + static final MENU_ITEM_SELECT : String; + static final MENU_SELECT : String; } diff --git a/std/flash/events/DRMAuthenticateEvent.hx b/std/flash/events/DRMAuthenticateEvent.hx index 02181ee55b8..4c7d735600c 100644 --- a/std/flash/events/DRMAuthenticateEvent.hx +++ b/std/flash/events/DRMAuthenticateEvent.hx @@ -1,14 +1,20 @@ package flash.events; @:require(flash10_1) extern class DRMAuthenticateEvent extends Event { - var authenticationType(default,never) : String; - var header(default,never) : String; - var netstream(default,never) : flash.net.NetStream; - var passwordPrompt(default,never) : String; - var urlPrompt(default,never) : String; - var usernamePrompt(default,never) : String; + @:flash.property var authenticationType(get,never) : String; + @:flash.property var header(get,never) : String; + @:flash.property var netstream(get,never) : flash.net.NetStream; + @:flash.property var passwordPrompt(get,never) : String; + @:flash.property var urlPrompt(get,never) : String; + @:flash.property var usernamePrompt(get,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?header : String, ?userPrompt : String, ?passPrompt : String, ?urlPrompt : String, ?authenticationType : String, ?netstream : flash.net.NetStream) : Void; - static var AUTHENTICATION_TYPE_DRM(default,never) : String; - static var AUTHENTICATION_TYPE_PROXY(default,never) : String; - static var DRM_AUTHENTICATE(default,never) : String; + private function get_authenticationType() : String; + private function get_header() : String; + private function get_netstream() : flash.net.NetStream; + private function get_passwordPrompt() : String; + private function get_urlPrompt() : String; + private function get_usernamePrompt() : String; + static final AUTHENTICATION_TYPE_DRM : String; + static final AUTHENTICATION_TYPE_PROXY : String; + static final DRM_AUTHENTICATE : String; } diff --git a/std/flash/events/DRMAuthenticationCompleteEvent.hx b/std/flash/events/DRMAuthenticationCompleteEvent.hx index 018b08a6793..47c01cec881 100644 --- a/std/flash/events/DRMAuthenticationCompleteEvent.hx +++ b/std/flash/events/DRMAuthenticationCompleteEvent.hx @@ -1,9 +1,15 @@ package flash.events; @:require(flash10_1) extern class DRMAuthenticationCompleteEvent extends Event { - var domain : String; - var serverURL : String; - var token : flash.utils.ByteArray; + @:flash.property var domain(get,set) : String; + @:flash.property var serverURL(get,set) : String; + @:flash.property var token(get,set) : flash.utils.ByteArray; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inServerURL : String, ?inDomain : String, ?inToken : flash.utils.ByteArray) : Void; - static var AUTHENTICATION_COMPLETE(default,never) : String; + private function get_domain() : String; + private function get_serverURL() : String; + private function get_token() : flash.utils.ByteArray; + private function set_domain(value : String) : String; + private function set_serverURL(value : String) : String; + private function set_token(value : flash.utils.ByteArray) : flash.utils.ByteArray; + static final AUTHENTICATION_COMPLETE : String; } diff --git a/std/flash/events/DRMAuthenticationErrorEvent.hx b/std/flash/events/DRMAuthenticationErrorEvent.hx index cfd134f6d07..62217a9a2a4 100644 --- a/std/flash/events/DRMAuthenticationErrorEvent.hx +++ b/std/flash/events/DRMAuthenticationErrorEvent.hx @@ -1,9 +1,15 @@ package flash.events; @:require(flash10_1) extern class DRMAuthenticationErrorEvent extends ErrorEvent { - var domain : String; - var serverURL : String; - var subErrorID : Int; + @:flash.property var domain(get,set) : String; + @:flash.property var serverURL(get,set) : String; + @:flash.property var subErrorID(get,set) : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inDetail : String, inErrorID : Int = 0, inSubErrorID : Int = 0, ?inServerURL : String, ?inDomain : String) : Void; - static var AUTHENTICATION_ERROR(default,never) : String; + private function get_domain() : String; + private function get_serverURL() : String; + private function get_subErrorID() : Int; + private function set_domain(value : String) : String; + private function set_serverURL(value : String) : String; + private function set_subErrorID(value : Int) : Int; + static final AUTHENTICATION_ERROR : String; } diff --git a/std/flash/events/DRMDeviceGroupErrorEvent.hx b/std/flash/events/DRMDeviceGroupErrorEvent.hx index 982bf386ff1..3585a8c91a7 100644 --- a/std/flash/events/DRMDeviceGroupErrorEvent.hx +++ b/std/flash/events/DRMDeviceGroupErrorEvent.hx @@ -1,11 +1,17 @@ package flash.events; extern class DRMDeviceGroupErrorEvent extends ErrorEvent { - var deviceGroup : flash.net.drm.DRMDeviceGroup; - var drmUpdateNeeded(default,never) : Bool; - var subErrorID : Int; - var systemUpdateNeeded(default,never) : Bool; + @:flash.property var deviceGroup(get,set) : flash.net.drm.DRMDeviceGroup; + @:flash.property var drmUpdateNeeded(get,never) : Bool; + @:flash.property var subErrorID(get,set) : Int; + @:flash.property var systemUpdateNeeded(get,never) : Bool; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?errorDetail : String, errorCode : Int = 0, subErrorID : Int = 0, ?deviceGroup : flash.net.drm.DRMDeviceGroup, systemUpdateNeeded : Bool = false, drmUpdateNeeded : Bool = false) : Void; - static var ADD_TO_DEVICE_GROUP_ERROR(default,never) : String; - static var REMOVE_FROM_DEVICE_GROUP_ERROR(default,never) : String; + private function get_deviceGroup() : flash.net.drm.DRMDeviceGroup; + private function get_drmUpdateNeeded() : Bool; + private function get_subErrorID() : Int; + private function get_systemUpdateNeeded() : Bool; + private function set_deviceGroup(value : flash.net.drm.DRMDeviceGroup) : flash.net.drm.DRMDeviceGroup; + private function set_subErrorID(value : Int) : Int; + static final ADD_TO_DEVICE_GROUP_ERROR : String; + static final REMOVE_FROM_DEVICE_GROUP_ERROR : String; } diff --git a/std/flash/events/DRMDeviceGroupEvent.hx b/std/flash/events/DRMDeviceGroupEvent.hx index 57af6bd0a11..2b579c267f3 100644 --- a/std/flash/events/DRMDeviceGroupEvent.hx +++ b/std/flash/events/DRMDeviceGroupEvent.hx @@ -1,8 +1,10 @@ package flash.events; extern class DRMDeviceGroupEvent extends Event { - var deviceGroup : flash.net.drm.DRMDeviceGroup; + @:flash.property var deviceGroup(get,set) : flash.net.drm.DRMDeviceGroup; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?deviceGroup : flash.net.drm.DRMDeviceGroup) : Void; - static var ADD_TO_DEVICE_GROUP_COMPLETE(default,never) : String; - static var REMOVE_FROM_DEVICE_GROUP_COMPLETE(default,never) : String; + private function get_deviceGroup() : flash.net.drm.DRMDeviceGroup; + private function set_deviceGroup(value : flash.net.drm.DRMDeviceGroup) : flash.net.drm.DRMDeviceGroup; + static final ADD_TO_DEVICE_GROUP_COMPLETE : String; + static final REMOVE_FROM_DEVICE_GROUP_COMPLETE : String; } diff --git a/std/flash/events/DRMErrorEvent.hx b/std/flash/events/DRMErrorEvent.hx index 9e035fab261..0f3cce7667e 100644 --- a/std/flash/events/DRMErrorEvent.hx +++ b/std/flash/events/DRMErrorEvent.hx @@ -1,11 +1,16 @@ package flash.events; @:require(flash10_1) extern class DRMErrorEvent extends ErrorEvent { - var contentData : flash.net.drm.DRMContentData; - var drmUpdateNeeded(default,never) : Bool; - var subErrorID(default,never) : Int; - var systemUpdateNeeded(default,never) : Bool; + @:flash.property var contentData(get,set) : flash.net.drm.DRMContentData; + @:flash.property var drmUpdateNeeded(get,never) : Bool; + @:flash.property var subErrorID(get,never) : Int; + @:flash.property var systemUpdateNeeded(get,never) : Bool; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inErrorDetail : String, inErrorCode : Int = 0, insubErrorID : Int = 0, ?inMetadata : flash.net.drm.DRMContentData, inSystemUpdateNeeded : Bool = false, inDrmUpdateNeeded : Bool = false) : Void; - static var DRM_ERROR(default,never) : String; - static var DRM_LOAD_DEVICEID_ERROR(default,never) : String; + private function get_contentData() : flash.net.drm.DRMContentData; + private function get_drmUpdateNeeded() : Bool; + private function get_subErrorID() : Int; + private function get_systemUpdateNeeded() : Bool; + private function set_contentData(value : flash.net.drm.DRMContentData) : flash.net.drm.DRMContentData; + static final DRM_ERROR : String; + static final DRM_LOAD_DEVICEID_ERROR : String; } diff --git a/std/flash/events/DRMLicenseRequestEvent.hx b/std/flash/events/DRMLicenseRequestEvent.hx index 873f4b8292a..745b46d90c9 100644 --- a/std/flash/events/DRMLicenseRequestEvent.hx +++ b/std/flash/events/DRMLicenseRequestEvent.hx @@ -1,7 +1,9 @@ package flash.events; extern class DRMLicenseRequestEvent extends Event { - var serverURL : String; + @:flash.property var serverURL(get,set) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inServerURL : String) : Void; - static var LICENSE_REQUEST(default,never) : String; + private function get_serverURL() : String; + private function set_serverURL(value : String) : String; + static final LICENSE_REQUEST : String; } diff --git a/std/flash/events/DRMMetadataEvent.hx b/std/flash/events/DRMMetadataEvent.hx index 4a4aebd011e..f279c73cb6d 100644 --- a/std/flash/events/DRMMetadataEvent.hx +++ b/std/flash/events/DRMMetadataEvent.hx @@ -1,8 +1,10 @@ package flash.events; extern class DRMMetadataEvent extends Event { - var drmMetadata(default,never) : flash.net.drm.DRMContentData; - var timestamp(default,never) : Float; + @:flash.property var drmMetadata(get,never) : flash.net.drm.DRMContentData; + @:flash.property var timestamp(get,never) : Float; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inMetadata : flash.utils.ByteArray, inTimestamp : Float = 0) : Void; - static var DRM_METADATA(default,never) : String; + private function get_drmMetadata() : flash.net.drm.DRMContentData; + private function get_timestamp() : Float; + static final DRM_METADATA : String; } diff --git a/std/flash/events/DRMReturnVoucherCompleteEvent.hx b/std/flash/events/DRMReturnVoucherCompleteEvent.hx index dbec165c5d5..31ef37dd84b 100644 --- a/std/flash/events/DRMReturnVoucherCompleteEvent.hx +++ b/std/flash/events/DRMReturnVoucherCompleteEvent.hx @@ -1,10 +1,18 @@ package flash.events; extern class DRMReturnVoucherCompleteEvent extends Event { - var licenseID : String; - var numberOfVouchersReturned : Int; - var policyID : String; - var serverURL : String; + @:flash.property var licenseID(get,set) : String; + @:flash.property var numberOfVouchersReturned(get,set) : Int; + @:flash.property var policyID(get,set) : String; + @:flash.property var serverURL(get,set) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inServerURL : String, ?inLicenseID : String, ?inPolicyID : String, inNumberOfVouchersReturned : Int = 0) : Void; - static var RETURN_VOUCHER_COMPLETE(default,never) : String; + private function get_licenseID() : String; + private function get_numberOfVouchersReturned() : Int; + private function get_policyID() : String; + private function get_serverURL() : String; + private function set_licenseID(value : String) : String; + private function set_numberOfVouchersReturned(value : Int) : Int; + private function set_policyID(value : String) : String; + private function set_serverURL(value : String) : String; + static final RETURN_VOUCHER_COMPLETE : String; } diff --git a/std/flash/events/DRMReturnVoucherErrorEvent.hx b/std/flash/events/DRMReturnVoucherErrorEvent.hx index 568a31ad995..91fc46f4d1f 100644 --- a/std/flash/events/DRMReturnVoucherErrorEvent.hx +++ b/std/flash/events/DRMReturnVoucherErrorEvent.hx @@ -1,10 +1,18 @@ package flash.events; extern class DRMReturnVoucherErrorEvent extends ErrorEvent { - var licenseID : String; - var policyID : String; - var serverURL : String; - var subErrorID : Int; + @:flash.property var licenseID(get,set) : String; + @:flash.property var policyID(get,set) : String; + @:flash.property var serverURL(get,set) : String; + @:flash.property var subErrorID(get,set) : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inDetail : String, inErrorID : Int = 0, inSubErrorID : Int = 0, ?inServerURL : String, ?inLicenseID : String, ?inPolicyID : String) : Void; - static var RETURN_VOUCHER_ERROR(default,never) : String; + private function get_licenseID() : String; + private function get_policyID() : String; + private function get_serverURL() : String; + private function get_subErrorID() : Int; + private function set_licenseID(value : String) : String; + private function set_policyID(value : String) : String; + private function set_serverURL(value : String) : String; + private function set_subErrorID(value : Int) : Int; + static final RETURN_VOUCHER_ERROR : String; } diff --git a/std/flash/events/DRMStatusEvent.hx b/std/flash/events/DRMStatusEvent.hx index ac71f0b5037..b9e6018d475 100644 --- a/std/flash/events/DRMStatusEvent.hx +++ b/std/flash/events/DRMStatusEvent.hx @@ -1,9 +1,15 @@ package flash.events; @:require(flash10_1) extern class DRMStatusEvent extends Event { - var contentData : flash.net.drm.DRMContentData; - var isLocal : Bool; - var voucher : flash.net.drm.DRMVoucher; + @:flash.property var contentData(get,set) : flash.net.drm.DRMContentData; + @:flash.property var isLocal(get,set) : Bool; + @:flash.property var voucher(get,set) : flash.net.drm.DRMVoucher; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inMetadata : flash.net.drm.DRMContentData, ?inVoucher : flash.net.drm.DRMVoucher, inLocal : Bool = false) : Void; - static var DRM_STATUS(default,never) : String; + private function get_contentData() : flash.net.drm.DRMContentData; + private function get_isLocal() : Bool; + private function get_voucher() : flash.net.drm.DRMVoucher; + private function set_contentData(value : flash.net.drm.DRMContentData) : flash.net.drm.DRMContentData; + private function set_isLocal(value : Bool) : Bool; + private function set_voucher(value : flash.net.drm.DRMVoucher) : flash.net.drm.DRMVoucher; + static final DRM_STATUS : String; } diff --git a/std/flash/events/DataEvent.hx b/std/flash/events/DataEvent.hx index 359146c4a49..bbbde23cb3d 100644 --- a/std/flash/events/DataEvent.hx +++ b/std/flash/events/DataEvent.hx @@ -1,8 +1,10 @@ package flash.events; extern class DataEvent extends TextEvent { - var data : String; + @:flash.property var data(get,set) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?data : String) : Void; - static var DATA(default,never) : String; - static var UPLOAD_COMPLETE_DATA(default,never) : String; + private function get_data() : String; + private function set_data(value : String) : String; + static final DATA : String; + static final UPLOAD_COMPLETE_DATA : String; } diff --git a/std/flash/events/ErrorEvent.hx b/std/flash/events/ErrorEvent.hx index 1541236f46d..a8ed65b52de 100644 --- a/std/flash/events/ErrorEvent.hx +++ b/std/flash/events/ErrorEvent.hx @@ -1,7 +1,8 @@ package flash.events; extern class ErrorEvent extends TextEvent { - @:require(flash10_1) var errorID(default,never) : Int; + @:flash.property @:require(flash10_1) var errorID(get,never) : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, id : Int = 0) : Void; - static var ERROR(default,never) : String; + private function get_errorID() : Int; + static final ERROR : String; } diff --git a/std/flash/events/Event.hx b/std/flash/events/Event.hx index 1406fbde427..6594afd4540 100644 --- a/std/flash/events/Event.hx +++ b/std/flash/events/Event.hx @@ -1,61 +1,67 @@ package flash.events; extern class Event { - var bubbles(default,never) : Bool; - var cancelable(default,never) : Bool; - var currentTarget(default,never) : Dynamic; - var eventPhase(default,never) : EventPhase; - var target(default,never) : Dynamic; - var type(default,never) : String; + @:flash.property var bubbles(get,never) : Bool; + @:flash.property var cancelable(get,never) : Bool; + @:flash.property var currentTarget(get,never) : Dynamic; + @:flash.property var eventPhase(get,never) : EventPhase; + @:flash.property var target(get,never) : Dynamic; + @:flash.property var type(get,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false) : Void; function clone() : Event; - function formatToString(className : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : String; + function formatToString(className : String, restArgs : haxe.extern.Rest) : String; + private function get_bubbles() : Bool; + private function get_cancelable() : Bool; + private function get_currentTarget() : Dynamic; + private function get_eventPhase() : EventPhase; + private function get_target() : Dynamic; + private function get_type() : String; function isDefaultPrevented() : Bool; function preventDefault() : Void; function stopImmediatePropagation() : Void; function stopPropagation() : Void; function toString() : String; - static var ACTIVATE(default,never) : String; - static var ADDED(default,never) : String; - static var ADDED_TO_STAGE(default,never) : String; - static var BROWSER_ZOOM_CHANGE(default,never) : String; - static var CANCEL(default,never) : String; - static var CHANGE(default,never) : String; - static var CHANNEL_MESSAGE(default,never) : String; - static var CHANNEL_STATE(default,never) : String; - @:require(flash10) static var CLEAR(default,never) : String; - static var CLOSE(default,never) : String; - static var COMPLETE(default,never) : String; - static var CONNECT(default,never) : String; - @:require(flash11) static var CONTEXT3D_CREATE(default,never) : String; - @:require(flash10) static var COPY(default,never) : String; - @:require(flash10) static var CUT(default,never) : String; - static var DEACTIVATE(default,never) : String; - static var ENTER_FRAME(default,never) : String; - @:require(flash10) static var EXIT_FRAME(default,never) : String; - @:require(flash10) static var FRAME_CONSTRUCTED(default,never) : String; - @:require(flash11_3) static var FRAME_LABEL(default,never) : String; - static var FULLSCREEN(default,never) : String; - static var ID3(default,never) : String; - static var INIT(default,never) : String; - static var MOUSE_LEAVE(default,never) : String; - static var OPEN(default,never) : String; - @:require(flash10) static var PASTE(default,never) : String; - static var REMOVED(default,never) : String; - static var REMOVED_FROM_STAGE(default,never) : String; - static var RENDER(default,never) : String; - static var RESIZE(default,never) : String; - static var SCROLL(default,never) : String; - static var SELECT(default,never) : String; - @:require(flash10) static var SELECT_ALL(default,never) : String; - static var SOUND_COMPLETE(default,never) : String; - @:require(flash11_3) static var SUSPEND(default,never) : String; - static var TAB_CHILDREN_CHANGE(default,never) : String; - static var TAB_ENABLED_CHANGE(default,never) : String; - static var TAB_INDEX_CHANGE(default,never) : String; - @:require(flash11_3) static var TEXTURE_READY(default,never) : String; - @:require(flash11) static var TEXT_INTERACTION_MODE_CHANGE(default,never) : String; - static var UNLOAD(default,never) : String; - static var VIDEO_FRAME(default,never) : String; - static var WORKER_STATE(default,never) : String; + static final ACTIVATE : String; + static final ADDED : String; + static final ADDED_TO_STAGE : String; + static final BROWSER_ZOOM_CHANGE : String; + static final CANCEL : String; + static final CHANGE : String; + static final CHANNEL_MESSAGE : String; + static final CHANNEL_STATE : String; + @:require(flash10) static final CLEAR : String; + static final CLOSE : String; + static final COMPLETE : String; + static final CONNECT : String; + @:require(flash11) static final CONTEXT3D_CREATE : String; + @:require(flash10) static final COPY : String; + @:require(flash10) static final CUT : String; + static final DEACTIVATE : String; + static final ENTER_FRAME : String; + @:require(flash10) static final EXIT_FRAME : String; + @:require(flash10) static final FRAME_CONSTRUCTED : String; + @:require(flash11_3) static final FRAME_LABEL : String; + static final FULLSCREEN : String; + static final ID3 : String; + static final INIT : String; + static final MOUSE_LEAVE : String; + static final OPEN : String; + @:require(flash10) static final PASTE : String; + static final REMOVED : String; + static final REMOVED_FROM_STAGE : String; + static final RENDER : String; + static final RESIZE : String; + static final SCROLL : String; + static final SELECT : String; + @:require(flash10) static final SELECT_ALL : String; + static final SOUND_COMPLETE : String; + @:require(flash11_3) static final SUSPEND : String; + static final TAB_CHILDREN_CHANGE : String; + static final TAB_ENABLED_CHANGE : String; + static final TAB_INDEX_CHANGE : String; + @:require(flash11_3) static final TEXTURE_READY : String; + @:require(flash11) static final TEXT_INTERACTION_MODE_CHANGE : String; + static final UNLOAD : String; + static final VIDEO_FRAME : String; + static final WORKER_STATE : String; } diff --git a/std/flash/events/EventPhase.hx b/std/flash/events/EventPhase.hx index a704069b62a..87e3f2151ae 100644 --- a/std/flash/events/EventPhase.hx +++ b/std/flash/events/EventPhase.hx @@ -1,7 +1,7 @@ package flash.events; -@:fakeEnum(UInt) extern enum EventPhase { - AT_TARGET; - BUBBLING_PHASE; - CAPTURING_PHASE; +@:native("flash.events.EventPhase") extern enum abstract EventPhase(UInt) { + var AT_TARGET; + var BUBBLING_PHASE; + var CAPTURING_PHASE; } diff --git a/std/flash/events/FocusEvent.hx b/std/flash/events/FocusEvent.hx index 1142f5ab767..98c0dc50726 100644 --- a/std/flash/events/FocusEvent.hx +++ b/std/flash/events/FocusEvent.hx @@ -1,13 +1,21 @@ package flash.events; extern class FocusEvent extends Event { - @:require(flash10) var isRelatedObjectInaccessible : Bool; - var keyCode : UInt; - var relatedObject : flash.display.InteractiveObject; - var shiftKey : Bool; + @:flash.property @:require(flash10) var isRelatedObjectInaccessible(get,set) : Bool; + @:flash.property var keyCode(get,set) : UInt; + @:flash.property var relatedObject(get,set) : flash.display.InteractiveObject; + @:flash.property var shiftKey(get,set) : Bool; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, ?relatedObject : flash.display.InteractiveObject, shiftKey : Bool = false, keyCode : UInt = 0) : Void; - static var FOCUS_IN(default,never) : String; - static var FOCUS_OUT(default,never) : String; - static var KEY_FOCUS_CHANGE(default,never) : String; - static var MOUSE_FOCUS_CHANGE(default,never) : String; + private function get_isRelatedObjectInaccessible() : Bool; + private function get_keyCode() : UInt; + private function get_relatedObject() : flash.display.InteractiveObject; + private function get_shiftKey() : Bool; + private function set_isRelatedObjectInaccessible(value : Bool) : Bool; + private function set_keyCode(value : UInt) : UInt; + private function set_relatedObject(value : flash.display.InteractiveObject) : flash.display.InteractiveObject; + private function set_shiftKey(value : Bool) : Bool; + static final FOCUS_IN : String; + static final FOCUS_OUT : String; + static final KEY_FOCUS_CHANGE : String; + static final MOUSE_FOCUS_CHANGE : String; } diff --git a/std/flash/events/FullScreenEvent.hx b/std/flash/events/FullScreenEvent.hx index bcb6e000c82..4aa45411efa 100644 --- a/std/flash/events/FullScreenEvent.hx +++ b/std/flash/events/FullScreenEvent.hx @@ -1,9 +1,11 @@ package flash.events; extern class FullScreenEvent extends ActivityEvent { - var fullScreen(default,never) : Bool; - @:require(flash11_3) var interactive(default,never) : Bool; + @:flash.property var fullScreen(get,never) : Bool; + @:flash.property @:require(flash11_3) var interactive(get,never) : Bool; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, fullScreen : Bool = false, interactive : Bool = false) : Void; - static var FULL_SCREEN(default,never) : String; - @:require(flash11_3) static var FULL_SCREEN_INTERACTIVE_ACCEPTED(default,never) : String; + private function get_fullScreen() : Bool; + private function get_interactive() : Bool; + static final FULL_SCREEN : String; + @:require(flash11_3) static final FULL_SCREEN_INTERACTIVE_ACCEPTED : String; } diff --git a/std/flash/events/GameInputEvent.hx b/std/flash/events/GameInputEvent.hx index 7bcbb9a9661..5fd728861e6 100644 --- a/std/flash/events/GameInputEvent.hx +++ b/std/flash/events/GameInputEvent.hx @@ -1,9 +1,10 @@ package flash.events; -@:final @:require(flash11_8) extern class GameInputEvent extends Event { - var device(default,never) : flash.ui.GameInputDevice; +@:require(flash11_8) extern final class GameInputEvent extends Event { + @:flash.property var device(get,never) : flash.ui.GameInputDevice; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?device : flash.ui.GameInputDevice) : Void; - static var DEVICE_ADDED(default,never) : String; - static var DEVICE_REMOVED(default,never) : String; - static var DEVICE_UNUSABLE(default,never) : String; + private function get_device() : flash.ui.GameInputDevice; + static final DEVICE_ADDED : String; + static final DEVICE_REMOVED : String; + static final DEVICE_UNUSABLE : String; } diff --git a/std/flash/events/GeolocationEvent.hx b/std/flash/events/GeolocationEvent.hx index d6248acc436..2f2994a5cbc 100644 --- a/std/flash/events/GeolocationEvent.hx +++ b/std/flash/events/GeolocationEvent.hx @@ -1,14 +1,30 @@ package flash.events; @:require(flash10_1) extern class GeolocationEvent extends Event { - var altitude : Float; - var heading : Float; - var horizontalAccuracy : Float; - var latitude : Float; - var longitude : Float; - var speed : Float; - var timestamp : Float; - var verticalAccuracy : Float; + @:flash.property var altitude(get,set) : Float; + @:flash.property var heading(get,set) : Float; + @:flash.property var horizontalAccuracy(get,set) : Float; + @:flash.property var latitude(get,set) : Float; + @:flash.property var longitude(get,set) : Float; + @:flash.property var speed(get,set) : Float; + @:flash.property var timestamp(get,set) : Float; + @:flash.property var verticalAccuracy(get,set) : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, latitude : Float = 0, longitude : Float = 0, altitude : Float = 0, hAccuracy : Float = 0, vAccuracy : Float = 0, speed : Float = 0, heading : Float = 0, timestamp : Float = 0) : Void; - static var UPDATE(default,never) : String; + private function get_altitude() : Float; + private function get_heading() : Float; + private function get_horizontalAccuracy() : Float; + private function get_latitude() : Float; + private function get_longitude() : Float; + private function get_speed() : Float; + private function get_timestamp() : Float; + private function get_verticalAccuracy() : Float; + private function set_altitude(value : Float) : Float; + private function set_heading(value : Float) : Float; + private function set_horizontalAccuracy(value : Float) : Float; + private function set_latitude(value : Float) : Float; + private function set_longitude(value : Float) : Float; + private function set_speed(value : Float) : Float; + private function set_timestamp(value : Float) : Float; + private function set_verticalAccuracy(value : Float) : Float; + static final UPDATE : String; } diff --git a/std/flash/events/GestureEvent.hx b/std/flash/events/GestureEvent.hx index 40e002857d4..6b061abb982 100644 --- a/std/flash/events/GestureEvent.hx +++ b/std/flash/events/GestureEvent.hx @@ -1,15 +1,29 @@ package flash.events; @:require(flash10_1) extern class GestureEvent extends Event { - var altKey : Bool; - var ctrlKey : Bool; - var localX : Float; - var localY : Float; - var phase : String; - var shiftKey : Bool; - var stageX(default,never) : Float; - var stageY(default,never) : Float; + @:flash.property var altKey(get,set) : Bool; + @:flash.property var ctrlKey(get,set) : Bool; + @:flash.property var localX(get,set) : Float; + @:flash.property var localY(get,set) : Float; + @:flash.property var phase(get,set) : String; + @:flash.property var shiftKey(get,set) : Bool; + @:flash.property var stageX(get,never) : Float; + @:flash.property var stageY(get,never) : Float; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, ?phase : String, localX : Float = 0, localY : Float = 0, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false) : Void; + private function get_altKey() : Bool; + private function get_ctrlKey() : Bool; + private function get_localX() : Float; + private function get_localY() : Float; + private function get_phase() : String; + private function get_shiftKey() : Bool; + private function get_stageX() : Float; + private function get_stageY() : Float; + private function set_altKey(value : Bool) : Bool; + private function set_ctrlKey(value : Bool) : Bool; + private function set_localX(value : Float) : Float; + private function set_localY(value : Float) : Float; + private function set_phase(value : String) : String; + private function set_shiftKey(value : Bool) : Bool; function updateAfterEvent() : Void; - static var GESTURE_TWO_FINGER_TAP(default,never) : String; + static final GESTURE_TWO_FINGER_TAP : String; } diff --git a/std/flash/events/GesturePhase.hx b/std/flash/events/GesturePhase.hx index 0a10aac7dab..0780eb9778b 100644 --- a/std/flash/events/GesturePhase.hx +++ b/std/flash/events/GesturePhase.hx @@ -1,8 +1,8 @@ package flash.events; -@:fakeEnum(String) @:require(flash10_1) extern enum GesturePhase { - ALL; - BEGIN; - END; - UPDATE; +@:native("flash.events.GesturePhase") @:require(flash10_1) extern enum abstract GesturePhase(String) { + var ALL; + var BEGIN; + var END; + var UPDATE; } diff --git a/std/flash/events/HTTPStatusEvent.hx b/std/flash/events/HTTPStatusEvent.hx index 131b65cf1fc..fb75273e3d3 100644 --- a/std/flash/events/HTTPStatusEvent.hx +++ b/std/flash/events/HTTPStatusEvent.hx @@ -1,11 +1,18 @@ package flash.events; extern class HTTPStatusEvent extends Event { - var redirected : Bool; - @:require(flash10_1) var responseHeaders : Array; - @:require(flash10_1) var responseURL : String; - var status(default,never) : Int; + @:flash.property var redirected(get,set) : Bool; + @:flash.property @:require(flash10_1) var responseHeaders(get,set) : Array; + @:flash.property @:require(flash10_1) var responseURL(get,set) : String; + @:flash.property var status(get,never) : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, status : Int = 0, redirected : Bool = false) : Void; - @:require(flash10_1) static var HTTP_RESPONSE_STATUS(default,never) : String; - static var HTTP_STATUS(default,never) : String; + private function get_redirected() : Bool; + private function get_responseHeaders() : Array; + private function get_responseURL() : String; + private function get_status() : Int; + private function set_redirected(value : Bool) : Bool; + private function set_responseHeaders(value : Array) : Array; + private function set_responseURL(value : String) : String; + @:require(flash10_1) static final HTTP_RESPONSE_STATUS : String; + static final HTTP_STATUS : String; } diff --git a/std/flash/events/IMEEvent.hx b/std/flash/events/IMEEvent.hx index 0553d585716..7b991dd6ef8 100644 --- a/std/flash/events/IMEEvent.hx +++ b/std/flash/events/IMEEvent.hx @@ -1,8 +1,10 @@ package flash.events; extern class IMEEvent extends TextEvent { - @:require(flash10_1) var imeClient : flash.text.ime.IIMEClient; + @:flash.property @:require(flash10_1) var imeClient(get,set) : flash.text.ime.IIMEClient; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, ?imeClient : flash.text.ime.IIMEClient) : Void; - static var IME_COMPOSITION(default,never) : String; - @:require(flash10_1) static var IME_START_COMPOSITION(default,never) : String; + private function get_imeClient() : flash.text.ime.IIMEClient; + private function set_imeClient(value : flash.text.ime.IIMEClient) : flash.text.ime.IIMEClient; + static final IME_COMPOSITION : String; + @:require(flash10_1) static final IME_START_COMPOSITION : String; } diff --git a/std/flash/events/IOErrorEvent.hx b/std/flash/events/IOErrorEvent.hx index 4b351378c30..3ca285bd4b6 100644 --- a/std/flash/events/IOErrorEvent.hx +++ b/std/flash/events/IOErrorEvent.hx @@ -2,8 +2,8 @@ package flash.events; extern class IOErrorEvent extends ErrorEvent { function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, id : Int = 0) : Void; - static var DISK_ERROR(default,never) : String; - static var IO_ERROR(default,never) : String; - static var NETWORK_ERROR(default,never) : String; - static var VERIFY_ERROR(default,never) : String; + static final DISK_ERROR : String; + static final IO_ERROR : String; + static final NETWORK_ERROR : String; + static final VERIFY_ERROR : String; } diff --git a/std/flash/events/KeyboardEvent.hx b/std/flash/events/KeyboardEvent.hx index 5e913d4523a..1f9129a0343 100644 --- a/std/flash/events/KeyboardEvent.hx +++ b/std/flash/events/KeyboardEvent.hx @@ -1,14 +1,26 @@ package flash.events; extern class KeyboardEvent extends Event { - var altKey : Bool; - var charCode : UInt; - var ctrlKey : Bool; - var keyCode : UInt; - var keyLocation : flash.ui.KeyLocation; - var shiftKey : Bool; + @:flash.property var altKey(get,set) : Bool; + @:flash.property var charCode(get,set) : UInt; + @:flash.property var ctrlKey(get,set) : Bool; + @:flash.property var keyCode(get,set) : UInt; + @:flash.property var keyLocation(get,set) : flash.ui.KeyLocation; + @:flash.property var shiftKey(get,set) : Bool; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, charCodeValue : UInt = 0, keyCodeValue : UInt = 0, keyLocationValue : flash.ui.KeyLocation = 0, ctrlKeyValue : Bool = false, altKeyValue : Bool = false, shiftKeyValue : Bool = false) : Void; + private function get_altKey() : Bool; + private function get_charCode() : UInt; + private function get_ctrlKey() : Bool; + private function get_keyCode() : UInt; + private function get_keyLocation() : flash.ui.KeyLocation; + private function get_shiftKey() : Bool; + private function set_altKey(value : Bool) : Bool; + private function set_charCode(value : UInt) : UInt; + private function set_ctrlKey(value : Bool) : Bool; + private function set_keyCode(value : UInt) : UInt; + private function set_keyLocation(value : flash.ui.KeyLocation) : flash.ui.KeyLocation; + private function set_shiftKey(value : Bool) : Bool; function updateAfterEvent() : Void; - static var KEY_DOWN(default,never) : String; - static var KEY_UP(default,never) : String; + static final KEY_DOWN : String; + static final KEY_UP : String; } diff --git a/std/flash/events/MouseEvent.hx b/std/flash/events/MouseEvent.hx index c5b1d4c13ed..9376f099492 100644 --- a/std/flash/events/MouseEvent.hx +++ b/std/flash/events/MouseEvent.hx @@ -1,37 +1,61 @@ package flash.events; extern class MouseEvent extends Event { - var altKey : Bool; - var buttonDown : Bool; - var ctrlKey : Bool; - var delta : Int; - @:require(flash10) var isRelatedObjectInaccessible : Bool; - var localX : Float; - var localY : Float; - @:require(flash11_2) var movementX : Float; - @:require(flash11_2) var movementY : Float; - var relatedObject : flash.display.InteractiveObject; - var shiftKey : Bool; - var stageX(default,never) : Float; - var stageY(default,never) : Float; + @:flash.property var altKey(get,set) : Bool; + @:flash.property var buttonDown(get,set) : Bool; + @:flash.property var ctrlKey(get,set) : Bool; + @:flash.property var delta(get,set) : Int; + @:flash.property @:require(flash10) var isRelatedObjectInaccessible(get,set) : Bool; + @:flash.property var localX(get,set) : Float; + @:flash.property var localY(get,set) : Float; + @:flash.property @:require(flash11_2) var movementX(get,set) : Float; + @:flash.property @:require(flash11_2) var movementY(get,set) : Float; + @:flash.property var relatedObject(get,set) : flash.display.InteractiveObject; + @:flash.property var shiftKey(get,set) : Bool; + @:flash.property var stageX(get,never) : Float; + @:flash.property var stageY(get,never) : Float; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, localX : Null = 0, localY : Null = 0, ?relatedObject : flash.display.InteractiveObject, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false, buttonDown : Bool = false, delta : Int = 0) : Void; + private function get_altKey() : Bool; + private function get_buttonDown() : Bool; + private function get_ctrlKey() : Bool; + private function get_delta() : Int; + private function get_isRelatedObjectInaccessible() : Bool; + private function get_localX() : Float; + private function get_localY() : Float; + private function get_movementX() : Float; + private function get_movementY() : Float; + private function get_relatedObject() : flash.display.InteractiveObject; + private function get_shiftKey() : Bool; + private function get_stageX() : Float; + private function get_stageY() : Float; + private function set_altKey(value : Bool) : Bool; + private function set_buttonDown(value : Bool) : Bool; + private function set_ctrlKey(value : Bool) : Bool; + private function set_delta(value : Int) : Int; + private function set_isRelatedObjectInaccessible(value : Bool) : Bool; + private function set_localX(value : Float) : Float; + private function set_localY(value : Float) : Float; + private function set_movementX(value : Float) : Float; + private function set_movementY(value : Float) : Float; + private function set_relatedObject(value : flash.display.InteractiveObject) : flash.display.InteractiveObject; + private function set_shiftKey(value : Bool) : Bool; function updateAfterEvent() : Void; - static var CLICK(default,never) : String; - @:require(flash11_2) static var CONTEXT_MENU(default,never) : String; - static var DOUBLE_CLICK(default,never) : String; - @:require(flash11_2) static var MIDDLE_CLICK(default,never) : String; - @:require(flash11_2) static var MIDDLE_MOUSE_DOWN(default,never) : String; - @:require(flash11_2) static var MIDDLE_MOUSE_UP(default,never) : String; - static var MOUSE_DOWN(default,never) : String; - static var MOUSE_MOVE(default,never) : String; - static var MOUSE_OUT(default,never) : String; - static var MOUSE_OVER(default,never) : String; - static var MOUSE_UP(default,never) : String; - static var MOUSE_WHEEL(default,never) : String; - @:require(flash11_3) static var RELEASE_OUTSIDE(default,never) : String; - @:require(flash11_2) static var RIGHT_CLICK(default,never) : String; - @:require(flash11_2) static var RIGHT_MOUSE_DOWN(default,never) : String; - @:require(flash11_2) static var RIGHT_MOUSE_UP(default,never) : String; - static var ROLL_OUT(default,never) : String; - static var ROLL_OVER(default,never) : String; + static final CLICK : String; + @:require(flash11_2) static final CONTEXT_MENU : String; + static final DOUBLE_CLICK : String; + @:require(flash11_2) static final MIDDLE_CLICK : String; + @:require(flash11_2) static final MIDDLE_MOUSE_DOWN : String; + @:require(flash11_2) static final MIDDLE_MOUSE_UP : String; + static final MOUSE_DOWN : String; + static final MOUSE_MOVE : String; + static final MOUSE_OUT : String; + static final MOUSE_OVER : String; + static final MOUSE_UP : String; + static final MOUSE_WHEEL : String; + @:require(flash11_3) static final RELEASE_OUTSIDE : String; + @:require(flash11_2) static final RIGHT_CLICK : String; + @:require(flash11_2) static final RIGHT_MOUSE_DOWN : String; + @:require(flash11_2) static final RIGHT_MOUSE_UP : String; + static final ROLL_OUT : String; + static final ROLL_OVER : String; } diff --git a/std/flash/events/NetDataEvent.hx b/std/flash/events/NetDataEvent.hx index 8349d780bd2..686c600a8a8 100644 --- a/std/flash/events/NetDataEvent.hx +++ b/std/flash/events/NetDataEvent.hx @@ -1,8 +1,10 @@ package flash.events; extern class NetDataEvent extends Event { - var info(default,never) : Dynamic; - var timestamp(default,never) : Float; + @:flash.property var info(get,never) : Dynamic; + @:flash.property var timestamp(get,never) : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, timestamp : Float = 0, ?info : Dynamic) : Void; - static var MEDIA_TYPE_DATA(default,never) : String; + private function get_info() : Dynamic; + private function get_timestamp() : Float; + static final MEDIA_TYPE_DATA : String; } diff --git a/std/flash/events/NetMonitorEvent.hx b/std/flash/events/NetMonitorEvent.hx index 6c3b743d4f5..435573936ef 100644 --- a/std/flash/events/NetMonitorEvent.hx +++ b/std/flash/events/NetMonitorEvent.hx @@ -1,7 +1,8 @@ package flash.events; extern class NetMonitorEvent extends Event { - var netStream(default,never) : flash.net.NetStream; + @:flash.property var netStream(get,never) : flash.net.NetStream; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?netStream : flash.net.NetStream) : Void; - static var NET_STREAM_CREATE(default,never) : String; + private function get_netStream() : flash.net.NetStream; + static final NET_STREAM_CREATE : String; } diff --git a/std/flash/events/NetStatusEvent.hx b/std/flash/events/NetStatusEvent.hx index fe23b7bc233..60a4b87be2b 100644 --- a/std/flash/events/NetStatusEvent.hx +++ b/std/flash/events/NetStatusEvent.hx @@ -1,7 +1,9 @@ package flash.events; extern class NetStatusEvent extends Event { - var info : Dynamic; + @:flash.property var info(get,set) : Dynamic; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?info : Dynamic) : Void; - static var NET_STATUS(default,never) : String; + private function get_info() : Dynamic; + private function set_info(value : Dynamic) : Dynamic; + static final NET_STATUS : String; } diff --git a/std/flash/events/OutputProgressEvent.hx b/std/flash/events/OutputProgressEvent.hx index 501a67bf8ba..358ffd955a5 100644 --- a/std/flash/events/OutputProgressEvent.hx +++ b/std/flash/events/OutputProgressEvent.hx @@ -1,8 +1,12 @@ package flash.events; extern class OutputProgressEvent extends Event { - var bytesPending : Float; - var bytesTotal : Float; + @:flash.property var bytesPending(get,set) : Float; + @:flash.property var bytesTotal(get,set) : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, bytesPending : Float = 0, bytesTotal : Float = 0) : Void; - static var OUTPUT_PROGRESS(default,never) : String; + private function get_bytesPending() : Float; + private function get_bytesTotal() : Float; + private function set_bytesPending(value : Float) : Float; + private function set_bytesTotal(value : Float) : Float; + static final OUTPUT_PROGRESS : String; } diff --git a/std/flash/events/PressAndTapGestureEvent.hx b/std/flash/events/PressAndTapGestureEvent.hx index 6a65ab76188..c1915b5e6f8 100644 --- a/std/flash/events/PressAndTapGestureEvent.hx +++ b/std/flash/events/PressAndTapGestureEvent.hx @@ -1,10 +1,16 @@ package flash.events; @:require(flash10_1) extern class PressAndTapGestureEvent extends GestureEvent { - var tapLocalX : Float; - var tapLocalY : Float; - var tapStageX(default,never) : Float; - var tapStageY(default,never) : Float; + @:flash.property var tapLocalX(get,set) : Float; + @:flash.property var tapLocalY(get,set) : Float; + @:flash.property var tapStageX(get,never) : Float; + @:flash.property var tapStageY(get,never) : Float; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, ?phase : String, localX : Float = 0, localY : Float = 0, tapLocalX : Float = 0, tapLocalY : Float = 0, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false) : Void; - static var GESTURE_PRESS_AND_TAP(default,never) : String; + private function get_tapLocalX() : Float; + private function get_tapLocalY() : Float; + private function get_tapStageX() : Float; + private function get_tapStageY() : Float; + private function set_tapLocalX(value : Float) : Float; + private function set_tapLocalY(value : Float) : Float; + static final GESTURE_PRESS_AND_TAP : String; } diff --git a/std/flash/events/ProgressEvent.hx b/std/flash/events/ProgressEvent.hx index d49dc348011..21cc26acfed 100644 --- a/std/flash/events/ProgressEvent.hx +++ b/std/flash/events/ProgressEvent.hx @@ -1,9 +1,13 @@ package flash.events; extern class ProgressEvent extends Event { - var bytesLoaded : Float; - var bytesTotal : Float; + @:flash.property var bytesLoaded(get,set) : Float; + @:flash.property var bytesTotal(get,set) : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, bytesLoaded : Float = 0, bytesTotal : Float = 0) : Void; - static var PROGRESS(default,never) : String; - static var SOCKET_DATA(default,never) : String; + private function get_bytesLoaded() : Float; + private function get_bytesTotal() : Float; + private function set_bytesLoaded(value : Float) : Float; + private function set_bytesTotal(value : Float) : Float; + static final PROGRESS : String; + static final SOCKET_DATA : String; } diff --git a/std/flash/events/SampleDataEvent.hx b/std/flash/events/SampleDataEvent.hx index 219332fb1d1..f9c94675777 100644 --- a/std/flash/events/SampleDataEvent.hx +++ b/std/flash/events/SampleDataEvent.hx @@ -1,8 +1,12 @@ package flash.events; extern class SampleDataEvent extends Event { - var data : flash.utils.ByteArray; - var position : Float; + @:flash.property var data(get,set) : flash.utils.ByteArray; + @:flash.property var position(get,set) : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, theposition : Float = 0, ?thedata : flash.utils.ByteArray) : Void; - static var SAMPLE_DATA(default,never) : String; + private function get_data() : flash.utils.ByteArray; + private function get_position() : Float; + private function set_data(value : flash.utils.ByteArray) : flash.utils.ByteArray; + private function set_position(value : Float) : Float; + static final SAMPLE_DATA : String; } diff --git a/std/flash/events/SecurityErrorEvent.hx b/std/flash/events/SecurityErrorEvent.hx index 9d4e267faf2..3baa8ed9013 100644 --- a/std/flash/events/SecurityErrorEvent.hx +++ b/std/flash/events/SecurityErrorEvent.hx @@ -2,5 +2,5 @@ package flash.events; extern class SecurityErrorEvent extends ErrorEvent { function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, id : Int = 0) : Void; - static var SECURITY_ERROR(default,never) : String; + static final SECURITY_ERROR : String; } diff --git a/std/flash/events/ShaderEvent.hx b/std/flash/events/ShaderEvent.hx index b7055cb6a1d..2c09d4a97d7 100644 --- a/std/flash/events/ShaderEvent.hx +++ b/std/flash/events/ShaderEvent.hx @@ -1,9 +1,15 @@ package flash.events; extern class ShaderEvent extends Event { - var bitmapData : flash.display.BitmapData; - var byteArray : flash.utils.ByteArray; - var vector : flash.Vector; + @:flash.property var bitmapData(get,set) : flash.display.BitmapData; + @:flash.property var byteArray(get,set) : flash.utils.ByteArray; + @:flash.property var vector(get,set) : flash.Vector; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?bitmap : flash.display.BitmapData, ?array : flash.utils.ByteArray, ?vector : flash.Vector) : Void; - static var COMPLETE(default,never) : String; + private function get_bitmapData() : flash.display.BitmapData; + private function get_byteArray() : flash.utils.ByteArray; + private function get_vector() : flash.Vector; + private function set_bitmapData(value : flash.display.BitmapData) : flash.display.BitmapData; + private function set_byteArray(value : flash.utils.ByteArray) : flash.utils.ByteArray; + private function set_vector(value : flash.Vector) : flash.Vector; + static final COMPLETE : String; } diff --git a/std/flash/events/SoftKeyboardEvent.hx b/std/flash/events/SoftKeyboardEvent.hx index c1100893423..1dcc37d386c 100644 --- a/std/flash/events/SoftKeyboardEvent.hx +++ b/std/flash/events/SoftKeyboardEvent.hx @@ -1,10 +1,13 @@ package flash.events; extern class SoftKeyboardEvent extends Event { - var relatedObject : flash.display.InteractiveObject; - var triggerType(default,never) : String; + @:flash.property var relatedObject(get,set) : flash.display.InteractiveObject; + @:flash.property var triggerType(get,never) : String; function new(type : String, bubbles : Bool, cancelable : Bool, relatedObjectVal : flash.display.InteractiveObject, triggerTypeVal : String) : Void; - static var SOFT_KEYBOARD_ACTIVATE(default,never) : String; - static var SOFT_KEYBOARD_ACTIVATING(default,never) : String; - static var SOFT_KEYBOARD_DEACTIVATE(default,never) : String; + private function get_relatedObject() : flash.display.InteractiveObject; + private function get_triggerType() : String; + private function set_relatedObject(value : flash.display.InteractiveObject) : flash.display.InteractiveObject; + static final SOFT_KEYBOARD_ACTIVATE : String; + static final SOFT_KEYBOARD_ACTIVATING : String; + static final SOFT_KEYBOARD_DEACTIVATE : String; } diff --git a/std/flash/events/SoftKeyboardTrigger.hx b/std/flash/events/SoftKeyboardTrigger.hx index 1396ac37b27..122d8489c52 100644 --- a/std/flash/events/SoftKeyboardTrigger.hx +++ b/std/flash/events/SoftKeyboardTrigger.hx @@ -2,6 +2,6 @@ package flash.events; extern class SoftKeyboardTrigger { function new() : Void; - static var CONTENT_TRIGGERED(default,never) : String; - static var USER_TRIGGERED(default,never) : String; + static final CONTENT_TRIGGERED : String; + static final USER_TRIGGERED : String; } diff --git a/std/flash/events/StageVideoAvailabilityEvent.hx b/std/flash/events/StageVideoAvailabilityEvent.hx index 8a8c16800f0..d2dd353d0ee 100644 --- a/std/flash/events/StageVideoAvailabilityEvent.hx +++ b/std/flash/events/StageVideoAvailabilityEvent.hx @@ -1,9 +1,10 @@ package flash.events; extern class StageVideoAvailabilityEvent extends Event { - var availability(default,never) : String; - var driver(default,never) : String; - var reason(default,never) : String; + @:flash.property var availability(get,never) : String; + final driver : String; + final reason : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?availability : String) : Void; - static var STAGE_VIDEO_AVAILABILITY(default,never) : String; + private function get_availability() : String; + static final STAGE_VIDEO_AVAILABILITY : String; } diff --git a/std/flash/events/StageVideoEvent.hx b/std/flash/events/StageVideoEvent.hx index 8df13c91d2a..e54f0e2bdd1 100644 --- a/std/flash/events/StageVideoEvent.hx +++ b/std/flash/events/StageVideoEvent.hx @@ -1,12 +1,14 @@ package flash.events; @:require(flash10_2) extern class StageVideoEvent extends Event { - var codecInfo(default,never) : String; - var colorSpace(default,never) : String; - var status(default,never) : String; + final codecInfo : String; + @:flash.property var colorSpace(get,never) : String; + @:flash.property var status(get,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?status : String, ?colorSpace : String) : Void; - static var RENDER_STATE(default,never) : String; - static var RENDER_STATUS_ACCELERATED(default,never) : String; - static var RENDER_STATUS_SOFTWARE(default,never) : String; - static var RENDER_STATUS_UNAVAILABLE(default,never) : String; + private function get_colorSpace() : String; + private function get_status() : String; + static final RENDER_STATE : String; + static final RENDER_STATUS_ACCELERATED : String; + static final RENDER_STATUS_SOFTWARE : String; + static final RENDER_STATUS_UNAVAILABLE : String; } diff --git a/std/flash/events/StatusEvent.hx b/std/flash/events/StatusEvent.hx index fa06b59566e..9831bcf3d00 100644 --- a/std/flash/events/StatusEvent.hx +++ b/std/flash/events/StatusEvent.hx @@ -1,8 +1,12 @@ package flash.events; extern class StatusEvent extends Event { - var code : String; - var level : String; + @:flash.property var code(get,set) : String; + @:flash.property var level(get,set) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?code : String, ?level : String) : Void; - static var STATUS(default,never) : String; + private function get_code() : String; + private function get_level() : String; + private function set_code(value : String) : String; + private function set_level(value : String) : String; + static final STATUS : String; } diff --git a/std/flash/events/SyncEvent.hx b/std/flash/events/SyncEvent.hx index c519ab9f795..1d8718fc756 100644 --- a/std/flash/events/SyncEvent.hx +++ b/std/flash/events/SyncEvent.hx @@ -1,7 +1,9 @@ package flash.events; extern class SyncEvent extends Event { - var changeList : Array; + @:flash.property var changeList(get,set) : Array; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?changeList : Array) : Void; - static var SYNC(default,never) : String; + private function get_changeList() : Array; + private function set_changeList(value : Array) : Array; + static final SYNC : String; } diff --git a/std/flash/events/TextEvent.hx b/std/flash/events/TextEvent.hx index fbaa1e36b0a..d1194bb3147 100644 --- a/std/flash/events/TextEvent.hx +++ b/std/flash/events/TextEvent.hx @@ -1,8 +1,10 @@ package flash.events; extern class TextEvent extends Event { - var text : String; + @:flash.property var text(get,set) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String) : Void; - static var LINK(default,never) : String; - static var TEXT_INPUT(default,never) : String; + private function get_text() : String; + private function set_text(value : String) : String; + static final LINK : String; + static final TEXT_INPUT : String; } diff --git a/std/flash/events/ThrottleEvent.hx b/std/flash/events/ThrottleEvent.hx index 8cf89a37a51..0eb973ee212 100644 --- a/std/flash/events/ThrottleEvent.hx +++ b/std/flash/events/ThrottleEvent.hx @@ -1,8 +1,10 @@ package flash.events; @:require(flash11_2) extern class ThrottleEvent extends Event { - var state(default,never) : String; - var targetFrameRate(default,never) : Float; + @:flash.property var state(get,never) : String; + @:flash.property var targetFrameRate(get,never) : Float; function new(type : ThrottleType, bubbles : Bool = false, cancelable : Bool = false, ?state : String, targetFrameRate : Float = 0) : Void; - static var THROTTLE(default,never) : String; + private function get_state() : String; + private function get_targetFrameRate() : Float; + static final THROTTLE : String; } diff --git a/std/flash/events/ThrottleType.hx b/std/flash/events/ThrottleType.hx index 93c5e727a65..6b57d0c6f71 100644 --- a/std/flash/events/ThrottleType.hx +++ b/std/flash/events/ThrottleType.hx @@ -1,7 +1,7 @@ package flash.events; -@:fakeEnum(String) extern enum ThrottleType { - PAUSE; - RESUME; - THROTTLE; +@:native("flash.events.ThrottleType") extern enum abstract ThrottleType(String) { + var PAUSE; + var RESUME; + var THROTTLE; } diff --git a/std/flash/events/TimerEvent.hx b/std/flash/events/TimerEvent.hx index 3195b0faecb..5ffc25b6e5f 100644 --- a/std/flash/events/TimerEvent.hx +++ b/std/flash/events/TimerEvent.hx @@ -3,6 +3,6 @@ package flash.events; extern class TimerEvent extends Event { function new(type : String, bubbles : Bool = false, cancelable : Bool = false) : Void; function updateAfterEvent() : Void; - static var TIMER(default,never) : String; - static var TIMER_COMPLETE(default,never) : String; + static final TIMER : String; + static final TIMER_COMPLETE : String; } diff --git a/std/flash/events/TouchEvent.hx b/std/flash/events/TouchEvent.hx index 3b164614a8b..616c75bc865 100644 --- a/std/flash/events/TouchEvent.hx +++ b/std/flash/events/TouchEvent.hx @@ -1,35 +1,61 @@ package flash.events; @:require(flash10_1) extern class TouchEvent extends Event { - var altKey : Bool; - var ctrlKey : Bool; - var isPrimaryTouchPoint : Bool; - var isRelatedObjectInaccessible : Bool; - var localX : Float; - var localY : Float; - var pressure : Float; - var relatedObject : flash.display.InteractiveObject; - var shiftKey : Bool; - var sizeX : Float; - var sizeY : Float; - var stageX(default,never) : Float; - var stageY(default,never) : Float; - var touchPointID : Int; + @:flash.property var altKey(get,set) : Bool; + @:flash.property var ctrlKey(get,set) : Bool; + @:flash.property var isPrimaryTouchPoint(get,set) : Bool; + @:flash.property var isRelatedObjectInaccessible(get,set) : Bool; + @:flash.property var localX(get,set) : Float; + @:flash.property var localY(get,set) : Float; + @:flash.property var pressure(get,set) : Float; + @:flash.property var relatedObject(get,set) : flash.display.InteractiveObject; + @:flash.property var shiftKey(get,set) : Bool; + @:flash.property var sizeX(get,set) : Float; + @:flash.property var sizeY(get,set) : Float; + @:flash.property var stageX(get,never) : Float; + @:flash.property var stageY(get,never) : Float; + @:flash.property var touchPointID(get,set) : Int; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, touchPointID : Int = 0, isPrimaryTouchPoint : Bool = false, localX : Float = 0./*NaN*/, localY : Float = 0./*NaN*/, sizeX : Float = 0./*NaN*/, sizeY : Float = 0./*NaN*/, pressure : Float = 0./*NaN*/, ?relatedObject : flash.display.InteractiveObject, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false) : Void; + private function get_altKey() : Bool; + private function get_ctrlKey() : Bool; + private function get_isPrimaryTouchPoint() : Bool; + private function get_isRelatedObjectInaccessible() : Bool; + private function get_localX() : Float; + private function get_localY() : Float; + private function get_pressure() : Float; + private function get_relatedObject() : flash.display.InteractiveObject; + private function get_shiftKey() : Bool; + private function get_sizeX() : Float; + private function get_sizeY() : Float; + private function get_stageX() : Float; + private function get_stageY() : Float; + private function get_touchPointID() : Int; + private function set_altKey(value : Bool) : Bool; + private function set_ctrlKey(value : Bool) : Bool; + private function set_isPrimaryTouchPoint(value : Bool) : Bool; + private function set_isRelatedObjectInaccessible(value : Bool) : Bool; + private function set_localX(value : Float) : Float; + private function set_localY(value : Float) : Float; + private function set_pressure(value : Float) : Float; + private function set_relatedObject(value : flash.display.InteractiveObject) : flash.display.InteractiveObject; + private function set_shiftKey(value : Bool) : Bool; + private function set_sizeX(value : Float) : Float; + private function set_sizeY(value : Float) : Float; + private function set_touchPointID(value : Int) : Int; function updateAfterEvent() : Void; - static var PROXIMITY_BEGIN(default,never) : String; - static var PROXIMITY_END(default,never) : String; - static var PROXIMITY_MOVE(default,never) : String; - static var PROXIMITY_OUT(default,never) : String; - static var PROXIMITY_OVER(default,never) : String; - static var PROXIMITY_ROLL_OUT(default,never) : String; - static var PROXIMITY_ROLL_OVER(default,never) : String; - static var TOUCH_BEGIN(default,never) : String; - static var TOUCH_END(default,never) : String; - static var TOUCH_MOVE(default,never) : String; - static var TOUCH_OUT(default,never) : String; - static var TOUCH_OVER(default,never) : String; - static var TOUCH_ROLL_OUT(default,never) : String; - static var TOUCH_ROLL_OVER(default,never) : String; - static var TOUCH_TAP(default,never) : String; + static final PROXIMITY_BEGIN : String; + static final PROXIMITY_END : String; + static final PROXIMITY_MOVE : String; + static final PROXIMITY_OUT : String; + static final PROXIMITY_OVER : String; + static final PROXIMITY_ROLL_OUT : String; + static final PROXIMITY_ROLL_OVER : String; + static final TOUCH_BEGIN : String; + static final TOUCH_END : String; + static final TOUCH_MOVE : String; + static final TOUCH_OUT : String; + static final TOUCH_OVER : String; + static final TOUCH_ROLL_OUT : String; + static final TOUCH_ROLL_OVER : String; + static final TOUCH_TAP : String; } diff --git a/std/flash/events/TransformGestureEvent.hx b/std/flash/events/TransformGestureEvent.hx index 1aaf5542f13..5345bb900a2 100644 --- a/std/flash/events/TransformGestureEvent.hx +++ b/std/flash/events/TransformGestureEvent.hx @@ -1,14 +1,28 @@ package flash.events; @:require(flash10_1) extern class TransformGestureEvent extends GestureEvent { - var offsetX : Float; - var offsetY : Float; - var rotation : Float; - var scaleX : Float; - var scaleY : Float; + @:flash.property var offsetX(get,set) : Float; + @:flash.property var offsetY(get,set) : Float; + @:flash.property var rotation(get,set) : Float; + @:flash.property var scaleX(get,set) : Float; + @:flash.property var scaleY(get,set) : Float; + @:flash.property var velocity(get,set) : Float; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, ?phase : String, localX : Float = 0, localY : Float = 0, scaleX : Float = 1, scaleY : Float = 1, rotation : Float = 0, offsetX : Float = 0, offsetY : Float = 0, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false) : Void; - static var GESTURE_PAN(default,never) : String; - static var GESTURE_ROTATE(default,never) : String; - static var GESTURE_SWIPE(default,never) : String; - static var GESTURE_ZOOM(default,never) : String; + private function get_offsetX() : Float; + private function get_offsetY() : Float; + private function get_rotation() : Float; + private function get_scaleX() : Float; + private function get_scaleY() : Float; + private function get_velocity() : Float; + private function set_offsetX(value : Float) : Float; + private function set_offsetY(value : Float) : Float; + private function set_rotation(value : Float) : Float; + private function set_scaleX(value : Float) : Float; + private function set_scaleY(value : Float) : Float; + private function set_velocity(value : Float) : Float; + static final GESTURE_DIRECTIONAL_TAP : String; + static final GESTURE_PAN : String; + static final GESTURE_ROTATE : String; + static final GESTURE_SWIPE : String; + static final GESTURE_ZOOM : String; } diff --git a/std/flash/events/UncaughtErrorEvent.hx b/std/flash/events/UncaughtErrorEvent.hx index 835d09283e5..fb4a6cf4318 100644 --- a/std/flash/events/UncaughtErrorEvent.hx +++ b/std/flash/events/UncaughtErrorEvent.hx @@ -1,7 +1,8 @@ package flash.events; @:require(flash10_1) extern class UncaughtErrorEvent extends ErrorEvent { - var error(default,never) : Dynamic; + @:flash.property var error(get,never) : Dynamic; function new(?type : String, bubbles : Bool = true, cancelable : Bool = true, ?error_in : Dynamic) : Void; - static var UNCAUGHT_ERROR(default,never) : String; + private function get_error() : Dynamic; + static final UNCAUGHT_ERROR : String; } diff --git a/std/flash/events/VideoEvent.hx b/std/flash/events/VideoEvent.hx index 69b1d50a03b..1760ae3e70a 100644 --- a/std/flash/events/VideoEvent.hx +++ b/std/flash/events/VideoEvent.hx @@ -1,11 +1,12 @@ package flash.events; @:require(flash10_2) extern class VideoEvent extends Event { - var codecInfo(default,never) : String; - var status(default,never) : String; + final codecInfo : String; + @:flash.property var status(get,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?status : String) : Void; - static var RENDER_STATE(default,never) : String; - static var RENDER_STATUS_ACCELERATED(default,never) : String; - static var RENDER_STATUS_SOFTWARE(default,never) : String; - static var RENDER_STATUS_UNAVAILABLE(default,never) : String; + private function get_status() : String; + static final RENDER_STATE : String; + static final RENDER_STATUS_ACCELERATED : String; + static final RENDER_STATUS_SOFTWARE : String; + static final RENDER_STATUS_UNAVAILABLE : String; } diff --git a/std/flash/events/VideoTextureEvent.hx b/std/flash/events/VideoTextureEvent.hx index c17657f8301..3551a492837 100644 --- a/std/flash/events/VideoTextureEvent.hx +++ b/std/flash/events/VideoTextureEvent.hx @@ -1,9 +1,11 @@ package flash.events; extern class VideoTextureEvent extends Event { - var codecInfo(default,never) : String; - var colorSpace(default,never) : String; - var status(default,never) : String; + final codecInfo : String; + @:flash.property var colorSpace(get,never) : String; + @:flash.property var status(get,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?status : String, ?colorSpace : String) : Void; - static var RENDER_STATE(default,never) : String; + private function get_colorSpace() : String; + private function get_status() : String; + static final RENDER_STATE : String; } diff --git a/std/flash/external/ExternalInterface.hx b/std/flash/external/ExternalInterface.hx index 052a7372ac3..f408318c9ae 100644 --- a/std/flash/external/ExternalInterface.hx +++ b/std/flash/external/ExternalInterface.hx @@ -1,9 +1,11 @@ package flash.external; extern class ExternalInterface { - static var available(default,never) : Bool; + @:flash.property static var available(get,never) : Bool; static var marshallExceptions : Bool; - static var objectID(default,never) : String; + @:flash.property static var objectID(get,never) : String; static function addCallback(functionName : String, closure : Dynamic) : Void; - static function call(functionName : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Dynamic; + static function call(functionName : String, restArgs : haxe.extern.Rest) : Dynamic; + private static function get_available() : Bool; + private static function get_objectID() : String; } diff --git a/std/flash/filters/BevelFilter.hx b/std/flash/filters/BevelFilter.hx index 73c29764bae..e6a0b14b7cf 100644 --- a/std/flash/filters/BevelFilter.hx +++ b/std/flash/filters/BevelFilter.hx @@ -1,17 +1,41 @@ package flash.filters; -@:final extern class BevelFilter extends BitmapFilter { - var angle : Float; - var blurX : Float; - var blurY : Float; - var distance : Float; - var highlightAlpha : Float; - var highlightColor : UInt; - var knockout : Bool; - var quality : Int; - var shadowAlpha : Float; - var shadowColor : UInt; - var strength : Float; - var type : BitmapFilterType; +extern final class BevelFilter extends BitmapFilter { + @:flash.property var angle(get,set) : Float; + @:flash.property var blurX(get,set) : Float; + @:flash.property var blurY(get,set) : Float; + @:flash.property var distance(get,set) : Float; + @:flash.property var highlightAlpha(get,set) : Float; + @:flash.property var highlightColor(get,set) : UInt; + @:flash.property var knockout(get,set) : Bool; + @:flash.property var quality(get,set) : Int; + @:flash.property var shadowAlpha(get,set) : Float; + @:flash.property var shadowColor(get,set) : UInt; + @:flash.property var strength(get,set) : Float; + @:flash.property var type(get,set) : BitmapFilterType; function new(distance : Float = 4, angle : Float = 45, highlightColor : UInt = 0xFFFFFF, highlightAlpha : Float = 1, shadowColor : UInt = 0, shadowAlpha : Float = 1, blurX : Float = 4, blurY : Float = 4, strength : Float = 1, quality : Int = 1, ?type : BitmapFilterType, knockout : Bool = false) : Void; + private function get_angle() : Float; + private function get_blurX() : Float; + private function get_blurY() : Float; + private function get_distance() : Float; + private function get_highlightAlpha() : Float; + private function get_highlightColor() : UInt; + private function get_knockout() : Bool; + private function get_quality() : Int; + private function get_shadowAlpha() : Float; + private function get_shadowColor() : UInt; + private function get_strength() : Float; + private function get_type() : BitmapFilterType; + private function set_angle(value : Float) : Float; + private function set_blurX(value : Float) : Float; + private function set_blurY(value : Float) : Float; + private function set_distance(value : Float) : Float; + private function set_highlightAlpha(value : Float) : Float; + private function set_highlightColor(value : UInt) : UInt; + private function set_knockout(value : Bool) : Bool; + private function set_quality(value : Int) : Int; + private function set_shadowAlpha(value : Float) : Float; + private function set_shadowColor(value : UInt) : UInt; + private function set_strength(value : Float) : Float; + private function set_type(value : BitmapFilterType) : BitmapFilterType; } diff --git a/std/flash/filters/BitmapFilterType.hx b/std/flash/filters/BitmapFilterType.hx index deab80c8b46..ea45f124de9 100644 --- a/std/flash/filters/BitmapFilterType.hx +++ b/std/flash/filters/BitmapFilterType.hx @@ -1,7 +1,7 @@ package flash.filters; -@:fakeEnum(String) extern enum BitmapFilterType { - FULL; - INNER; - OUTER; +@:native("flash.filters.BitmapFilterType") extern enum abstract BitmapFilterType(String) { + var FULL; + var INNER; + var OUTER; } diff --git a/std/flash/filters/BlurFilter.hx b/std/flash/filters/BlurFilter.hx index ea9c4254696..a1062915731 100644 --- a/std/flash/filters/BlurFilter.hx +++ b/std/flash/filters/BlurFilter.hx @@ -1,8 +1,14 @@ package flash.filters; -@:final extern class BlurFilter extends BitmapFilter { - var blurX : Float; - var blurY : Float; - var quality : Int; +extern final class BlurFilter extends BitmapFilter { + @:flash.property var blurX(get,set) : Float; + @:flash.property var blurY(get,set) : Float; + @:flash.property var quality(get,set) : Int; function new(blurX : Float = 4, blurY : Float = 4, quality : Int = 1) : Void; + private function get_blurX() : Float; + private function get_blurY() : Float; + private function get_quality() : Int; + private function set_blurX(value : Float) : Float; + private function set_blurY(value : Float) : Float; + private function set_quality(value : Int) : Int; } diff --git a/std/flash/filters/ColorMatrixFilter.hx b/std/flash/filters/ColorMatrixFilter.hx index c72e403ce46..050b334fb22 100644 --- a/std/flash/filters/ColorMatrixFilter.hx +++ b/std/flash/filters/ColorMatrixFilter.hx @@ -1,6 +1,8 @@ package flash.filters; -@:final extern class ColorMatrixFilter extends BitmapFilter { - var matrix : Array; +extern final class ColorMatrixFilter extends BitmapFilter { + @:flash.property var matrix(get,set) : Array; function new(?matrix : Array) : Void; + private function get_matrix() : Array; + private function set_matrix(value : Array) : Array; } diff --git a/std/flash/filters/ConvolutionFilter.hx b/std/flash/filters/ConvolutionFilter.hx index 18cbc74a7a0..1411d52e2e3 100644 --- a/std/flash/filters/ConvolutionFilter.hx +++ b/std/flash/filters/ConvolutionFilter.hx @@ -1,14 +1,32 @@ package flash.filters; extern class ConvolutionFilter extends BitmapFilter { - var alpha : Float; - var bias : Float; - var clamp : Bool; - var color : UInt; - var divisor : Float; - var matrix : Array; - var matrixX : Float; - var matrixY : Float; - var preserveAlpha : Bool; + @:flash.property var alpha(get,set) : Float; + @:flash.property var bias(get,set) : Float; + @:flash.property var clamp(get,set) : Bool; + @:flash.property var color(get,set) : UInt; + @:flash.property var divisor(get,set) : Float; + @:flash.property var matrix(get,set) : Array; + @:flash.property var matrixX(get,set) : Float; + @:flash.property var matrixY(get,set) : Float; + @:flash.property var preserveAlpha(get,set) : Bool; function new(matrixX : Float = 0, matrixY : Float = 0, ?matrix : Array, divisor : Float = 1, bias : Float = 0, preserveAlpha : Bool = true, clamp : Bool = true, color : UInt = 0, alpha : Float = 0) : Void; + private function get_alpha() : Float; + private function get_bias() : Float; + private function get_clamp() : Bool; + private function get_color() : UInt; + private function get_divisor() : Float; + private function get_matrix() : Array; + private function get_matrixX() : Float; + private function get_matrixY() : Float; + private function get_preserveAlpha() : Bool; + private function set_alpha(value : Float) : Float; + private function set_bias(value : Float) : Float; + private function set_clamp(value : Bool) : Bool; + private function set_color(value : UInt) : UInt; + private function set_divisor(value : Float) : Float; + private function set_matrix(value : Array) : Array; + private function set_matrixX(value : Float) : Float; + private function set_matrixY(value : Float) : Float; + private function set_preserveAlpha(value : Bool) : Bool; } diff --git a/std/flash/filters/DisplacementMapFilter.hx b/std/flash/filters/DisplacementMapFilter.hx index 3dff32c47d6..4eb2a241c4a 100644 --- a/std/flash/filters/DisplacementMapFilter.hx +++ b/std/flash/filters/DisplacementMapFilter.hx @@ -1,14 +1,32 @@ package flash.filters; -@:final extern class DisplacementMapFilter extends BitmapFilter { - var alpha : Float; - var color : UInt; - var componentX : UInt; - var componentY : UInt; - var mapBitmap : flash.display.BitmapData; - var mapPoint : flash.geom.Point; - var mode : DisplacementMapFilterMode; - var scaleX : Float; - var scaleY : Float; +extern final class DisplacementMapFilter extends BitmapFilter { + @:flash.property var alpha(get,set) : Float; + @:flash.property var color(get,set) : UInt; + @:flash.property var componentX(get,set) : UInt; + @:flash.property var componentY(get,set) : UInt; + @:flash.property var mapBitmap(get,set) : flash.display.BitmapData; + @:flash.property var mapPoint(get,set) : flash.geom.Point; + @:flash.property var mode(get,set) : DisplacementMapFilterMode; + @:flash.property var scaleX(get,set) : Float; + @:flash.property var scaleY(get,set) : Float; function new(?mapBitmap : flash.display.BitmapData, ?mapPoint : flash.geom.Point, componentX : UInt = 0, componentY : UInt = 0, scaleX : Float = 0, scaleY : Float = 0, ?mode : DisplacementMapFilterMode, color : UInt = 0, alpha : Float = 0) : Void; + private function get_alpha() : Float; + private function get_color() : UInt; + private function get_componentX() : UInt; + private function get_componentY() : UInt; + private function get_mapBitmap() : flash.display.BitmapData; + private function get_mapPoint() : flash.geom.Point; + private function get_mode() : DisplacementMapFilterMode; + private function get_scaleX() : Float; + private function get_scaleY() : Float; + private function set_alpha(value : Float) : Float; + private function set_color(value : UInt) : UInt; + private function set_componentX(value : UInt) : UInt; + private function set_componentY(value : UInt) : UInt; + private function set_mapBitmap(value : flash.display.BitmapData) : flash.display.BitmapData; + private function set_mapPoint(value : flash.geom.Point) : flash.geom.Point; + private function set_mode(value : DisplacementMapFilterMode) : DisplacementMapFilterMode; + private function set_scaleX(value : Float) : Float; + private function set_scaleY(value : Float) : Float; } diff --git a/std/flash/filters/DisplacementMapFilterMode.hx b/std/flash/filters/DisplacementMapFilterMode.hx index 25710adc391..59a16030908 100644 --- a/std/flash/filters/DisplacementMapFilterMode.hx +++ b/std/flash/filters/DisplacementMapFilterMode.hx @@ -1,8 +1,8 @@ package flash.filters; -@:fakeEnum(String) extern enum DisplacementMapFilterMode { - CLAMP; - COLOR; - IGNORE; - WRAP; +@:native("flash.filters.DisplacementMapFilterMode") extern enum abstract DisplacementMapFilterMode(String) { + var CLAMP; + var COLOR; + var IGNORE; + var WRAP; } diff --git a/std/flash/filters/DropShadowFilter.hx b/std/flash/filters/DropShadowFilter.hx index be103ca25ce..462164c58c3 100644 --- a/std/flash/filters/DropShadowFilter.hx +++ b/std/flash/filters/DropShadowFilter.hx @@ -1,16 +1,38 @@ package flash.filters; -@:final extern class DropShadowFilter extends BitmapFilter { - var alpha : Float; - var angle : Float; - var blurX : Float; - var blurY : Float; - var color : UInt; - var distance : Float; - var hideObject : Bool; - var inner : Bool; - var knockout : Bool; - var quality : Int; - var strength : Float; +extern final class DropShadowFilter extends BitmapFilter { + @:flash.property var alpha(get,set) : Float; + @:flash.property var angle(get,set) : Float; + @:flash.property var blurX(get,set) : Float; + @:flash.property var blurY(get,set) : Float; + @:flash.property var color(get,set) : UInt; + @:flash.property var distance(get,set) : Float; + @:flash.property var hideObject(get,set) : Bool; + @:flash.property var inner(get,set) : Bool; + @:flash.property var knockout(get,set) : Bool; + @:flash.property var quality(get,set) : Int; + @:flash.property var strength(get,set) : Float; function new(distance : Float = 4, angle : Float = 45, color : UInt = 0, alpha : Float = 1, blurX : Float = 4, blurY : Float = 4, strength : Float = 1, quality : Int = 1, inner : Bool = false, knockout : Bool = false, hideObject : Bool = false) : Void; + private function get_alpha() : Float; + private function get_angle() : Float; + private function get_blurX() : Float; + private function get_blurY() : Float; + private function get_color() : UInt; + private function get_distance() : Float; + private function get_hideObject() : Bool; + private function get_inner() : Bool; + private function get_knockout() : Bool; + private function get_quality() : Int; + private function get_strength() : Float; + private function set_alpha(value : Float) : Float; + private function set_angle(value : Float) : Float; + private function set_blurX(value : Float) : Float; + private function set_blurY(value : Float) : Float; + private function set_color(value : UInt) : UInt; + private function set_distance(value : Float) : Float; + private function set_hideObject(value : Bool) : Bool; + private function set_inner(value : Bool) : Bool; + private function set_knockout(value : Bool) : Bool; + private function set_quality(value : Int) : Int; + private function set_strength(value : Float) : Float; } diff --git a/std/flash/filters/GlowFilter.hx b/std/flash/filters/GlowFilter.hx index de5fc007e90..440c4c50621 100644 --- a/std/flash/filters/GlowFilter.hx +++ b/std/flash/filters/GlowFilter.hx @@ -1,13 +1,29 @@ package flash.filters; -@:final extern class GlowFilter extends BitmapFilter { - var alpha : Float; - var blurX : Float; - var blurY : Float; - var color : UInt; - var inner : Bool; - var knockout : Bool; - var quality : Int; - var strength : Float; +extern final class GlowFilter extends BitmapFilter { + @:flash.property var alpha(get,set) : Float; + @:flash.property var blurX(get,set) : Float; + @:flash.property var blurY(get,set) : Float; + @:flash.property var color(get,set) : UInt; + @:flash.property var inner(get,set) : Bool; + @:flash.property var knockout(get,set) : Bool; + @:flash.property var quality(get,set) : Int; + @:flash.property var strength(get,set) : Float; function new(color : UInt = 16711680, alpha : Float = 1, blurX : Float = 6, blurY : Float = 6, strength : Float = 2, quality : Int = 1, inner : Bool = false, knockout : Bool = false) : Void; + private function get_alpha() : Float; + private function get_blurX() : Float; + private function get_blurY() : Float; + private function get_color() : UInt; + private function get_inner() : Bool; + private function get_knockout() : Bool; + private function get_quality() : Int; + private function get_strength() : Float; + private function set_alpha(value : Float) : Float; + private function set_blurX(value : Float) : Float; + private function set_blurY(value : Float) : Float; + private function set_color(value : UInt) : UInt; + private function set_inner(value : Bool) : Bool; + private function set_knockout(value : Bool) : Bool; + private function set_quality(value : Int) : Int; + private function set_strength(value : Float) : Float; } diff --git a/std/flash/filters/GradientBevelFilter.hx b/std/flash/filters/GradientBevelFilter.hx index c04663e4cb8..93ee39e4818 100644 --- a/std/flash/filters/GradientBevelFilter.hx +++ b/std/flash/filters/GradientBevelFilter.hx @@ -1,16 +1,38 @@ package flash.filters; -@:final extern class GradientBevelFilter extends BitmapFilter { - var alphas : Array; - var angle : Float; - var blurX : Float; - var blurY : Float; - var colors : Array; - var distance : Float; - var knockout : Bool; - var quality : Int; - var ratios : Array; - var strength : Float; - var type : String; +extern final class GradientBevelFilter extends BitmapFilter { + @:flash.property var alphas(get,set) : Array; + @:flash.property var angle(get,set) : Float; + @:flash.property var blurX(get,set) : Float; + @:flash.property var blurY(get,set) : Float; + @:flash.property var colors(get,set) : Array; + @:flash.property var distance(get,set) : Float; + @:flash.property var knockout(get,set) : Bool; + @:flash.property var quality(get,set) : Int; + @:flash.property var ratios(get,set) : Array; + @:flash.property var strength(get,set) : Float; + @:flash.property var type(get,set) : String; function new(distance : Float = 4, angle : Float = 45, ?colors : Array, ?alphas : Array, ?ratios : Array, blurX : Float = 4, blurY : Float = 4, strength : Float = 1, quality : Int = 1, ?type : String, knockout : Bool = false) : Void; + private function get_alphas() : Array; + private function get_angle() : Float; + private function get_blurX() : Float; + private function get_blurY() : Float; + private function get_colors() : Array; + private function get_distance() : Float; + private function get_knockout() : Bool; + private function get_quality() : Int; + private function get_ratios() : Array; + private function get_strength() : Float; + private function get_type() : String; + private function set_alphas(value : Array) : Array; + private function set_angle(value : Float) : Float; + private function set_blurX(value : Float) : Float; + private function set_blurY(value : Float) : Float; + private function set_colors(value : Array) : Array; + private function set_distance(value : Float) : Float; + private function set_knockout(value : Bool) : Bool; + private function set_quality(value : Int) : Int; + private function set_ratios(value : Array) : Array; + private function set_strength(value : Float) : Float; + private function set_type(value : String) : String; } diff --git a/std/flash/filters/GradientGlowFilter.hx b/std/flash/filters/GradientGlowFilter.hx index 4f40b37a2cb..74be7360beb 100644 --- a/std/flash/filters/GradientGlowFilter.hx +++ b/std/flash/filters/GradientGlowFilter.hx @@ -1,16 +1,38 @@ package flash.filters; -@:final extern class GradientGlowFilter extends BitmapFilter { - var alphas : Array; - var angle : Float; - var blurX : Float; - var blurY : Float; - var colors : Array; - var distance : Float; - var knockout : Bool; - var quality : Int; - var ratios : Array; - var strength : Float; - var type : BitmapFilterType; +extern final class GradientGlowFilter extends BitmapFilter { + @:flash.property var alphas(get,set) : Array; + @:flash.property var angle(get,set) : Float; + @:flash.property var blurX(get,set) : Float; + @:flash.property var blurY(get,set) : Float; + @:flash.property var colors(get,set) : Array; + @:flash.property var distance(get,set) : Float; + @:flash.property var knockout(get,set) : Bool; + @:flash.property var quality(get,set) : Int; + @:flash.property var ratios(get,set) : Array; + @:flash.property var strength(get,set) : Float; + @:flash.property var type(get,set) : BitmapFilterType; function new(distance : Float = 4, angle : Float = 45, ?colors : Array, ?alphas : Array, ?ratios : Array, blurX : Float = 4, blurY : Float = 4, strength : Float = 1, quality : Int = 1, ?type : BitmapFilterType, knockout : Bool = false) : Void; + private function get_alphas() : Array; + private function get_angle() : Float; + private function get_blurX() : Float; + private function get_blurY() : Float; + private function get_colors() : Array; + private function get_distance() : Float; + private function get_knockout() : Bool; + private function get_quality() : Int; + private function get_ratios() : Array; + private function get_strength() : Float; + private function get_type() : BitmapFilterType; + private function set_alphas(value : Array) : Array; + private function set_angle(value : Float) : Float; + private function set_blurX(value : Float) : Float; + private function set_blurY(value : Float) : Float; + private function set_colors(value : Array) : Array; + private function set_distance(value : Float) : Float; + private function set_knockout(value : Bool) : Bool; + private function set_quality(value : Int) : Int; + private function set_ratios(value : Array) : Array; + private function set_strength(value : Float) : Float; + private function set_type(value : BitmapFilterType) : BitmapFilterType; } diff --git a/std/flash/filters/ShaderFilter.hx b/std/flash/filters/ShaderFilter.hx index f4a91640f62..e58a0de07bf 100644 --- a/std/flash/filters/ShaderFilter.hx +++ b/std/flash/filters/ShaderFilter.hx @@ -1,10 +1,20 @@ package flash.filters; extern class ShaderFilter extends BitmapFilter { - var bottomExtension : Int; - var leftExtension : Int; - var rightExtension : Int; - var shader : flash.display.Shader; - var topExtension : Int; + @:flash.property var bottomExtension(get,set) : Int; + @:flash.property var leftExtension(get,set) : Int; + @:flash.property var rightExtension(get,set) : Int; + @:flash.property var shader(get,set) : flash.display.Shader; + @:flash.property var topExtension(get,set) : Int; function new(?shader : flash.display.Shader) : Void; + private function get_bottomExtension() : Int; + private function get_leftExtension() : Int; + private function get_rightExtension() : Int; + private function get_shader() : flash.display.Shader; + private function get_topExtension() : Int; + private function set_bottomExtension(value : Int) : Int; + private function set_leftExtension(value : Int) : Int; + private function set_rightExtension(value : Int) : Int; + private function set_shader(value : flash.display.Shader) : flash.display.Shader; + private function set_topExtension(value : Int) : Int; } diff --git a/std/flash/geom/ColorTransform.hx b/std/flash/geom/ColorTransform.hx index d320be9c54c..ef85afd6c61 100644 --- a/std/flash/geom/ColorTransform.hx +++ b/std/flash/geom/ColorTransform.hx @@ -5,12 +5,14 @@ extern class ColorTransform { var alphaOffset : Float; var blueMultiplier : Float; var blueOffset : Float; - var color : UInt; + @:flash.property var color(get,set) : UInt; var greenMultiplier : Float; var greenOffset : Float; var redMultiplier : Float; var redOffset : Float; function new(redMultiplier : Float = 1, greenMultiplier : Float = 1, blueMultiplier : Float = 1, alphaMultiplier : Float = 1, redOffset : Float = 0, greenOffset : Float = 0, blueOffset : Float = 0, alphaOffset : Float = 0) : Void; function concat(second : ColorTransform) : Void; + private function get_color() : UInt; + private function set_color(value : UInt) : UInt; function toString() : String; } diff --git a/std/flash/geom/Matrix3D.hx b/std/flash/geom/Matrix3D.hx index 3f7bab6e53b..2e1e15d7fa8 100644 --- a/std/flash/geom/Matrix3D.hx +++ b/std/flash/geom/Matrix3D.hx @@ -1,9 +1,9 @@ package flash.geom; @:require(flash10) extern class Matrix3D { - var determinant(default,never) : Float; - var position : Vector3D; - var rawData : flash.Vector; + @:flash.property var determinant(get,never) : Float; + @:flash.property var position(get,set) : Vector3D; + @:flash.property var rawData(get,set) : flash.Vector; function new(?v : flash.Vector) : Void; function append(lhs : Matrix3D) : Void; function appendRotation(degrees : Float, axis : Vector3D, ?pivotPoint : Vector3D) : Void; @@ -20,6 +20,9 @@ package flash.geom; @:require(flash11) function copyToMatrix3D(dest : Matrix3D) : Void; function decompose(?orientationStyle : Orientation3D) : flash.Vector; function deltaTransformVector(v : Vector3D) : Vector3D; + private function get_determinant() : Float; + private function get_position() : Vector3D; + private function get_rawData() : flash.Vector; function identity() : Void; function interpolateTo(toMat : Matrix3D, percent : Float) : Void; function invert() : Bool; @@ -29,6 +32,8 @@ package flash.geom; function prependScale(xScale : Float, yScale : Float, zScale : Float) : Void; function prependTranslation(x : Float, y : Float, z : Float) : Void; function recompose(components : flash.Vector, ?orientationStyle : Orientation3D) : Bool; + private function set_position(value : Vector3D) : Vector3D; + private function set_rawData(value : flash.Vector) : flash.Vector; function transformVector(v : Vector3D) : Vector3D; function transformVectors(vin : flash.Vector, vout : flash.Vector) : Void; function transpose() : Void; diff --git a/std/flash/geom/Orientation3D.hx b/std/flash/geom/Orientation3D.hx index 01cf205851a..f0df04b5471 100644 --- a/std/flash/geom/Orientation3D.hx +++ b/std/flash/geom/Orientation3D.hx @@ -1,7 +1,7 @@ package flash.geom; -@:fakeEnum(String) extern enum Orientation3D { - AXIS_ANGLE; - EULER_ANGLES; - QUATERNION; +@:native("flash.geom.Orientation3D") extern enum abstract Orientation3D(String) { + var AXIS_ANGLE; + var EULER_ANGLES; + var QUATERNION; } diff --git a/std/flash/geom/PerspectiveProjection.hx b/std/flash/geom/PerspectiveProjection.hx index 3051df818a7..c5a6259c791 100644 --- a/std/flash/geom/PerspectiveProjection.hx +++ b/std/flash/geom/PerspectiveProjection.hx @@ -1,9 +1,15 @@ package flash.geom; @:require(flash10) extern class PerspectiveProjection { - var fieldOfView : Float; - var focalLength : Float; - var projectionCenter : Point; + @:flash.property var fieldOfView(get,set) : Float; + @:flash.property var focalLength(get,set) : Float; + @:flash.property var projectionCenter(get,set) : Point; function new() : Void; + private function get_fieldOfView() : Float; + private function get_focalLength() : Float; + private function get_projectionCenter() : Point; + private function set_fieldOfView(value : Float) : Float; + private function set_focalLength(value : Float) : Float; + private function set_projectionCenter(value : Point) : Point; function toMatrix3D() : Matrix3D; } diff --git a/std/flash/geom/Point.hx b/std/flash/geom/Point.hx index 1396b7fe8f1..7c96a2a1b61 100644 --- a/std/flash/geom/Point.hx +++ b/std/flash/geom/Point.hx @@ -1,7 +1,7 @@ package flash.geom; extern class Point { - var length(default,never) : Float; + @:flash.property var length(get,never) : Float; var x : Float; var y : Float; function new(x : Float = 0, y : Float = 0) : Void; @@ -9,6 +9,7 @@ extern class Point { function clone() : Point; @:require(flash11) function copyFrom(sourcePoint : Point) : Void; function equals(toCompare : Point) : Bool; + private function get_length() : Float; function normalize(thickness : Float) : Void; function offset(dx : Float, dy : Float) : Void; @:require(flash11) function setTo(xa : Float, ya : Float) : Void; diff --git a/std/flash/geom/Rectangle.hx b/std/flash/geom/Rectangle.hx index 7e09bcfcc05..9f21bd75b23 100644 --- a/std/flash/geom/Rectangle.hx +++ b/std/flash/geom/Rectangle.hx @@ -1,14 +1,14 @@ package flash.geom; extern class Rectangle { - var bottom : Float; - var bottomRight : Point; + @:flash.property var bottom(get,set) : Float; + @:flash.property var bottomRight(get,set) : Point; var height : Float; - var left : Float; - var right : Float; - var size : Point; - var top : Float; - var topLeft : Point; + @:flash.property var left(get,set) : Float; + @:flash.property var right(get,set) : Float; + @:flash.property var size(get,set) : Point; + @:flash.property var top(get,set) : Float; + @:flash.property var topLeft(get,set) : Point; var width : Float; var x : Float; var y : Float; @@ -19,6 +19,13 @@ extern class Rectangle { function containsRect(rect : Rectangle) : Bool; @:require(flash11) function copyFrom(sourceRect : Rectangle) : Void; function equals(toCompare : Rectangle) : Bool; + private function get_bottom() : Float; + private function get_bottomRight() : Point; + private function get_left() : Float; + private function get_right() : Float; + private function get_size() : Point; + private function get_top() : Float; + private function get_topLeft() : Point; function inflate(dx : Float, dy : Float) : Void; function inflatePoint(point : Point) : Void; function intersection(toIntersect : Rectangle) : Rectangle; @@ -28,6 +35,13 @@ extern class Rectangle { function offsetPoint(point : Point) : Void; function setEmpty() : Void; @:require(flash11) function setTo(xa : Float, ya : Float, widtha : Float, heighta : Float) : Void; + private function set_bottom(value : Float) : Float; + private function set_bottomRight(value : Point) : Point; + private function set_left(value : Float) : Float; + private function set_right(value : Float) : Float; + private function set_size(value : Point) : Point; + private function set_top(value : Float) : Float; + private function set_topLeft(value : Point) : Point; function toString() : String; function union(toUnion : Rectangle) : Rectangle; } diff --git a/std/flash/geom/Transform.hx b/std/flash/geom/Transform.hx index 13f3c440028..dcd93fd271c 100644 --- a/std/flash/geom/Transform.hx +++ b/std/flash/geom/Transform.hx @@ -1,13 +1,24 @@ package flash.geom; extern class Transform { - var colorTransform : ColorTransform; - var concatenatedColorTransform(default,never) : ColorTransform; - var concatenatedMatrix(default,never) : Matrix; - var matrix : Matrix; - @:require(flash10) var matrix3D : Matrix3D; - @:require(flash10) var perspectiveProjection : PerspectiveProjection; - var pixelBounds(default,never) : Rectangle; + @:flash.property var colorTransform(get,set) : ColorTransform; + @:flash.property var concatenatedColorTransform(get,never) : ColorTransform; + @:flash.property var concatenatedMatrix(get,never) : Matrix; + @:flash.property var matrix(get,set) : Matrix; + @:flash.property @:require(flash10) var matrix3D(get,set) : Matrix3D; + @:flash.property @:require(flash10) var perspectiveProjection(get,set) : PerspectiveProjection; + @:flash.property var pixelBounds(get,never) : Rectangle; function new(displayObject : flash.display.DisplayObject) : Void; @:require(flash10) function getRelativeMatrix3D(relativeTo : flash.display.DisplayObject) : Matrix3D; + private function get_colorTransform() : ColorTransform; + private function get_concatenatedColorTransform() : ColorTransform; + private function get_concatenatedMatrix() : Matrix; + private function get_matrix() : Matrix; + private function get_matrix3D() : Matrix3D; + private function get_perspectiveProjection() : PerspectiveProjection; + private function get_pixelBounds() : Rectangle; + private function set_colorTransform(value : ColorTransform) : ColorTransform; + private function set_matrix(value : Matrix) : Matrix; + private function set_matrix3D(value : Matrix3D) : Matrix3D; + private function set_perspectiveProjection(value : PerspectiveProjection) : PerspectiveProjection; } diff --git a/std/flash/geom/Vector3D.hx b/std/flash/geom/Vector3D.hx index 01a91ff5b7e..f03e51d4b33 100644 --- a/std/flash/geom/Vector3D.hx +++ b/std/flash/geom/Vector3D.hx @@ -1,8 +1,8 @@ package flash.geom; @:require(flash10) extern class Vector3D { - var length(default,never) : Float; - var lengthSquared(default,never) : Float; + @:flash.property var length(get,never) : Float; + @:flash.property var lengthSquared(get,never) : Float; var w : Float; var x : Float; var y : Float; @@ -15,6 +15,8 @@ package flash.geom; function decrementBy(a : Vector3D) : Void; function dotProduct(a : Vector3D) : Float; function equals(toCompare : Vector3D, allFour : Bool = false) : Bool; + private function get_length() : Float; + private function get_lengthSquared() : Float; function incrementBy(a : Vector3D) : Void; function nearEquals(toCompare : Vector3D, tolerance : Float, allFour : Bool = false) : Bool; function negate() : Void; @@ -24,9 +26,9 @@ package flash.geom; @:require(flash11) function setTo(xa : Float, ya : Float, za : Float) : Void; function subtract(a : Vector3D) : Vector3D; function toString() : String; - static var X_AXIS(default,never) : Vector3D; - static var Y_AXIS(default,never) : Vector3D; - static var Z_AXIS(default,never) : Vector3D; + static final X_AXIS : Vector3D; + static final Y_AXIS : Vector3D; + static final Z_AXIS : Vector3D; static function angleBetween(a : Vector3D, b : Vector3D) : Float; static function distance(pt1 : Vector3D, pt2 : Vector3D) : Float; } diff --git a/std/flash/globalization/Collator.hx b/std/flash/globalization/Collator.hx index de60b570c87..4e2e137e01c 100644 --- a/std/flash/globalization/Collator.hx +++ b/std/flash/globalization/Collator.hx @@ -1,17 +1,32 @@ package flash.globalization; -@:final @:require(flash10_1) extern class Collator { - var actualLocaleIDName(default,never) : String; - var ignoreCase : Bool; - var ignoreCharacterWidth : Bool; - var ignoreDiacritics : Bool; - var ignoreKanaType : Bool; - var ignoreSymbols : Bool; - var lastOperationStatus(default,never) : LastOperationStatus; - var numericComparison : Bool; - var requestedLocaleIDName(default,never) : String; +@:require(flash10_1) extern final class Collator { + @:flash.property var actualLocaleIDName(get,never) : String; + @:flash.property var ignoreCase(get,set) : Bool; + @:flash.property var ignoreCharacterWidth(get,set) : Bool; + @:flash.property var ignoreDiacritics(get,set) : Bool; + @:flash.property var ignoreKanaType(get,set) : Bool; + @:flash.property var ignoreSymbols(get,set) : Bool; + @:flash.property var lastOperationStatus(get,never) : LastOperationStatus; + @:flash.property var numericComparison(get,set) : Bool; + @:flash.property var requestedLocaleIDName(get,never) : String; function new(requestedLocaleIDName : String, ?initialMode : CollatorMode) : Void; function compare(string1 : String, string2 : String) : Int; function equals(string1 : String, string2 : String) : Bool; + private function get_actualLocaleIDName() : String; + private function get_ignoreCase() : Bool; + private function get_ignoreCharacterWidth() : Bool; + private function get_ignoreDiacritics() : Bool; + private function get_ignoreKanaType() : Bool; + private function get_ignoreSymbols() : Bool; + private function get_lastOperationStatus() : LastOperationStatus; + private function get_numericComparison() : Bool; + private function get_requestedLocaleIDName() : String; + private function set_ignoreCase(value : Bool) : Bool; + private function set_ignoreCharacterWidth(value : Bool) : Bool; + private function set_ignoreDiacritics(value : Bool) : Bool; + private function set_ignoreKanaType(value : Bool) : Bool; + private function set_ignoreSymbols(value : Bool) : Bool; + private function set_numericComparison(value : Bool) : Bool; static function getAvailableLocaleIDNames() : flash.Vector; } diff --git a/std/flash/globalization/CollatorMode.hx b/std/flash/globalization/CollatorMode.hx index 28a86f9b9c9..4cdb56195ea 100644 --- a/std/flash/globalization/CollatorMode.hx +++ b/std/flash/globalization/CollatorMode.hx @@ -1,6 +1,6 @@ package flash.globalization; -@:fakeEnum(String) extern enum CollatorMode { - MATCHING; - SORTING; +@:native("flash.globalization.CollatorMode") extern enum abstract CollatorMode(String) { + var MATCHING; + var SORTING; } diff --git a/std/flash/globalization/CurrencyFormatter.hx b/std/flash/globalization/CurrencyFormatter.hx index c19793ba361..97e1df57712 100644 --- a/std/flash/globalization/CurrencyFormatter.hx +++ b/std/flash/globalization/CurrencyFormatter.hx @@ -1,26 +1,53 @@ package flash.globalization; -@:final @:require(flash10_1) extern class CurrencyFormatter { - var actualLocaleIDName(default,never) : String; - var currencyISOCode(default,never) : String; - var currencySymbol(default,never) : String; - var decimalSeparator : String; - var digitsType : UInt; - var fractionalDigits : Int; - var groupingPattern : String; - var groupingSeparator : String; - var lastOperationStatus(default,never) : LastOperationStatus; - var leadingZero : Bool; - var negativeCurrencyFormat : UInt; - var negativeSymbol : String; - var positiveCurrencyFormat : UInt; - var requestedLocaleIDName(default,never) : String; - var trailingZeros : Bool; - var useGrouping : Bool; +@:require(flash10_1) extern final class CurrencyFormatter { + @:flash.property var actualLocaleIDName(get,never) : String; + @:flash.property var currencyISOCode(get,never) : String; + @:flash.property var currencySymbol(get,never) : String; + @:flash.property var decimalSeparator(get,set) : String; + @:flash.property var digitsType(get,set) : UInt; + @:flash.property var fractionalDigits(get,set) : Int; + @:flash.property var groupingPattern(get,set) : String; + @:flash.property var groupingSeparator(get,set) : String; + @:flash.property var lastOperationStatus(get,never) : LastOperationStatus; + @:flash.property var leadingZero(get,set) : Bool; + @:flash.property var negativeCurrencyFormat(get,set) : UInt; + @:flash.property var negativeSymbol(get,set) : String; + @:flash.property var positiveCurrencyFormat(get,set) : UInt; + @:flash.property var requestedLocaleIDName(get,never) : String; + @:flash.property var trailingZeros(get,set) : Bool; + @:flash.property var useGrouping(get,set) : Bool; function new(requestedLocaleIDName : String) : Void; function format(value : Float, withCurrencySymbol : Bool = false) : String; function formattingWithCurrencySymbolIsSafe(requestedISOCode : String) : Bool; + private function get_actualLocaleIDName() : String; + private function get_currencyISOCode() : String; + private function get_currencySymbol() : String; + private function get_decimalSeparator() : String; + private function get_digitsType() : UInt; + private function get_fractionalDigits() : Int; + private function get_groupingPattern() : String; + private function get_groupingSeparator() : String; + private function get_lastOperationStatus() : LastOperationStatus; + private function get_leadingZero() : Bool; + private function get_negativeCurrencyFormat() : UInt; + private function get_negativeSymbol() : String; + private function get_positiveCurrencyFormat() : UInt; + private function get_requestedLocaleIDName() : String; + private function get_trailingZeros() : Bool; + private function get_useGrouping() : Bool; function parse(inputString : String) : CurrencyParseResult; function setCurrency(currencyISOCode : String, currencySymbol : String) : Void; + private function set_decimalSeparator(value : String) : String; + private function set_digitsType(value : UInt) : UInt; + private function set_fractionalDigits(value : Int) : Int; + private function set_groupingPattern(value : String) : String; + private function set_groupingSeparator(value : String) : String; + private function set_leadingZero(value : Bool) : Bool; + private function set_negativeCurrencyFormat(value : UInt) : UInt; + private function set_negativeSymbol(value : String) : String; + private function set_positiveCurrencyFormat(value : UInt) : UInt; + private function set_trailingZeros(value : Bool) : Bool; + private function set_useGrouping(value : Bool) : Bool; static function getAvailableLocaleIDNames() : flash.Vector; } diff --git a/std/flash/globalization/CurrencyParseResult.hx b/std/flash/globalization/CurrencyParseResult.hx index b26e7c8d5dd..3df82ea0f5c 100644 --- a/std/flash/globalization/CurrencyParseResult.hx +++ b/std/flash/globalization/CurrencyParseResult.hx @@ -1,7 +1,9 @@ package flash.globalization; -@:final extern class CurrencyParseResult { - var currencyString(default,never) : String; - var value(default,never) : Float; +extern final class CurrencyParseResult { + @:flash.property var currencyString(get,never) : String; + @:flash.property var value(get,never) : Float; function new(value : Float = 0./*NaN*/, ?symbol : String) : Void; + private function get_currencyString() : String; + private function get_value() : Float; } diff --git a/std/flash/globalization/DateTimeFormatter.hx b/std/flash/globalization/DateTimeFormatter.hx index 03b019cbf4e..e37bb8bfd03 100644 --- a/std/flash/globalization/DateTimeFormatter.hx +++ b/std/flash/globalization/DateTimeFormatter.hx @@ -1,9 +1,9 @@ package flash.globalization; -@:final @:require(flash10_1) extern class DateTimeFormatter { - var actualLocaleIDName(default,never) : String; - var lastOperationStatus(default,never) : LastOperationStatus; - var requestedLocaleIDName(default,never) : String; +@:require(flash10_1) extern final class DateTimeFormatter { + @:flash.property var actualLocaleIDName(get,never) : String; + @:flash.property var lastOperationStatus(get,never) : LastOperationStatus; + @:flash.property var requestedLocaleIDName(get,never) : String; function new(requestedLocaleIDName : String, ?dateStyle : DateTimeStyle, ?timeStyle : DateTimeStyle) : Void; function format(dateTime : Date) : String; function formatUTC(dateTime : Date) : String; @@ -13,6 +13,9 @@ package flash.globalization; function getMonthNames(?nameStyle : DateTimeNameStyle, ?context : DateTimeNameContext) : flash.Vector; function getTimeStyle() : DateTimeStyle; function getWeekdayNames(?nameStyle : DateTimeNameStyle, ?context : DateTimeNameContext) : flash.Vector; + private function get_actualLocaleIDName() : String; + private function get_lastOperationStatus() : LastOperationStatus; + private function get_requestedLocaleIDName() : String; function setDateTimePattern(pattern : String) : Void; function setDateTimeStyles(dateStyle : DateTimeStyle, timeStyle : DateTimeStyle) : Void; static function getAvailableLocaleIDNames() : flash.Vector; diff --git a/std/flash/globalization/DateTimeNameContext.hx b/std/flash/globalization/DateTimeNameContext.hx index 35bd0661afd..0d1f2e4a81b 100644 --- a/std/flash/globalization/DateTimeNameContext.hx +++ b/std/flash/globalization/DateTimeNameContext.hx @@ -1,6 +1,6 @@ package flash.globalization; -@:fakeEnum(String) extern enum DateTimeNameContext { - FORMAT; - STANDALONE; +@:native("flash.globalization.DateTimeNameContext") extern enum abstract DateTimeNameContext(String) { + var FORMAT; + var STANDALONE; } diff --git a/std/flash/globalization/DateTimeNameStyle.hx b/std/flash/globalization/DateTimeNameStyle.hx index bb8503b88e6..067fbf653d1 100644 --- a/std/flash/globalization/DateTimeNameStyle.hx +++ b/std/flash/globalization/DateTimeNameStyle.hx @@ -1,7 +1,7 @@ package flash.globalization; -@:fakeEnum(String) extern enum DateTimeNameStyle { - FULL; - LONG_ABBREVIATION; - SHORT_ABBREVIATION; +@:native("flash.globalization.DateTimeNameStyle") extern enum abstract DateTimeNameStyle(String) { + var FULL; + var LONG_ABBREVIATION; + var SHORT_ABBREVIATION; } diff --git a/std/flash/globalization/DateTimeStyle.hx b/std/flash/globalization/DateTimeStyle.hx index c084f5df906..1c6b84bcedf 100644 --- a/std/flash/globalization/DateTimeStyle.hx +++ b/std/flash/globalization/DateTimeStyle.hx @@ -1,9 +1,9 @@ package flash.globalization; -@:fakeEnum(String) extern enum DateTimeStyle { - CUSTOM; - LONG; - MEDIUM; - NONE; - SHORT; +@:native("flash.globalization.DateTimeStyle") extern enum abstract DateTimeStyle(String) { + var CUSTOM; + var LONG; + var MEDIUM; + var NONE; + var SHORT; } diff --git a/std/flash/globalization/LastOperationStatus.hx b/std/flash/globalization/LastOperationStatus.hx index a6bbd58461d..a18bf215dc3 100644 --- a/std/flash/globalization/LastOperationStatus.hx +++ b/std/flash/globalization/LastOperationStatus.hx @@ -1,21 +1,21 @@ package flash.globalization; -@:fakeEnum(String) extern enum LastOperationStatus { - BUFFER_OVERFLOW_ERROR; - ERROR_CODE_UNKNOWN; - ILLEGAL_ARGUMENT_ERROR; - INDEX_OUT_OF_BOUNDS_ERROR; - INVALID_ATTR_VALUE; - INVALID_CHAR_FOUND; - MEMORY_ALLOCATION_ERROR; - NO_ERROR; - NUMBER_OVERFLOW_ERROR; - PARSE_ERROR; - PATTERN_SYNTAX_ERROR; - PLATFORM_API_FAILED; - TRUNCATED_CHAR_FOUND; - UNEXPECTED_TOKEN; - UNSUPPORTED_ERROR; - USING_DEFAULT_WARNING; - USING_FALLBACK_WARNING; +@:native("flash.globalization.LastOperationStatus") extern enum abstract LastOperationStatus(String) { + var BUFFER_OVERFLOW_ERROR; + var ERROR_CODE_UNKNOWN; + var ILLEGAL_ARGUMENT_ERROR; + var INDEX_OUT_OF_BOUNDS_ERROR; + var INVALID_ATTR_VALUE; + var INVALID_CHAR_FOUND; + var MEMORY_ALLOCATION_ERROR; + var NO_ERROR; + var NUMBER_OVERFLOW_ERROR; + var PARSE_ERROR; + var PATTERN_SYNTAX_ERROR; + var PLATFORM_API_FAILED; + var TRUNCATED_CHAR_FOUND; + var UNEXPECTED_TOKEN; + var UNSUPPORTED_ERROR; + var USING_DEFAULT_WARNING; + var USING_FALLBACK_WARNING; } diff --git a/std/flash/globalization/LocaleID.hx b/std/flash/globalization/LocaleID.hx index 250840c5f32..f86d0d7270b 100644 --- a/std/flash/globalization/LocaleID.hx +++ b/std/flash/globalization/LocaleID.hx @@ -1,15 +1,17 @@ package flash.globalization; -@:final @:require(flash10_1) extern class LocaleID { - var lastOperationStatus(default,never) : LastOperationStatus; - var name(default,never) : String; +@:require(flash10_1) extern final class LocaleID { + @:flash.property var lastOperationStatus(get,never) : LastOperationStatus; + @:flash.property var name(get,never) : String; function new(name : String) : Void; function getKeysAndValues() : flash.utils.Object; function getLanguage() : String; function getRegion() : String; function getScript() : String; function getVariant() : String; + private function get_lastOperationStatus() : LastOperationStatus; + private function get_name() : String; function isRightToLeft() : Bool; - static var DEFAULT(default,never) : String; + static final DEFAULT : String; static function determinePreferredLocales(want : flash.Vector, have : flash.Vector, ?keyword : String) : flash.Vector; } diff --git a/std/flash/globalization/NationalDigitsType.hx b/std/flash/globalization/NationalDigitsType.hx index ede278cf27c..af535ae44ad 100644 --- a/std/flash/globalization/NationalDigitsType.hx +++ b/std/flash/globalization/NationalDigitsType.hx @@ -1,36 +1,36 @@ package flash.globalization; -@:fakeEnum(UInt) extern enum NationalDigitsType { - ARABIC_INDIC; - BALINESE; - BENGALI; - CHAM; - DEVANAGARI; - EUROPEAN; - EXTENDED_ARABIC_INDIC; - FULL_WIDTH; - GUJARATI; - GURMUKHI; - KANNADA; - KAYAH_LI; - KHMER; - LAO; - LEPCHA; - LIMBU; - MALAYALAM; - MONGOLIAN; - MYANMAR; - MYANMAR_SHAN; - NEW_TAI_LUE; - NKO; - OL_CHIKI; - ORIYA; - OSMANYA; - SAURASHTRA; - SUNDANESE; - TAMIL; - TELUGU; - THAI; - TIBETAN; - VAI; +@:native("flash.globalization.NationalDigitsType") extern enum abstract NationalDigitsType(UInt) { + var ARABIC_INDIC; + var BALINESE; + var BENGALI; + var CHAM; + var DEVANAGARI; + var EUROPEAN; + var EXTENDED_ARABIC_INDIC; + var FULL_WIDTH; + var GUJARATI; + var GURMUKHI; + var KANNADA; + var KAYAH_LI; + var KHMER; + var LAO; + var LEPCHA; + var LIMBU; + var MALAYALAM; + var MONGOLIAN; + var MYANMAR; + var MYANMAR_SHAN; + var NEW_TAI_LUE; + var NKO; + var OL_CHIKI; + var ORIYA; + var OSMANYA; + var SAURASHTRA; + var SUNDANESE; + var TAMIL; + var TELUGU; + var THAI; + var TIBETAN; + var VAI; } diff --git a/std/flash/globalization/NumberFormatter.hx b/std/flash/globalization/NumberFormatter.hx index 325edfc77f9..27b3f85053d 100644 --- a/std/flash/globalization/NumberFormatter.hx +++ b/std/flash/globalization/NumberFormatter.hx @@ -1,24 +1,47 @@ package flash.globalization; -@:final @:require(flash10_1) extern class NumberFormatter { - var actualLocaleIDName(default,never) : String; - var decimalSeparator : String; - var digitsType : NationalDigitsType; - var fractionalDigits : Int; - var groupingPattern : String; - var groupingSeparator : String; - var lastOperationStatus(default,never) : LastOperationStatus; - var leadingZero : Bool; - var negativeNumberFormat : UInt; - var negativeSymbol : String; - var requestedLocaleIDName(default,never) : String; - var trailingZeros : Bool; - var useGrouping : Bool; +@:require(flash10_1) extern final class NumberFormatter { + @:flash.property var actualLocaleIDName(get,never) : String; + @:flash.property var decimalSeparator(get,set) : String; + @:flash.property var digitsType(get,set) : NationalDigitsType; + @:flash.property var fractionalDigits(get,set) : Int; + @:flash.property var groupingPattern(get,set) : String; + @:flash.property var groupingSeparator(get,set) : String; + @:flash.property var lastOperationStatus(get,never) : LastOperationStatus; + @:flash.property var leadingZero(get,set) : Bool; + @:flash.property var negativeNumberFormat(get,set) : UInt; + @:flash.property var negativeSymbol(get,set) : String; + @:flash.property var requestedLocaleIDName(get,never) : String; + @:flash.property var trailingZeros(get,set) : Bool; + @:flash.property var useGrouping(get,set) : Bool; function new(requestedLocaleIDName : String) : Void; function formatInt(value : Int) : String; function formatNumber(value : Float) : String; function formatUint(value : UInt) : String; + private function get_actualLocaleIDName() : String; + private function get_decimalSeparator() : String; + private function get_digitsType() : NationalDigitsType; + private function get_fractionalDigits() : Int; + private function get_groupingPattern() : String; + private function get_groupingSeparator() : String; + private function get_lastOperationStatus() : LastOperationStatus; + private function get_leadingZero() : Bool; + private function get_negativeNumberFormat() : UInt; + private function get_negativeSymbol() : String; + private function get_requestedLocaleIDName() : String; + private function get_trailingZeros() : Bool; + private function get_useGrouping() : Bool; function parse(parseString : String) : NumberParseResult; function parseNumber(parseString : String) : Float; + private function set_decimalSeparator(value : String) : String; + private function set_digitsType(value : NationalDigitsType) : NationalDigitsType; + private function set_fractionalDigits(value : Int) : Int; + private function set_groupingPattern(value : String) : String; + private function set_groupingSeparator(value : String) : String; + private function set_leadingZero(value : Bool) : Bool; + private function set_negativeNumberFormat(value : UInt) : UInt; + private function set_negativeSymbol(value : String) : String; + private function set_trailingZeros(value : Bool) : Bool; + private function set_useGrouping(value : Bool) : Bool; static function getAvailableLocaleIDNames() : flash.Vector; } diff --git a/std/flash/globalization/NumberParseResult.hx b/std/flash/globalization/NumberParseResult.hx index ab3484f679d..9697303be0f 100644 --- a/std/flash/globalization/NumberParseResult.hx +++ b/std/flash/globalization/NumberParseResult.hx @@ -1,8 +1,11 @@ package flash.globalization; -@:final @:require(flash10_1) extern class NumberParseResult { - var endIndex(default,never) : Int; - var startIndex(default,never) : Int; - var value(default,never) : Float; +@:require(flash10_1) extern final class NumberParseResult { + @:flash.property var endIndex(get,never) : Int; + @:flash.property var startIndex(get,never) : Int; + @:flash.property var value(get,never) : Float; function new(value : Float = 0./*NaN*/, startIndex : Int = 2147483647, endIndex : Int = 2147483647) : Void; + private function get_endIndex() : Int; + private function get_startIndex() : Int; + private function get_value() : Float; } diff --git a/std/flash/globalization/StringTools.hx b/std/flash/globalization/StringTools.hx index 7dd7fce80f2..4badc737261 100644 --- a/std/flash/globalization/StringTools.hx +++ b/std/flash/globalization/StringTools.hx @@ -1,10 +1,13 @@ package flash.globalization; -@:final @:require(flash10_1) extern class StringTools { - var actualLocaleIDName(default,never) : String; - var lastOperationStatus(default,never) : LastOperationStatus; - var requestedLocaleIDName(default,never) : String; +@:require(flash10_1) extern final class StringTools { + @:flash.property var actualLocaleIDName(get,never) : String; + @:flash.property var lastOperationStatus(get,never) : LastOperationStatus; + @:flash.property var requestedLocaleIDName(get,never) : String; function new(requestedLocaleIDName : String) : Void; + private function get_actualLocaleIDName() : String; + private function get_lastOperationStatus() : LastOperationStatus; + private function get_requestedLocaleIDName() : String; function toLowerCase(s : String) : String; function toUpperCase(s : String) : String; static function getAvailableLocaleIDNames() : flash.Vector; diff --git a/std/flash/media/AVABRParameters.hx b/std/flash/media/AVABRParameters.hx index fb6f2e72c59..249ce7fea58 100644 --- a/std/flash/media/AVABRParameters.hx +++ b/std/flash/media/AVABRParameters.hx @@ -1,12 +1,20 @@ package flash.media; extern class AVABRParameters { - var maxBitsPerSecond : Int; - var minBitsPerSecond : Int; - var policy : String; - var startBitsPerSecond : Int; + @:flash.property var maxBitsPerSecond(get,set) : Int; + @:flash.property var minBitsPerSecond(get,set) : Int; + @:flash.property var policy(get,set) : String; + @:flash.property var startBitsPerSecond(get,set) : Int; function new(init_policy : String, init_startBitsPerSecond : UInt, init_minBitsPerSecond : UInt, init_maxBitsPerSecond : UInt) : Void; - static var AGGRESSIVE(default,never) : String; - static var CONSERVATIVE(default,never) : String; - static var MODERATE(default,never) : String; + private function get_maxBitsPerSecond() : Int; + private function get_minBitsPerSecond() : Int; + private function get_policy() : String; + private function get_startBitsPerSecond() : Int; + private function set_maxBitsPerSecond(value : Int) : Int; + private function set_minBitsPerSecond(value : Int) : Int; + private function set_policy(value : String) : String; + private function set_startBitsPerSecond(value : Int) : Int; + static final AGGRESSIVE : String; + static final CONSERVATIVE : String; + static final MODERATE : String; } diff --git a/std/flash/media/AVABRProfileInfo.hx b/std/flash/media/AVABRProfileInfo.hx index 990cc96b559..983e2c38595 100644 --- a/std/flash/media/AVABRProfileInfo.hx +++ b/std/flash/media/AVABRProfileInfo.hx @@ -1,8 +1,11 @@ package flash.media; extern class AVABRProfileInfo { - var bitsPerSecond(default,never) : Int; - var height(default,never) : Int; - var width(default,never) : Int; + @:flash.property var bitsPerSecond(get,never) : Int; + @:flash.property var height(get,never) : Int; + @:flash.property var width(get,never) : Int; function new(init_bitsPerSecond : Int, init_width : Int, init_height : Int) : Void; + private function get_bitsPerSecond() : Int; + private function get_height() : Int; + private function get_width() : Int; } diff --git a/std/flash/media/AVCaptionStyle.hx b/std/flash/media/AVCaptionStyle.hx index 21436f18c31..fc3c76f8a77 100644 --- a/std/flash/media/AVCaptionStyle.hx +++ b/std/flash/media/AVCaptionStyle.hx @@ -1,55 +1,77 @@ package flash.media; extern class AVCaptionStyle { - var backgroundColor : String; - var backgroundOpacity : String; - var bottomInset : String; - var edgeColor : String; - var fillColor : String; - var fillOpacity : String; - var font : String; - var fontColor : String; - var fontEdge : String; - var fontOpacity : String; - var size : String; + @:flash.property var backgroundColor(get,set) : String; + @:flash.property var backgroundOpacity(get,set) : String; + @:flash.property var bottomInset(get,set) : String; + @:flash.property var edgeColor(get,set) : String; + @:flash.property var fillColor(get,set) : String; + @:flash.property var fillOpacity(get,set) : String; + @:flash.property var font(get,set) : String; + @:flash.property var fontColor(get,set) : String; + @:flash.property var fontEdge(get,set) : String; + @:flash.property var fontOpacity(get,set) : String; + @:flash.property var size(get,set) : String; function new() : Void; - static var BLACK(default,never) : String; - static var BLUE(default,never) : String; - static var BRIGHT_BLUE(default,never) : String; - static var BRIGHT_CYAN(default,never) : String; - static var BRIGHT_GREEN(default,never) : String; - static var BRIGHT_MAGENTA(default,never) : String; - static var BRIGHT_RED(default,never) : String; - static var BRIGHT_WHITE(default,never) : String; - static var BRIGHT_YELLOW(default,never) : String; - static var CASUAL(default,never) : String; - static var CURSIVE(default,never) : String; - static var CYAN(default,never) : String; - static var DARK_BLUE(default,never) : String; - static var DARK_CYAN(default,never) : String; - static var DARK_GREEN(default,never) : String; - static var DARK_MAGENTA(default,never) : String; - static var DARK_RED(default,never) : String; - static var DARK_YELLOW(default,never) : String; - static var DEFAULT(default,never) : String; - static var DEPRESSED(default,never) : String; - static var GRAY(default,never) : String; - static var GREEN(default,never) : String; - static var LARGE(default,never) : String; - static var LEFT_DROP_SHADOW(default,never) : String; - static var MAGENTA(default,never) : String; - static var MEDIUM(default,never) : String; - static var MONOSPACED_WITHOUT_SERIFS(default,never) : String; - static var MONOSPACE_WITH_SERIFS(default,never) : String; - static var NONE(default,never) : String; - static var PROPORTIONAL_WITHOUT_SERIFS(default,never) : String; - static var PROPORTIONAL_WITH_SERIFS(default,never) : String; - static var RAISED(default,never) : String; - static var RED(default,never) : String; - static var RIGHT_DROP_SHADOW(default,never) : String; - static var SMALL(default,never) : String; - static var SMALL_CAPITALS(default,never) : String; - static var UNIFORM(default,never) : String; - static var WHITE(default,never) : String; - static var YELLOW(default,never) : String; + private function get_backgroundColor() : String; + private function get_backgroundOpacity() : String; + private function get_bottomInset() : String; + private function get_edgeColor() : String; + private function get_fillColor() : String; + private function get_fillOpacity() : String; + private function get_font() : String; + private function get_fontColor() : String; + private function get_fontEdge() : String; + private function get_fontOpacity() : String; + private function get_size() : String; + private function set_backgroundColor(value : String) : String; + private function set_backgroundOpacity(value : String) : String; + private function set_bottomInset(value : String) : String; + private function set_edgeColor(value : String) : String; + private function set_fillColor(value : String) : String; + private function set_fillOpacity(value : String) : String; + private function set_font(value : String) : String; + private function set_fontColor(value : String) : String; + private function set_fontEdge(value : String) : String; + private function set_fontOpacity(value : String) : String; + private function set_size(value : String) : String; + static final BLACK : String; + static final BLUE : String; + static final BRIGHT_BLUE : String; + static final BRIGHT_CYAN : String; + static final BRIGHT_GREEN : String; + static final BRIGHT_MAGENTA : String; + static final BRIGHT_RED : String; + static final BRIGHT_WHITE : String; + static final BRIGHT_YELLOW : String; + static final CASUAL : String; + static final CURSIVE : String; + static final CYAN : String; + static final DARK_BLUE : String; + static final DARK_CYAN : String; + static final DARK_GREEN : String; + static final DARK_MAGENTA : String; + static final DARK_RED : String; + static final DARK_YELLOW : String; + static final DEFAULT : String; + static final DEPRESSED : String; + static final GRAY : String; + static final GREEN : String; + static final LARGE : String; + static final LEFT_DROP_SHADOW : String; + static final MAGENTA : String; + static final MEDIUM : String; + static final MONOSPACED_WITHOUT_SERIFS : String; + static final MONOSPACE_WITH_SERIFS : String; + static final NONE : String; + static final PROPORTIONAL_WITHOUT_SERIFS : String; + static final PROPORTIONAL_WITH_SERIFS : String; + static final RAISED : String; + static final RED : String; + static final RIGHT_DROP_SHADOW : String; + static final SMALL : String; + static final SMALL_CAPITALS : String; + static final UNIFORM : String; + static final WHITE : String; + static final YELLOW : String; } diff --git a/std/flash/media/AVCuePoint.hx b/std/flash/media/AVCuePoint.hx index b8d7c852f4c..34b2427d55f 100644 --- a/std/flash/media/AVCuePoint.hx +++ b/std/flash/media/AVCuePoint.hx @@ -1,7 +1,9 @@ package flash.media; extern class AVCuePoint { - var dictionary(default,never) : flash.utils.Dictionary; - var localTime(default,never) : Float; + @:flash.property var dictionary(get,never) : flash.utils.Dictionary; + @:flash.property var localTime(get,never) : Float; function new(init_dictionary : flash.utils.Dictionary, init_localTime : Float) : Void; + private function get_dictionary() : flash.utils.Dictionary; + private function get_localTime() : Float; } diff --git a/std/flash/media/AVInsertionResult.hx b/std/flash/media/AVInsertionResult.hx index b306a15bb68..8f1e555511a 100644 --- a/std/flash/media/AVInsertionResult.hx +++ b/std/flash/media/AVInsertionResult.hx @@ -1,7 +1,9 @@ package flash.media; extern class AVInsertionResult extends AVResult { - var insertedBeforeReadHead(default,never) : Bool; - var periodIndex(default,never) : Int; + @:flash.property var insertedBeforeReadHead(get,never) : Bool; + @:flash.property var periodIndex(get,never) : Int; function new(result : Int, periodIndex : Int, insertedBeforeReadHead : Bool) : Void; + private function get_insertedBeforeReadHead() : Bool; + private function get_periodIndex() : Int; } diff --git a/std/flash/media/AVNetworkingParams.hx b/std/flash/media/AVNetworkingParams.hx index e0056540c19..7bc5cbde149 100644 --- a/std/flash/media/AVNetworkingParams.hx +++ b/std/flash/media/AVNetworkingParams.hx @@ -1,8 +1,20 @@ package flash.media; extern class AVNetworkingParams { - var forceNativeNetworking : Bool; - var readSetCookieHeader : Bool; - var useCookieHeaderForAllRequests : Bool; - function new(init_forceNativeNetworking : Bool = false, init_readSetCookieHeader : Bool = true, init_useCookieHeaderForAllRequests : Bool = false) : Void; + @:flash.property var appendRandomQueryParameter(get,set) : String; + @:flash.property var forceNativeNetworking(get,set) : Bool; + @:flash.property var networkDownVerificationUrl(get,set) : String; + @:flash.property var readSetCookieHeader(get,set) : Bool; + @:flash.property var useCookieHeaderForAllRequests(get,set) : Bool; + function new(init_forceNativeNetworking : Bool = false, init_readSetCookieHeader : Bool = true, init_useCookieHeaderForAllRequests : Bool = false, ?init_networkDownVerificationUrl : String) : Void; + private function get_appendRandomQueryParameter() : String; + private function get_forceNativeNetworking() : Bool; + private function get_networkDownVerificationUrl() : String; + private function get_readSetCookieHeader() : Bool; + private function get_useCookieHeaderForAllRequests() : Bool; + private function set_appendRandomQueryParameter(value : String) : String; + private function set_forceNativeNetworking(value : Bool) : Bool; + private function set_networkDownVerificationUrl(value : String) : String; + private function set_readSetCookieHeader(value : Bool) : Bool; + private function set_useCookieHeaderForAllRequests(value : Bool) : Bool; } diff --git a/std/flash/media/AVPeriodInfo.hx b/std/flash/media/AVPeriodInfo.hx index 91cde1a74ce..5f49b21ce12 100644 --- a/std/flash/media/AVPeriodInfo.hx +++ b/std/flash/media/AVPeriodInfo.hx @@ -1,15 +1,25 @@ package flash.media; extern class AVPeriodInfo { - var duration(default,never) : Float; - var firstCuePointIndex(default,never) : Int; - var firstSubscribedTagIndex(default,never) : Int; - var lastCuePointIndex(default,never) : Int; - var lastSubscribedTagIndex(default,never) : Int; - var localStartTime(default,never) : Float; - var supportsTrickPlay(default,never) : Bool; - var targetDuration(default,never) : Float; - var userData(default,never) : Int; - var virtualStartTime(default,never) : Float; + @:flash.property var duration(get,never) : Float; + @:flash.property var firstCuePointIndex(get,never) : Int; + @:flash.property var firstSubscribedTagIndex(get,never) : Int; + @:flash.property var lastCuePointIndex(get,never) : Int; + @:flash.property var lastSubscribedTagIndex(get,never) : Int; + @:flash.property var localStartTime(get,never) : Float; + @:flash.property var supportsTrickPlay(get,never) : Bool; + @:flash.property var targetDuration(get,never) : Float; + @:flash.property var userData(get,never) : Int; + @:flash.property var virtualStartTime(get,never) : Float; function new(init_localStartTime : Float, init_virtualStartTime : Float, init_duration : Float, init_firstCuePointIndex : Int, init_lastCuePointIndex : Int, init_firstSubscribedTagIndex : Int, init_lastSubscribedTagIndex : Int, init_userData : Int, init_supportsTrickPlay : Bool, init_targetDuration : Float) : Void; + private function get_duration() : Float; + private function get_firstCuePointIndex() : Int; + private function get_firstSubscribedTagIndex() : Int; + private function get_lastCuePointIndex() : Int; + private function get_lastSubscribedTagIndex() : Int; + private function get_localStartTime() : Float; + private function get_supportsTrickPlay() : Bool; + private function get_targetDuration() : Float; + private function get_userData() : Int; + private function get_virtualStartTime() : Float; } diff --git a/std/flash/media/AVPlayState.hx b/std/flash/media/AVPlayState.hx index 2b61091805e..00f40202102 100644 --- a/std/flash/media/AVPlayState.hx +++ b/std/flash/media/AVPlayState.hx @@ -1,15 +1,16 @@ package flash.media; extern class AVPlayState { - var state(default,never) : Int; + @:flash.property var state(get,never) : Int; function new(state : UInt) : Void; - static var BUFFERING(default,never) : Int; - static var EOF(default,never) : Int; - static var PAUSED(default,never) : Int; - static var PLAYING(default,never) : Int; - static var READY(default,never) : Int; - static var SUSPENDED(default,never) : Int; - static var TRICK_PLAY(default,never) : Int; - static var UNINITIALIZED(default,never) : Int; - static var UNRECOVERABLE_ERROR(default,never) : Int; + private function get_state() : Int; + static final BUFFERING : Int; + static final EOF : Int; + static final PAUSED : Int; + static final PLAYING : Int; + static final READY : Int; + static final SUSPENDED : Int; + static final TRICK_PLAY : Int; + static final UNINITIALIZED : Int; + static final UNRECOVERABLE_ERROR : Int; } diff --git a/std/flash/media/AVResult.hx b/std/flash/media/AVResult.hx index 0fad410f2fa..1594a40cca3 100644 --- a/std/flash/media/AVResult.hx +++ b/std/flash/media/AVResult.hx @@ -1,107 +1,108 @@ package flash.media; extern class AVResult { - var result(default,never) : Int; + @:flash.property var result(get,never) : Int; function new(inResult : Int) : Void; - static var ASYNC_OPERATION_IN_PROGRESS(default,never) : Int; - static var AUDIO_ONLY_STREAM_END(default,never) : Int; - static var AUDIO_ONLY_STREAM_START(default,never) : Int; - static var AUDIO_START_ERROR(default,never) : Int; - static var BAD_MANIFEST_SIGNATURE(default,never) : Int; - static var BAD_MEDIASAMPLE_FOUND(default,never) : Int; - static var BAD_MEDIA_INTERLEAVING(default,never) : Int; - static var CALLED_FROM_WRONG_THREAD(default,never) : Int; - static var CANNOT_ERASE_TIMELINE(default,never) : Int; - static var CANNOT_FAIL_OVER(default,never) : Int; - static var CANNOT_HANDLE_MAIN_MANIFEST_UPDATE(default,never) : Int; - static var CANNOT_LOAD_PLAY_LIST(default,never) : Int; - static var CANNOT_SPLIT_TIMELINE(default,never) : Int; - static var CODEC_NOT_SUPPORTED(default,never) : Int; - static var COMPONENT_CREATION_FAILURE(default,never) : Int; - static var CONTAINER_NOT_SUPPORTED(default,never) : Int; - static var CONTENT_LENGTH_MISMATCH(default,never) : Int; - static var CRYPTO_ALGORITHM_NOT_SUPPORTED(default,never) : Int; - static var CRYPTO_ERROR_BAD_CERTIFICATE(default,never) : Int; - static var CRYPTO_ERROR_BAD_PARAMETER(default,never) : Int; - static var CRYPTO_ERROR_BUFFER_TOO_SMALL(default,never) : Int; - static var CRYPTO_ERROR_CORRUPTED_DATA(default,never) : Int; - static var CRYPTO_ERROR_DIGEST_FINISH(default,never) : Int; - static var CRYPTO_ERROR_DIGEST_UPDATE(default,never) : Int; - static var CRYPTO_ERROR_UNKNOWN(default,never) : Int; - static var CURRENT_PERIOD_EXPIRED(default,never) : Int; - static var DECODER_FAILED(default,never) : Int; - static var DEVICE_OPEN_ERROR(default,never) : Int; - static var DID_NOT_GET_NEXT_FRAGMENT(default,never) : Int; - static var DRM_INIT_ERROR(default,never) : Int; - static var DRM_NOT_AVAILABLE(default,never) : Int; - static var END_OF_PERIOD(default,never) : Int; - static var EOF(default,never) : Int; - static var FILE_NOT_FOUND(default,never) : Int; - static var FILE_OPEN_ERROR(default,never) : Int; - static var FILE_READ_ERROR(default,never) : Int; - static var FILE_STRUCTURE_INVALID(default,never) : Int; - static var FILE_WRITE_ERROR(default,never) : Int; - static var FRAGMENT_READ_ERROR(default,never) : Int; - static var GENERIC_ERROR(default,never) : Int; - static var HTTP_TIME_OUT(default,never) : Int; - static var ID3_PARSE_ERROR(default,never) : Int; - static var INCOMPATIBLE_RENDER_MODE(default,never) : Int; - static var INCOMPATIBLE_VERSION(default,never) : Int; - static var INTERNAL_ERROR(default,never) : Int; - static var INVALID_KEY(default,never) : Int; - static var INVALID_OPERATION(default,never) : Int; - static var INVALID_PARAMETER(default,never) : Int; - static var INVALID_REPLACE_DURATION(default,never) : Int; - static var INVALID_SEEK_TIME(default,never) : Int; - static var INVALID_WITH_AUDIO_ONLY_FILE(default,never) : Int; - static var IRRECOVERABLE_ERROR(default,never) : Int; - static var KEY_NOT_FOUND(default,never) : Int; - static var KEY_SERVER_NOT_FOUND(default,never) : Int; - static var LISTENER_NOT_FOUND(default,never) : Int; - static var LIVE_HOLD(default,never) : Int; - static var LIVE_WINDOW_MOVED_BACKWARD(default,never) : Int; - static var LOST_CONNECTION_RECOVERABLE(default,never) : Int; - static var MAIN_MANIFEST_UPDATE_TO_BE_HANDLED(default,never) : Int; - static var MANIFEST_FILE_UNEXPECTEDLY_CHANGED(default,never) : Int; - static var NETWORK_DOWN(default,never) : Int; - static var NETWORK_ERROR(default,never) : Int; - static var NETWORK_UNAVAILABLE(default,never) : Int; - static var NOT_IMPLEMENTED(default,never) : Int; - static var NO_AUDIO_SINK(default,never) : Int; - static var NO_FIXED_SIZE(default,never) : Int; - static var NO_TIMELINE(default,never) : Int; - static var NO_USEABLE_BITRATE_PROFILE(default,never) : Int; - static var NULL_OPERATION(default,never) : Int; - static var ONLY_ALLOWED_IN_PAUSED_STATE(default,never) : Int; - static var OPERATION_ABORTED(default,never) : Int; - static var OUT_OF_MEMORY(default,never) : Int; - static var OVERFLOW(default,never) : Int; - static var PARSE_ERROR(default,never) : Int; - static var PARTIAL_REPLACEMENT(default,never) : Int; - static var PERIOD_HOLD(default,never) : Int; - static var PERIOD_NOT_LOADED(default,never) : Int; - static var PLAYBACK_NOT_ENABLED(default,never) : Int; - static var POSTROLL_WITH_LIVE_NOT_ALLOWED(default,never) : Int; - static var PREVIOUS_STEP_SEEK_IN_PROGRESS(default,never) : Int; - static var PROTOCOL_NOT_SUPPORTED(default,never) : Int; - static var RANGE_ERROR(default,never) : Int; - static var RANGE_SPANS_READHEAD(default,never) : Int; - static var RENDITION_M3U8_ERROR(default,never) : Int; - static var REPLACEMENT_FAILED(default,never) : Int; - static var RESOURCE_NOT_SPECIFIED(default,never) : Int; - static var SECURITY_ERROR(default,never) : Int; - static var SEEK_FAILED(default,never) : Int; - static var SEGMENT_SKIPPED_ON_FAILURE(default,never) : Int; - static var SIZE_UNKNOWN(default,never) : Int; - static var SPS_PPS_FOUND_OUTSIDE_AVCC(default,never) : Int; - static var SUCCESS(default,never) : Int; - static var SWITCH_TO_ASYMMETRIC_PROFILE(default,never) : Int; - static var TIMELINE_TOO_SHORT(default,never) : Int; - static var UNDERFLOW(default,never) : Int; - static var UNREPORTED_TIME_DISCONTINUITY_FOUND(default,never) : Int; - static var UNSUPPORTED_CONFIGURATION(default,never) : Int; - static var UNSUPPORTED_HLS_VERSION(default,never) : Int; - static var UNSUPPORTED_OPERATION(default,never) : Int; - static var VIDEO_PROFILE_NOT_SUPPORTED(default,never) : Int; - static var WAITING_FOR_INIT(default,never) : Int; + private function get_result() : Int; + static final ASYNC_OPERATION_IN_PROGRESS : Int; + static final AUDIO_ONLY_STREAM_END : Int; + static final AUDIO_ONLY_STREAM_START : Int; + static final AUDIO_START_ERROR : Int; + static final BAD_MANIFEST_SIGNATURE : Int; + static final BAD_MEDIASAMPLE_FOUND : Int; + static final BAD_MEDIA_INTERLEAVING : Int; + static final CALLED_FROM_WRONG_THREAD : Int; + static final CANNOT_ERASE_TIMELINE : Int; + static final CANNOT_FAIL_OVER : Int; + static final CANNOT_HANDLE_MAIN_MANIFEST_UPDATE : Int; + static final CANNOT_LOAD_PLAY_LIST : Int; + static final CANNOT_SPLIT_TIMELINE : Int; + static final CODEC_NOT_SUPPORTED : Int; + static final COMPONENT_CREATION_FAILURE : Int; + static final CONTAINER_NOT_SUPPORTED : Int; + static final CONTENT_LENGTH_MISMATCH : Int; + static final CRYPTO_ALGORITHM_NOT_SUPPORTED : Int; + static final CRYPTO_ERROR_BAD_CERTIFICATE : Int; + static final CRYPTO_ERROR_BAD_PARAMETER : Int; + static final CRYPTO_ERROR_BUFFER_TOO_SMALL : Int; + static final CRYPTO_ERROR_CORRUPTED_DATA : Int; + static final CRYPTO_ERROR_DIGEST_FINISH : Int; + static final CRYPTO_ERROR_DIGEST_UPDATE : Int; + static final CRYPTO_ERROR_UNKNOWN : Int; + static final CURRENT_PERIOD_EXPIRED : Int; + static final DECODER_FAILED : Int; + static final DEVICE_OPEN_ERROR : Int; + static final DID_NOT_GET_NEXT_FRAGMENT : Int; + static final DRM_INIT_ERROR : Int; + static final DRM_NOT_AVAILABLE : Int; + static final END_OF_PERIOD : Int; + static final EOF : Int; + static final FILE_NOT_FOUND : Int; + static final FILE_OPEN_ERROR : Int; + static final FILE_READ_ERROR : Int; + static final FILE_STRUCTURE_INVALID : Int; + static final FILE_WRITE_ERROR : Int; + static final FRAGMENT_READ_ERROR : Int; + static final GENERIC_ERROR : Int; + static final HTTP_TIME_OUT : Int; + static final ID3_PARSE_ERROR : Int; + static final INCOMPATIBLE_RENDER_MODE : Int; + static final INCOMPATIBLE_VERSION : Int; + static final INTERNAL_ERROR : Int; + static final INVALID_KEY : Int; + static final INVALID_OPERATION : Int; + static final INVALID_PARAMETER : Int; + static final INVALID_REPLACE_DURATION : Int; + static final INVALID_SEEK_TIME : Int; + static final INVALID_WITH_AUDIO_ONLY_FILE : Int; + static final IRRECOVERABLE_ERROR : Int; + static final KEY_NOT_FOUND : Int; + static final KEY_SERVER_NOT_FOUND : Int; + static final LISTENER_NOT_FOUND : Int; + static final LIVE_HOLD : Int; + static final LIVE_WINDOW_MOVED_BACKWARD : Int; + static final LOST_CONNECTION_RECOVERABLE : Int; + static final MAIN_MANIFEST_UPDATE_TO_BE_HANDLED : Int; + static final MANIFEST_FILE_UNEXPECTEDLY_CHANGED : Int; + static final NETWORK_DOWN : Int; + static final NETWORK_ERROR : Int; + static final NETWORK_UNAVAILABLE : Int; + static final NOT_IMPLEMENTED : Int; + static final NO_AUDIO_SINK : Int; + static final NO_FIXED_SIZE : Int; + static final NO_TIMELINE : Int; + static final NO_USEABLE_BITRATE_PROFILE : Int; + static final NULL_OPERATION : Int; + static final ONLY_ALLOWED_IN_PAUSED_STATE : Int; + static final OPERATION_ABORTED : Int; + static final OUT_OF_MEMORY : Int; + static final OVERFLOW : Int; + static final PARSE_ERROR : Int; + static final PARTIAL_REPLACEMENT : Int; + static final PERIOD_HOLD : Int; + static final PERIOD_NOT_LOADED : Int; + static final PLAYBACK_NOT_ENABLED : Int; + static final POSTROLL_WITH_LIVE_NOT_ALLOWED : Int; + static final PREVIOUS_STEP_SEEK_IN_PROGRESS : Int; + static final PROTOCOL_NOT_SUPPORTED : Int; + static final RANGE_ERROR : Int; + static final RANGE_SPANS_READHEAD : Int; + static final RENDITION_M3U8_ERROR : Int; + static final REPLACEMENT_FAILED : Int; + static final RESOURCE_NOT_SPECIFIED : Int; + static final SECURITY_ERROR : Int; + static final SEEK_FAILED : Int; + static final SEGMENT_SKIPPED_ON_FAILURE : Int; + static final SIZE_UNKNOWN : Int; + static final SPS_PPS_FOUND_OUTSIDE_AVCC : Int; + static final SUCCESS : Int; + static final SWITCH_TO_ASYMMETRIC_PROFILE : Int; + static final TIMELINE_TOO_SHORT : Int; + static final UNDERFLOW : Int; + static final UNREPORTED_TIME_DISCONTINUITY_FOUND : Int; + static final UNSUPPORTED_CONFIGURATION : Int; + static final UNSUPPORTED_HLS_VERSION : Int; + static final UNSUPPORTED_OPERATION : Int; + static final VIDEO_PROFILE_NOT_SUPPORTED : Int; + static final WAITING_FOR_INIT : Int; } diff --git a/std/flash/media/AVSegmentedSource.hx b/std/flash/media/AVSegmentedSource.hx index 537775aaa99..b9fa0ec27e6 100644 --- a/std/flash/media/AVSegmentedSource.hx +++ b/std/flash/media/AVSegmentedSource.hx @@ -1,10 +1,10 @@ package flash.media; extern class AVSegmentedSource extends AVSource { - var cookieHeader(never,default) : String; - var masterUpdateInterval(never,default) : Int; - var networkingParams : AVNetworkingParams; - var useRedirectedUrl(never,default) : Bool; + @:flash.property var cookieHeader(never,set) : String; + @:flash.property var masterUpdateInterval(never,set) : Int; + @:flash.property var networkingParams(get,set) : AVNetworkingParams; + @:flash.property var useRedirectedUrl(never,set) : Bool; function new() : Void; function addCustomHeader(headerName : String, args : flash.Vector) : Void; function clearPauseAtPeriodEnd(periodIndex : Int) : AVResult; @@ -13,8 +13,10 @@ extern class AVSegmentedSource extends AVSource { function getBackgroundPeriodInfo(periodIndex : Int) : AVPeriodInfo; function getBackgroundTimeline() : AVTimeline; function getCuePoint(periodIndex : Int, cuePointIndex : Int) : AVCuePoint; + function getMediaPreferredStartTime() : Float; function getPerceivedBandwidth() : UInt; function getPeriodInfo(periodIndex : Int) : AVPeriodInfo; + function getPeriodInfoWithTagsAcrossIndexes(periodIndex : Int, startPeriodIndex : Int) : AVPeriodInfo; function getSubscribedTag(periodIndex : Int, tagDataIndex : Int) : AVTagData; function getSubscribedTagForBackgroundManifest(periodIndex : Int, tagDataIndex : Int) : AVTagData; function getTimeline() : AVTimeline; @@ -22,6 +24,7 @@ extern class AVSegmentedSource extends AVSource { function getTimelineSubscribedTagForBackgroundManifest(tagDataIndex : Int) : AVTagData; function getTrackCount(periodIndex : Int, payloadType : String) : Int; function getTrackInfo(periodIndex : Int, payloadType : String, trackIndex : Int) : AVTrackInfo; + private function get_networkingParams() : AVNetworkingParams; function insertByLocalTime(periodIndex : Int, insertionTime : Float, handle : Int, userData : Int = 0, replaceDuration : Float = 0) : AVInsertionResult; function insertByVirtualTime(insertionTime : Float, handle : Int, userData : Int = 0, replaceDuration : Float = 0) : AVInsertionResult; function load(url : String, ?containerType : String, userData : Int = 0) : AVResult; @@ -30,6 +33,7 @@ extern class AVSegmentedSource extends AVSource { function releaseManifest(handle : Int) : AVResult; function removeByLocalTime(periodIndex : Int, timeStart : Float, timeEnd : Float, replaceWithMainMedia : Bool) : AVResult; function removeByVirtualTime(virtualTimeStart : Float, virtualTimeEnd : Float) : AVResult; + function removeByVirtualTimeWithReplacement(virtualTimeStart : Float, virtualTimeEnd : Float, replaceWithMainMedia : Bool) : AVResult; function selectTrack(periodIndex : Int, payloadType : String, trackIndex : Int) : AVResult; function selectTrackString(periodIndex : Int, payloadType : String, trackString : String) : AVResult; function setABRParameters(params : AVABRParameters) : AVResult; @@ -39,14 +43,18 @@ extern class AVSegmentedSource extends AVSource { function setPauseAtPeriodEnd(periodIndex : Int, userData : Int = 0) : AVResult; function setSubscribedTags(tagArray : Array) : AVResult; function setSubscribedTagsForBackgroundManifest(tagArray : Array) : AVResult; - static var AUDIO(default,never) : String; - static var AUDIO_DESCRIPTION(default,never) : String; - static var AUDIO_LANGUAGE(default,never) : String; - static var AUDIO_PID(default,never) : String; - static var DASH(default,never) : String; - static var DATA(default,never) : String; - static var DATA_DESCRIPTION(default,never) : String; - static var HLS(default,never) : String; - static var VIDEO(default,never) : String; - static var VIDEO_DESCRIPTION(default,never) : String; + private function set_cookieHeader(value : String) : String; + private function set_masterUpdateInterval(value : Int) : Int; + private function set_networkingParams(value : AVNetworkingParams) : AVNetworkingParams; + private function set_useRedirectedUrl(value : Bool) : Bool; + static final AUDIO : String; + static final AUDIO_DESCRIPTION : String; + static final AUDIO_LANGUAGE : String; + static final AUDIO_PID : String; + static final DASH : String; + static final DATA : String; + static final DATA_DESCRIPTION : String; + static final HLS : String; + static final VIDEO : String; + static final VIDEO_DESCRIPTION : String; } diff --git a/std/flash/media/AVStream.hx b/std/flash/media/AVStream.hx index e98442cecc6..272037b9f2d 100644 --- a/std/flash/media/AVStream.hx +++ b/std/flash/media/AVStream.hx @@ -1,26 +1,39 @@ package flash.media; extern class AVStream extends flash.events.EventDispatcher { - var backBufferLength(default,never) : Float; - var backBufferTime(never,default) : Float; - var bufferLength(default,never) : Float; - var bufferTime(never,default) : Float; - var captionStyle(never,default) : AVCaptionStyle; - var captionsEnabled : Bool; - var clientLivePoint(default,never) : Float; - var currentFPS(default,never) : Float; - var decoderType(default,never) : String; - var droppedFrames(default,never) : Int; - var frameTime(default,never) : Float; - var initialBufferTime(never,default) : Float; - var playState(default,never) : AVPlayState; - var renderType(default,never) : String; - var time(default,never) : Float; - var useHardwareDecoder : Bool; - var volume : Float; + @:flash.property var backBufferLength(get,never) : Float; + @:flash.property var backBufferTime(never,set) : Float; + @:flash.property var bufferLength(get,never) : Float; + @:flash.property var bufferTime(never,set) : Float; + @:flash.property var captionStyle(never,set) : AVCaptionStyle; + @:flash.property var captionsEnabled(get,set) : Bool; + @:flash.property var clientLivePoint(get,never) : Float; + @:flash.property var currentFPS(get,never) : Float; + @:flash.property var decoderType(get,never) : String; + @:flash.property var droppedFrames(get,never) : Int; + @:flash.property var frameTime(get,never) : Float; + @:flash.property var initialBufferTime(never,set) : Float; + @:flash.property var playState(get,never) : AVPlayState; + @:flash.property var renderType(get,never) : String; + @:flash.property var time(get,never) : Float; + @:flash.property var useHardwareDecoder(get,set) : Bool; + @:flash.property var volume(get,set) : Float; function new(source : AVSource) : Void; function dispose() : Void; function fastForward(rate : Float) : AVResult; + private function get_backBufferLength() : Float; + private function get_bufferLength() : Float; + private function get_captionsEnabled() : Bool; + private function get_clientLivePoint() : Float; + private function get_currentFPS() : Float; + private function get_decoderType() : String; + private function get_droppedFrames() : Int; + private function get_frameTime() : Float; + private function get_playState() : AVPlayState; + private function get_renderType() : String; + private function get_time() : Float; + private function get_useHardwareDecoder() : Bool; + private function get_volume() : Float; function pause() : AVResult; function play() : AVResult; function resume() : Bool; @@ -30,8 +43,15 @@ extern class AVStream extends flash.events.EventDispatcher { function seekToLivePoint() : AVResult; function seekToLocalTime(periodIndex : Int, time : Float) : AVResult; function setPlaySpeed(speed : Float, reserved : Float) : Void; + private function set_backBufferTime(value : Float) : Float; + private function set_bufferTime(value : Float) : Float; + private function set_captionStyle(value : AVCaptionStyle) : AVCaptionStyle; + private function set_captionsEnabled(value : Bool) : Bool; + private function set_initialBufferTime(value : Float) : Float; + private function set_useHardwareDecoder(value : Bool) : Bool; + private function set_volume(value : Float) : Float; function step(frames : Int) : AVResult; - static var HARDWARE(default,never) : String; - static var SOFTWARE(default,never) : String; - static var UNDEFINED(default,never) : String; + static final HARDWARE : String; + static final SOFTWARE : String; + static final UNDEFINED : String; } diff --git a/std/flash/media/AVTagData.hx b/std/flash/media/AVTagData.hx index 6f3d42b652e..0d1272a6f94 100644 --- a/std/flash/media/AVTagData.hx +++ b/std/flash/media/AVTagData.hx @@ -1,7 +1,9 @@ package flash.media; extern class AVTagData { - var data(default,never) : String; - var localTime(default,never) : Float; + @:flash.property var data(get,never) : String; + @:flash.property var localTime(get,never) : Float; function new(init_data : String, init_localTime : Float) : Void; + private function get_data() : String; + private function get_localTime() : Float; } diff --git a/std/flash/media/AVTimeline.hx b/std/flash/media/AVTimeline.hx index b5ebd161462..e939c8cfd97 100644 --- a/std/flash/media/AVTimeline.hx +++ b/std/flash/media/AVTimeline.hx @@ -1,13 +1,21 @@ package flash.media; extern class AVTimeline { - var complete(default,never) : Bool; - var firstPeriodIndex(default,never) : Int; - var firstSubscribedTagIndex(default,never) : Int; - var lastPeriodIndex(default,never) : Int; - var lastSubscribedTagIndex(default,never) : Int; - var type(default,never) : String; - var virtualDuration(default,never) : Float; - var virtualStartTime(default,never) : Float; + @:flash.property var complete(get,never) : Bool; + @:flash.property var firstPeriodIndex(get,never) : Int; + @:flash.property var firstSubscribedTagIndex(get,never) : Int; + @:flash.property var lastPeriodIndex(get,never) : Int; + @:flash.property var lastSubscribedTagIndex(get,never) : Int; + @:flash.property var type(get,never) : String; + @:flash.property var virtualDuration(get,never) : Float; + @:flash.property var virtualStartTime(get,never) : Float; function new(init_type : String, init_virtualStartTime : Float, init_virtualDuration : Float, init_firstPeriodIndex : Int, init_lastPeriodIndex : Int, init_firstSubscribedIndex : Int, init_lastSubscribedIndex : Int, init_complete : Bool) : Void; + private function get_complete() : Bool; + private function get_firstPeriodIndex() : Int; + private function get_firstSubscribedTagIndex() : Int; + private function get_lastPeriodIndex() : Int; + private function get_lastSubscribedTagIndex() : Int; + private function get_type() : String; + private function get_virtualDuration() : Float; + private function get_virtualStartTime() : Float; } diff --git a/std/flash/media/AVTrackInfo.hx b/std/flash/media/AVTrackInfo.hx index 8ca3777a450..08dbd284942 100644 --- a/std/flash/media/AVTrackInfo.hx +++ b/std/flash/media/AVTrackInfo.hx @@ -1,16 +1,24 @@ package flash.media; extern class AVTrackInfo { - var activity(default,never) : Bool; - var autoSelect(default,never) : Bool; - var dataTrackInfoServiceType(default,never) : String; - var defaultTrack(default,never) : Bool; - var description(default,never) : String; - var forced(default,never) : Bool; - var language(default,never) : String; - var pid(default,never) : Int; + @:flash.property var activity(get,never) : Bool; + @:flash.property var autoSelect(get,never) : Bool; + @:flash.property var dataTrackInfoServiceType(get,never) : String; + @:flash.property var defaultTrack(get,never) : Bool; + @:flash.property var description(get,never) : String; + @:flash.property var forced(get,never) : Bool; + @:flash.property var language(get,never) : String; + @:flash.property var pid(get,never) : Int; function new(init_description : String, init_language : String, init_defaultTrack : Bool, init_autoSelect : Bool, init_forced : Bool, init_activity : Bool, init_dataTrackInfoServiceType : String, init_pid : Int) : Void; - static var DTI_608_CAPTIONS(default,never) : String; - static var DTI_708_CAPTIONS(default,never) : String; - static var DTI_WEBVTT_CAPTIONS(default,never) : String; + private function get_activity() : Bool; + private function get_autoSelect() : Bool; + private function get_dataTrackInfoServiceType() : String; + private function get_defaultTrack() : Bool; + private function get_description() : String; + private function get_forced() : Bool; + private function get_language() : String; + private function get_pid() : Int; + static final DTI_608_CAPTIONS : String; + static final DTI_708_CAPTIONS : String; + static final DTI_WEBVTT_CAPTIONS : String; } diff --git a/std/flash/media/AVURLLoader.hx b/std/flash/media/AVURLLoader.hx index 05c4ca9715a..4f9fd81b9b9 100644 --- a/std/flash/media/AVURLLoader.hx +++ b/std/flash/media/AVURLLoader.hx @@ -1,7 +1,8 @@ package flash.media; extern class AVURLLoader extends flash.net.URLLoader { - var cookieHeader(never,default) : String; + @:flash.property var cookieHeader(never,set) : String; var stream : AVURLStream; function new(?request : flash.net.URLRequest) : Void; + private function set_cookieHeader(value : String) : String; } diff --git a/std/flash/media/AVURLStream.hx b/std/flash/media/AVURLStream.hx index 6e6ef8ff028..ea59d6597bb 100644 --- a/std/flash/media/AVURLStream.hx +++ b/std/flash/media/AVURLStream.hx @@ -1,6 +1,7 @@ package flash.media; extern class AVURLStream extends flash.net.URLStream { - var cookieHeader(never,default) : String; + @:flash.property var cookieHeader(never,set) : String; function new() : Void; + private function set_cookieHeader(value : String) : String; } diff --git a/std/flash/media/AudioDecoder.hx b/std/flash/media/AudioDecoder.hx index a4fe5e95515..a4cac29bbd3 100644 --- a/std/flash/media/AudioDecoder.hx +++ b/std/flash/media/AudioDecoder.hx @@ -2,10 +2,10 @@ package flash.media; extern class AudioDecoder { function new() : Void; - static var DOLBY_DIGITAL(default,never) : String; - static var DOLBY_DIGITAL_PLUS(default,never) : String; - static var DTS(default,never) : String; - static var DTS_EXPRESS(default,never) : String; - static var DTS_HD_HIGH_RESOLUTION_AUDIO(default,never) : String; - static var DTS_HD_MASTER_AUDIO(default,never) : String; + static final DOLBY_DIGITAL : String; + static final DOLBY_DIGITAL_PLUS : String; + static final DTS : String; + static final DTS_EXPRESS : String; + static final DTS_HD_HIGH_RESOLUTION_AUDIO : String; + static final DTS_HD_MASTER_AUDIO : String; } diff --git a/std/flash/media/AudioDeviceManager.hx b/std/flash/media/AudioDeviceManager.hx new file mode 100644 index 00000000000..791aba665a1 --- /dev/null +++ b/std/flash/media/AudioDeviceManager.hx @@ -0,0 +1,14 @@ +package flash.media; + +extern final class AudioDeviceManager extends flash.events.EventDispatcher { + @:flash.property var deviceNames(get,never) : Array; + @:flash.property var selectedDeviceIndex(get,set) : Int; + function new() : Void; + private function get_deviceNames() : Array; + private function get_selectedDeviceIndex() : Int; + private function set_selectedDeviceIndex(value : Int) : Int; + @:flash.property static var audioDeviceManager(get,never) : AudioDeviceManager; + @:flash.property static var isSupported(get,never) : Bool; + private static function get_audioDeviceManager() : AudioDeviceManager; + private static function get_isSupported() : Bool; +} diff --git a/std/flash/media/AudioOutputChangeReason.hx b/std/flash/media/AudioOutputChangeReason.hx new file mode 100644 index 00000000000..3e12b6cb0c0 --- /dev/null +++ b/std/flash/media/AudioOutputChangeReason.hx @@ -0,0 +1,7 @@ +package flash.media; + +extern class AudioOutputChangeReason { + function new() : Void; + static final DEVICE_CHANGE : String; + static final USER_SELECTION : String; +} diff --git a/std/flash/media/Camera.hx b/std/flash/media/Camera.hx index 75f0ef79e23..033410a5e11 100644 --- a/std/flash/media/Camera.hx +++ b/std/flash/media/Camera.hx @@ -1,33 +1,50 @@ package flash.media; -@:final extern class Camera extends flash.events.EventDispatcher { - var activityLevel(default,never) : Float; - var bandwidth(default,never) : Int; - var currentFPS(default,never) : Float; - var fps(default,never) : Float; - var height(default,never) : Int; - var index(default,never) : Int; - var keyFrameInterval(default,never) : Int; - var loopback(default,never) : Bool; - var motionLevel(default,never) : Int; - var motionTimeout(default,never) : Int; - var muted(default,never) : Bool; - var name(default,never) : String; - @:require(flash11_2) var position(default,never) : String; - var quality(default,never) : Int; - var width(default,never) : Int; +extern final class Camera extends flash.events.EventDispatcher { + @:flash.property var activityLevel(get,never) : Float; + @:flash.property var bandwidth(get,never) : Int; + @:flash.property var currentFPS(get,never) : Float; + @:flash.property var fps(get,never) : Float; + @:flash.property var height(get,never) : Int; + @:flash.property var index(get,never) : Int; + @:flash.property var keyFrameInterval(get,never) : Int; + @:flash.property var loopback(get,never) : Bool; + @:flash.property var motionLevel(get,never) : Int; + @:flash.property var motionTimeout(get,never) : Int; + @:flash.property var muted(get,never) : Bool; + @:flash.property var name(get,never) : String; + @:flash.property @:require(flash11_2) var position(get,never) : String; + @:flash.property var quality(get,never) : Int; + @:flash.property var width(get,never) : Int; function new() : Void; @:require(flash11_4) function copyToByteArray(rect : flash.geom.Rectangle, destination : flash.utils.ByteArray) : Void; @:require(flash11_4) function copyToVector(rect : flash.geom.Rectangle, destination : flash.Vector) : Void; @:require(flash11_4) function drawToBitmapData(destination : flash.display.BitmapData) : Void; + private function get_activityLevel() : Float; + private function get_bandwidth() : Int; + private function get_currentFPS() : Float; + private function get_fps() : Float; + private function get_height() : Int; + private function get_index() : Int; + private function get_keyFrameInterval() : Int; + private function get_loopback() : Bool; + private function get_motionLevel() : Int; + private function get_motionTimeout() : Int; + private function get_muted() : Bool; + private function get_name() : String; + private function get_position() : String; + private function get_quality() : Int; + private function get_width() : Int; function setCursor(value : Bool) : Void; function setKeyFrameInterval(keyFrameInterval : Int) : Void; function setLoopback(compress : Bool = false) : Void; function setMode(width : Int, height : Int, fps : Float, favorArea : Bool = true) : Void; function setMotionLevel(motionLevel : Int, timeout : Int = 2000) : Void; function setQuality(bandwidth : Int, quality : Int) : Void; - @:require(flash10_1) static var isSupported(default,never) : Bool; - static var names(default,never) : Array; - @:require(flash10_1) static function _scanHardware() : Void; + @:flash.property @:require(flash10_1) static var isSupported(get,never) : Bool; + @:flash.property static var names(get,never) : Array; + @:ns("flash.media",internal) @:require(flash10_1) static function _scanHardware() : Void; static function getCamera(?name : String) : Camera; + private static function get_isSupported() : Bool; + private static function get_names() : Array; } diff --git a/std/flash/media/H264Level.hx b/std/flash/media/H264Level.hx index 02f62e1a5ea..e908c84f83d 100644 --- a/std/flash/media/H264Level.hx +++ b/std/flash/media/H264Level.hx @@ -2,20 +2,20 @@ package flash.media; extern class H264Level { function new() : Void; - static var LEVEL_1(default,never) : String; - static var LEVEL_1B(default,never) : String; - static var LEVEL_1_1(default,never) : String; - static var LEVEL_1_2(default,never) : String; - static var LEVEL_1_3(default,never) : String; - static var LEVEL_2(default,never) : String; - static var LEVEL_2_1(default,never) : String; - static var LEVEL_2_2(default,never) : String; - static var LEVEL_3(default,never) : String; - static var LEVEL_3_1(default,never) : String; - static var LEVEL_3_2(default,never) : String; - static var LEVEL_4(default,never) : String; - static var LEVEL_4_1(default,never) : String; - static var LEVEL_4_2(default,never) : String; - static var LEVEL_5(default,never) : String; - static var LEVEL_5_1(default,never) : String; + static final LEVEL_1 : String; + static final LEVEL_1B : String; + static final LEVEL_1_1 : String; + static final LEVEL_1_2 : String; + static final LEVEL_1_3 : String; + static final LEVEL_2 : String; + static final LEVEL_2_1 : String; + static final LEVEL_2_2 : String; + static final LEVEL_3 : String; + static final LEVEL_3_1 : String; + static final LEVEL_3_2 : String; + static final LEVEL_4 : String; + static final LEVEL_4_1 : String; + static final LEVEL_4_2 : String; + static final LEVEL_5 : String; + static final LEVEL_5_1 : String; } diff --git a/std/flash/media/H264Profile.hx b/std/flash/media/H264Profile.hx index 92ec292899a..41ba13a5d27 100644 --- a/std/flash/media/H264Profile.hx +++ b/std/flash/media/H264Profile.hx @@ -2,6 +2,6 @@ package flash.media; extern class H264Profile { function new() : Void; - static var BASELINE(default,never) : String; - static var MAIN(default,never) : String; + static final BASELINE : String; + static final MAIN : String; } diff --git a/std/flash/media/H264VideoStreamSettings.hx b/std/flash/media/H264VideoStreamSettings.hx index cc2c6e4eb7b..7086be17cba 100644 --- a/std/flash/media/H264VideoStreamSettings.hx +++ b/std/flash/media/H264VideoStreamSettings.hx @@ -1,8 +1,10 @@ package flash.media; extern class H264VideoStreamSettings extends VideoStreamSettings { - var level(default,never) : String; - var profile(default,never) : String; + @:flash.property var level(get,never) : String; + @:flash.property var profile(get,never) : String; function new() : Void; + private function get_level() : String; + private function get_profile() : String; function setProfileLevel(profile : String, level : String) : Void; } diff --git a/std/flash/media/ID3Info.hx b/std/flash/media/ID3Info.hx index 235a97b0280..aef5c75c65c 100644 --- a/std/flash/media/ID3Info.hx +++ b/std/flash/media/ID3Info.hx @@ -1,6 +1,6 @@ package flash.media; -@:final extern class ID3Info implements Dynamic { +extern final class ID3Info implements Dynamic { var album : String; var artist : String; var comment : String; diff --git a/std/flash/media/Microphone.hx b/std/flash/media/Microphone.hx index f2daac99b20..4fd568fb5aa 100644 --- a/std/flash/media/Microphone.hx +++ b/std/flash/media/Microphone.hx @@ -1,28 +1,55 @@ package flash.media; -@:final extern class Microphone extends flash.events.EventDispatcher { - var activityLevel(default,never) : Float; - @:require(flash10) var codec : SoundCodec; - @:require(flash10_1) var enableVAD : Bool; - @:require(flash10) var encodeQuality : Int; - @:require(flash10_2) var enhancedOptions : MicrophoneEnhancedOptions; - @:require(flash10) var framesPerPacket : Int; - var gain : Float; - var index(default,never) : Int; - var muted(default,never) : Bool; - var name(default,never) : String; - @:require(flash10_1) var noiseSuppressionLevel : Int; - var rate : Int; - var silenceLevel(default,never) : Float; - var silenceTimeout(default,never) : Int; - var soundTransform : SoundTransform; - var useEchoSuppression(default,never) : Bool; +extern final class Microphone extends flash.events.EventDispatcher { + @:flash.property var activityLevel(get,never) : Float; + @:flash.property @:require(flash10) var codec(get,set) : SoundCodec; + @:flash.property @:require(flash10_1) var enableVAD(get,set) : Bool; + @:flash.property @:require(flash10) var encodeQuality(get,set) : Int; + @:flash.property @:require(flash10_2) var enhancedOptions(get,set) : MicrophoneEnhancedOptions; + @:flash.property @:require(flash10) var framesPerPacket(get,set) : Int; + @:flash.property var gain(get,set) : Float; + @:flash.property var index(get,never) : Int; + @:flash.property var muted(get,never) : Bool; + @:flash.property var name(get,never) : String; + @:flash.property @:require(flash10_1) var noiseSuppressionLevel(get,set) : Int; + @:flash.property var rate(get,set) : Int; + @:flash.property var silenceLevel(get,never) : Float; + @:flash.property var silenceTimeout(get,never) : Int; + @:flash.property var soundTransform(get,set) : SoundTransform; + @:flash.property var useEchoSuppression(get,never) : Bool; function new() : Void; + private function get_activityLevel() : Float; + private function get_codec() : SoundCodec; + private function get_enableVAD() : Bool; + private function get_encodeQuality() : Int; + private function get_enhancedOptions() : MicrophoneEnhancedOptions; + private function get_framesPerPacket() : Int; + private function get_gain() : Float; + private function get_index() : Int; + private function get_muted() : Bool; + private function get_name() : String; + private function get_noiseSuppressionLevel() : Int; + private function get_rate() : Int; + private function get_silenceLevel() : Float; + private function get_silenceTimeout() : Int; + private function get_soundTransform() : SoundTransform; + private function get_useEchoSuppression() : Bool; function setLoopBack(state : Bool = true) : Void; function setSilenceLevel(silenceLevel : Float, timeout : Int = -1) : Void; function setUseEchoSuppression(useEchoSuppression : Bool) : Void; - @:require(flash10_1) static var isSupported(default,never) : Bool; - static var names(default,never) : Array; + private function set_codec(value : SoundCodec) : SoundCodec; + private function set_enableVAD(value : Bool) : Bool; + private function set_encodeQuality(value : Int) : Int; + private function set_enhancedOptions(value : MicrophoneEnhancedOptions) : MicrophoneEnhancedOptions; + private function set_framesPerPacket(value : Int) : Int; + private function set_gain(value : Float) : Float; + private function set_noiseSuppressionLevel(value : Int) : Int; + private function set_rate(value : Int) : Int; + private function set_soundTransform(value : SoundTransform) : SoundTransform; + @:flash.property @:require(flash10_1) static var isSupported(get,never) : Bool; + @:flash.property static var names(get,never) : Array; @:require(flash10_2) static function getEnhancedMicrophone(index : Int = -1) : Microphone; static function getMicrophone(index : Int = -1) : Microphone; + private static function get_isSupported() : Bool; + private static function get_names() : Array; } diff --git a/std/flash/media/MicrophoneEnhancedMode.hx b/std/flash/media/MicrophoneEnhancedMode.hx index 82a6b90ae51..7d21c3fde4c 100644 --- a/std/flash/media/MicrophoneEnhancedMode.hx +++ b/std/flash/media/MicrophoneEnhancedMode.hx @@ -1,9 +1,9 @@ package flash.media; -@:fakeEnum(String) @:require(flash10_2) extern enum MicrophoneEnhancedMode { - FULL_DUPLEX; - HALF_DUPLEX; - HEADSET; - OFF; - SPEAKER_MUTE; +@:native("flash.media.MicrophoneEnhancedMode") @:require(flash10_2) extern enum abstract MicrophoneEnhancedMode(String) { + var FULL_DUPLEX; + var HALF_DUPLEX; + var HEADSET; + var OFF; + var SPEAKER_MUTE; } diff --git a/std/flash/media/MicrophoneEnhancedOptions.hx b/std/flash/media/MicrophoneEnhancedOptions.hx index 7a5b6ebf8a8..d9bd921fb36 100644 --- a/std/flash/media/MicrophoneEnhancedOptions.hx +++ b/std/flash/media/MicrophoneEnhancedOptions.hx @@ -1,10 +1,20 @@ package flash.media; -@:final @:require(flash10_2) extern class MicrophoneEnhancedOptions { - var autoGain : Bool; - var echoPath : Int; - var isVoiceDetected : Int; - var mode : MicrophoneEnhancedMode; - var nonLinearProcessing : Bool; +@:require(flash10_2) extern final class MicrophoneEnhancedOptions { + @:flash.property var autoGain(get,set) : Bool; + @:flash.property var echoPath(get,set) : Int; + @:flash.property var isVoiceDetected(get,set) : Int; + @:flash.property var mode(get,set) : MicrophoneEnhancedMode; + @:flash.property var nonLinearProcessing(get,set) : Bool; function new() : Void; + private function get_autoGain() : Bool; + private function get_echoPath() : Int; + private function get_isVoiceDetected() : Int; + private function get_mode() : MicrophoneEnhancedMode; + private function get_nonLinearProcessing() : Bool; + private function set_autoGain(value : Bool) : Bool; + private function set_echoPath(value : Int) : Int; + private function set_isVoiceDetected(value : Int) : Int; + private function set_mode(value : MicrophoneEnhancedMode) : MicrophoneEnhancedMode; + private function set_nonLinearProcessing(value : Bool) : Bool; } diff --git a/std/flash/media/Sound.hx b/std/flash/media/Sound.hx index 6fda1e36b38..45b2e195eaf 100644 --- a/std/flash/media/Sound.hx +++ b/std/flash/media/Sound.hx @@ -1,16 +1,23 @@ package flash.media; extern class Sound extends flash.events.EventDispatcher { - var bytesLoaded(default,never) : UInt; - var bytesTotal(default,never) : Int; - var id3(default,never) : ID3Info; - var isBuffering(default,never) : Bool; - @:require(flash10_1) var isURLInaccessible(default,never) : Bool; - var length(default,never) : Float; - var url(default,never) : String; + @:flash.property var bytesLoaded(get,never) : UInt; + @:flash.property var bytesTotal(get,never) : Int; + @:flash.property var id3(get,never) : ID3Info; + @:flash.property var isBuffering(get,never) : Bool; + @:flash.property @:require(flash10_1) var isURLInaccessible(get,never) : Bool; + @:flash.property var length(get,never) : Float; + @:flash.property var url(get,never) : String; function new(?stream : flash.net.URLRequest, ?context : SoundLoaderContext) : Void; function close() : Void; @:require(flash10) function extract(target : flash.utils.ByteArray, length : Float, startPosition : Float = -1) : Float; + private function get_bytesLoaded() : UInt; + private function get_bytesTotal() : Int; + private function get_id3() : ID3Info; + private function get_isBuffering() : Bool; + private function get_isURLInaccessible() : Bool; + private function get_length() : Float; + private function get_url() : String; function load(stream : flash.net.URLRequest, ?context : SoundLoaderContext) : Void; @:require(flash11) function loadCompressedDataFromByteArray(bytes : flash.utils.ByteArray, bytesLength : UInt) : Void; @:require(flash11) function loadPCMFromByteArray(bytes : flash.utils.ByteArray, samples : UInt, ?format : String, stereo : Bool = true, sampleRate : Float = 44100) : Void; diff --git a/std/flash/media/SoundChannel.hx b/std/flash/media/SoundChannel.hx index adee7c79ce6..f4874997ed0 100644 --- a/std/flash/media/SoundChannel.hx +++ b/std/flash/media/SoundChannel.hx @@ -1,10 +1,15 @@ package flash.media; -@:final extern class SoundChannel extends flash.events.EventDispatcher { - var leftPeak(default,never) : Float; - var position(default,never) : Float; - var rightPeak(default,never) : Float; - var soundTransform : SoundTransform; +extern final class SoundChannel extends flash.events.EventDispatcher { + @:flash.property var leftPeak(get,never) : Float; + @:flash.property var position(get,never) : Float; + @:flash.property var rightPeak(get,never) : Float; + @:flash.property var soundTransform(get,set) : SoundTransform; function new() : Void; + private function get_leftPeak() : Float; + private function get_position() : Float; + private function get_rightPeak() : Float; + private function get_soundTransform() : SoundTransform; + private function set_soundTransform(value : SoundTransform) : SoundTransform; function stop() : Void; } diff --git a/std/flash/media/SoundCodec.hx b/std/flash/media/SoundCodec.hx index b2d93cdd0b1..ec09fde00e9 100644 --- a/std/flash/media/SoundCodec.hx +++ b/std/flash/media/SoundCodec.hx @@ -1,8 +1,8 @@ package flash.media; -@:fakeEnum(String) extern enum SoundCodec { - NELLYMOSER; - PCMA; - PCMU; - SPEEX; +@:native("flash.media.SoundCodec") extern enum abstract SoundCodec(String) { + var NELLYMOSER; + var PCMA; + var PCMU; + var SPEEX; } diff --git a/std/flash/media/SoundMixer.hx b/std/flash/media/SoundMixer.hx index 7eb50ff538a..5b31805e2ad 100644 --- a/std/flash/media/SoundMixer.hx +++ b/std/flash/media/SoundMixer.hx @@ -1,11 +1,19 @@ package flash.media; extern class SoundMixer { - static var audioPlaybackMode : String; - static var bufferTime : Int; - static var soundTransform : SoundTransform; - static var useSpeakerphoneForVoice : Bool; + @:flash.property static var audioPlaybackMode(get,set) : String; + @:flash.property static var bufferTime(get,set) : Int; + @:flash.property static var soundTransform(get,set) : SoundTransform; + @:flash.property static var useSpeakerphoneForVoice(get,set) : Bool; static function areSoundsInaccessible() : Bool; static function computeSpectrum(outputArray : flash.utils.ByteArray, FFTMode : Bool = false, stretchFactor : Int = 0) : Void; + private static function get_audioPlaybackMode() : String; + private static function get_bufferTime() : Int; + private static function get_soundTransform() : SoundTransform; + private static function get_useSpeakerphoneForVoice() : Bool; + private static function set_audioPlaybackMode(value : String) : String; + private static function set_bufferTime(value : Int) : Int; + private static function set_soundTransform(value : SoundTransform) : SoundTransform; + private static function set_useSpeakerphoneForVoice(value : Bool) : Bool; static function stopAll() : Void; } diff --git a/std/flash/media/SoundTransform.hx b/std/flash/media/SoundTransform.hx index 91b8eda4316..53ec3deb513 100644 --- a/std/flash/media/SoundTransform.hx +++ b/std/flash/media/SoundTransform.hx @@ -1,11 +1,23 @@ package flash.media; -@:final extern class SoundTransform { - var leftToLeft : Float; - var leftToRight : Float; - var pan : Float; - var rightToLeft : Float; - var rightToRight : Float; - var volume : Float; +extern final class SoundTransform { + @:flash.property var leftToLeft(get,set) : Float; + @:flash.property var leftToRight(get,set) : Float; + @:flash.property var pan(get,set) : Float; + @:flash.property var rightToLeft(get,set) : Float; + @:flash.property var rightToRight(get,set) : Float; + @:flash.property var volume(get,set) : Float; function new(vol : Float = 1, panning : Float = 0) : Void; + private function get_leftToLeft() : Float; + private function get_leftToRight() : Float; + private function get_pan() : Float; + private function get_rightToLeft() : Float; + private function get_rightToRight() : Float; + private function get_volume() : Float; + private function set_leftToLeft(value : Float) : Float; + private function set_leftToRight(value : Float) : Float; + private function set_pan(value : Float) : Float; + private function set_rightToLeft(value : Float) : Float; + private function set_rightToRight(value : Float) : Float; + private function set_volume(value : Float) : Float; } diff --git a/std/flash/media/StageVideo.hx b/std/flash/media/StageVideo.hx index 39a716e566c..70e3b0a59ca 100644 --- a/std/flash/media/StageVideo.hx +++ b/std/flash/media/StageVideo.hx @@ -1,15 +1,26 @@ package flash.media; @:require(flash10_2) extern class StageVideo extends flash.events.EventDispatcher { - var colorSpaces(default,never) : flash.Vector; - var depth : Int; - var pan : flash.geom.Point; - var videoHeight(default,never) : Int; - var videoWidth(default,never) : Int; - var viewPort : flash.geom.Rectangle; - var zoom : flash.geom.Point; + @:flash.property var colorSpaces(get,never) : flash.Vector; + @:flash.property var depth(get,set) : Int; + @:flash.property var pan(get,set) : flash.geom.Point; + @:flash.property var videoHeight(get,never) : Int; + @:flash.property var videoWidth(get,never) : Int; + @:flash.property var viewPort(get,set) : flash.geom.Rectangle; + @:flash.property var zoom(get,set) : flash.geom.Point; function new() : Void; @:require(flash11_7) function attachAVStream(avStream : AVStream) : Void; @:require(flash11_4) function attachCamera(theCamera : Camera) : Void; function attachNetStream(netStream : flash.net.NetStream) : Void; + private function get_colorSpaces() : flash.Vector; + private function get_depth() : Int; + private function get_pan() : flash.geom.Point; + private function get_videoHeight() : Int; + private function get_videoWidth() : Int; + private function get_viewPort() : flash.geom.Rectangle; + private function get_zoom() : flash.geom.Point; + private function set_depth(value : Int) : Int; + private function set_pan(value : flash.geom.Point) : flash.geom.Point; + private function set_viewPort(value : flash.geom.Rectangle) : flash.geom.Rectangle; + private function set_zoom(value : flash.geom.Point) : flash.geom.Point; } diff --git a/std/flash/media/StageVideoAvailability.hx b/std/flash/media/StageVideoAvailability.hx index 88583b489c2..cdc367686db 100644 --- a/std/flash/media/StageVideoAvailability.hx +++ b/std/flash/media/StageVideoAvailability.hx @@ -2,6 +2,6 @@ package flash.media; extern class StageVideoAvailability { function new() : Void; - static var AVAILABLE(default,never) : String; - static var UNAVAILABLE(default,never) : String; + static final AVAILABLE : String; + static final UNAVAILABLE : String; } diff --git a/std/flash/media/StageVideoAvailabilityReason.hx b/std/flash/media/StageVideoAvailabilityReason.hx index a09dfac3999..82ff954c2f5 100644 --- a/std/flash/media/StageVideoAvailabilityReason.hx +++ b/std/flash/media/StageVideoAvailabilityReason.hx @@ -2,9 +2,9 @@ package flash.media; extern class StageVideoAvailabilityReason { function new() : Void; - static var DRIVER_TOO_OLD(default,never) : String; - static var NO_ERROR(default,never) : String; - static var UNAVAILABLE(default,never) : String; - static var USER_DISABLED(default,never) : String; - static var WMODE_INCOMPATIBLE(default,never) : String; + static final DRIVER_TOO_OLD : String; + static final NO_ERROR : String; + static final UNAVAILABLE : String; + static final USER_DISABLED : String; + static final WMODE_INCOMPATIBLE : String; } diff --git a/std/flash/media/Video.hx b/std/flash/media/Video.hx index f8ac7596ba7..d39918a4de2 100644 --- a/std/flash/media/Video.hx +++ b/std/flash/media/Video.hx @@ -1,12 +1,18 @@ package flash.media; extern class Video extends flash.display.DisplayObject { - var deblocking : Int; - var smoothing : Bool; - var videoHeight(default,never) : Int; - var videoWidth(default,never) : Int; + @:flash.property var deblocking(get,set) : Int; + @:flash.property var smoothing(get,set) : Bool; + @:flash.property var videoHeight(get,never) : Int; + @:flash.property var videoWidth(get,never) : Int; function new(width : Int = 320, height : Int = 240) : Void; function attachCamera(camera : Camera) : Void; function attachNetStream(netStream : flash.net.NetStream) : Void; function clear() : Void; + private function get_deblocking() : Int; + private function get_smoothing() : Bool; + private function get_videoHeight() : Int; + private function get_videoWidth() : Int; + private function set_deblocking(value : Int) : Int; + private function set_smoothing(value : Bool) : Bool; } diff --git a/std/flash/media/VideoCodec.hx b/std/flash/media/VideoCodec.hx index e18325f63d8..42afa7c1fab 100644 --- a/std/flash/media/VideoCodec.hx +++ b/std/flash/media/VideoCodec.hx @@ -2,7 +2,7 @@ package flash.media; extern class VideoCodec { function new() : Void; - static var H264AVC(default,never) : String; - static var SORENSON(default,never) : String; - static var VP6(default,never) : String; + static final H264AVC : String; + static final SORENSON : String; + static final VP6 : String; } diff --git a/std/flash/media/VideoStatus.hx b/std/flash/media/VideoStatus.hx index 0304da72d1b..92e357c7eaa 100644 --- a/std/flash/media/VideoStatus.hx +++ b/std/flash/media/VideoStatus.hx @@ -2,7 +2,7 @@ package flash.media; extern class VideoStatus { function new() : Void; - static var ACCELERATED(default,never) : String; - static var SOFTWARE(default,never) : String; - static var UNAVAILABLE(default,never) : String; + static final ACCELERATED : String; + static final SOFTWARE : String; + static final UNAVAILABLE : String; } diff --git a/std/flash/media/VideoStreamSettings.hx b/std/flash/media/VideoStreamSettings.hx index 305d8cc7ec2..fb1a93166ea 100644 --- a/std/flash/media/VideoStreamSettings.hx +++ b/std/flash/media/VideoStreamSettings.hx @@ -1,14 +1,21 @@ package flash.media; extern class VideoStreamSettings { - var bandwidth(default,never) : Int; - var codec(default,never) : String; - var fps(default,never) : Float; - var height(default,never) : Int; - var keyFrameInterval(default,never) : Int; - var quality(default,never) : Int; - var width(default,never) : Int; + @:flash.property var bandwidth(get,never) : Int; + @:flash.property var codec(get,never) : String; + @:flash.property var fps(get,never) : Float; + @:flash.property var height(get,never) : Int; + @:flash.property var keyFrameInterval(get,never) : Int; + @:flash.property var quality(get,never) : Int; + @:flash.property var width(get,never) : Int; function new() : Void; + private function get_bandwidth() : Int; + private function get_codec() : String; + private function get_fps() : Float; + private function get_height() : Int; + private function get_keyFrameInterval() : Int; + private function get_quality() : Int; + private function get_width() : Int; function setKeyFrameInterval(keyFrameInterval : Int) : Void; function setMode(width : Int, height : Int, fps : Float) : Void; function setQuality(bandwidth : Int, quality : Int) : Void; diff --git a/std/flash/net/FileFilter.hx b/std/flash/net/FileFilter.hx index 176144bd823..c56204c5466 100644 --- a/std/flash/net/FileFilter.hx +++ b/std/flash/net/FileFilter.hx @@ -1,8 +1,14 @@ package flash.net; -@:final extern class FileFilter { - var description : String; - var extension : String; - var macType : String; +extern final class FileFilter { + @:flash.property var description(get,set) : String; + @:flash.property var extension(get,set) : String; + @:flash.property var macType(get,set) : String; function new(description : String, extension : String, ?macType : String) : Void; + private function get_description() : String; + private function get_extension() : String; + private function get_macType() : String; + private function set_description(value : String) : String; + private function set_extension(value : String) : String; + private function set_macType(value : String) : String; } diff --git a/std/flash/net/FileReference.hx b/std/flash/net/FileReference.hx index d86d601fc90..1ff113f00b5 100644 --- a/std/flash/net/FileReference.hx +++ b/std/flash/net/FileReference.hx @@ -1,17 +1,24 @@ package flash.net; extern class FileReference extends flash.events.EventDispatcher { - var creationDate(default,never) : Date; - var creator(default,never) : String; - @:require(flash10) var data(default,never) : flash.utils.ByteArray; - var modificationDate(default,never) : Date; - var name(default,never) : String; - var size(default,never) : Float; - var type(default,never) : String; + @:flash.property var creationDate(get,never) : Date; + @:flash.property var creator(get,never) : String; + @:flash.property @:require(flash10) var data(get,never) : flash.utils.ByteArray; + @:flash.property var modificationDate(get,never) : Date; + @:flash.property var name(get,never) : String; + @:flash.property var size(get,never) : Float; + @:flash.property var type(get,never) : String; function new() : Void; function browse(?typeFilter : Array) : Bool; function cancel() : Void; function download(request : URLRequest, ?defaultFileName : String) : Void; + private function get_creationDate() : Date; + private function get_creator() : String; + private function get_data() : flash.utils.ByteArray; + private function get_modificationDate() : Date; + private function get_name() : String; + private function get_size() : Float; + private function get_type() : String; @:require(flash10) function load() : Void; @:require(flash10) function save(data : Dynamic, ?defaultFileName : String) : Void; function upload(request : URLRequest, ?uploadDataFieldName : String, testUpload : Bool = false) : Void; diff --git a/std/flash/net/FileReferenceList.hx b/std/flash/net/FileReferenceList.hx index decb89ddafd..65a2a3fa553 100644 --- a/std/flash/net/FileReferenceList.hx +++ b/std/flash/net/FileReferenceList.hx @@ -1,7 +1,8 @@ package flash.net; extern class FileReferenceList extends flash.events.EventDispatcher { - var fileList(default,never) : Array; + @:flash.property var fileList(get,never) : Array; function new() : Void; function browse(?typeFilter : Array) : Bool; + private function get_fileList() : Array; } diff --git a/std/flash/net/GroupSpecifier.hx b/std/flash/net/GroupSpecifier.hx index c04e28a635d..bf76d5c8d67 100644 --- a/std/flash/net/GroupSpecifier.hx +++ b/std/flash/net/GroupSpecifier.hx @@ -1,27 +1,44 @@ package flash.net; @:require(flash10_1) extern class GroupSpecifier { - var ipMulticastMemberUpdatesEnabled : Bool; - var minGroupspecVersion : Int; - var multicastEnabled : Bool; - var objectReplicationEnabled : Bool; - var peerToPeerDisabled : Bool; - var postingEnabled : Bool; - var routingEnabled : Bool; - var serverChannelEnabled : Bool; + @:flash.property var ipMulticastMemberUpdatesEnabled(get,set) : Bool; + @:flash.property var minGroupspecVersion(get,set) : Int; + @:flash.property var multicastEnabled(get,set) : Bool; + @:flash.property var objectReplicationEnabled(get,set) : Bool; + @:flash.property var peerToPeerDisabled(get,set) : Bool; + @:flash.property var postingEnabled(get,set) : Bool; + @:flash.property var routingEnabled(get,set) : Bool; + @:flash.property var serverChannelEnabled(get,set) : Bool; function new(name : String) : Void; function addBootstrapPeer(peerID : String) : Void; function addIPMulticastAddress(address : String, ?port : Dynamic, ?source : String) : Void; function authorizations() : String; + private function get_ipMulticastMemberUpdatesEnabled() : Bool; + private function get_minGroupspecVersion() : Int; + private function get_multicastEnabled() : Bool; + private function get_objectReplicationEnabled() : Bool; + private function get_peerToPeerDisabled() : Bool; + private function get_postingEnabled() : Bool; + private function get_routingEnabled() : Bool; + private function get_serverChannelEnabled() : Bool; function groupspecWithAuthorizations() : String; function groupspecWithoutAuthorizations() : String; function makeUnique() : Void; function setPostingPassword(?password : String, ?salt : String) : Void; function setPublishPassword(?password : String, ?salt : String) : Void; + private function set_ipMulticastMemberUpdatesEnabled(value : Bool) : Bool; + private function set_minGroupspecVersion(value : Int) : Int; + private function set_multicastEnabled(value : Bool) : Bool; + private function set_objectReplicationEnabled(value : Bool) : Bool; + private function set_peerToPeerDisabled(value : Bool) : Bool; + private function set_postingEnabled(value : Bool) : Bool; + private function set_routingEnabled(value : Bool) : Bool; + private function set_serverChannelEnabled(value : Bool) : Bool; function toString() : String; - static var maxSupportedGroupspecVersion(default,never) : Int; + @:flash.property static var maxSupportedGroupspecVersion(get,never) : Int; static function encodeBootstrapPeerIDSpec(peerID : String) : String; static function encodeIPMulticastAddressSpec(address : String, ?port : Dynamic, ?source : String) : String; static function encodePostingAuthorization(password : String) : String; static function encodePublishAuthorization(password : String) : String; + private static function get_maxSupportedGroupspecVersion() : Int; } diff --git a/std/flash/net/LocalConnection.hx b/std/flash/net/LocalConnection.hx index 5ba14b21a28..c3aad344cf8 100644 --- a/std/flash/net/LocalConnection.hx +++ b/std/flash/net/LocalConnection.hx @@ -1,14 +1,20 @@ package flash.net; extern class LocalConnection extends flash.events.EventDispatcher { - var client : Dynamic; - var domain(default,never) : String; - @:require(flash10_1) var isPerUser : Bool; + @:flash.property var client(get,set) : Dynamic; + @:flash.property var domain(get,never) : String; + @:flash.property @:require(flash10_1) var isPerUser(get,set) : Bool; function new() : Void; - function allowDomain(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; - function allowInsecureDomain(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; + function allowDomain(restArgs : haxe.extern.Rest) : Void; + function allowInsecureDomain(restArgs : haxe.extern.Rest) : Void; function close() : Void; function connect(connectionName : String) : Void; - function send(connectionName : String, methodName : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; - @:require(flash10_1) static var isSupported(default,never) : Bool; + private function get_client() : Dynamic; + private function get_domain() : String; + private function get_isPerUser() : Bool; + function send(connectionName : String, methodName : String, restArgs : haxe.extern.Rest) : Void; + private function set_client(value : Dynamic) : Dynamic; + private function set_isPerUser(value : Bool) : Bool; + @:flash.property @:require(flash10_1) static var isSupported(get,never) : Bool; + private static function get_isSupported() : Bool; } diff --git a/std/flash/net/NetConnection.hx b/std/flash/net/NetConnection.hx index a2acc221b7b..e5b223004c8 100644 --- a/std/flash/net/NetConnection.hx +++ b/std/flash/net/NetConnection.hx @@ -1,24 +1,44 @@ package flash.net; extern class NetConnection extends flash.events.EventDispatcher { - var client : Dynamic; - var connected(default,never) : Bool; - var connectedProxyType(default,never) : String; - @:require(flash10) var farID(default,never) : String; - @:require(flash10) var farNonce(default,never) : String; - @:require(flash10) var maxPeerConnections : UInt; - @:require(flash10) var nearID(default,never) : String; - @:require(flash10) var nearNonce(default,never) : String; - var objectEncoding : UInt; - @:require(flash10) var protocol(default,never) : String; - var proxyType : String; - @:require(flash10) var unconnectedPeerStreams(default,never) : Array; - var uri(default,never) : String; - var usingTLS(default,never) : Bool; + @:flash.property var client(get,set) : Dynamic; + @:flash.property var connected(get,never) : Bool; + @:flash.property var connectedProxyType(get,never) : String; + @:flash.property @:require(flash10) var farID(get,never) : String; + @:flash.property @:require(flash10) var farNonce(get,never) : String; + @:flash.property @:require(flash10) var maxPeerConnections(get,set) : UInt; + @:flash.property @:require(flash10) var nearID(get,never) : String; + @:flash.property @:require(flash10) var nearNonce(get,never) : String; + @:flash.property var objectEncoding(get,set) : UInt; + @:flash.property @:require(flash10) var protocol(get,never) : String; + @:flash.property var proxyType(get,set) : String; + @:flash.property @:require(flash10) var unconnectedPeerStreams(get,never) : Array; + @:flash.property var uri(get,never) : String; + @:flash.property var usingTLS(get,never) : Bool; function new() : Void; function addHeader(operation : String, mustUnderstand : Bool = false, ?param : flash.utils.Object) : Void; - function call(command : String, responder : Responder, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; + function call(command : String, responder : Responder, restArgs : haxe.extern.Rest) : Void; function close() : Void; - function connect(command : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; - static var defaultObjectEncoding : UInt; + function connect(command : String, restArgs : haxe.extern.Rest) : Void; + private function get_client() : Dynamic; + private function get_connected() : Bool; + private function get_connectedProxyType() : String; + private function get_farID() : String; + private function get_farNonce() : String; + private function get_maxPeerConnections() : UInt; + private function get_nearID() : String; + private function get_nearNonce() : String; + private function get_objectEncoding() : UInt; + private function get_protocol() : String; + private function get_proxyType() : String; + private function get_unconnectedPeerStreams() : Array; + private function get_uri() : String; + private function get_usingTLS() : Bool; + private function set_client(value : Dynamic) : Dynamic; + private function set_maxPeerConnections(value : UInt) : UInt; + private function set_objectEncoding(value : UInt) : UInt; + private function set_proxyType(value : String) : String; + @:flash.property static var defaultObjectEncoding(get,set) : UInt; + private static function get_defaultObjectEncoding() : UInt; + private static function set_defaultObjectEncoding(value : UInt) : UInt; } diff --git a/std/flash/net/NetGroup.hx b/std/flash/net/NetGroup.hx index 542541aed5d..3e1f90f8b84 100644 --- a/std/flash/net/NetGroup.hx +++ b/std/flash/net/NetGroup.hx @@ -1,13 +1,13 @@ package flash.net; @:require(flash10_1) extern class NetGroup extends flash.events.EventDispatcher { - var estimatedMemberCount(default,never) : Float; - var info(default,never) : NetGroupInfo; - var localCoverageFrom(default,never) : String; - var localCoverageTo(default,never) : String; - var neighborCount(default,never) : Float; - var receiveMode : String; - var replicationStrategy : String; + @:flash.property var estimatedMemberCount(get,never) : Float; + @:flash.property var info(get,never) : NetGroupInfo; + @:flash.property var localCoverageFrom(get,never) : String; + @:flash.property var localCoverageTo(get,never) : String; + @:flash.property var neighborCount(get,never) : Float; + @:flash.property var receiveMode(get,set) : String; + @:flash.property var replicationStrategy(get,set) : String; function new(connection : NetConnection, groupspec : String) : Void; function addHaveObjects(startIndex : Float, endIndex : Float) : Void; function addMemberHint(peerID : String) : Bool; @@ -16,11 +16,20 @@ package flash.net; function close() : Void; function convertPeerIDToGroupAddress(peerID : String) : String; function denyRequestedObject(requestID : Int) : Void; + private function get_estimatedMemberCount() : Float; + private function get_info() : NetGroupInfo; + private function get_localCoverageFrom() : String; + private function get_localCoverageTo() : String; + private function get_neighborCount() : Float; + private function get_receiveMode() : String; + private function get_replicationStrategy() : String; function post(message : flash.utils.Object) : String; function removeHaveObjects(startIndex : Float, endIndex : Float) : Void; function removeWantObjects(startIndex : Float, endIndex : Float) : Void; function sendToAllNeighbors(message : flash.utils.Object) : String; function sendToNearest(message : flash.utils.Object, groupAddress : String) : String; function sendToNeighbor(message : flash.utils.Object, sendMode : String) : String; + private function set_receiveMode(value : String) : String; + private function set_replicationStrategy(value : String) : String; function writeRequestedObject(requestID : Int, object : flash.utils.Object) : Void; } diff --git a/std/flash/net/NetGroupInfo.hx b/std/flash/net/NetGroupInfo.hx index 3f5696463b0..e1746feb44e 100644 --- a/std/flash/net/NetGroupInfo.hx +++ b/std/flash/net/NetGroupInfo.hx @@ -1,14 +1,22 @@ package flash.net; -@:final @:require(flash10_1) extern class NetGroupInfo { - var objectReplicationReceiveBytesPerSecond(default,never) : Float; - var objectReplicationSendBytesPerSecond(default,never) : Float; - var postingReceiveControlBytesPerSecond(default,never) : Float; - var postingReceiveDataBytesPerSecond(default,never) : Float; - var postingSendControlBytesPerSecond(default,never) : Float; - var postingSendDataBytesPerSecond(default,never) : Float; - var routingReceiveBytesPerSecond(default,never) : Float; - var routingSendBytesPerSecond(default,never) : Float; +@:require(flash10_1) extern final class NetGroupInfo { + @:flash.property var objectReplicationReceiveBytesPerSecond(get,never) : Float; + @:flash.property var objectReplicationSendBytesPerSecond(get,never) : Float; + @:flash.property var postingReceiveControlBytesPerSecond(get,never) : Float; + @:flash.property var postingReceiveDataBytesPerSecond(get,never) : Float; + @:flash.property var postingSendControlBytesPerSecond(get,never) : Float; + @:flash.property var postingSendDataBytesPerSecond(get,never) : Float; + @:flash.property var routingReceiveBytesPerSecond(get,never) : Float; + @:flash.property var routingSendBytesPerSecond(get,never) : Float; function new(postingSendDataBytesPerSecond : Float, postingSendControlBytesPerSecond : Float, postingReceiveDataBytesPerSecond : Float, postingReceiveControlBytesPerSecond : Float, routingSendBytesPerSecond : Float, routingReceiveBytesPerSecond : Float, objectReplicationSendBytesPerSecond : Float, objectReplicationReceiveBytesPerSecond : Float) : Void; + private function get_objectReplicationReceiveBytesPerSecond() : Float; + private function get_objectReplicationSendBytesPerSecond() : Float; + private function get_postingReceiveControlBytesPerSecond() : Float; + private function get_postingReceiveDataBytesPerSecond() : Float; + private function get_postingSendControlBytesPerSecond() : Float; + private function get_postingSendDataBytesPerSecond() : Float; + private function get_routingReceiveBytesPerSecond() : Float; + private function get_routingSendBytesPerSecond() : Float; function toString() : String; } diff --git a/std/flash/net/NetGroupReceiveMode.hx b/std/flash/net/NetGroupReceiveMode.hx index 00bdd9e79f9..48d50c99e3a 100644 --- a/std/flash/net/NetGroupReceiveMode.hx +++ b/std/flash/net/NetGroupReceiveMode.hx @@ -2,6 +2,6 @@ package flash.net; extern class NetGroupReceiveMode { function new() : Void; - static var EXACT(default,never) : String; - static var NEAREST(default,never) : String; + static final EXACT : String; + static final NEAREST : String; } diff --git a/std/flash/net/NetGroupReplicationStrategy.hx b/std/flash/net/NetGroupReplicationStrategy.hx index 5c7e2bd7e32..a6521be7c06 100644 --- a/std/flash/net/NetGroupReplicationStrategy.hx +++ b/std/flash/net/NetGroupReplicationStrategy.hx @@ -2,6 +2,6 @@ package flash.net; extern class NetGroupReplicationStrategy { function new() : Void; - static var LOWEST_FIRST(default,never) : String; - static var RAREST_FIRST(default,never) : String; + static final LOWEST_FIRST : String; + static final RAREST_FIRST : String; } diff --git a/std/flash/net/NetGroupSendMode.hx b/std/flash/net/NetGroupSendMode.hx index 79de5b709d4..fdd61293b87 100644 --- a/std/flash/net/NetGroupSendMode.hx +++ b/std/flash/net/NetGroupSendMode.hx @@ -2,6 +2,6 @@ package flash.net; extern class NetGroupSendMode { function new() : Void; - static var NEXT_DECREASING(default,never) : String; - static var NEXT_INCREASING(default,never) : String; + static final NEXT_DECREASING : String; + static final NEXT_INCREASING : String; } diff --git a/std/flash/net/NetGroupSendResult.hx b/std/flash/net/NetGroupSendResult.hx index aa0122dba68..901d62e1805 100644 --- a/std/flash/net/NetGroupSendResult.hx +++ b/std/flash/net/NetGroupSendResult.hx @@ -2,7 +2,7 @@ package flash.net; extern class NetGroupSendResult { function new() : Void; - static var ERROR(default,never) : String; - static var NO_ROUTE(default,never) : String; - static var SENT(default,never) : String; + static final ERROR : String; + static final NO_ROUTE : String; + static final SENT : String; } diff --git a/std/flash/net/NetStream.hx b/std/flash/net/NetStream.hx index 8451653d2c7..792976fcaca 100644 --- a/std/flash/net/NetStream.hx +++ b/std/flash/net/NetStream.hx @@ -1,45 +1,45 @@ package flash.net; extern class NetStream extends flash.events.EventDispatcher { - var audioCodec(default,never) : UInt; - @:require(flash10_1) var audioReliable : Bool; - @:require(flash10_1) var audioSampleAccess : Bool; - @:require(flash10_1) var backBufferLength(default,never) : Float; - @:require(flash10_1) var backBufferTime : Float; - var bufferLength(default,never) : Float; - var bufferTime : Float; - @:require(flash10_1) var bufferTimeMax : Float; - var bytesLoaded(default,never) : UInt; - var bytesTotal(default,never) : UInt; - var checkPolicyFile : Bool; - var client : Dynamic; - var currentFPS(default,never) : Float; - @:require(flash10_1) var dataReliable : Bool; - var decodedFrames(default,never) : UInt; - @:require(flash10) var farID(default,never) : String; - @:require(flash10) var farNonce(default,never) : String; - @:require(flash10_1) var inBufferSeek : Bool; - @:require(flash10) var info(default,never) : NetStreamInfo; - var liveDelay(default,never) : Float; - @:require(flash10) var maxPauseBufferTime : Float; - @:require(flash10_1) var multicastAvailabilitySendToAll : Bool; - @:require(flash10_1) var multicastAvailabilityUpdatePeriod : Float; - @:require(flash10_1) var multicastFetchPeriod : Float; - @:require(flash10_1) var multicastInfo(default,never) : NetStreamMulticastInfo; - @:require(flash10_1) var multicastPushNeighborLimit : Float; - @:require(flash10_1) var multicastRelayMarginDuration : Float; - @:require(flash10_1) var multicastWindowDuration : Float; - @:require(flash10) var nearNonce(default,never) : String; - var objectEncoding(default,never) : UInt; - @:require(flash10) var peerStreams(default,never) : Array; - var soundTransform : flash.media.SoundTransform; - var time(default,never) : Float; - @:require(flash11) var useHardwareDecoder : Bool; - @:require(flash11_3) var useJitterBuffer : Bool; - var videoCodec(default,never) : UInt; - @:require(flash10_1) var videoReliable : Bool; - @:require(flash10_1) var videoSampleAccess : Bool; - @:require(flash11) var videoStreamSettings : flash.media.VideoStreamSettings; + @:flash.property var audioCodec(get,never) : UInt; + @:flash.property @:require(flash10_1) var audioReliable(get,set) : Bool; + @:flash.property @:require(flash10_1) var audioSampleAccess(get,set) : Bool; + @:flash.property @:require(flash10_1) var backBufferLength(get,never) : Float; + @:flash.property @:require(flash10_1) var backBufferTime(get,set) : Float; + @:flash.property var bufferLength(get,never) : Float; + @:flash.property var bufferTime(get,set) : Float; + @:flash.property @:require(flash10_1) var bufferTimeMax(get,set) : Float; + @:flash.property var bytesLoaded(get,never) : UInt; + @:flash.property var bytesTotal(get,never) : UInt; + @:flash.property var checkPolicyFile(get,set) : Bool; + @:flash.property var client(get,set) : Dynamic; + @:flash.property var currentFPS(get,never) : Float; + @:flash.property @:require(flash10_1) var dataReliable(get,set) : Bool; + @:flash.property var decodedFrames(get,never) : UInt; + @:flash.property @:require(flash10) var farID(get,never) : String; + @:flash.property @:require(flash10) var farNonce(get,never) : String; + @:flash.property @:require(flash10_1) var inBufferSeek(get,set) : Bool; + @:flash.property @:require(flash10) var info(get,never) : NetStreamInfo; + @:flash.property var liveDelay(get,never) : Float; + @:flash.property @:require(flash10) var maxPauseBufferTime(get,set) : Float; + @:flash.property @:require(flash10_1) var multicastAvailabilitySendToAll(get,set) : Bool; + @:flash.property @:require(flash10_1) var multicastAvailabilityUpdatePeriod(get,set) : Float; + @:flash.property @:require(flash10_1) var multicastFetchPeriod(get,set) : Float; + @:flash.property @:require(flash10_1) var multicastInfo(get,never) : NetStreamMulticastInfo; + @:flash.property @:require(flash10_1) var multicastPushNeighborLimit(get,set) : Float; + @:flash.property @:require(flash10_1) var multicastRelayMarginDuration(get,set) : Float; + @:flash.property @:require(flash10_1) var multicastWindowDuration(get,set) : Float; + @:flash.property @:require(flash10) var nearNonce(get,never) : String; + @:flash.property var objectEncoding(get,never) : UInt; + @:flash.property @:require(flash10) var peerStreams(get,never) : Array; + @:flash.property var soundTransform(get,set) : flash.media.SoundTransform; + @:flash.property var time(get,never) : Float; + @:flash.property @:require(flash11) var useHardwareDecoder(get,set) : Bool; + @:flash.property @:require(flash11_3) var useJitterBuffer(get,set) : Bool; + @:flash.property var videoCodec(get,never) : UInt; + @:flash.property @:require(flash10_1) var videoReliable(get,set) : Bool; + @:flash.property @:require(flash10_1) var videoSampleAccess(get,set) : Bool; + @:flash.property @:require(flash11) var videoStreamSettings(get,set) : flash.media.VideoStreamSettings; function new(connection : NetConnection, ?peerID : String) : Void; @:require(flash10_1) function appendBytes(bytes : flash.utils.ByteArray) : Void; @:require(flash10_1) function appendBytesAction(netStreamAppendBytesAction : String) : Void; @@ -48,9 +48,48 @@ extern class NetStream extends flash.events.EventDispatcher { function attachCamera(theCamera : flash.media.Camera, snapshotMilliseconds : Int = -1) : Void; function close() : Void; @:require(flash11_2) function dispose() : Void; + private function get_audioCodec() : UInt; + private function get_audioReliable() : Bool; + private function get_audioSampleAccess() : Bool; + private function get_backBufferLength() : Float; + private function get_backBufferTime() : Float; + private function get_bufferLength() : Float; + private function get_bufferTime() : Float; + private function get_bufferTimeMax() : Float; + private function get_bytesLoaded() : UInt; + private function get_bytesTotal() : UInt; + private function get_checkPolicyFile() : Bool; + private function get_client() : Dynamic; + private function get_currentFPS() : Float; + private function get_dataReliable() : Bool; + private function get_decodedFrames() : UInt; + private function get_farID() : String; + private function get_farNonce() : String; + private function get_inBufferSeek() : Bool; + private function get_info() : NetStreamInfo; + private function get_liveDelay() : Float; + private function get_maxPauseBufferTime() : Float; + private function get_multicastAvailabilitySendToAll() : Bool; + private function get_multicastAvailabilityUpdatePeriod() : Float; + private function get_multicastFetchPeriod() : Float; + private function get_multicastInfo() : NetStreamMulticastInfo; + private function get_multicastPushNeighborLimit() : Float; + private function get_multicastRelayMarginDuration() : Float; + private function get_multicastWindowDuration() : Float; + private function get_nearNonce() : String; + private function get_objectEncoding() : UInt; + private function get_peerStreams() : Array; + private function get_soundTransform() : flash.media.SoundTransform; + private function get_time() : Float; + private function get_useHardwareDecoder() : Bool; + private function get_useJitterBuffer() : Bool; + private function get_videoCodec() : UInt; + private function get_videoReliable() : Bool; + private function get_videoSampleAccess() : Bool; + private function get_videoStreamSettings() : flash.media.VideoStreamSettings; @:require(flash10) function onPeerConnect(subscriber : NetStream) : Bool; function pause() : Void; - function play(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; + function play(restArgs : haxe.extern.Rest) : Void; @:require(flash10) function play2(param : NetStreamPlayOptions) : Void; function publish(?name : String, ?type : String) : Void; function receiveAudio(flag : Bool) : Void; @@ -58,10 +97,32 @@ extern class NetStream extends flash.events.EventDispatcher { function receiveVideoFPS(FPS : Float) : Void; function resume() : Void; function seek(offset : Float) : Void; - function send(handlerName : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; + function send(handlerName : String, restArgs : haxe.extern.Rest) : Void; + private function set_audioReliable(value : Bool) : Bool; + private function set_audioSampleAccess(value : Bool) : Bool; + private function set_backBufferTime(value : Float) : Float; + private function set_bufferTime(value : Float) : Float; + private function set_bufferTimeMax(value : Float) : Float; + private function set_checkPolicyFile(value : Bool) : Bool; + private function set_client(value : Dynamic) : Dynamic; + private function set_dataReliable(value : Bool) : Bool; + private function set_inBufferSeek(value : Bool) : Bool; + private function set_maxPauseBufferTime(value : Float) : Float; + private function set_multicastAvailabilitySendToAll(value : Bool) : Bool; + private function set_multicastAvailabilityUpdatePeriod(value : Float) : Float; + private function set_multicastFetchPeriod(value : Float) : Float; + private function set_multicastPushNeighborLimit(value : Float) : Float; + private function set_multicastRelayMarginDuration(value : Float) : Float; + private function set_multicastWindowDuration(value : Float) : Float; + private function set_soundTransform(value : flash.media.SoundTransform) : flash.media.SoundTransform; + private function set_useHardwareDecoder(value : Bool) : Bool; + private function set_useJitterBuffer(value : Bool) : Bool; + private function set_videoReliable(value : Bool) : Bool; + private function set_videoSampleAccess(value : Bool) : Bool; + private function set_videoStreamSettings(value : flash.media.VideoStreamSettings) : flash.media.VideoStreamSettings; @:require(flash10_1) function step(frames : Int) : Void; function togglePause() : Void; - @:require(flash10) static var CONNECT_TO_FMS(default,never) : String; - @:require(flash10) static var DIRECT_CONNECTIONS(default,never) : String; + @:require(flash10) static final CONNECT_TO_FMS : String; + @:require(flash10) static final DIRECT_CONNECTIONS : String; static function resetDRMVouchers() : Void; } diff --git a/std/flash/net/NetStreamAppendBytesAction.hx b/std/flash/net/NetStreamAppendBytesAction.hx index b7c7f8c9cd6..a03f27f3fca 100644 --- a/std/flash/net/NetStreamAppendBytesAction.hx +++ b/std/flash/net/NetStreamAppendBytesAction.hx @@ -2,7 +2,7 @@ package flash.net; extern class NetStreamAppendBytesAction { function new() : Void; - static var END_SEQUENCE(default,never) : String; - static var RESET_BEGIN(default,never) : String; - static var RESET_SEEK(default,never) : String; + static final END_SEQUENCE : String; + static final RESET_BEGIN : String; + static final RESET_SEEK : String; } diff --git a/std/flash/net/NetStreamInfo.hx b/std/flash/net/NetStreamInfo.hx index b65ea7767b8..7c461e07050 100644 --- a/std/flash/net/NetStreamInfo.hx +++ b/std/flash/net/NetStreamInfo.hx @@ -1,31 +1,56 @@ package flash.net; -@:final extern class NetStreamInfo { - var SRTT(default,never) : Float; - var audioBufferByteLength(default,never) : Float; - var audioBufferLength(default,never) : Float; - var audioByteCount(default,never) : Float; - var audioBytesPerSecond(default,never) : Float; - var audioLossRate(default,never) : Float; - var byteCount(default,never) : Float; - var currentBytesPerSecond(default,never) : Float; - var dataBufferByteLength(default,never) : Float; - var dataBufferLength(default,never) : Float; - var dataByteCount(default,never) : Float; - var dataBytesPerSecond(default,never) : Float; - var droppedFrames(default,never) : Float; - var isLive(default,never) : Bool; - var maxBytesPerSecond(default,never) : Float; - var metaData(default,never) : Dynamic; - var playbackBytesPerSecond(default,never) : Float; - var resourceName(default,never) : String; - var uri(default,never) : String; - var videoBufferByteLength(default,never) : Float; - var videoBufferLength(default,never) : Float; - var videoByteCount(default,never) : Float; - var videoBytesPerSecond(default,never) : Float; - @:require(flash10_1) var videoLossRate(default,never) : Float; - var xmpData(default,never) : Dynamic; +extern final class NetStreamInfo { + @:flash.property var SRTT(get,never) : Float; + @:flash.property var audioBufferByteLength(get,never) : Float; + @:flash.property var audioBufferLength(get,never) : Float; + @:flash.property var audioByteCount(get,never) : Float; + @:flash.property var audioBytesPerSecond(get,never) : Float; + @:flash.property var audioLossRate(get,never) : Float; + @:flash.property var byteCount(get,never) : Float; + @:flash.property var currentBytesPerSecond(get,never) : Float; + @:flash.property var dataBufferByteLength(get,never) : Float; + @:flash.property var dataBufferLength(get,never) : Float; + @:flash.property var dataByteCount(get,never) : Float; + @:flash.property var dataBytesPerSecond(get,never) : Float; + @:flash.property var droppedFrames(get,never) : Float; + @:flash.property var isLive(get,never) : Bool; + @:flash.property var maxBytesPerSecond(get,never) : Float; + @:flash.property var metaData(get,never) : Dynamic; + @:flash.property var playbackBytesPerSecond(get,never) : Float; + @:flash.property var resourceName(get,never) : String; + @:flash.property var uri(get,never) : String; + @:flash.property var videoBufferByteLength(get,never) : Float; + @:flash.property var videoBufferLength(get,never) : Float; + @:flash.property var videoByteCount(get,never) : Float; + @:flash.property var videoBytesPerSecond(get,never) : Float; + @:flash.property @:require(flash10_1) var videoLossRate(get,never) : Float; + @:flash.property var xmpData(get,never) : Dynamic; function new(curBPS : Float, byteCount : Float, maxBPS : Float, audioBPS : Float, audioByteCount : Float, videoBPS : Float, videoByteCount : Float, dataBPS : Float, dataByteCount : Float, playbackBPS : Float, droppedFrames : Float, audioBufferByteLength : Float, videoBufferByteLength : Float, dataBufferByteLength : Float, audioBufferLength : Float, videoBufferLength : Float, dataBufferLength : Float, srtt : Float, audioLossRate : Float, videoLossRate : Float, ?metaData : Dynamic, ?xmpData : Dynamic, ?uri : String, ?resourceName : String, isLive : Bool = true) : Void; + private function get_SRTT() : Float; + private function get_audioBufferByteLength() : Float; + private function get_audioBufferLength() : Float; + private function get_audioByteCount() : Float; + private function get_audioBytesPerSecond() : Float; + private function get_audioLossRate() : Float; + private function get_byteCount() : Float; + private function get_currentBytesPerSecond() : Float; + private function get_dataBufferByteLength() : Float; + private function get_dataBufferLength() : Float; + private function get_dataByteCount() : Float; + private function get_dataBytesPerSecond() : Float; + private function get_droppedFrames() : Float; + private function get_isLive() : Bool; + private function get_maxBytesPerSecond() : Float; + private function get_metaData() : Dynamic; + private function get_playbackBytesPerSecond() : Float; + private function get_resourceName() : String; + private function get_uri() : String; + private function get_videoBufferByteLength() : Float; + private function get_videoBufferLength() : Float; + private function get_videoByteCount() : Float; + private function get_videoBytesPerSecond() : Float; + private function get_videoLossRate() : Float; + private function get_xmpData() : Dynamic; function toString() : String; } diff --git a/std/flash/net/NetStreamMulticastInfo.hx b/std/flash/net/NetStreamMulticastInfo.hx index c86a04df0c5..5a40bb53277 100644 --- a/std/flash/net/NetStreamMulticastInfo.hx +++ b/std/flash/net/NetStreamMulticastInfo.hx @@ -1,25 +1,44 @@ package flash.net; -@:final @:require(flash10_1) extern class NetStreamMulticastInfo { - var bytesPushedFromPeers(default,never) : Float; - var bytesPushedToPeers(default,never) : Float; - var bytesReceivedFromIPMulticast(default,never) : Float; - var bytesReceivedFromServer(default,never) : Float; - var bytesRequestedByPeers(default,never) : Float; - var bytesRequestedFromPeers(default,never) : Float; - var fragmentsPushedFromPeers(default,never) : Float; - var fragmentsPushedToPeers(default,never) : Float; - var fragmentsReceivedFromIPMulticast(default,never) : Float; - var fragmentsReceivedFromServer(default,never) : Float; - var fragmentsRequestedByPeers(default,never) : Float; - var fragmentsRequestedFromPeers(default,never) : Float; - var receiveControlBytesPerSecond(default,never) : Float; - var receiveDataBytesPerSecond(default,never) : Float; - var receiveDataBytesPerSecondFromIPMulticast(default,never) : Float; - var receiveDataBytesPerSecondFromServer(default,never) : Float; - var sendControlBytesPerSecond(default,never) : Float; - var sendControlBytesPerSecondToServer(default,never) : Float; - var sendDataBytesPerSecond(default,never) : Float; +@:require(flash10_1) extern final class NetStreamMulticastInfo { + @:flash.property var bytesPushedFromPeers(get,never) : Float; + @:flash.property var bytesPushedToPeers(get,never) : Float; + @:flash.property var bytesReceivedFromIPMulticast(get,never) : Float; + @:flash.property var bytesReceivedFromServer(get,never) : Float; + @:flash.property var bytesRequestedByPeers(get,never) : Float; + @:flash.property var bytesRequestedFromPeers(get,never) : Float; + @:flash.property var fragmentsPushedFromPeers(get,never) : Float; + @:flash.property var fragmentsPushedToPeers(get,never) : Float; + @:flash.property var fragmentsReceivedFromIPMulticast(get,never) : Float; + @:flash.property var fragmentsReceivedFromServer(get,never) : Float; + @:flash.property var fragmentsRequestedByPeers(get,never) : Float; + @:flash.property var fragmentsRequestedFromPeers(get,never) : Float; + @:flash.property var receiveControlBytesPerSecond(get,never) : Float; + @:flash.property var receiveDataBytesPerSecond(get,never) : Float; + @:flash.property var receiveDataBytesPerSecondFromIPMulticast(get,never) : Float; + @:flash.property var receiveDataBytesPerSecondFromServer(get,never) : Float; + @:flash.property var sendControlBytesPerSecond(get,never) : Float; + @:flash.property var sendControlBytesPerSecondToServer(get,never) : Float; + @:flash.property var sendDataBytesPerSecond(get,never) : Float; function new(sendDataBytesPerSecond : Float, sendControlBytesPerSecond : Float, receiveDataBytesPerSecond : Float, receiveControlBytesPerSecond : Float, bytesPushedToPeers : Float, fragmentsPushedToPeers : Float, bytesRequestedByPeers : Float, fragmentsRequestedByPeers : Float, bytesPushedFromPeers : Float, fragmentsPushedFromPeers : Float, bytesRequestedFromPeers : Float, fragmentsRequestedFromPeers : Float, sendControlBytesPerSecondToServer : Float, receiveDataBytesPerSecondFromServer : Float, bytesReceivedFromServer : Float, fragmentsReceivedFromServer : Float, receiveDataBytesPerSecondFromIPMulticast : Float, bytesReceivedFromIPMulticast : Float, fragmentsReceivedFromIPMulticast : Float) : Void; + private function get_bytesPushedFromPeers() : Float; + private function get_bytesPushedToPeers() : Float; + private function get_bytesReceivedFromIPMulticast() : Float; + private function get_bytesReceivedFromServer() : Float; + private function get_bytesRequestedByPeers() : Float; + private function get_bytesRequestedFromPeers() : Float; + private function get_fragmentsPushedFromPeers() : Float; + private function get_fragmentsPushedToPeers() : Float; + private function get_fragmentsReceivedFromIPMulticast() : Float; + private function get_fragmentsReceivedFromServer() : Float; + private function get_fragmentsRequestedByPeers() : Float; + private function get_fragmentsRequestedFromPeers() : Float; + private function get_receiveControlBytesPerSecond() : Float; + private function get_receiveDataBytesPerSecond() : Float; + private function get_receiveDataBytesPerSecondFromIPMulticast() : Float; + private function get_receiveDataBytesPerSecondFromServer() : Float; + private function get_sendControlBytesPerSecond() : Float; + private function get_sendControlBytesPerSecondToServer() : Float; + private function get_sendDataBytesPerSecond() : Float; function toString() : String; } diff --git a/std/flash/net/ObjectEncoding.hx b/std/flash/net/ObjectEncoding.hx index 0b7b9f1472f..305ddfe8098 100644 --- a/std/flash/net/ObjectEncoding.hx +++ b/std/flash/net/ObjectEncoding.hx @@ -1,8 +1,10 @@ package flash.net; extern class ObjectEncoding { - static var AMF0(default,never) : UInt; - static var AMF3(default,never) : UInt; - static var DEFAULT(default,never) : UInt; - static var dynamicPropertyWriter : IDynamicPropertyWriter; + static final AMF0 : UInt; + static final AMF3 : UInt; + static final DEFAULT : UInt; + @:flash.property static var dynamicPropertyWriter(get,set) : IDynamicPropertyWriter; + private static function get_dynamicPropertyWriter() : IDynamicPropertyWriter; + private static function set_dynamicPropertyWriter(value : IDynamicPropertyWriter) : IDynamicPropertyWriter; } diff --git a/std/flash/net/SecureSocket.hx b/std/flash/net/SecureSocket.hx index a895d58e09d..a19352f25a7 100644 --- a/std/flash/net/SecureSocket.hx +++ b/std/flash/net/SecureSocket.hx @@ -1,9 +1,12 @@ package flash.net; @:require(flash11) extern class SecureSocket extends Socket { - var serverCertificate(default,never) : flash.security.X509Certificate; - var serverCertificateStatus(default,never) : String; + @:flash.property var serverCertificate(get,never) : flash.security.X509Certificate; + @:flash.property var serverCertificateStatus(get,never) : String; function new() : Void; function addBinaryChainBuildingCertificate(certificate : flash.utils.ByteArray, trusted : Bool) : Void; - static var isSupported(default,never) : Bool; + private function get_serverCertificate() : flash.security.X509Certificate; + private function get_serverCertificateStatus() : String; + @:flash.property static var isSupported(get,never) : Bool; + private static function get_isSupported() : Bool; } diff --git a/std/flash/net/SharedObject.hx b/std/flash/net/SharedObject.hx index 267eb4fb7ea..cc152a3cd4e 100644 --- a/std/flash/net/SharedObject.hx +++ b/std/flash/net/SharedObject.hx @@ -1,23 +1,34 @@ package flash.net; extern class SharedObject extends flash.events.EventDispatcher { - var client : Dynamic; - var data(default,never) : Dynamic; - var fps(never,default) : Float; - var objectEncoding : UInt; - var size(default,never) : UInt; + @:flash.property var client(get,set) : Dynamic; + @:flash.property var data(get,never) : Dynamic; + @:flash.property var fps(never,set) : Float; + @:flash.property var objectEncoding(get,set) : UInt; + @:flash.property var size(get,never) : UInt; function new() : Void; function clear() : Void; function close() : Void; function connect(myConnection : NetConnection, ?params : String) : Void; function flush(minDiskSpace : Int = 0) : String; - function send(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; + private function get_client() : Dynamic; + private function get_data() : Dynamic; + private function get_objectEncoding() : UInt; + private function get_size() : UInt; + function send(restArgs : haxe.extern.Rest) : Void; function setDirty(propertyName : String) : Void; function setProperty(propertyName : String, ?value : flash.utils.Object) : Void; - static var defaultObjectEncoding : UInt; - @:require(flash11_7) static var preventBackup : Bool; + private function set_client(value : Dynamic) : Dynamic; + private function set_fps(value : Float) : Float; + private function set_objectEncoding(value : UInt) : UInt; + @:flash.property static var defaultObjectEncoding(get,set) : UInt; + @:flash.property @:require(flash11_7) static var preventBackup(get,set) : Bool; static function deleteAll(url : String) : Int; static function getDiskUsage(url : String) : Int; static function getLocal(name : String, ?localPath : String, secure : Bool = false) : SharedObject; static function getRemote(name : String, ?remotePath : String, persistence : Dynamic = false, secure : Bool = false) : SharedObject; + private static function get_defaultObjectEncoding() : UInt; + private static function get_preventBackup() : Bool; + private static function set_defaultObjectEncoding(value : UInt) : UInt; + private static function set_preventBackup(value : Bool) : Bool; } diff --git a/std/flash/net/SharedObjectFlushStatus.hx b/std/flash/net/SharedObjectFlushStatus.hx index 505c2da01aa..15e603156f2 100644 --- a/std/flash/net/SharedObjectFlushStatus.hx +++ b/std/flash/net/SharedObjectFlushStatus.hx @@ -2,6 +2,6 @@ package flash.net; extern class SharedObjectFlushStatus { function new() : Void; - static var FLUSHED(default,never) : String; - static var PENDING(default,never) : String; + static final FLUSHED : String; + static final PENDING : String; } diff --git a/std/flash/net/Socket.hx b/std/flash/net/Socket.hx index d8dfd1470d8..2c8716bf620 100644 --- a/std/flash/net/Socket.hx +++ b/std/flash/net/Socket.hx @@ -1,16 +1,22 @@ package flash.net; extern class Socket extends flash.events.EventDispatcher implements flash.utils.IDataOutput implements flash.utils.IDataInput { - var bytesAvailable(default,never) : UInt; - @:require(flash11) var bytesPending(default,never) : UInt; - var connected(default,never) : Bool; - var endian : flash.utils.Endian; - var objectEncoding : UInt; - @:require(flash10) var timeout : UInt; + @:flash.property var bytesAvailable(get,never) : UInt; + @:flash.property @:require(flash11) var bytesPending(get,never) : UInt; + @:flash.property var connected(get,never) : Bool; + @:flash.property var endian(get,set) : flash.utils.Endian; + @:flash.property var objectEncoding(get,set) : UInt; + @:flash.property @:require(flash10) var timeout(get,set) : UInt; function new(?host : String, port : Int = 0) : Void; function close() : Void; function connect(host : String, port : Int) : Void; function flush() : Void; + private function get_bytesAvailable() : UInt; + private function get_bytesPending() : UInt; + private function get_connected() : Bool; + private function get_endian() : flash.utils.Endian; + private function get_objectEncoding() : UInt; + private function get_timeout() : UInt; function readBoolean() : Bool; function readByte() : Int; function readBytes(bytes : flash.utils.ByteArray, offset : UInt = 0, length : UInt = 0) : Void; @@ -25,6 +31,9 @@ extern class Socket extends flash.events.EventDispatcher implements flash.utils. function readUnsignedByte() : UInt; function readUnsignedInt() : UInt; function readUnsignedShort() : UInt; + private function set_endian(value : flash.utils.Endian) : flash.utils.Endian; + private function set_objectEncoding(value : UInt) : UInt; + private function set_timeout(value : UInt) : UInt; function writeBoolean(value : Bool) : Void; function writeByte(value : Int) : Void; function writeBytes(bytes : flash.utils.ByteArray, offset : UInt = 0, length : UInt = 0) : Void; diff --git a/std/flash/net/URLLoaderDataFormat.hx b/std/flash/net/URLLoaderDataFormat.hx index b8827d7ff37..19bf1b94db7 100644 --- a/std/flash/net/URLLoaderDataFormat.hx +++ b/std/flash/net/URLLoaderDataFormat.hx @@ -1,7 +1,7 @@ package flash.net; -@:fakeEnum(String) extern enum URLLoaderDataFormat { - BINARY; - TEXT; - VARIABLES; +@:native("flash.net.URLLoaderDataFormat") extern enum abstract URLLoaderDataFormat(String) { + var BINARY; + var TEXT; + var VARIABLES; } diff --git a/std/flash/net/URLRequest.hx b/std/flash/net/URLRequest.hx index 61707bf6455..213fd1f4733 100644 --- a/std/flash/net/URLRequest.hx +++ b/std/flash/net/URLRequest.hx @@ -1,12 +1,24 @@ package flash.net; -@:final extern class URLRequest { - var contentType : String; - var data : Dynamic; - var digest : String; - var method : String; - var requestHeaders : Array; - var url : String; +extern final class URLRequest { + @:flash.property var contentType(get,set) : String; + @:flash.property var data(get,set) : Dynamic; + @:flash.property var digest(get,set) : String; + @:flash.property var method(get,set) : String; + @:flash.property var requestHeaders(get,set) : Array; + @:flash.property var url(get,set) : String; function new(?url : String) : Void; + private function get_contentType() : String; + private function get_data() : Dynamic; + private function get_digest() : String; + private function get_method() : String; + private function get_requestHeaders() : Array; + private function get_url() : String; + private function set_contentType(value : String) : String; + private function set_data(value : Dynamic) : Dynamic; + private function set_digest(value : String) : String; + private function set_method(value : String) : String; + private function set_requestHeaders(value : Array) : Array; + private function set_url(value : String) : String; function useRedirectedURL(sourceRequest : URLRequest, wholeURL : Bool = false, ?pattern : Dynamic, ?replace : String) : Void; } diff --git a/std/flash/net/URLRequestHeader.hx b/std/flash/net/URLRequestHeader.hx index 77b6224891c..e8c4e46d0c5 100644 --- a/std/flash/net/URLRequestHeader.hx +++ b/std/flash/net/URLRequestHeader.hx @@ -1,6 +1,6 @@ package flash.net; -@:final extern class URLRequestHeader { +extern final class URLRequestHeader { var name : String; var value : String; function new(?name : String, ?value : String) : Void; diff --git a/std/flash/net/URLRequestMethod.hx b/std/flash/net/URLRequestMethod.hx index 7e00873f2e7..62a8413313f 100644 --- a/std/flash/net/URLRequestMethod.hx +++ b/std/flash/net/URLRequestMethod.hx @@ -1,10 +1,10 @@ package flash.net; extern class URLRequestMethod { - @:require(flash10_1) static var DELETE(default,never) : String; - static var GET(default,never) : String; - @:require(flash10_1) static var HEAD(default,never) : String; - @:require(flash10_1) static var OPTIONS(default,never) : String; - static var POST(default,never) : String; - @:require(flash10_1) static var PUT(default,never) : String; + @:require(flash10_1) static final DELETE : String; + static final GET : String; + @:require(flash10_1) static final HEAD : String; + @:require(flash10_1) static final OPTIONS : String; + static final POST : String; + @:require(flash10_1) static final PUT : String; } diff --git a/std/flash/net/URLStream.hx b/std/flash/net/URLStream.hx index 2cb4cf41f2a..d33139f417b 100644 --- a/std/flash/net/URLStream.hx +++ b/std/flash/net/URLStream.hx @@ -1,15 +1,22 @@ package flash.net; extern class URLStream extends flash.events.EventDispatcher implements flash.utils.IDataInput { - var bytesAvailable(default,never) : UInt; - var connected(default,never) : Bool; - @:require(flash11_4) var diskCacheEnabled(default,never) : Bool; - var endian : flash.utils.Endian; - @:require(flash11_4) var length(default,never) : Float; - var objectEncoding : UInt; - @:require(flash11_4) var position : Float; + @:flash.property var bytesAvailable(get,never) : UInt; + @:flash.property var connected(get,never) : Bool; + @:flash.property @:require(flash11_4) var diskCacheEnabled(get,never) : Bool; + @:flash.property var endian(get,set) : flash.utils.Endian; + @:flash.property @:require(flash11_4) var length(get,never) : Float; + @:flash.property var objectEncoding(get,set) : UInt; + @:flash.property @:require(flash11_4) var position(get,set) : Float; function new() : Void; function close() : Void; + private function get_bytesAvailable() : UInt; + private function get_connected() : Bool; + private function get_diskCacheEnabled() : Bool; + private function get_endian() : flash.utils.Endian; + private function get_length() : Float; + private function get_objectEncoding() : UInt; + private function get_position() : Float; function load(request : URLRequest) : Void; function readBoolean() : Bool; function readByte() : Int; @@ -25,5 +32,8 @@ extern class URLStream extends flash.events.EventDispatcher implements flash.uti function readUnsignedByte() : UInt; function readUnsignedInt() : UInt; function readUnsignedShort() : UInt; + private function set_endian(value : flash.utils.Endian) : flash.utils.Endian; + private function set_objectEncoding(value : UInt) : UInt; + private function set_position(value : Float) : Float; @:require(flash11_4) function stop() : Void; } diff --git a/std/flash/net/XMLSocket.hx b/std/flash/net/XMLSocket.hx index b8e787efe2d..777e99ec781 100644 --- a/std/flash/net/XMLSocket.hx +++ b/std/flash/net/XMLSocket.hx @@ -1,10 +1,13 @@ package flash.net; extern class XMLSocket extends flash.events.EventDispatcher { - var connected(default,never) : Bool; - @:require(flash10) var timeout : Int; + @:flash.property var connected(get,never) : Bool; + @:flash.property @:require(flash10) var timeout(get,set) : Int; function new(?host : String, port : Int = 0) : Void; function close() : Void; function connect(host : String, port : Int) : Void; + private function get_connected() : Bool; + private function get_timeout() : Int; function send(object : Dynamic) : Void; + private function set_timeout(value : Int) : Int; } diff --git a/std/flash/net/drm/AddToDeviceGroupSetting.hx b/std/flash/net/drm/AddToDeviceGroupSetting.hx index 89739329db1..bed0442ea06 100644 --- a/std/flash/net/drm/AddToDeviceGroupSetting.hx +++ b/std/flash/net/drm/AddToDeviceGroupSetting.hx @@ -2,7 +2,7 @@ package flash.net.drm; extern class AddToDeviceGroupSetting { function new() : Void; - static var ALLOW_SERVER(default,never) : String; - static var FORCE_REFRESH(default,never) : String; - static var LOCAL_ONLY(default,never) : String; + static final ALLOW_SERVER : String; + static final FORCE_REFRESH : String; + static final LOCAL_ONLY : String; } diff --git a/std/flash/net/drm/AuthenticationMethod.hx b/std/flash/net/drm/AuthenticationMethod.hx index 44b4afe5f0e..6b9e13ac979 100644 --- a/std/flash/net/drm/AuthenticationMethod.hx +++ b/std/flash/net/drm/AuthenticationMethod.hx @@ -2,6 +2,6 @@ package flash.net.drm; extern class AuthenticationMethod { function new() : Void; - static var ANONYMOUS(default,never) : String; - static var USERNAME_AND_PASSWORD(default,never) : String; + static final ANONYMOUS : String; + static final USERNAME_AND_PASSWORD : String; } diff --git a/std/flash/net/drm/DRMAuthenticationContext.hx b/std/flash/net/drm/DRMAuthenticationContext.hx index c220658960d..dbe94a3ca56 100644 --- a/std/flash/net/drm/DRMAuthenticationContext.hx +++ b/std/flash/net/drm/DRMAuthenticationContext.hx @@ -1,7 +1,8 @@ package flash.net.drm; extern class DRMAuthenticationContext extends DRMManagerSession { - var authenticationToken(default,never) : flash.utils.ByteArray; + @:flash.property var authenticationToken(get,never) : flash.utils.ByteArray; function new() : Void; function authenticate(url : String, domain : String, username : String, password : String) : Void; + private function get_authenticationToken() : flash.utils.ByteArray; } diff --git a/std/flash/net/drm/DRMContentData.hx b/std/flash/net/drm/DRMContentData.hx index 5b5487ca776..f1286940d96 100644 --- a/std/flash/net/drm/DRMContentData.hx +++ b/std/flash/net/drm/DRMContentData.hx @@ -1,10 +1,14 @@ package flash.net.drm; extern class DRMContentData { - var authenticationMethod(default,never) : String; - var domain(default,never) : String; - var licenseID(default,never) : String; - var serverURL(default,never) : String; + @:flash.property var authenticationMethod(get,never) : String; + @:flash.property var domain(get,never) : String; + @:flash.property var licenseID(get,never) : String; + @:flash.property var serverURL(get,never) : String; function new(?rawData : flash.utils.ByteArray) : Void; function getVoucherAccessInfo() : flash.Vector; + private function get_authenticationMethod() : String; + private function get_domain() : String; + private function get_licenseID() : String; + private function get_serverURL() : String; } diff --git a/std/flash/net/drm/DRMDeviceGroup.hx b/std/flash/net/drm/DRMDeviceGroup.hx index 7ede90f975a..bd2ad81a4bc 100644 --- a/std/flash/net/drm/DRMDeviceGroup.hx +++ b/std/flash/net/drm/DRMDeviceGroup.hx @@ -1,9 +1,14 @@ package flash.net.drm; -@:final extern class DRMDeviceGroup { - var authenticationMethod(default,never) : String; - var domain(default,never) : String; - var name : String; - var serverURL(default,never) : String; +extern final class DRMDeviceGroup { + @:flash.property var authenticationMethod(get,never) : String; + @:flash.property var domain(get,never) : String; + @:flash.property var name(get,set) : String; + @:flash.property var serverURL(get,never) : String; function new() : Void; + private function get_authenticationMethod() : String; + private function get_domain() : String; + private function get_name() : String; + private function get_serverURL() : String; + private function set_name(value : String) : String; } diff --git a/std/flash/net/drm/DRMManager.hx b/std/flash/net/drm/DRMManager.hx index 6e857657b6e..4c2a4f08268 100644 --- a/std/flash/net/drm/DRMManager.hx +++ b/std/flash/net/drm/DRMManager.hx @@ -8,12 +8,15 @@ extern class DRMManager extends flash.events.EventDispatcher { function loadVoucher(contentData : DRMContentData, setting : String) : Void; function removeFromDeviceGroup(deviceGroup : DRMDeviceGroup) : Void; function resetDRMVouchers() : Void; - function resetDRMVouchersInternal(isAutoReset : Bool) : Void; + @:ns("flash.net.drm",internal) function resetDRMVouchersInternal(isAutoReset : Bool) : Void; function returnVoucher(inServerURL : String, immediateCommit : Bool, licenseID : String, policyID : String) : Void; function setAuthenticationToken(serverUrl : String, domain : String, token : flash.utils.ByteArray) : Void; function storeVoucher(voucher : flash.utils.ByteArray) : Void; - static var isSupported(default,never) : Bool; - static var networkIdleTimeout : Float; + @:flash.property static var isSupported(get,never) : Bool; + @:flash.property static var networkIdleTimeout(get,set) : Float; static function getDRMManager() : DRMManager; - static function getDRMManagerInternal() : DRMManager; + @:ns("flash.net.drm",internal) static function getDRMManagerInternal() : DRMManager; + private static function get_isSupported() : Bool; + private static function get_networkIdleTimeout() : Float; + private static function set_networkIdleTimeout(value : Float) : Float; } diff --git a/std/flash/net/drm/DRMManagerSession.hx b/std/flash/net/drm/DRMManagerSession.hx index be1f42228da..3ffb9ed759e 100644 --- a/std/flash/net/drm/DRMManagerSession.hx +++ b/std/flash/net/drm/DRMManagerSession.hx @@ -2,20 +2,22 @@ package flash.net.drm; extern class DRMManagerSession extends flash.events.EventDispatcher { var m_isInSession : Bool; - var metadata : DRMContentData; + @:flash.property var metadata(get,set) : DRMContentData; function new() : Void; function checkStatus() : UInt; function errorCodeToThrow(errorCode : UInt) : Void; function getLastError() : UInt; function getLastServerErrorString() : String; function getLastSubErrorID() : UInt; + private function get_metadata() : DRMContentData; function issueDRMErrorEvent(metadata : DRMContentData, errorID : Int, subErrorID : Int, serverErrorString : String) : Void; function issueDRMStatusEvent(inMetadata : DRMContentData, voucher : DRMVoucher) : Dynamic; function onSessionComplete() : Void; function onSessionError() : Void; function setTimerUp() : Void; - static var STATUS_FAILED(default,never) : UInt; - static var STATUS_NOTREADY(default,never) : UInt; - static var STATUS_READY(default,never) : UInt; - static var STATUS_UNKNOWN(default,never) : UInt; + private function set_metadata(value : DRMContentData) : DRMContentData; + @:ns("flash.net.drm",internal) static final STATUS_FAILED : UInt; + @:ns("flash.net.drm",internal) static final STATUS_NOTREADY : UInt; + @:ns("flash.net.drm",internal) static final STATUS_READY : UInt; + @:ns("flash.net.drm",internal) static final STATUS_UNKNOWN : UInt; } diff --git a/std/flash/net/drm/DRMPlaybackTimeWindow.hx b/std/flash/net/drm/DRMPlaybackTimeWindow.hx index 7014bd2edaf..f4252d3c1d8 100644 --- a/std/flash/net/drm/DRMPlaybackTimeWindow.hx +++ b/std/flash/net/drm/DRMPlaybackTimeWindow.hx @@ -1,8 +1,11 @@ package flash.net.drm; extern class DRMPlaybackTimeWindow { - var endDate(default,never) : Date; - var period(default,never) : UInt; - var startDate(default,never) : Date; + @:flash.property var endDate(get,never) : Date; + @:flash.property var period(get,never) : UInt; + @:flash.property var startDate(get,never) : Date; function new() : Void; + private function get_endDate() : Date; + private function get_period() : UInt; + private function get_startDate() : Date; } diff --git a/std/flash/net/drm/DRMVoucher.hx b/std/flash/net/drm/DRMVoucher.hx index 71051044881..fc694a2d8eb 100644 --- a/std/flash/net/drm/DRMVoucher.hx +++ b/std/flash/net/drm/DRMVoucher.hx @@ -1,15 +1,24 @@ package flash.net.drm; extern class DRMVoucher { - var licenseID(default,never) : String; - var offlineLeaseEndDate(default,never) : Date; - var offlineLeaseStartDate(default,never) : Date; - var playbackTimeWindow(default,never) : DRMPlaybackTimeWindow; - var policies(default,never) : Dynamic; - var policyID(default,never) : String; - var serverURL(default,never) : String; - var voucherEndDate(default,never) : Date; - var voucherStartDate(default,never) : Date; + @:flash.property var licenseID(get,never) : String; + @:flash.property var offlineLeaseEndDate(get,never) : Date; + @:flash.property var offlineLeaseStartDate(get,never) : Date; + @:flash.property var playbackTimeWindow(get,never) : DRMPlaybackTimeWindow; + @:flash.property var policies(get,never) : Dynamic; + @:flash.property var policyID(get,never) : String; + @:flash.property var serverURL(get,never) : String; + @:flash.property var voucherEndDate(get,never) : Date; + @:flash.property var voucherStartDate(get,never) : Date; function new() : Void; + private function get_licenseID() : String; + private function get_offlineLeaseEndDate() : Date; + private function get_offlineLeaseStartDate() : Date; + private function get_playbackTimeWindow() : DRMPlaybackTimeWindow; + private function get_policies() : Dynamic; + private function get_policyID() : String; + private function get_serverURL() : String; + private function get_voucherEndDate() : Date; + private function get_voucherStartDate() : Date; function toByteArray() : flash.utils.ByteArray; } diff --git a/std/flash/net/drm/DRMVoucherDownloadContext.hx b/std/flash/net/drm/DRMVoucherDownloadContext.hx index 44c6725f406..62b34c07af9 100644 --- a/std/flash/net/drm/DRMVoucherDownloadContext.hx +++ b/std/flash/net/drm/DRMVoucherDownloadContext.hx @@ -1,7 +1,8 @@ package flash.net.drm; extern class DRMVoucherDownloadContext extends DRMManagerSession { - var voucher(default,never) : DRMVoucher; + @:flash.property var voucher(get,never) : DRMVoucher; function new() : Void; function download(inMetadata : DRMContentData, previewVoucher : Bool = false) : Void; + private function get_voucher() : DRMVoucher; } diff --git a/std/flash/net/drm/DRMVoucherStoreContext.hx b/std/flash/net/drm/DRMVoucherStoreContext.hx index dc731f06764..bbc7b0a4d9c 100644 --- a/std/flash/net/drm/DRMVoucherStoreContext.hx +++ b/std/flash/net/drm/DRMVoucherStoreContext.hx @@ -1,7 +1,8 @@ package flash.net.drm; extern class DRMVoucherStoreContext extends DRMManagerSession { - var voucher(default,never) : DRMVoucher; + @:flash.property var voucher(get,never) : DRMVoucher; function new() : Void; function getVoucherFromStore(inMetadata : DRMContentData) : Void; + private function get_voucher() : DRMVoucher; } diff --git a/std/flash/net/drm/LoadVoucherSetting.hx b/std/flash/net/drm/LoadVoucherSetting.hx index 18993c8d022..7fb9162e3c7 100644 --- a/std/flash/net/drm/LoadVoucherSetting.hx +++ b/std/flash/net/drm/LoadVoucherSetting.hx @@ -2,7 +2,7 @@ package flash.net.drm; extern class LoadVoucherSetting { function new() : Void; - static var ALLOW_SERVER(default,never) : String; - static var FORCE_REFRESH(default,never) : String; - static var LOCAL_ONLY(default,never) : String; + static final ALLOW_SERVER : String; + static final FORCE_REFRESH : String; + static final LOCAL_ONLY : String; } diff --git a/std/flash/net/drm/VoucherAccessInfo.hx b/std/flash/net/drm/VoucherAccessInfo.hx index 895bd536b1b..ce0c64c7563 100644 --- a/std/flash/net/drm/VoucherAccessInfo.hx +++ b/std/flash/net/drm/VoucherAccessInfo.hx @@ -1,10 +1,15 @@ package flash.net.drm; -@:final extern class VoucherAccessInfo { - var authenticationMethod(default,never) : String; - var deviceGroup(default,never) : DRMDeviceGroup; - var displayName(default,never) : String; - var domain(default,never) : String; - var policyID(default,never) : String; +extern final class VoucherAccessInfo { + @:flash.property var authenticationMethod(get,never) : String; + @:flash.property var deviceGroup(get,never) : DRMDeviceGroup; + @:flash.property var displayName(get,never) : String; + @:flash.property var domain(get,never) : String; + @:flash.property var policyID(get,never) : String; function new() : Void; + private function get_authenticationMethod() : String; + private function get_deviceGroup() : DRMDeviceGroup; + private function get_displayName() : String; + private function get_domain() : String; + private function get_policyID() : String; } diff --git a/std/flash/printing/PrintJob.hx b/std/flash/printing/PrintJob.hx index 1fc72279c01..1f870be6302 100644 --- a/std/flash/printing/PrintJob.hx +++ b/std/flash/printing/PrintJob.hx @@ -1,14 +1,20 @@ package flash.printing; extern class PrintJob extends flash.events.EventDispatcher { - var orientation(default,never) : PrintJobOrientation; - var pageHeight(default,never) : Int; - var pageWidth(default,never) : Int; - var paperHeight(default,never) : Int; - var paperWidth(default,never) : Int; + @:flash.property var orientation(get,never) : PrintJobOrientation; + @:flash.property var pageHeight(get,never) : Int; + @:flash.property var pageWidth(get,never) : Int; + @:flash.property var paperHeight(get,never) : Int; + @:flash.property var paperWidth(get,never) : Int; function new() : Void; function addPage(sprite : flash.display.Sprite, ?printArea : flash.geom.Rectangle, ?options : PrintJobOptions, frameNum : Int = 0) : Void; + private function get_orientation() : PrintJobOrientation; + private function get_pageHeight() : Int; + private function get_pageWidth() : Int; + private function get_paperHeight() : Int; + private function get_paperWidth() : Int; function send() : Void; function start() : Bool; - @:require(flash10_1) static var isSupported(default,never) : Bool; + @:flash.property @:require(flash10_1) static var isSupported(get,never) : Bool; + private static function get_isSupported() : Bool; } diff --git a/std/flash/printing/PrintJobOrientation.hx b/std/flash/printing/PrintJobOrientation.hx index fb4f7551b0d..82f1d0445ae 100644 --- a/std/flash/printing/PrintJobOrientation.hx +++ b/std/flash/printing/PrintJobOrientation.hx @@ -1,6 +1,6 @@ package flash.printing; -@:fakeEnum(String) extern enum PrintJobOrientation { - LANDSCAPE; - PORTRAIT; +@:native("flash.printing.PrintJobOrientation") extern enum abstract PrintJobOrientation(String) { + var LANDSCAPE; + var PORTRAIT; } diff --git a/std/flash/profiler/Telemetry.hx b/std/flash/profiler/Telemetry.hx index 2e878d40c4c..377ebfeafde 100644 --- a/std/flash/profiler/Telemetry.hx +++ b/std/flash/profiler/Telemetry.hx @@ -2,8 +2,10 @@ package flash.profiler; extern class Telemetry { function new() : Void; - static var connected(default,never) : Bool; - static var spanMarker(default,never) : Float; + @:flash.property static var connected(get,never) : Bool; + @:flash.property static var spanMarker(get,never) : Float; + private static function get_connected() : Bool; + private static function get_spanMarker() : Float; static function registerCommandHandler(commandName : String, handler : Dynamic) : Bool; static function sendMetric(metric : String, value : Dynamic) : Void; static function sendSpanMetric(metric : String, startSpanMarker : Float, ?value : Dynamic) : Void; diff --git a/std/flash/sampler/ClassFactory.hx b/std/flash/sampler/ClassFactory.hx index 2969ec5603b..ba016eb349a 100644 --- a/std/flash/sampler/ClassFactory.hx +++ b/std/flash/sampler/ClassFactory.hx @@ -2,8 +2,8 @@ package flash.sampler; extern class ClassFactory { function new() : Void; - static var DeleteObjectSampleClass(default,never) : Class; - static var NewObjectSampleClass(default,never) : Class; - static var SampleClass(default,never) : Class; - static var StackFrameClass(default,never) : Class; + static final DeleteObjectSampleClass : Class; + static final NewObjectSampleClass : Class; + static final SampleClass : Class; + static final StackFrameClass : Class; } diff --git a/std/flash/sampler/DeleteObjectSample.hx b/std/flash/sampler/DeleteObjectSample.hx index 333afdd2ecc..1766d47a570 100644 --- a/std/flash/sampler/DeleteObjectSample.hx +++ b/std/flash/sampler/DeleteObjectSample.hx @@ -1,6 +1,6 @@ package flash.sampler; -@:final extern class DeleteObjectSample extends Sample { - var id(default,never) : Float; - var size(default,never) : Float; +extern final class DeleteObjectSample extends Sample { + final id : Float; + final size : Float; } diff --git a/std/flash/sampler/NewObjectSample.hx b/std/flash/sampler/NewObjectSample.hx index 3b78bcc0b76..22c3e8f0c38 100644 --- a/std/flash/sampler/NewObjectSample.hx +++ b/std/flash/sampler/NewObjectSample.hx @@ -1,8 +1,10 @@ package flash.sampler; -@:final extern class NewObjectSample extends Sample { - var id(default,never) : Float; - var object(default,never) : Dynamic; - @:require(flash10_1) var size(default,never) : Float; - var type(default,never) : Class; +extern final class NewObjectSample extends Sample { + final id : Float; + @:flash.property var object(get,never) : Dynamic; + @:flash.property @:require(flash10_1) var size(get,never) : Float; + final type : Class; + private function get_object() : Dynamic; + private function get_size() : Float; } diff --git a/std/flash/sampler/Sample.hx b/std/flash/sampler/Sample.hx index 173137b37de..f6d80cb4767 100644 --- a/std/flash/sampler/Sample.hx +++ b/std/flash/sampler/Sample.hx @@ -1,6 +1,6 @@ package flash.sampler; extern class Sample { - var stack(default,never) : Array; - var time(default,never) : Float; + final stack : Array; + final time : Float; } diff --git a/std/flash/sampler/StackFrame.hx b/std/flash/sampler/StackFrame.hx index 330213dedde..2e4fa851ad5 100644 --- a/std/flash/sampler/StackFrame.hx +++ b/std/flash/sampler/StackFrame.hx @@ -1,9 +1,9 @@ package flash.sampler; -@:final extern class StackFrame { - var file(default,never) : String; - var line(default,never) : UInt; - var name(default,never) : String; - @:require(flash10_1) var scriptID(default,never) : Float; +extern final class StackFrame { + final file : String; + final line : UInt; + final name : String; + @:require(flash10_1) final scriptID : Float; function toString() : String; } diff --git a/std/flash/security/CertificateStatus.hx b/std/flash/security/CertificateStatus.hx index 05f873cd83c..886f07ef899 100644 --- a/std/flash/security/CertificateStatus.hx +++ b/std/flash/security/CertificateStatus.hx @@ -2,13 +2,13 @@ package flash.security; extern class CertificateStatus { function new() : Void; - static var EXPIRED(default,never) : String; - static var INVALID(default,never) : String; - static var INVALID_CHAIN(default,never) : String; - static var NOT_YET_VALID(default,never) : String; - static var PRINCIPAL_MISMATCH(default,never) : String; - static var REVOKED(default,never) : String; - static var TRUSTED(default,never) : String; - static var UNKNOWN(default,never) : String; - static var UNTRUSTED_SIGNERS(default,never) : String; + static final EXPIRED : String; + static final INVALID : String; + static final INVALID_CHAIN : String; + static final NOT_YET_VALID : String; + static final PRINCIPAL_MISMATCH : String; + static final REVOKED : String; + static final TRUSTED : String; + static final UNKNOWN : String; + static final UNTRUSTED_SIGNERS : String; } diff --git a/std/flash/security/X500DistinguishedName.hx b/std/flash/security/X500DistinguishedName.hx index 37defca3ac4..b69ae568e1e 100644 --- a/std/flash/security/X500DistinguishedName.hx +++ b/std/flash/security/X500DistinguishedName.hx @@ -1,12 +1,18 @@ package flash.security; extern class X500DistinguishedName { - var commonName(default,never) : String; - var countryName(default,never) : String; - var localityName(default,never) : String; - var organizationName(default,never) : String; - var organizationalUnitName(default,never) : String; - var stateOrProvinceName(default,never) : String; + @:flash.property var commonName(get,never) : String; + @:flash.property var countryName(get,never) : String; + @:flash.property var localityName(get,never) : String; + @:flash.property var organizationName(get,never) : String; + @:flash.property var organizationalUnitName(get,never) : String; + @:flash.property var stateOrProvinceName(get,never) : String; function new() : Void; + private function get_commonName() : String; + private function get_countryName() : String; + private function get_localityName() : String; + private function get_organizationName() : String; + private function get_organizationalUnitName() : String; + private function get_stateOrProvinceName() : String; function toString() : String; } diff --git a/std/flash/security/X509Certificate.hx b/std/flash/security/X509Certificate.hx index dfdd82c5f17..b1e7d10d47e 100644 --- a/std/flash/security/X509Certificate.hx +++ b/std/flash/security/X509Certificate.hx @@ -1,18 +1,31 @@ package flash.security; extern class X509Certificate { - var encoded(default,never) : flash.utils.ByteArray; - var issuer(default,never) : X500DistinguishedName; - var issuerUniqueID(default,never) : String; - var serialNumber(default,never) : String; - var signatureAlgorithmOID(default,never) : String; - var signatureAlgorithmParams(default,never) : flash.utils.ByteArray; - var subject(default,never) : X500DistinguishedName; - var subjectPublicKey(default,never) : String; - var subjectPublicKeyAlgorithmOID(default,never) : String; - var subjectUniqueID(default,never) : String; - var validNotAfter(default,never) : Date; - var validNotBefore(default,never) : Date; - var version(default,never) : UInt; + @:flash.property var encoded(get,never) : flash.utils.ByteArray; + @:flash.property var issuer(get,never) : X500DistinguishedName; + @:flash.property var issuerUniqueID(get,never) : String; + @:flash.property var serialNumber(get,never) : String; + @:flash.property var signatureAlgorithmOID(get,never) : String; + @:flash.property var signatureAlgorithmParams(get,never) : flash.utils.ByteArray; + @:flash.property var subject(get,never) : X500DistinguishedName; + @:flash.property var subjectPublicKey(get,never) : String; + @:flash.property var subjectPublicKeyAlgorithmOID(get,never) : String; + @:flash.property var subjectUniqueID(get,never) : String; + @:flash.property var validNotAfter(get,never) : Date; + @:flash.property var validNotBefore(get,never) : Date; + @:flash.property var version(get,never) : UInt; function new() : Void; + private function get_encoded() : flash.utils.ByteArray; + private function get_issuer() : X500DistinguishedName; + private function get_issuerUniqueID() : String; + private function get_serialNumber() : String; + private function get_signatureAlgorithmOID() : String; + private function get_signatureAlgorithmParams() : flash.utils.ByteArray; + private function get_subject() : X500DistinguishedName; + private function get_subjectPublicKey() : String; + private function get_subjectPublicKeyAlgorithmOID() : String; + private function get_subjectUniqueID() : String; + private function get_validNotAfter() : Date; + private function get_validNotBefore() : Date; + private function get_version() : UInt; } diff --git a/std/flash/sensors/Accelerometer.hx b/std/flash/sensors/Accelerometer.hx index dbeab47fca4..ad341210142 100644 --- a/std/flash/sensors/Accelerometer.hx +++ b/std/flash/sensors/Accelerometer.hx @@ -1,8 +1,10 @@ package flash.sensors; @:require(flash10_1) extern class Accelerometer extends flash.events.EventDispatcher { - var muted(default,never) : Bool; + @:flash.property var muted(get,never) : Bool; function new() : Void; + private function get_muted() : Bool; function setRequestedUpdateInterval(interval : Float) : Void; - static var isSupported(default,never) : Bool; + @:flash.property static var isSupported(get,never) : Bool; + private static function get_isSupported() : Bool; } diff --git a/std/flash/sensors/Geolocation.hx b/std/flash/sensors/Geolocation.hx index 7f917e248b7..d87fc25ba99 100644 --- a/std/flash/sensors/Geolocation.hx +++ b/std/flash/sensors/Geolocation.hx @@ -1,8 +1,10 @@ package flash.sensors; @:require(flash10_1) extern class Geolocation extends flash.events.EventDispatcher { - var muted(default,never) : Bool; + @:flash.property var muted(get,never) : Bool; function new() : Void; + private function get_muted() : Bool; function setRequestedUpdateInterval(interval : Float) : Void; - static var isSupported(default,never) : Bool; + @:flash.property static var isSupported(get,never) : Bool; + private static function get_isSupported() : Bool; } diff --git a/std/flash/system/ApplicationDomain.hx b/std/flash/system/ApplicationDomain.hx index 557689e7539..5b0f7833506 100644 --- a/std/flash/system/ApplicationDomain.hx +++ b/std/flash/system/ApplicationDomain.hx @@ -1,12 +1,17 @@ package flash.system; -@:final extern class ApplicationDomain { - @:require(flash10) var domainMemory : flash.utils.ByteArray; - var parentDomain(default,never) : ApplicationDomain; +extern final class ApplicationDomain { + @:flash.property @:require(flash10) var domainMemory(get,set) : flash.utils.ByteArray; + @:flash.property var parentDomain(get,never) : ApplicationDomain; function new(?parentDomain : ApplicationDomain) : Void; function getDefinition(name : String) : flash.utils.Object; @:require(flash11_3) function getQualifiedDefinitionNames() : flash.Vector; + private function get_domainMemory() : flash.utils.ByteArray; + private function get_parentDomain() : ApplicationDomain; function hasDefinition(name : String) : Bool; - @:require(flash10) static var MIN_DOMAIN_MEMORY_LENGTH(default,never) : UInt; - static var currentDomain(default,never) : ApplicationDomain; + private function set_domainMemory(value : flash.utils.ByteArray) : flash.utils.ByteArray; + @:flash.property @:require(flash10) static var MIN_DOMAIN_MEMORY_LENGTH(get,never) : UInt; + @:flash.property static var currentDomain(get,never) : ApplicationDomain; + private static function get_MIN_DOMAIN_MEMORY_LENGTH() : UInt; + private static function get_currentDomain() : ApplicationDomain; } diff --git a/std/flash/system/ApplicationInstaller.hx b/std/flash/system/ApplicationInstaller.hx index 6c658b17740..52491934692 100644 --- a/std/flash/system/ApplicationInstaller.hx +++ b/std/flash/system/ApplicationInstaller.hx @@ -1,8 +1,9 @@ package flash.system; -@:final @:require(flash11_3) extern class ApplicationInstaller extends flash.events.EventDispatcher { - var isInstalled(default,never) : Bool; +@:require(flash11_3) extern final class ApplicationInstaller extends flash.events.EventDispatcher { + @:flash.property var isInstalled(get,never) : Bool; function new() : Void; + private function get_isInstalled() : Bool; function install(?mode : String) : Void; static function iconDigest(icon : flash.utils.ByteArray) : String; static function stringsDigest(strings : flash.xml.XML) : String; diff --git a/std/flash/system/ApplicationInstallerMode.hx b/std/flash/system/ApplicationInstallerMode.hx index a512cc2b365..4d67e6b15a7 100644 --- a/std/flash/system/ApplicationInstallerMode.hx +++ b/std/flash/system/ApplicationInstallerMode.hx @@ -1,7 +1,7 @@ package flash.system; -@:fakeEnum(String) extern enum ApplicationInstallerMode { - INSTALL_ONLY; - INSTALL_WITH_SHORTCUTS; - SHORTCUTS_ONLY; +@:native("flash.system.ApplicationInstallerMode") extern enum abstract ApplicationInstallerMode(String) { + var INSTALL_ONLY; + var INSTALL_WITH_SHORTCUTS; + var SHORTCUTS_ONLY; } diff --git a/std/flash/system/AuthorizedFeatures.hx b/std/flash/system/AuthorizedFeatures.hx index 1eb9a131e0d..cfc84b10f42 100644 --- a/std/flash/system/AuthorizedFeatures.hx +++ b/std/flash/system/AuthorizedFeatures.hx @@ -1,6 +1,6 @@ package flash.system; -@:final @:require(flash11_3) extern class AuthorizedFeatures { +@:require(flash11_3) extern final class AuthorizedFeatures { function new() : Void; function createApplicationInstaller(strings : flash.xml.XML, icon : flash.utils.ByteArray) : ApplicationInstaller; function enableAVLoader(loader : flash.display.AVLoader) : Bool; @@ -9,6 +9,6 @@ package flash.system; @:require(flash11_4) function enableDiskCache(stream : flash.net.URLStream) : Bool; @:require(flash11_7) function enableHLSPlayback(stream : flash.media.AVStream) : Bool; function enableMediaPlayerHLSPlayback(player : Dynamic) : Bool; - @:require(flash11_4) function isFeatureEnabled(feature : String, ?data : String) : Bool; - @:require(flash11_4) function isNegativeToken() : Bool; + @:ns("flash.system",internal) @:require(flash11_4) function isFeatureEnabled(feature : String, ?data : String) : Bool; + @:ns("flash.system",internal) @:require(flash11_4) function isNegativeToken() : Bool; } diff --git a/std/flash/system/AuthorizedFeaturesLoader.hx b/std/flash/system/AuthorizedFeaturesLoader.hx index 6f5934564eb..8ce6f162cef 100644 --- a/std/flash/system/AuthorizedFeaturesLoader.hx +++ b/std/flash/system/AuthorizedFeaturesLoader.hx @@ -1,9 +1,10 @@ package flash.system; -@:final @:require(flash11_3) extern class AuthorizedFeaturesLoader extends flash.events.EventDispatcher { - var authorizedFeatures(default,never) : AuthorizedFeatures; +@:require(flash11_3) extern final class AuthorizedFeaturesLoader extends flash.events.EventDispatcher { + @:flash.property var authorizedFeatures(get,never) : AuthorizedFeatures; function new() : Void; + private function get_authorizedFeatures() : AuthorizedFeatures; function loadAuthorizedFeatures() : Void; @:require(flash11_7) function loadAuthorizedFeaturesFromData(data : flash.utils.ByteArray) : Void; - @:require(flash11_4) function makeGlobal() : Void; + @:ns("flash.system",internal) @:require(flash11_4) function makeGlobal() : Void; } diff --git a/std/flash/system/Capabilities.hx b/std/flash/system/Capabilities.hx index 0fe6f780d78..22f1f86ae2f 100644 --- a/std/flash/system/Capabilities.hx +++ b/std/flash/system/Capabilities.hx @@ -1,39 +1,75 @@ package flash.system; extern class Capabilities { - static var _internal(default,never) : UInt; - static var avHardwareDisable(default,never) : Bool; - @:require(flash10_1) static var cpuArchitecture(default,never) : String; - static var hasAccessibility(default,never) : Bool; - static var hasAudio(default,never) : Bool; - static var hasAudioEncoder(default,never) : Bool; - static var hasEmbeddedVideo(default,never) : Bool; - static var hasIME(default,never) : Bool; - static var hasMP3(default,never) : Bool; - static var hasPrinting(default,never) : Bool; - static var hasScreenBroadcast(default,never) : Bool; - static var hasScreenPlayback(default,never) : Bool; - static var hasStreamingAudio(default,never) : Bool; - static var hasStreamingVideo(default,never) : Bool; - static var hasTLS(default,never) : Bool; - static var hasVideoEncoder(default,never) : Bool; - static var isDebugger(default,never) : Bool; - @:require(flash10) static var isEmbeddedInAcrobat(default,never) : Bool; - static var language(default,never) : String; - static var localFileReadDisable(default,never) : Bool; - static var manufacturer(default,never) : String; - @:require(flash10) static var maxLevelIDC(default,never) : String; - static var os(default,never) : String; - static var pixelAspectRatio(default,never) : Float; - static var playerType(default,never) : String; - static var screenColor(default,never) : String; - static var screenDPI(default,never) : Float; - static var screenResolutionX(default,never) : Float; - static var screenResolutionY(default,never) : Float; - static var serverString(default,never) : String; - @:require(flash10_1) static var supports32BitProcesses(default,never) : Bool; - @:require(flash10_1) static var supports64BitProcesses(default,never) : Bool; - @:require(flash10_1) static var touchscreenType(default,never) : TouchscreenType; - static var version(default,never) : String; + @:flash.property static var _internal(get,never) : UInt; + @:flash.property static var avHardwareDisable(get,never) : Bool; + @:flash.property static var cpuAddressSize(get,never) : Float; + @:flash.property @:require(flash10_1) static var cpuArchitecture(get,never) : String; + @:flash.property static var hasAccessibility(get,never) : Bool; + @:flash.property static var hasAudio(get,never) : Bool; + @:flash.property static var hasAudioEncoder(get,never) : Bool; + @:flash.property static var hasEmbeddedVideo(get,never) : Bool; + @:flash.property static var hasIME(get,never) : Bool; + @:flash.property static var hasMP3(get,never) : Bool; + @:flash.property static var hasPrinting(get,never) : Bool; + @:flash.property static var hasScreenBroadcast(get,never) : Bool; + @:flash.property static var hasScreenPlayback(get,never) : Bool; + @:flash.property static var hasStreamingAudio(get,never) : Bool; + @:flash.property static var hasStreamingVideo(get,never) : Bool; + @:flash.property static var hasTLS(get,never) : Bool; + @:flash.property static var hasVideoEncoder(get,never) : Bool; + @:flash.property static var isDebugger(get,never) : Bool; + @:flash.property @:require(flash10) static var isEmbeddedInAcrobat(get,never) : Bool; + @:flash.property static var language(get,never) : String; + @:flash.property static var localFileReadDisable(get,never) : Bool; + @:flash.property static var manufacturer(get,never) : String; + @:flash.property @:require(flash10) static var maxLevelIDC(get,never) : String; + @:flash.property static var os(get,never) : String; + @:flash.property static var pixelAspectRatio(get,never) : Float; + @:flash.property static var playerType(get,never) : String; + @:flash.property static var screenColor(get,never) : String; + @:flash.property static var screenDPI(get,never) : Float; + @:flash.property static var screenResolutionX(get,never) : Float; + @:flash.property static var screenResolutionY(get,never) : Float; + @:flash.property static var serverString(get,never) : String; + @:flash.property @:require(flash10_1) static var supports32BitProcesses(get,never) : Bool; + @:flash.property @:require(flash10_1) static var supports64BitProcesses(get,never) : Bool; + @:flash.property @:require(flash10_1) static var touchscreenType(get,never) : TouchscreenType; + @:flash.property static var version(get,never) : String; + private static function get__internal() : UInt; + private static function get_avHardwareDisable() : Bool; + private static function get_cpuAddressSize() : Float; + private static function get_cpuArchitecture() : String; + private static function get_hasAccessibility() : Bool; + private static function get_hasAudio() : Bool; + private static function get_hasAudioEncoder() : Bool; + private static function get_hasEmbeddedVideo() : Bool; + private static function get_hasIME() : Bool; + private static function get_hasMP3() : Bool; + private static function get_hasPrinting() : Bool; + private static function get_hasScreenBroadcast() : Bool; + private static function get_hasScreenPlayback() : Bool; + private static function get_hasStreamingAudio() : Bool; + private static function get_hasStreamingVideo() : Bool; + private static function get_hasTLS() : Bool; + private static function get_hasVideoEncoder() : Bool; + private static function get_isDebugger() : Bool; + private static function get_isEmbeddedInAcrobat() : Bool; + private static function get_language() : String; + private static function get_localFileReadDisable() : Bool; + private static function get_manufacturer() : String; + private static function get_maxLevelIDC() : String; + private static function get_os() : String; + private static function get_pixelAspectRatio() : Float; + private static function get_playerType() : String; + private static function get_screenColor() : String; + private static function get_screenDPI() : Float; + private static function get_screenResolutionX() : Float; + private static function get_screenResolutionY() : Float; + private static function get_serverString() : String; + private static function get_supports32BitProcesses() : Bool; + private static function get_supports64BitProcesses() : Bool; + private static function get_touchscreenType() : TouchscreenType; + private static function get_version() : String; @:require(flash11) static function hasMultiChannelAudio(type : String) : Bool; } diff --git a/std/flash/system/ConnexionsClient.hx b/std/flash/system/ConnexionsClient.hx index 923d25cdf5c..68300cc0022 100644 --- a/std/flash/system/ConnexionsClient.hx +++ b/std/flash/system/ConnexionsClient.hx @@ -1,6 +1,6 @@ package flash.system; -@:final extern class ConnexionsClient { +extern final class ConnexionsClient { function new() : Void; function Connexions() : Dynamic; function _init(topLocation : String, documentReferrer : String, windowLocation : String, movie : String, userAgent : String, timeout : UInt) : Void; diff --git a/std/flash/system/IME.hx b/std/flash/system/IME.hx index 5e94a16dfa9..7a6659f186e 100644 --- a/std/flash/system/IME.hx +++ b/std/flash/system/IME.hx @@ -1,11 +1,16 @@ package flash.system; extern class IME extends flash.events.EventDispatcher { - static var conversionMode : IMEConversionMode; - static var enabled : Bool; - @:require(flash10_1) static var isSupported(default,never) : Bool; + @:flash.property static var conversionMode(get,set) : IMEConversionMode; + @:flash.property static var enabled(get,set) : Bool; + @:flash.property @:require(flash10_1) static var isSupported(get,never) : Bool; @:require(flash10_1) static function compositionAbandoned() : Void; @:require(flash10_1) static function compositionSelectionChanged(start : Int, end : Int) : Void; static function doConversion() : Void; + private static function get_conversionMode() : IMEConversionMode; + private static function get_enabled() : Bool; + private static function get_isSupported() : Bool; static function setCompositionString(composition : String) : Void; + private static function set_conversionMode(value : IMEConversionMode) : IMEConversionMode; + private static function set_enabled(value : Bool) : Bool; } diff --git a/std/flash/system/IMEConversionMode.hx b/std/flash/system/IMEConversionMode.hx index ba1a04d7a4d..102baa905ef 100644 --- a/std/flash/system/IMEConversionMode.hx +++ b/std/flash/system/IMEConversionMode.hx @@ -1,12 +1,12 @@ package flash.system; -@:fakeEnum(String) extern enum IMEConversionMode { - ALPHANUMERIC_FULL; - ALPHANUMERIC_HALF; - CHINESE; - JAPANESE_HIRAGANA; - JAPANESE_KATAKANA_FULL; - JAPANESE_KATAKANA_HALF; - KOREAN; - UNKNOWN; +@:native("flash.system.IMEConversionMode") extern enum abstract IMEConversionMode(String) { + var ALPHANUMERIC_FULL; + var ALPHANUMERIC_HALF; + var CHINESE; + var JAPANESE_HIRAGANA; + var JAPANESE_KATAKANA_FULL; + var JAPANESE_KATAKANA_HALF; + var KOREAN; + var UNKNOWN; } diff --git a/std/flash/system/ImageDecodingPolicy.hx b/std/flash/system/ImageDecodingPolicy.hx index caa63053b4b..195b18777df 100644 --- a/std/flash/system/ImageDecodingPolicy.hx +++ b/std/flash/system/ImageDecodingPolicy.hx @@ -1,6 +1,6 @@ package flash.system; -@:fakeEnum(String) extern enum ImageDecodingPolicy { - ON_DEMAND; - ON_LOAD; +@:native("flash.system.ImageDecodingPolicy") extern enum abstract ImageDecodingPolicy(String) { + var ON_DEMAND; + var ON_LOAD; } diff --git a/std/flash/system/LoaderContext.hx b/std/flash/system/LoaderContext.hx index d3c4e32ef81..3f5e6f53176 100644 --- a/std/flash/system/LoaderContext.hx +++ b/std/flash/system/LoaderContext.hx @@ -2,7 +2,7 @@ package flash.system; extern class LoaderContext { @:require(flash10_1) var allowCodeImport : Bool; - @:require(flash10_1) var allowLoadBytesCodeExecution : Bool; + @:flash.property @:require(flash10_1) var allowLoadBytesCodeExecution(get,set) : Bool; var applicationDomain : ApplicationDomain; var checkPolicyFile : Bool; @:require(flash11) var imageDecodingPolicy : ImageDecodingPolicy; @@ -10,4 +10,6 @@ extern class LoaderContext { @:require(flash11) var requestedContentParent : flash.display.DisplayObjectContainer; var securityDomain : SecurityDomain; function new(checkPolicyFile : Bool = false, ?applicationDomain : ApplicationDomain, ?securityDomain : SecurityDomain) : Void; + private function get_allowLoadBytesCodeExecution() : Bool; + private function set_allowLoadBytesCodeExecution(value : Bool) : Bool; } diff --git a/std/flash/system/MessageChannel.hx b/std/flash/system/MessageChannel.hx index 9fcd885f7a1..1a184cd316a 100644 --- a/std/flash/system/MessageChannel.hx +++ b/std/flash/system/MessageChannel.hx @@ -1,9 +1,11 @@ package flash.system; -@:final @:require(flash11_4) extern class MessageChannel extends flash.events.EventDispatcher { - var messageAvailable(default,never) : Bool; - var state(default,never) : MessageChannelState; +@:require(flash11_4) extern final class MessageChannel extends flash.events.EventDispatcher { + @:flash.property var messageAvailable(get,never) : Bool; + @:flash.property var state(get,never) : MessageChannelState; function close() : Void; + private function get_messageAvailable() : Bool; + private function get_state() : MessageChannelState; function receive(blockUntilReceived : Bool = false) : Dynamic; function send(arg : Dynamic, queueLimit : Int = -1) : Void; } diff --git a/std/flash/system/MessageChannelState.hx b/std/flash/system/MessageChannelState.hx index 27d04e81b45..e8459061827 100644 --- a/std/flash/system/MessageChannelState.hx +++ b/std/flash/system/MessageChannelState.hx @@ -1,8 +1,7 @@ package flash.system; -extern class MessageChannelState { - function new() : Void; - static var CLOSED(default,never) : String; - static var CLOSING(default,never) : String; - static var OPEN(default,never) : String; +@:native("flash.system.MessageChannelState") extern enum abstract MessageChannelState(String) { + var CLOSED; + var CLOSING; + var OPEN; } diff --git a/std/flash/system/Security.hx b/std/flash/system/Security.hx index 1c5e586f31a..70db3ef2fb7 100644 --- a/std/flash/system/Security.hx +++ b/std/flash/system/Security.hx @@ -1,19 +1,25 @@ package flash.system; extern class Security { - @:require(flash10_1) static var APPLICATION(default,never) : String; - static var LOCAL_TRUSTED(default,never) : String; - static var LOCAL_WITH_FILE(default,never) : String; - static var LOCAL_WITH_NETWORK(default,never) : String; - static var REMOTE(default,never) : String; - static var disableAVM1Loading : Bool; - static var exactSettings : Bool; - @:require(flash11) static var pageDomain(default,never) : String; - static var sandboxType(default,never) : String; - static function allowDomain(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; - static function allowInsecureDomain(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; - @:require(flash10_1) static function duplicateSandboxBridgeInputArguments(toplevel : Dynamic, args : Array) : Array; - @:require(flash10_1) static function duplicateSandboxBridgeOutputArgument(toplevel : Dynamic, arg : Dynamic) : Dynamic; + @:require(flash10_1) static final APPLICATION : String; + static final LOCAL_TRUSTED : String; + static final LOCAL_WITH_FILE : String; + static final LOCAL_WITH_NETWORK : String; + static final REMOTE : String; + @:flash.property static var disableAVM1Loading(get,set) : Bool; + @:flash.property static var exactSettings(get,set) : Bool; + @:flash.property @:require(flash11) static var pageDomain(get,never) : String; + @:flash.property static var sandboxType(get,never) : String; + static function allowDomain(restArgs : haxe.extern.Rest) : Void; + static function allowInsecureDomain(restArgs : haxe.extern.Rest) : Void; + @:ns("flash.system",internal) @:require(flash10_1) static function duplicateSandboxBridgeInputArguments(toplevel : Dynamic, args : Array) : Array; + @:ns("flash.system",internal) @:require(flash10_1) static function duplicateSandboxBridgeOutputArgument(toplevel : Dynamic, arg : Dynamic) : Dynamic; + private static function get_disableAVM1Loading() : Bool; + private static function get_exactSettings() : Bool; + private static function get_pageDomain() : String; + private static function get_sandboxType() : String; static function loadPolicyFile(url : String) : Void; + private static function set_disableAVM1Loading(value : Bool) : Bool; + private static function set_exactSettings(value : Bool) : Bool; static function showSettings(?panel : SecurityPanel) : Void; } diff --git a/std/flash/system/SecurityDomain.hx b/std/flash/system/SecurityDomain.hx index 0334d7a17bb..ba6b7dbb8fa 100644 --- a/std/flash/system/SecurityDomain.hx +++ b/std/flash/system/SecurityDomain.hx @@ -1,6 +1,8 @@ package flash.system; extern class SecurityDomain { - @:require(flash11_3) var domainID(default,never) : String; - static var currentDomain(default,never) : SecurityDomain; + @:flash.property @:require(flash11_3) var domainID(get,never) : String; + private function get_domainID() : String; + @:flash.property static var currentDomain(get,never) : SecurityDomain; + private static function get_currentDomain() : SecurityDomain; } diff --git a/std/flash/system/SecurityPanel.hx b/std/flash/system/SecurityPanel.hx index caa1db8843d..aa88021d9ab 100644 --- a/std/flash/system/SecurityPanel.hx +++ b/std/flash/system/SecurityPanel.hx @@ -1,11 +1,11 @@ package flash.system; -@:fakeEnum(String) extern enum SecurityPanel { - CAMERA; - DEFAULT; - DISPLAY; - LOCAL_STORAGE; - MICROPHONE; - PRIVACY; - SETTINGS_MANAGER; +@:native("flash.system.SecurityPanel") extern enum abstract SecurityPanel(String) { + var CAMERA; + var DEFAULT; + var DISPLAY; + var LOCAL_STORAGE; + var MICROPHONE; + var PRIVACY; + var SETTINGS_MANAGER; } diff --git a/std/flash/system/System.hx b/std/flash/system/System.hx index 68110693249..ba8c567c705 100644 --- a/std/flash/system/System.hx +++ b/std/flash/system/System.hx @@ -1,19 +1,28 @@ package flash.system; extern class System { - @:require(flash10_1) static var freeMemory(default,never) : Float; - static var ime(default,never) : IME; - @:require(flash10_1) static var privateMemory(default,never) : Float; - @:require(flash11) static var processCPUUsage(default,never) : Float; - static var totalMemory(default,never) : UInt; - @:require(flash10_1) static var totalMemoryNumber(default,never) : Float; - static var useCodePage : Bool; - static var vmVersion(default,never) : String; + @:flash.property @:require(flash10_1) static var freeMemory(get,never) : Float; + @:flash.property static var ime(get,never) : IME; + @:flash.property @:require(flash10_1) static var privateMemory(get,never) : Float; + @:flash.property @:require(flash11) static var processCPUUsage(get,never) : Float; + @:flash.property static var totalMemory(get,never) : UInt; + @:flash.property @:require(flash10_1) static var totalMemoryNumber(get,never) : Float; + @:flash.property static var useCodePage(get,set) : Bool; + @:flash.property static var vmVersion(get,never) : String; @:require(flash10_1) static function disposeXML(node : flash.xml.XML) : Void; static function exit(code : UInt) : Void; static function gc() : Void; + private static function get_freeMemory() : Float; + private static function get_ime() : IME; + private static function get_privateMemory() : Float; + private static function get_processCPUUsage() : Float; + private static function get_totalMemory() : UInt; + private static function get_totalMemoryNumber() : Float; + private static function get_useCodePage() : Bool; + private static function get_vmVersion() : String; static function pause() : Void; @:require(flash11) static function pauseForGCIfCollectionImminent(imminence : Float = 0.75) : Void; static function resume() : Void; static function setClipboard(string : String) : Void; + private static function set_useCodePage(value : Bool) : Bool; } diff --git a/std/flash/system/SystemUpdaterType.hx b/std/flash/system/SystemUpdaterType.hx index 2a3958008cd..fc5ac33fa9d 100644 --- a/std/flash/system/SystemUpdaterType.hx +++ b/std/flash/system/SystemUpdaterType.hx @@ -1,6 +1,6 @@ package flash.system; -@:fakeEnum(String) extern enum SystemUpdaterType { - DRM; - SYSTEM; +@:native("flash.system.SystemUpdaterType") extern enum abstract SystemUpdaterType(String) { + var DRM; + var SYSTEM; } diff --git a/std/flash/system/TouchscreenType.hx b/std/flash/system/TouchscreenType.hx index b6d900bef7a..463911de923 100644 --- a/std/flash/system/TouchscreenType.hx +++ b/std/flash/system/TouchscreenType.hx @@ -1,7 +1,7 @@ package flash.system; -@:fakeEnum(String) extern enum TouchscreenType { - FINGER; - NONE; - STYLUS; +@:native("flash.system.TouchscreenType") extern enum abstract TouchscreenType(String) { + var FINGER; + var NONE; + var STYLUS; } diff --git a/std/flash/system/Worker.hx b/std/flash/system/Worker.hx index bf55de5f9da..6abfee293c1 100644 --- a/std/flash/system/Worker.hx +++ b/std/flash/system/Worker.hx @@ -1,13 +1,17 @@ package flash.system; -@:final @:require(flash11_4) extern class Worker extends flash.events.EventDispatcher { - var isPrimordial(default,never) : Bool; - var state(default,never) : WorkerState; +@:require(flash11_4) extern final class Worker extends flash.events.EventDispatcher { + @:flash.property var isPrimordial(get,never) : Bool; + @:flash.property var state(get,never) : WorkerState; function createMessageChannel(receiver : Worker) : MessageChannel; function getSharedProperty(key : String) : Dynamic; + private function get_isPrimordial() : Bool; + private function get_state() : WorkerState; function setSharedProperty(key : String, value : Dynamic) : Void; function start() : Void; function terminate() : Bool; - static var current(default,never) : Worker; - static var isSupported(default,never) : Bool; + @:flash.property static var current(get,never) : Worker; + @:flash.property static var isSupported(get,never) : Bool; + private static function get_current() : Worker; + private static function get_isSupported() : Bool; } diff --git a/std/flash/system/WorkerDomain.hx b/std/flash/system/WorkerDomain.hx index 806db4a08a9..a6070e4b24d 100644 --- a/std/flash/system/WorkerDomain.hx +++ b/std/flash/system/WorkerDomain.hx @@ -1,9 +1,11 @@ package flash.system; -@:final @:require(flash11_4) extern class WorkerDomain { +@:require(flash11_4) extern final class WorkerDomain { function new() : Void; function createWorker(swf : flash.utils.ByteArray, giveAppPrivileges : Bool = false) : Worker; function listWorkers() : flash.Vector; - static var current(default,never) : WorkerDomain; - static var isSupported(default,never) : Bool; + @:flash.property static var current(get,never) : WorkerDomain; + @:flash.property static var isSupported(get,never) : Bool; + private static function get_current() : WorkerDomain; + private static function get_isSupported() : Bool; } diff --git a/std/flash/system/WorkerState.hx b/std/flash/system/WorkerState.hx index 10828ff32c6..ed3ab4e030d 100644 --- a/std/flash/system/WorkerState.hx +++ b/std/flash/system/WorkerState.hx @@ -1,7 +1,7 @@ package flash.system; -@:fakeEnum(String) extern enum WorkerState { - NEW; - RUNNING; - TERMINATED; +@:native("flash.system.WorkerState") extern enum abstract WorkerState(String) { + var NEW; + var RUNNING; + var TERMINATED; } diff --git a/std/flash/text/AntiAliasType.hx b/std/flash/text/AntiAliasType.hx index fdb8610b2a3..8ccc1c5c61f 100644 --- a/std/flash/text/AntiAliasType.hx +++ b/std/flash/text/AntiAliasType.hx @@ -1,6 +1,6 @@ package flash.text; -@:fakeEnum(String) extern enum AntiAliasType { - ADVANCED; - NORMAL; +@:native("flash.text.AntiAliasType") extern enum abstract AntiAliasType(String) { + var ADVANCED; + var NORMAL; } diff --git a/std/flash/text/CSMSettings.hx b/std/flash/text/CSMSettings.hx index 2ff3e9f28b3..4ea19e77553 100644 --- a/std/flash/text/CSMSettings.hx +++ b/std/flash/text/CSMSettings.hx @@ -1,6 +1,6 @@ package flash.text; -@:final extern class CSMSettings { +extern final class CSMSettings { var fontSize : Float; var insideCutoff : Float; var outsideCutoff : Float; diff --git a/std/flash/text/Font.hx b/std/flash/text/Font.hx index 6a30c0892c6..4e974f4dd23 100644 --- a/std/flash/text/Font.hx +++ b/std/flash/text/Font.hx @@ -1,10 +1,13 @@ package flash.text; extern class Font { - var fontName(default,never) : String; - var fontStyle(default,never) : FontStyle; - var fontType(default,never) : FontType; + @:flash.property var fontName(get,never) : String; + @:flash.property var fontStyle(get,never) : FontStyle; + @:flash.property var fontType(get,never) : FontType; function new() : Void; + private function get_fontName() : String; + private function get_fontStyle() : FontStyle; + private function get_fontType() : FontType; function hasGlyphs(str : String) : Bool; static function enumerateFonts(enumerateDeviceFonts : Bool = false) : Array; static function registerFont(font : Class) : Void; diff --git a/std/flash/text/FontStyle.hx b/std/flash/text/FontStyle.hx index d59e9a529c4..2c7242ebab7 100644 --- a/std/flash/text/FontStyle.hx +++ b/std/flash/text/FontStyle.hx @@ -1,8 +1,8 @@ package flash.text; -@:fakeEnum(String) extern enum FontStyle { - BOLD; - BOLD_ITALIC; - ITALIC; - REGULAR; +@:native("flash.text.FontStyle") extern enum abstract FontStyle(String) { + var BOLD; + var BOLD_ITALIC; + var ITALIC; + var REGULAR; } diff --git a/std/flash/text/FontType.hx b/std/flash/text/FontType.hx index d83a915a311..9c8cef0f0ed 100644 --- a/std/flash/text/FontType.hx +++ b/std/flash/text/FontType.hx @@ -1,7 +1,7 @@ package flash.text; -@:fakeEnum(String) extern enum FontType { - DEVICE; - EMBEDDED; - EMBEDDED_CFF; +@:native("flash.text.FontType") extern enum abstract FontType(String) { + var DEVICE; + var EMBEDDED; + var EMBEDDED_CFF; } diff --git a/std/flash/text/GridFitType.hx b/std/flash/text/GridFitType.hx index e4e754591db..f24bf93adcd 100644 --- a/std/flash/text/GridFitType.hx +++ b/std/flash/text/GridFitType.hx @@ -1,7 +1,7 @@ package flash.text; -@:fakeEnum(String) extern enum GridFitType { - NONE; - PIXEL; - SUBPIXEL; +@:native("flash.text.GridFitType") extern enum abstract GridFitType(String) { + var NONE; + var PIXEL; + var SUBPIXEL; } diff --git a/std/flash/text/StaticText.hx b/std/flash/text/StaticText.hx index 01d7e7c0e50..1b9c995f4cb 100644 --- a/std/flash/text/StaticText.hx +++ b/std/flash/text/StaticText.hx @@ -1,6 +1,7 @@ package flash.text; -@:final extern class StaticText extends flash.display.DisplayObject { - var text(default,never) : String; +extern final class StaticText extends flash.display.DisplayObject { + @:flash.property var text(get,never) : String; function new() : Void; + private function get_text() : String; } diff --git a/std/flash/text/StyleSheet.hx b/std/flash/text/StyleSheet.hx index 10cb9a44039..443bd0a9642 100644 --- a/std/flash/text/StyleSheet.hx +++ b/std/flash/text/StyleSheet.hx @@ -1,10 +1,11 @@ package flash.text; extern class StyleSheet extends flash.events.EventDispatcher implements Dynamic { - var styleNames(default,never) : Array; + @:flash.property var styleNames(get,never) : Array; function new() : Void; function clear() : Void; function getStyle(styleName : String) : flash.utils.Object; + private function get_styleNames() : Array; function parseCSS(CSSText : String) : Void; function setStyle(styleName : String, styleObject : flash.utils.Object) : Void; function transform(formatObject : flash.utils.Object) : TextFormat; diff --git a/std/flash/text/TextColorType.hx b/std/flash/text/TextColorType.hx index fb7db4342d4..804dab9abd6 100644 --- a/std/flash/text/TextColorType.hx +++ b/std/flash/text/TextColorType.hx @@ -1,6 +1,6 @@ package flash.text; -@:fakeEnum(String) extern enum TextColorType { - DARK_COLOR; - LIGHT_COLOR; +@:native("flash.text.TextColorType") extern enum abstract TextColorType(String) { + var DARK_COLOR; + var LIGHT_COLOR; } diff --git a/std/flash/text/TextDisplayMode.hx b/std/flash/text/TextDisplayMode.hx index 84878cd11fe..0a0cd651e9b 100644 --- a/std/flash/text/TextDisplayMode.hx +++ b/std/flash/text/TextDisplayMode.hx @@ -1,7 +1,7 @@ package flash.text; -@:fakeEnum(String) extern enum TextDisplayMode { - CRT; - DEFAULT; - LCD; +@:native("flash.text.TextDisplayMode") extern enum abstract TextDisplayMode(String) { + var CRT; + var DEFAULT; + var LCD; } diff --git a/std/flash/text/TextField.hx b/std/flash/text/TextField.hx index bfdba610582..487be74918b 100644 --- a/std/flash/text/TextField.hx +++ b/std/flash/text/TextField.hx @@ -1,49 +1,49 @@ package flash.text; extern class TextField extends flash.display.InteractiveObject { - var alwaysShowSelection : Bool; - var antiAliasType : AntiAliasType; - var autoSize : TextFieldAutoSize; - var background : Bool; - var backgroundColor : UInt; - var border : Bool; - var borderColor : UInt; - var bottomScrollV(default,never) : Int; - var caretIndex(default,never) : Int; - var condenseWhite : Bool; - var defaultTextFormat : TextFormat; - var displayAsPassword : Bool; - var embedFonts : Bool; - var gridFitType : GridFitType; - var htmlText : String; - var length(default,never) : Int; - var maxChars : Int; - var maxScrollH(default,never) : Int; - var maxScrollV(default,never) : Int; - var mouseWheelEnabled : Bool; - var multiline : Bool; - var numLines(default,never) : Int; - var restrict : String; - var scrollH : Int; - var scrollV : Int; - var selectable : Bool; - var selectedText(default,never) : String; - var selectionBeginIndex(default,never) : Int; - var selectionEndIndex(default,never) : Int; - var sharpness : Float; - var styleSheet : StyleSheet; - var text : String; - var textColor : UInt; - var textHeight(default,never) : Float; - @:require(flash11) var textInteractionMode(default,never) : TextInteractionMode; - var textWidth(default,never) : Float; - var thickness : Float; - var type : TextFieldType; - var useRichTextClipboard : Bool; - var wordWrap : Bool; + @:flash.property var alwaysShowSelection(get,set) : Bool; + @:flash.property var antiAliasType(get,set) : AntiAliasType; + @:flash.property var autoSize(get,set) : TextFieldAutoSize; + @:flash.property var background(get,set) : Bool; + @:flash.property var backgroundColor(get,set) : UInt; + @:flash.property var border(get,set) : Bool; + @:flash.property var borderColor(get,set) : UInt; + @:flash.property var bottomScrollV(get,never) : Int; + @:flash.property var caretIndex(get,never) : Int; + @:flash.property var condenseWhite(get,set) : Bool; + @:flash.property var defaultTextFormat(get,set) : TextFormat; + @:flash.property var displayAsPassword(get,set) : Bool; + @:flash.property var embedFonts(get,set) : Bool; + @:flash.property var gridFitType(get,set) : GridFitType; + @:flash.property var htmlText(get,set) : String; + @:flash.property var length(get,never) : Int; + @:flash.property var maxChars(get,set) : Int; + @:flash.property var maxScrollH(get,never) : Int; + @:flash.property var maxScrollV(get,never) : Int; + @:flash.property var mouseWheelEnabled(get,set) : Bool; + @:flash.property var multiline(get,set) : Bool; + @:flash.property var numLines(get,never) : Int; + @:flash.property var restrict(get,set) : String; + @:flash.property var scrollH(get,set) : Int; + @:flash.property var scrollV(get,set) : Int; + @:flash.property var selectable(get,set) : Bool; + @:flash.property var selectedText(get,never) : String; + @:flash.property var selectionBeginIndex(get,never) : Int; + @:flash.property var selectionEndIndex(get,never) : Int; + @:flash.property var sharpness(get,set) : Float; + @:flash.property var styleSheet(get,set) : StyleSheet; + @:flash.property var text(get,set) : String; + @:flash.property var textColor(get,set) : UInt; + @:flash.property var textHeight(get,never) : Float; + @:flash.property @:require(flash11) var textInteractionMode(get,never) : TextInteractionMode; + @:flash.property var textWidth(get,never) : Float; + @:flash.property var thickness(get,set) : Float; + @:flash.property var type(get,set) : TextFieldType; + @:flash.property var useRichTextClipboard(get,set) : Bool; + @:flash.property var wordWrap(get,set) : Bool; function new() : Void; function appendText(newText : String) : Void; - function copyRichText() : String; + @:ns("flash.text",internal) function copyRichText() : String; function getCharBoundaries(charIndex : Int) : flash.geom.Rectangle; function getCharIndexAtPoint(x : Float, y : Float) : Int; function getFirstCharInParagraph(charIndex : Int) : Int; @@ -59,11 +59,79 @@ extern class TextField extends flash.display.InteractiveObject { function getTextFormat(beginIndex : Int = -1, endIndex : Int = -1) : TextFormat; function getTextRuns(beginIndex : Int = 0, endIndex : Int = 2147483647) : Array; function getXMLText(beginIndex : Int = 0, endIndex : Int = 2147483647) : String; + private function get_alwaysShowSelection() : Bool; + private function get_antiAliasType() : AntiAliasType; + private function get_autoSize() : TextFieldAutoSize; + private function get_background() : Bool; + private function get_backgroundColor() : UInt; + private function get_border() : Bool; + private function get_borderColor() : UInt; + private function get_bottomScrollV() : Int; + private function get_caretIndex() : Int; + private function get_condenseWhite() : Bool; + private function get_defaultTextFormat() : TextFormat; + private function get_displayAsPassword() : Bool; + private function get_embedFonts() : Bool; + private function get_gridFitType() : GridFitType; + private function get_htmlText() : String; + private function get_length() : Int; + private function get_maxChars() : Int; + private function get_maxScrollH() : Int; + private function get_maxScrollV() : Int; + private function get_mouseWheelEnabled() : Bool; + private function get_multiline() : Bool; + private function get_numLines() : Int; + private function get_restrict() : String; + private function get_scrollH() : Int; + private function get_scrollV() : Int; + private function get_selectable() : Bool; + private function get_selectedText() : String; + private function get_selectionBeginIndex() : Int; + private function get_selectionEndIndex() : Int; + private function get_sharpness() : Float; + private function get_styleSheet() : StyleSheet; + private function get_text() : String; + private function get_textColor() : UInt; + private function get_textHeight() : Float; + private function get_textInteractionMode() : TextInteractionMode; + private function get_textWidth() : Float; + private function get_thickness() : Float; + private function get_type() : TextFieldType; + private function get_useRichTextClipboard() : Bool; + private function get_wordWrap() : Bool; function insertXMLText(beginIndex : Int, endIndex : Int, richText : String, pasting : Bool = false) : Void; - function pasteRichText(richText : String) : Bool; + @:ns("flash.text",internal) function pasteRichText(richText : String) : Bool; function replaceSelectedText(value : String) : Void; function replaceText(beginIndex : Int, endIndex : Int, newText : String) : Void; function setSelection(beginIndex : Int, endIndex : Int) : Void; function setTextFormat(format : TextFormat, beginIndex : Int = -1, endIndex : Int = -1) : Void; + private function set_alwaysShowSelection(value : Bool) : Bool; + private function set_antiAliasType(value : AntiAliasType) : AntiAliasType; + private function set_autoSize(value : TextFieldAutoSize) : TextFieldAutoSize; + private function set_background(value : Bool) : Bool; + private function set_backgroundColor(value : UInt) : UInt; + private function set_border(value : Bool) : Bool; + private function set_borderColor(value : UInt) : UInt; + private function set_condenseWhite(value : Bool) : Bool; + private function set_defaultTextFormat(value : TextFormat) : TextFormat; + private function set_displayAsPassword(value : Bool) : Bool; + private function set_embedFonts(value : Bool) : Bool; + private function set_gridFitType(value : GridFitType) : GridFitType; + private function set_htmlText(value : String) : String; + private function set_maxChars(value : Int) : Int; + private function set_mouseWheelEnabled(value : Bool) : Bool; + private function set_multiline(value : Bool) : Bool; + private function set_restrict(value : String) : String; + private function set_scrollH(value : Int) : Int; + private function set_scrollV(value : Int) : Int; + private function set_selectable(value : Bool) : Bool; + private function set_sharpness(value : Float) : Float; + private function set_styleSheet(value : StyleSheet) : StyleSheet; + private function set_text(value : String) : String; + private function set_textColor(value : UInt) : UInt; + private function set_thickness(value : Float) : Float; + private function set_type(value : TextFieldType) : TextFieldType; + private function set_useRichTextClipboard(value : Bool) : Bool; + private function set_wordWrap(value : Bool) : Bool; @:require(flash10) static function isFontCompatible(fontName : String, fontStyle : String) : Bool; } diff --git a/std/flash/text/TextFieldAutoSize.hx b/std/flash/text/TextFieldAutoSize.hx index ce2da0bb37f..67a59a1c9b7 100644 --- a/std/flash/text/TextFieldAutoSize.hx +++ b/std/flash/text/TextFieldAutoSize.hx @@ -1,8 +1,8 @@ package flash.text; -@:fakeEnum(String) extern enum TextFieldAutoSize { - CENTER; - LEFT; - NONE; - RIGHT; +@:native("flash.text.TextFieldAutoSize") extern enum abstract TextFieldAutoSize(String) { + var CENTER; + var LEFT; + var NONE; + var RIGHT; } diff --git a/std/flash/text/TextFieldType.hx b/std/flash/text/TextFieldType.hx index d07365589b3..7580dc29f83 100644 --- a/std/flash/text/TextFieldType.hx +++ b/std/flash/text/TextFieldType.hx @@ -1,6 +1,6 @@ package flash.text; -@:fakeEnum(String) extern enum TextFieldType { - DYNAMIC; - INPUT; +@:native("flash.text.TextFieldType") extern enum abstract TextFieldType(String) { + var DYNAMIC; + var INPUT; } diff --git a/std/flash/text/TextFormat.hx b/std/flash/text/TextFormat.hx index 08d6d455987..277755ec48b 100644 --- a/std/flash/text/TextFormat.hx +++ b/std/flash/text/TextFormat.hx @@ -1,24 +1,62 @@ package flash.text; extern class TextFormat { - var align : TextFormatAlign; - var blockIndent : Null; - var bold : Null; - var bullet : Null; - var color : Null; - var display : TextFormatDisplay; - var font : String; - var indent : Null; - var italic : Null; - var kerning : Null; - var leading : Null; - var leftMargin : Null; - var letterSpacing : Null; - var rightMargin : Null; - var size : Null; - var tabStops : Array; - var target : String; - var underline : Null; - var url : String; + @:flash.property var align(get,set) : TextFormatAlign; + @:flash.property var blockIndent(get,set) : Null; + @:flash.property var bold(get,set) : Null; + @:flash.property var bullet(get,set) : Null; + @:flash.property var color(get,set) : Null; + @:flash.property var display(get,set) : TextFormatDisplay; + @:flash.property var font(get,set) : String; + @:flash.property var indent(get,set) : Null; + @:flash.property var italic(get,set) : Null; + @:flash.property var kerning(get,set) : Null; + @:flash.property var leading(get,set) : Null; + @:flash.property var leftMargin(get,set) : Null; + @:flash.property var letterSpacing(get,set) : Null; + @:flash.property var rightMargin(get,set) : Null; + @:flash.property var size(get,set) : Null; + @:flash.property var tabStops(get,set) : Array; + @:flash.property var target(get,set) : String; + @:flash.property var underline(get,set) : Null; + @:flash.property var url(get,set) : String; function new(?font : String, size : Null = 0, color : Null = 0, bold : Null = false, italic : Null = false, underline : Null = false, ?url : String, ?target : String, ?align : TextFormatAlign, leftMargin : Null = 0, rightMargin : Null = 0, indent : Null = 0, leading : Null = 0) : Void; + private function get_align() : TextFormatAlign; + private function get_blockIndent() : Null; + private function get_bold() : Null; + private function get_bullet() : Null; + private function get_color() : Null; + private function get_display() : TextFormatDisplay; + private function get_font() : String; + private function get_indent() : Null; + private function get_italic() : Null; + private function get_kerning() : Null; + private function get_leading() : Null; + private function get_leftMargin() : Null; + private function get_letterSpacing() : Null; + private function get_rightMargin() : Null; + private function get_size() : Null; + private function get_tabStops() : Array; + private function get_target() : String; + private function get_underline() : Null; + private function get_url() : String; + private function set_align(value : TextFormatAlign) : TextFormatAlign; + private function set_blockIndent(value : Null) : Null; + private function set_bold(value : Null) : Null; + private function set_bullet(value : Null) : Null; + private function set_color(value : Null) : Null; + private function set_display(value : TextFormatDisplay) : TextFormatDisplay; + private function set_font(value : String) : String; + private function set_indent(value : Null) : Null; + private function set_italic(value : Null) : Null; + private function set_kerning(value : Null) : Null; + private function set_leading(value : Null) : Null; + private function set_leftMargin(value : Null) : Null; + private function set_letterSpacing(value : Null) : Null; + private function set_rightMargin(value : Null) : Null; + private function set_size(value : Null) : Null; + private function set_tabStops(value : Array) : Array; + private function set_target(value : String) : String; + private function set_underline(value : Null) : Null; + private function set_url(value : String) : String; } diff --git a/std/flash/text/TextFormatAlign.hx b/std/flash/text/TextFormatAlign.hx index b8f52f828c8..b826cab3aa2 100644 --- a/std/flash/text/TextFormatAlign.hx +++ b/std/flash/text/TextFormatAlign.hx @@ -1,10 +1,10 @@ package flash.text; -@:fakeEnum(String) extern enum TextFormatAlign { - CENTER; - END; - JUSTIFY; - LEFT; - RIGHT; - START; +@:native("flash.text.TextFormatAlign") extern enum abstract TextFormatAlign(String) { + var CENTER; + var END; + var JUSTIFY; + var LEFT; + var RIGHT; + var START; } diff --git a/std/flash/text/TextFormatDisplay.hx b/std/flash/text/TextFormatDisplay.hx index 27987d271d5..917d36fb796 100644 --- a/std/flash/text/TextFormatDisplay.hx +++ b/std/flash/text/TextFormatDisplay.hx @@ -1,6 +1,6 @@ package flash.text; -@:fakeEnum(String) extern enum TextFormatDisplay { - BLOCK; - INLINE; +@:native("flash.text.TextFormatDisplay") extern enum abstract TextFormatDisplay(String) { + var BLOCK; + var INLINE; } diff --git a/std/flash/text/TextInteractionMode.hx b/std/flash/text/TextInteractionMode.hx index c4a6f824463..3724886085c 100644 --- a/std/flash/text/TextInteractionMode.hx +++ b/std/flash/text/TextInteractionMode.hx @@ -1,6 +1,6 @@ package flash.text; -@:fakeEnum(String) extern enum TextInteractionMode { - NORMAL; - SELECTION; +@:native("flash.text.TextInteractionMode") extern enum abstract TextInteractionMode(String) { + var NORMAL; + var SELECTION; } diff --git a/std/flash/text/TextRenderer.hx b/std/flash/text/TextRenderer.hx index 7de44e9073a..db747a9f8a2 100644 --- a/std/flash/text/TextRenderer.hx +++ b/std/flash/text/TextRenderer.hx @@ -1,8 +1,14 @@ package flash.text; extern class TextRenderer { - static var antiAliasType : AntiAliasType; - static var displayMode : TextDisplayMode; - static var maxLevel : Int; + @:flash.property static var antiAliasType(get,set) : AntiAliasType; + @:flash.property static var displayMode(get,set) : TextDisplayMode; + @:flash.property static var maxLevel(get,set) : Int; + private static function get_antiAliasType() : AntiAliasType; + private static function get_displayMode() : TextDisplayMode; + private static function get_maxLevel() : Int; static function setAdvancedAntiAliasingTable(fontName : String, fontStyle : FontStyle, colorType : TextColorType, advancedAntiAliasingTable : Array) : Void; + private static function set_antiAliasType(value : AntiAliasType) : AntiAliasType; + private static function set_displayMode(value : TextDisplayMode) : TextDisplayMode; + private static function set_maxLevel(value : Int) : Int; } diff --git a/std/flash/text/TextSnapshot.hx b/std/flash/text/TextSnapshot.hx index 80598c0d243..cea8b3064b4 100644 --- a/std/flash/text/TextSnapshot.hx +++ b/std/flash/text/TextSnapshot.hx @@ -1,13 +1,14 @@ package flash.text; extern class TextSnapshot { - var charCount(default,never) : Int; + @:flash.property var charCount(get,never) : Int; function new() : Void; function findText(beginIndex : Int, textToFind : String, caseSensitive : Bool) : Int; function getSelected(beginIndex : Int, endIndex : Int) : Bool; function getSelectedText(includeLineEndings : Bool = false) : String; function getText(beginIndex : Int, endIndex : Int, includeLineEndings : Bool = false) : String; function getTextRunInfo(beginIndex : Int, endIndex : Int) : Array; + private function get_charCount() : Int; function hitTestTextNearPos(x : Float, y : Float, maxDistance : Float = 0) : Float; function setSelectColor(hexColor : UInt = 16776960) : Void; function setSelected(beginIndex : Int, endIndex : Int, select : Bool) : Void; diff --git a/std/flash/text/engine/BreakOpportunity.hx b/std/flash/text/engine/BreakOpportunity.hx index 8def3901e10..0b5d515fa78 100644 --- a/std/flash/text/engine/BreakOpportunity.hx +++ b/std/flash/text/engine/BreakOpportunity.hx @@ -1,8 +1,8 @@ package flash.text.engine; -@:fakeEnum(String) extern enum BreakOpportunity { - ALL; - ANY; - AUTO; - NONE; +@:native("flash.text.engine.BreakOpportunity") extern enum abstract BreakOpportunity(String) { + var ALL; + var ANY; + var AUTO; + var NONE; } diff --git a/std/flash/text/engine/CFFHinting.hx b/std/flash/text/engine/CFFHinting.hx index be6a43e52c0..09d2abf7834 100644 --- a/std/flash/text/engine/CFFHinting.hx +++ b/std/flash/text/engine/CFFHinting.hx @@ -1,6 +1,6 @@ package flash.text.engine; -@:fakeEnum(String) extern enum CFFHinting { - HORIZONTAL_STEM; - NONE; +@:native("flash.text.engine.CFFHinting") extern enum abstract CFFHinting(String) { + var HORIZONTAL_STEM; + var NONE; } diff --git a/std/flash/text/engine/ContentElement.hx b/std/flash/text/engine/ContentElement.hx index c6cb5fbfd33..b4e61486d07 100644 --- a/std/flash/text/engine/ContentElement.hx +++ b/std/flash/text/engine/ContentElement.hx @@ -1,15 +1,26 @@ package flash.text.engine; extern class ContentElement { - var elementFormat : ElementFormat; - var eventMirror : flash.events.EventDispatcher; - var groupElement(default,never) : GroupElement; - var rawText(default,never) : String; - var text(default,never) : String; - var textBlock(default,never) : TextBlock; - var textBlockBeginIndex(default,never) : Int; - var textRotation : TextRotation; + @:flash.property var elementFormat(get,set) : ElementFormat; + @:flash.property var eventMirror(get,set) : flash.events.EventDispatcher; + @:flash.property var groupElement(get,never) : GroupElement; + @:flash.property var rawText(get,never) : String; + @:flash.property var text(get,never) : String; + @:flash.property var textBlock(get,never) : TextBlock; + @:flash.property var textBlockBeginIndex(get,never) : Int; + @:flash.property var textRotation(get,set) : TextRotation; var userData : Dynamic; function new(?elementFormat : ElementFormat, ?eventMirror : flash.events.EventDispatcher, ?textRotation : TextRotation) : Void; - static var GRAPHIC_ELEMENT(default,never) : UInt; + private function get_elementFormat() : ElementFormat; + private function get_eventMirror() : flash.events.EventDispatcher; + private function get_groupElement() : GroupElement; + private function get_rawText() : String; + private function get_text() : String; + private function get_textBlock() : TextBlock; + private function get_textBlockBeginIndex() : Int; + private function get_textRotation() : TextRotation; + private function set_elementFormat(value : ElementFormat) : ElementFormat; + private function set_eventMirror(value : flash.events.EventDispatcher) : flash.events.EventDispatcher; + private function set_textRotation(value : TextRotation) : TextRotation; + static final GRAPHIC_ELEMENT : UInt; } diff --git a/std/flash/text/engine/DigitCase.hx b/std/flash/text/engine/DigitCase.hx index 937d336c5b6..598d602fe24 100644 --- a/std/flash/text/engine/DigitCase.hx +++ b/std/flash/text/engine/DigitCase.hx @@ -1,7 +1,7 @@ package flash.text.engine; -@:fakeEnum(String) extern enum DigitCase { - DEFAULT; - LINING; - OLD_STYLE; +@:native("flash.text.engine.DigitCase") extern enum abstract DigitCase(String) { + var DEFAULT; + var LINING; + var OLD_STYLE; } diff --git a/std/flash/text/engine/DigitWidth.hx b/std/flash/text/engine/DigitWidth.hx index bcbf801f322..46cbc83326b 100644 --- a/std/flash/text/engine/DigitWidth.hx +++ b/std/flash/text/engine/DigitWidth.hx @@ -1,7 +1,7 @@ package flash.text.engine; -@:fakeEnum(String) extern enum DigitWidth { - DEFAULT; - PROPORTIONAL; - TABULAR; +@:native("flash.text.engine.DigitWidth") extern enum abstract DigitWidth(String) { + var DEFAULT; + var PROPORTIONAL; + var TABULAR; } diff --git a/std/flash/text/engine/EastAsianJustifier.hx b/std/flash/text/engine/EastAsianJustifier.hx index cb6a554dd01..57b8136b477 100644 --- a/std/flash/text/engine/EastAsianJustifier.hx +++ b/std/flash/text/engine/EastAsianJustifier.hx @@ -1,7 +1,11 @@ package flash.text.engine; -@:final extern class EastAsianJustifier extends TextJustifier { - var composeTrailingIdeographicSpaces : Bool; - var justificationStyle : JustificationStyle; +extern final class EastAsianJustifier extends TextJustifier { + @:flash.property var composeTrailingIdeographicSpaces(get,set) : Bool; + @:flash.property var justificationStyle(get,set) : JustificationStyle; function new(?locale : String, ?lineJustification : LineJustification, ?justificationStyle : JustificationStyle) : Void; + private function get_composeTrailingIdeographicSpaces() : Bool; + private function get_justificationStyle() : JustificationStyle; + private function set_composeTrailingIdeographicSpaces(value : Bool) : Bool; + private function set_justificationStyle(value : JustificationStyle) : JustificationStyle; } diff --git a/std/flash/text/engine/ElementFormat.hx b/std/flash/text/engine/ElementFormat.hx index bbb986a4d87..6c139a8c0ee 100644 --- a/std/flash/text/engine/ElementFormat.hx +++ b/std/flash/text/engine/ElementFormat.hx @@ -1,25 +1,61 @@ package flash.text.engine; -@:final extern class ElementFormat { - var alignmentBaseline : TextBaseline; - var alpha : Float; - var baselineShift : Float; - var breakOpportunity : BreakOpportunity; - var color : UInt; - var digitCase : DigitCase; - var digitWidth : DigitWidth; - var dominantBaseline : TextBaseline; - var fontDescription : FontDescription; - var fontSize : Float; - var kerning : Kerning; - var ligatureLevel : LigatureLevel; - var locale : String; - var locked : Bool; - var textRotation : TextRotation; - var trackingLeft : Float; - var trackingRight : Float; - var typographicCase : TypographicCase; +extern final class ElementFormat { + @:flash.property var alignmentBaseline(get,set) : TextBaseline; + @:flash.property var alpha(get,set) : Float; + @:flash.property var baselineShift(get,set) : Float; + @:flash.property var breakOpportunity(get,set) : BreakOpportunity; + @:flash.property var color(get,set) : UInt; + @:flash.property var digitCase(get,set) : DigitCase; + @:flash.property var digitWidth(get,set) : DigitWidth; + @:flash.property var dominantBaseline(get,set) : TextBaseline; + @:flash.property var fontDescription(get,set) : FontDescription; + @:flash.property var fontSize(get,set) : Float; + @:flash.property var kerning(get,set) : Kerning; + @:flash.property var ligatureLevel(get,set) : LigatureLevel; + @:flash.property var locale(get,set) : String; + @:flash.property var locked(get,set) : Bool; + @:flash.property var textRotation(get,set) : TextRotation; + @:flash.property var trackingLeft(get,set) : Float; + @:flash.property var trackingRight(get,set) : Float; + @:flash.property var typographicCase(get,set) : TypographicCase; function new(?fontDescription : FontDescription, fontSize : Float = 12, color : UInt = 0, alpha : Float = 1, ?textRotation : TextRotation, ?dominantBaseline : TextBaseline, ?alignmentBaseline : TextBaseline, baselineShift : Float = 0, ?kerning : Kerning, trackingRight : Float = 0, trackingLeft : Float = 0, ?locale : String, ?breakOpportunity : BreakOpportunity, ?digitCase : DigitCase, ?digitWidth : DigitWidth, ?ligatureLevel : LigatureLevel, ?typographicCase : TypographicCase) : Void; function clone() : ElementFormat; function getFontMetrics() : FontMetrics; + private function get_alignmentBaseline() : TextBaseline; + private function get_alpha() : Float; + private function get_baselineShift() : Float; + private function get_breakOpportunity() : BreakOpportunity; + private function get_color() : UInt; + private function get_digitCase() : DigitCase; + private function get_digitWidth() : DigitWidth; + private function get_dominantBaseline() : TextBaseline; + private function get_fontDescription() : FontDescription; + private function get_fontSize() : Float; + private function get_kerning() : Kerning; + private function get_ligatureLevel() : LigatureLevel; + private function get_locale() : String; + private function get_locked() : Bool; + private function get_textRotation() : TextRotation; + private function get_trackingLeft() : Float; + private function get_trackingRight() : Float; + private function get_typographicCase() : TypographicCase; + private function set_alignmentBaseline(value : TextBaseline) : TextBaseline; + private function set_alpha(value : Float) : Float; + private function set_baselineShift(value : Float) : Float; + private function set_breakOpportunity(value : BreakOpportunity) : BreakOpportunity; + private function set_color(value : UInt) : UInt; + private function set_digitCase(value : DigitCase) : DigitCase; + private function set_digitWidth(value : DigitWidth) : DigitWidth; + private function set_dominantBaseline(value : TextBaseline) : TextBaseline; + private function set_fontDescription(value : FontDescription) : FontDescription; + private function set_fontSize(value : Float) : Float; + private function set_kerning(value : Kerning) : Kerning; + private function set_ligatureLevel(value : LigatureLevel) : LigatureLevel; + private function set_locale(value : String) : String; + private function set_locked(value : Bool) : Bool; + private function set_textRotation(value : TextRotation) : TextRotation; + private function set_trackingLeft(value : Float) : Float; + private function set_trackingRight(value : Float) : Float; + private function set_typographicCase(value : TypographicCase) : TypographicCase; } diff --git a/std/flash/text/engine/FontDescription.hx b/std/flash/text/engine/FontDescription.hx index 3e91c4e2e11..2954df1e2ef 100644 --- a/std/flash/text/engine/FontDescription.hx +++ b/std/flash/text/engine/FontDescription.hx @@ -1,15 +1,29 @@ package flash.text.engine; -@:final extern class FontDescription { - var cffHinting : CFFHinting; - var fontLookup : FontLookup; - var fontName : String; - var fontPosture : FontPosture; - var fontWeight : FontWeight; - var locked : Bool; - var renderingMode : RenderingMode; +extern final class FontDescription { + @:flash.property var cffHinting(get,set) : CFFHinting; + @:flash.property var fontLookup(get,set) : FontLookup; + @:flash.property var fontName(get,set) : String; + @:flash.property var fontPosture(get,set) : FontPosture; + @:flash.property var fontWeight(get,set) : FontWeight; + @:flash.property var locked(get,set) : Bool; + @:flash.property var renderingMode(get,set) : RenderingMode; function new(?fontName : String, ?fontWeight : FontWeight, ?fontPosture : FontPosture, ?fontLookup : FontLookup, ?renderingMode : RenderingMode, ?cffHinting : CFFHinting) : Void; function clone() : FontDescription; + private function get_cffHinting() : CFFHinting; + private function get_fontLookup() : FontLookup; + private function get_fontName() : String; + private function get_fontPosture() : FontPosture; + private function get_fontWeight() : FontWeight; + private function get_locked() : Bool; + private function get_renderingMode() : RenderingMode; + private function set_cffHinting(value : CFFHinting) : CFFHinting; + private function set_fontLookup(value : FontLookup) : FontLookup; + private function set_fontName(value : String) : String; + private function set_fontPosture(value : FontPosture) : FontPosture; + private function set_fontWeight(value : FontWeight) : FontWeight; + private function set_locked(value : Bool) : Bool; + private function set_renderingMode(value : RenderingMode) : RenderingMode; @:require(flash10_1) static function isDeviceFontCompatible(fontName : String, fontWeight : FontWeight, fontPosture : FontPosture) : Bool; static function isFontCompatible(fontName : String, fontWeight : FontWeight, fontPosture : FontPosture) : Bool; } diff --git a/std/flash/text/engine/FontLookup.hx b/std/flash/text/engine/FontLookup.hx index dce00c8ee0c..38de1f56045 100644 --- a/std/flash/text/engine/FontLookup.hx +++ b/std/flash/text/engine/FontLookup.hx @@ -1,6 +1,6 @@ package flash.text.engine; -@:fakeEnum(String) extern enum FontLookup { - DEVICE; - EMBEDDED_CFF; +@:native("flash.text.engine.FontLookup") extern enum abstract FontLookup(String) { + var DEVICE; + var EMBEDDED_CFF; } diff --git a/std/flash/text/engine/FontMetrics.hx b/std/flash/text/engine/FontMetrics.hx index e7e9aa2a4c6..5b184bac49c 100644 --- a/std/flash/text/engine/FontMetrics.hx +++ b/std/flash/text/engine/FontMetrics.hx @@ -1,6 +1,6 @@ package flash.text.engine; -@:final extern class FontMetrics { +extern final class FontMetrics { var emBox : flash.geom.Rectangle; var lineGap : Float; var strikethroughOffset : Float; diff --git a/std/flash/text/engine/FontPosture.hx b/std/flash/text/engine/FontPosture.hx index 7d364851f4c..e771f395263 100644 --- a/std/flash/text/engine/FontPosture.hx +++ b/std/flash/text/engine/FontPosture.hx @@ -1,6 +1,6 @@ package flash.text.engine; -@:fakeEnum(String) extern enum FontPosture { - ITALIC; - NORMAL; +@:native("flash.text.engine.FontPosture") extern enum abstract FontPosture(String) { + var ITALIC; + var NORMAL; } diff --git a/std/flash/text/engine/FontWeight.hx b/std/flash/text/engine/FontWeight.hx index 3fd85f62923..31803218577 100644 --- a/std/flash/text/engine/FontWeight.hx +++ b/std/flash/text/engine/FontWeight.hx @@ -1,6 +1,6 @@ package flash.text.engine; -@:fakeEnum(String) extern enum FontWeight { - BOLD; - NORMAL; +@:native("flash.text.engine.FontWeight") extern enum abstract FontWeight(String) { + var BOLD; + var NORMAL; } diff --git a/std/flash/text/engine/GraphicElement.hx b/std/flash/text/engine/GraphicElement.hx index 4e0513563d1..f412d3b9ef4 100644 --- a/std/flash/text/engine/GraphicElement.hx +++ b/std/flash/text/engine/GraphicElement.hx @@ -1,8 +1,14 @@ package flash.text.engine; -@:final extern class GraphicElement extends ContentElement { - var elementHeight : Float; - var elementWidth : Float; - var graphic : flash.display.DisplayObject; +extern final class GraphicElement extends ContentElement { + @:flash.property var elementHeight(get,set) : Float; + @:flash.property var elementWidth(get,set) : Float; + @:flash.property var graphic(get,set) : flash.display.DisplayObject; function new(?graphic : flash.display.DisplayObject, elementWidth : Float = 15, elementHeight : Float = 15, ?elementFormat : ElementFormat, ?eventMirror : flash.events.EventDispatcher, ?textRotation : TextRotation) : Void; + private function get_elementHeight() : Float; + private function get_elementWidth() : Float; + private function get_graphic() : flash.display.DisplayObject; + private function set_elementHeight(value : Float) : Float; + private function set_elementWidth(value : Float) : Float; + private function set_graphic(value : flash.display.DisplayObject) : flash.display.DisplayObject; } diff --git a/std/flash/text/engine/GroupElement.hx b/std/flash/text/engine/GroupElement.hx index b48b4294efc..7d031d85f8a 100644 --- a/std/flash/text/engine/GroupElement.hx +++ b/std/flash/text/engine/GroupElement.hx @@ -1,11 +1,12 @@ package flash.text.engine; -@:final extern class GroupElement extends ContentElement { - var elementCount(default,never) : Int; +extern final class GroupElement extends ContentElement { + @:flash.property var elementCount(get,never) : Int; function new(?elements : flash.Vector, ?elementFormat : ElementFormat, ?eventMirror : flash.events.EventDispatcher, ?textRotation : TextRotation) : Void; function getElementAt(index : Int) : ContentElement; function getElementAtCharIndex(charIndex : Int) : ContentElement; function getElementIndex(element : ContentElement) : Int; + private function get_elementCount() : Int; function groupElements(beginIndex : Int, endIndex : Int) : GroupElement; function mergeTextElements(beginIndex : Int, endIndex : Int) : TextElement; function replaceElements(beginIndex : Int, endIndex : Int, newElements : flash.Vector) : flash.Vector; diff --git a/std/flash/text/engine/JustificationStyle.hx b/std/flash/text/engine/JustificationStyle.hx index 6ae3baf4e07..1b665fbac7d 100644 --- a/std/flash/text/engine/JustificationStyle.hx +++ b/std/flash/text/engine/JustificationStyle.hx @@ -1,7 +1,7 @@ package flash.text.engine; -@:fakeEnum(String) extern enum JustificationStyle { - PRIORITIZE_LEAST_ADJUSTMENT; - PUSH_IN_KINSOKU; - PUSH_OUT_ONLY; +@:native("flash.text.engine.JustificationStyle") extern enum abstract JustificationStyle(String) { + var PRIORITIZE_LEAST_ADJUSTMENT; + var PUSH_IN_KINSOKU; + var PUSH_OUT_ONLY; } diff --git a/std/flash/text/engine/Kerning.hx b/std/flash/text/engine/Kerning.hx index afc337d8956..a6c6e866a9f 100644 --- a/std/flash/text/engine/Kerning.hx +++ b/std/flash/text/engine/Kerning.hx @@ -1,7 +1,7 @@ package flash.text.engine; -@:fakeEnum(String) extern enum Kerning { - AUTO; - OFF; - ON; +@:native("flash.text.engine.Kerning") extern enum abstract Kerning(String) { + var AUTO; + var OFF; + var ON; } diff --git a/std/flash/text/engine/LigatureLevel.hx b/std/flash/text/engine/LigatureLevel.hx index 733e307cc06..476dcd463f6 100644 --- a/std/flash/text/engine/LigatureLevel.hx +++ b/std/flash/text/engine/LigatureLevel.hx @@ -1,9 +1,9 @@ package flash.text.engine; -@:fakeEnum(String) extern enum LigatureLevel { - COMMON; - EXOTIC; - MINIMUM; - NONE; - UNCOMMON; +@:native("flash.text.engine.LigatureLevel") extern enum abstract LigatureLevel(String) { + var COMMON; + var EXOTIC; + var MINIMUM; + var NONE; + var UNCOMMON; } diff --git a/std/flash/text/engine/LineJustification.hx b/std/flash/text/engine/LineJustification.hx index d57fd8c8e9f..a348f8e19eb 100644 --- a/std/flash/text/engine/LineJustification.hx +++ b/std/flash/text/engine/LineJustification.hx @@ -1,8 +1,8 @@ package flash.text.engine; -@:fakeEnum(String) extern enum LineJustification { - ALL_BUT_LAST; - ALL_BUT_MANDATORY_BREAK; - ALL_INCLUDING_LAST; - UNJUSTIFIED; +@:native("flash.text.engine.LineJustification") extern enum abstract LineJustification(String) { + var ALL_BUT_LAST; + var ALL_BUT_MANDATORY_BREAK; + var ALL_INCLUDING_LAST; + var UNJUSTIFIED; } diff --git a/std/flash/text/engine/RenderingMode.hx b/std/flash/text/engine/RenderingMode.hx index e624009a9d1..c48997f78a6 100644 --- a/std/flash/text/engine/RenderingMode.hx +++ b/std/flash/text/engine/RenderingMode.hx @@ -1,6 +1,6 @@ package flash.text.engine; -@:fakeEnum(String) extern enum RenderingMode { - CFF; - NORMAL; +@:native("flash.text.engine.RenderingMode") extern enum abstract RenderingMode(String) { + var CFF; + var NORMAL; } diff --git a/std/flash/text/engine/SpaceJustifier.hx b/std/flash/text/engine/SpaceJustifier.hx index fe61cf66745..e1a9028d992 100644 --- a/std/flash/text/engine/SpaceJustifier.hx +++ b/std/flash/text/engine/SpaceJustifier.hx @@ -1,9 +1,17 @@ package flash.text.engine; -@:final extern class SpaceJustifier extends TextJustifier { - var letterSpacing : Bool; - @:require(flash10_1) var maximumSpacing : Float; - @:require(flash10_1) var minimumSpacing : Float; - @:require(flash10_1) var optimumSpacing : Float; +extern final class SpaceJustifier extends TextJustifier { + @:flash.property var letterSpacing(get,set) : Bool; + @:flash.property @:require(flash10_1) var maximumSpacing(get,set) : Float; + @:flash.property @:require(flash10_1) var minimumSpacing(get,set) : Float; + @:flash.property @:require(flash10_1) var optimumSpacing(get,set) : Float; function new(?locale : String, ?lineJustification : LineJustification, letterSpacing : Bool = false) : Void; + private function get_letterSpacing() : Bool; + private function get_maximumSpacing() : Float; + private function get_minimumSpacing() : Float; + private function get_optimumSpacing() : Float; + private function set_letterSpacing(value : Bool) : Bool; + private function set_maximumSpacing(value : Float) : Float; + private function set_minimumSpacing(value : Float) : Float; + private function set_optimumSpacing(value : Float) : Float; } diff --git a/std/flash/text/engine/TabAlignment.hx b/std/flash/text/engine/TabAlignment.hx index 0e99e4f3a7a..f22d6558125 100644 --- a/std/flash/text/engine/TabAlignment.hx +++ b/std/flash/text/engine/TabAlignment.hx @@ -1,8 +1,8 @@ package flash.text.engine; -@:fakeEnum(String) extern enum TabAlignment { - CENTER; - DECIMAL; - END; - START; +@:native("flash.text.engine.TabAlignment") extern enum abstract TabAlignment(String) { + var CENTER; + var DECIMAL; + var END; + var START; } diff --git a/std/flash/text/engine/TabStop.hx b/std/flash/text/engine/TabStop.hx index 2a1422c2b9a..16998be3d51 100644 --- a/std/flash/text/engine/TabStop.hx +++ b/std/flash/text/engine/TabStop.hx @@ -1,8 +1,14 @@ package flash.text.engine; -@:final extern class TabStop { - var alignment : TabAlignment; - var decimalAlignmentToken : String; - var position : Float; +extern final class TabStop { + @:flash.property var alignment(get,set) : TabAlignment; + @:flash.property var decimalAlignmentToken(get,set) : String; + @:flash.property var position(get,set) : Float; function new(?alignment : TabAlignment, position : Float = 0, ?decimalAlignmentToken : String) : Void; + private function get_alignment() : TabAlignment; + private function get_decimalAlignmentToken() : String; + private function get_position() : Float; + private function set_alignment(value : TabAlignment) : TabAlignment; + private function set_decimalAlignmentToken(value : String) : String; + private function set_position(value : Float) : Float; } diff --git a/std/flash/text/engine/TextBaseline.hx b/std/flash/text/engine/TextBaseline.hx index 36795d3c4e4..f6181500f75 100644 --- a/std/flash/text/engine/TextBaseline.hx +++ b/std/flash/text/engine/TextBaseline.hx @@ -1,11 +1,11 @@ package flash.text.engine; -@:fakeEnum(String) extern enum TextBaseline { - ASCENT; - DESCENT; - IDEOGRAPHIC_BOTTOM; - IDEOGRAPHIC_CENTER; - IDEOGRAPHIC_TOP; - ROMAN; - USE_DOMINANT_BASELINE; +@:native("flash.text.engine.TextBaseline") extern enum abstract TextBaseline(String) { + var ASCENT; + var DESCENT; + var IDEOGRAPHIC_BOTTOM; + var IDEOGRAPHIC_CENTER; + var IDEOGRAPHIC_TOP; + var ROMAN; + var USE_DOMINANT_BASELINE; } diff --git a/std/flash/text/engine/TextBlock.hx b/std/flash/text/engine/TextBlock.hx index f59db45e103..873596ed37a 100644 --- a/std/flash/text/engine/TextBlock.hx +++ b/std/flash/text/engine/TextBlock.hx @@ -1,19 +1,19 @@ package flash.text.engine; -@:final extern class TextBlock { - var applyNonLinearFontScaling : Bool; - var baselineFontDescription : FontDescription; - var baselineFontSize : Float; - var baselineZero : TextBaseline; - var bidiLevel : Int; - var content : ContentElement; - var firstInvalidLine(default,never) : TextLine; - var firstLine(default,never) : TextLine; - var lastLine(default,never) : TextLine; - var lineRotation : TextRotation; - var tabStops : flash.Vector; - var textJustifier : TextJustifier; - var textLineCreationResult(default,never) : TextLineCreationResult; +extern final class TextBlock { + @:flash.property var applyNonLinearFontScaling(get,set) : Bool; + @:flash.property var baselineFontDescription(get,set) : FontDescription; + @:flash.property var baselineFontSize(get,set) : Float; + @:flash.property var baselineZero(get,set) : TextBaseline; + @:flash.property var bidiLevel(get,set) : Int; + @:flash.property var content(get,set) : ContentElement; + @:flash.property var firstInvalidLine(get,never) : TextLine; + @:flash.property var firstLine(get,never) : TextLine; + @:flash.property var lastLine(get,never) : TextLine; + @:flash.property var lineRotation(get,set) : TextRotation; + @:flash.property var tabStops(get,set) : flash.Vector; + @:flash.property var textJustifier(get,set) : TextJustifier; + @:flash.property var textLineCreationResult(get,never) : TextLineCreationResult; var userData : Dynamic; function new(?content : ContentElement, ?tabStops : flash.Vector, ?textJustifier : TextJustifier, ?lineRotation : TextRotation, ?baselineZero : TextBaseline, bidiLevel : Int = 0, applyNonLinearFontScaling : Bool = true, ?baselineFontDescription : FontDescription, baselineFontSize : Float = 12) : Void; function createTextLine(?previousLine : TextLine, width : Float = 1000000, lineOffset : Float = 0, fitSomething : Bool = false) : TextLine; @@ -23,7 +23,29 @@ package flash.text.engine; function findPreviousAtomBoundary(beforeCharIndex : Int) : Int; function findPreviousWordBoundary(beforeCharIndex : Int) : Int; function getTextLineAtCharIndex(charIndex : Int) : TextLine; + private function get_applyNonLinearFontScaling() : Bool; + private function get_baselineFontDescription() : FontDescription; + private function get_baselineFontSize() : Float; + private function get_baselineZero() : TextBaseline; + private function get_bidiLevel() : Int; + private function get_content() : ContentElement; + private function get_firstInvalidLine() : TextLine; + private function get_firstLine() : TextLine; + private function get_lastLine() : TextLine; + private function get_lineRotation() : TextRotation; + private function get_tabStops() : flash.Vector; + private function get_textJustifier() : TextJustifier; + private function get_textLineCreationResult() : TextLineCreationResult; @:require(flash10_1) function recreateTextLine(textLine : TextLine, ?previousLine : TextLine, width : Float = 1000000, lineOffset : Float = 0, fitSomething : Bool = false) : TextLine; @:require(flash10_1) function releaseLineCreationData() : Void; function releaseLines(firstLine : TextLine, lastLine : TextLine) : Void; + private function set_applyNonLinearFontScaling(value : Bool) : Bool; + private function set_baselineFontDescription(value : FontDescription) : FontDescription; + private function set_baselineFontSize(value : Float) : Float; + private function set_baselineZero(value : TextBaseline) : TextBaseline; + private function set_bidiLevel(value : Int) : Int; + private function set_content(value : ContentElement) : ContentElement; + private function set_lineRotation(value : TextRotation) : TextRotation; + private function set_tabStops(value : flash.Vector) : flash.Vector; + private function set_textJustifier(value : TextJustifier) : TextJustifier; } diff --git a/std/flash/text/engine/TextElement.hx b/std/flash/text/engine/TextElement.hx index 3ca785d2e01..d32c30e4b6d 100644 --- a/std/flash/text/engine/TextElement.hx +++ b/std/flash/text/engine/TextElement.hx @@ -1,6 +1,7 @@ package flash.text.engine; -@:final extern class TextElement extends ContentElement { +extern final class TextElement extends ContentElement { function new(?text : String, ?elementFormat : ElementFormat, ?eventMirror : flash.events.EventDispatcher, ?textRotation : TextRotation) : Void; function replaceText(beginIndex : Int, endIndex : Int, newText : String) : Void; + private function set_text(value : String) : String; } diff --git a/std/flash/text/engine/TextJustifier.hx b/std/flash/text/engine/TextJustifier.hx index 7525682faf6..abc6f44e67f 100644 --- a/std/flash/text/engine/TextJustifier.hx +++ b/std/flash/text/engine/TextJustifier.hx @@ -1,9 +1,12 @@ package flash.text.engine; extern class TextJustifier { - var lineJustification : LineJustification; - var locale(default,never) : String; + @:flash.property var lineJustification(get,set) : LineJustification; + @:flash.property var locale(get,never) : String; function new(locale : String, lineJustification : LineJustification) : Void; function clone() : TextJustifier; + private function get_lineJustification() : LineJustification; + private function get_locale() : String; + private function set_lineJustification(value : LineJustification) : LineJustification; static function getJustifierForLocale(locale : String) : TextJustifier; } diff --git a/std/flash/text/engine/TextLine.hx b/std/flash/text/engine/TextLine.hx index b6e6aabce18..fd3400980a4 100644 --- a/std/flash/text/engine/TextLine.hx +++ b/std/flash/text/engine/TextLine.hx @@ -1,26 +1,26 @@ package flash.text.engine; -@:final extern class TextLine extends flash.display.DisplayObjectContainer { - var ascent(default,never) : Float; - var atomCount(default,never) : Int; - var descent(default,never) : Float; - var hasGraphicElement(default,never) : Bool; - @:require(flash10_1) var hasTabs(default,never) : Bool; - var mirrorRegions(default,never) : flash.Vector; - var nextLine(default,never) : TextLine; - var previousLine(default,never) : TextLine; - var rawTextLength(default,never) : Int; - var specifiedWidth(default,never) : Float; - var textBlock(default,never) : TextBlock; - var textBlockBeginIndex(default,never) : Int; - var textHeight(default,never) : Float; - var textWidth(default,never) : Float; - var totalAscent(default,never) : Float; - var totalDescent(default,never) : Float; - var totalHeight(default,never) : Float; - var unjustifiedTextWidth(default,never) : Float; +extern final class TextLine extends flash.display.DisplayObjectContainer { + @:flash.property var ascent(get,never) : Float; + @:flash.property var atomCount(get,never) : Int; + @:flash.property var descent(get,never) : Float; + @:flash.property var hasGraphicElement(get,never) : Bool; + @:flash.property @:require(flash10_1) var hasTabs(get,never) : Bool; + @:flash.property var mirrorRegions(get,never) : flash.Vector; + @:flash.property var nextLine(get,never) : TextLine; + @:flash.property var previousLine(get,never) : TextLine; + @:flash.property var rawTextLength(get,never) : Int; + @:flash.property var specifiedWidth(get,never) : Float; + @:flash.property var textBlock(get,never) : TextBlock; + @:flash.property var textBlockBeginIndex(get,never) : Int; + @:flash.property var textHeight(get,never) : Float; + @:flash.property var textWidth(get,never) : Float; + @:flash.property var totalAscent(get,never) : Float; + @:flash.property var totalDescent(get,never) : Float; + @:flash.property var totalHeight(get,never) : Float; + @:flash.property var unjustifiedTextWidth(get,never) : Float; var userData : Dynamic; - var validity : String; + @:flash.property var validity(get,set) : String; function new() : Void; function dump() : String; function flushAtomData() : Void; @@ -36,5 +36,25 @@ package flash.text.engine; function getAtomWordBoundaryOnLeft(atomIndex : Int) : Bool; function getBaselinePosition(baseline : String) : Float; function getMirrorRegion(mirror : flash.events.EventDispatcher) : TextLineMirrorRegion; - static var MAX_LINE_WIDTH(default,never) : Int; + private function get_ascent() : Float; + private function get_atomCount() : Int; + private function get_descent() : Float; + private function get_hasGraphicElement() : Bool; + private function get_hasTabs() : Bool; + private function get_mirrorRegions() : flash.Vector; + private function get_nextLine() : TextLine; + private function get_previousLine() : TextLine; + private function get_rawTextLength() : Int; + private function get_specifiedWidth() : Float; + private function get_textBlock() : TextBlock; + private function get_textBlockBeginIndex() : Int; + private function get_textHeight() : Float; + private function get_textWidth() : Float; + private function get_totalAscent() : Float; + private function get_totalDescent() : Float; + private function get_totalHeight() : Float; + private function get_unjustifiedTextWidth() : Float; + private function get_validity() : String; + private function set_validity(value : String) : String; + static final MAX_LINE_WIDTH : Int; } diff --git a/std/flash/text/engine/TextLineCreationResult.hx b/std/flash/text/engine/TextLineCreationResult.hx index b01016f466a..34531b25bb0 100644 --- a/std/flash/text/engine/TextLineCreationResult.hx +++ b/std/flash/text/engine/TextLineCreationResult.hx @@ -1,8 +1,8 @@ package flash.text.engine; -@:fakeEnum(String) extern enum TextLineCreationResult { - COMPLETE; - EMERGENCY; - INSUFFICIENT_WIDTH; - SUCCESS; +@:native("flash.text.engine.TextLineCreationResult") extern enum abstract TextLineCreationResult(String) { + var COMPLETE; + var EMERGENCY; + var INSUFFICIENT_WIDTH; + var SUCCESS; } diff --git a/std/flash/text/engine/TextLineMirrorRegion.hx b/std/flash/text/engine/TextLineMirrorRegion.hx index 74f96c89456..0d4aa8e4edf 100644 --- a/std/flash/text/engine/TextLineMirrorRegion.hx +++ b/std/flash/text/engine/TextLineMirrorRegion.hx @@ -1,11 +1,17 @@ package flash.text.engine; -@:final extern class TextLineMirrorRegion { - var bounds(default,never) : flash.geom.Rectangle; - var element(default,never) : ContentElement; - var mirror(default,never) : flash.events.EventDispatcher; - var nextRegion(default,never) : TextLineMirrorRegion; - var previousRegion(default,never) : TextLineMirrorRegion; - var textLine(default,never) : TextLine; +extern final class TextLineMirrorRegion { + @:flash.property var bounds(get,never) : flash.geom.Rectangle; + @:flash.property var element(get,never) : ContentElement; + @:flash.property var mirror(get,never) : flash.events.EventDispatcher; + @:flash.property var nextRegion(get,never) : TextLineMirrorRegion; + @:flash.property var previousRegion(get,never) : TextLineMirrorRegion; + @:flash.property var textLine(get,never) : TextLine; function new() : Void; + private function get_bounds() : flash.geom.Rectangle; + private function get_element() : ContentElement; + private function get_mirror() : flash.events.EventDispatcher; + private function get_nextRegion() : TextLineMirrorRegion; + private function get_previousRegion() : TextLineMirrorRegion; + private function get_textLine() : TextLine; } diff --git a/std/flash/text/engine/TextLineValidity.hx b/std/flash/text/engine/TextLineValidity.hx index 4336ad9ac61..d8b773ff32f 100644 --- a/std/flash/text/engine/TextLineValidity.hx +++ b/std/flash/text/engine/TextLineValidity.hx @@ -1,8 +1,8 @@ package flash.text.engine; -@:fakeEnum(String) extern enum TextLineValidity { - INVALID; - POSSIBLY_INVALID; - STATIC; - VALID; +@:native("flash.text.engine.TextLineValidity") extern enum abstract TextLineValidity(String) { + var INVALID; + var POSSIBLY_INVALID; + var STATIC; + var VALID; } diff --git a/std/flash/text/engine/TextRotation.hx b/std/flash/text/engine/TextRotation.hx index 391a0e5ac6e..b424d9d823a 100644 --- a/std/flash/text/engine/TextRotation.hx +++ b/std/flash/text/engine/TextRotation.hx @@ -1,9 +1,9 @@ package flash.text.engine; -@:fakeEnum(String) extern enum TextRotation { - AUTO; - ROTATE_0; - ROTATE_180; - ROTATE_270; - ROTATE_90; +@:native("flash.text.engine.TextRotation") extern enum abstract TextRotation(String) { + var AUTO; + var ROTATE_0; + var ROTATE_180; + var ROTATE_270; + var ROTATE_90; } diff --git a/std/flash/text/engine/TypographicCase.hx b/std/flash/text/engine/TypographicCase.hx index 6787c75e5f7..2d5c0ff9bd7 100644 --- a/std/flash/text/engine/TypographicCase.hx +++ b/std/flash/text/engine/TypographicCase.hx @@ -1,11 +1,11 @@ package flash.text.engine; -@:fakeEnum(String) extern enum TypographicCase { - CAPS; - CAPS_AND_SMALL_CAPS; - DEFAULT; - LOWERCASE; - SMALL_CAPS; - TITLE; - UPPERCASE; +@:native("flash.text.engine.TypographicCase") extern enum abstract TypographicCase(String) { + var CAPS; + var CAPS_AND_SMALL_CAPS; + var DEFAULT; + var LOWERCASE; + var SMALL_CAPS; + var TITLE; + var UPPERCASE; } diff --git a/std/flash/text/ime/CompositionAttributeRange.hx b/std/flash/text/ime/CompositionAttributeRange.hx index 69079f34eb9..2a4d60beecc 100644 --- a/std/flash/text/ime/CompositionAttributeRange.hx +++ b/std/flash/text/ime/CompositionAttributeRange.hx @@ -1,6 +1,6 @@ package flash.text.ime; -@:final extern class CompositionAttributeRange { +extern final class CompositionAttributeRange { var converted : Bool; var relativeEnd : Int; var relativeStart : Int; diff --git a/std/flash/text/ime/IIMEClient.hx b/std/flash/text/ime/IIMEClient.hx index 12470fdde0e..f5259952e1f 100644 --- a/std/flash/text/ime/IIMEClient.hx +++ b/std/flash/text/ime/IIMEClient.hx @@ -1,14 +1,19 @@ package flash.text.ime; extern interface IIMEClient { - var compositionEndIndex(default,never) : Int; - var compositionStartIndex(default,never) : Int; - var selectionActiveIndex(default,never) : Int; - var selectionAnchorIndex(default,never) : Int; - var verticalTextLayout(default,never) : Bool; + @:flash.property var compositionEndIndex(get,never) : Int; + @:flash.property var compositionStartIndex(get,never) : Int; + @:flash.property var selectionActiveIndex(get,never) : Int; + @:flash.property var selectionAnchorIndex(get,never) : Int; + @:flash.property var verticalTextLayout(get,never) : Bool; function confirmComposition(?text : String, preserveSelection : Bool = false) : Void; function getTextBounds(startIndex : Int, endIndex : Int) : flash.geom.Rectangle; function getTextInRange(startIndex : Int, endIndex : Int) : String; + private function get_compositionEndIndex() : Int; + private function get_compositionStartIndex() : Int; + private function get_selectionActiveIndex() : Int; + private function get_selectionAnchorIndex() : Int; + private function get_verticalTextLayout() : Bool; function selectRange(anchorIndex : Int, activeIndex : Int) : Void; function updateComposition(text : String, attributes : flash.Vector, compositionStartIndex : Int, compositionEndIndex : Int) : Void; } diff --git a/std/flash/trace/Trace.hx b/std/flash/trace/Trace.hx index 05902f96123..ba015974374 100644 --- a/std/flash/trace/Trace.hx +++ b/std/flash/trace/Trace.hx @@ -1,13 +1,13 @@ package flash.trace; extern class Trace { - static var FILE(default,never) : Dynamic; - static var LISTENER(default,never) : Dynamic; - static var METHODS(default,never) : Int; - static var METHODS_AND_LINES(default,never) : Int; - static var METHODS_AND_LINES_WITH_ARGS(default,never) : Int; - static var METHODS_WITH_ARGS(default,never) : Int; - static var OFF(default,never) : Int; + static final FILE : Dynamic; + static final LISTENER : Dynamic; + static final METHODS : Int; + static final METHODS_AND_LINES : Int; + static final METHODS_AND_LINES_WITH_ARGS : Int; + static final METHODS_WITH_ARGS : Int; + static final OFF : Int; static function getLevel(target : Int = 2) : Int; static function getListener() : Dynamic; static function setLevel(l : Int, target : Int = 2) : Dynamic; diff --git a/std/flash/ui/ContextMenu.hx b/std/flash/ui/ContextMenu.hx index 89cfe2bc507..4372e8b15a0 100644 --- a/std/flash/ui/ContextMenu.hx +++ b/std/flash/ui/ContextMenu.hx @@ -1,13 +1,24 @@ package flash.ui; -@:final extern class ContextMenu extends flash.display.NativeMenu { - var builtInItems : ContextMenuBuiltInItems; - @:require(flash10) var clipboardItems : ContextMenuClipboardItems; - @:require(flash10) var clipboardMenu : Bool; - var customItems : Array; - @:require(flash10) var link : flash.net.URLRequest; +extern final class ContextMenu extends flash.display.NativeMenu { + @:flash.property var builtInItems(get,set) : ContextMenuBuiltInItems; + @:flash.property @:require(flash10) var clipboardItems(get,set) : ContextMenuClipboardItems; + @:flash.property @:require(flash10) var clipboardMenu(get,set) : Bool; + @:flash.property var customItems(get,set) : Array; + @:flash.property @:require(flash10) var link(get,set) : flash.net.URLRequest; function new() : Void; function clone() : ContextMenu; + private function get_builtInItems() : ContextMenuBuiltInItems; + private function get_clipboardItems() : ContextMenuClipboardItems; + private function get_clipboardMenu() : Bool; + private function get_customItems() : Array; + private function get_link() : flash.net.URLRequest; function hideBuiltInItems() : Void; - @:require(flash10_1) static var isSupported(default,never) : Bool; + private function set_builtInItems(value : ContextMenuBuiltInItems) : ContextMenuBuiltInItems; + private function set_clipboardItems(value : ContextMenuClipboardItems) : ContextMenuClipboardItems; + private function set_clipboardMenu(value : Bool) : Bool; + private function set_customItems(value : Array) : Array; + private function set_link(value : flash.net.URLRequest) : flash.net.URLRequest; + @:flash.property @:require(flash10_1) static var isSupported(get,never) : Bool; + private static function get_isSupported() : Bool; } diff --git a/std/flash/ui/ContextMenuBuiltInItems.hx b/std/flash/ui/ContextMenuBuiltInItems.hx index 21bb60039a7..fa9fca15853 100644 --- a/std/flash/ui/ContextMenuBuiltInItems.hx +++ b/std/flash/ui/ContextMenuBuiltInItems.hx @@ -1,14 +1,30 @@ package flash.ui; -@:final extern class ContextMenuBuiltInItems { - var forwardAndBack : Bool; - var loop : Bool; - var play : Bool; - var print : Bool; - var quality : Bool; - var rewind : Bool; - var save : Bool; - var zoom : Bool; +extern final class ContextMenuBuiltInItems { + @:flash.property var forwardAndBack(get,set) : Bool; + @:flash.property var loop(get,set) : Bool; + @:flash.property var play(get,set) : Bool; + @:flash.property var print(get,set) : Bool; + @:flash.property var quality(get,set) : Bool; + @:flash.property var rewind(get,set) : Bool; + @:flash.property var save(get,set) : Bool; + @:flash.property var zoom(get,set) : Bool; function new() : Void; function clone() : ContextMenuBuiltInItems; + private function get_forwardAndBack() : Bool; + private function get_loop() : Bool; + private function get_play() : Bool; + private function get_print() : Bool; + private function get_quality() : Bool; + private function get_rewind() : Bool; + private function get_save() : Bool; + private function get_zoom() : Bool; + private function set_forwardAndBack(value : Bool) : Bool; + private function set_loop(value : Bool) : Bool; + private function set_play(value : Bool) : Bool; + private function set_print(value : Bool) : Bool; + private function set_quality(value : Bool) : Bool; + private function set_rewind(value : Bool) : Bool; + private function set_save(value : Bool) : Bool; + private function set_zoom(value : Bool) : Bool; } diff --git a/std/flash/ui/ContextMenuClipboardItems.hx b/std/flash/ui/ContextMenuClipboardItems.hx index d99c43a2780..8e49f9c9ca6 100644 --- a/std/flash/ui/ContextMenuClipboardItems.hx +++ b/std/flash/ui/ContextMenuClipboardItems.hx @@ -1,11 +1,21 @@ package flash.ui; -@:final extern class ContextMenuClipboardItems { - var clear : Bool; - var copy : Bool; - var cut : Bool; - var paste : Bool; - var selectAll : Bool; +extern final class ContextMenuClipboardItems { + @:flash.property var clear(get,set) : Bool; + @:flash.property var copy(get,set) : Bool; + @:flash.property var cut(get,set) : Bool; + @:flash.property var paste(get,set) : Bool; + @:flash.property var selectAll(get,set) : Bool; function new() : Void; function clone() : ContextMenuClipboardItems; + private function get_clear() : Bool; + private function get_copy() : Bool; + private function get_cut() : Bool; + private function get_paste() : Bool; + private function get_selectAll() : Bool; + private function set_clear(value : Bool) : Bool; + private function set_copy(value : Bool) : Bool; + private function set_cut(value : Bool) : Bool; + private function set_paste(value : Bool) : Bool; + private function set_selectAll(value : Bool) : Bool; } diff --git a/std/flash/ui/ContextMenuItem.hx b/std/flash/ui/ContextMenuItem.hx index 5039530b014..2e6cf0b449b 100644 --- a/std/flash/ui/ContextMenuItem.hx +++ b/std/flash/ui/ContextMenuItem.hx @@ -1,9 +1,15 @@ package flash.ui; -@:final extern class ContextMenuItem extends flash.display.NativeMenuItem { - var caption : String; - var separatorBefore : Bool; - var visible : Bool; +extern final class ContextMenuItem extends flash.display.NativeMenuItem { + @:flash.property var caption(get,set) : String; + @:flash.property var separatorBefore(get,set) : Bool; + @:flash.property var visible(get,set) : Bool; function new(caption : String, separatorBefore : Bool = false, enabled : Bool = true, visible : Bool = true) : Void; function clone() : ContextMenuItem; + private function get_caption() : String; + private function get_separatorBefore() : Bool; + private function get_visible() : Bool; + private function set_caption(value : String) : String; + private function set_separatorBefore(value : Bool) : Bool; + private function set_visible(value : Bool) : Bool; } diff --git a/std/flash/ui/GameInput.hx b/std/flash/ui/GameInput.hx index 3f9671ffa75..49aec66771b 100644 --- a/std/flash/ui/GameInput.hx +++ b/std/flash/ui/GameInput.hx @@ -1,7 +1,9 @@ package flash.ui; @:require(flash11_8) extern class GameInput extends flash.events.EventDispatcher { - static var isSupported(default,never) : Bool; - static var numDevices(default,never) : Int; + @:flash.property static var isSupported(get,never) : Bool; + @:flash.property static var numDevices(get,never) : Int; static function getDeviceAt(index : Int) : GameInputDevice; + private static function get_isSupported() : Bool; + private static function get_numDevices() : Int; } diff --git a/std/flash/ui/GameInputControl.hx b/std/flash/ui/GameInputControl.hx index e6c4314daef..18549d42bcf 100644 --- a/std/flash/ui/GameInputControl.hx +++ b/std/flash/ui/GameInputControl.hx @@ -1,10 +1,15 @@ package flash.ui; extern class GameInputControl extends flash.events.EventDispatcher implements Dynamic { - var device(default,never) : GameInputDevice; - var id(default,never) : String; - var maxValue(default,never) : Float; - var minValue(default,never) : Float; - var value(default,never) : Float; + @:flash.property var device(get,never) : GameInputDevice; + @:flash.property var id(get,never) : String; + @:flash.property var maxValue(get,never) : Float; + @:flash.property var minValue(get,never) : Float; + @:flash.property var value(get,never) : Float; function new() : Void; + private function get_device() : GameInputDevice; + private function get_id() : String; + private function get_maxValue() : Float; + private function get_minValue() : Float; + private function get_value() : Float; } diff --git a/std/flash/ui/GameInputControlType.hx b/std/flash/ui/GameInputControlType.hx index 868b7824d75..cb4497eb0b5 100644 --- a/std/flash/ui/GameInputControlType.hx +++ b/std/flash/ui/GameInputControlType.hx @@ -1,10 +1,10 @@ package flash.ui; -@:fakeEnum(String) extern enum GameInputControlType { - ACCELERATION; - BUTTON; - DIRECTION; - MOVEMENT; - ROTATION; - TRIGGER; +@:native("flash.ui.GameInputControlType") extern enum abstract GameInputControlType(String) { + var ACCELERATION; + var BUTTON; + var DIRECTION; + var MOVEMENT; + var ROTATION; + var TRIGGER; } diff --git a/std/flash/ui/GameInputDevice.hx b/std/flash/ui/GameInputDevice.hx index ad4b5994f3d..2201d58b0ac 100644 --- a/std/flash/ui/GameInputDevice.hx +++ b/std/flash/ui/GameInputDevice.hx @@ -1,15 +1,22 @@ package flash.ui; -@:final @:require(flash11_8) extern class GameInputDevice { - var enabled : Bool; - var id(default,never) : String; - var name(default,never) : String; - var numControls(default,never) : Int; - var sampleInterval : Int; +@:require(flash11_8) extern final class GameInputDevice { + @:flash.property var enabled(get,set) : Bool; + @:flash.property var id(get,never) : String; + @:flash.property var name(get,never) : String; + @:flash.property var numControls(get,never) : Int; + @:flash.property var sampleInterval(get,set) : Int; function new() : Void; function getCachedSamples(data : flash.utils.ByteArray, append : Bool = false) : Int; function getControlAt(i : Int) : GameInputControl; + private function get_enabled() : Bool; + private function get_id() : String; + private function get_name() : String; + private function get_numControls() : Int; + private function get_sampleInterval() : Int; + private function set_enabled(value : Bool) : Bool; + private function set_sampleInterval(value : Int) : Int; function startCachingSamples(numSamples : Int, controls : flash.Vector) : Void; function stopCachingSamples() : Void; - static var MAX_BUFFER_SIZE(default,never) : Int; + static final MAX_BUFFER_SIZE : Int; } diff --git a/std/flash/ui/GameInputFinger.hx b/std/flash/ui/GameInputFinger.hx index e5414e6d663..52275fd9807 100644 --- a/std/flash/ui/GameInputFinger.hx +++ b/std/flash/ui/GameInputFinger.hx @@ -1,8 +1,8 @@ package flash.ui; -@:fakeEnum(String) extern enum GameInputFinger { - INDEX; - MIDDLE; - THUMB; - UNKNOWN; +@:native("flash.ui.GameInputFinger") extern enum abstract GameInputFinger(String) { + var INDEX; + var MIDDLE; + var THUMB; + var UNKNOWN; } diff --git a/std/flash/ui/GameInputHand.hx b/std/flash/ui/GameInputHand.hx index 4f6a1a2b03b..842286f2673 100644 --- a/std/flash/ui/GameInputHand.hx +++ b/std/flash/ui/GameInputHand.hx @@ -1,7 +1,7 @@ package flash.ui; -@:fakeEnum(String) extern enum GameInputHand { - LEFT; - RIGHT; - UNKNOWN; +@:native("flash.ui.GameInputHand") extern enum abstract GameInputHand(String) { + var LEFT; + var RIGHT; + var UNKNOWN; } diff --git a/std/flash/ui/KeyLocation.hx b/std/flash/ui/KeyLocation.hx index 10e015408fe..eac4a30dd8a 100644 --- a/std/flash/ui/KeyLocation.hx +++ b/std/flash/ui/KeyLocation.hx @@ -1,9 +1,9 @@ package flash.ui; -@:fakeEnum(UInt) extern enum KeyLocation { - D_PAD; - LEFT; - NUM_PAD; - RIGHT; - STANDARD; +@:native("flash.ui.KeyLocation") extern enum abstract KeyLocation(UInt) { + var D_PAD; + var LEFT; + var NUM_PAD; + var RIGHT; + var STANDARD; } diff --git a/std/flash/ui/Keyboard.hx b/std/flash/ui/Keyboard.hx index 4d78de55be5..e65f70e8b64 100644 --- a/std/flash/ui/Keyboard.hx +++ b/std/flash/ui/Keyboard.hx @@ -1,285 +1,291 @@ package flash.ui; extern class Keyboard { - @:require(flash10_1) static var A(default,never) : UInt; - @:require(flash10_1) static var ALTERNATE(default,never) : UInt; - @:require(flash10_2) static var AUDIO(default,never) : UInt; - @:require(flash10_1) static var B(default,never) : UInt; - @:require(flash10_2) static var BACK(default,never) : UInt; - @:require(flash10_1) static var BACKQUOTE(default,never) : UInt; - @:require(flash10_1) static var BACKSLASH(default,never) : UInt; - static var BACKSPACE(default,never) : UInt; - @:require(flash10_2) static var BLUE(default,never) : UInt; - @:require(flash10_1) static var C(default,never) : UInt; - static var CAPS_LOCK(default,never) : UInt; - @:require(flash10_2) static var CHANNEL_DOWN(default,never) : UInt; - @:require(flash10_2) static var CHANNEL_UP(default,never) : UInt; - @:require(flash10_1) static var COMMA(default,never) : UInt; - @:require(flash10_1) static var COMMAND(default,never) : UInt; - static var CONTROL(default,never) : UInt; - @:require(flash10_1) static var CharCodeStrings(default,never) : Array; - @:require(flash10_1) static var D(default,never) : UInt; - static var DELETE(default,never) : UInt; - static var DOWN(default,never) : UInt; - @:require(flash10_2) static var DVR(default,never) : UInt; - @:require(flash10_1) static var E(default,never) : UInt; - static var END(default,never) : UInt; - static var ENTER(default,never) : UInt; - @:require(flash10_1) static var EQUAL(default,never) : UInt; - static var ESCAPE(default,never) : UInt; - @:require(flash10_2) static var EXIT(default,never) : UInt; - @:require(flash10_1) static var F(default,never) : UInt; - static var F1(default,never) : UInt; - static var F10(default,never) : UInt; - static var F11(default,never) : UInt; - static var F12(default,never) : UInt; - static var F13(default,never) : UInt; - static var F14(default,never) : UInt; - static var F15(default,never) : UInt; - static var F2(default,never) : UInt; - static var F3(default,never) : UInt; - static var F4(default,never) : UInt; - static var F5(default,never) : UInt; - static var F6(default,never) : UInt; - static var F7(default,never) : UInt; - static var F8(default,never) : UInt; - static var F9(default,never) : UInt; - @:require(flash10_2) static var FAST_FORWARD(default,never) : UInt; - @:require(flash10_1) static var G(default,never) : UInt; - @:require(flash10_2) static var GREEN(default,never) : UInt; - @:require(flash10_2) static var GUIDE(default,never) : UInt; - @:require(flash10_1) static var H(default,never) : UInt; - @:require(flash10_2) static var HELP(default,never) : UInt; - static var HOME(default,never) : UInt; - @:require(flash10_1) static var I(default,never) : UInt; - @:require(flash10_2) static var INFO(default,never) : UInt; - @:require(flash10_2) static var INPUT(default,never) : UInt; - static var INSERT(default,never) : UInt; - @:require(flash10_1) static var J(default,never) : UInt; - @:require(flash10_1) static var K(default,never) : UInt; - @:require(flash10_1) static var KEYNAME_BEGIN(default,never) : String; - @:require(flash10_1) static var KEYNAME_BREAK(default,never) : String; - @:require(flash10_1) static var KEYNAME_CLEARDISPLAY(default,never) : String; - @:require(flash10_1) static var KEYNAME_CLEARLINE(default,never) : String; - @:require(flash10_1) static var KEYNAME_DELETE(default,never) : String; - @:require(flash10_1) static var KEYNAME_DELETECHAR(default,never) : String; - @:require(flash10_1) static var KEYNAME_DELETELINE(default,never) : String; - @:require(flash10_1) static var KEYNAME_DOWNARROW(default,never) : String; - @:require(flash10_1) static var KEYNAME_END(default,never) : String; - @:require(flash10_1) static var KEYNAME_EXECUTE(default,never) : String; - @:require(flash10_1) static var KEYNAME_F1(default,never) : String; - @:require(flash10_1) static var KEYNAME_F10(default,never) : String; - @:require(flash10_1) static var KEYNAME_F11(default,never) : String; - @:require(flash10_1) static var KEYNAME_F12(default,never) : String; - @:require(flash10_1) static var KEYNAME_F13(default,never) : String; - @:require(flash10_1) static var KEYNAME_F14(default,never) : String; - @:require(flash10_1) static var KEYNAME_F15(default,never) : String; - @:require(flash10_1) static var KEYNAME_F16(default,never) : String; - @:require(flash10_1) static var KEYNAME_F17(default,never) : String; - @:require(flash10_1) static var KEYNAME_F18(default,never) : String; - @:require(flash10_1) static var KEYNAME_F19(default,never) : String; - @:require(flash10_1) static var KEYNAME_F2(default,never) : String; - @:require(flash10_1) static var KEYNAME_F20(default,never) : String; - @:require(flash10_1) static var KEYNAME_F21(default,never) : String; - @:require(flash10_1) static var KEYNAME_F22(default,never) : String; - @:require(flash10_1) static var KEYNAME_F23(default,never) : String; - @:require(flash10_1) static var KEYNAME_F24(default,never) : String; - @:require(flash10_1) static var KEYNAME_F25(default,never) : String; - @:require(flash10_1) static var KEYNAME_F26(default,never) : String; - @:require(flash10_1) static var KEYNAME_F27(default,never) : String; - @:require(flash10_1) static var KEYNAME_F28(default,never) : String; - @:require(flash10_1) static var KEYNAME_F29(default,never) : String; - @:require(flash10_1) static var KEYNAME_F3(default,never) : String; - @:require(flash10_1) static var KEYNAME_F30(default,never) : String; - @:require(flash10_1) static var KEYNAME_F31(default,never) : String; - @:require(flash10_1) static var KEYNAME_F32(default,never) : String; - @:require(flash10_1) static var KEYNAME_F33(default,never) : String; - @:require(flash10_1) static var KEYNAME_F34(default,never) : String; - @:require(flash10_1) static var KEYNAME_F35(default,never) : String; - @:require(flash10_1) static var KEYNAME_F4(default,never) : String; - @:require(flash10_1) static var KEYNAME_F5(default,never) : String; - @:require(flash10_1) static var KEYNAME_F6(default,never) : String; - @:require(flash10_1) static var KEYNAME_F7(default,never) : String; - @:require(flash10_1) static var KEYNAME_F8(default,never) : String; - @:require(flash10_1) static var KEYNAME_F9(default,never) : String; - @:require(flash10_1) static var KEYNAME_FIND(default,never) : String; - @:require(flash10_1) static var KEYNAME_HELP(default,never) : String; - @:require(flash10_1) static var KEYNAME_HOME(default,never) : String; - @:require(flash10_1) static var KEYNAME_INSERT(default,never) : String; - @:require(flash10_1) static var KEYNAME_INSERTCHAR(default,never) : String; - @:require(flash10_1) static var KEYNAME_INSERTLINE(default,never) : String; - @:require(flash10_1) static var KEYNAME_LEFTARROW(default,never) : String; - @:require(flash10_1) static var KEYNAME_MENU(default,never) : String; - @:require(flash10_1) static var KEYNAME_MODESWITCH(default,never) : String; - @:require(flash10_1) static var KEYNAME_NEXT(default,never) : String; - @:require(flash10_1) static var KEYNAME_PAGEDOWN(default,never) : String; - @:require(flash10_1) static var KEYNAME_PAGEUP(default,never) : String; - @:require(flash10_1) static var KEYNAME_PAUSE(default,never) : String; - @:require(flash10_1) static var KEYNAME_PREV(default,never) : String; - @:require(flash10_1) static var KEYNAME_PRINT(default,never) : String; - @:require(flash10_1) static var KEYNAME_PRINTSCREEN(default,never) : String; - @:require(flash10_1) static var KEYNAME_REDO(default,never) : String; - @:require(flash10_1) static var KEYNAME_RESET(default,never) : String; - @:require(flash10_1) static var KEYNAME_RIGHTARROW(default,never) : String; - @:require(flash10_1) static var KEYNAME_SCROLLLOCK(default,never) : String; - @:require(flash10_1) static var KEYNAME_SELECT(default,never) : String; - @:require(flash10_1) static var KEYNAME_STOP(default,never) : String; - @:require(flash10_1) static var KEYNAME_SYSREQ(default,never) : String; - @:require(flash10_1) static var KEYNAME_SYSTEM(default,never) : String; - @:require(flash10_1) static var KEYNAME_UNDO(default,never) : String; - @:require(flash10_1) static var KEYNAME_UPARROW(default,never) : String; - @:require(flash10_1) static var KEYNAME_USER(default,never) : String; - @:require(flash10_1) static var L(default,never) : UInt; - @:require(flash10_2) static var LAST(default,never) : UInt; - static var LEFT(default,never) : UInt; - @:require(flash10_1) static var LEFTBRACKET(default,never) : UInt; - @:require(flash10_2) static var LIVE(default,never) : UInt; - @:require(flash10_1) static var M(default,never) : UInt; - @:require(flash10_2) static var MASTER_SHELL(default,never) : UInt; - @:require(flash10_2) static var MENU(default,never) : UInt; - @:require(flash10_1) static var MINUS(default,never) : UInt; - @:require(flash10_1) static var N(default,never) : UInt; - @:require(flash10_2) static var NEXT(default,never) : UInt; - @:require(flash10_1) static var NUMBER_0(default,never) : UInt; - @:require(flash10_1) static var NUMBER_1(default,never) : UInt; - @:require(flash10_1) static var NUMBER_2(default,never) : UInt; - @:require(flash10_1) static var NUMBER_3(default,never) : UInt; - @:require(flash10_1) static var NUMBER_4(default,never) : UInt; - @:require(flash10_1) static var NUMBER_5(default,never) : UInt; - @:require(flash10_1) static var NUMBER_6(default,never) : UInt; - @:require(flash10_1) static var NUMBER_7(default,never) : UInt; - @:require(flash10_1) static var NUMBER_8(default,never) : UInt; - @:require(flash10_1) static var NUMBER_9(default,never) : UInt; - @:require(flash10_1) static var NUMPAD(default,never) : UInt; - static var NUMPAD_0(default,never) : UInt; - static var NUMPAD_1(default,never) : UInt; - static var NUMPAD_2(default,never) : UInt; - static var NUMPAD_3(default,never) : UInt; - static var NUMPAD_4(default,never) : UInt; - static var NUMPAD_5(default,never) : UInt; - static var NUMPAD_6(default,never) : UInt; - static var NUMPAD_7(default,never) : UInt; - static var NUMPAD_8(default,never) : UInt; - static var NUMPAD_9(default,never) : UInt; - static var NUMPAD_ADD(default,never) : UInt; - static var NUMPAD_DECIMAL(default,never) : UInt; - static var NUMPAD_DIVIDE(default,never) : UInt; - static var NUMPAD_ENTER(default,never) : UInt; - static var NUMPAD_MULTIPLY(default,never) : UInt; - static var NUMPAD_SUBTRACT(default,never) : UInt; - @:require(flash10_1) static var O(default,never) : UInt; - @:require(flash10_1) static var P(default,never) : UInt; - static var PAGE_DOWN(default,never) : UInt; - static var PAGE_UP(default,never) : UInt; - @:require(flash10_2) static var PAUSE(default,never) : UInt; - @:require(flash10_1) static var PERIOD(default,never) : UInt; - @:require(flash10_2) static var PLAY(default,never) : UInt; - @:require(flash10_2) static var PREVIOUS(default,never) : UInt; - @:require(flash10_1) static var Q(default,never) : UInt; - @:require(flash10_1) static var QUOTE(default,never) : UInt; - @:require(flash10_1) static var R(default,never) : UInt; - @:require(flash10_2) static var RECORD(default,never) : UInt; - @:require(flash10_2) static var RED(default,never) : UInt; - @:require(flash10_2) static var REWIND(default,never) : UInt; - static var RIGHT(default,never) : UInt; - @:require(flash10_1) static var RIGHTBRACKET(default,never) : UInt; - @:require(flash10_1) static var S(default,never) : UInt; - @:require(flash10_2) static var SEARCH(default,never) : UInt; - @:require(flash10_1) static var SEMICOLON(default,never) : UInt; - @:require(flash10_2) static var SETUP(default,never) : UInt; - static var SHIFT(default,never) : UInt; - @:require(flash10_2) static var SKIP_BACKWARD(default,never) : UInt; - @:require(flash10_2) static var SKIP_FORWARD(default,never) : UInt; - @:require(flash10_1) static var SLASH(default,never) : UInt; - static var SPACE(default,never) : UInt; - @:require(flash10_2) static var STOP(default,never) : UInt; - @:require(flash10_1) static var STRING_BEGIN(default,never) : String; - @:require(flash10_1) static var STRING_BREAK(default,never) : String; - @:require(flash10_1) static var STRING_CLEARDISPLAY(default,never) : String; - @:require(flash10_1) static var STRING_CLEARLINE(default,never) : String; - @:require(flash10_1) static var STRING_DELETE(default,never) : String; - @:require(flash10_1) static var STRING_DELETECHAR(default,never) : String; - @:require(flash10_1) static var STRING_DELETELINE(default,never) : String; - @:require(flash10_1) static var STRING_DOWNARROW(default,never) : String; - @:require(flash10_1) static var STRING_END(default,never) : String; - @:require(flash10_1) static var STRING_EXECUTE(default,never) : String; - @:require(flash10_1) static var STRING_F1(default,never) : String; - @:require(flash10_1) static var STRING_F10(default,never) : String; - @:require(flash10_1) static var STRING_F11(default,never) : String; - @:require(flash10_1) static var STRING_F12(default,never) : String; - @:require(flash10_1) static var STRING_F13(default,never) : String; - @:require(flash10_1) static var STRING_F14(default,never) : String; - @:require(flash10_1) static var STRING_F15(default,never) : String; - @:require(flash10_1) static var STRING_F16(default,never) : String; - @:require(flash10_1) static var STRING_F17(default,never) : String; - @:require(flash10_1) static var STRING_F18(default,never) : String; - @:require(flash10_1) static var STRING_F19(default,never) : String; - @:require(flash10_1) static var STRING_F2(default,never) : String; - @:require(flash10_1) static var STRING_F20(default,never) : String; - @:require(flash10_1) static var STRING_F21(default,never) : String; - @:require(flash10_1) static var STRING_F22(default,never) : String; - @:require(flash10_1) static var STRING_F23(default,never) : String; - @:require(flash10_1) static var STRING_F24(default,never) : String; - @:require(flash10_1) static var STRING_F25(default,never) : String; - @:require(flash10_1) static var STRING_F26(default,never) : String; - @:require(flash10_1) static var STRING_F27(default,never) : String; - @:require(flash10_1) static var STRING_F28(default,never) : String; - @:require(flash10_1) static var STRING_F29(default,never) : String; - @:require(flash10_1) static var STRING_F3(default,never) : String; - @:require(flash10_1) static var STRING_F30(default,never) : String; - @:require(flash10_1) static var STRING_F31(default,never) : String; - @:require(flash10_1) static var STRING_F32(default,never) : String; - @:require(flash10_1) static var STRING_F33(default,never) : String; - @:require(flash10_1) static var STRING_F34(default,never) : String; - @:require(flash10_1) static var STRING_F35(default,never) : String; - @:require(flash10_1) static var STRING_F4(default,never) : String; - @:require(flash10_1) static var STRING_F5(default,never) : String; - @:require(flash10_1) static var STRING_F6(default,never) : String; - @:require(flash10_1) static var STRING_F7(default,never) : String; - @:require(flash10_1) static var STRING_F8(default,never) : String; - @:require(flash10_1) static var STRING_F9(default,never) : String; - @:require(flash10_1) static var STRING_FIND(default,never) : String; - @:require(flash10_1) static var STRING_HELP(default,never) : String; - @:require(flash10_1) static var STRING_HOME(default,never) : String; - @:require(flash10_1) static var STRING_INSERT(default,never) : String; - @:require(flash10_1) static var STRING_INSERTCHAR(default,never) : String; - @:require(flash10_1) static var STRING_INSERTLINE(default,never) : String; - @:require(flash10_1) static var STRING_LEFTARROW(default,never) : String; - @:require(flash10_1) static var STRING_MENU(default,never) : String; - @:require(flash10_1) static var STRING_MODESWITCH(default,never) : String; - @:require(flash10_1) static var STRING_NEXT(default,never) : String; - @:require(flash10_1) static var STRING_PAGEDOWN(default,never) : String; - @:require(flash10_1) static var STRING_PAGEUP(default,never) : String; - @:require(flash10_1) static var STRING_PAUSE(default,never) : String; - @:require(flash10_1) static var STRING_PREV(default,never) : String; - @:require(flash10_1) static var STRING_PRINT(default,never) : String; - @:require(flash10_1) static var STRING_PRINTSCREEN(default,never) : String; - @:require(flash10_1) static var STRING_REDO(default,never) : String; - @:require(flash10_1) static var STRING_RESET(default,never) : String; - @:require(flash10_1) static var STRING_RIGHTARROW(default,never) : String; - @:require(flash10_1) static var STRING_SCROLLLOCK(default,never) : String; - @:require(flash10_1) static var STRING_SELECT(default,never) : String; - @:require(flash10_1) static var STRING_STOP(default,never) : String; - @:require(flash10_1) static var STRING_SYSREQ(default,never) : String; - @:require(flash10_1) static var STRING_SYSTEM(default,never) : String; - @:require(flash10_1) static var STRING_UNDO(default,never) : String; - @:require(flash10_1) static var STRING_UPARROW(default,never) : String; - @:require(flash10_1) static var STRING_USER(default,never) : String; - @:require(flash10_2) static var SUBTITLE(default,never) : UInt; - @:require(flash10_1) static var T(default,never) : UInt; - static var TAB(default,never) : UInt; - @:require(flash10_1) static var U(default,never) : UInt; - static var UP(default,never) : UInt; - @:require(flash10_1) static var V(default,never) : UInt; - @:require(flash10_2) static var VOD(default,never) : UInt; - @:require(flash10_1) static var W(default,never) : UInt; - @:require(flash10_1) static var X(default,never) : UInt; - @:require(flash10_1) static var Y(default,never) : UInt; - @:require(flash10_2) static var YELLOW(default,never) : UInt; - @:require(flash10_1) static var Z(default,never) : UInt; - static var capsLock(default,never) : Bool; - @:require(flash10_1) static var hasVirtualKeyboard(default,never) : Bool; - static var numLock(default,never) : Bool; - @:require(flash10_1) static var physicalKeyboardType(default,never) : KeyboardType; + @:require(flash10_1) static final A : UInt; + @:require(flash10_1) static final ALTERNATE : UInt; + @:require(flash10_2) static final AUDIO : UInt; + @:require(flash10_1) static final B : UInt; + @:require(flash10_2) static final BACK : UInt; + @:require(flash10_1) static final BACKQUOTE : UInt; + @:require(flash10_1) static final BACKSLASH : UInt; + static final BACKSPACE : UInt; + @:require(flash10_2) static final BLUE : UInt; + @:require(flash10_1) static final C : UInt; + static final CAPS_LOCK : UInt; + @:require(flash10_2) static final CHANNEL_DOWN : UInt; + @:require(flash10_2) static final CHANNEL_UP : UInt; + @:require(flash10_1) static final COMMA : UInt; + @:require(flash10_1) static final COMMAND : UInt; + static final CONTROL : UInt; + @:require(flash10_1) static final CharCodeStrings : Array; + @:require(flash10_1) static final D : UInt; + static final DELETE : UInt; + static final DOWN : UInt; + @:require(flash10_2) static final DVR : UInt; + @:require(flash10_1) static final E : UInt; + static final END : UInt; + static final ENTER : UInt; + @:require(flash10_1) static final EQUAL : UInt; + static final ESCAPE : UInt; + @:require(flash10_2) static final EXIT : UInt; + @:require(flash10_1) static final F : UInt; + static final F1 : UInt; + static final F10 : UInt; + static final F11 : UInt; + static final F12 : UInt; + static final F13 : UInt; + static final F14 : UInt; + static final F15 : UInt; + static final F2 : UInt; + static final F3 : UInt; + static final F4 : UInt; + static final F5 : UInt; + static final F6 : UInt; + static final F7 : UInt; + static final F8 : UInt; + static final F9 : UInt; + @:require(flash10_2) static final FAST_FORWARD : UInt; + @:require(flash10_1) static final G : UInt; + @:require(flash10_2) static final GREEN : UInt; + @:require(flash10_2) static final GUIDE : UInt; + @:require(flash10_1) static final H : UInt; + @:require(flash10_2) static final HELP : UInt; + static final HOME : UInt; + @:require(flash10_1) static final I : UInt; + @:require(flash10_2) static final INFO : UInt; + @:require(flash10_2) static final INPUT : UInt; + static final INSERT : UInt; + @:require(flash10_1) static final J : UInt; + @:require(flash10_1) static final K : UInt; + @:require(flash10_1) static final KEYNAME_BEGIN : String; + @:require(flash10_1) static final KEYNAME_BREAK : String; + @:require(flash10_1) static final KEYNAME_CLEARDISPLAY : String; + @:require(flash10_1) static final KEYNAME_CLEARLINE : String; + @:require(flash10_1) static final KEYNAME_DELETE : String; + @:require(flash10_1) static final KEYNAME_DELETECHAR : String; + @:require(flash10_1) static final KEYNAME_DELETELINE : String; + @:require(flash10_1) static final KEYNAME_DOWNARROW : String; + @:require(flash10_1) static final KEYNAME_END : String; + @:require(flash10_1) static final KEYNAME_EXECUTE : String; + @:require(flash10_1) static final KEYNAME_F1 : String; + @:require(flash10_1) static final KEYNAME_F10 : String; + @:require(flash10_1) static final KEYNAME_F11 : String; + @:require(flash10_1) static final KEYNAME_F12 : String; + @:require(flash10_1) static final KEYNAME_F13 : String; + @:require(flash10_1) static final KEYNAME_F14 : String; + @:require(flash10_1) static final KEYNAME_F15 : String; + @:require(flash10_1) static final KEYNAME_F16 : String; + @:require(flash10_1) static final KEYNAME_F17 : String; + @:require(flash10_1) static final KEYNAME_F18 : String; + @:require(flash10_1) static final KEYNAME_F19 : String; + @:require(flash10_1) static final KEYNAME_F2 : String; + @:require(flash10_1) static final KEYNAME_F20 : String; + @:require(flash10_1) static final KEYNAME_F21 : String; + @:require(flash10_1) static final KEYNAME_F22 : String; + @:require(flash10_1) static final KEYNAME_F23 : String; + @:require(flash10_1) static final KEYNAME_F24 : String; + @:require(flash10_1) static final KEYNAME_F25 : String; + @:require(flash10_1) static final KEYNAME_F26 : String; + @:require(flash10_1) static final KEYNAME_F27 : String; + @:require(flash10_1) static final KEYNAME_F28 : String; + @:require(flash10_1) static final KEYNAME_F29 : String; + @:require(flash10_1) static final KEYNAME_F3 : String; + @:require(flash10_1) static final KEYNAME_F30 : String; + @:require(flash10_1) static final KEYNAME_F31 : String; + @:require(flash10_1) static final KEYNAME_F32 : String; + @:require(flash10_1) static final KEYNAME_F33 : String; + @:require(flash10_1) static final KEYNAME_F34 : String; + @:require(flash10_1) static final KEYNAME_F35 : String; + @:require(flash10_1) static final KEYNAME_F4 : String; + @:require(flash10_1) static final KEYNAME_F5 : String; + @:require(flash10_1) static final KEYNAME_F6 : String; + @:require(flash10_1) static final KEYNAME_F7 : String; + @:require(flash10_1) static final KEYNAME_F8 : String; + @:require(flash10_1) static final KEYNAME_F9 : String; + @:require(flash10_1) static final KEYNAME_FIND : String; + @:require(flash10_1) static final KEYNAME_HELP : String; + @:require(flash10_1) static final KEYNAME_HOME : String; + @:require(flash10_1) static final KEYNAME_INSERT : String; + @:require(flash10_1) static final KEYNAME_INSERTCHAR : String; + @:require(flash10_1) static final KEYNAME_INSERTLINE : String; + @:require(flash10_1) static final KEYNAME_LEFTARROW : String; + @:require(flash10_1) static final KEYNAME_MENU : String; + @:require(flash10_1) static final KEYNAME_MODESWITCH : String; + @:require(flash10_1) static final KEYNAME_NEXT : String; + @:require(flash10_1) static final KEYNAME_PAGEDOWN : String; + @:require(flash10_1) static final KEYNAME_PAGEUP : String; + @:require(flash10_1) static final KEYNAME_PAUSE : String; + static final KEYNAME_PLAYPAUSE : String; + @:require(flash10_1) static final KEYNAME_PREV : String; + @:require(flash10_1) static final KEYNAME_PRINT : String; + @:require(flash10_1) static final KEYNAME_PRINTSCREEN : String; + @:require(flash10_1) static final KEYNAME_REDO : String; + @:require(flash10_1) static final KEYNAME_RESET : String; + @:require(flash10_1) static final KEYNAME_RIGHTARROW : String; + @:require(flash10_1) static final KEYNAME_SCROLLLOCK : String; + @:require(flash10_1) static final KEYNAME_SELECT : String; + @:require(flash10_1) static final KEYNAME_STOP : String; + @:require(flash10_1) static final KEYNAME_SYSREQ : String; + @:require(flash10_1) static final KEYNAME_SYSTEM : String; + @:require(flash10_1) static final KEYNAME_UNDO : String; + @:require(flash10_1) static final KEYNAME_UPARROW : String; + @:require(flash10_1) static final KEYNAME_USER : String; + @:require(flash10_1) static final L : UInt; + @:require(flash10_2) static final LAST : UInt; + static final LEFT : UInt; + @:require(flash10_1) static final LEFTBRACKET : UInt; + @:require(flash10_2) static final LIVE : UInt; + @:require(flash10_1) static final M : UInt; + @:require(flash10_2) static final MASTER_SHELL : UInt; + @:require(flash10_2) static final MENU : UInt; + @:require(flash10_1) static final MINUS : UInt; + @:require(flash10_1) static final N : UInt; + @:require(flash10_2) static final NEXT : UInt; + @:require(flash10_1) static final NUMBER_0 : UInt; + @:require(flash10_1) static final NUMBER_1 : UInt; + @:require(flash10_1) static final NUMBER_2 : UInt; + @:require(flash10_1) static final NUMBER_3 : UInt; + @:require(flash10_1) static final NUMBER_4 : UInt; + @:require(flash10_1) static final NUMBER_5 : UInt; + @:require(flash10_1) static final NUMBER_6 : UInt; + @:require(flash10_1) static final NUMBER_7 : UInt; + @:require(flash10_1) static final NUMBER_8 : UInt; + @:require(flash10_1) static final NUMBER_9 : UInt; + @:require(flash10_1) static final NUMPAD : UInt; + static final NUMPAD_0 : UInt; + static final NUMPAD_1 : UInt; + static final NUMPAD_2 : UInt; + static final NUMPAD_3 : UInt; + static final NUMPAD_4 : UInt; + static final NUMPAD_5 : UInt; + static final NUMPAD_6 : UInt; + static final NUMPAD_7 : UInt; + static final NUMPAD_8 : UInt; + static final NUMPAD_9 : UInt; + static final NUMPAD_ADD : UInt; + static final NUMPAD_DECIMAL : UInt; + static final NUMPAD_DIVIDE : UInt; + static final NUMPAD_ENTER : UInt; + static final NUMPAD_MULTIPLY : UInt; + static final NUMPAD_SUBTRACT : UInt; + @:require(flash10_1) static final O : UInt; + @:require(flash10_1) static final P : UInt; + static final PAGE_DOWN : UInt; + static final PAGE_UP : UInt; + @:require(flash10_2) static final PAUSE : UInt; + @:require(flash10_1) static final PERIOD : UInt; + @:require(flash10_2) static final PLAY : UInt; + static final PLAY_PAUSE : UInt; + @:require(flash10_2) static final PREVIOUS : UInt; + @:require(flash10_1) static final Q : UInt; + @:require(flash10_1) static final QUOTE : UInt; + @:require(flash10_1) static final R : UInt; + @:require(flash10_2) static final RECORD : UInt; + @:require(flash10_2) static final RED : UInt; + @:require(flash10_2) static final REWIND : UInt; + static final RIGHT : UInt; + @:require(flash10_1) static final RIGHTBRACKET : UInt; + @:require(flash10_1) static final S : UInt; + @:require(flash10_2) static final SEARCH : UInt; + @:require(flash10_1) static final SEMICOLON : UInt; + @:require(flash10_2) static final SETUP : UInt; + static final SHIFT : UInt; + @:require(flash10_2) static final SKIP_BACKWARD : UInt; + @:require(flash10_2) static final SKIP_FORWARD : UInt; + @:require(flash10_1) static final SLASH : UInt; + static final SPACE : UInt; + @:require(flash10_2) static final STOP : UInt; + @:require(flash10_1) static final STRING_BEGIN : String; + @:require(flash10_1) static final STRING_BREAK : String; + @:require(flash10_1) static final STRING_CLEARDISPLAY : String; + @:require(flash10_1) static final STRING_CLEARLINE : String; + @:require(flash10_1) static final STRING_DELETE : String; + @:require(flash10_1) static final STRING_DELETECHAR : String; + @:require(flash10_1) static final STRING_DELETELINE : String; + @:require(flash10_1) static final STRING_DOWNARROW : String; + @:require(flash10_1) static final STRING_END : String; + @:require(flash10_1) static final STRING_EXECUTE : String; + @:require(flash10_1) static final STRING_F1 : String; + @:require(flash10_1) static final STRING_F10 : String; + @:require(flash10_1) static final STRING_F11 : String; + @:require(flash10_1) static final STRING_F12 : String; + @:require(flash10_1) static final STRING_F13 : String; + @:require(flash10_1) static final STRING_F14 : String; + @:require(flash10_1) static final STRING_F15 : String; + @:require(flash10_1) static final STRING_F16 : String; + @:require(flash10_1) static final STRING_F17 : String; + @:require(flash10_1) static final STRING_F18 : String; + @:require(flash10_1) static final STRING_F19 : String; + @:require(flash10_1) static final STRING_F2 : String; + @:require(flash10_1) static final STRING_F20 : String; + @:require(flash10_1) static final STRING_F21 : String; + @:require(flash10_1) static final STRING_F22 : String; + @:require(flash10_1) static final STRING_F23 : String; + @:require(flash10_1) static final STRING_F24 : String; + @:require(flash10_1) static final STRING_F25 : String; + @:require(flash10_1) static final STRING_F26 : String; + @:require(flash10_1) static final STRING_F27 : String; + @:require(flash10_1) static final STRING_F28 : String; + @:require(flash10_1) static final STRING_F29 : String; + @:require(flash10_1) static final STRING_F3 : String; + @:require(flash10_1) static final STRING_F30 : String; + @:require(flash10_1) static final STRING_F31 : String; + @:require(flash10_1) static final STRING_F32 : String; + @:require(flash10_1) static final STRING_F33 : String; + @:require(flash10_1) static final STRING_F34 : String; + @:require(flash10_1) static final STRING_F35 : String; + @:require(flash10_1) static final STRING_F4 : String; + @:require(flash10_1) static final STRING_F5 : String; + @:require(flash10_1) static final STRING_F6 : String; + @:require(flash10_1) static final STRING_F7 : String; + @:require(flash10_1) static final STRING_F8 : String; + @:require(flash10_1) static final STRING_F9 : String; + @:require(flash10_1) static final STRING_FIND : String; + @:require(flash10_1) static final STRING_HELP : String; + @:require(flash10_1) static final STRING_HOME : String; + @:require(flash10_1) static final STRING_INSERT : String; + @:require(flash10_1) static final STRING_INSERTCHAR : String; + @:require(flash10_1) static final STRING_INSERTLINE : String; + @:require(flash10_1) static final STRING_LEFTARROW : String; + @:require(flash10_1) static final STRING_MENU : String; + @:require(flash10_1) static final STRING_MODESWITCH : String; + @:require(flash10_1) static final STRING_NEXT : String; + @:require(flash10_1) static final STRING_PAGEDOWN : String; + @:require(flash10_1) static final STRING_PAGEUP : String; + @:require(flash10_1) static final STRING_PAUSE : String; + @:require(flash10_1) static final STRING_PREV : String; + @:require(flash10_1) static final STRING_PRINT : String; + @:require(flash10_1) static final STRING_PRINTSCREEN : String; + @:require(flash10_1) static final STRING_REDO : String; + @:require(flash10_1) static final STRING_RESET : String; + @:require(flash10_1) static final STRING_RIGHTARROW : String; + @:require(flash10_1) static final STRING_SCROLLLOCK : String; + @:require(flash10_1) static final STRING_SELECT : String; + @:require(flash10_1) static final STRING_STOP : String; + @:require(flash10_1) static final STRING_SYSREQ : String; + @:require(flash10_1) static final STRING_SYSTEM : String; + @:require(flash10_1) static final STRING_UNDO : String; + @:require(flash10_1) static final STRING_UPARROW : String; + @:require(flash10_1) static final STRING_USER : String; + @:require(flash10_2) static final SUBTITLE : UInt; + @:require(flash10_1) static final T : UInt; + static final TAB : UInt; + @:require(flash10_1) static final U : UInt; + static final UP : UInt; + @:require(flash10_1) static final V : UInt; + @:require(flash10_2) static final VOD : UInt; + @:require(flash10_1) static final W : UInt; + @:require(flash10_1) static final X : UInt; + @:require(flash10_1) static final Y : UInt; + @:require(flash10_2) static final YELLOW : UInt; + @:require(flash10_1) static final Z : UInt; + @:flash.property static var capsLock(get,never) : Bool; + @:flash.property @:require(flash10_1) static var hasVirtualKeyboard(get,never) : Bool; + @:flash.property static var numLock(get,never) : Bool; + @:flash.property @:require(flash10_1) static var physicalKeyboardType(get,never) : KeyboardType; + private static function get_capsLock() : Bool; + private static function get_hasVirtualKeyboard() : Bool; + private static function get_numLock() : Bool; + private static function get_physicalKeyboardType() : KeyboardType; static function isAccessible() : Bool; } diff --git a/std/flash/ui/KeyboardType.hx b/std/flash/ui/KeyboardType.hx index 1da12b81f2b..f2a589a5c74 100644 --- a/std/flash/ui/KeyboardType.hx +++ b/std/flash/ui/KeyboardType.hx @@ -1,7 +1,7 @@ package flash.ui; -@:fakeEnum(String) extern enum KeyboardType { - ALPHANUMERIC; - KEYPAD; - NONE; +@:native("flash.ui.KeyboardType") extern enum abstract KeyboardType(String) { + var ALPHANUMERIC; + var KEYPAD; + var NONE; } diff --git a/std/flash/ui/Mouse.hx b/std/flash/ui/Mouse.hx index e9070a8e965..18aac659f4a 100644 --- a/std/flash/ui/Mouse.hx +++ b/std/flash/ui/Mouse.hx @@ -1,11 +1,15 @@ package flash.ui; extern class Mouse { - @:require(flash10) static var cursor : Dynamic; - @:require(flash10_1) static var supportsCursor(default,never) : Bool; - @:require(flash11) static var supportsNativeCursor(default,never) : Bool; + @:flash.property @:require(flash10) static var cursor(get,set) : Dynamic; + @:flash.property @:require(flash10_1) static var supportsCursor(get,never) : Bool; + @:flash.property @:require(flash11) static var supportsNativeCursor(get,never) : Bool; + private static function get_cursor() : Dynamic; + private static function get_supportsCursor() : Bool; + private static function get_supportsNativeCursor() : Bool; static function hide() : Void; @:require(flash10_2) static function registerCursor(name : String, cursor : MouseCursorData) : Void; + private static function set_cursor(value : Dynamic) : Dynamic; static function show() : Void; @:require(flash11) static function unregisterCursor(name : String) : Void; } diff --git a/std/flash/ui/MouseCursor.hx b/std/flash/ui/MouseCursor.hx index b5e62e6c5ea..93bd0cc333b 100644 --- a/std/flash/ui/MouseCursor.hx +++ b/std/flash/ui/MouseCursor.hx @@ -1,9 +1,9 @@ package flash.ui; extern class MouseCursor { - static var ARROW(default,never) : String; - static var AUTO(default,never) : String; - static var BUTTON(default,never) : String; - static var HAND(default,never) : String; - static var IBEAM(default,never) : String; + static final ARROW : String; + static final AUTO : String; + static final BUTTON : String; + static final HAND : String; + static final IBEAM : String; } diff --git a/std/flash/ui/MouseCursorData.hx b/std/flash/ui/MouseCursorData.hx index f832e403ddc..93f4db871eb 100644 --- a/std/flash/ui/MouseCursorData.hx +++ b/std/flash/ui/MouseCursorData.hx @@ -1,8 +1,14 @@ package flash.ui; -@:final @:require(flash10_2) extern class MouseCursorData { - var data : flash.Vector; - var frameRate : Float; - var hotSpot : flash.geom.Point; +@:require(flash10_2) extern final class MouseCursorData { + @:flash.property var data(get,set) : flash.Vector; + @:flash.property var frameRate(get,set) : Float; + @:flash.property var hotSpot(get,set) : flash.geom.Point; function new() : Void; + private function get_data() : flash.Vector; + private function get_frameRate() : Float; + private function get_hotSpot() : flash.geom.Point; + private function set_data(value : flash.Vector) : flash.Vector; + private function set_frameRate(value : Float) : Float; + private function set_hotSpot(value : flash.geom.Point) : flash.geom.Point; } diff --git a/std/flash/ui/Multitouch.hx b/std/flash/ui/Multitouch.hx index c1ae7018d21..6cfa29f0d07 100644 --- a/std/flash/ui/Multitouch.hx +++ b/std/flash/ui/Multitouch.hx @@ -1,10 +1,18 @@ package flash.ui; @:require(flash10_1) extern class Multitouch { - static var inputMode : MultitouchInputMode; - static var mapTouchToMouse : Bool; - static var maxTouchPoints(default,never) : Int; - static var supportedGestures(default,never) : flash.Vector; - static var supportsGestureEvents(default,never) : Bool; - static var supportsTouchEvents(default,never) : Bool; + @:flash.property static var inputMode(get,set) : MultitouchInputMode; + @:flash.property static var mapTouchToMouse(get,set) : Bool; + @:flash.property static var maxTouchPoints(get,never) : Int; + @:flash.property static var supportedGestures(get,never) : flash.Vector; + @:flash.property static var supportsGestureEvents(get,never) : Bool; + @:flash.property static var supportsTouchEvents(get,never) : Bool; + private static function get_inputMode() : MultitouchInputMode; + private static function get_mapTouchToMouse() : Bool; + private static function get_maxTouchPoints() : Int; + private static function get_supportedGestures() : flash.Vector; + private static function get_supportsGestureEvents() : Bool; + private static function get_supportsTouchEvents() : Bool; + private static function set_inputMode(value : MultitouchInputMode) : MultitouchInputMode; + private static function set_mapTouchToMouse(value : Bool) : Bool; } diff --git a/std/flash/ui/MultitouchInputMode.hx b/std/flash/ui/MultitouchInputMode.hx index eb4aae5d72e..29cdf5258bf 100644 --- a/std/flash/ui/MultitouchInputMode.hx +++ b/std/flash/ui/MultitouchInputMode.hx @@ -1,7 +1,7 @@ package flash.ui; -@:fakeEnum(String) @:require(flash10_1) extern enum MultitouchInputMode { - GESTURE; - NONE; - TOUCH_POINT; +@:native("flash.ui.MultitouchInputMode") @:require(flash10_1) extern enum abstract MultitouchInputMode(String) { + var GESTURE; + var NONE; + var TOUCH_POINT; } diff --git a/std/flash/utils/ByteArray.hx b/std/flash/utils/ByteArray.hx index f9008156ff9..866b611498d 100644 --- a/std/flash/utils/ByteArray.hx +++ b/std/flash/utils/ByteArray.hx @@ -1,18 +1,24 @@ package flash.utils; extern class ByteArray implements IDataOutput2 implements IDataInput2 implements ArrayAccess { - var bytesAvailable(default,never) : UInt; - var endian : Endian; - var length : UInt; - var objectEncoding : UInt; - var position : UInt; - @:require(flash11_4) var shareable : Bool; + @:flash.property var bytesAvailable(get,never) : UInt; + @:flash.property var endian(get,set) : Endian; + @:flash.property var length(get,set) : UInt; + @:flash.property var objectEncoding(get,set) : UInt; + @:flash.property var position(get,set) : UInt; + @:flash.property @:require(flash11_4) var shareable(get,set) : Bool; function new() : Void; @:require(flash11_4) function atomicCompareAndSwapIntAt(byteIndex : Int, expectedValue : Int, newValue : Int) : Int; @:require(flash11_4) function atomicCompareAndSwapLength(expectedLength : Int, newLength : Int) : Int; @:require(flash10) function clear() : Void; function compress(?algorithm : CompressionAlgorithm) : Void; @:require(flash10) function deflate() : Void; + private function get_bytesAvailable() : UInt; + private function get_endian() : Endian; + private function get_length() : UInt; + private function get_objectEncoding() : UInt; + private function get_position() : UInt; + private function get_shareable() : Bool; @:require(flash10) function inflate() : Void; function readBoolean() : Bool; function readByte() : Int; @@ -28,6 +34,11 @@ extern class ByteArray implements IDataOutput2 implements IDataInput2 implements function readUnsignedByte() : UInt; function readUnsignedInt() : UInt; function readUnsignedShort() : UInt; + private function set_endian(value : Endian) : Endian; + private function set_length(value : UInt) : UInt; + private function set_objectEncoding(value : UInt) : UInt; + private function set_position(value : UInt) : UInt; + private function set_shareable(value : Bool) : Bool; function toString() : String; function uncompress(?algorithm : CompressionAlgorithm) : Void; function writeBoolean(value : Bool) : Void; @@ -42,5 +53,7 @@ extern class ByteArray implements IDataOutput2 implements IDataInput2 implements function writeUTF(value : String) : Void; function writeUTFBytes(value : String) : Void; function writeUnsignedInt(value : UInt) : Void; - static var defaultObjectEncoding : UInt; + @:flash.property static var defaultObjectEncoding(get,set) : UInt; + private static function get_defaultObjectEncoding() : UInt; + private static function set_defaultObjectEncoding(value : UInt) : UInt; } diff --git a/std/flash/utils/CompressionAlgorithm.hx b/std/flash/utils/CompressionAlgorithm.hx index 5f22bdc8210..b2057a7236a 100644 --- a/std/flash/utils/CompressionAlgorithm.hx +++ b/std/flash/utils/CompressionAlgorithm.hx @@ -1,7 +1,7 @@ package flash.utils; -@:fakeEnum(String) @:require(flash11) extern enum CompressionAlgorithm { - DEFLATE; - LZMA; - ZLIB; +@:native("flash.utils.CompressionAlgorithm") @:require(flash11) extern enum abstract CompressionAlgorithm(String) { + var DEFLATE; + var LZMA; + var ZLIB; } diff --git a/std/flash/utils/Endian.hx b/std/flash/utils/Endian.hx index 59ca426208c..9378bc480a4 100644 --- a/std/flash/utils/Endian.hx +++ b/std/flash/utils/Endian.hx @@ -1,6 +1,6 @@ package flash.utils; -@:fakeEnum(String) extern enum Endian { - BIG_ENDIAN; - LITTLE_ENDIAN; +@:native("flash.utils.Endian") extern enum abstract Endian(String) { + var BIG_ENDIAN; + var LITTLE_ENDIAN; } diff --git a/std/flash/utils/IDataInput.hx b/std/flash/utils/IDataInput.hx index 0f51a1c1bd0..e60c2c36cde 100644 --- a/std/flash/utils/IDataInput.hx +++ b/std/flash/utils/IDataInput.hx @@ -1,9 +1,12 @@ package flash.utils; extern interface IDataInput { - var bytesAvailable(default,never) : UInt; - var endian : Endian; - var objectEncoding : UInt; + @:flash.property var bytesAvailable(get,never) : UInt; + @:flash.property var endian(get,set) : Endian; + @:flash.property var objectEncoding(get,set) : UInt; + private function get_bytesAvailable() : UInt; + private function get_endian() : Endian; + private function get_objectEncoding() : UInt; function readBoolean() : Bool; function readByte() : Int; function readBytes(bytes : ByteArray, offset : UInt = 0, length : UInt = 0) : Void; @@ -18,4 +21,6 @@ extern interface IDataInput { function readUnsignedByte() : UInt; function readUnsignedInt() : UInt; function readUnsignedShort() : UInt; + private function set_endian(value : Endian) : Endian; + private function set_objectEncoding(value : UInt) : UInt; } diff --git a/std/flash/utils/IDataOutput.hx b/std/flash/utils/IDataOutput.hx index 53b3bbb909f..c5db43289ba 100644 --- a/std/flash/utils/IDataOutput.hx +++ b/std/flash/utils/IDataOutput.hx @@ -1,8 +1,12 @@ package flash.utils; extern interface IDataOutput { - var endian : Endian; - var objectEncoding : UInt; + @:flash.property var endian(get,set) : Endian; + @:flash.property var objectEncoding(get,set) : UInt; + private function get_endian() : Endian; + private function get_objectEncoding() : UInt; + private function set_endian(value : Endian) : Endian; + private function set_objectEncoding(value : UInt) : UInt; function writeBoolean(value : Bool) : Void; function writeByte(value : Int) : Void; function writeBytes(bytes : ByteArray, offset : UInt = 0, length : UInt = 0) : Void; diff --git a/std/flash/utils/Namespace.hx b/std/flash/utils/Namespace.hx index 8531ba908d3..ea08b670446 100644 --- a/std/flash/utils/Namespace.hx +++ b/std/flash/utils/Namespace.hx @@ -1,7 +1,9 @@ package flash.utils; -@:final extern class Namespace { - var prefix(default,never) : Dynamic; - var uri(default,never) : String; +extern final class Namespace { + @:flash.property var prefix(get,never) : Dynamic; + @:flash.property var uri(get,never) : String; function new(?prefix : Dynamic, ?uri : Dynamic) : Void; + private function get_prefix() : Dynamic; + private function get_uri() : String; } diff --git a/std/flash/utils/Object.hx b/std/flash/utils/Object.hx index 39b10eafa52..94f153cfbad 100644 --- a/std/flash/utils/Object.hx +++ b/std/flash/utils/Object.hx @@ -1,3 +1,4 @@ package flash.utils; -typedef Object = Dynamic +@:coreType @:runtimeValue +abstract Object from Dynamic to Dynamic {} diff --git a/std/flash/utils/ObjectInput.hx b/std/flash/utils/ObjectInput.hx index 871a009e540..b2620be710d 100644 --- a/std/flash/utils/ObjectInput.hx +++ b/std/flash/utils/ObjectInput.hx @@ -1,10 +1,13 @@ package flash.utils; extern class ObjectInput implements IDataInput { - var bytesAvailable(default,never) : UInt; - var endian : Endian; - var objectEncoding : UInt; + @:flash.property var bytesAvailable(get,never) : UInt; + @:flash.property var endian(get,set) : Endian; + @:flash.property var objectEncoding(get,set) : UInt; function new() : Void; + private function get_bytesAvailable() : UInt; + private function get_endian() : Endian; + private function get_objectEncoding() : UInt; function readBoolean() : Bool; function readByte() : Int; function readBytes(bytes : ByteArray, offset : UInt = 0, length : UInt = 0) : Void; @@ -19,4 +22,6 @@ extern class ObjectInput implements IDataInput { function readUnsignedByte() : UInt; function readUnsignedInt() : UInt; function readUnsignedShort() : UInt; + private function set_endian(value : Endian) : Endian; + private function set_objectEncoding(value : UInt) : UInt; } diff --git a/std/flash/utils/ObjectOutput.hx b/std/flash/utils/ObjectOutput.hx index c6dc82a4117..4e856459a0f 100644 --- a/std/flash/utils/ObjectOutput.hx +++ b/std/flash/utils/ObjectOutput.hx @@ -1,9 +1,13 @@ package flash.utils; extern class ObjectOutput implements IDataOutput { - var endian : Endian; - var objectEncoding : UInt; + @:flash.property var endian(get,set) : Endian; + @:flash.property var objectEncoding(get,set) : UInt; function new() : Void; + private function get_endian() : Endian; + private function get_objectEncoding() : UInt; + private function set_endian(value : Endian) : Endian; + private function set_objectEncoding(value : UInt) : UInt; function writeBoolean(value : Bool) : Void; function writeByte(value : Int) : Void; function writeBytes(bytes : ByteArray, offset : UInt = 0, length : UInt = 0) : Void; diff --git a/std/flash/utils/Proxy.hx b/std/flash/utils/Proxy.hx index 2ad1568d078..0cddd76fcd0 100644 --- a/std/flash/utils/Proxy.hx +++ b/std/flash/utils/Proxy.hx @@ -2,7 +2,7 @@ package flash.utils; extern class Proxy { function new() : Void; - @:ns("http://www.adobe.com/2006/actionscript/flash/proxy") function callProperty(name : Dynamic, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Dynamic; + @:ns("http://www.adobe.com/2006/actionscript/flash/proxy") function callProperty(name : Dynamic, restArgs : haxe.extern.Rest) : Dynamic; @:ns("http://www.adobe.com/2006/actionscript/flash/proxy") function deleteProperty(name : Dynamic) : Bool; @:ns("http://www.adobe.com/2006/actionscript/flash/proxy") function getDescendants(name : Dynamic) : Dynamic; @:ns("http://www.adobe.com/2006/actionscript/flash/proxy") function getProperty(name : Dynamic) : Dynamic; diff --git a/std/flash/utils/QName.hx b/std/flash/utils/QName.hx index bf5a4ef9b1d..1ceb4bb3465 100644 --- a/std/flash/utils/QName.hx +++ b/std/flash/utils/QName.hx @@ -1,7 +1,9 @@ package flash.utils; -@:final extern class QName { - var localName(default,never) : String; - var uri(default,never) : Dynamic; +extern final class QName { + @:flash.property var localName(get,never) : String; + @:flash.property var uri(get,never) : Dynamic; function new(?namespace : Dynamic, ?name : Dynamic) : Void; + private function get_localName() : String; + private function get_uri() : Dynamic; } diff --git a/std/flash/utils/RegExp.hx b/std/flash/utils/RegExp.hx index 26b01c3dc21..fc20310b5c8 100644 --- a/std/flash/utils/RegExp.hx +++ b/std/flash/utils/RegExp.hx @@ -1,14 +1,22 @@ package flash.utils; @:realPath("flash.utils.RegExp") @:native("RegExp") extern class RegExp implements Dynamic { - var dotall(default,never) : Bool; - var extended(default,never) : Bool; - var global(default,never) : Bool; - var ignoreCase(default,never) : Bool; - var lastIndex : Int; - var multiline(default,never) : Bool; - var source(default,never) : String; + @:flash.property var dotall(get,never) : Bool; + @:flash.property var extended(get,never) : Bool; + @:flash.property var global(get,never) : Bool; + @:flash.property var ignoreCase(get,never) : Bool; + @:flash.property var lastIndex(get,set) : Int; + @:flash.property var multiline(get,never) : Bool; + @:flash.property var source(get,never) : String; function new(?pattern : Dynamic, ?options : Dynamic) : Void; @:ns("http://adobe.com/AS3/2006/builtin") function exec(?s : String) : Dynamic; + private function get_dotall() : Bool; + private function get_extended() : Bool; + private function get_global() : Bool; + private function get_ignoreCase() : Bool; + private function get_lastIndex() : Int; + private function get_multiline() : Bool; + private function get_source() : String; + private function set_lastIndex(value : Int) : Int; @:ns("http://adobe.com/AS3/2006/builtin") function test(?s : String) : Bool; } diff --git a/std/flash/utils/SetIntervalTimer.hx b/std/flash/utils/SetIntervalTimer.hx index 08ff9b6bb45..1c0c589f371 100644 --- a/std/flash/utils/SetIntervalTimer.hx +++ b/std/flash/utils/SetIntervalTimer.hx @@ -1,7 +1,7 @@ package flash.utils; -@:final extern class SetIntervalTimer extends Timer { - var id : UInt; +extern final class SetIntervalTimer extends Timer { + @:ns("flash.utils",internal) var id : UInt; function new(closure : Dynamic, delay : Float, repeats : Bool, rest : Array) : Void; - static function clearInterval(id_to_clear : UInt) : Void; + @:ns("flash.utils",internal) static function clearInterval(id_to_clear : UInt) : Void; } diff --git a/std/flash/utils/Timer.hx b/std/flash/utils/Timer.hx index 728f9c5c993..9e5029a0390 100644 --- a/std/flash/utils/Timer.hx +++ b/std/flash/utils/Timer.hx @@ -1,12 +1,18 @@ package flash.utils; extern class Timer extends flash.events.EventDispatcher { - var currentCount(default,never) : Int; - var delay : Float; - var repeatCount : Int; - var running(default,never) : Bool; + @:flash.property var currentCount(get,never) : Int; + @:flash.property var delay(get,set) : Float; + @:flash.property var repeatCount(get,set) : Int; + @:flash.property var running(get,never) : Bool; function new(delay : Float, repeatCount : Int = 0) : Void; + private function get_currentCount() : Int; + private function get_delay() : Float; + private function get_repeatCount() : Int; + private function get_running() : Bool; function reset() : Void; + private function set_delay(value : Float) : Float; + private function set_repeatCount(value : Int) : Int; function start() : Void; function stop() : Void; } diff --git a/std/flash/xml/XML.hx b/std/flash/xml/XML.hx index c52dc049d3a..2ba80c26491 100644 --- a/std/flash/xml/XML.hx +++ b/std/flash/xml/XML.hx @@ -1,6 +1,6 @@ package flash.xml; -@:final extern class XML implements Dynamic { +extern final class XML implements Dynamic { function new(?value : Dynamic) : Void; function addNamespace(ns : Dynamic) : XML; function appendChild(child : Dynamic) : XML; @@ -42,12 +42,22 @@ package flash.xml; function toString() : String; function toXMLString() : String; function valueOf() : XML; - static var ignoreComments : Bool; - static var ignoreProcessingInstructions : Bool; - static var ignoreWhitespace : Bool; - static var prettyIndent : Int; - static var prettyPrinting : Bool; + @:flash.property static var ignoreComments(get,set) : Bool; + @:flash.property static var ignoreProcessingInstructions(get,set) : Bool; + @:flash.property static var ignoreWhitespace(get,set) : Bool; + @:flash.property static var prettyIndent(get,set) : Int; + @:flash.property static var prettyPrinting(get,set) : Bool; static function defaultSettings() : Dynamic; + private static function get_ignoreComments() : Bool; + private static function get_ignoreProcessingInstructions() : Bool; + private static function get_ignoreWhitespace() : Bool; + private static function get_prettyIndent() : Int; + private static function get_prettyPrinting() : Bool; static function setSettings(?o : Dynamic) : Void; + private static function set_ignoreComments(value : Bool) : Bool; + private static function set_ignoreProcessingInstructions(value : Bool) : Bool; + private static function set_ignoreWhitespace(value : Bool) : Bool; + private static function set_prettyIndent(value : Int) : Int; + private static function set_prettyPrinting(value : Bool) : Bool; static function settings() : Dynamic; } diff --git a/std/flash/xml/XMLList.hx b/std/flash/xml/XMLList.hx index 456849ac1d0..d46b83a958a 100644 --- a/std/flash/xml/XMLList.hx +++ b/std/flash/xml/XMLList.hx @@ -1,6 +1,6 @@ package flash.xml; -@:final extern class XMLList implements ArrayAccess { +extern final class XMLList implements ArrayAccess { function new(?value : Dynamic) : Void; function addNamespace(ns : Dynamic) : XML; function appendChild(child : Dynamic) : XML; diff --git a/std/flash/xml/XMLNode.hx b/std/flash/xml/XMLNode.hx index 4dc45a57970..9ba371d13ad 100644 --- a/std/flash/xml/XMLNode.hx +++ b/std/flash/xml/XMLNode.hx @@ -1,26 +1,32 @@ package flash.xml; extern class XMLNode { - var attributes : Dynamic; - var childNodes(default,never) : Array; + @:flash.property var attributes(get,set) : Dynamic; + @:flash.property var childNodes(get,never) : Array; var firstChild : XMLNode; var lastChild : XMLNode; - var localName(default,never) : String; - var namespaceURI(default,never) : String; + @:flash.property var localName(get,never) : String; + @:flash.property var namespaceURI(get,never) : String; var nextSibling : XMLNode; var nodeName : String; var nodeType : XMLNodeType; var nodeValue : String; var parentNode : XMLNode; - var prefix(default,never) : String; + @:flash.property var prefix(get,never) : String; var previousSibling : XMLNode; function new(type : XMLNodeType, value : String) : Void; function appendChild(node : XMLNode) : Void; function cloneNode(deep : Bool) : XMLNode; function getNamespaceForPrefix(prefix : String) : String; function getPrefixForNamespace(ns : String) : String; + private function get_attributes() : Dynamic; + private function get_childNodes() : Array; + private function get_localName() : String; + private function get_namespaceURI() : String; + private function get_prefix() : String; function hasChildNodes() : Bool; function insertBefore(node : XMLNode, before : XMLNode) : Void; function removeNode() : Void; + private function set_attributes(value : Dynamic) : Dynamic; function toString() : String; } diff --git a/std/flash/xml/XMLNodeType.hx b/std/flash/xml/XMLNodeType.hx index 6b728e6375f..36f75cbba6d 100644 --- a/std/flash/xml/XMLNodeType.hx +++ b/std/flash/xml/XMLNodeType.hx @@ -1,11 +1,11 @@ package flash.xml; -@:fakeEnum(UInt) extern enum XMLNodeType { - CDATA_NODE; - COMMENT_NODE; - DOCUMENT_TYPE_NODE; - ELEMENT_NODE; - PROCESSING_INSTRUCTION_NODE; - TEXT_NODE; - XML_DECLARATION; +@:native("flash.xml.XMLNodeType") extern enum abstract XMLNodeType(UInt) { + var CDATA_NODE; + var COMMENT_NODE; + var DOCUMENT_TYPE_NODE; + var ELEMENT_NODE; + var PROCESSING_INSTRUCTION_NODE; + var TEXT_NODE; + var XML_DECLARATION; } diff --git a/std/flash/xml/XMLParser.hx b/std/flash/xml/XMLParser.hx index d21660bea1e..ef9441d9abe 100644 --- a/std/flash/xml/XMLParser.hx +++ b/std/flash/xml/XMLParser.hx @@ -1,6 +1,6 @@ package flash.xml; -@:final extern class XMLParser { +extern final class XMLParser { function new() : Void; function getNext(tag : XMLTag) : Int; function startParse(source : String, ignoreWhite : Bool) : Void; diff --git a/std/flash/xml/XMLTag.hx b/std/flash/xml/XMLTag.hx index dcddbd01178..468fda40ab9 100644 --- a/std/flash/xml/XMLTag.hx +++ b/std/flash/xml/XMLTag.hx @@ -1,9 +1,17 @@ package flash.xml; -@:final extern class XMLTag { - var attrs : Dynamic; - var empty : Bool; - var type : XMLNodeType; - var value : String; +extern final class XMLTag { + @:flash.property var attrs(get,set) : Dynamic; + @:flash.property var empty(get,set) : Bool; + @:flash.property var type(get,set) : XMLNodeType; + @:flash.property var value(get,set) : String; function new() : Void; + private function get_attrs() : Dynamic; + private function get_empty() : Bool; + private function get_type() : XMLNodeType; + private function get_value() : String; + private function set_attrs(value : Dynamic) : Dynamic; + private function set_empty(value : Bool) : Bool; + private function set_type(value : XMLNodeType) : XMLNodeType; + private function set_value(value : String) : String; } diff --git a/std/haxe/CallStack.hx b/std/haxe/CallStack.hx index a6bfbf6a104..8e98b8c7a93 100644 --- a/std/haxe/CallStack.hx +++ b/std/haxe/CallStack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; /** @@ -26,10 +27,10 @@ package haxe; **/ enum StackItem { CFunction; - Module( m : String ); - FilePos( s : Null, file : String, line : Int ); - Method( classname : String, method : String ); - LocalFunction( ?v : Int ); + Module(m:String); + FilePos(s:Null, file:String, line:Int, ?column:Null); + Method(classname:Null, method:String); + LocalFunction(?v:Int); } /** @@ -37,27 +38,33 @@ enum StackItem { **/ class CallStack { #if js - static var lastException:js.Error; + static var lastException:js.lib.Error; - static function getStack(e:js.Error):Array { - if (e == null) return []; + static function getStack(e:js.lib.Error):Array { + if (e == null) + return []; // https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi var oldValue = (untyped Error).prepareStackTrace; - (untyped Error).prepareStackTrace = function (error, callsites :Array) { + (untyped Error).prepareStackTrace = function(error, callsites:Array) { var stack = []; for (site in callsites) { - if (wrapCallSite != null) site = wrapCallSite(site); + if (wrapCallSite != null) + site = wrapCallSite(site); var method = null; - var fullName :String = site.getFunctionName(); + var fullName:String = site.getFunctionName(); if (fullName != null) { var idx = fullName.lastIndexOf("."); if (idx >= 0) { var className = fullName.substr(0, idx); - var methodName = fullName.substr(idx+1); + var methodName = fullName.substr(idx + 1); method = Method(className, methodName); } } - stack.push(FilePos(method, site.getFileName(), site.getLineNumber())); + var fileName:String = site.getFileName(); + var fileAddr = fileName == null ? -1 : fileName.indexOf("file:"); + if (wrapCallSite != null && fileAddr > 0) + fileName = fileName.substr(fileAddr + 6); + stack.push(FilePos(method, fileName, site.getLineNumber(), site.getColumnNumber())); } return stack; } @@ -72,91 +79,105 @@ class CallStack { #end #if eval - static function getCallStack() { return []; } - static function getExceptionStack() { return []; } + static function getCallStack() { + return []; + } + + static function getExceptionStack() { + return []; + } #end /** Return the call stack elements, or an empty array if not available. **/ - public static function callStack() : Array { + public static function callStack():Array { #if neko - var a = makeStack(untyped __dollar__callstack()); - a.shift(); // remove Stack.callStack() - return a; + var a = makeStack(untyped __dollar__callstack()); + a.shift(); // remove Stack.callStack() + return a; #elseif flash - var a = makeStack( new flash.errors.Error().getStackTrace() ); - a.shift(); // remove Stack.callStack() - return a; + var a = makeStack(new flash.errors.Error().getStackTrace()); + a.shift(); // remove Stack.callStack() + return a; #elseif cpp - var s:Array = untyped __global__.__hxcpp_get_call_stack(true); - return makeStack(s); + var s:Array = untyped __global__.__hxcpp_get_call_stack(true); + return makeStack(s); #elseif js - try { - throw new js.Error(); - } catch( e : Dynamic ) { - var a = getStack(e); - a.shift(); // remove Stack.callStack() - return a; - } - + try { + throw new js.lib.Error(); + } catch (e:Dynamic) { + var a = getStack(js.Lib.getOriginalException()); + a.shift(); // remove Stack.callStack() + return a; + } #elseif java - var stack = []; - for ( el in java.lang.Thread.currentThread().getStackTrace() ) { - var className = el.getClassName(); - var methodName = el.getMethodName(); - var fileName = el.getFileName(); - var lineNumber = el.getLineNumber(); - var method = Method( className, methodName ); - if ( fileName != null || lineNumber >= 0 ) { - stack.push( FilePos( method, fileName, lineNumber ) ); - } - else { - stack.push( method ); - } + var stack = []; + for (el in java.lang.Thread.currentThread().getStackTrace()) { + var className = el.getClassName(); + var methodName = el.getMethodName(); + var fileName = el.getFileName(); + var lineNumber = el.getLineNumber(); + var method = Method(className, methodName); + if (fileName != null || lineNumber >= 0) { + stack.push(FilePos(method, fileName, lineNumber)); + } else { + stack.push(method); } - stack.shift(); - stack.shift(); - stack.pop(); - return stack; + } + stack.shift(); + stack.shift(); + stack.pop(); + return stack; #elseif cs - return makeStack(new cs.system.diagnostics.StackTrace(1, true)); + return makeStack(new cs.system.diagnostics.StackTrace(1, true)); #elseif python - var stack = []; - var infos = python.lib.Traceback.extract_stack(); - infos.pop(); - infos.reverse(); - for (elem in infos) - stack.push(FilePos(null, elem._1, elem._2)); - return stack; + var stack = []; + var infos = python.lib.Traceback.extract_stack(); + infos.pop(); + infos.reverse(); + for (elem in infos) + stack.push(FilePos(Method(null, elem._3), elem._1, elem._2)); + return stack; #elseif lua - var stack = []; - var infos = lua.Debug.traceback(); - var luastack = infos.split("\n").slice(2,-1); - for (s in luastack){ - var parts = s.split(":"); - var file = parts[0]; - var line = parts[1]; - // TODO: Give more information for FilePos - stack.push(FilePos(null, file, Std.parseInt(line))); + var stack = []; + var infos = lua.Debug.traceback(); + var luastack = infos.split("\n").slice(2, -1); + for (s in luastack) { + var parts = s.split(":"); + var file = parts[0]; + var line = parts[1]; + var method = if(parts.length <= 2) { + null; + } else { + var methodPos = parts[2].indexOf("'"); + if(methodPos < 0) { + null; + } else { + Method(null, parts[2].substring(methodPos + 1, parts[2].length - 1)); + } } - return stack; + stack.push(FilePos(method, file, Std.parseInt(line))); + } + return stack; #elseif hl - try { - throw null; - } catch( e : Dynamic ) { - var st = _getExceptionStack(); - return makeStack(st.length > 2 ? st.sub(2,st.length - 2) : st); - } + try { + throw null; + } catch (e:Dynamic) { + var st = _getExceptionStack(); + return makeStack(st.length > 2 ? st.sub(2, st.length - 2) : st); + } #elseif eval - return getCallStack(); + return getCallStack(); #else - return []; // Unsupported + return []; // Unsupported #end } #if hl - @:hlNative("std", "exception_stack") static function _getExceptionStack() : hl.NativeArray { return null; } + @:hlNative("std", "exception_stack") static function _getExceptionStack():hl.NativeArray { + return null; + } #end /** @@ -164,215 +185,231 @@ class CallStack { the place the last exception was thrown and the place it was caught, or an empty array if not available. **/ - #if cpp @:noDebug #end /* Do not mess up the exception stack */ - public static function exceptionStack() : Array { + #if cpp + @:noDebug /* Do not mess up the exception stack */ + #end + public static function exceptionStack():Array { #if neko - return makeStack(untyped __dollar__excstack()); + return makeStack(untyped __dollar__excstack()); #elseif as3 - return new Array(); + return new Array(); #elseif hl - return makeStack(_getExceptionStack()); + return makeStack(_getExceptionStack()); #elseif flash - var err : flash.errors.Error = untyped flash.Boot.lastError; - if( err == null ) return new Array(); - var a = makeStack( err.getStackTrace() ); - var c = callStack(); - var i = c.length - 1; - while( i > 0 ) { - if( Std.string(a[a.length-1]) == Std.string(c[i]) ) - a.pop(); - else - break; - i--; - } - return a; + var err:flash.errors.Error = untyped flash.Boot.lastError; + if (err == null) + return new Array(); + var a = makeStack(err.getStackTrace()); + var c = callStack(); + var i = c.length - 1; + while (i > 0) { + if (Std.string(a[a.length - 1]) == Std.string(c[i])) + a.pop(); + else + break; + i--; + } + return a; #elseif cpp - var s:Array = untyped __global__.__hxcpp_get_exception_stack(); - return makeStack(s); + var s:Array = untyped __global__.__hxcpp_get_exception_stack(); + return makeStack(s); #elseif java - var stack = []; - for ( el in java.internal.Exceptions.currentException().getStackTrace() ) { - var className = el.getClassName(); - var methodName = el.getMethodName(); - var fileName = el.getFileName(); - var lineNumber = el.getLineNumber(); - var method = Method( className, methodName ); - if ( fileName != null || lineNumber >= 0 ) { - stack.push( FilePos( method, fileName, lineNumber ) ); - } - else { - stack.push( method ); + var stack = []; + switch (#if jvm jvm.Exception #else java.internal.Exceptions #end.currentException()) { + case null: + case current: + for (el in current.getStackTrace()) { + var className = el.getClassName(); + var methodName = el.getMethodName(); + var fileName = el.getFileName(); + var lineNumber = el.getLineNumber(); + var method = Method(className, methodName); + if (fileName != null || lineNumber >= 0) { + stack.push(FilePos(method, fileName, lineNumber)); + } else { + stack.push(method); + } } - } - return stack; + } + return stack; #elseif cs - return makeStack(new cs.system.diagnostics.StackTrace(cs.internal.Exceptions.exception, true)); + return cs.internal.Exceptions.exception == null ? [] : makeStack(new cs.system.diagnostics.StackTrace(cs.internal.Exceptions.exception, true)); #elseif python - var stack = []; - var exc = python.lib.Sys.exc_info(); - if (exc._3 != null) - { - var infos = python.lib.Traceback.extract_tb(exc._3); - infos.reverse(); - for (elem in infos) - stack.push(FilePos(null, elem._1, elem._2)); - } - return stack; + var stack = []; + var exc = python.lib.Sys.exc_info(); + if (exc._3 != null) { + var infos = python.lib.Traceback.extract_tb(exc._3); + infos.reverse(); + for (elem in infos) + stack.push(FilePos(Method(null, elem._3), elem._1, elem._2)); + } + return stack; #elseif js - return untyped __define_feature__("haxe.CallStack.exceptionStack", getStack(lastException)); + return getStack(lastException); #elseif eval - return getExceptionStack(); + return getExceptionStack(); #else - return []; // Unsupported + return []; // Unsupported #end } /** Returns a representation of the stack as a printable string. **/ - public static function toString( stack : Array ) { + public static function toString(stack:Array) { var b = new StringBuf(); - for( s in stack ) { + for (s in stack) { b.add("\nCalled from "); - itemToString(b,s); + itemToString(b, s); } return b.toString(); } - private static function itemToString( b : StringBuf, s ) { - switch( s ) { - case CFunction: - b.add("a C function"); - case Module(m): - b.add("module "); - b.add(m); - case FilePos(s,file,line): - if( s != null ) { - itemToString(b,s); - b.add(" ("); - } - b.add(file); - b.add(" line "); - b.add(line); - if( s != null ) b.add(")"); - case Method(cname,meth): - b.add(cname); - b.add("."); - b.add(meth); - case LocalFunction(n): - b.add("local function #"); - b.add(n); + private static function itemToString(b:StringBuf, s) { + switch (s) { + case CFunction: + b.add("a C function"); + case Module(m): + b.add("module "); + b.add(m); + case FilePos(s, file, line, col): + if (s != null) { + itemToString(b, s); + b.add(" ("); + } + b.add(file); + b.add(" line "); + b.add(line); + if (col != null) { + b.add(" column "); + b.add(col); + } + if (s != null) + b.add(")"); + case Method(cname, meth): + b.add(cname == null ? "" : cname); + b.add("."); + b.add(meth); + case LocalFunction(n): + b.add("local function #"); + b.add(n); } } - #if cpp @:noDebug #end /* Do not mess up the exception stack */ - private static function makeStack(s #if cs : cs.system.diagnostics.StackTrace #elseif hl : hl.NativeArray #else : Dynamic #end) { + #if cpp + @:noDebug /* Do not mess up the exception stack */ + #end + private static function makeStack(s #if cs:cs.system.diagnostics.StackTrace #elseif hl:hl.NativeArray #else:Dynamic #end) { #if neko - var a = new Array(); - var l = untyped __dollar__asize(s); - var i = 0; - while( i < l ) { - var x = s[i++]; - if( x == null ) - a.unshift(CFunction); - else if( untyped __dollar__typeof(x) == __dollar__tstring ) - a.unshift(Module(new String(x))); - else - a.unshift(FilePos(null,new String(untyped x[0]),untyped x[1])); - } - return a; + var a = new Array(); + var l = untyped __dollar__asize(s); + var i = 0; + while (i < l) { + var x = s[i++]; + if (x == null) + a.unshift(CFunction); + else if (untyped __dollar__typeof(x) == __dollar__tstring) + a.unshift(Module(new String(x))); + else + a.unshift(FilePos(null, new String(untyped x[0]), untyped x[1])); + } + return a; #elseif flash - var a = new Array(); - var r = ~/at ([^\/]+?)\$?(\/[^\(]+)?\(\)(\[(.*?):([0-9]+)\])?/; - var rlambda = ~/^MethodInfo-([0-9]+)$/g; - while( r.match(s) ) { - var cl = r.matched(1).split("::").join("."); - var meth = r.matched(2); - var item; - if( meth == null ) { - if( rlambda.match(cl) ) - item = LocalFunction(Std.parseInt(rlambda.matched(1))); - else - item = Method(cl,"new"); - } else - item = Method(cl,meth.substr(1)); - if( r.matched(3) != null ) - item = FilePos( item, r.matched(4), Std.parseInt(r.matched(5)) ); - a.push(item); - s = r.matchedRight(); - } - return a; + var a = new Array(); + var r = ~/at ([^\/]+?)\$?(\/[^\(]+)?\(\)(\[(.*?):([0-9]+)\])?/; + var rlambda = ~/^MethodInfo-([0-9]+)$/g; + while (r.match(s)) { + var cl = r.matched(1).split("::").join("."); + var meth = r.matched(2); + var item; + if (meth == null) { + if (rlambda.match(cl)) + item = LocalFunction(Std.parseInt(rlambda.matched(1))); + else + item = Method(cl, "new"); + } else + item = Method(cl, meth.substr(1)); + if (r.matched(3) != null) + item = FilePos(item, r.matched(4), Std.parseInt(r.matched(5))); + a.push(item); + s = r.matchedRight(); + } + return a; #elseif cpp - var stack : Array = s; - var m = new Array(); - for(func in stack) { - var words = func.split("::"); - if (words.length==0) - m.push(CFunction) - else if (words.length==2) - m.push(Method(words[0],words[1])); - else if (words.length==4) - m.push(FilePos( Method(words[0],words[1]),words[2],Std.parseInt(words[3]))); - } - return m; + var stack:Array = s; + var m = new Array(); + for (func in stack) { + var words = func.split("::"); + if (words.length == 0) + m.push(CFunction) + else if (words.length == 2) + m.push(Method(words[0], words[1])); + else if (words.length == 4) + m.push(FilePos(Method(words[0], words[1]), words[2], Std.parseInt(words[3]))); + } + return m; #elseif js - if (s == null) { - return []; - } else if (js.Lib.typeof(s) == "string") { - // Return the raw lines in browsers that don't support prepareStackTrace - var stack : Array = s.split("\n"); - if( stack[0] == "Error" ) stack.shift(); - var m = []; - var rie10 = ~/^ at ([A-Za-z0-9_. ]+) \(([^)]+):([0-9]+):([0-9]+)\)$/; - for( line in stack ) { - if( rie10.match(line) ) { - var path = rie10.matched(1).split("."); - var meth = path.pop(); - var file = rie10.matched(2); - var line = Std.parseInt(rie10.matched(3)); - m.push(FilePos( meth == "Anonymous function" ? LocalFunction() : meth == "Global code" ? null : Method(path.join("."),meth), file, line )); - } else - m.push(Module(StringTools.trim(line))); // A little weird, but better than nothing - } - return m; - } else { - return cast s; + if (s == null) { + return []; + } else if (js.Syntax.typeof(s) == "string") { + // Return the raw lines in browsers that don't support prepareStackTrace + var stack:Array = s.split("\n"); + if (stack[0] == "Error") + stack.shift(); + var m = []; + var rie10 = ~/^ at ([A-Za-z0-9_. ]+) \(([^)]+):([0-9]+):([0-9]+)\)$/; + for (line in stack) { + if (rie10.match(line)) { + var path = rie10.matched(1).split("."); + var meth = path.pop(); + var file = rie10.matched(2); + var line = Std.parseInt(rie10.matched(3)); + var column = Std.parseInt(rie10.matched(4)); + m.push(FilePos(meth == "Anonymous function" ? LocalFunction() : meth == "Global code" ? null : Method(path.join("."), meth), file, line, + column)); + } else + m.push(Module(StringTools.trim(line))); // A little weird, but better than nothing } + return m; + } else { + return cast s; + } #elseif cs - var stack = []; - for (i in 0...s.FrameCount) - { - var frame = s.GetFrame(i); - var m = frame.GetMethod(); + var stack = []; + for (i in 0...s.FrameCount) { + var frame = s.GetFrame(i); + var m = frame.GetMethod(); - if (m == null) { - continue; - } - var method = StackItem.Method(m.ReflectedType.ToString(), m.Name); + if (m == null) { + continue; + } + var method = StackItem.Method(m.ReflectedType.ToString(), m.Name); - var fileName = frame.GetFileName(); - var lineNumber = frame.GetFileLineNumber(); + var fileName = frame.GetFileName(); + var lineNumber = frame.GetFileLineNumber(); - if (fileName != null || lineNumber >= 0) - stack.push(FilePos(method, fileName, lineNumber)); - else - stack.push(method); - } - return stack; + if (fileName != null || lineNumber >= 0) + stack.push(FilePos(method, fileName, lineNumber)); + else + stack.push(method); + } + return stack; #elseif hl - var stack = []; - var r = ~/^([A-Za-z0-9.$_]+)\.([A-Za-z0-9_]+)\((.+):([0-9]+)\)$/; - for( i in 0...s.length-1 ) { - var str = @:privateAccess String.fromUCS2(s[i]); - if( r.match(str) ) - stack.push(FilePos(Method(r.matched(1), r.matched(2)), r.matched(3), Std.parseInt(r.matched(4)))); - else - stack.push(Module(str)); - } - return stack; + var stack = []; + var r = ~/^([A-Za-z0-9.$_]+)\.([~A-Za-z0-9_]+(\.[0-9]+)?)\((.+):([0-9]+)\)$/; + var r_fun = ~/^fun\$([0-9]+)\((.+):([0-9]+)\)$/; + for (i in 0...s.length - 1) { + var str = @:privateAccess String.fromUCS2(s[i]); + if (r.match(str)) + stack.push(FilePos(Method(r.matched(1), r.matched(2)), r.matched(4), Std.parseInt(r.matched(5)))); + else if (r_fun.match(str)) + stack.push(FilePos(LocalFunction(Std.parseInt(r_fun.matched(1))), r_fun.matched(2), Std.parseInt(r_fun.matched(3)))); + else + stack.push(Module(str)); + } + return stack; #else - return null; + return null; #end } - } diff --git a/std/haxe/Constraints.hx b/std/haxe/Constraints.hx index 2f2de951272..80cc644fc27 100644 --- a/std/haxe/Constraints.hx +++ b/std/haxe/Constraints.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -29,7 +29,7 @@ package haxe; type, the underlying type will be `Dynamic`. **/ @:callable -abstract Function(Dynamic) { } +abstract Function(Dynamic) {} /** This type unifies with an enum instance if all constructors of the enum @@ -38,13 +38,14 @@ abstract Function(Dynamic) { } It is intended to be used as a type parameter constraint. If used as a real type, the underlying type will be `Dynamic`. **/ -abstract FlatEnum(Dynamic) { } +abstract FlatEnum(Dynamic) {} /** This type unifies with any instance of classes that have a constructor which - * is public and - * unifies with the type used for type parameter `T`. + + * is public and + * unifies with the type used for type parameter `T`. If a type parameter A is assigned to a type parameter B which is constrained to `Constructible`, A must be explicitly constrained to @@ -53,15 +54,16 @@ abstract FlatEnum(Dynamic) { } It is intended to be used as a type parameter constraint. If used as a real type, the underlying type will be `Dynamic`. **/ -abstract Constructible(Dynamic) { } +abstract Constructible(Dynamic) {} -interface IMap { +interface IMap { public function get(k:K):Null; public function set(k:K, v:V):Void; public function exists(k:K):Bool; public function remove(k:K):Bool; public function keys():Iterator; public function iterator():Iterator; - public function copy():IMap; + public function keyValueIterator():KeyValueIterator; + public function copy():IMap; public function toString():String; -} \ No newline at end of file +} diff --git a/std/haxe/DynamicAccess.hx b/std/haxe/DynamicAccess.hx index 28673749ece..91f552bbf35 100644 --- a/std/haxe/DynamicAccess.hx +++ b/std/haxe/DynamicAccess.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,8 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; +import haxe.iterators.DynamicAccessIterator; +import haxe.iterators.DynamicAccessKeyValueIterator; + /** DynamicAccess is an abstract type for working with anonymous structures that are intended to hold collections of objects by the string key. @@ -30,18 +34,18 @@ package haxe; Basically, it wraps `Reflect` calls in a `Map`-like interface. **/ abstract DynamicAccess(Dynamic) from Dynamic to Dynamic { - /** Creates a new structure. **/ - public inline function new() this = {}; + public inline function new() + this = {}; /** Returns a value by specified `key`. - If the structure does not contain the given key, null is returned. + If the structure does not contain the given key, `null` is returned. - If `key` is null, the result is unspecified. + If `key` is `null`, the result is unspecified. **/ @:arrayAccess public inline function get(key:String):Null { @@ -59,7 +63,7 @@ abstract DynamicAccess(Dynamic) from Dynamic to Dynamic { Returns the given value. - If `key` is null, the result is unspecified. + If `key` is `null`, the result is unspecified. **/ @:arrayAccess public inline function set(key:String, value:T):T { @@ -74,26 +78,48 @@ abstract DynamicAccess(Dynamic) from Dynamic to Dynamic { /** Tells if the structure contains a specified `key`. - If `key` is null, the result is unspecified. + If `key` is `null`, the result is unspecified. **/ - public inline function exists(key:String):Bool return Reflect.hasField(this, key); + public inline function exists(key:String):Bool + return Reflect.hasField(this, key); /** Removes a specified `key` from the structure. Returns true, if `key` was present in structure, or false otherwise. - If `key` is null, the result is unspecified. + If `key` is `null`, the result is unspecified. **/ - public inline function remove(key:String):Bool return Reflect.deleteField(this, key); + public inline function remove(key:String):Bool + return Reflect.deleteField(this, key); /** Returns an array of `keys` in a structure. **/ - public inline function keys():Array return Reflect.fields(this); - + public inline function keys():Array + return Reflect.fields(this); + /** Returns a shallow copy of the structure **/ - public inline function copy():DynamicAccess return Reflect.copy(this); + public inline function copy():DynamicAccess + return Reflect.copy(this); + + /** + Returns an Iterator over the values of this `DynamicAccess`. + + The order of values is undefined. + **/ + public inline function iterator():DynamicAccessIterator { + return new DynamicAccessIterator(this); + } + + /** + Returns an Iterator over the keys and values of this `DynamicAccess`. + + The order of values is undefined. + **/ + public inline function keyValueIterator():DynamicAccessKeyValueIterator { + return new DynamicAccessKeyValueIterator(this); + } } diff --git a/std/haxe/EntryPoint.hx b/std/haxe/EntryPoint.hx index fafafa26534..4eba6fb3d87 100644 --- a/std/haxe/EntryPoint.hx +++ b/std/haxe/EntryPoint.hx @@ -1,36 +1,28 @@ package haxe; -#if (neko && !macro && !interp) -import neko.vm.Lock; -import neko.vm.Mutex; -import neko.vm.Thread; -#elseif cpp -import cpp.vm.Lock; -import cpp.vm.Mutex; -import cpp.vm.Thread; -#elseif java -import java.vm.Lock; -import java.vm.Mutex; -import java.vm.Thread; +#if target.threaded +import sys.thread.Lock; +import sys.thread.Mutex; +import sys.thread.Thread; #elseif sys private class Lock { - public function new() { - } - public inline function release() { - } - public inline function wait( ?t : Float ) { - } + public function new() {} + + public inline function release() {} + + public inline function wait(?t:Float) {} } + private class Mutex { - public function new() { - } - public inline function acquire() { - } - public inline function release() { - } + public function new() {} + + public inline function acquire() {} + + public inline function release() {} } + private class Thread { - public static function create( f : Void -> Void ) { + public static function create(f:Void->Void) { f(); } } @@ -41,14 +33,12 @@ private class Thread { This class can be redefined by custom frameworks so they can handle their own main loop logic. **/ class EntryPoint { - #if sys static var sleepLock = new Lock(); static var mutex = new Mutex(); #end static var pending = new ArrayVoid>(); - - public static var threadCount(default,null) : Int = 0; + public static var threadCount(default, null):Int = 0; /** Wakeup a sleeping run() @@ -59,7 +49,7 @@ class EntryPoint { #end } - public static function runInMainThread( f : Void -> Void ) { + public static function runInMainThread(f:Void->Void) { #if sys mutex.acquire(); pending.push(f); @@ -70,7 +60,7 @@ class EntryPoint { #end } - public static function addThread( f : Void -> Void ) { + public static function addThread(f:Void->Void) { #if sys mutex.acquire(); threadCount++; @@ -79,18 +69,22 @@ class EntryPoint { f(); mutex.acquire(); threadCount--; - if( threadCount == 0 ) wakeup(); + if (threadCount == 0) + wakeup(); mutex.release(); }); #else threadCount++; - pending.push(function() { f(); threadCount--; } ); + pending.push(function() { + f(); + threadCount--; + }); #end } - static function processEvents() : Float { + static function processEvents():Float { // flush all pending calls - while( true ) { + while (true) { #if sys mutex.acquire(); var f = pending.shift(); @@ -98,12 +92,14 @@ class EntryPoint { #else var f = pending.shift(); #end - if( f == null ) break; + if (f == null) + break; f(); } - if( !MainLoop.hasEvents() && threadCount == 0 ) + var time = @:privateAccess MainLoop.tick(); + if (!MainLoop.hasEvents() && threadCount == 0) return -1; - return @:privateAccess MainLoop.tick(); + return time; } /** @@ -111,37 +107,29 @@ class EntryPoint { **/ @:keep public static function run() @:privateAccess { #if js - var nextTick = processEvents(); #if nodejs - if( nextTick < 0 ) + if (nextTick < 0) return; - (untyped setTimeout)(run,nextTick); + (untyped setTimeout)(run, nextTick); #else - var window : Dynamic = js.Browser.window; - var rqf : Dynamic = window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame; + var window:Dynamic = js.Browser.window; + var rqf:Dynamic = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; rqf(run); #end - #elseif flash - flash.Lib.current.stage.addEventListener(flash.events.Event.ENTER_FRAME, function(_) processEvents()); - #elseif sys - while( true ) { + while (true) { var nextTick = processEvents(); - if( nextTick < 0 ) + if (nextTick < 0) break; - if( nextTick > 0 ) + if (nextTick > 0) sleepLock.wait(nextTick); // wait until nextTick or wakeup() call } #else - // no implementation available, let's exit immediately - #end } } diff --git a/std/haxe/EnumFlags.hx b/std/haxe/EnumFlags.hx index 4268d454f16..5730d9e3de4 100644 --- a/std/haxe/EnumFlags.hx +++ b/std/haxe/EnumFlags.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; /** @@ -32,7 +33,6 @@ package haxe; Type.enumIndex() reflection is used. **/ abstract EnumFlags(Int) { - /** Initializes the bitflags to `i`. **/ @@ -48,7 +48,7 @@ abstract EnumFlags(Int) { If `v` is null, the result is unspecified. **/ - public inline function has( v : T ) : Bool { + public inline function has(v:T):Bool { return this & (1 << Type.enumIndex(v)) != 0; } @@ -60,7 +60,7 @@ abstract EnumFlags(Int) { If `v` is null, the result is unspecified. **/ - public inline function set( v : T ) : Void { + public inline function set(v:T):Void { this |= 1 << Type.enumIndex(v); } @@ -72,7 +72,7 @@ abstract EnumFlags(Int) { If `v` is null, the result is unspecified. **/ - public inline function unset( v : T ) : Void { + public inline function unset(v:T):Void { this &= 0xFFFFFFFF - (1 << Type.enumIndex(v)); } @@ -80,7 +80,7 @@ abstract EnumFlags(Int) { Convert a integer bitflag into a typed one (this is a no-op, it does not have any impact on speed). **/ - public inline static function ofInt( i : Int ) : EnumFlags { + public inline static function ofInt(i:Int):EnumFlags { return new EnumFlags(i); } @@ -88,7 +88,7 @@ abstract EnumFlags(Int) { Convert the typed bitflag into the corresponding int value (this is a no-op, it doesn't have any impact on speed). **/ - public inline function toInt() : Int { + public inline function toInt():Int { return this; } } diff --git a/std/haxe/EnumTools.hx b/std/haxe/EnumTools.hx index 93129ee6a77..0b3d7069b95 100644 --- a/std/haxe/EnumTools.hx +++ b/std/haxe/EnumTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,9 +24,9 @@ package haxe; /** This class provides advanced methods on enums. It is ideally used with - `using EnumTools` and then acts as an - [extension](https://haxe.org/manual/lf-static-extension.html) to the - `enum` types. + `using EnumTools` and then acts as an + [extension](https://haxe.org/manual/lf-static-extension.html) to the + `enum` types. If the first argument to any of the methods is null, the result is unspecified. @@ -112,15 +112,14 @@ extern class EnumTools { /** This class provides advanced methods on enum values. It is ideally used with - `using EnumValueTools` and then acts as an - [extension](https://haxe.org/manual/lf-static-extension.html) to the - `EnumValue` types. + `using EnumValueTools` and then acts as an + [extension](https://haxe.org/manual/lf-static-extension.html) to the + `EnumValue` types. If the first argument to any of the methods is null, the result is unspecified. **/ extern class EnumValueTools { - /** Recursively compares two enum instances `a` and `b` by value. @@ -169,36 +168,4 @@ extern class EnumValueTools { static public inline function getIndex(e:EnumValue):Int { return Type.enumIndex(e); } - - /** - Matches enum instance `e` against pattern `pattern`, returning `true` if - matching succeeded and `false` otherwise. - - Example usage: - - ```haxe - if (e.match(pattern)) { - // codeIfTrue - } else { - // codeIfFalse - } - ``` - - This is equivalent to the following code: - - ```haxe - switch (e) { - case pattern: - // codeIfTrue - case _: - // codeIfFalse - } - ``` - - This method is implemented in the compiler. This definition exists only - for documentation. - **/ - static public function match(e:EnumValue, pattern:Dynamic):Bool { - return false; - } } diff --git a/std/haxe/Http.hx b/std/haxe/Http.hx index 103acec3e30..2d23db2e05f 100644 --- a/std/haxe/Http.hx +++ b/std/haxe/Http.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,826 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe; - -import haxe.ds.List; - -#if sys - -import sys.net.Host; -import sys.net.Socket; - -#end - -/** - This class can be used to handle Http requests consistently across - platforms. There are two intended usages: - - - call `haxe.Http.requestUrl(url)` and receive the result as a `String` - (not available on flash) - - create a `new haxe.Http(url)`, register your callbacks for `onData`, - `onError` and `onStatus`, then call `request()`. -**/ -class Http { - - /** - The url of `this` request. It is used only by the `request()` method and - can be changed in order to send the same request to different target - Urls. - **/ - public var url : String; - public var responseData(default, null) : Null; -#if sys - public var noShutdown : Bool; - public var cnxTimeout : Float; - public var responseHeaders : Map; - var chunk_size : Null; - var chunk_buf : haxe.io.Bytes; - var file : { param : String, filename : String, io : haxe.io.Input, size : Int, mimeType : String }; -#elseif (js && !nodejs) - public var async : Bool; - public var withCredentials : Bool; -#end - var postData : String; - var headers : List<{ header:String, value:String }>; - var params : List<{ param:String, value:String }>; - - #if sys - public static var PROXY : { host : String, port : Int, auth : { user : String, pass : String } } = null; - #end - - /** - Creates a new Http instance with `url` as parameter. - - This does not do a request until `request()` is called. - - If `url` is null, the field url must be set to a value before making the - call to `request()`, or the result is unspecified. - - (Php) Https (SSL) connections are allowed only if the OpenSSL extension - is enabled. - **/ - public function new( url : String ) { - this.url = url; - headers = new List<{ header:String, value:String }>(); - params = new List<{ param:String, value:String }>(); - - #if (js && !nodejs) - async = true; - withCredentials = false; - #elseif sys - cnxTimeout = 10; - #end - #if php - noShutdown = ! untyped __call__('function_exists', 'stream_socket_shutdown'); - #end - } - - /** - Sets the header identified as `header` to value `value`. - - If `header` or `value` are null, the result is unspecified. - - This method provides a fluent interface. - **/ - public function setHeader( header : String, value : String ):Http { - headers = Lambda.filter(headers, function(h) return h.header != header); - headers.push({ header:header, value:value }); - return this; - } - - public function addHeader( header : String, value : String ):Http { - headers.push({ header:header, value:value }); - return this; - } - - /** - Sets the parameter identified as `param` to value `value`. - - If `header` or `value` are null, the result is unspecified. - - This method provides a fluent interface. - **/ - public function setParameter( param : String, value : String ):Http { - params = Lambda.filter(params, function(p) return p.param != param); - params.push({ param:param, value:value }); - return this; - } - - public function addParameter( param : String, value : String ):Http { - params.push({ param:param, value:value }); - return this; - } - - /** - Sets the post data of `this` Http request to `data`. - - There can only be one post data per request. Subsequent calls overwrite - the previously set value. - - If `data` is null, the post data is considered to be absent. - - This method provides a fluent interface. - **/ - public function setPostData( data : String ):Http { - postData = data; - return this; - } - - #if (js || flash) - - #if nodejs - var req:js.node.http.ClientRequest; - #elseif js - var req:js.html.XMLHttpRequest; - #elseif flash - var req:flash.net.URLLoader; - #end - - /** - Cancels `this` Http request if `request` has been called and a response - has not yet been received. - **/ - public function cancel() - { - if (req == null) return; - #if js - req.abort(); - #elseif flash - req.close(); - #end - req = null; - } - #end - - /** - Sends `this` Http request to the Url specified by `this.url`. - - If `post` is true, the request is sent as POST request, otherwise it is - sent as GET request. - - Depending on the outcome of the request, this method calls the - `onStatus()`, `onError()` or `onData()` callback functions. - If `this.url` is null, the result is unspecified. - - If `this.url` is an invalid or inaccessible Url, the `onError()` callback - function is called. - - [js] If `this.async` is false, the callback functions are called before - this method returns. - **/ - public function request( ?post : Bool ) : Void { - var me = this; - #if (js && nodejs) - me.responseData = null; - var parsedUrl = js.node.Url.parse(url); - var secure = (parsedUrl.protocol == "https:"); - var host = parsedUrl.hostname; - var path = parsedUrl.path; - var port = if (parsedUrl.port != null) Std.parseInt(parsedUrl.port) else (secure ? 443 : 80); - var h:Dynamic = {}; - for (i in headers) { - var arr = Reflect.field(h, i.header); - if (arr == null) { - arr = new Array(); - Reflect.setField(h, i.header, arr); - } - - arr.push(i.value); - } - var uri = postData; - if( uri != null ) - post = true; - else for( p in params ) { - if( uri == null ) - uri = ""; - else - uri += "&"; - uri += StringTools.urlEncode(p.param)+"="+StringTools.urlEncode(p.value); - } - var question = path.split("?").length <= 1; - if (!post && uri != null) path += (if( question ) "?" else "&") + uri; - - var opts = { - protocol: parsedUrl.protocol, - hostname: host, - port: port, - method: post ? 'POST' : 'GET', - path: path, - headers: h - }; - function httpResponse (res) { - var s = res.statusCode; - if (s != null) - me.onStatus(s); - var body = ''; - res.on('data', function (d) { - body += d; - }); - res.on('end', function (_) { - me.responseData = body; - me.req = null; - if (s != null && s >= 200 && s < 400) { - me.onData(body); - } else { - me.onError("Http Error #"+s); - } - }); - } - req = secure ? js.node.Https.request(untyped opts, httpResponse) : js.node.Http.request(untyped opts, httpResponse); - if (post) req.write(uri); - req.end(); - #elseif js - me.responseData = null; - var r = req = js.Browser.createXMLHttpRequest(); - var onreadystatechange = function(_) { - if( r.readyState != 4 ) - return; - var s = try r.status catch( e : Dynamic ) null; - if ( s != null && untyped __js__('"undefined" !== typeof window') ) { - // If the request is local and we have data: assume a success (jQuery approach): - var protocol = js.Browser.location.protocol.toLowerCase(); - var rlocalProtocol = ~/^(?:about|app|app-storage|.+-extension|file|res|widget):$/; - var isLocal = rlocalProtocol.match( protocol ); - if ( isLocal ) { - s = r.responseText != null ? 200 : 404; - } - } - if( s == untyped __js__("undefined") ) - s = null; - if( s != null ) - me.onStatus(s); - if( s != null && s >= 200 && s < 400 ) { - me.req = null; - me.onData(me.responseData = r.responseText); - } - else if ( s == null ) { - me.req = null; - me.onError("Failed to connect or resolve host"); - } - else switch( s ) { - case 12029: - me.req = null; - me.onError("Failed to connect to host"); - case 12007: - me.req = null; - me.onError("Unknown host"); - default: - me.req = null; - me.responseData = r.responseText; - me.onError("Http Error #"+r.status); - } - }; - if( async ) - r.onreadystatechange = onreadystatechange; - var uri = postData; - if( uri != null ) - post = true; - else for( p in params ) { - if( uri == null ) - uri = ""; - else - uri += "&"; - uri += StringTools.urlEncode(p.param)+"="+StringTools.urlEncode(p.value); - } - try { - if( post ) - r.open("POST",url,async); - else if( uri != null ) { - var question = url.split("?").length <= 1; - r.open("GET",url+(if( question ) "?" else "&")+uri,async); - uri = null; - } else - r.open("GET",url,async); - } catch( e : Dynamic ) { - me.req = null; - onError(e.toString()); - return; - } - r.withCredentials = withCredentials; - if( !Lambda.exists(headers, function(h) return h.header == "Content-Type") && post && postData == null ) - r.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); - - for( h in headers ) - r.setRequestHeader(h.header,h.value); - r.send(uri); - if( !async ) - onreadystatechange(null); - #elseif flash - me.responseData = null; - var loader = req = new flash.net.URLLoader(); - loader.addEventListener( "complete", function(e) { - me.req = null; - me.responseData = loader.data; - me.onData( loader.data ); - }); - loader.addEventListener( "httpStatus", function(e:flash.events.HTTPStatusEvent){ - // on Firefox 1.5, Flash calls onHTTPStatus with 0 (!??) - if( e.status != 0 ) - me.onStatus( e.status ); - }); - loader.addEventListener( "ioError", function(e:flash.events.IOErrorEvent){ - me.req = null; - me.responseData = loader.data; - me.onError(e.text); - }); - loader.addEventListener( "securityError", function(e:flash.events.SecurityErrorEvent){ - me.req = null; - me.onError(e.text); - }); - - // headers - var param = false; - var vars = new flash.net.URLVariables(); - for( p in params ){ - param = true; - Reflect.setField(vars,p.param,p.value); - } - var small_url = url; - if( param && !post ){ - var k = url.split("?"); - if( k.length > 1 ) { - small_url = k.shift(); - vars.decode(k.join("?")); - } - } - // Bug in flash player 9 ??? - var bug = small_url.split("xxx"); - - var request = new flash.net.URLRequest( small_url ); - for( h in headers ) - request.requestHeaders.push( new flash.net.URLRequestHeader(h.header,h.value) ); - - if( postData != null ) { - request.data = postData; - request.method = "POST"; - } else { - request.data = vars; - request.method = if( post ) "POST" else "GET"; - } - - try { - loader.load( request ); - }catch( e : Dynamic ){ - me.req = null; - onError("Exception: "+Std.string(e)); - } - #elseif sys - var me = this; - var output = new haxe.io.BytesOutput(); - var old = onError; - var err = false; - onError = function(e) { - #if neko - me.responseData = neko.Lib.stringReference(output.getBytes()); - #else - me.responseData = output.getBytes().toString(); - #end - err = true; - // Resetting back onError before calling it allows for a second "retry" request to be sent without onError being wrapped twice - onError = old; - onError(e); - } - customRequest(post,output); - if( !err ) - #if neko - me.onData(me.responseData = neko.Lib.stringReference(output.getBytes())); - #else - me.onData(me.responseData = output.getBytes().toString()); - #end - #end - } +package haxe; #if sys - - /** - Note: Deprecated in 4.0 - **/ - @:noCompletion - inline public function fileTransfert( argname : String, filename : String, file : haxe.io.Input, size : Int, mimeType = "application/octet-stream" ) { - fileTransfer(argname, filename, file, size, mimeType); - } - - public function fileTransfer( argname : String, filename : String, file : haxe.io.Input, size : Int, mimeType = "application/octet-stream" ) { - this.file = { param : argname, filename : filename, io : file, size : size, mimeType : mimeType }; - } - - public function customRequest( post : Bool, api : haxe.io.Output, ?sock : sys.net.Socket, ?method : String ) { - this.responseData = null; - var url_regexp = ~/^(https?:\/\/)?([a-zA-Z\.0-9_-]+)(:[0-9]+)?(.*)$/; - if( !url_regexp.match(url) ) { - onError("Invalid URL"); - return; - } - var secure = (url_regexp.matched(1) == "https://"); - if( sock == null ) { - if( secure ) { - #if php - sock = new php.net.SslSocket(); - #elseif java - sock = new java.net.SslSocket(); - #elseif (!no_ssl && (hxssl || hl || cpp || (neko && !(macro || interp)))) - sock = new sys.ssl.Socket(); - #else - throw "Https is only supported with -lib hxssl"; - #end - } else - sock = new Socket(); - } - var host = url_regexp.matched(2); - var portString = url_regexp.matched(3); - var request = url_regexp.matched(4); - if( request == "" ) - request = "/"; - var port = if ( portString == null || portString == "" ) secure ? 443 : 80 else Std.parseInt(portString.substr(1, portString.length - 1)); - var data; - - var multipart = (file != null); - var boundary = null; - var uri = null; - if( multipart ) { - post = true; - boundary = Std.string(Std.random(1000))+Std.string(Std.random(1000))+Std.string(Std.random(1000))+Std.string(Std.random(1000)); - while( boundary.length < 38 ) - boundary = "-" + boundary; - var b = new StringBuf(); - for( p in params ) { - b.add("--"); - b.add(boundary); - b.add("\r\n"); - b.add('Content-Disposition: form-data; name="'); - b.add(p.param); - b.add('"'); - b.add("\r\n"); - b.add("\r\n"); - b.add(p.value); - b.add("\r\n"); - } - b.add("--"); - b.add(boundary); - b.add("\r\n"); - b.add('Content-Disposition: form-data; name="'); - b.add(file.param); - b.add('"; filename="'); - b.add(file.filename); - b.add('"'); - b.add("\r\n"); - b.add("Content-Type: "+file.mimeType+"\r\n"+"\r\n"); - uri = b.toString(); - } else { - for( p in params ) { - if( uri == null ) - uri = ""; - else - uri += "&"; - uri += StringTools.urlEncode(p.param)+"="+StringTools.urlEncode(p.value); - } - } - - var b = new StringBuf(); - if( method != null ) { - b.add(method); - b.add(" "); - } else if( post ) - b.add("POST "); - else - b.add("GET "); - - if( Http.PROXY != null ) { - b.add("http://"); - b.add(host); - if( port != 80 ) { - b.add(":"); - b.add(port); - } - } - b.add(request); - - if( !post && uri != null ) { - if( request.indexOf("?",0) >= 0 ) - b.add("&"); - else - b.add("?"); - b.add(uri); - } - b.add(" HTTP/1.1\r\nHost: "+host+"\r\n"); - if( postData != null ) - b.add("Content-Length: "+postData.length+"\r\n"); - else if( post && uri != null ) { - if( multipart || !Lambda.exists(headers, function(h) return h.header == "Content-Type") ) { - b.add("Content-Type: "); - if( multipart ) { - b.add("multipart/form-data"); - b.add("; boundary="); - b.add(boundary); - } else - b.add("application/x-www-form-urlencoded"); - b.add("\r\n"); - } - if( multipart ) - b.add("Content-Length: "+(uri.length+file.size+boundary.length+6)+"\r\n"); - else - b.add("Content-Length: "+uri.length+"\r\n"); - } - b.add("Connection: close\r\n"); - for( h in headers ) { - b.add(h.header); - b.add(": "); - b.add(h.value); - b.add("\r\n"); - } - b.add("\r\n"); - if( postData != null) - b.add(postData); - else if( post && uri != null ) - b.add(uri); - try { - if( Http.PROXY != null ) - sock.connect(new Host(Http.PROXY.host),Http.PROXY.port); - else - sock.connect(new Host(host),port); - sock.write(b.toString()); - if( multipart ) { - var bufsize = 4096; - var buf = haxe.io.Bytes.alloc(bufsize); - while( file.size > 0 ) { - var size = if( file.size > bufsize ) bufsize else file.size; - var len = 0; - try { - len = file.io.readBytes(buf,0,size); - } catch( e : haxe.io.Eof ) break; - sock.output.writeFullBytes(buf,0,len); - file.size -= len; - } - sock.write("\r\n"); - sock.write("--"); - sock.write(boundary); - sock.write("--"); - } - readHttpResponse(api,sock); - sock.close(); - } catch( e : Dynamic ) { - try sock.close() catch( e : Dynamic ) { }; - onError(Std.string(e)); - } - } - - function readHttpResponse( api : haxe.io.Output, sock : sys.net.Socket ) { - // READ the HTTP header (until \r\n\r\n) - var b = new haxe.io.BytesBuffer(); - var k = 4; - var s = haxe.io.Bytes.alloc(4); - sock.setTimeout(cnxTimeout); - while( true ) { - var p = sock.input.readBytes(s,0,k); - while( p != k ) - p += sock.input.readBytes(s,p,k - p); - b.addBytes(s,0,k); - switch( k ) { - case 1: - var c = s.get(0); - if( c == 10 ) - break; - if( c == 13 ) - k = 3; - else - k = 4; - case 2: - var c = s.get(1); - if( c == 10 ) { - if( s.get(0) == 13 ) - break; - k = 4; - } else if( c == 13 ) - k = 3; - else - k = 4; - case 3: - var c = s.get(2); - if( c == 10 ) { - if( s.get(1) != 13 ) - k = 4; - else if( s.get(0) != 10 ) - k = 2; - else - break; - } else if( c == 13 ) { - if( s.get(1) != 10 || s.get(0) != 13 ) - k = 1; - else - k = 3; - } else - k = 4; - case 4: - var c = s.get(3); - if( c == 10 ) { - if( s.get(2) != 13 ) - continue; - else if( s.get(1) != 10 || s.get(0) != 13 ) - k = 2; - else - break; - } else if( c == 13 ) { - if( s.get(2) != 10 || s.get(1) != 13 ) - k = 3; - else - k = 1; - } - } - } - #if neko - var headers = neko.Lib.stringReference(b.getBytes()).split("\r\n"); - #else - var headers = b.getBytes().toString().split("\r\n"); - #end - var response = headers.shift(); - var rp = response.split(" "); - var status = Std.parseInt(rp[1]); - if( status == 0 || status == null ) - throw "Response status error"; - - // remove the two lasts \r\n\r\n - headers.pop(); - headers.pop(); - responseHeaders = new haxe.ds.StringMap(); - var size = null; - var chunked = false; - for( hline in headers ) { - var a = hline.split(": "); - var hname = a.shift(); - var hval = if( a.length == 1 ) a[0] else a.join(": "); - hval = StringTools.ltrim( StringTools.rtrim( hval ) ); - responseHeaders.set(hname, hval); - switch(hname.toLowerCase()) - { - case "content-length": - size = Std.parseInt(hval); - case "transfer-encoding": - chunked = (hval.toLowerCase() == "chunked"); - } - } - - onStatus(status); - - var chunk_re = ~/^([0-9A-Fa-f]+)[ ]*\r\n/m; - chunk_size = null; - chunk_buf = null; - - var bufsize = 1024; - var buf = haxe.io.Bytes.alloc(bufsize); - if( chunked ) { - try { - while( true ) { - var len = sock.input.readBytes(buf,0,bufsize); - if( !readChunk(chunk_re,api,buf,len) ) - break; - } - } catch ( e : haxe.io.Eof ) { - throw "Transfer aborted"; - } - } else if( size == null ) { - if( !noShutdown ) - sock.shutdown(false,true); - try { - while( true ) { - var len = sock.input.readBytes(buf,0,bufsize); - api.writeBytes(buf,0,len); - } - } catch( e : haxe.io.Eof ) { - } - } else { - api.prepare(size); - try { - while( size > 0 ) { - var len = sock.input.readBytes(buf,0,if( size > bufsize ) bufsize else size); - api.writeBytes(buf,0,len); - size -= len; - } - } catch( e : haxe.io.Eof ) { - throw "Transfer aborted"; - } - } - if( chunked && (chunk_size != null || chunk_buf != null) ) - throw "Invalid chunk"; - if( status < 200 || status >= 400 ) - throw "Http Error #"+status; - api.close(); - } - - function readChunk(chunk_re : EReg, api : haxe.io.Output, buf : haxe.io.Bytes, len ) { - if( chunk_size == null ) { - if( chunk_buf != null ) { - var b = new haxe.io.BytesBuffer(); - b.add(chunk_buf); - b.addBytes(buf,0,len); - buf = b.getBytes(); - len += chunk_buf.length; - chunk_buf = null; - } - #if neko - if( chunk_re.match(neko.Lib.stringReference(buf)) ) { - #else - if( chunk_re.match(buf.toString()) ) { - #end - var p = chunk_re.matchedPos(); - if( p.len <= len ) { - var cstr = chunk_re.matched(1); - chunk_size = Std.parseInt("0x"+cstr); - if( cstr == "0" ) { - chunk_size = null; - chunk_buf = null; - return false; - } - len -= p.len; - return readChunk(chunk_re,api,buf.sub(p.len,len),len); - } - } - // prevent buffer accumulation - if( len > 10 ) { - onError("Invalid chunk"); - return false; - } - chunk_buf = buf.sub(0,len); - return true; - } - if( chunk_size > len ) { - chunk_size -= len; - api.writeBytes(buf,0,len); - return true; - } - var end = chunk_size + 2; - if( len >= end ) { - if( chunk_size > 0 ) - api.writeBytes(buf,0,chunk_size); - len -= end; - chunk_size = null; - if( len == 0 ) - return true; - return readChunk(chunk_re,api,buf.sub(end,len),len); - } - if( chunk_size > 0 ) - api.writeBytes(buf,0,chunk_size); - chunk_size -= len; - return true; - } - +typedef Http = sys.Http; +#elseif nodejs +typedef Http = haxe.http.HttpNodeJs; +#elseif js +typedef Http = haxe.http.HttpJs; +#else +typedef Http = haxe.http.HttpBase; #end - - /** - This method is called upon a successful request, with `data` containing - the result String. - - The intended usage is to bind it to a custom function: - `httpInstance.onData = function(data) { // handle result }` - **/ - public dynamic function onData( data : String ) { - } - - /** - This method is called upon a request error, with `msg` containing the - error description. - - The intended usage is to bind it to a custom function: - `httpInstance.onError = function(msg) { // handle error }` - **/ - public dynamic function onError( msg : String ) { - } - - /** - This method is called upon a Http status change, with `status` being the - new status. - - The intended usage is to bind it to a custom function: - `httpInstance.onStatus = function(status) { // handle status }` - **/ - public dynamic function onStatus( status : Int ) { - } - -#if (!flash && !nodejs) - /** - Makes a synchronous request to `url`. - - This creates a new Http instance and makes a GET request by calling its - `request(false)` method. - - If `url` is null, the result is unspecified. - **/ - public static function requestUrl( url : String ) : String { - var h = new Http(url); - #if js - h.async = false; - #end - var r = null; - h.onData = function(d){ - r = d; - } - h.onError = function(e){ - throw e; - } - h.request(false); - return r; - } -#end - -} diff --git a/std/haxe/Int32.hx b/std/haxe/Int32.hx index edef469f4cf..5c1210049ec 100644 --- a/std/haxe/Int32.hx +++ b/std/haxe/Int32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package haxe; - /** - Int32 provides a 32-bit integer with consistent overflow behavior across - all platforms. - **/ +package haxe; + +/** + Int32 provides a 32-bit integer with consistent overflow behavior across + all platforms. +**/ abstract Int32(Int) from Int to Int { - @:op(-A) private function negate():Int32; + @:op(-A) private inline function negate():Int32 + return clamp(~this + 1); @:op(++A) private inline function preIncrement():Int32 return this = clamp(++this); @@ -47,28 +49,27 @@ abstract Int32(Int) from Int to Int { } @:op(A + B) private static inline function add(a:Int32, b:Int32):Int32 - return clamp( (a : Int) + (b : Int) ); + return clamp((a : Int) + (b : Int)); @:op(A + B) @:commutative private static inline function addInt(a:Int32, b:Int):Int32 - return clamp( (a : Int) + (b : Int) ); + return clamp((a : Int) + (b : Int)); @:op(A + B) @:commutative private static function addFloat(a:Int32, b:Float):Float; @:op(A - B) private static inline function sub(a:Int32, b:Int32):Int32 - return clamp( (a : Int) - (b : Int) ); + return clamp((a : Int) - (b : Int)); @:op(A - B) private static inline function subInt(a:Int32, b:Int):Int32 - return clamp( (a : Int) - (b : Int) ); + return clamp((a : Int) - (b : Int)); @:op(A - B) private static inline function intSub(a:Int, b:Int32):Int32 - return clamp( (a : Int) - (b : Int) ); + return clamp((a : Int) - (b : Int)); @:op(A - B) private static function subFloat(a:Int32, b:Float):Float; @:op(A - B) public static function floatSub(a:Float, b:Int32):Float; #if (as3 || js || php || python || lua) - #if js // on JS we want to try using Math.imul, but we have to assign that function to Int32.mul only once, // or else V8 will deoptimize it, so we need to be a bit funky with this. @@ -76,166 +77,193 @@ abstract Int32(Int) from Int to Int { @:op(A * B) inline static function mul(a:Int32, b:Int32):Int32 return _mul(a, b); - static var _mul:Int32->Int32->Int32 = untyped - if (Math.imul != null) + static var _mul:Int32->Int32->Int32 = untyped if (Math.imul != null) Math.imul else - function(a:Int32, b:Int32):Int32 - return clamp( (a : Int) * ((b : Int) & 0xFFFF) + clamp( (a : Int) * ((b : Int) >>> 16) << 16 ) ); - + function(a:Int32, b:Int32):Int32 return clamp((a : Int) * ((b : Int) & 0xFFFF) + clamp((a : Int) * ((b : Int) >>> 16) << 16)); #else @:op(A * B) private static function mul(a:Int32, b:Int32):Int32 - return clamp( (a : Int) * ((b : Int) & 0xFFFF) + clamp( (a : Int) * ((b : Int) >>> 16) << 16 ) ); + return clamp((a : Int) * ((b : Int) & 0xFFFF) + clamp((a : Int) * ((b : Int) >>> 16) << 16)); #end @:op(A * B) @:commutative private static inline function mulInt(a:Int32, b:Int):Int32 return mul(a, b); - #else - @:op(A * B) private static function mul(a:Int32, b:Int32):Int32; - @:op(A * B) @:commutative private static function mulInt(a:Int32, b:Int):Int32; + @:op(A * B) @:commutative private static function mulInt(a:Int32, b:Int):Int32; #end @:op(A * B) @:commutative private static function mulFloat(a:Int32, b:Float):Float; @:op(A / B) private static function div(a:Int32, b:Int32):Float; + @:op(A / B) private static function divInt(a:Int32, b:Int):Float; + @:op(A / B) private static function intDiv(a:Int, b:Int32):Float; + @:op(A / B) private static function divFloat(a:Int32, b:Float):Float; + @:op(A / B) private static function floatDiv(a:Float, b:Int32):Float; @:op(A % B) private static function mod(a:Int32, b:Int32):Int32; + @:op(A % B) private static function modInt(a:Int32, b:Int):Int; + @:op(A % B) private static function intMod(a:Int, b:Int32):Int; + @:op(A % B) private static function modFloat(a:Int32, b:Float):Float; + @:op(A % B) private static function floatMod(a:Float, b:Int32):Float; @:op(A == B) private static function eq(a:Int32, b:Int32):Bool; + @:op(A == B) @:commutative private static function eqInt(a:Int32, b:Int):Bool; + @:op(A == B) @:commutative private static function eqFloat(a:Int32, b:Float):Bool; @:op(A != B) private static function neq(a:Int32, b:Int32):Bool; + @:op(A != B) @:commutative private static function neqInt(a:Int32, b:Int):Bool; + @:op(A != B) @:commutative private static function neqFloat(a:Int32, b:Float):Bool; @:op(A < B) private static function lt(a:Int32, b:Int32):Bool; + @:op(A < B) private static function ltInt(a:Int32, b:Int):Bool; + @:op(A < B) private static function intLt(a:Int, b:Int32):Bool; + @:op(A < B) private static function ltFloat(a:Int32, b:Float):Bool; + @:op(A < B) private static function floatLt(a:Float, b:Int32):Bool; @:op(A <= B) private static function lte(a:Int32, b:Int32):Bool; + @:op(A <= B) private static function lteInt(a:Int32, b:Int):Bool; + @:op(A <= B) private static function intLte(a:Int, b:Int32):Bool; + @:op(A <= B) private static function lteFloat(a:Int32, b:Float):Bool; + @:op(A <= B) private static function floatLte(a:Float, b:Int32):Bool; @:op(A > B) private static function gt(a:Int32, b:Int32):Bool; + @:op(A > B) private static function gtInt(a:Int32, b:Int):Bool; + @:op(A > B) private static function intGt(a:Int, b:Int32):Bool; + @:op(A > B) private static function gtFloat(a:Int32, b:Float):Bool; + @:op(A > B) private static function floatGt(a:Float, b:Int32):Bool; @:op(A >= B) private static function gte(a:Int32, b:Int32):Bool; + @:op(A >= B) private static function gteInt(a:Int32, b:Int):Bool; + @:op(A >= B) private static function intGte(a:Int, b:Int32):Bool; + @:op(A >= B) private static function gteFloat(a:Int32, b:Float):Bool; + @:op(A >= B) private static function floatGte(a:Float, b:Int32):Bool; #if (lua || python || php) - @:op(~A) private static inline function complement( a : Int32 ) : Int32 - #if lua - return lua.Boot.clamp(~a); - #else - return clamp(~a); - #end + @:op(~A) private static inline function complement(a:Int32):Int32 + #if lua return lua.Boot.clampInt32(~a); #else return clamp(~a); #end #else @:op(~A) private function complement():Int32; #end @:op(A & B) private static function and(a:Int32, b:Int32):Int32; + @:op(A & B) @:commutative private static function andInt(a:Int32, b:Int):Int32; #if (lua || python || php) @:op(A | B) private static #if (python || php) inline #end function or(a:Int32, b:Int32):Int32 - return clamp((a:Int) | (b:Int)); + return clamp((a : Int) | (b : Int)); + @:op(A | B) @:commutative private #if (python || php) inline #end static function orInt(a:Int32, b:Int):Int32 - return clamp((a:Int) | b); + return clamp((a : Int) | b); #else @:op(A | B) private static function or(a:Int32, b:Int32):Int32; + @:op(A | B) @:commutative private static function orInt(a:Int32, b:Int):Int32; #end #if (lua || python || php) @:op(A ^ B) private static #if (python || php) inline #end function xor(a:Int32, b:Int32):Int32 - return clamp((a:Int) ^ (b:Int)); + return clamp((a : Int) ^ (b : Int)); + @:op(A ^ B) @:commutative private static #if (python || php) inline #end function xorInt(a:Int32, b:Int):Int32 - return clamp((a:Int) ^ b); + return clamp((a : Int) ^ b); #else @:op(A ^ B) private static function xor(a:Int32, b:Int32):Int32; + @:op(A ^ B) @:commutative private static function xorInt(a:Int32, b:Int):Int32; #end - -#if (lua || python || php) + #if (lua || python || php) @:op(A >> B) private static #if (python || php) inline #end function shr(a:Int32, b:Int32):Int32 - return clamp((a:Int) >> (b:Int)); + return clamp((a : Int) >> (b : Int)); + @:op(A >> B) private static #if (python || php) inline #end function shrInt(a:Int32, b:Int):Int32 - return clamp((a:Int) >> b); + return clamp((a : Int) >> b); + @:op(A >> B) private static #if (python || php) inline #end function intShr(a:Int, b:Int32):Int32 - return clamp(a >> (b:Int)); -#else + return clamp(a >> (b : Int)); + #else @:op(A >> B) private static function shr(a:Int32, b:Int32):Int32; + @:op(A >> B) private static function shrInt(a:Int32, b:Int):Int32; + @:op(A >> B) private static function intShr(a:Int, b:Int32):Int32; -#end + #end @:op(A >>> B) private static function ushr(a:Int32, b:Int32):Int32; + @:op(A >>> B) private static function ushrInt(a:Int32, b:Int):Int32; + @:op(A >>> B) private static function intUshr(a:Int, b:Int32):Int32; #if (php || python || lua) - // PHP may be 64-bit, so shifts must be clamped @:op(A << B) private static inline function shl(a:Int32, b:Int32):Int32 - return clamp( (a : Int) << (b : Int) ); + return clamp((a : Int) << (b : Int)); @:op(A << B) private static inline function shlInt(a:Int32, b:Int):Int32 - return clamp( (a : Int) << b ); + return clamp((a : Int) << b); @:op(A << B) private static inline function intShl(a:Int, b:Int32):Int32 - return clamp( a << (b : Int) ); - + return clamp(a << (b : Int)); #else - @:op(A << B) private static function shl(a:Int32, b:Int32):Int32; + @:op(A << B) private static function shlInt(a:Int32, b:Int):Int32; - @:op(A << B) private static function intShl(a:Int, b:Int32):Int32; + @:op(A << B) private static function intShl(a:Int, b:Int32):Int32; #end - @:to private inline function toFloat():Float return this; /** Compare `a` and `b` in unsigned mode. **/ - public static function ucompare( a : Int32, b : Int32 ) : Int { - if( a < 0 ) - return b < 0 ? ( ~b - ~a ) : 1; + public static function ucompare(a:Int32, b:Int32):Int { + if (a < 0) + return b < 0 ? (~b - ~a) : 1; return b < 0 ? -1 : (a - b); } #if php - static var extraBits : Int = php.Const.PHP_INT_SIZE * 8 - 32; + static var extraBits:Int = php.Const.PHP_INT_SIZE * 8 - 32; #end - -#if !lua inline #end - static function clamp( x : Int ) : Int { + #if !lua + inline + #end + static function clamp(x:Int):Int { // force to-int conversion on platforms that require it #if (as3 || js) return x | 0; @@ -243,9 +271,9 @@ abstract Int32(Int) from Int to Int { // we might be on 64-bit php, so sign extend from 32-bit return (x << extraBits) >> extraBits; #elseif python - return python.Syntax.pythonCode("{0} % {1}", (x + python.Syntax.opPow(2, 31)), python.Syntax.opPow(2, 32)) - python.Syntax.opPow(2, 31); + return (python.Syntax.code("{0} % {1}", (x + python.Syntax.opPow(2, 31)), python.Syntax.opPow(2, 32)) : Int) - python.Syntax.opPow(2, 31); #elseif lua - return lua.Boot.clamp(x); + return lua.Boot.clampInt32(x); #else return (x); #end diff --git a/std/haxe/Int64.hx b/std/haxe/Int64.hx index e803c8daba3..a4c7d202f72 100644 --- a/std/haxe/Int64.hx +++ b/std/haxe/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,51 +19,47 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; using haxe.Int64; - /** +/** A cross-platform signed 64-bit integer. Int64 instances can be created from two 32-bit words using `Int64.make()`. - **/ +**/ #if flash @:notNull #end -abstract Int64(__Int64) from __Int64 to __Int64 -{ - private inline function new( x : __Int64 ) +abstract Int64(__Int64) from __Int64 to __Int64 { + private inline function new(x:__Int64) this = x; /** Makes a copy of `this` Int64. **/ public inline function copy():Int64 - return make( high, low ); + return make(high, low); /** Construct an Int64 from two 32-bit words `high` and `low`. **/ - public static inline function make( high:Int32, low:Int32 ) : Int64 - return new Int64( new __Int64(high, low) ); + public static inline function make(high:Int32, low:Int32):Int64 + return new Int64(new __Int64(high, low)); /** Returns an Int64 with the value of the Int `x`. `x` is sign-extended to fill 64 bits. **/ - @:from public static inline function ofInt( x : Int ) : Int64 -#if lua - return make( (x:Int32) >> 31, (x:Int32)); -#else - return make( x >> 31, x ); -#end + @:from public static inline function ofInt(x:Int):Int64 + #if lua return make((x : Int32) >> 31, (x : Int32)); #else return make(x >> 31, x); #end /** Returns an Int with the value of the Int64 `x`. Throws an exception if `x` cannot be represented in 32 bits. **/ - public static inline function toInt( x : Int64 ) : Int { - if( x.high != x.low >> 31 ) + public static inline function toInt(x:Int64):Int { + if (x.high != x.low >> 31) throw "Overflow"; return x.low; @@ -72,33 +68,33 @@ abstract Int64(__Int64) from __Int64 to __Int64 /** Returns whether the value `val` is of type `haxe.Int64` **/ - inline public static function is( val : Dynamic ) : Bool - return Std.is(val,__Int64); + inline public static function is(val:Dynamic):Bool + return Std.is(val, __Int64); /** Returns the high 32-bit word of `x`. **/ @:deprecated("Use high instead") - public static inline function getHigh( x : Int64 ) : Int32 + public static inline function getHigh(x:Int64):Int32 return x.high; /** Returns the low 32-bit word of `x`. **/ @:deprecated("Use low instead") - public static inline function getLow( x : Int64 ) : Int32 + public static inline function getLow(x:Int64):Int32 return x.low; /** Returns `true` if `x` is less than zero. **/ - public static inline function isNeg( x : Int64) : Bool + public static inline function isNeg(x:Int64):Bool return x.high < 0; /** Returns `true` if `x` is exactly zero. **/ - public static inline function isZero( x : Int64 ) : Bool + public static inline function isZero(x:Int64):Bool return x == 0; /** @@ -106,9 +102,9 @@ abstract Int64(__Int64) from __Int64 to __Int64 Returns a negative value if `a < b`, positive if `a > b`, or 0 if `a == b`. **/ - public static inline function compare( a : Int64, b : Int64 ) : Int { + public static inline function compare(a:Int64, b:Int64):Int { var v = a.high - b.high; - v = if( v != 0 ) v else Int32.ucompare(a.low, b.low); + v = if (v != 0) v else Int32.ucompare(a.low, b.low); return a.high < 0 ? (b.high < 0 ? v : -1) : (b.high >= 0 ? v : 1); } @@ -117,31 +113,30 @@ abstract Int64(__Int64) from __Int64 to __Int64 Returns a negative value if `a < b`, positive if `a > b`, or 0 if `a == b`. **/ - public static inline function ucompare( a : Int64, b : Int64 ) : Int { + public static inline function ucompare(a:Int64, b:Int64):Int { var v = Int32.ucompare(a.high, b.high); - return if( v != 0 ) v else Int32.ucompare(a.low, b.low); + return if (v != 0) v else Int32.ucompare(a.low, b.low); } /** Returns a signed decimal `String` representation of `x`. **/ - public static inline function toStr(x:Int64) : String + public static inline function toStr(x:Int64):String return x.toString(); - #if as3 public #else private #end function toString() : String - { - var i : Int64 = cast this; - if ( i == 0 ) + #if as3 public #else private #end function toString():String { + var i:Int64 = cast this; + if (i == 0) return "0"; var str = ""; var neg = false; - if( i.isNeg() ) { + if (i.isNeg()) { neg = true; // i = -i; cannot negate here as --9223372036854775808 = -9223372036854775808 } - var ten : Int64 = 10; - while( i != 0 ) { - var r = i.divMod( ten ); + var ten:Int64 = 10; + while (i != 0) { + var r = i.divMod(ten); if (r.modulus.isNeg()) { str = Int64.neg(r.modulus).low + str; i = Int64.neg(r.quotient); @@ -150,30 +145,31 @@ abstract Int64(__Int64) from __Int64 to __Int64 i = r.quotient; } } - if( neg ) str = "-" + str; + if (neg) + str = "-" + str; return str; } - public static inline function parseString( sParam : String ) : Int64 { - return Int64Helper.parseString( sParam ); + public static inline function parseString(sParam:String):Int64 { + return Int64Helper.parseString(sParam); } - public static inline function fromFloat( f : Float ) : Int64 { - return Int64Helper.fromFloat( f ); + public static inline function fromFloat(f:Float):Int64 { + return Int64Helper.fromFloat(f); } /** Performs signed integer divison of `dividend` by `divisor`. Returns `{ quotient : Int64, modulus : Int64 }`. **/ - public static function divMod( dividend : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 } - { + public static function divMod(dividend:Int64, divisor:Int64):{quotient:Int64, modulus:Int64} { // Handle special cases of 0 and 1 - if( divisor.high == 0 ) - { - switch( divisor.low ) { - case 0: throw "divide by zero"; - case 1: return { quotient : dividend.copy(), modulus : 0 }; + if (divisor.high == 0) { + switch (divisor.low) { + case 0: + throw "divide by zero"; + case 1: + return {quotient: dividend.copy(), modulus: 0}; } } @@ -182,18 +178,19 @@ abstract Int64(__Int64) from __Int64 to __Int64 var modulus = dividend.isNeg() ? -dividend : dividend.copy(); divisor = divisor.isNeg() ? -divisor : divisor; - var quotient : Int64 = 0; - var mask : Int64 = 1; + var quotient:Int64 = 0; + var mask:Int64 = 1; - while( !divisor.isNeg() ) { - var cmp = ucompare( divisor, modulus ); + while (!divisor.isNeg()) { + var cmp = ucompare(divisor, modulus); divisor <<= 1; mask <<= 1; - if( cmp >= 0 ) break; + if (cmp >= 0) + break; } - while( mask != 0 ) { - if( ucompare(modulus, divisor) >= 0 ) { + while (mask != 0) { + if (ucompare(modulus, divisor) >= 0) { quotient |= mask; modulus -= divisor; } @@ -201,47 +198,51 @@ abstract Int64(__Int64) from __Int64 to __Int64 divisor >>>= 1; } - if( divSign ) quotient = -quotient; - if( dividend.isNeg() ) modulus = -modulus; + if (divSign) + quotient = -quotient; + if (dividend.isNeg()) + modulus = -modulus; return { - quotient : quotient, - modulus : modulus + quotient: quotient, + modulus: modulus }; } /** Returns the negative of `x`. **/ - @:op(-A) public static inline function neg( x : Int64 ) : Int64 { + @:op(-A) public static inline function neg(x:Int64):Int64 { var high = ~x.high; var low = -x.low; - if( low == 0 ) + if (low == 0) high++; - return make( high, low ); + return make(high, low); } - @:op(++A) private inline function preIncrement() : Int64 { + @:op(++A) private inline function preIncrement():Int64 { this = copy(); this.low++; - if( this.low == 0 ) this.high++; + if (this.low == 0) + this.high++; return cast this; } - @:op(A++) private inline function postIncrement() : Int64 { + @:op(A++) private inline function postIncrement():Int64 { var ret = this; preIncrement(); return ret; } - @:op(--A) private inline function preDecrement() : Int64 { + @:op(--A) private inline function preDecrement():Int64 { this = copy(); - if( this.low == 0 ) this.high--; + if (this.low == 0) + this.high--; this.low--; return cast this; } - @:op(A--) private inline function postDecrement() : Int64 { + @:op(A--) private inline function postDecrement():Int64 { var ret = this; preDecrement(); return ret; @@ -250,36 +251,39 @@ abstract Int64(__Int64) from __Int64 to __Int64 /** Returns the sum of `a` and `b`. **/ - @:op(A + B) public static inline function add( a : Int64, b : Int64 ) : Int64 { + @:op(A + B) public static inline function add(a:Int64, b:Int64):Int64 { var high = a.high + b.high; var low = a.low + b.low; - if( Int32.ucompare( low, a.low ) < 0 ) high++; - return make( high, low ); + if (Int32.ucompare(low, a.low) < 0) + high++; + return make(high, low); } - @:op(A + B) @:commutative private static inline function addInt( a : Int64, b : Int ) : Int64 - return add( a, b ); + @:op(A + B) @:commutative private static inline function addInt(a:Int64, b:Int):Int64 + return add(a, b); /** Returns `a` minus `b`. **/ - @:op(A - B) public static inline function sub( a : Int64, b : Int64 ) : Int64 { + @:op(A - B) public static inline function sub(a:Int64, b:Int64):Int64 { var high = a.high - b.high; var low = a.low - b.low; - if( Int32.ucompare( a.low, b.low ) < 0 ) high--; - return make( high, low ); + if (Int32.ucompare(a.low, b.low) < 0) + high--; + return make(high, low); } - @:op(A - B) private static inline function subInt( a : Int64, b : Int ) : Int64 - return sub( a, b ); + @:op(A - B) private static inline function subInt(a:Int64, b:Int):Int64 + return sub(a, b); - @:op(A - B) private static inline function intSub( a : Int, b : Int64 ) : Int64 - return sub( a, b ); + @:op(A - B) private static inline function intSub(a:Int, b:Int64):Int64 + return sub(a, b); /** Returns the product of `a` and `b`. **/ - @:op(A * B) public static #if !lua inline #end function mul( a : Int64, b : Int64 ) : Int64 { + @:op(A * B) + public static #if !lua inline #end function mul(a:Int64, b:Int64):Int64 { var mask = 0xFFFF; var al = a.low & mask, ah = a.low >>> 16; var bl = b.low & mask, bh = b.low >>> 16; @@ -291,181 +295,185 @@ abstract Int64(__Int64) from __Int64 to __Int64 var high = p11 + (p01 >>> 16) + (p10 >>> 16); p01 <<= 16; low += p01; - if( Int32.ucompare(low, p01) < 0 ) high++; + if (Int32.ucompare(low, p01) < 0) + high++; p10 <<= 16; low += p10; - if( Int32.ucompare(low, p10) < 0 ) high++; + if (Int32.ucompare(low, p10) < 0) + high++; high += a.low * b.high + a.high * b.low; - return make( high, low ); + return make(high, low); } - @:op(A * B) @:commutative private static inline function mulInt( a : Int64, b : Int ) : Int64 - return mul( a, b ); + @:op(A * B) @:commutative private static inline function mulInt(a:Int64, b:Int):Int64 + return mul(a, b); /** Returns the quotient of `a` divided by `b`. **/ - @:op(A / B) public static inline function div( a : Int64, b : Int64 ) : Int64 + @:op(A / B) public static inline function div(a:Int64, b:Int64):Int64 return divMod(a, b).quotient; - @:op(A / B) private static inline function divInt( a : Int64, b : Int ) : Int64 - return div( a, b ); + @:op(A / B) private static inline function divInt(a:Int64, b:Int):Int64 + return div(a, b); - @:op(A / B) private static inline function intDiv( a : Int, b : Int64 ) : Int64 - return div( a, b ).toInt(); + @:op(A / B) private static inline function intDiv(a:Int, b:Int64):Int64 + return div(a, b).toInt(); /** Returns the modulus of `a` divided by `b`. **/ - @:op(A % B) public static inline function mod( a : Int64, b : Int64 ) : Int64 + @:op(A % B) public static inline function mod(a:Int64, b:Int64):Int64 return divMod(a, b).modulus; - @:op(A % B) private static inline function modInt( a : Int64, b : Int ) : Int64 - return mod( a, b ).toInt(); + @:op(A % B) private static inline function modInt(a:Int64, b:Int):Int64 + return mod(a, b).toInt(); - @:op(A % B) private static inline function intMod( a : Int, b : Int64 ) : Int64 - return mod( a, b ).toInt(); + @:op(A % B) private static inline function intMod(a:Int, b:Int64):Int64 + return mod(a, b).toInt(); /** Returns `true` if `a` is equal to `b`. **/ - @:op(A == B) public static inline function eq( a : Int64, b : Int64 ) : Bool + @:op(A == B) public static inline function eq(a:Int64, b:Int64):Bool return a.high == b.high && a.low == b.low; - @:op(A == B) @:commutative private static inline function eqInt( a : Int64, b : Int ) : Bool - return eq( a, b ); + @:op(A == B) @:commutative private static inline function eqInt(a:Int64, b:Int):Bool + return eq(a, b); /** Returns `true` if `a` is not equal to `b`. **/ - @:op(A != B) public static inline function neq( a : Int64, b : Int64 ) : Bool + @:op(A != B) public static inline function neq(a:Int64, b:Int64):Bool return a.high != b.high || a.low != b.low; - @:op(A != B) @:commutative private static inline function neqInt( a : Int64, b : Int ) : Bool + @:op(A != B) @:commutative private static inline function neqInt(a:Int64, b:Int):Bool return neq(a, b); - @:op(A < B) private static inline function lt( a : Int64, b : Int64 ) : Bool + @:op(A < B) private static inline function lt(a:Int64, b:Int64):Bool return compare(a, b) < 0; - @:op(A < B) private static inline function ltInt( a : Int64, b : Int ) : Bool + @:op(A < B) private static inline function ltInt(a:Int64, b:Int):Bool return lt(a, b); - @:op(A < B) private static inline function intLt( a : Int, b : Int64 ) : Bool + @:op(A < B) private static inline function intLt(a:Int, b:Int64):Bool return lt(a, b); - @:op(A <= B) private static inline function lte( a : Int64, b : Int64 ) : Bool + @:op(A <= B) private static inline function lte(a:Int64, b:Int64):Bool return compare(a, b) <= 0; - @:op(A <= B) private static inline function lteInt( a : Int64, b : Int ) : Bool + @:op(A <= B) private static inline function lteInt(a:Int64, b:Int):Bool return lte(a, b); - @:op(A <= B) private static inline function intLte( a : Int, b : Int64 ) : Bool + @:op(A <= B) private static inline function intLte(a:Int, b:Int64):Bool return lte(a, b); - @:op(A > B) private static inline function gt( a : Int64, b : Int64 ) : Bool + @:op(A > B) private static inline function gt(a:Int64, b:Int64):Bool return compare(a, b) > 0; - @:op(A > B) private static inline function gtInt( a : Int64, b : Int ) : Bool + @:op(A > B) private static inline function gtInt(a:Int64, b:Int):Bool return gt(a, b); - @:op(A > B) private static inline function intGt( a : Int, b : Int64 ) : Bool - return gt( a, b ); + @:op(A > B) private static inline function intGt(a:Int, b:Int64):Bool + return gt(a, b); - @:op(A >= B) private static inline function gte( a : Int64, b : Int64 ) : Bool + @:op(A >= B) private static inline function gte(a:Int64, b:Int64):Bool return compare(a, b) >= 0; - @:op(A >= B) private static inline function gteInt( a : Int64, b : Int ) : Bool + @:op(A >= B) private static inline function gteInt(a:Int64, b:Int):Bool return gte(a, b); - @:op(A >= B) private static inline function intGte( a : Int, b : Int64 ) : Bool + @:op(A >= B) private static inline function intGte(a:Int, b:Int64):Bool return gte(a, b); /** Returns the bitwise NOT of `a`. **/ - @:op(~A) private static inline function complement( a : Int64 ) : Int64 - return make( ~a.high, ~a.low ); + @:op(~A) private static inline function complement(a:Int64):Int64 + return make(~a.high, ~a.low); /** Returns the bitwise AND of `a` and `b`. **/ - @:op(A & B) public static inline function and( a : Int64, b : Int64 ) : Int64 - return make( a.high & b.high, a.low & b.low ); + @:op(A & B) public static inline function and(a:Int64, b:Int64):Int64 + return make(a.high & b.high, a.low & b.low); /** Returns the bitwise OR of `a` and `b`. **/ - @:op(A | B) public static inline function or( a : Int64, b : Int64 ) : Int64 - return make( a.high | b.high, a.low | b.low ); + @:op(A | B) public static inline function or(a:Int64, b:Int64):Int64 + return make(a.high | b.high, a.low | b.low); /** Returns the bitwise XOR of `a` and `b`. **/ - @:op(A ^ B) public static inline function xor( a : Int64, b : Int64 ) : Int64 - return make( a.high ^ b.high, a.low ^ b.low ); + @:op(A ^ B) public static inline function xor(a:Int64, b:Int64):Int64 + return make(a.high ^ b.high, a.low ^ b.low); /** Returns `a` left-shifted by `b` bits. **/ - @:op(A << B) public static inline function shl( a : Int64, b : Int ) : Int64 { + @:op(A << B) public static inline function shl(a:Int64, b:Int):Int64 { b &= 63; - return if( b == 0 ) a.copy() - else if( b < 32 ) make( (a.high << b) | (a.low >>> (32-b)), a.low << b) - else make( a.low << (b-32), 0 ); + return if (b == 0) a.copy() else if (b < 32) make((a.high << b) | (a.low >>> (32 - b)), a.low << b) else make(a.low << (b - 32), 0); } /** Returns `a` right-shifted by `b` bits in signed mode. `a` is sign-extended. **/ - @:op(A >> B) public static inline function shr( a : Int64, b : Int) : Int64 { + @:op(A >> B) public static inline function shr(a:Int64, b:Int):Int64 { b &= 63; - return if( b == 0 ) a.copy() - else if( b < 32 ) make( a.high >> b, (a.high << (32-b)) | (a.low >>> b) ); - else make( a.high >> 31, a.high >> (b - 32) ); + return if (b == 0) a.copy() else if (b < 32) make(a.high >> b, (a.high << (32 - b)) | (a.low >>> b)); else make(a.high >> 31, a.high >> (b - 32)); } /** Returns `a` right-shifted by `b` bits in unsigned mode. `a` is padded with zeroes. **/ - @:op(A >>> B) public static inline function ushr( a : Int64, b : Int ) : Int64 { + @:op(A >>> B) public static inline function ushr(a:Int64, b:Int):Int64 { b &= 63; - return if( b == 0 ) a.copy() - else if( b < 32 ) make( a.high >>> b, (a.high << (32-b)) | (a.low >>> b) ); - else make( 0, a.high >>> (b - 32) ); + return if (b == 0) a.copy() else if (b < 32) make(a.high >>> b, (a.high << (32 - b)) | (a.low >>> b)); else make(0, a.high >>> (b - 32)); } - public var high(get, never) : Int32; - private inline function get_high() return this.high; - private inline function set_high(x) return this.high = x; + public var high(get, never):Int32; + + private inline function get_high() + return this.high; + + private inline function set_high(x) + return this.high = x; + + public var low(get, never):Int32; + + private inline function get_low() + return this.low; - public var low(get, never) : Int32; - private inline function get_low() return this.low; - private inline function set_low(x) return this.low = x; + private inline function set_low(x) + return this.low = x; } /** - * This typedef will fool @:coreApi into thinking that we are using - * the same underlying type, even though it might be different on - * specific platforms. - */ + This typedef will fool `@:coreApi` into thinking that we are using + the same underlying type, even though it might be different on + specific platforms. +**/ private typedef __Int64 = ___Int64; private class ___Int64 { - public var high : Int32; - public var low : Int32; + public var high:Int32; + public var low:Int32; - public inline function new( high, low ) { + public inline function new(high, low) { this.high = high; this.low = low; } /** We also define toString here to ensure we always get a pretty string - when tracing or calling Std.string. This tends not to happen when - toString is only in the abstract. + when tracing or calling `Std.string`. This tends not to happen when + `toString` is only in the abstract. **/ - public function toString() : String - return Int64.toStr( cast this ); + public function toString():String + return Int64.toStr(cast this); } diff --git a/std/haxe/Int64Helper.hx b/std/haxe/Int64Helper.hx index 5fcb9b9c8b0..bd34c341fed 100644 --- a/std/haxe/Int64Helper.hx +++ b/std/haxe/Int64Helper.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; using haxe.Int64; @@ -32,7 +33,7 @@ class Int64Helper { /** Create `Int64` from given string. **/ - public static function parseString( sParam : String ) : Int64 { + public static function parseString(sParam:String):Int64 { var base = Int64.ofInt(10); var current = Int64.ofInt(0); var multiplier = Int64.ofInt(1); @@ -51,8 +52,8 @@ class Int64Helper { if (digitInt < 0 || digitInt > 9) { throw "NumberFormatError"; } - - if (digitInt != 0 ) { + + if (digitInt != 0) { var digit:Int64 = Int64.ofInt(digitInt); if (sIsNegative) { current = Int64.sub(current, Int64.mul(multiplier, digit)); @@ -66,7 +67,7 @@ class Int64Helper { } } } - + multiplier = Int64.mul(multiplier, base); } return current; @@ -75,7 +76,7 @@ class Int64Helper { /** Create `Int64` from given float. **/ - public static function fromFloat( f : Float ) : Int64 { + public static function fromFloat(f:Float):Int64 { if (Math.isNaN(f) || !Math.isFinite(f)) { throw "Number is NaN or Infinite"; } @@ -84,7 +85,7 @@ class Int64Helper { // 2^53-1 and -2^53+1: these are parseable without loss of precision. // In theory 2^53 and -2^53 are parseable too, but then there's no way to - // distinguish 2^53 from 2^53+1 + // distinguish 2^53 from 2^53+1 // (i.e. trace(9007199254740992. + 1. > 9007199254740992.); // false!) if (noFractions > 9007199254740991) { throw "Conversion overflow"; diff --git a/std/haxe/Json.hx b/std/haxe/Json.hx index aa16564dbcd..18a7dc4dbb9 100644 --- a/std/haxe/Json.hx +++ b/std/haxe/Json.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; /** @@ -29,7 +30,6 @@ package haxe; @see https://haxe.org/manual/std-Json.html **/ class Json { - /** Parses given JSON-encoded `text` and returns the resulting object. @@ -40,7 +40,7 @@ class Json { @see https://haxe.org/manual/std-Json-parsing.html **/ - public static inline function parse( text : String ) : Dynamic { + public static inline function parse(text:String):Dynamic { return haxe.format.JsonParser.parse(text); } @@ -50,14 +50,13 @@ class Json { If `replacer` is given and is not null, it is used to retrieve the actual object to be encoded. The `replacer` function takes two parameters, the key and the value being encoded. Initial key value is an empty string. - + If `space` is given and is not null, the result will be pretty-printed. Successive levels will be indented by this string. @see https://haxe.org/manual/std-Json-encoding.html **/ - public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space : String ) : String { + public static inline function stringify(value:Dynamic, ?replacer:(key:Dynamic, value:Dynamic) -> Dynamic, ?space:String):String { return haxe.format.JsonPrinter.print(value, replacer, space); } - } diff --git a/std/haxe/Log.hx b/std/haxe/Log.hx index 05ded56e42d..9814dde23db 100644 --- a/std/haxe/Log.hx +++ b/std/haxe/Log.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,27 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; /** Log primarily provides the `trace()` method, which is invoked upon a call to `trace()` in Haxe code. **/ -extern class Log { +class Log { + /** + Format the output of `trace` before printing it. + **/ + public static function formatOutput(v:Dynamic, infos:PosInfos):String { + var str = Std.string(v); + if (infos == null) + return str; + var pstr = infos.fileName + ":" + infos.lineNumber; + if (infos.customParams != null) + for (v in infos.customParams) + str += ", " + Std.string(v); + return pstr + ": " + str; + } /** Outputs `v` in a platform-dependent way. @@ -34,6 +48,7 @@ extern class Log { information about the position where the `trace()` call was made. This method can be rebound to a custom function: + var oldTrace = haxe.Log.trace; // store old function haxe.Log.trace = function(v, ?infos) { // handle trace @@ -44,5 +59,17 @@ extern class Log { If it is bound to null, subsequent calls to `trace()` will cause an exception. **/ - static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void; + public static dynamic function trace(v:Dynamic, ?infos:PosInfos):Void { + var str = formatOutput(v, infos); + #if js + if (js.Syntax.typeof(untyped console) != "undefined" && (untyped console).log != null) + (untyped console).log(str); + #elseif lua + untyped __define_feature__("use._hx_print", _hx_print(str)); + #elseif sys + Sys.println(str); + #else + throw "Not implemented" + #end + } } diff --git a/std/haxe/MainLoop.hx b/std/haxe/MainLoop.hx index 5336c4025bd..e63cac8b8de 100644 --- a/std/haxe/MainLoop.hx +++ b/std/haxe/MainLoop.hx @@ -1,13 +1,19 @@ package haxe; + import haxe.EntryPoint; class MainEvent { + var f:Void->Void; + var prev:MainEvent; + var next:MainEvent; + + /** + Tells if the event can lock the process from exiting (default:true) + **/ + public var isBlocking:Bool = true; - var f : Void -> Void; - var prev : MainEvent; - var next : MainEvent; - public var nextRun(default,null) : Float; - public var priority(default,null) : Int; + public var nextRun(default, null):Float; + public var priority(default, null):Int; function new(f, p) { this.f = f; @@ -19,7 +25,7 @@ class MainEvent { Delay the execution of the event for the given time, in seconds. If t is null, the event will be run at tick() time. **/ - public function delay( t : Null ) { + public function delay(t:Null) { nextRun = t == null ? -1 : haxe.Timer.stamp() + t; } @@ -27,56 +33,64 @@ class MainEvent { Call the event. Will do nothing if the event has been stopped. **/ public inline function call() { - if( f != null ) f(); + if (f != null) + f(); } /** Stop the event from firing anymore. **/ public function stop() { - if( f == null ) return; + if (f == null) + return; f = null; nextRun = -1; - if( prev == null ) + if (prev == null) @:privateAccess MainLoop.pending = next; else prev.next = next; - if( next != null ) + if (next != null) next.prev = prev; } - } @:access(haxe.MainEvent) class MainLoop { + static var pending:MainEvent; - static var pending : MainEvent = null; - - public static var threadCount(get, never) : Int; + public static var threadCount(get, never):Int; - inline static function get_threadCount() return EntryPoint.threadCount; + inline static function get_threadCount() + return EntryPoint.threadCount; - public inline static function hasEvents() { - return pending != null; + public static function hasEvents() { + var p = pending; + while (p != null) { + if (p.isBlocking) + return true; + p = p.next; + } + return false; } - public static function addThread( f : Void -> Void ) { + public static function addThread(f:Void->Void) { EntryPoint.addThread(f); } - public static function runInMainThread( f : Void -> Void ) { + public static function runInMainThread(f:Void->Void) { EntryPoint.runInMainThread(f); } /** Add a pending event to be run into the main loop. **/ - public static function add( f : Void -> Void, priority = 0 ) : MainEvent @:privateAccess { - if( f == null ) + public static function add(f:Void->Void, priority = 0):MainEvent@:privateAccess { + if (f == null) throw "Event function is null"; var e = new MainEvent(f, priority); var head = pending; - if( head != null ) head.prev = e; + if (head != null) + head.prev = e; e.next = head; pending = e; return e; @@ -88,32 +102,36 @@ class MainLoop { // we do then a manual inline, this also allow use to do a Float comparison of nextRun var list = pending; - if( list == null ) return; + if (list == null) + return; var insize = 1, nmerges, psize = 0, qsize = 0; - var p, q, e, tail : MainEvent; + var p, q, e, tail:MainEvent; - while( true ) { + while (true) { p = list; list = null; tail = null; nmerges = 0; - while( p != null ) { + while (p != null) { nmerges++; q = p; psize = 0; - for( i in 0...insize ) { + for (i in 0...insize) { psize++; q = q.next; - if( q == null ) break; + if (q == null) + break; } qsize = insize; - while( psize > 0 || (qsize > 0 && q != null) ) { - if( psize == 0 ) { + while (psize > 0 || (qsize > 0 && q != null)) { + if (psize == 0) { e = q; q = q.next; qsize--; - } else if( qsize == 0 || q == null || (p.priority > q.priority || (p.priority == q.priority && p.nextRun <= q.nextRun)) ) { + } else if (qsize == 0 + || q == null + || (p.priority > q.priority || (p.priority == q.priority && p.nextRun <= q.nextRun))) { e = p; p = p.next; psize--; @@ -122,7 +140,7 @@ class MainLoop { q = q.next; qsize--; } - if( tail != null ) + if (tail != null) tail.next = e; else list = e; @@ -132,7 +150,7 @@ class MainLoop { p = q; } tail.next = null; - if( nmerges <= 1 ) + if (nmerges <= 1) break; insize *= 2; } @@ -148,17 +166,16 @@ class MainLoop { var e = pending; var now = haxe.Timer.stamp(); var wait = 1e9; - while( e != null ) { + while (e != null) { var next = e.next; var wt = e.nextRun - now; - if( e.nextRun < 0 || wt <= 0 ) { + if (e.nextRun < 0 || wt <= 0) { wait = 0; e.call(); - } else if( wait > wt ) + } else if (wait > wt) wait = wt; e = next; } return wait; } - } diff --git a/std/haxe/PosInfos.hx b/std/haxe/PosInfos.hx index 8a18c39ddf3..a34b2996c1f 100644 --- a/std/haxe/PosInfos.hx +++ b/std/haxe/PosInfos.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; /** @@ -33,9 +34,9 @@ package haxe; framework. **/ typedef PosInfos = { - var fileName : String; - var lineNumber : Int; - var className : String; - var methodName : String; - @:optional var customParams : Array; -} \ No newline at end of file + var fileName:String; + var lineNumber:Int; + var className:String; + var methodName:String; + var ?customParams:Array; +} diff --git a/std/haxe/Resource.hx b/std/haxe/Resource.hx index e4501892294..c6ee62d84ce 100644 --- a/std/haxe/Resource.hx +++ b/std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; /** @@ -31,14 +32,13 @@ package haxe; A list of all available resource names can be obtained from listNames(). **/ class Resource { - - static var content : Array<{ name : String, data : String, str : String }>; + static var content:Array<{name:String, data:String, str:String}>; /** Lists all available resource names. The resource name is the name part of the -resource file@name command line parameter. **/ - public static function listNames() : Array { + public static function listNames():Array { return [for (x in content) x.name]; } @@ -47,14 +47,15 @@ class Resource { If `name` does not match any resource name, null is returned. **/ - public static function getString( name : String ) : String { - for( x in content ) - if( x.name == name ) { + public static function getString(name:String):String { + for (x in content) + if (x.name == name) { #if neko return new String(x.data); #else - if( x.str != null ) return x.str; - var b : haxe.io.Bytes = haxe.crypto.Base64.decode(x.data); + if (x.str != null) + return x.str; + var b:haxe.io.Bytes = haxe.crypto.Base64.decode(x.data); return b.toString(); #end } @@ -67,13 +68,14 @@ class Resource { If `name` does not match any resource name, null is returned. **/ - public static function getBytes( name : String ) : haxe.io.Bytes { - for( x in content ) - if( x.name == name ) { + public static function getBytes(name:String):haxe.io.Bytes { + for (x in content) + if (x.name == name) { #if neko return haxe.io.Bytes.ofData(cast x.data); #else - if( x.str != null ) return haxe.io.Bytes.ofString(x.str); + if (x.str != null) + return haxe.io.Bytes.ofString(x.str); return haxe.crypto.Base64.decode(x.data); #end } @@ -83,12 +85,11 @@ class Resource { static function __init__() { #if neko var tmp = untyped __resources__(); - content = untyped Array.new1(tmp,__dollar__asize(tmp)); + content = untyped Array.new1(tmp, __dollar__asize(tmp)); #elseif as3 null; #else content = untyped __resources__(); #end } - } diff --git a/std/haxe/Serializer.hx b/std/haxe/Serializer.hx index 4b89e70f378..45631924292 100644 --- a/std/haxe/Serializer.hx +++ b/std/haxe/Serializer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,9 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; import haxe.ds.List; + /** The Serializer class can be used to encode values and objects into a `String`, from which the `Unserializer` class can recreate the original representation. @@ -38,10 +40,9 @@ import haxe.ds.List; or may not work for instances of external/native classes. The specification of the serialization format can be found here: - + **/ class Serializer { - /** If the values you are serializing can contain circular references or objects repetitions, you should set `USE_CACHE` to true to prevent @@ -70,24 +71,24 @@ class Serializer { static var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%:"; static var BASE64_CODES = null; - var buf : StringBuf; - var cache : Array; - var shash : haxe.ds.StringMap; - var scount : Int; + var buf:StringBuf; + var cache:Array; + var shash:haxe.ds.StringMap; + var scount:Int; /** The individual cache setting for `this` Serializer instance. See USE_CACHE for a complete description. **/ - public var useCache : Bool; + public var useCache:Bool; /** The individual enum index setting for `this` Serializer instance. See USE_ENUM_INDEX for a complete description. **/ - public var useEnumIndex : Bool; + public var useEnumIndex:Bool; /** Creates a new Serializer instance. @@ -149,19 +150,19 @@ class Serializer { B : Enum M : haxe.ds.ObjectMap C : custom - */ - - function serializeString( s : String ) { + */ + function serializeString(s:String) { var x = shash.get(s); - if( x != null ) { + if (x != null) { buf.add("R"); buf.add(x); return; } - shash.set(s,scount++); + shash.set(s, scount++); #if old_serialize - // no more support for -D old_serialize due to 'j' reuse - #if error #end + // no more support for -D old_serialize due to 'j' reuse + #if error + #end #end buf.add("y"); s = StringTools.urlEncode(s); @@ -172,14 +173,14 @@ class Serializer { function serializeRef(v:Dynamic) { #if js - var vt = js.Lib.typeof(v); + var vt = js.Syntax.typeof(v); #end - for( i in 0...cache.length ) { + for (i in 0...cache.length) { #if js var ci = cache[i]; - if( js.Lib.typeof(ci) == vt && ci == v ) { + if (js.Syntax.typeof(ci) == vt && ci == v) { #else - if( cache[i] == v ) { + if (cache[i] == v) { #end buf.add("r"); buf.add(i); @@ -194,358 +195,367 @@ class Serializer { // only the instance variables function serializeClassFields(v:Dynamic, c:Dynamic) { - var xml : flash.xml.XML = untyped __global__["flash.utils.describeType"](c); + var xml:flash.xml.XML = untyped __global__["flash.utils.describeType"](c); var vars = xml.factory[0].child("variable"); - for( i in 0...vars.length() ) { + for (i in 0...vars.length()) { var f = vars[i].attribute("name").toString(); - if( !v.hasOwnProperty(f) ) + if (!v.hasOwnProperty(f)) continue; serializeString(f); - serialize(Reflect.field(v,f)); + serialize(Reflect.field(v, f)); } buf.add("g"); } #end function serializeFields(v:{}) { - for( f in Reflect.fields(v) ) { + for (f in Reflect.fields(v)) { serializeString(f); - serialize(Reflect.field(v,f)); + serialize(Reflect.field(v, f)); } buf.add("g"); } /** - Serializes `v`. + Serializes `v`. - All haxe-defined values and objects with the exception of functions can - be serialized. Serialization of external/native objects is not - guaranteed to work. + All haxe-defined values and objects with the exception of functions can + be serialized. Serialization of external/native objects is not + guaranteed to work. - The values of `this.useCache` and `this.useEnumIndex` may affect - serialization output. - **/ - public function serialize( v : Dynamic ) { - switch( Type.typeof(v) ) { - case TNull: - buf.add("n"); - case TInt: - var v : Int = v; - if( v == 0 ) { - buf.add("z"); - return; - } - buf.add("i"); - buf.add(v); - case TFloat: - var v : Float = v; - if( Math.isNaN(v) ) - buf.add("k"); - else if( !Math.isFinite(v) ) - buf.add(if( v < 0 ) "m" else "p"); - else { - buf.add("d"); + The values of `this.useCache` and `this.useEnumIndex` may affect + serialization output. +**/ + public function serialize(v:Dynamic) { + switch (Type.typeof(v)) { + case TNull: + buf.add("n"); + case TInt: + var v:Int = v; + if (v == 0) { + buf.add("z"); + return; + } + buf.add("i"); buf.add(v); - } - case TBool: - buf.add(if( v ) "t" else "f"); - case TClass(c): - if( #if neko untyped c.__is_String #else c == String #end ) { - serializeString(v); - return; - } - if( useCache && serializeRef(v) ) - return; - switch( #if (neko || cs || python) Type.getClassName(c) #else c #end ) { - case #if (neko || cs || python) "Array" #else cast Array #end: - var ucount = 0; - buf.add("a"); - #if (flash || python || hl) - var v : Array = v; - #end - var l = #if (neko || flash || php || cs || java || python || hl || lua || eval) v.length #elseif cpp v.__length() #else __getField(v, "length") #end; - for( i in 0...l ) { - if( v[i] == null ) - ucount++; - else { - if( ucount > 0 ) { - if( ucount == 1 ) + case TFloat: + var v:Float = v; + if (Math.isNaN(v)) + buf.add("k"); + else if (!Math.isFinite(v)) + buf.add(if (v < 0) "m" else "p"); + else { + buf.add("d"); + buf.add(v); + } + case TBool: + buf.add(if (v) "t" else "f"); + case TClass(c): + if (#if neko untyped c.__is_String #else c == String #end) { + serializeString(v); + return; + } + if (useCache && serializeRef(v)) + return; + switch (#if (neko || cs || python) Type.getClassName(c) #else c #end) { + case #if (neko || cs || python) "Array" #else cast Array #end: + var ucount = 0; + buf.add("a"); + #if (flash || python || hl) + var v:Array = v; + #end + var l = #if (neko || flash || php || cs || java || python || hl || lua || eval) v.length #elseif cpp v.__length() #else __getField(v, + "length") #end; + for (i in 0...l) { + if (v[i] == null) + ucount++; + else { + if (ucount > 0) { + if (ucount == 1) + buf.add("n"); + else { + buf.add("u"); + buf.add(ucount); + } + ucount = 0; + } + serialize(v[i]); + } + } + if (ucount > 0) { + if (ucount == 1) buf.add("n"); else { buf.add("u"); buf.add(ucount); } - ucount = 0; } - serialize(v[i]); - } + buf.add("h"); + case #if (neko || cs || python) "haxe.ds.List" #else cast List #end: + buf.add("l"); + var v:List = v; + for (i in v) + serialize(i); + buf.add("h"); + case #if (neko || cs || python) "Date" #else cast Date #end: + var d:Date = v; + buf.add("v"); + buf.add(d.getTime()); + case #if (neko || cs || python) "haxe.ds.StringMap" #else cast haxe.ds.StringMap #end: + buf.add("b"); + var v:haxe.ds.StringMap = v; + for (k in v.keys()) { + serializeString(k); + serialize(v.get(k)); + } + buf.add("h"); + case #if (neko || cs || python) "haxe.ds.IntMap" #else cast haxe.ds.IntMap #end: + buf.add("q"); + var v:haxe.ds.IntMap = v; + for (k in v.keys()) { + buf.add(":"); + buf.add(k); + serialize(v.get(k)); + } + buf.add("h"); + case #if (neko || cs || python) "haxe.ds.ObjectMap" #else cast haxe.ds.ObjectMap #end: + buf.add("M"); + var v:haxe.ds.ObjectMap = v; + for (k in v.keys()) { + #if (js || neko) + var id = Reflect.field(k, "__id__"); + Reflect.deleteField(k, "__id__"); + serialize(k); + Reflect.setField(k, "__id__", id); + #else + serialize(k); + #end + serialize(v.get(k)); + } + buf.add("h"); + case #if (neko || cs || python) "haxe.io.Bytes" #else cast haxe.io.Bytes #end: + var v:haxe.io.Bytes = v; + #if neko + var chars = new String(base_encode(v.getData(), untyped BASE64.__s)); + buf.add("s"); + buf.add(chars.length); + buf.add(":"); + buf.add(chars); + #else + buf.add("s"); + buf.add(Math.ceil((v.length * 8) / 6)); + buf.add(":"); + + var i = 0; + var max = v.length - 2; + var b64 = BASE64_CODES; + if (b64 == null) { + b64 = new haxe.ds.Vector(BASE64.length); + for (i in 0...BASE64.length) + b64[i] = BASE64.charCodeAt(i); + BASE64_CODES = b64; + } + while (i < max) { + var b1 = v.get(i++); + var b2 = v.get(i++); + var b3 = v.get(i++); + + buf.addChar(b64[b1 >> 2]); + buf.addChar(b64[((b1 << 4) | (b2 >> 4)) & 63]); + buf.addChar(b64[((b2 << 2) | (b3 >> 6)) & 63]); + buf.addChar(b64[b3 & 63]); + } + if (i == max) { + var b1 = v.get(i++); + var b2 = v.get(i++); + buf.addChar(b64[b1 >> 2]); + buf.addChar(b64[((b1 << 4) | (b2 >> 4)) & 63]); + buf.addChar(b64[(b2 << 2) & 63]); + } else if (i == max + 1) { + var b1 = v.get(i++); + buf.addChar(b64[b1 >> 2]); + buf.addChar(b64[(b1 << 4) & 63]); + } + #end + default: + if (useCache) cache.pop(); + if (#if flash try + v.hxSerialize != null + catch (e:Dynamic) + false #elseif (cs || java || python) Reflect.hasField(v, + "hxSerialize") #elseif php php.Global.method_exists(v, 'hxSerialize') #else v.hxSerialize != null #end) { + buf.add("C"); + serializeString(Type.getClassName(c)); + if (useCache) + cache.push(v); + v.hxSerialize(this); + buf.add("g"); + } else { + buf.add("c"); + serializeString(Type.getClassName(c)); + if (useCache) + cache.push(v); + #if flash + serializeClassFields(v, c); + #else + serializeFields(v); + #end + } } - if( ucount > 0 ) { - if( ucount == 1 ) - buf.add("n"); - else { - buf.add("u"); - buf.add(ucount); - } + case TObject: + if (Std.is(v, Class)) { + var className = Type.getClassName(v); + #if (flash || cpp) + // Currently, Enum and Class are the same for flash and cpp. + // use resolveEnum to test if it is actually an enum + if (Type.resolveEnum(className) != null) + buf.add("B") + else + #end + buf.add("A"); + serializeString(className); + } else if (Std.is(v, Enum)) { + buf.add("B"); + serializeString(Type.getEnumName(v)); + } else { + if (useCache && serializeRef(v)) + return; + buf.add("o"); + serializeFields(v); } - buf.add("h"); - case #if (neko || cs || python) "haxe.ds.List" #else cast List #end: - buf.add("l"); - var v : List = v; - for( i in v ) - serialize(i); - buf.add("h"); - case #if (neko || cs || python) "Date" #else cast Date #end: - var d : Date = v; - buf.add("v"); - buf.add(d.getTime()); - case #if (neko || cs || python) "haxe.ds.StringMap" #else cast haxe.ds.StringMap #end: - buf.add("b"); - var v : haxe.ds.StringMap = v; - for( k in v.keys() ) { - serializeString(k); - serialize(v.get(k)); + case TEnum(e): + if (useCache) { + if (serializeRef(v)) + return; + cache.pop(); } - buf.add("h"); - case #if (neko || cs || python) "haxe.ds.IntMap" #else cast haxe.ds.IntMap #end: - buf.add("q"); - var v : haxe.ds.IntMap = v; - for( k in v.keys() ) { + buf.add(useEnumIndex ? "j" : "w"); + serializeString(Type.getEnumName(e)); + #if neko + if (useEnumIndex) { buf.add(":"); - buf.add(k); - serialize(v.get(k)); + buf.add(v.index); + } else + serializeString(new String(v.tag)); + buf.add(":"); + if (v.args == null) + buf.add(0); + else { + var l:Int = untyped __dollar__asize(v.args); + buf.add(l); + for (i in 0...l) + serialize(v.args[i]); } - buf.add("h"); - case #if (neko || cs || python) "haxe.ds.ObjectMap" #else cast haxe.ds.ObjectMap #end: - buf.add("M"); - var v : haxe.ds.ObjectMap = v; - for ( k in v.keys() ) { - #if (js || neko) - var id = Reflect.field(k, "__id__"); - Reflect.deleteField(k, "__id__"); - serialize(k); - Reflect.setField(k, "__id__", id); - #else - serialize(k); - #end - serialize(v.get(k)); + #elseif flash + if (useEnumIndex) { + buf.add(":"); + var i:Int = v.index; + buf.add(i); + } else + serializeString(v.tag); + buf.add(":"); + var pl:Array = v.params; + if (pl == null) + buf.add(0); + else { + buf.add(pl.length); + for (p in pl) + serialize(p); } - buf.add("h"); - case #if (neko || cs || python) "haxe.io.Bytes" #else cast haxe.io.Bytes #end: - var v : haxe.io.Bytes = v; - #if neko - var chars = new String(base_encode(v.getData(),untyped BASE64.__s)); - buf.add("s"); - buf.add(chars.length); + #elseif cpp + var enumBase:cpp.EnumBase = v; + if (useEnumIndex) { + buf.add(":"); + buf.add(enumBase.getIndex()); + } else + serializeString(enumBase.getTag()); buf.add(":"); - buf.add(chars); - #else - - buf.add("s"); - buf.add(Math.ceil((v.length * 8) / 6)); + var len = enumBase.getParamCount(); + buf.add(len); + for (p in 0...len) + serialize(enumBase.getParamI(p)); + #elseif php + if (useEnumIndex) { + buf.add(":"); + buf.add(v.index); + } else + serializeString(v.tag); buf.add(":"); - - var i = 0; - var max = v.length - 2; - var b64 = BASE64_CODES; - if( b64 == null ) { - b64 = new haxe.ds.Vector(BASE64.length); - for( i in 0...BASE64.length ) - b64[i] = BASE64.charCodeAt(i); - BASE64_CODES = b64; - } - while( i < max ) { - var b1 = v.get(i++); - var b2 = v.get(i++); - var b3 = v.get(i++); - - buf.addChar(b64[b1 >> 2]); - buf.addChar(b64[((b1 << 4) | (b2 >> 4)) & 63]); - buf.addChar(b64[((b2 << 2) | (b3 >> 6)) & 63]); - buf.addChar(b64[b3 & 63]); - } - if( i == max ) { - var b1 = v.get(i++); - var b2 = v.get(i++); - buf.addChar(b64[b1 >> 2]); - buf.addChar(b64[((b1 << 4) | (b2 >> 4)) & 63]); - buf.addChar(b64[(b2 << 2) & 63]); - } else if( i == max + 1 ) { - var b1 = v.get(i++); - buf.addChar(b64[b1 >> 2]); - buf.addChar(b64[(b1 << 4) & 63]); + var l:Int = php.Syntax.code("count({0})", v.params); + if (l == 0 || v.params == null) + buf.add(0); + else { + buf.add(l); + for (i in 0...l) { + #if php + serialize(v.params[i]); + #end + } } - #end - default: - if( useCache ) cache.pop(); - if( #if flash try v.hxSerialize != null catch( e : Dynamic ) false #elseif (cs || java || python) Reflect.hasField(v, "hxSerialize") #elseif php php.Global.method_exists(v, 'hxSerialize') #else v.hxSerialize != null #end ) { - buf.add("C"); - serializeString(Type.getClassName(c)); - if( useCache ) cache.push(v); - v.hxSerialize(this); - buf.add("g"); + #elseif (java || cs || python || hl || eval) + if (useEnumIndex) { + buf.add(":"); + buf.add(Type.enumIndex(v)); + } else + serializeString(Type.enumConstructor(v)); + buf.add(":"); + var arr:Array = Type.enumParameters(v); + if (arr != null) { + buf.add(arr.length); + for (v in arr) + serialize(v); } else { - buf.add("c"); - serializeString(Type.getClassName(c)); - if( useCache ) cache.push(v); - #if flash - serializeClassFields(v,c); - #else - serializeFields(v); - #end + buf.add("0"); } - } - case TObject: - if (Std.is(v,Class)) { - var className = Type.getClassName(v); - #if (flash || cpp) - // Currently, Enum and Class are the same for flash and cpp. - // use resolveEnum to test if it is actually an enum - if (Type.resolveEnum(className)!=null) buf.add("B") else - #end - buf.add("A"); - serializeString(className); - } else if (Std.is(v,Enum)) { - buf.add("B"); - serializeString(Type.getEnumName(v)); - } else { - if( useCache && serializeRef(v) ) - return; - buf.add("o"); - serializeFields(v); - } - case TEnum(e): - if( useCache ) { - if( serializeRef(v) ) - return; - cache.pop(); - } - buf.add(useEnumIndex?"j":"w"); - serializeString(Type.getEnumName(e)); - #if neko - if( useEnumIndex ) { - buf.add(":"); - buf.add(v.index); - } else - serializeString(new String(v.tag)); - buf.add(":"); - if( v.args == null ) - buf.add(0); - else { - var l : Int = untyped __dollar__asize(v.args); - buf.add(l); - for( i in 0...l ) - serialize(v.args[i]); - } - #elseif flash - if( useEnumIndex ) { + #elseif (js && !js_enums_as_arrays) + if (useEnumIndex) { + buf.add(":"); + buf.add(v._hx_index); + } else + serializeString(Type.enumConstructor(v)); buf.add(":"); - var i : Int = v.index; - buf.add(i); - } else - serializeString(v.tag); - buf.add(":"); - var pl : Array = v.params; - if( pl == null ) - buf.add(0); - else { - buf.add(pl.length); - for( p in pl ) + var params = Type.enumParameters(v); + buf.add(params.length); + for (p in params) serialize(p); - } - #elseif cpp - var enumBase:cpp.EnumBase = v; - if( useEnumIndex ) { - buf.add(":"); - buf.add(enumBase.getIndex()); - } else - serializeString(enumBase.getTag()); - buf.add(":"); - var len = enumBase.getParamCount(); - buf.add(len); - for( p in 0...len ) - serialize( enumBase.getParamI(p)); - #elseif php - if( useEnumIndex ) { + #else + if (useEnumIndex) { + buf.add(":"); + buf.add(v[1]); + } else + serializeString(v[0]); buf.add(":"); - buf.add(v.index); - } else - serializeString(v.tag); - buf.add(":"); - var l : Int = untyped __call__("count", v.params); - if( l == 0 || v.params == null) - buf.add(0); - else { - buf.add(l); - for( i in 0...l ) { - #if php - serialize(v.params[i]); - #end + var l = __getField(v, "length"); + buf.add(l - 2); + for (i in 2...l) + serialize(v[i]); + #end + if (useCache) + cache.push(v); + case TFunction: + throw "Cannot serialize function"; + default: + #if neko + if (untyped (__i32__kind != null && __dollar__iskind(v, __i32__kind))) { + buf.add("i"); + buf.add(v); + return; } - } - #elseif (java || cs || python || hl || eval) - if( useEnumIndex ) { - buf.add(":"); - buf.add(Type.enumIndex(v)); - } else - serializeString(Type.enumConstructor(v)); - buf.add(":"); - var arr:Array = Type.enumParameters(v); - if (arr != null) - { - buf.add(arr.length); - for (v in arr) - serialize(v); - } else { - buf.add("0"); - } - - #elseif js_enums_as_objects - if( useEnumIndex ) { - buf.add(":"); - buf.add(v._hx_index); - } else - serializeString(Type.enumConstructor(v)); - buf.add(":"); - var params = Type.enumParameters(v); - buf.add(params.length); - for(p in params) serialize(p); - #else - if( useEnumIndex ) { - buf.add(":"); - buf.add(v[1]); - } else - serializeString(v[0]); - buf.add(":"); - var l = __getField(v, "length"); - buf.add(l - 2); - for( i in 2...l ) - serialize(v[i]); - #end - if( useCache ) cache.push(v); - case TFunction: - throw "Cannot serialize function"; - default: - #if neko - if( untyped (__i32__kind != null && __dollar__iskind(v,__i32__kind)) ) { - buf.add("i"); - buf.add(v); - return; - } - #end - throw "Cannot serialize "+Std.string(v); + #end + throw "Cannot serialize " + Std.string(v); } } - @:extern inline function __getField(o:Dynamic, f:String):Dynamic return untyped o[f]; + extern inline function __getField(o:Dynamic, f:String):Dynamic + return o[cast f]; - public function serializeException( e : Dynamic ) { + public function serializeException(e:Dynamic) { buf.add("x"); #if flash - if( untyped __is__(e,__global__["Error"]) ) { - var e : flash.errors.Error = e; + if (untyped __is__(e, __global__["Error"])) { + var e:flash.errors.Error = e; var s = e.getStackTrace(); - if( s == null ) + if (s == null) serialize(e.message); else serialize(s); @@ -556,21 +566,19 @@ class Serializer { } /** - Serializes `v` and returns the String representation. + Serializes `v` and returns the String representation. - This is a convenience function for creating a new instance of - Serializer, serialize `v` into it and obtain the result through a call - to toString(). - **/ - public static function run( v : Dynamic ) { + This is a convenience function for creating a new instance of + Serializer, serialize `v` into it and obtain the result through a call + to toString(). +**/ + public static function run(v:Dynamic) { var s = new Serializer(); s.serialize(v); return s.toString(); } #if neko - static var base_encode = neko.Lib.load("std","base_encode",2); + static var base_encode = neko.Lib.load("std", "base_encode", 2); #end - } - diff --git a/std/haxe/SysTools.hx b/std/haxe/SysTools.hx new file mode 100644 index 00000000000..147f4e81199 --- /dev/null +++ b/std/haxe/SysTools.hx @@ -0,0 +1,106 @@ +package haxe; + +import haxe.ds.ReadOnlyArray; + +class SysTools { + /** + Character codes of the characters that will be escaped by `quoteWinArg(_, true)`. + **/ + public static final winMetaCharacters:ReadOnlyArray = [ + " ".code, "(".code, ")".code, "%".code, "!".code, "^".code, "\"".code, "<".code, ">".code, "&".code, "|".code, "\n".code, "\r".code, ",".code, ";".code + ]; + + /** + Returns a String that can be used as a single command line argument + on Unix. + The input will be quoted, or escaped if necessary. + **/ + public static function quoteUnixArg(argument:String):String { + // Based on cpython's shlex.quote(). + // https://hg.python.org/cpython/file/a3f076d4f54f/Lib/shlex.py#l278 + + if (argument == "") + return "''"; + + if (!~/[^a-zA-Z0-9_@%+=:,.\/-]/.match(argument)) + return argument; + + // use single quotes, and put single quotes into double quotes + // the string $'b is then quoted as '$'"'"'b' + return "'" + StringTools.replace(argument, "'", "'\"'\"'") + "'"; + } + + /** + Returns a String that can be used as a single command line argument + on Windows. + The input will be quoted, or escaped if necessary, such that the output + will be parsed as a single argument using the rule specified in + http://msdn.microsoft.com/en-us/library/ms880421 + + Examples: + ```haxe + quoteWinArg("abc") == "abc"; + quoteWinArg("ab c") == '"ab c"'; + ``` + **/ + public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String { + // If there is no space, tab, back-slash, or double-quotes, and it is not an empty string. + if (!~/^[^ \t\\"]+$/.match(argument)) { + // Based on cpython's subprocess.list2cmdline(). + // https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620 + + var result = new StringBuf(); + var needquote = argument.indexOf(" ") != -1 || argument.indexOf("\t") != -1 || argument == ""; + + if (needquote) + result.add('"'); + + var bs_buf = new StringBuf(); + for (i in 0...argument.length) { + switch (argument.charCodeAt(i)) { + case "\\".code: + // Don't know if we need to double yet. + bs_buf.add("\\"); + case '"'.code: + // Double backslashes. + var bs = bs_buf.toString(); + result.add(bs); + result.add(bs); + bs_buf = new StringBuf(); + result.add('\\"'); + case var c: + // Normal char + if (bs_buf.length > 0) { + result.add(bs_buf.toString()); + bs_buf = new StringBuf(); + } + result.addChar(c); + } + } + + // Add remaining backslashes, if any. + result.add(bs_buf.toString()); + + if (needquote) { + result.add(bs_buf.toString()); + result.add('"'); + } + + argument = result.toString(); + } + + if (escapeMetaCharacters) { + var result = new StringBuf(); + for (i in 0...argument.length) { + var c = argument.charCodeAt(i); + if (winMetaCharacters.indexOf(c) >= 0) { + result.addChar("^".code); + } + result.addChar(c); + } + return result.toString(); + } else { + return argument; + } + } +} diff --git a/std/haxe/Template.hx b/std/haxe/Template.hx index 29868574980..f55c8c44d69 100644 --- a/std/haxe/Template.hx +++ b/std/haxe/Template.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,29 +19,32 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; import haxe.ds.List; +using StringTools; + private enum TemplateExpr { - OpVar( v : String ); - OpExpr( expr : Void -> Dynamic ); - OpIf( expr : Void -> Dynamic, eif : TemplateExpr, eelse : TemplateExpr ); - OpStr( str : String ); - OpBlock( l : List ); - OpForeach( expr : Void -> Dynamic, loop : TemplateExpr ); - OpMacro( name : String, params : List ); + OpVar(v:String); + OpExpr(expr:Void->Dynamic); + OpIf(expr:Void->Dynamic, eif:TemplateExpr, eelse:TemplateExpr); + OpStr(str:String); + OpBlock(l:List); + OpForeach(expr:Void->Dynamic, loop:TemplateExpr); + OpMacro(name:String, params:List); } private typedef Token = { - var s : Bool; - var p : String; - var l : Array; + var s:Bool; + var p:String; + var l:Array; } private typedef ExprToken = { - var s : Bool; - var p : String; + var s:Bool; + var p:String; } /** @@ -52,7 +55,6 @@ private typedef ExprToken = { **/ class Template { - static var splitter = ~/(::[A-Za-z0-9_ ()&|!+=\/><*."-]+::|\$\$([A-Za-z0-9_-]+)\()/; static var expr_splitter = ~/(\(|\)|[ \r\n\t]*"[^"]*"[ \r\n\t]*|[!+=\/><*.&|-]+)/; static var expr_trim = ~/^[ ]*([^ ]+)[ ]*$/; @@ -63,13 +65,16 @@ class Template { Global replacements which are used across all Template instances. This has lower priority than the context argument of execute(). **/ - public static var globals : Dynamic = {}; + public static var globals:Dynamic = {}; - var expr : TemplateExpr; - var context : Dynamic; - var macros : Dynamic; - var stack : List; - var buf : StringBuf; + // To avoid issues with DCE, keep the array iterator. + @:ifFeature("haxe.Template.run") static var hxKeepArrayIterator = [].iterator(); + + var expr:TemplateExpr; + var context:Dynamic; + var macros:Dynamic; + var stack:List; + var buf:StringBuf; /** Creates a new Template instance from `str`. @@ -81,11 +86,11 @@ class Template { If `str` is null, the result is unspecified. **/ - public function new( str : String ) { + public function new(str:String) { var tokens = parseTokens(str); expr = parseBlock(tokens); - if( !tokens.isEmpty() ) - throw "Unexpected '"+tokens.first().s+"'"; + if (!tokens.isEmpty()) + throw "Unexpected '" + tokens.first().s + "'"; } /** @@ -104,8 +109,8 @@ class Template { If `context` is null, the result is unspecified. If `macros` is null, no macros are used. **/ - public function execute( context : Dynamic, ?macros : Dynamic ):String { - this.macros = if( macros == null ) {} else macros; + public function execute(context:Dynamic, ?macros:Dynamic):String { + this.macros = if (macros == null) {} else macros; this.context = context; stack = new List(); buf = new StringBuf(); @@ -113,30 +118,30 @@ class Template { return buf.toString(); } - function resolve( v : String ) : Dynamic { - if( v == "__current__" ) + function resolve(v:String):Dynamic { + if (v == "__current__") return context; var value = Reflect.getProperty(context, v); - if( value != null || Reflect.hasField(context,v) ) + if (value != null || Reflect.hasField(context, v)) return value; - for( ctx in stack ) { - value = Reflect.getProperty(ctx,v); - if( value != null || Reflect.hasField(ctx,v) ) + for (ctx in stack) { + value = Reflect.getProperty(ctx, v); + if (value != null || Reflect.hasField(ctx, v)) return value; } - return Reflect.field(globals,v); + return Reflect.field(globals, v); } - function parseTokens( data : String ) { + function parseTokens(data:String) { var tokens = new List(); - while( splitter.match(data) ) { + while (splitter.match(data)) { var p = splitter.matchedPos(); - if( p.pos > 0 ) - tokens.add({ p : data.substr(0,p.pos), s : true, l : null }); + if (p.pos > 0) + tokens.add({p: data.substr(0, p.pos), s: true, l: null}); // : ? - if( data.charCodeAt(p.pos) == 58 ) { - tokens.add({ p : data.substr(p.pos + 2,p.len - 4), s : false, l : null }); + if (data.charCodeAt(p.pos) == 58) { + tokens.add({p: data.substr(p.pos + 2, p.len - 4), s: false, l: null}); data = splitter.matchedRight(); continue; } @@ -146,18 +151,19 @@ class Template { var npar = 1; var params = []; var part = ""; - while( true ) { + while (true) { var c = data.charCodeAt(parp); parp++; - if( c == 40 ) { + if (c == 40) { npar++; - } else if( c == 41 ) { + } else if (c == 41) { npar--; - if (npar <= 0) break; - } else if( c == null ){ + if (npar <= 0) + break; + } else if (c == null) { throw "Unclosed macro parenthesis"; } - if ( c == 44 && npar == 1) { + if (c == 44 && npar == 1) { params.push(part); part = ""; } else { @@ -165,255 +171,336 @@ class Template { } } params.push(part); - tokens.add({ p : splitter.matched(2), s : false, l : params }); - data = data.substr(parp,data.length - parp); + tokens.add({p: splitter.matched(2), s: false, l: params}); + data = data.substr(parp, data.length - parp); } - if( data.length > 0 ) - tokens.add({ p : data, s : true, l : null }); + if (data.length > 0) + tokens.add({p: data, s: true, l: null}); return tokens; } - function parseBlock( tokens : List ) { + function parseBlock(tokens:List) { var l = new List(); - while( true ) { + while (true) { var t = tokens.first(); - if( t == null ) + if (t == null) break; - if( !t.s && (t.p == "end" || t.p == "else" || t.p.substr(0,7) == "elseif ") ) + if (!t.s && (t.p == "end" || t.p == "else" || t.p.substr(0, 7) == "elseif ")) break; l.add(parse(tokens)); } - if( l.length == 1 ) + if (l.length == 1) return l.first(); return OpBlock(l); } - function parse( tokens : List ) { + function parse(tokens:List) { var t = tokens.pop(); var p = t.p; - if( t.s ) + if (t.s) return OpStr(p); // macro - if( t.l != null ) { + if (t.l != null) { var pe = new List(); - for( p in t.l ) + for (p in t.l) pe.add(parseBlock(parseTokens(p))); - return OpMacro(p,pe); + return OpMacro(p, pe); + } + function kwdEnd(kwd:String):Int { + var pos = -1; + var length = kwd.length; + if (p.substr(0, length) == kwd) { + pos = length; + for (c in p.substr(length)) { + switch c { + case ' '.code: pos++; + case _: break; + } + } + } + return pos; } // 'end' , 'else', 'elseif' can't be found here - if( p.substr(0,3) == "if " ) { - p = p.substr(3,p.length - 3); + var pos = kwdEnd("if"); + if (pos > 0) { + p = p.substr(pos, p.length - pos); var e = parseExpr(p); var eif = parseBlock(tokens); var t = tokens.first(); var eelse; - if( t == null ) + if (t == null) throw "Unclosed 'if'"; - if( t.p == "end" ) { + if (t.p == "end") { tokens.pop(); eelse = null; - } else if( t.p == "else" ) { + } else if (t.p == "else") { tokens.pop(); eelse = parseBlock(tokens); t = tokens.pop(); - if( t == null || t.p != "end" ) + if (t == null || t.p != "end") throw "Unclosed 'else'"; } else { // elseif - t.p = t.p.substr(4,t.p.length - 4); + t.p = t.p.substr(4, t.p.length - 4); eelse = parse(tokens); } - return OpIf(e,eif,eelse); + return OpIf(e, eif, eelse); } - if( p.substr(0,8) == "foreach " ) { - p = p.substr(8,p.length - 8); + var pos = kwdEnd("foreach"); + if (pos >= 0) { + p = p.substr(pos, p.length - pos); var e = parseExpr(p); var efor = parseBlock(tokens); var t = tokens.pop(); - if( t == null || t.p != "end" ) + if (t == null || t.p != "end") throw "Unclosed 'foreach'"; - return OpForeach(e,efor); + return OpForeach(e, efor); } - if( expr_splitter.match(p) ) + if (expr_splitter.match(p)) return OpExpr(parseExpr(p)); return OpVar(p); } - function parseExpr( data : String ) { + function parseExpr(data:String) { var l = new List(); var expr = data; - while( expr_splitter.match(data) ) { + while (expr_splitter.match(data)) { var p = expr_splitter.matchedPos(); var k = p.pos + p.len; - if( p.pos != 0 ) - l.add({ p : data.substr(0,p.pos), s : true }); + if (p.pos != 0) + l.add({p: data.substr(0, p.pos), s: true}); var p = expr_splitter.matched(0); - l.add({ p : p, s : p.indexOf('"') >= 0 }); + l.add({p: p, s: p.indexOf('"') >= 0}); data = expr_splitter.matchedRight(); } - if( data.length != 0 ) - l.add({ p : data, s : true }); + if (data.length != 0) { + for (i => c in data) { + switch c { + case ' '.code: + case _: + l.add({p: data.substr(i), s: true}); + break; + } + } + } var e:Void->Dynamic; try { e = makeExpr(l); - if( !l.isEmpty() ) + if (!l.isEmpty()) throw l.first().p; - } catch( s : String ) { - throw "Unexpected '"+s+"' in "+expr; + } catch (s:String) { + throw "Unexpected '" + s + "' in " + expr; } return function() { try { return e(); - } catch( exc : Dynamic ) { - throw "Error : "+Std.string(exc)+" in "+expr; + } catch (exc:Dynamic) { + throw "Error : " + Std.string(exc) + " in " + expr; } } } - function makeConst( v : String ) : Void -> Dynamic { + function makeConst(v:String):Void->Dynamic { expr_trim.match(v); v = expr_trim.matched(1); - if( v.charCodeAt(0) == 34 ) { - var str = v.substr(1,v.length-2); + if (v.charCodeAt(0) == 34) { + var str = v.substr(1, v.length - 2); return function() return str; } - if( expr_int.match(v) ) { + if (expr_int.match(v)) { var i = Std.parseInt(v); - return function() { return i; }; + return function() { + return i; + }; } - if( expr_float.match(v) ) { + if (expr_float.match(v)) { var f = Std.parseFloat(v); - return function() { return f; }; + return function() { + return f; + }; } var me = this; - return function() { return me.resolve(v); }; + return function() { + return me.resolve(v); + }; } - function makePath( e : Void -> Dynamic, l : List ) { + function makePath(e:Void->Dynamic, l:List) { var p = l.first(); - if( p == null || p.p != "." ) + if (p == null || p.p != ".") return e; l.pop(); var field = l.pop(); - if( field == null || !field.s ) + if (field == null || !field.s) throw field.p; var f = field.p; expr_trim.match(f); f = expr_trim.matched(1); - return makePath(function() { return Reflect.field(e(),f); },l); + return makePath(function() { + return Reflect.field(e(), f); + }, l); + } + + function makeExpr(l) { + return makePath(makeExpr2(l), l); } - function makeExpr( l ) { - return makePath(makeExpr2(l),l); + function skipSpaces(l:List) { + var p = l.first(); + while (p != null) { + for (c in p.p) { + if (c != " ".code) { + return; + } + } + l.pop(); + p = l.first(); + } } - function makeExpr2( l : List ) : Void -> Dynamic { + function makeExpr2(l:List):Void->Dynamic { + skipSpaces(l); var p = l.pop(); - if( p == null ) + skipSpaces(l); + if (p == null) throw ""; - if( p.s ) + if (p.s) return makeConst(p.p); - switch( p.p ) { - case "(": - var e1:Dynamic = makeExpr(l); - var p = l.pop(); - if( p == null || p.s ) - throw p; - if( p.p == ")" ) - return e1; - var e2:Dynamic = makeExpr(l); - var p2 = l.pop(); - if( p2 == null || p2.p != ")" ) - throw p2; - return switch( p.p ) { - case "+": function() { return cast e1() + e2(); }; - case "-": function() { return cast e1() - e2(); }; - case "*": function() { return cast e1() * e2(); }; - case "/": function() { return cast e1() / e2(); }; - case ">": function() { return cast e1() > e2(); }; - case "<": function() { return cast e1() < e2(); }; - case ">=": function() { return cast e1() >= e2(); }; - case "<=": function() { return cast e1() <= e2(); }; - case "==": function() { return cast e1() == e2(); }; - case "!=": function() { return cast e1() != e2(); }; - case "&&": function() { return cast e1() && e2(); }; - case "||": function() { return cast e1() || e2(); }; - default: throw "Unknown operation "+p.p; - } - case "!": - var e : Void->Dynamic = makeExpr(l); - return function() { - var v : Dynamic = e(); - return (v == null || v == false); - }; - case "-": - var e = makeExpr(l); - return function() { return -e(); }; + switch (p.p) { + case "(": + skipSpaces(l); + var e1:Dynamic = makeExpr(l); + skipSpaces(l); + var p = l.pop(); + if (p == null || p.s) + throw p; + if (p.p == ")") + return e1; + skipSpaces(l); + var e2:Dynamic = makeExpr(l); + skipSpaces(l); + var p2 = l.pop(); + skipSpaces(l); + if (p2 == null || p2.p != ")") + throw p2; + return switch (p.p) { + case "+": function() { + return cast e1() + e2(); + }; + case "-": function() { + return cast e1() - e2(); + }; + case "*": function() { + return cast e1() * e2(); + }; + case "/": function() { + return cast e1() / e2(); + }; + case ">": function() { + return cast e1() > e2(); + }; + case "<": function() { + return cast e1() < e2(); + }; + case ">=": function() { + return cast e1() >= e2(); + }; + case "<=": function() { + return cast e1() <= e2(); + }; + case "==": function() { + return cast e1() == e2(); + }; + case "!=": function() { + return cast e1() != e2(); + }; + case "&&": function() { + return cast e1() && e2(); + }; + case "||": function() { + return cast e1() || e2(); + }; + default: throw "Unknown operation " + p.p; + } + case "!": + var e:Void->Dynamic = makeExpr(l); + return function() { + var v:Dynamic = e(); + return (v == null || v == false); + }; + case "-": + var e = makeExpr(l); + return function() { + return -e(); + }; } throw p.p; } - function run( e : TemplateExpr ) { - switch( e ) { - case OpVar(v): - buf.add(Std.string(resolve(v))); - case OpExpr(e): - buf.add(Std.string(e())); - case OpIf(e,eif,eelse): - var v : Dynamic = e(); - if( v == null || v == false ) { - if( eelse != null ) run(eelse); - } else - run(eif); - case OpStr(str): - buf.add(str); - case OpBlock(l): - for( e in l ) - run(e); - case OpForeach(e,loop): - var v : Dynamic = e(); - try { - var x : Dynamic = v.iterator(); - if( x.hasNext == null ) throw null; - v = x; - } catch( e : Dynamic ) try { - if( v.hasNext == null ) throw null; - } catch( e : Dynamic ) { - throw "Cannot iter on " + v; - } - stack.push(context); - var v : Iterator = v; - for( ctx in v ) { - context = ctx; - run(loop); - } - context = stack.pop(); - case OpMacro(m,params): - var v : Dynamic = Reflect.field(macros,m); - var pl = new Array(); - var old = buf; - pl.push(resolve); - for( p in params ) { - switch( p ) { - case OpVar(v): pl.push(resolve(v)); - default: - buf = new StringBuf(); - run(p); - pl.push(buf.toString()); + function run(e:TemplateExpr) { + switch (e) { + case OpVar(v): + buf.add(Std.string(resolve(v))); + case OpExpr(e): + buf.add(Std.string(e())); + case OpIf(e, eif, eelse): + var v:Dynamic = e(); + if (v == null || v == false) { + if (eelse != null) + run(eelse); + } else + run(eif); + case OpStr(str): + buf.add(str); + case OpBlock(l): + for (e in l) + run(e); + case OpForeach(e, loop): + var v:Dynamic = e(); + try { + var x:Dynamic = v.iterator(); + if (x.hasNext == null) + throw null; + v = x; + } catch (e:Dynamic) + try { + if (v.hasNext == null) + throw null; + } catch (e:Dynamic) { + throw "Cannot iter on " + v; + } + stack.push(context); + var v:Iterator = v; + for (ctx in v) { + context = ctx; + run(loop); + } + context = stack.pop(); + case OpMacro(m, params): + var v:Dynamic = Reflect.field(macros, m); + var pl = new Array(); + var old = buf; + pl.push(resolve); + for (p in params) { + switch (p) { + case OpVar(v): pl.push(resolve(v)); + default: + buf = new StringBuf(); + run(p); + pl.push(buf.toString()); + } + } + buf = old; + try { + buf.add(Std.string(Reflect.callMethod(macros, v, pl))); + } catch (e:Dynamic) { + var plstr = try pl.join(",") catch (e:Dynamic) "???"; + var msg = "Macro call " + m + "(" + plstr + ") failed (" + Std.string(e) + ")"; + #if neko + neko.Lib.rethrow(msg); + #else + throw msg; + #end } - } - buf = old; - try { - buf.add(Std.string(Reflect.callMethod(macros,v,pl))); - } catch( e : Dynamic ) { - var plstr = try pl.join(",") catch( e : Dynamic ) "???"; - var msg = "Macro call "+m+"("+plstr+") failed ("+Std.string(e)+")"; - #if neko - neko.Lib.rethrow(msg); - #else - throw msg; - #end - } } } - } diff --git a/std/haxe/Timer.hx b/std/haxe/Timer.hx index ecbca0cc14c..fcb13f47b46 100644 --- a/std/haxe/Timer.hx +++ b/std/haxe/Timer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; /** @@ -36,14 +37,13 @@ package haxe; the child class. **/ class Timer { - #if (flash || js) - private var id : Null; + private var id:Null; #elseif java - private var timer : java.util.Timer; - private var task : java.util.TimerTask; + private var timer:java.util.Timer; + private var task:java.util.TimerTask; #else - private var event : MainLoop.MainEvent; + private var event:MainLoop.MainEvent; #end /** @@ -57,23 +57,25 @@ class Timer { The accuracy of this may be platform-dependent. **/ - public function new( time_ms : Int ){ + public function new(time_ms:Int) { #if flash - var me = this; - id = untyped __global__["flash.utils.setInterval"](function() { me.run(); },time_ms); + var me = this; + id = untyped __global__["flash.utils.setInterval"](function() { + me.run(); + }, time_ms); #elseif js - var me = this; - id = untyped setInterval(function() me.run(),time_ms); + var me = this; + id = untyped setInterval(function() me.run(), time_ms); #elseif java - timer = new java.util.Timer(); - timer.scheduleAtFixedRate(task = new TimerTask(this), haxe.Int64.ofInt(time_ms), haxe.Int64.ofInt(time_ms)); + timer = new java.util.Timer(); + timer.scheduleAtFixedRate(task = new TimerTask(this), haxe.Int64.ofInt(time_ms), haxe.Int64.ofInt(time_ms)); #else - var dt = time_ms / 1000; - event = MainLoop.add(function() { - @:privateAccess event.nextRun += dt; - run(); - }); - event.delay(dt); + var dt = time_ms / 1000; + event = MainLoop.add(function() { + @:privateAccess event.nextRun += dt; + run(); + }); + event.delay(dt); #end } @@ -87,25 +89,25 @@ class Timer { **/ public function stop() { #if (flash || js) - if( id == null ) - return; - #if flash - untyped __global__["flash.utils.clearInterval"](id); - #elseif js - untyped clearInterval(id); - #end - id = null; + if (id == null) + return; + #if flash + untyped __global__["flash.utils.clearInterval"](id); + #elseif js + untyped clearInterval(id); + #end + id = null; #elseif java - if(timer != null) { - timer.cancel(); - timer = null; - } - task = null; + if (timer != null) { + timer.cancel(); + timer = null; + } + task = null; #else - if( event != null ) { - event.stop(); - event = null; - } + if (event != null) { + event.stop(); + event = null; + } #end } @@ -120,9 +122,7 @@ class Timer { Once bound, it can still be rebound to different functions until `this` Timer is stopped through a call to `this.stop`. **/ - public dynamic function run() { - - } + public dynamic function run() {} /** Invokes `f` after `time_ms` milliseconds. @@ -133,7 +133,7 @@ class Timer { If `f` is null, the result is unspecified. **/ - public static function delay( f : Void -> Void, time_ms : Int ) { + public static function delay(f:Void->Void, time_ms:Int) { var t = new haxe.Timer(time_ms); t.run = function() { t.stop(); @@ -153,7 +153,7 @@ class Timer { If `f` is null, the result is unspecified. **/ - public static function measure( f : Void -> T, ?pos : PosInfos ) : T { + public static function measure(f:Void->T, ?pos:PosInfos):T { var t0 = stamp(); var r = f(); Log.trace((stamp() - t0) + "s", pos); @@ -166,31 +166,30 @@ class Timer { The value itself might differ depending on platforms, only differences between two values make sense. **/ - public static inline function stamp() : Float { + public static inline function stamp():Float { #if flash - return flash.Lib.getTimer() / 1000; + return flash.Lib.getTimer() / 1000; #elseif (neko || php) - return Sys.time(); + return Sys.time(); #elseif js - return Date.now().getTime() / 1000; + return js.lib.Date.now() / 1000; #elseif cpp - return untyped __global__.__time_stamp(); + return untyped __global__.__time_stamp(); #elseif python - return Sys.cpuTime(); + return Sys.cpuTime(); #elseif sys - return Sys.time(); - + return Sys.time(); #else - return 0; + return 0; #end } - } #if java @:nativeGen private class TimerTask extends java.util.TimerTask { var timer:Timer; + public function new(timer:Timer):Void { super(); this.timer = timer; diff --git a/std/haxe/Ucs2.hx b/std/haxe/Ucs2.hx index 0c9a7d62313..9576c26463a 100644 --- a/std/haxe/Ucs2.hx +++ b/std/haxe/Ucs2.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,16 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; /** Cross platform UCS2 string API. **/ abstract Ucs2(String) { + extern public var length(get, never):Int; - @:extern public var length(get,never) : Int; - - @:extern inline function new(str:String) : Void { + extern inline function new(str:String):Void { // this implementation only allows platforms which have native UCS2 String. // other platforms should create a shadow class in their _std directory #if !(flash || js) @@ -37,7 +37,7 @@ abstract Ucs2(String) { this = str; } - @:extern inline function get_length() { + extern inline function get_length() { return this.length; } @@ -46,7 +46,7 @@ abstract Ucs2(String) { Affects the characters `a-z`. Other characters remain unchanged. **/ - @:extern public inline function toUpperCase() : Ucs2 { + extern public inline function toUpperCase():Ucs2 { return new Ucs2(this.toUpperCase()); } @@ -55,7 +55,7 @@ abstract Ucs2(String) { Affects the characters `A-Z`. Other characters remain unchanged. **/ - @:extern public inline function toLowerCase() : Ucs2 { + extern public inline function toLowerCase():Ucs2 { return new Ucs2(this.toLowerCase()); } @@ -65,7 +65,7 @@ abstract Ucs2(String) { If `index` is negative or exceeds `this.length`, the empty Ucs2 "" is returned. **/ - @:extern public inline function charAt(index : Int) : Ucs2 { + extern public inline function charAt(index:Int):Ucs2 { return new Ucs2(this.charAt(index)); } @@ -75,10 +75,10 @@ abstract Ucs2(String) { If `index` is negative or exceeds `this.length`, null is returned. To obtain the character code of a single character, "x".code can be used - instead to @:extern public inline the character code at compile time. Note that this + instead to extern public inline the character code at compile time. Note that this only works on Ucs2 literals of length 1. **/ - @:extern public inline function charCodeAt( index : Int) : Null { + extern public inline function charCodeAt(index:Int):Null { return this.charCodeAt(index); } @@ -93,8 +93,8 @@ abstract Ucs2(String) { If `str` cannot be found, -1 is returned. **/ - @:extern public inline function indexOf( str : Ucs2, ?startIndex : Int ) : Int { - return this.indexOf(str.toNativeString(),startIndex); + extern public inline function indexOf(str:Ucs2, ?startIndex:Int):Int { + return this.indexOf(str.toNativeString(), startIndex); } /** @@ -108,8 +108,8 @@ abstract Ucs2(String) { If `str` cannot be found, -1 is returned. **/ - @:extern public inline function lastIndexOf( str : Ucs2, ?startIndex : Int ) : Int { - return this.lastIndexOf(str.toNativeString(),startIndex); + extern public inline function lastIndexOf(str:Ucs2, ?startIndex:Int):Int { + return this.lastIndexOf(str.toNativeString(), startIndex); } /** @@ -132,7 +132,7 @@ abstract Ucs2(String) { result Array contains a leading (or trailing) empty Ucs2 "" element. Two subsequent delimiters also result in an empty Ucs2 "" element. **/ - @:extern public inline function split( delimiter : Ucs2 ) : Array { + extern public inline function split(delimiter:Ucs2):Array { return cast this.split(delimiter.toNativeString()); } @@ -151,8 +151,8 @@ abstract Ucs2(String) { If `len` is negative, the result is unspecified. **/ - @:extern public inline function substr( pos : Int, ?len : Int ) : Ucs2 { - return new Ucs2(this.substr(pos,len)); + extern public inline function substr(pos:Int, ?len:Int):Ucs2 { + return new Ucs2(this.substr(pos, len)); } /** @@ -168,14 +168,14 @@ abstract Ucs2(String) { If the (possibly swapped) `startIndex` exceeds `this.length`, the empty Ucs2 "" is returned. **/ - @:extern public inline function substring( startIndex : Int, ?endIndex : Int ) : Ucs2 { - return new Ucs2(this.substring(startIndex,endIndex)); + extern public inline function substring(startIndex:Int, ?endIndex:Int):Ucs2 { + return new Ucs2(this.substring(startIndex, endIndex)); } /** Returns the native underlying String. **/ - @:extern public inline function toNativeString() : String { + extern public inline function toNativeString():String { return this; } @@ -185,8 +185,7 @@ abstract Ucs2(String) { If `code` is negative or has another invalid value, the result is unspecified. **/ - @:extern public static inline function fromCharCode( code : Int ) : Ucs2 { + extern public static inline function fromCharCode(code:Int):Ucs2 { return new Ucs2(String.fromCharCode(code)); } - -} \ No newline at end of file +} diff --git a/std/haxe/Unserializer.hx b/std/haxe/Unserializer.hx index de387fdb597..4353d10f8f6 100644 --- a/std/haxe/Unserializer.hx +++ b/std/haxe/Unserializer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; import haxe.ds.List; @:noDoc typedef TypeResolver = { - function resolveClass( name : String ) : Class; - function resolveEnum( name : String ) : Enum; + function resolveClass(name:String):Class; + function resolveEnum(name:String):Enum; } /** @@ -45,7 +46,6 @@ typedef TypeResolver = { **/ class Unserializer { - /** This value can be set to use custom type resolvers. @@ -62,7 +62,7 @@ class Unserializer { This value is applied when a new `Unserializer` instance is created. Changing it afterwards has no effect on previously created instances. **/ - public static var DEFAULT_RESOLVER : TypeResolver = new DefaultResolver(); + public static var DEFAULT_RESOLVER:TypeResolver = new DefaultResolver(); static var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%:"; @@ -70,27 +70,22 @@ class Unserializer { static var CODES = null; static function initCodes() { - var codes = - #if flash - new flash.utils.ByteArray(); - #else - new Array(); - #end - for( i in 0...BASE64.length ) - codes[StringTools.fastCodeAt(BASE64,i)] = i; + var codes = #if flash new flash.utils.ByteArray(); #else new Array(); #end + for (i in 0...BASE64.length) + codes[StringTools.fastCodeAt(BASE64, i)] = i; return codes; } #end - var buf : String; - var pos : Int; - var length : Int; - var cache : Array; - var scache : Array; - var resolver : TypeResolver; - #if neko - var upos : Int; - #end + var buf:String; + var pos:Int; + var length:Int; + var cache:Array; + var scache:Array; + var resolver:TypeResolver; + #if neko + var upos:Int; + #end /** Creates a new Unserializer instance, with its internal buffer @@ -101,22 +96,22 @@ class Unserializer { Each Unserializer instance maintains its own cache. **/ - public function new( buf : String ) { - this.buf = buf; - length = buf.length; - pos = 0; - #if neko - upos = 0; - #end - scache = new Array(); - cache = new Array(); + public function new(buf:String) { + this.buf = buf; + length = buf.length; + pos = 0; + #if neko + upos = 0; + #end + scache = new Array(); + cache = new Array(); var r = DEFAULT_RESOLVER; - if( r == null ) { + if (r == null) { r = new DefaultResolver(); DEFAULT_RESOLVER = r; } resolver = r; - } + } /** Sets the type resolver of `this` Unserializer instance to `r`. @@ -126,8 +121,8 @@ class Unserializer { See `DEFAULT_RESOLVER` for more information on type resolvers. **/ - public function setResolver( r ) { - if( r == null ) + public function setResolver(r) { + if (r == null) resolver = NullResolver.instance; else resolver = r; @@ -138,78 +133,79 @@ class Unserializer { See `DEFAULT_RESOLVER` for more information on type resolvers. **/ - public function getResolver() { + public function getResolver() { return resolver; } - inline function get(p) : Int { + inline function get(p):Int { return StringTools.fastCodeAt(buf, p); } - function readDigits() { - var k = 0; - var s = false; - var fpos = pos; - while( true ) { - var c = get(pos); - if( StringTools.isEof(c) ) + function readDigits() { + var k = 0; + var s = false; + var fpos = pos; + while (true) { + var c = get(pos); + if (StringTools.isEof(c)) break; - if( c == "-".code ) { - if( pos != fpos ) - break; - s = true; - pos++; - continue; - } - if( c < "0".code || c > "9".code ) - break; - k = k * 10 + (c - "0".code); - pos++; - } - if( s ) - k *= -1; - return k; - } + if (c == "-".code) { + if (pos != fpos) + break; + s = true; + pos++; + continue; + } + if (c < "0".code || c > "9".code) + break; + k = k * 10 + (c - "0".code); + pos++; + } + if (s) + k *= -1; + return k; + } function readFloat() { var p1 = pos; - while( true ) { - var c = get(pos); - if( StringTools.isEof(c)) break; - // + - . , 0-9 - if( (c >= 43 && c < 58) || c == "e".code || c == "E".code ) - pos++; - else - break; - } - return Std.parseFloat(buf.substr(p1,pos-p1)); + while (true) { + var c = get(pos); + if (StringTools.isEof(c)) + break; + // + - . , 0-9 + if ((c >= 43 && c < 58) || c == "e".code || c == "E".code) + pos++; + else + break; + } + return Std.parseFloat(buf.substr(p1, pos - p1)); } function unserializeObject(o:{}) { - while( true ) { - if( pos >= length ) - throw "Invalid object"; - if( get(pos) == "g".code ) - break; - var k : Dynamic = unserialize(); - if( !Std.is(k,String) ) - throw "Invalid object key"; - var v = unserialize(); - Reflect.setField(o,k,v); - } - pos++; + while (true) { + if (pos >= length) + throw "Invalid object"; + if (get(pos) == "g".code) + break; + var k:Dynamic = unserialize(); + if (!Std.is(k, String)) + throw "Invalid object key"; + var v = unserialize(); + Reflect.setField(o, k, v); + } + pos++; } - function unserializeEnum( edecl:Enum, tag:String ) { - if( get(pos++) != ":".code ) + function unserializeEnum(edecl:Enum, tag:String) { + if (get(pos++) != ":".code) throw "Invalid enum format"; var nargs = readDigits(); - if( nargs == 0 ) - return Type.createEnum(edecl,tag); + if (nargs == 0) + return Type.createEnum(edecl, tag); var args = new Array(); - while( nargs-- > 0 ) + while (nargs-- > 0) args.push(unserialize()); - return Type.createEnum(edecl,tag,args); + return Type.createEnum(edecl, tag, args); } /** @@ -232,230 +228,228 @@ class Unserializer { Classes are created from `Type.createEmptyInstance`, which means their constructors are not called. **/ - public function unserialize() : Dynamic { - switch( get(pos++) ) { - case "n".code: - return null; - case "t".code: - return true; - case "f".code: - return false; - case "z".code: - return 0; - case "i".code: - return readDigits(); - case "d".code: - return readFloat(); - case "y".code: - var len = readDigits(); - if( get(pos++) != ":".code || length - pos < len ) - throw "Invalid string length"; - var s = buf.substr(pos,len); - pos += len; - s = StringTools.urlDecode(s); - scache.push(s); - return s; - case "k".code: - return Math.NaN; - case "m".code: - return Math.NEGATIVE_INFINITY; - case "p".code: - return Math.POSITIVE_INFINITY; - case "a".code: - var buf = buf; - var a = new Array(); - #if cpp var cachePos = cache.length; #end - cache.push(a); - while( true ) { - var c = get(pos); - if( c == "h".code ) { - pos++; - break; + public function unserialize():Dynamic { + switch (get(pos++)) { + case "n".code: + return null; + case "t".code: + return true; + case "f".code: + return false; + case "z".code: + return 0; + case "i".code: + return readDigits(); + case "d".code: + return readFloat(); + case "y".code: + var len = readDigits(); + if (get(pos++) != ":".code || length - pos < len) + throw "Invalid string length"; + var s = buf.substr(pos, len); + pos += len; + s = StringTools.urlDecode(s); + scache.push(s); + return s; + case "k".code: + return Math.NaN; + case "m".code: + return Math.NEGATIVE_INFINITY; + case "p".code: + return Math.POSITIVE_INFINITY; + case "a".code: + var buf = buf; + var a = new Array(); + #if cpp + var cachePos = cache.length; + #end + cache.push(a); + while (true) { + var c = get(pos); + if (c == "h".code) { + pos++; + break; + } + if (c == "u".code) { + pos++; + var n = readDigits(); + a[a.length + n - 1] = null; + } else + a.push(unserialize()); } - if( c == "u".code ) { - pos++; - var n = readDigits(); - a[a.length+n-1] = null; - } else - a.push(unserialize()); - } - #if cpp - return cache[cachePos] = cpp.NativeArray.resolveVirtualArray(a); - #else - return a; - #end - case "o".code: - var o = {}; - cache.push(o); - unserializeObject(o); - return o; - case "r".code: - var n = readDigits(); - if( n < 0 || n >= cache.length ) - throw "Invalid reference"; - return cache[n]; - case "R".code: - var n = readDigits(); - if( n < 0 || n >= scache.length ) - throw "Invalid string reference"; - return scache[n]; - case "x".code: - throw unserialize(); - case "c".code: - var name = unserialize(); - var cl = resolver.resolveClass(name); - if( cl == null ) - throw "Class not found " + name; - var o = Type.createEmptyInstance(cl); - cache.push(o); - unserializeObject(o); - return o; - case "w".code: - var name = unserialize(); - var edecl = resolver.resolveEnum(name); - if( edecl == null ) - throw "Enum not found " + name; - var e = unserializeEnum(edecl, unserialize()); - cache.push(e); - return e; - case "j".code: - var name = unserialize(); - var edecl = resolver.resolveEnum(name); - if( edecl == null ) - throw "Enum not found " + name; - pos++; /* skip ':' */ - var index = readDigits(); - var tag = Type.getEnumConstructs(edecl)[index]; - if( tag == null ) - throw "Unknown enum index "+name+"@"+index; - var e = unserializeEnum(edecl, tag); - cache.push(e); - return e; - case "l".code: - var l = new List(); - cache.push(l); - var buf = buf; - while( get(pos) != "h".code ) - l.add(unserialize()); - pos++; - return l; - case "b".code: - var h = new haxe.ds.StringMap(); - cache.push(h); - var buf = buf; - while( get(pos) != "h".code ) { - var s = unserialize(); - h.set(s,unserialize()); - } - pos++; - return h; - case "q".code: - var h = new haxe.ds.IntMap(); - cache.push(h); - var buf = buf; - var c = get(pos++); - while( c == ":".code ) { - var i = readDigits(); - h.set(i,unserialize()); - c = get(pos++); - } - if( c != "h".code ) - throw "Invalid IntMap format"; - return h; - case "M".code: - var h = new haxe.ds.ObjectMap(); - cache.push(h); - var buf = buf; - while( get(pos) != "h".code ) { - var s = unserialize(); - h.set(s,unserialize()); - } - pos++; - return h; - case "v".code: - var d; - if( get(pos) >= '0'.code && get(pos) <= '9'.code && - get(pos + 1) >= '0'.code && get(pos + 1) <= '9'.code && - get(pos + 2) >= '0'.code && get(pos + 2) <= '9'.code && - get(pos + 3) >= '0'.code && get(pos + 3) <= '9'.code && - get(pos + 4) == '-'.code - ) { - // Included for backwards compatibility - d = Date.fromString(buf.substr(pos,19)); - pos += 19; - } else - d = Date.fromTime(readFloat()); - cache.push(d); - return d; - case "s".code: - var len = readDigits(); - var buf = buf; - if( get(pos++) != ":".code || length - pos < len ) - throw "Invalid bytes length"; - #if neko - var bytes = haxe.io.Bytes.ofData( base_decode(untyped buf.substr(pos,len).__s,untyped BASE64.__s) ); - #else - var codes = CODES; - if( codes == null ) { - codes = initCodes(); - CODES = codes; - } - var i = pos; - var rest = len & 3; - var size = (len >> 2) * 3 + ((rest >= 2) ? rest - 1 : 0); - var max = i + (len - rest); - var bytes = haxe.io.Bytes.alloc(size); - var bpos = 0; - while( i < max ) { - var c1 = codes[StringTools.fastCodeAt(buf,i++)]; - var c2 = codes[StringTools.fastCodeAt(buf,i++)]; - bytes.set(bpos++,(c1 << 2) | (c2 >> 4)); - var c3 = codes[StringTools.fastCodeAt(buf,i++)]; - bytes.set(bpos++,(c2 << 4) | (c3 >> 2)); - var c4 = codes[StringTools.fastCodeAt(buf,i++)]; - bytes.set(bpos++,(c3 << 6) | c4); - } - if( rest >= 2 ) { - var c1 = codes[StringTools.fastCodeAt(buf,i++)]; - var c2 = codes[StringTools.fastCodeAt(buf,i++)]; - bytes.set(bpos++,(c1 << 2) | (c2 >> 4)); - if( rest == 3 ) { - var c3 = codes[StringTools.fastCodeAt(buf,i++)]; - bytes.set(bpos++,(c2 << 4) | (c3 >> 2)); + #if cpp + return cache[cachePos] = cpp.NativeArray.resolveVirtualArray(a); + #else + return a; + #end + case "o".code: + var o = {}; + cache.push(o); + unserializeObject(o); + return o; + case "r".code: + var n = readDigits(); + if (n < 0 || n >= cache.length) + throw "Invalid reference"; + return cache[n]; + case "R".code: + var n = readDigits(); + if (n < 0 || n >= scache.length) + throw "Invalid string reference"; + return scache[n]; + case "x".code: + throw unserialize(); + case "c".code: + var name = unserialize(); + var cl = resolver.resolveClass(name); + if (cl == null) + throw "Class not found " + name; + var o = Type.createEmptyInstance(cl); + cache.push(o); + unserializeObject(o); + return o; + case "w".code: + var name = unserialize(); + var edecl = resolver.resolveEnum(name); + if (edecl == null) + throw "Enum not found " + name; + var e = unserializeEnum(edecl, unserialize()); + cache.push(e); + return e; + case "j".code: + var name = unserialize(); + var edecl = resolver.resolveEnum(name); + if (edecl == null) + throw "Enum not found " + name; + pos++; /* skip ':' */ + var index = readDigits(); + var tag = Type.getEnumConstructs(edecl)[index]; + if (tag == null) + throw "Unknown enum index " + name + "@" + index; + var e = unserializeEnum(edecl, tag); + cache.push(e); + return e; + case "l".code: + var l = new List(); + cache.push(l); + var buf = buf; + while (get(pos) != "h".code) + l.add(unserialize()); + pos++; + return l; + case "b".code: + var h = new haxe.ds.StringMap(); + cache.push(h); + var buf = buf; + while (get(pos) != "h".code) { + var s = unserialize(); + h.set(s, unserialize()); } - } - #end - pos += len; - cache.push(bytes); - return bytes; - case "C".code: - var name = unserialize(); - var cl = resolver.resolveClass(name); - if( cl == null ) - throw "Class not found " + name; - var o : Dynamic = Type.createEmptyInstance(cl); - cache.push(o); - o.hxUnserialize(this); - if( get(pos++) != "g".code ) - throw "Invalid custom data"; - return o; - case "A".code: - var name = unserialize(); - var cl = resolver.resolveClass(name); - if( cl == null ) - throw "Class not found " + name; - return cl; - case "B".code: - var name = unserialize(); - var e = resolver.resolveEnum(name); - if( e == null ) - throw "Enum not found " + name; - return e; - default: - } - pos--; - throw ("Invalid char "+buf.charAt(pos)+" at position "+pos); - } + pos++; + return h; + case "q".code: + var h = new haxe.ds.IntMap(); + cache.push(h); + var buf = buf; + var c = get(pos++); + while (c == ":".code) { + var i = readDigits(); + h.set(i, unserialize()); + c = get(pos++); + } + if (c != "h".code) + throw "Invalid IntMap format"; + return h; + case "M".code: + var h = new haxe.ds.ObjectMap(); + cache.push(h); + var buf = buf; + while (get(pos) != "h".code) { + var s = unserialize(); + h.set(s, unserialize()); + } + pos++; + return h; + case "v".code: + var d; + if (get(pos) >= '0'.code && get(pos) <= '9'.code && get(pos + 1) >= '0'.code && get(pos + 1) <= '9'.code && get(pos + 2) >= '0'.code + && get(pos + 2) <= '9'.code && get(pos + 3) >= '0'.code && get(pos + 3) <= '9'.code && get(pos + 4) == '-'.code) { + // Included for backwards compatibility + d = Date.fromString(buf.substr(pos, 19)); + pos += 19; + } else + d = Date.fromTime(readFloat()); + cache.push(d); + return d; + case "s".code: + var len = readDigits(); + var buf = buf; + if (get(pos++) != ":".code || length - pos < len) + throw "Invalid bytes length"; + #if neko + var bytes = haxe.io.Bytes.ofData(base_decode(untyped buf.substr(pos, len).__s, untyped BASE64.__s)); + #else + var codes = CODES; + if (codes == null) { + codes = initCodes(); + CODES = codes; + } + var i = pos; + var rest = len & 3; + var size = (len >> 2) * 3 + ((rest >= 2) ? rest - 1 : 0); + var max = i + (len - rest); + var bytes = haxe.io.Bytes.alloc(size); + var bpos = 0; + while (i < max) { + var c1 = codes[StringTools.fastCodeAt(buf, i++)]; + var c2 = codes[StringTools.fastCodeAt(buf, i++)]; + bytes.set(bpos++, (c1 << 2) | (c2 >> 4)); + var c3 = codes[StringTools.fastCodeAt(buf, i++)]; + bytes.set(bpos++, (c2 << 4) | (c3 >> 2)); + var c4 = codes[StringTools.fastCodeAt(buf, i++)]; + bytes.set(bpos++, (c3 << 6) | c4); + } + if (rest >= 2) { + var c1 = codes[StringTools.fastCodeAt(buf, i++)]; + var c2 = codes[StringTools.fastCodeAt(buf, i++)]; + bytes.set(bpos++, (c1 << 2) | (c2 >> 4)); + if (rest == 3) { + var c3 = codes[StringTools.fastCodeAt(buf, i++)]; + bytes.set(bpos++, (c2 << 4) | (c3 >> 2)); + } + } + #end + pos += len; + cache.push(bytes); + return bytes; + case "C".code: + var name = unserialize(); + var cl = resolver.resolveClass(name); + if (cl == null) + throw "Class not found " + name; + var o:Dynamic = Type.createEmptyInstance(cl); + cache.push(o); + o.hxUnserialize(this); + if (get(pos++) != "g".code) + throw "Invalid custom data"; + return o; + case "A".code: + var name = unserialize(); + var cl = resolver.resolveClass(name); + if (cl == null) + throw "Class not found " + name; + return cl; + case "B".code: + var name = unserialize(); + var e = resolver.resolveEnum(name); + if (e == null) + throw "Enum not found " + name; + return e; + default: + } + pos--; + throw("Invalid char " + buf.charAt(pos) + " at position " + pos); + } /** Unserializes `v` and returns the according value. @@ -464,29 +458,39 @@ class Unserializer { Unserializer with `v` as buffer and calling its unserialize() method once. **/ - public static function run( v : String ) : Dynamic { + public static function run(v:String):Dynamic { return new Unserializer(v).unserialize(); } #if neko - static var base_decode = neko.Lib.load("std","base_decode",2); + static var base_decode = neko.Lib.load("std", "base_decode", 2); #end - } private class DefaultResolver { public function new() {} - @:final public inline function resolveClass(name:String):Class return Type.resolveClass(name); - @:final public inline function resolveEnum(name:String):Enum return Type.resolveEnum(name); + + public inline function resolveClass(name:String):Class + return Type.resolveClass(name); + + public inline function resolveEnum(name:String):Enum + return Type.resolveEnum(name); } private class NullResolver { function new() {} - @:final public inline function resolveClass(name:String):Class return null; - @:final public inline function resolveEnum(name:String):Enum return null; - public static var instance(get,null):NullResolver; + + public inline function resolveClass(name:String):Class + return null; + + public inline function resolveEnum(name:String):Enum + return null; + + public static var instance(get, null):NullResolver; + inline static function get_instance():NullResolver { - if (instance == null) instance = new NullResolver(); + if (instance == null) + instance = new NullResolver(); return instance; } } diff --git a/std/haxe/Utf8.hx b/std/haxe/Utf8.hx index 09b2cad2d42..9ceee126c12 100644 --- a/std/haxe/Utf8.hx +++ b/std/haxe/Utf8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,49 +19,50 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; /** Since not all platforms guarantee that `String` always uses UTF-8 encoding, you can use this cross-platform API to perform operations on such strings. **/ +@:deprecated('haxe.Utf8 is deprecated. Use UnicodeString instead.') class Utf8 { - - var __b : String; + var __b:String; /** Allocate a new Utf8 buffer using an optional bytes size. **/ - public function new( ?size : Int ) { + public function new(?size:Int) { __b = ""; } /** Add the given UTF8 character code to the buffer. **/ - public inline function addChar( c : Int ) : Void { + public inline function addChar(c:Int):Void { __b += String.fromCharCode(c); } /** Returns the buffer converted to a String. **/ - public inline function toString() : String { + public inline function toString():String { return __b; } /** Call the `chars` function for each UTF8 char of the string. **/ - public static function iter( s : String, chars : Int -> Void ) { - for( i in 0...s.length ) + public static function iter(s:String, chars:Int->Void) { + for (i in 0...s.length) chars(s.charCodeAt(i)); } /** Encode the input ISO string into the corresponding UTF8 one. **/ - public static function encode( s : String ) : String { + public static function encode(s:String):String { throw "Not implemented"; } @@ -69,44 +70,45 @@ class Utf8 { Decode an UTF8 string back to an ISO string. Throw an exception if a given UTF8 character is not supported by the decoder. **/ - public static function decode( s : String ) : String { + public static function decode(s:String):String { throw "Not implemented"; } /** Similar to `String.charCodeAt` but uses the UTF8 character position. **/ - public static inline function charCodeAt( s : String, index : Int ) : Int { + public static inline function charCodeAt(s:String, index:Int):Int { return s.charCodeAt(index); } /** Tells if the String is correctly encoded as UTF8. **/ - public static inline function validate( s : String ) : Bool { + public static inline function validate(s:String):Bool { return true; } /** Returns the number of UTF8 chars of the String. **/ - #if js @:extern #end - public static inline function length( s : String ) : Int { + #if js + extern + #end + public static inline function length(s:String):Int { return s.length; } /** Compare two UTF8 strings, character by character. **/ - public static function compare( a : String, b : String ) : Int { + public static function compare(a:String, b:String):Int { return a > b ? 1 : (a == b ? 0 : -1); } /** This is similar to `String.substr` but the `pos` and `len` parts are considering UTF8 characters. **/ - public static inline function sub( s : String, pos : Int, len : Int ) : String { - return s.substr(pos,len); + public static inline function sub(s:String, pos:Int, len:Int):String { + return s.substr(pos, len); } - } diff --git a/std/haxe/crypto/Adler32.hx b/std/haxe/crypto/Adler32.hx index 93e3f6552d0..6bef9e12f32 100644 --- a/std/haxe/crypto/Adler32.hx +++ b/std/haxe/crypto/Adler32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,15 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.crypto; /** - Calculates the Adler32 of the given Bytes. -*/ + Calculates the Adler32 of the given Bytes. + */ class Adler32 { - - var a1 : Int; - var a2 : Int; + var a1:Int; + var a2:Int; public function new() { a1 = 1; @@ -38,9 +38,9 @@ class Adler32 { return (a2 << 16) | a1; } - public function update( b : haxe.io.Bytes, pos, len ) { + public function update(b:haxe.io.Bytes, pos, len) { var a1 = a1, a2 = a2; - for( p in pos...pos + len ) { + for (p in pos...pos + len) { var c = b.get(p); a1 = (a1 + c) % 65521; a2 = (a2 + a1) % 65521; @@ -49,15 +49,15 @@ class Adler32 { this.a2 = a2; } - public function equals( a : Adler32 ) { + public function equals(a:Adler32) { return a.a1 == a1 && a.a2 == a2; } public function toString() { - return StringTools.hex(a2,8) + StringTools.hex(a1,8); + return StringTools.hex(a2, 8) + StringTools.hex(a1, 8); } - public static function read( i : haxe.io.Input ) { + public static function read(i:haxe.io.Input) { var a = new Adler32(); var a2a = i.readByte(); var a2b = i.readByte(); @@ -68,11 +68,9 @@ class Adler32 { return a; } - public static function make( b : haxe.io.Bytes ) { + public static function make(b:haxe.io.Bytes) { var a = new Adler32(); - a.update(b,0,b.length); + a.update(b, 0, b.length); return a.get(); } - - } diff --git a/std/haxe/crypto/Base64.hx b/std/haxe/crypto/Base64.hx index d46a4129acf..aee6895e96f 100644 --- a/std/haxe/crypto/Base64.hx +++ b/std/haxe/crypto/Base64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,34 +19,56 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.crypto; /** Allows one to encode/decode String and bytes using Base64 encoding. **/ class Base64 { + public static var CHARS(default, null) = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + public static var BYTES(default, null) = haxe.io.Bytes.ofString(CHARS); - public static var CHARS(default,null) = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - public static var BYTES(default,null) = haxe.io.Bytes.ofString(CHARS); + public static var URL_CHARS(default, null) = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + public static var URL_BYTES(default, null) = haxe.io.Bytes.ofString(URL_CHARS); - public static function encode( bytes : haxe.io.Bytes, complement = true ) : String { + public static function encode(bytes:haxe.io.Bytes, complement = true):String { var str = new BaseCode(BYTES).encodeBytes(bytes).toString(); - if( complement ) + if (complement) switch (bytes.length % 3) { - case 1: - str += "=="; - case 2: - str += "="; - default: + case 1: + str += "=="; + case 2: + str += "="; + default: } return str; } - public static function decode( str : String, complement = true ) : haxe.io.Bytes { - if( complement ) - while( str.charCodeAt(str.length-1) == "=".code ) - str = str.substr(0,-1); + public static function decode(str:String, complement = true):haxe.io.Bytes { + if (complement) + while (str.charCodeAt(str.length - 1) == "=".code) + str = str.substr(0, -1); return new BaseCode(BYTES).decodeBytes(haxe.io.Bytes.ofString(str)); } + public static function urlEncode(bytes:haxe.io.Bytes, complement = false):String { + var str = new BaseCode(URL_BYTES).encodeBytes(bytes).toString(); + if (complement) + switch (bytes.length % 3) { + case 1: + str += "=="; + case 2: + str += "="; + default: + } + return str; + } + + public static function urlDecode(str:String, complement = false):haxe.io.Bytes { + if (complement) + while (str.charCodeAt(str.length - 1) == "=".code) + str = str.substr(0, -1); + return new BaseCode(URL_BYTES).decodeBytes(haxe.io.Bytes.ofString(str)); + } } diff --git a/std/haxe/crypto/BaseCode.hx b/std/haxe/crypto/BaseCode.hx index ef4397933cd..0bf636a7859 100644 --- a/std/haxe/crypto/BaseCode.hx +++ b/std/haxe/crypto/BaseCode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,72 +19,73 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.crypto; /** Allows one to encode/decode String and bytes using a power of two base dictionary. **/ class BaseCode { + var base:haxe.io.Bytes; + var nbits:Int; + var tbl:Array; - var base : haxe.io.Bytes; - var nbits : Int; - var tbl : Array; - - public function new( base : haxe.io.Bytes ) { + public function new(base:haxe.io.Bytes) { var len = base.length; var nbits = 1; - while( len > 1 << nbits ) + while (len > 1 << nbits) nbits++; - if( nbits > 8 || len != 1 << nbits ) + if (nbits > 8 || len != 1 << nbits) throw "BaseCode : base length must be a power of two."; this.base = base; this.nbits = nbits; } - public function encodeBytes( b : haxe.io.Bytes ) : haxe.io.Bytes { + public function encodeBytes(b:haxe.io.Bytes):haxe.io.Bytes { #if (neko && !interp) - return haxe.io.Bytes.ofData( base_encode(b.getData(),base.getData()) ); + return haxe.io.Bytes.ofData(base_encode(b.getData(), base.getData())); #else var nbits = this.nbits; var base = this.base; var size = Std.int(b.length * 8 / nbits); - var out = haxe.io.Bytes.alloc(size + (((b.length * 8) % nbits == 0) ? 0 : 1) ); + var out = haxe.io.Bytes.alloc(size + (((b.length * 8) % nbits == 0) ? 0 : 1)); var buf = 0; var curbits = 0; var mask = (1 << nbits) - 1; var pin = 0; var pout = 0; - while( pout < size ) { - while( curbits < nbits ) { + while (pout < size) { + while (curbits < nbits) { curbits += 8; buf <<= 8; buf |= b.get(pin++); } curbits -= nbits; - out.set(pout++,base.get((buf >> curbits) & mask)); + out.set(pout++, base.get((buf >> curbits) & mask)); } - if( curbits > 0 ) - out.set(pout++,base.get((buf << (nbits - curbits)) & mask)); + if (curbits > 0) + out.set(pout++, base.get((buf << (nbits - curbits)) & mask)); return out; #end } function initTable() { var tbl = new Array(); - for( i in 0...256 ) + for (i in 0...256) tbl[i] = -1; - for( i in 0...base.length ) + for (i in 0...base.length) tbl[base.get(i)] = i; this.tbl = tbl; } - public function decodeBytes( b : haxe.io.Bytes ) : haxe.io.Bytes { + public function decodeBytes(b:haxe.io.Bytes):haxe.io.Bytes { #if (neko && !interp) - return haxe.io.Bytes.ofData( base_decode(b.getData(),base.getData()) ); + return haxe.io.Bytes.ofData(base_decode(b.getData(), base.getData())); #else var nbits = this.nbits; var base = this.base; - if( this.tbl == null ) initTable(); + if (this.tbl == null) + initTable(); var tbl = this.tbl; var size = (b.length * nbits) >> 3; var out = haxe.io.Bytes.alloc(size); @@ -92,50 +93,50 @@ class BaseCode { var curbits = 0; var pin = 0; var pout = 0; - while( pout < size ) { - while( curbits < 8 ) { + while (pout < size) { + while (curbits < 8) { curbits += nbits; buf <<= nbits; var i = tbl[b.get(pin++)]; - if( i == -1 ) + if (i == -1) throw "BaseCode : invalid encoded char"; buf |= i; } curbits -= 8; - out.set(pout++,(buf >> curbits) & 0xFF); + out.set(pout++, (buf >> curbits) & 0xFF); } return out; #end } - public function encodeString( s : String ) { + public function encodeString(s:String) { #if (neko && !interp) - return neko.NativeString.toString( base_encode(neko.NativeString.ofString(s),base.getData()) ); + return neko.NativeString.toString(base_encode(neko.NativeString.ofString(s), base.getData())); #else return encodeBytes(haxe.io.Bytes.ofString(s)).toString(); #end } - public function decodeString( s : String ) { + public function decodeString(s:String) { #if (neko && !interp) - return neko.NativeString.toString( base_decode(neko.NativeString.ofString(s),base.getData()) ); + return neko.NativeString.toString(base_decode(neko.NativeString.ofString(s), base.getData())); #else return decodeBytes(haxe.io.Bytes.ofString(s)).toString(); #end } - public static function encode( s : String, base : String ) { + public static function encode(s:String, base:String) { var b = new BaseCode(haxe.io.Bytes.ofString(base)); return b.encodeString(s); } - public static function decode( s : String, base : String ) { + public static function decode(s:String, base:String) { var b = new BaseCode(haxe.io.Bytes.ofString(base)); return b.decodeString(s); } #if neko - private static var base_encode = neko.Lib.load("std","base_encode",2); - private static var base_decode = neko.Lib.load("std","base_decode",2); + private static var base_encode = neko.Lib.load("std", "base_encode", 2); + private static var base_decode = neko.Lib.load("std", "base_decode", 2); #end } diff --git a/std/haxe/crypto/Crc32.hx b/std/haxe/crypto/Crc32.hx index a74d362a3d0..dc30a734de5 100644 --- a/std/haxe/crypto/Crc32.hx +++ b/std/haxe/crypto/Crc32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,66 +19,46 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.crypto; /** - Calculates the Crc32 of the given Bytes. -*/ + Calculates the Crc32 of the given Bytes. + */ class Crc32 { + var crc:Int; - var crc : Int; - - public function new() { + public inline function new() { crc = 0xFFFFFFFF; } - public function byte( b : Int ) { + public inline function byte(b:Int) { var tmp = (crc ^ b) & 0xFF; - for( j in 0...8 ) { - if( tmp & 1 == 1 ) - tmp = (tmp >>> 1) ^ 0xEDB88320; - else - tmp >>>= 1; - } + for (j in 0...8) + tmp = (tmp >>> 1) ^ (-(tmp & 1) & 0xEDB88320); crc = (crc >>> 8) ^ tmp; } - public function update( b : haxe.io.Bytes, pos, len ) { + public inline function update(b:haxe.io.Bytes, pos, len) { var b = b.getData(); - for( i in pos...pos+len ) { - var tmp = (crc ^ haxe.io.Bytes.fastGet(b,i)) & 0xFF; - for( j in 0...8 ) { - if( tmp & 1 == 1 ) - tmp = (tmp >>> 1) ^ 0xEDB88320; - else - tmp >>>= 1; - } + for (i in pos...pos + len) { + var tmp = (crc ^ haxe.io.Bytes.fastGet(b, i)) & 0xFF; + for (j in 0...8) + tmp = (tmp >>> 1) ^ (-(tmp & 1) & 0xEDB88320); crc = (crc >>> 8) ^ tmp; } } - public function get() { + public inline function get() { return crc ^ 0xFFFFFFFF; } /** Calculates the CRC32 of the given data bytes **/ - public static function make( data : haxe.io.Bytes ) : Int { - var init = 0xFFFFFFFF; - var crc = init; - var b = data.getData(); - for( i in 0...data.length ) { - var tmp = (crc ^ haxe.io.Bytes.fastGet(b,i)) & 0xFF; - for( j in 0...8 ) { - if( tmp & 1 == 1 ) - tmp = (tmp >>> 1) ^ 0xEDB88320; - else - tmp >>>= 1; - } - crc = (crc >>> 8) ^ tmp; - } - return crc ^ init; + public static function make(data:haxe.io.Bytes):Int { + var c = new Crc32(); + c.update(data, 0, data.length); + return c.get(); } - } diff --git a/std/haxe/crypto/Hmac.hx b/std/haxe/crypto/Hmac.hx index e98b66283ea..0137065fc5d 100644 --- a/std/haxe/crypto/Hmac.hx +++ b/std/haxe/crypto/Hmac.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.crypto; /** - Hash methods for Hmac calculation. -*/ + Hash methods for Hmac calculation. +**/ enum HashMethod { MD5; SHA1; @@ -31,47 +32,46 @@ enum HashMethod { } /** - Calculates a Hmac of the given Bytes using a HashMethod. -*/ + Calculates a Hmac of the given Bytes using a HashMethod. +**/ class Hmac { - - var method : HashMethod; - var blockSize : Int; - var length : Int; - - public function new( hashMethod : HashMethod ) { + var method:HashMethod; + var blockSize:Int; + var length:Int; + + public function new(hashMethod:HashMethod) { method = hashMethod; - blockSize = switch ( hashMethod ) { + blockSize = switch (hashMethod) { case MD5, SHA1, SHA256: 64; } - length = switch ( hashMethod ) { + length = switch (hashMethod) { case MD5: 16; case SHA1: 20; case SHA256: 32; } } - - inline function doHash( b : haxe.io.Bytes ) : haxe.io.Bytes { - return switch ( method ) { + + inline function doHash(b:haxe.io.Bytes):haxe.io.Bytes { + return switch (method) { case MD5: Md5.make(b); case SHA1: Sha1.make(b); case SHA256: Sha256.make(b); } } - - function nullPad( s : haxe.io.Bytes, chunkLen : Int ) : haxe.io.Bytes { + + function nullPad(s:haxe.io.Bytes, chunkLen:Int):haxe.io.Bytes { var r = chunkLen - (s.length % chunkLen); - if(r == chunkLen && s.length != 0) + if (r == chunkLen && s.length != 0) return s; var sb = new haxe.io.BytesBuffer(); sb.add(s); - for(x in 0...r) + for (x in 0...r) sb.addByte(0); return sb.getBytes(); } - - public function make( key : haxe.io.Bytes, msg : haxe.io.Bytes ) : haxe.io.Bytes { - if(key.length > blockSize) { + + public function make(key:haxe.io.Bytes, msg:haxe.io.Bytes):haxe.io.Bytes { + if (key.length > blockSize) { key = doHash(key); } key = nullPad(key, blockSize); @@ -87,5 +87,4 @@ class Hmac { Ko.add(doHash(Ki.getBytes())); return doHash(Ko.getBytes()); } - } diff --git a/std/haxe/crypto/Md5.hx b/std/haxe/crypto/Md5.hx index d46cac50949..057c048a167 100644 --- a/std/haxe/crypto/Md5.hx +++ b/std/haxe/crypto/Md5.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,106 +19,103 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.crypto; /** Creates a MD5 of a String. **/ class Md5 { - - public static function encode( s : String ) : String { + public static function encode(s:String):String { #if neko - return untyped new String(base_encode(make_md5(s.__s),"0123456789abcdef".__s)); + return untyped new String(base_encode(make_md5(s.__s), "0123456789abcdef".__s)); #else - var m = new Md5(); - var h = m.doEncode(str2blks(s)); - return m.hex(h); + var m = new Md5(); + var h = m.doEncode(str2blks(s)); + return m.hex(h); #end } - public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes { + public static function make(b:haxe.io.Bytes):haxe.io.Bytes { #if neko - return haxe.io.Bytes.ofData(make_md5(b.getData())); + return haxe.io.Bytes.ofData(make_md5(b.getData())); #else - var h = new Md5().doEncode(bytes2blks(b)); - var out = haxe.io.Bytes.alloc(16); - var p = 0; - for( i in 0...4 ) { - out.set(p++,h[i]&0xFF); - out.set(p++,(h[i]>>8)&0xFF); - out.set(p++,(h[i]>>16)&0xFF); - out.set(p++,h[i]>>>24); - } - return out; + var h = new Md5().doEncode(bytes2blks(b)); + var out = haxe.io.Bytes.alloc(16); + var p = 0; + for (i in 0...4) { + out.set(p++, h[i] & 0xFF); + out.set(p++, (h[i] >> 8) & 0xFF); + out.set(p++, (h[i] >> 16) & 0xFF); + out.set(p++, h[i] >>> 24); + } + return out; #end } #if neko - static var base_encode = neko.Lib.load("std","base_encode",2); - static var make_md5 = neko.Lib.load("std","make_md5",1); + static var base_encode = neko.Lib.load("std", "base_encode", 2); + static var make_md5 = neko.Lib.load("std", "make_md5", 1); #else - -/* - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Copyright (C) Paul Johnston 1999 - 2000. - * Updated by Greg Holt 2000 - 2001. - * See http://pajhome.org.uk/site/legal.html for details. - */ - - function new() { - } - - function bitOR(a, b){ + /* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Copyright (C) Paul Johnston 1999 - 2000. + * Updated by Greg Holt 2000 - 2001. + * See http://pajhome.org.uk/site/legal.html for details. + */ + function new() {} + + function bitOR(a, b) { var lsb = (a & 0x1) | (b & 0x1); var msb31 = (a >>> 1) | (b >>> 1); return (msb31 << 1) | lsb; } - function bitXOR(a, b){ + function bitXOR(a, b) { var lsb = (a & 0x1) ^ (b & 0x1); var msb31 = (a >>> 1) ^ (b >>> 1); return (msb31 << 1) | lsb; } - function bitAND(a, b){ + function bitAND(a, b) { var lsb = (a & 0x1) & (b & 0x1); var msb31 = (a >>> 1) & (b >>> 1); return (msb31 << 1) | lsb; } function addme(x, y) { - var lsw = (x & 0xFFFF)+(y & 0xFFFF); - var msw = (x >> 16)+(y >> 16)+(lsw >> 16); + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } - function hex( a : Array ){ + function hex(a:Array) { var str = ""; var hex_chr = "0123456789abcdef"; - for( num in a ) - for( j in 0...4 ) - str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) + - hex_chr.charAt((num >> (j * 8)) & 0x0F); + for (num in a) + for (j in 0...4) + str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) + hex_chr.charAt((num >> (j * 8)) & 0x0F); return str; } - static function bytes2blks( b : haxe.io.Bytes ){ + static function bytes2blks(b:haxe.io.Bytes) { var nblk = ((b.length + 8) >> 6) + 1; var blks = new Array(); - //preallocate size + // preallocate size var blksSize = nblk * 16; #if (neko || cs || cpp || java || hl) blks[blksSize - 1] = 0; #end - #if !(cpp || cs || hl) //C++ and C# will already initialize them with zeroes. - for( i in 0...blksSize ) blks[i] = 0; + #if !(cpp || cs || hl) // C++ and C# will already initialize them with zeroes. + for (i in 0...blksSize) + blks[i] = 0; #end var i = 0; - while( i < b.length ) { + while (i < b.length) { blks[i >> 2] |= b.get(i) << ((((b.length << 3) + i) & 3) << 3); i++; } @@ -132,28 +129,29 @@ class Md5 { return blks; } - static function str2blks( str : String ){ -#if !(neko || cpp) + static function str2blks(str:String) { + #if target.unicode var str = haxe.io.Bytes.ofString(str); -#end + #end var nblk = ((str.length + 8) >> 6) + 1; var blks = new Array(); - //preallocate size + // preallocate size var blksSize = nblk * 16; #if (neko || eval || cs || cpp || java || hl) blks[blksSize - 1] = 0; #end - #if !(cpp || cs || hl) //C++ and C# will already initialize them with zeroes. - for( i in 0...blksSize ) blks[i] = 0; + #if !(cpp || cs || hl) // C++ and C# will already initialize them with zeroes. + for (i in 0...blksSize) + blks[i] = 0; #end var i = 0; var max = str.length; var l = max * 8; - while( i < max ) { - blks[i >> 2] |= #if !(neko || cpp) str.get(i) #else StringTools.fastCodeAt(str, i) #end << (((l + i) % 4) * 8); + while (i < max) { + blks[i >> 2] |= #if target.unicode str.get(i) #else StringTools.fastCodeAt(str, i) #end << (((l + i) % 4) * 8); i++; } blks[i >> 2] |= 0x80 << (((l + i) % 4) * 8); @@ -165,111 +163,110 @@ class Md5 { return blks; } - function rol(num, cnt){ + function rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); } - function cmn(q, a, b, x, s, t){ + function cmn(q, a, b, x, s, t) { return addme(rol((addme(addme(a, q), addme(x, t))), s), b); } - function ff(a, b, c, d, x, s, t){ + function ff(a, b, c, d, x, s, t) { return cmn(bitOR(bitAND(b, c), bitAND((~b), d)), a, b, x, s, t); } - function gg(a, b, c, d, x, s, t){ + function gg(a, b, c, d, x, s, t) { return cmn(bitOR(bitAND(b, d), bitAND(c, (~d))), a, b, x, s, t); } - function hh(a, b, c, d, x, s, t){ + function hh(a, b, c, d, x, s, t) { return cmn(bitXOR(bitXOR(b, c), d), a, b, x, s, t); } - function ii(a, b, c, d, x, s, t){ + function ii(a, b, c, d, x, s, t) { return cmn(bitXOR(c, bitOR(b, (~d))), a, b, x, s, t); } - function doEncode( x : Array ) : Array { - - var a = 1732584193; + function doEncode(x:Array):Array { + var a = 1732584193; var b = -271733879; var c = -1732584194; - var d = 271733878; + var d = 271733878; var step; var i = 0; - while( i < x.length ) { + while (i < x.length) { var olda = a; var oldb = b; var oldc = c; var oldd = d; step = 0; - a = ff(a, b, c, d, x[i+ 0], 7 , -680876936); - d = ff(d, a, b, c, x[i+ 1], 12, -389564586); - c = ff(c, d, a, b, x[i+ 2], 17, 606105819); - b = ff(b, c, d, a, x[i+ 3], 22, -1044525330); - a = ff(a, b, c, d, x[i+ 4], 7 , -176418897); - d = ff(d, a, b, c, x[i+ 5], 12, 1200080426); - c = ff(c, d, a, b, x[i+ 6], 17, -1473231341); - b = ff(b, c, d, a, x[i+ 7], 22, -45705983); - a = ff(a, b, c, d, x[i+ 8], 7 , 1770035416); - d = ff(d, a, b, c, x[i+ 9], 12, -1958414417); - c = ff(c, d, a, b, x[i+10], 17, -42063); - b = ff(b, c, d, a, x[i+11], 22, -1990404162); - a = ff(a, b, c, d, x[i+12], 7 , 1804603682); - d = ff(d, a, b, c, x[i+13], 12, -40341101); - c = ff(c, d, a, b, x[i+14], 17, -1502002290); - b = ff(b, c, d, a, x[i+15], 22, 1236535329); - a = gg(a, b, c, d, x[i+ 1], 5 , -165796510); - d = gg(d, a, b, c, x[i+ 6], 9 , -1069501632); - c = gg(c, d, a, b, x[i+11], 14, 643717713); - b = gg(b, c, d, a, x[i+ 0], 20, -373897302); - a = gg(a, b, c, d, x[i+ 5], 5 , -701558691); - d = gg(d, a, b, c, x[i+10], 9 , 38016083); - c = gg(c, d, a, b, x[i+15], 14, -660478335); - b = gg(b, c, d, a, x[i+ 4], 20, -405537848); - a = gg(a, b, c, d, x[i+ 9], 5 , 568446438); - d = gg(d, a, b, c, x[i+14], 9 , -1019803690); - c = gg(c, d, a, b, x[i+ 3], 14, -187363961); - b = gg(b, c, d, a, x[i+ 8], 20, 1163531501); - a = gg(a, b, c, d, x[i+13], 5 , -1444681467); - d = gg(d, a, b, c, x[i+ 2], 9 , -51403784); - c = gg(c, d, a, b, x[i+ 7], 14, 1735328473); - b = gg(b, c, d, a, x[i+12], 20, -1926607734); - a = hh(a, b, c, d, x[i+ 5], 4 , -378558); - d = hh(d, a, b, c, x[i+ 8], 11, -2022574463); - c = hh(c, d, a, b, x[i+11], 16, 1839030562); - b = hh(b, c, d, a, x[i+14], 23, -35309556); - a = hh(a, b, c, d, x[i+ 1], 4 , -1530992060); - d = hh(d, a, b, c, x[i+ 4], 11, 1272893353); - c = hh(c, d, a, b, x[i+ 7], 16, -155497632); - b = hh(b, c, d, a, x[i+10], 23, -1094730640); - a = hh(a, b, c, d, x[i+13], 4 , 681279174); - d = hh(d, a, b, c, x[i+ 0], 11, -358537222); - c = hh(c, d, a, b, x[i+ 3], 16, -722521979); - b = hh(b, c, d, a, x[i+ 6], 23, 76029189); - a = hh(a, b, c, d, x[i+ 9], 4 , -640364487); - d = hh(d, a, b, c, x[i+12], 11, -421815835); - c = hh(c, d, a, b, x[i+15], 16, 530742520); - b = hh(b, c, d, a, x[i+ 2], 23, -995338651); - a = ii(a, b, c, d, x[i+ 0], 6 , -198630844); - d = ii(d, a, b, c, x[i+ 7], 10, 1126891415); - c = ii(c, d, a, b, x[i+14], 15, -1416354905); - b = ii(b, c, d, a, x[i+ 5], 21, -57434055); - a = ii(a, b, c, d, x[i+12], 6 , 1700485571); - d = ii(d, a, b, c, x[i+ 3], 10, -1894986606); - c = ii(c, d, a, b, x[i+10], 15, -1051523); - b = ii(b, c, d, a, x[i+ 1], 21, -2054922799); - a = ii(a, b, c, d, x[i+ 8], 6 , 1873313359); - d = ii(d, a, b, c, x[i+15], 10, -30611744); - c = ii(c, d, a, b, x[i+ 6], 15, -1560198380); - b = ii(b, c, d, a, x[i+13], 21, 1309151649); - a = ii(a, b, c, d, x[i+ 4], 6 , -145523070); - d = ii(d, a, b, c, x[i+11], 10, -1120210379); - c = ii(c, d, a, b, x[i+ 2], 15, 718787259); - b = ii(b, c, d, a, x[i+ 9], 21, -343485551); + a = ff(a, b, c, d, x[i + 0], 7, -680876936); + d = ff(d, a, b, c, x[i + 1], 12, -389564586); + c = ff(c, d, a, b, x[i + 2], 17, 606105819); + b = ff(b, c, d, a, x[i + 3], 22, -1044525330); + a = ff(a, b, c, d, x[i + 4], 7, -176418897); + d = ff(d, a, b, c, x[i + 5], 12, 1200080426); + c = ff(c, d, a, b, x[i + 6], 17, -1473231341); + b = ff(b, c, d, a, x[i + 7], 22, -45705983); + a = ff(a, b, c, d, x[i + 8], 7, 1770035416); + d = ff(d, a, b, c, x[i + 9], 12, -1958414417); + c = ff(c, d, a, b, x[i + 10], 17, -42063); + b = ff(b, c, d, a, x[i + 11], 22, -1990404162); + a = ff(a, b, c, d, x[i + 12], 7, 1804603682); + d = ff(d, a, b, c, x[i + 13], 12, -40341101); + c = ff(c, d, a, b, x[i + 14], 17, -1502002290); + b = ff(b, c, d, a, x[i + 15], 22, 1236535329); + a = gg(a, b, c, d, x[i + 1], 5, -165796510); + d = gg(d, a, b, c, x[i + 6], 9, -1069501632); + c = gg(c, d, a, b, x[i + 11], 14, 643717713); + b = gg(b, c, d, a, x[i + 0], 20, -373897302); + a = gg(a, b, c, d, x[i + 5], 5, -701558691); + d = gg(d, a, b, c, x[i + 10], 9, 38016083); + c = gg(c, d, a, b, x[i + 15], 14, -660478335); + b = gg(b, c, d, a, x[i + 4], 20, -405537848); + a = gg(a, b, c, d, x[i + 9], 5, 568446438); + d = gg(d, a, b, c, x[i + 14], 9, -1019803690); + c = gg(c, d, a, b, x[i + 3], 14, -187363961); + b = gg(b, c, d, a, x[i + 8], 20, 1163531501); + a = gg(a, b, c, d, x[i + 13], 5, -1444681467); + d = gg(d, a, b, c, x[i + 2], 9, -51403784); + c = gg(c, d, a, b, x[i + 7], 14, 1735328473); + b = gg(b, c, d, a, x[i + 12], 20, -1926607734); + a = hh(a, b, c, d, x[i + 5], 4, -378558); + d = hh(d, a, b, c, x[i + 8], 11, -2022574463); + c = hh(c, d, a, b, x[i + 11], 16, 1839030562); + b = hh(b, c, d, a, x[i + 14], 23, -35309556); + a = hh(a, b, c, d, x[i + 1], 4, -1530992060); + d = hh(d, a, b, c, x[i + 4], 11, 1272893353); + c = hh(c, d, a, b, x[i + 7], 16, -155497632); + b = hh(b, c, d, a, x[i + 10], 23, -1094730640); + a = hh(a, b, c, d, x[i + 13], 4, 681279174); + d = hh(d, a, b, c, x[i + 0], 11, -358537222); + c = hh(c, d, a, b, x[i + 3], 16, -722521979); + b = hh(b, c, d, a, x[i + 6], 23, 76029189); + a = hh(a, b, c, d, x[i + 9], 4, -640364487); + d = hh(d, a, b, c, x[i + 12], 11, -421815835); + c = hh(c, d, a, b, x[i + 15], 16, 530742520); + b = hh(b, c, d, a, x[i + 2], 23, -995338651); + a = ii(a, b, c, d, x[i + 0], 6, -198630844); + d = ii(d, a, b, c, x[i + 7], 10, 1126891415); + c = ii(c, d, a, b, x[i + 14], 15, -1416354905); + b = ii(b, c, d, a, x[i + 5], 21, -57434055); + a = ii(a, b, c, d, x[i + 12], 6, 1700485571); + d = ii(d, a, b, c, x[i + 3], 10, -1894986606); + c = ii(c, d, a, b, x[i + 10], 15, -1051523); + b = ii(b, c, d, a, x[i + 1], 21, -2054922799); + a = ii(a, b, c, d, x[i + 8], 6, 1873313359); + d = ii(d, a, b, c, x[i + 15], 10, -30611744); + c = ii(c, d, a, b, x[i + 6], 15, -1560198380); + b = ii(b, c, d, a, x[i + 13], 21, 1309151649); + a = ii(a, b, c, d, x[i + 4], 6, -145523070); + d = ii(d, a, b, c, x[i + 11], 10, -1120210379); + c = ii(c, d, a, b, x[i + 2], 15, 718787259); + b = ii(b, c, d, a, x[i + 9], 21, -343485551); a = addme(a, olda); b = addme(b, oldb); @@ -278,10 +275,7 @@ class Md5 { i += 16; } - return [a,b,c,d]; + return [a, b, c, d]; } - #end - - } diff --git a/std/haxe/crypto/Sha1.hx b/std/haxe/crypto/Sha1.hx index d1f73735141..d1ca641807f 100644 --- a/std/haxe/crypto/Sha1.hx +++ b/std/haxe/crypto/Sha1.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,36 +19,35 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.crypto; /** - Creates a Sha1 of a String. -*/ + Creates a Sha1 of a String. +**/ class Sha1 { - - public static function encode( s:String ) : String { + public static function encode(s:String):String { var sh = new Sha1(); var h = sh.doEncode(str2blks(s)); return sh.hex(h); } - public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes { + public static function make(b:haxe.io.Bytes):haxe.io.Bytes { var h = new Sha1().doEncode(bytes2blks(b)); var out = haxe.io.Bytes.alloc(20); var p = 0; - for( i in 0...5 ) { - out.set(p++,h[i]>>>24); - out.set(p++,(h[i]>>16)&0xFF); - out.set(p++,(h[i]>>8)&0xFF); - out.set(p++,h[i]&0xFF); + for (i in 0...5) { + out.set(p++, h[i] >>> 24); + out.set(p++, (h[i] >> 16) & 0xFF); + out.set(p++, (h[i] >> 8) & 0xFF); + out.set(p++, h[i] & 0xFF); } return out; } - function new() { - } + function new() {} - function doEncode( x : Array ) : Array { + function doEncode(x:Array):Array { var w = new Array(); var a = 0x67452301; @@ -58,7 +57,7 @@ class Sha1 { var e = 0xC3D2E1F0; var i = 0; - while( i < x.length ) { + while (i < x.length) { var olda = a; var oldb = b; var oldc = c; @@ -66,11 +65,11 @@ class Sha1 { var olde = e; var j = 0; - while( j < 80 ) { - if(j < 16) + while (j < 80) { + if (j < 16) w[j] = x[i + j]; else - w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); + w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); var t = rol(a, 5) + ft(j, b, c, d) + e + w[j] + kt(j); e = d; d = c; @@ -86,26 +85,25 @@ class Sha1 { e += olde; i += 16; } - return [a,b,c,d,e]; + return [a, b, c, d, e]; } - - /* + /** Convert a string to a sequence of 16-word blocks, stored as an array. Append padding bits and the length, as described in the SHA1 standard. - */ - static function str2blks( s :String ) : Array { -#if !(neko || cpp) + **/ + static function str2blks(s:String):Array { + #if target.unicode var s = haxe.io.Bytes.ofString(s); -#end + #end var nblk = ((s.length + 8) >> 6) + 1; var blks = new Array(); - for (i in 0...nblk*16) + for (i in 0...nblk * 16) blks[i] = 0; - for (i in 0...s.length){ + for (i in 0...s.length) { var p = i >> 2; - blks[p] |= #if !(neko || cpp) s.get(i) #else StringTools.fastCodeAt(s,i) #end << (24 - ((i & 3) << 3)); + blks[p] |= #if target.unicode s.get(i) #else StringTools.fastCodeAt(s, i) #end << (24 - ((i & 3) << 3)); } var i = s.length; var p = i >> 2; @@ -114,13 +112,13 @@ class Sha1 { return blks; } - static function bytes2blks( b : haxe.io.Bytes ) : Array { + static function bytes2blks(b:haxe.io.Bytes):Array { var nblk = ((b.length + 8) >> 6) + 1; var blks = new Array(); - for (i in 0...nblk*16) + for (i in 0...nblk * 16) blks[i] = 0; - for (i in 0...b.length){ + for (i in 0...b.length) { var p = i >> 2; blks[p] |= b.get(i) << (24 - ((i & 3) << 3)); } @@ -133,37 +131,40 @@ class Sha1 { /** Bitwise rotate a 32-bit number to the left - */ - inline function rol( num : Int, cnt : Int ) : Int { + **/ + inline function rol(num:Int, cnt:Int):Int { return (num << cnt) | (num >>> (32 - cnt)); } /** Perform the appropriate triplet combination function for the current iteration - */ - function ft( t : Int, b : Int, c : Int, d : Int ) : Int { - if ( t < 20 ) return (b & c) | ((~b) & d); - if ( t < 40 ) return b ^ c ^ d; - if ( t < 60 ) return (b & c) | (b & d) | (c & d); + **/ + function ft(t:Int, b:Int, c:Int, d:Int):Int { + if (t < 20) + return (b & c) | ((~b) & d); + if (t < 40) + return b ^ c ^ d; + if (t < 60) + return (b & c) | (b & d) | (c & d); return b ^ c ^ d; } /** Determine the appropriate additive constant for the current iteration - */ - function kt( t : Int ) : Int { - if( t < 20) + **/ + function kt(t:Int):Int { + if (t < 20) return 0x5A827999; - if ( t < 40) + if (t < 40) return 0x6ED9EBA1; if (t < 60) return 0x8F1BBCDC; return 0xCA62C1D6; } - function hex( a : Array ){ + function hex(a:Array) { var str = ""; - for( num in a ) { + for (num in a) { str += StringTools.hex(num, 8); } return str.toLowerCase(); diff --git a/std/haxe/crypto/Sha224.hx b/std/haxe/crypto/Sha224.hx index de8bed3d7a1..7623fc05850 100644 --- a/std/haxe/crypto/Sha224.hx +++ b/std/haxe/crypto/Sha224.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of Charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,184 +19,173 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.crypto; /** - Creates a Sha224 of a String. -*/ + Creates a Sha224 of a String. +**/ class Sha224 { - - public static function encode( s:String ) : String { - var sh = new Sha224(); - var h = sh.doEncode(s, s.length*8); - return sh.hex(h); - } - - public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes { - var h = new Sha224().doEncode(b.toString(), b.length*8); - var out = haxe.io.Bytes.alloc(28); - var p = 0; - for( i in 0...8 ) { - out.set(p++,h[i]>>>24); - out.set(p++,(h[i]>>16)&0xFF); - out.set(p++,(h[i]>>8)&0xFF); - out.set(p++,h[i]&0xFF); - } - return out; - } - - public function new() { - } - - function doEncode( str : String, strlen : Int ) : Array { - var K : Array = [ - 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, - 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, - 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, - 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, - 0xE49B69C1, 0xEFBE4786, 0xFC19DC6 , 0x240CA1CC, - 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, - 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, - 0xC6E00BF3, 0xD5A79147, 0x6CA6351 , 0x14292967, - 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, - 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, - 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, - 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, - 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, - 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, - 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, - 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 - ]; - var HASH : Array = [ - 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, - 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 - ]; - var W = new Array(); - W[64] = 0; - - var a:Int,b:Int,c:Int,d:Int,e:Int,f:Int,g:Int,h:Int,i:Int,j:Int; - var T1, T2; - var i : Int = 0; - var blocks : Array = str2blks(str); - blocks[strlen >> 5] |= 0x80 << (24 - strlen % 32); - blocks[((strlen + 64 >> 9) << 4) + 15] = strlen; - - while ( i < blocks.length ) { - a = HASH[0]; - b = HASH[1]; - c = HASH[2]; - d = HASH[3]; - e = HASH[4]; - f = HASH[5]; - g = HASH[6]; - h = HASH[7]; - - for ( j in 0...64 ) { - if (j < 16) { - W[j] = blocks[j + i]; - } else { - W[j] = safeAdd(safeAdd(safeAdd(Gamma1(W[j - 2]), W[j - 7]), Gamma0(W[j - 15])), W[j - 16]); - } - - T1 = safeAdd(safeAdd(safeAdd(safeAdd(h, Sigma1(e)), Ch(e, f, g)), K[j]), W[j]); - T2 = safeAdd(Sigma0(a), Maj(a, b, c)); - - h = g; - g = f; - f = e; - e = safeAdd(d, T1); - d = c; - c = b; - b = a; - a = safeAdd(T1, T2); - } - - HASH[0] = safeAdd(a, HASH[0]); - HASH[1] = safeAdd(b, HASH[1]); - HASH[2] = safeAdd(c, HASH[2]); - HASH[3] = safeAdd(d, HASH[3]); - HASH[4] = safeAdd(e, HASH[4]); - HASH[5] = safeAdd(f, HASH[5]); - HASH[6] = safeAdd(g, HASH[6]); - HASH[7] = safeAdd(h, HASH[7]); - i += 16; - } - return HASH; - } - - static function str2blks( s :String ) : Array { - var nblk = ((s.length + 8) >> 6) + 1; - var blks = new Array(); - for (i in 0...nblk*16) - blks[i] = 0; - for (i in 0...s.length){ - var p = i >> 2; - blks[p] |= s.charCodeAt(i) << (24 - ((i & 3) << 3)); - } - var i = s.length; - var p = i >> 2; - blks[p] |= 0x80 << (24 - ((i & 3) << 3)); - blks[nblk * 16 - 1] = s.length * 8; - return blks; - } - - @:extern - inline static function safeAdd(x, y) { - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >>> 16) + (y >>> 16) + (lsw >>> 16); - return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); - } - - // ++ - @:extern - inline function ROTR(X, n) { - return ( X >>> n ) | (X << (32 - n)); - } - - // ++ - @:extern - inline function SHR(X, n) { - return ( X >>> n ); - } - - // ++ - @:extern - inline function Ch(x, y, z) { - return ((x & y) ^ ((~x) & z)); - } - - // ++ - @:extern - inline function Maj(x, y, z) { - return ((x & y) ^ (x & z) ^ (y & z)); - } - - @:extern - inline function Sigma0(x) { - return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22); - } - - @:extern - inline function Sigma1(x) { - return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25); - } - - @:extern - inline function Gamma0(x) { - return ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3); - } - - @:extern - inline function Gamma1(x) { - return ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10); - } - - function hex( a : Array ){ - var str = ""; - for( num in a ) { - str += StringTools.hex(num, 8); - } - return str.substring(0, 56).toLowerCase(); - } - + public static function encode(s:String):String { + var sh = new Sha224(); + var h = sh.doEncode(s, s.length * 8); + return sh.hex(h); + } + + public static function make(b:haxe.io.Bytes):haxe.io.Bytes { + var h = new Sha224().doEncode(b.toString(), b.length * 8); + var out = haxe.io.Bytes.alloc(28); + var p = 0; + for (i in 0...8) { + out.set(p++, h[i] >>> 24); + out.set(p++, (h[i] >> 16) & 0xFF); + out.set(p++, (h[i] >> 8) & 0xFF); + out.set(p++, h[i] & 0xFF); + } + return out; + } + + public function new() {} + + function doEncode(str:String, strlen:Int):Array { + var K:Array = [ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 + ]; + var HASH:Array = [ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 + ]; + var W = new Array(); + W[64] = 0; + + var a:Int, b:Int, c:Int, d:Int, e:Int, f:Int, g:Int, h:Int, i:Int, j:Int; + var T1, T2; + var i:Int = 0; + var blocks:Array = str2blks(str); + blocks[strlen >> 5] |= 0x80 << (24 - strlen % 32); + blocks[((strlen + 64 >> 9) << 4) + 15] = strlen; + + while (i < blocks.length) { + a = HASH[0]; + b = HASH[1]; + c = HASH[2]; + d = HASH[3]; + e = HASH[4]; + f = HASH[5]; + g = HASH[6]; + h = HASH[7]; + + for (j in 0...64) { + if (j < 16) { + W[j] = blocks[j + i]; + } else { + W[j] = safeAdd(safeAdd(safeAdd(Gamma1(W[j - 2]), W[j - 7]), Gamma0(W[j - 15])), W[j - 16]); + } + + T1 = safeAdd(safeAdd(safeAdd(safeAdd(h, Sigma1(e)), Ch(e, f, g)), K[j]), W[j]); + T2 = safeAdd(Sigma0(a), Maj(a, b, c)); + + h = g; + g = f; + f = e; + e = safeAdd(d, T1); + d = c; + c = b; + b = a; + a = safeAdd(T1, T2); + } + + HASH[0] = safeAdd(a, HASH[0]); + HASH[1] = safeAdd(b, HASH[1]); + HASH[2] = safeAdd(c, HASH[2]); + HASH[3] = safeAdd(d, HASH[3]); + HASH[4] = safeAdd(e, HASH[4]); + HASH[5] = safeAdd(f, HASH[5]); + HASH[6] = safeAdd(g, HASH[6]); + HASH[7] = safeAdd(h, HASH[7]); + i += 16; + } + return HASH; + } + + static function str2blks(s:String):Array { + var nblk = ((s.length + 8) >> 6) + 1; + var blks = new Array(); + for (i in 0...nblk * 16) + blks[i] = 0; + for (i in 0...s.length) { + var p = i >> 2; + blks[p] |= s.charCodeAt(i) << (24 - ((i & 3) << 3)); + } + var i = s.length; + var p = i >> 2; + blks[p] |= 0x80 << (24 - ((i & 3) << 3)); + blks[nblk * 16 - 1] = s.length * 8; + return blks; + } + + extern inline static function safeAdd(x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >>> 16) + (y >>> 16) + (lsw >>> 16); + return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); + } + + // ++ + extern inline function ROTR(X, n) { + return (X >>> n) | (X << (32 - n)); + } + + // ++ + extern inline function SHR(X, n) { + return (X >>> n); + } + + // ++ + extern inline function Ch(x, y, z) { + return ((x & y) ^ ((~x) & z)); + } + + // ++ + extern inline function Maj(x, y, z) { + return ((x & y) ^ (x & z) ^ (y & z)); + } + + extern inline function Sigma0(x) { + return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22); + } + + extern inline function Sigma1(x) { + return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25); + } + + extern inline function Gamma0(x) { + return ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3); + } + + extern inline function Gamma1(x) { + return ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10); + } + + function hex(a:Array) { + var str = ""; + for (num in a) { + str += StringTools.hex(num, 8); + } + return str.substring(0, 56).toLowerCase(); + } } diff --git a/std/haxe/crypto/Sha256.hx b/std/haxe/crypto/Sha256.hx index 4b86afe2f62..cc144525e6b 100644 --- a/std/haxe/crypto/Sha256.hx +++ b/std/haxe/crypto/Sha256.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,73 +19,79 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.crypto; /** - Creates a Sha256 of a String. -*/ + Creates a Sha256 of a String. +**/ class Sha256 { - - public static function encode( s:String ) : String { + public static function encode(s:String):String { var sh = new Sha256(); - var h = sh.doEncode(str2blks(s), s.length*8); + var h = sh.doEncode(str2blks(s), s.length * 8); return sh.hex(h); } - public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes { - var h = new Sha256().doEncode(bytes2blks(b), b.length*8); + public static function make(b:haxe.io.Bytes):haxe.io.Bytes { + var h = new Sha256().doEncode(bytes2blks(b), b.length * 8); var out = haxe.io.Bytes.alloc(32); var p = 0; - for( i in 0...8 ) { - out.set(p++,h[i]>>>24); - out.set(p++,(h[i]>>16)&0xFF); - out.set(p++,(h[i]>>8)&0xFF); - out.set(p++,h[i]&0xFF); + for (i in 0...8) { + out.set(p++, h[i] >>> 24); + out.set(p++, (h[i] >> 16) & 0xFF); + out.set(p++, (h[i] >> 8) & 0xFF); + out.set(p++, h[i] & 0xFF); } return out; } - public function new() { - } + public function new() {} - function doEncode( m : Array, l : Int ) : Array { - var K : Array = [ - 0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B, - 0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01, - 0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7, - 0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC, - 0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152, - 0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147, - 0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC, - 0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85, - 0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819, - 0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08, - 0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F, - 0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208, - 0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2 + function doEncode(m:Array, l:Int):Array { + var K:Array = [ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 ]; - var HASH : Array = [ - 0x6A09E667,0xBB67AE85,0x3C6EF372,0xA54FF53A, - 0x510E527F,0x9B05688C,0x1F83D9AB,0x5BE0CD19 + var HASH:Array = [ + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ]; var W = new Array(); W[64] = 0; - var a:Int,b:Int,c:Int,d:Int,e:Int,f:Int,g:Int,h:Int; + var a:Int, b:Int, c:Int, d:Int, e:Int, f:Int, g:Int, h:Int; var T1, T2; m[l >> 5] |= 0x80 << (24 - l % 32); m[((l + 64 >> 9) << 4) + 15] = l; - var i : Int = 0; - while ( i < m.length ) { - a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7]; - for ( j in 0...64 ) { + var i:Int = 0; + while (i < m.length) { + a = HASH[0]; + b = HASH[1]; + c = HASH[2]; + d = HASH[3]; + e = HASH[4]; + f = HASH[5]; + g = HASH[6]; + h = HASH[7]; + for (j in 0...64) { if (j < 16) W[j] = m[j + i]; else W[j] = safeAdd(safeAdd(safeAdd(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]); T1 = safeAdd(safeAdd(safeAdd(safeAdd(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]); T2 = safeAdd(Sigma0256(a), Maj(a, b, c)); - h = g; g = f; f = e; e = safeAdd(d, T1); d = c; c = b; b = a; a = safeAdd(T1, T2); + h = g; + g = f; + f = e; + e = safeAdd(d, T1); + d = c; + c = b; + b = a; + a = safeAdd(T1, T2); } HASH[0] = safeAdd(a, HASH[0]); HASH[1] = safeAdd(b, HASH[1]); @@ -100,22 +106,22 @@ class Sha256 { return HASH; } - /* + /** Convert a string to a sequence of 16-word blocks, stored as an array. Append padding bits and the length, as described in the SHA1 standard. - */ - static function str2blks( s :String ) : Array { -#if !(neko || cpp) + **/ + static function str2blks(s:String):Array { + #if target.unicode var s = haxe.io.Bytes.ofString(s); -#end + #end var nblk = ((s.length + 8) >> 6) + 1; var blks = new Array(); - for (i in 0...nblk*16) + for (i in 0...nblk * 16) blks[i] = 0; - for (i in 0...s.length){ + for (i in 0...s.length) { var p = i >> 2; - blks[p] |= #if !(neko || cpp) s.get(i) #else s.charCodeAt(i) #end << (24 - ((i & 3) << 3)); + blks[p] |= #if target.unicode s.get(i) #else s.charCodeAt(i) #end << (24 - ((i & 3) << 3)); } var i = s.length; var p = i >> 2; @@ -124,13 +130,13 @@ class Sha256 { return blks; } - static function bytes2blks( b : haxe.io.Bytes ) : Array { + static function bytes2blks(b:haxe.io.Bytes):Array { var nblk = ((b.length + 8) >> 6) + 1; var blks = new Array(); - for (i in 0...nblk*16) + for (i in 0...nblk * 16) blks[i] = 0; - for (i in 0...b.length){ + for (i in 0...b.length) { var p = i >> 2; blks[p] |= b.get(i) << (24 - ((i & 3) << 3)); } @@ -140,59 +146,50 @@ class Sha256 { blks[nblk * 16 - 1] = b.length * 8; return blks; } - @:extern - inline function S(X, n) { - return ( X >>> n ) | (X << (32 - n)); + + extern inline function S(X, n) { + return (X >>> n) | (X << (32 - n)); } - @:extern - inline function R(X, n) { - return ( X >>> n ); + extern inline function R(X, n) { + return (X >>> n); } - @:extern - inline function Ch(x, y, z) { + extern inline function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); } - @:extern - inline function Maj(x, y, z) { + extern inline function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); } - @:extern - inline function Sigma0256(x) { + extern inline function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); } - @:extern - inline function Sigma1256(x) { + extern inline function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); } - @:extern - inline function Gamma0256(x) { + extern inline function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); } - @:extern - inline function Gamma1256(x) { + extern inline function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); } - @:extern - inline function safeAdd(x, y) { + extern inline function safeAdd(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } - function hex( a : Array ){ + function hex(a:Array) { var str = ""; - for( num in a ) { + for (num in a) { str += StringTools.hex(num, 8); } return str.toLowerCase(); } - } diff --git a/std/haxe/display/Display.hx b/std/haxe/display/Display.hx new file mode 100644 index 00000000000..b3d7675d901 --- /dev/null +++ b/std/haxe/display/Display.hx @@ -0,0 +1,507 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.display; + +import haxe.display.JsonModuleTypes; +import haxe.display.Protocol; +import haxe.display.Position; + +/** + Methods of the JSON-RPC-based `--display` protocol in Haxe 4. + A lot of the methods are *inspired* by the Language Server Protocol, but there is **no** intention to be directly compatible with it. +**/ +@:publicFields +class DisplayMethods { + /** + The completion request is sent from the client to Haxe to request code completion. + Haxe automatically determines the type of completion to use based on the passed position, see `CompletionResultKind`. + **/ + static inline var Completion = new HaxeRequestMethod("display/completion"); + + /** + The request is sent from the client to Haxe to resolve additional information for a given completion item. + **/ + static inline var CompletionItemResolve = new HaxeRequestMethod("display/completionItem/resolve"); + + /** + The find references request is sent from the client to Haxe to find locations that reference the symbol at a given text document position. + **/ + static inline var FindReferences = new HaxeRequestMethod("display/references"); + + /** + The goto definition request is sent from the client to Haxe to resolve the definition location(s) of a symbol at a given text document position. + **/ + static inline var GotoDefinition = new HaxeRequestMethod("display/definition"); + + /** + The goto type definition request is sent from the client to Haxe to resolve the type definition location(s) of a symbol at a given text document position. + **/ + static inline var GotoTypeDefinition = new HaxeRequestMethod("display/typeDefinition"); + + /** + The hover request is sent from the client to Haxe to request hover information at a given text document position. + **/ + static inline var Hover = new HaxeRequestMethod("display/hover"); + + /** + This request is sent from the client to Haxe to determine the package for a given file, based on class paths configuration. + **/ + static inline var DeterminePackage = new HaxeRequestMethod("display/package"); + + /** + The signature help request is sent from the client to Haxe to request signature information at a given cursor position. + **/ + static inline var SignatureHelp = new HaxeRequestMethod("display/signatureHelp"); + + /* + TODO: + + - finish completion + - diagnostics + - codeLens + - workspaceSymbols ("project/symbol"?) + */ +} + +/** Completion **/ +typedef CompletionParams = PositionParams & { + var wasAutoTriggered:Bool; + + /** list of metas to include in responses **/ + var ?meta:Array; +} + +typedef FieldResolution = { + /** + Whether it's valid to use the unqualified name of the field or not. + This is `false` if the identifier is shadowed. + **/ + var isQualified:Bool; + + /** + The qualifier that has to be inserted to use the field if `!isQualified`. + Can either be `this` or `super` for instance fields for the type name for `static` fields. + **/ + var qualifier:String; +} + +typedef DisplayLocal = { + var id:Int; + var name:String; + var type:JsonType; + var origin:LocalOrigin; + var capture:Bool; + var ?extra:{ + var params:Array; + var expr:JsonExpr; + }; + var meta:JsonMetadata; + var pos:JsonPos; + var isInline:Bool; + var isFinal:Bool; +} + +enum abstract LocalOrigin(Int) { + var LocalVariable; + var Argument; + var ForVariable; + var PatternVariable; + var CatchVariable; + var LocalFunction; +} + +enum abstract ClassFieldOriginKind(Int) { + /** + The field is declared on the current type itself. + **/ + var Self:ClassFieldOriginKind>; + + /** + The field is a static field brought into context via a static import + (`import pack.Module.Type.field`). + **/ + var StaticImport:ClassFieldOriginKind>; + + /** + The field is declared on a parent type, such as: + - a super class field that is not overriden + - a forwarded abstract field + **/ + var Parent:ClassFieldOriginKind>; + + /** + The field is a static extension method brought + into context with the `using` keyword. + **/ + var StaticExtension:ClassFieldOriginKind>; + + /** + This field doesn't belong to any named type, just an anonymous structure. + **/ + var AnonymousStructure:ClassFieldOriginKind; + + /** + Special fields built into the compiler, such as: + - `code` on single-character Strings + - `bind()` on functions. + **/ + var BuiltIn:ClassFieldOriginKind; + + /** + The origin of this class field is unknown. + **/ + var Unknown:ClassFieldOriginKind; +} + +typedef ClassFieldOrigin = { + var kind:ClassFieldOriginKind; + var ?args:T; +} + +typedef ClassFieldOccurrence = { + var field:JsonClassField; + var resolution:FieldResolution; + var ?origin:ClassFieldOrigin; +} + +enum abstract EnumFieldOriginKind(Int) { + /** + The enum value is declared on the current type itself. + **/ + var Self:EnumFieldOriginKind>; + + /** + The enum value is brought into context via a static import + (`import pack.Module.Enum.Value`). + **/ + var StaticImport:EnumFieldOriginKind>; +} + +typedef EnumFieldOrigin = { + var kind:EnumFieldOriginKind; + var ?args:T; +} + +typedef EnumFieldOccurrence = { + var field:JsonEnumField; + var resolution:FieldResolution; + var ?origin:EnumFieldOrigin; +} + +enum abstract Literal(String) { + var Null = "null"; + var True = "true"; + var False = "false"; + var This = "this"; + var Trace = "trace"; +} + +enum abstract DisplayModuleTypeKind(Int) { + var Class; + var Interface; + var Enum; + var Abstract; + var EnumAbstract; + + /** A `typedef` that is just an alias for another type. **/ + var TypeAlias; + + /** A `typedef` that is an alias for an anonymous structure. **/ + var Struct; + + /** A type name introduced by `import as` / `import in` **/ + // var ImportAlias; +} + +typedef DisplayModuleType = { + var path:JsonTypePath; + var pos:JsonPos; + var isPrivate:Bool; + var params:Array; + var meta:JsonMetadata; + var doc:JsonDoc; + var isExtern:Bool; + var isFinal:Bool; + var kind:DisplayModuleTypeKind; +} + +typedef DisplayModuleTypeParameter = { + var name:String; + var meta:JsonMetadata; + var constraints:Array>; +} + +typedef DisplayLiteral = { + var name:String; +} + +enum abstract MetadataTarget(String) { + var Class = "TClass"; + var ClassField = "TClassField"; + var Abstract = "TAbstract"; + var AbstractField = "TAbstractField"; + var Enum = "TEnum"; + var Typedef = "TTypedef"; + var AnyField = "TAnyField"; + var Expr = "TExpr"; + var TypeParameter = "TTypeParameter"; +} + +enum abstract Platform(String) { + var Cross = "cross"; + var Js = "js"; + var Lua = "lua"; + var Neko = "neko"; + var Flash = "flash"; + var Php = "php"; + var Cpp = "cpp"; + var Cs = "cs"; + var Java = "java"; + var Python = "python"; + var Hl = "hl"; + var Eval = "eval"; +} + +typedef Metadata = { + var name:String; + var doc:JsonDoc; + var parameters:Array; + var platforms:Array; + var targets:Array; + var internal:Bool; + var ?links:Array; +} + +typedef Keyword = { + var name:KeywordKind; +} + +enum abstract KeywordKind(String) to String { + var Implements = "implements"; + var Extends = "extends"; + var Function = "function"; + var Var = "var"; + var If = "if"; + var Else = "else"; + var While = "while"; + var Do = "do"; + var For = "for"; + var Break = "break"; + var Return = "return"; + var Continue = "continue"; + var Switch = "switch"; + var Case = "case"; + var Default = "default"; + var Try = "try"; + var Catch = "catch"; + var New = "new"; + var Throw = "throw"; + var Untyped = "untyped"; + var Cast = "cast"; + var Macro = "macro"; + var Package = "package"; + var Import = "import"; + var Using = "using"; + var Public = "public"; + var Private = "private"; + var Static = "static"; + var Extern = "extern"; + var Dynamic = "dynamic"; + var Override = "override"; + var Class = "class"; + var Interface = "interface"; + var Enum = "enum"; + var Abstract = "abstract"; + var Typedef = "typedef"; + var Final = "final"; + var Inline = "inline"; +} + +/* enum abstract PackageContentKind(Int) { + var Module; + var Package; +}*/ +typedef Package = { + var path:JsonPackagePath; + // var ?contents:Array<{name:String, kind:PackageContentKind}>; +} + +typedef Module = { + var path:JsonModulePath; + // var ?contents:Array; +} + +enum abstract DisplayItemKind(String) { + var Local:DisplayItemKind>; + var ClassField:DisplayItemKind>; + var EnumField:DisplayItemKind>; + + /** Only for the enum values in enum abstracts, other fields use `ClassField`. **/ + var EnumAbstractField:DisplayItemKind>; + + var Type:DisplayItemKind; + var Package:DisplayItemKind; + var Module:DisplayItemKind; + var Literal:DisplayItemKind>; + var Metadata:DisplayItemKind; + var Keyword:DisplayItemKind; + var AnonymousStructure:DisplayItemKind; + var Expression:DisplayItemKind; + var TypeParameter:DisplayItemKind; +} + +typedef DisplayItem = { + var kind:DisplayItemKind; + var args:T; + var ?type:JsonType; + var ?index:Int; +} + +typedef DisplayItemOccurrence = { + var range:Range; + var item:DisplayItem; + var ?moduleType:JsonModuleType; + var ?moduleTypeFollowed:JsonModuleType; +} + +typedef FieldCompletionSubject = DisplayItemOccurrence & { + var ?iterator:{ + var type:JsonType; + }; + var ?keyValueIterator:{ + var key:JsonType; + var value:JsonType; + }; +} + +typedef ToplevelCompletion = { + var ?expectedType:JsonType; + var ?expectedTypeFollowed:JsonType; +} + +typedef StructExtensionCompletion = { + var isIntersectionType:Bool; +} + +typedef PatternCompletion = ToplevelCompletion & { + var isOutermostPattern:Bool; +} + +enum abstract CompletionModeKind(Int) { + var Field:CompletionModeKind>; + var StructureField; + var Toplevel:CompletionModeKind>; + var Metadata; + var TypeHint; + var Extends; + var Implements; + var StructExtension:CompletionModeKind; + var Import; + var Using; + var New; + var Pattern:CompletionModeKind>; + var Override; + var TypeRelation; + var TypeDeclaration; +} + +typedef CompletionMode = { + var kind:CompletionModeKind; + var ?args:T; +} + +typedef CompletionResponse = { + var items:Array>; + var mode:CompletionMode; + var ?replaceRange:Range; + var ?isIncomplete:Bool; +} + +typedef CompletionResult = Response>>; + +/** CompletionItem Resolve **/ +typedef CompletionItemResolveParams = { + var index:Int; +}; + +typedef CompletionItemResolveResult = Response<{ + var item:DisplayItem; +}>; + +/** GotoDefinition **/ +typedef GotoDefinitionResult = Response>; + +/** GotoTypeDefinition **/ +typedef GotoTypeDefinitionResult = Response>; + +/** Hover **/ +typedef HoverResult = Response>>; + +typedef HoverDisplayItemOccurence = DisplayItemOccurrence & { + var ?expected:{ + var ?type:JsonType; + var ?name:{ + var name:String; + var kind:HoverExpectedNameKind; + }; + }; +} + +enum abstract HoverExpectedNameKind(Int) { + var FunctionArgument; + var StructureField; +} + +/** DeterminePackage **/ +typedef DeterminePackageResult = Response>; + +/** SignatureHelp **/ +typedef SignatureHelpParams = PositionParams & { + var wasAutoTriggered:Bool; +} + +typedef SignatureInformation = JsonFunctionSignature & { + var ?documentation:String; +} + +enum abstract SignatureItemKind(Int) { + var Call; + var ArrayAccess; +} + +typedef SignatureItem = { + var signatures:Array; + var activeSignature:Int; + var activeParameter:Int; + var kind:SignatureItemKind; +} + +typedef SignatureHelpResult = Response>; + +/** General types **/ +typedef PositionParams = FileParams & { + /** Unicode character offset in the file. **/ + var offset:Int; + + var ?contents:String; +} diff --git a/std/haxe/display/FsPath.hx b/std/haxe/display/FsPath.hx new file mode 100644 index 00000000000..f427b6fbf4a --- /dev/null +++ b/std/haxe/display/FsPath.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.display; + +abstract FsPath(String) { + public inline function new(path:String) { + this = path; + } + + public inline function toString():String { + return this; + } +} diff --git a/std/haxe/display/JsonModuleTypes.hx b/std/haxe/display/JsonModuleTypes.hx new file mode 100644 index 00000000000..88ba7d88b63 --- /dev/null +++ b/std/haxe/display/JsonModuleTypes.hx @@ -0,0 +1,371 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.display; + +typedef JsonTodo = Dynamic; + +typedef JsonPos = { + var file:String; + var min:Int; + var max:Int; +} + +typedef JsonDoc = Null; + +enum abstract ImportStatus(Int) { + /** + This type is already available with it's unqualified name for one of these reasons: + - it's a toplevel type + - it's imported with an `import` in the current module + - it's imported in an `import.hx` file + **/ + var Imported; + + /** + The type is currently not imported. It can be accessed either + with its fully qualified name or by inserting an import. + **/ + var Unimported; + + /** + A type with the same name is already imported in the module. + The fully qualified name has to be used to access it. + **/ + var Shadowed; +} + +/* Type instance */ +typedef JsonPackagePath = { + var pack:Array; +} + +typedef JsonModulePath = JsonPackagePath & { + var moduleName:String; + var ?importStatus:ImportStatus; +} + +typedef JsonTypePath = JsonModulePath & { + var typeName:String; +} + +typedef JsonStaticFieldPath = JsonTypePath & { + var fieldName:String; +} + +typedef JsonTypePathWithParams = { + var path:JsonTypePath; + var params:JsonTypes; +} + +typedef JsonFunctionArgument = { + var name:String; + var opt:Bool; + var t:JsonType; + var ?value:{ + var string:String; + }; +} + +typedef JsonFunctionSignature = { + var args:Array; + var ret:JsonType; +} + +enum abstract JsonAnonStatusKind(String) { + var AClosed; + var AOpened; + var AConst; + var AExtend:JsonAnonStatusKind; + var AClassStatics:JsonAnonStatusKind; + var AEnumStatics:JsonAnonStatusKind; + var AAbstractStatics:JsonAnonStatusKind; +} + +typedef JsonAnonStatus = { + var kind:JsonAnonStatusKind; + var args:T; +} + +typedef JsonAnon = { + var fields:JsonClassFields; + var status:JsonAnonStatus; +} + +enum abstract JsonTypeKind(String) { + var TMono; + var TInst:JsonTypeKind; + var TEnum:JsonTypeKind; + var TType:JsonTypeKind; + var TAbstract:JsonTypeKind; + var TFun:JsonTypeKind; + var TAnonymous:JsonTypeKind; + var TDynamic:JsonTypeKind>>; +} + +typedef JsonType = { + var kind:JsonTypeKind; + var args:T; +} + +typedef JsonTypes = Array>; + +/* Type parameters */ +typedef JsonTypeParameter = { + var name:String; + var constraints:JsonTypes; +} + +typedef JsonTypeParameters = Array; + +/* Expr */ +enum abstract JsonBinopKind(String) { + var OpAdd; + var OpMult; + var OpDiv; + var OpSub; + var OpAssign; + var OpEq; + var OpNotEq; + var OpGt; + var OpGte; + var OpLt; + var OpLte; + var OpAnd; + var OpOr; + var OpXor; + var OpBoolAnd; + var OpBoolOr; + var OpShl; + var OpShr; + var OpUShr; + var OpMod; + var OpAssignOp:JsonBinopKind>; + var OpInterval; + var OpArrow; + var OpIn; +} + +typedef JsonBinop = { + var kind:JsonBinopKind; + var args:T; +} + +enum abstract JsonUnop(String) { + var OpIncrement; + var OpDecrement; + var OpNot; + var OpNeg; + var OpNegBits; +} + +typedef JsonExpr = JsonTodo; + +typedef JsonMetadataEntry = { + var name:String; + var args:Array; + var pos:JsonPos; +} + +typedef JsonMetadata = Array; + +enum abstract JsonTConstantKind(String) { + var TInt:JsonTConstantKind; + var TFloat:JsonTConstantKind; + var TString:JsonTConstantKind; + var TBool:JsonTConstantKind; + var TNull; + var TThis; + var TSuper; +} + +typedef JsonTConstant = { + var kind:JsonTConstantKind; + var args:T; +} + +typedef JsonTExpr = JsonTodo; + +/* Fields */ +enum abstract JsonVarAccessKind(String) { + var AccNormal; + var AccNo; + var AccNever; + var AccResolve; + var AccCall; + var AccInline; + var AccRequire:JsonVarAccessKind<{require:String, message:Null}>; + var AccCtor; +} + +typedef JsonVarAccess = { + var kind:JsonVarAccessKind; + var args:T; +} + +enum abstract JsonMethodKind(String) { + var MethNormal; + var MethInline; + var MethDynamic; + var MethMacro; +} + +enum abstract JsonFieldKindKind(String) { + var FVar:JsonFieldKindKind<{read:JsonVarAccess, write:JsonVarAccess}>; + var FMethod:JsonFieldKindKind; +} + +typedef JsonFieldKind = { + var kind:JsonFieldKindKind; + var args:T; +} + +enum abstract JsonClassFieldScope(Int) { + var Static; + var Member; + var Constructor; +} + +typedef JsonClassField = { + var name:String; + var type:JsonType; + var isPublic:Bool; + var isFinal:Bool; + var params:JsonTypeParameters; + var meta:JsonMetadata; + var kind:JsonFieldKind; + var ?expr:{ + var string:String; + }; + var pos:JsonPos; + var doc:JsonDoc; + var overloads:JsonClassFields; + var scope:JsonClassFieldScope; +} + +typedef JsonClassFields = Array; +typedef JsonClassFieldReference = String; + +typedef JsonEnumField = { + var name:String; + var type:JsonType; + var pos:JsonPos; + var meta:JsonMetadata; + var index:Int; + var doc:JsonDoc; + var params:JsonTypeParameters; +} + +typedef JsonEnumFields = Array; + +/* Class */ +enum abstract JsonClassKindKind(String) { + var KNormal; + var KTypeParameter:JsonClassKindKind; + var KExtension:JsonClassKindKind; + var KExpr:JsonClassKindKind; + var KGeneric; + var KGenericInstance:JsonClassKindKind; + var KMacroType; + var KAbstractImpl:JsonClassKindKind; + var KGenericBuild; +} + +typedef JsonClassKind = { + var kind:JsonClassKindKind; + var args:T; +} + +typedef JsonClass = { + var kind:JsonClassKind; + var isInterface:Bool; + var isExtern:Bool; + var superClass:Null; + var interfaces:Array; + var fields:JsonClassFields; + var statics:JsonClassFields; + var constructor:Null; + var init:Null; + var overrides:Array; +} + +/* Enum */ +typedef JsonEnum = { + var constructors:JsonEnumFields; + var isExtern:Bool; +} + +/* Typedef */ +typedef JsonTypedef = { + var type:JsonType; +} + +/* Abstract */ +typedef JsonAbstractBinop = { + var op:JsonBinop; + var field:JsonClassFieldReference; +} + +typedef JsonAbstractUnop = { + var op:JsonUnop; + var postFix:Bool; + var field:JsonClassFieldReference; +} + +typedef JsonAbstractCast = { + var t:JsonType; + var field:JsonClassFieldReference; +} + +typedef JsonAbstract = { + var type:JsonType; + var impl:Null; + var binops:Array; + var unops:Array; + var from:Array; + var to:Array; + var array:JsonClassFields; + var resolve:Null; +} + +/* Module type */ +enum abstract JsonModuleTypeKind(String) { + var Class:JsonModuleTypeKind = "class"; + var Enum:JsonModuleTypeKind = "enum"; + var Typedef:JsonModuleTypeKind = "typedef"; + var Abstract:JsonModuleTypeKind = "abstract"; +} + +typedef JsonModuleType = { + var pack:Array; + var name:String; + var moduleName:String; + var pos:JsonPos; + var isPrivate:Bool; + var params:JsonTypeParameters; + var meta:JsonMetadata; + var doc:JsonDoc; + var kind:JsonModuleTypeKind; + var args:T; +} + +typedef JsonModuleTypes = Array>; diff --git a/std/haxe/display/Position.hx b/std/haxe/display/Position.hx index ec7e0e22b59..31bae6fd4db 100644 --- a/std/haxe/display/Position.hx +++ b/std/haxe/display/Position.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,42 +19,43 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.display; /** - Position in a text document expressed as zero-based line and character offset. + Position in a text document expressed as 1-based line and character offset. **/ typedef Position = { - /** - Line position in a document (zero-based). - **/ - var line:Int; + /** + Line position in a document (1-based). + **/ + var line:Int; - /** - Character offset on a line in a document (zero-based). - **/ - var character:Int; + /** + Character offset on a line in a document (1-based). + **/ + var character:Int; } /** - A range in a text document expressed as (zero-based) start and end positions. + A range in a text document expressed as (1-based) start and end positions. **/ typedef Range = { - /** - The range's start position - **/ - var start:Position; + /** + The range's start position + **/ + var start:Position; - /** - The range's end position - **/ - var end:Position; + /** + The range's end position + **/ + var end:Position; } /** - Represents a location inside a resource, such as a line inside a text file. + Represents a location inside a resource, such as a line inside a text file. **/ typedef Location = { - var file:String; - var range:Range; -} \ No newline at end of file + var file:FsPath; + var range:Range; +} diff --git a/std/haxe/display/Protocol.hx b/std/haxe/display/Protocol.hx new file mode 100644 index 00000000000..99a27b57ba3 --- /dev/null +++ b/std/haxe/display/Protocol.hx @@ -0,0 +1,111 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.display; + +import haxe.display.Position; + +@:publicFields +class Methods { + /** + The initialize request is sent from the client to Haxe to determine the capabilities. + **/ + static inline var Initialize = new HaxeRequestMethod("initialize"); +} + +/* Initialize */ +typedef InitializeParams = { + final ?supportsResolve:Bool; + + /** dot paths to exclude from readClassPaths / toplevel completion **/ + final ?exclude:Array; + + /** The maximum number of completion items to return **/ + final ?maxCompletionItems:Int; +} + +/** + Represents a semantic version, see https://semver.org/. +**/ +typedef Version = { + final major:Int; + final minor:Int; + final patch:Int; + final pre:String; + final build:String; +} + +typedef InitializeResult = Response<{ + final protocolVersion:Version; + final haxeVersion:Version; + final methods:Array; +}>; + +/* general protocol types */ +typedef Timer = { + final name:String; + final time:Float; + final ?path:String; + final ?info:String; + final ?calls:Int; + final ?percentTotal:Float; + final ?percentParent:Float; + final ?children:Array; +} + +typedef Response = { + final ?result:T; + + /** UNIX timestamp at the moment the data was sent. **/ + final ?timestamp:Float; + + /** Only sent if `--times` is enabled. **/ + final ?timers:Timer; +} + +typedef FileParams = { + var file:FsPath; +} + +abstract HaxeRequestMethod(String) to String { + public inline function new(method:String) + this = method; +} + +abstract HaxeNotificationMethod(String) to String { + public inline function new(method:String) + this = method; +} + +typedef HaxeResponseErrorData = Array<{ + var severity:HaxeResponseErrorSeverity; + var ?location:Location; + var message:String; +}>; + +enum abstract HaxeResponseErrorSeverity(Int) { + var Error = 1; + var Warning; + var Hint; +} + +enum NoData {} diff --git a/std/haxe/display/Server.hx b/std/haxe/display/Server.hx new file mode 100644 index 00000000000..4648aa5d184 --- /dev/null +++ b/std/haxe/display/Server.hx @@ -0,0 +1,142 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.display; + +import haxe.display.JsonModuleTypes; +import haxe.display.Position; +import haxe.display.Protocol; + +@:publicFields +class ServerMethods { + /** + This request is sent from the client to Haxe to explore the class paths. This effectively creates a cache for toplevel completion. + **/ + static inline var ReadClassPaths = new HaxeRequestMethod>("server/readClassPaths"); + + static inline var Configure = new HaxeRequestMethod>("server/configure"); + static inline var Invalidate = new HaxeRequestMethod>("server/invalidate"); + static inline var Contexts = new HaxeRequestMethod>>("server/contexts"); + static inline var Memory = new HaxeRequestMethod>("server/memory"); + static inline var Modules = new HaxeRequestMethod>>("server/modules"); + static inline var Module = new HaxeRequestMethod>("server/module"); + static inline var Files = new HaxeRequestMethod>>("server/files"); + static inline var ModuleCreated = new HaxeRequestMethod>("server/moduleCreated"); +} + +/* Configure */ +typedef ConfigurePrintParams = { + var ?addedDirectory:Bool; + var ?foundDirectories:Bool; + var ?changedDirectories:Bool; + var ?modulePathChanged:Bool; + var ?notCached:Bool; + var ?parsed:Bool; + var ?removedDirectory:Bool; + var ?reusing:Bool; + var ?skippingDep:Bool; + var ?unchangedContent:Bool; + var ?cachedModules:Bool; + var ?arguments:Bool; + var ?completion:Bool; + var ?defines:Bool; + var ?signature:Bool; + var ?displayPosition:Bool; + var ?stats:Bool; + var ?message:Bool; + var ?socketMessage:Bool; + var ?uncaughtError:Bool; + var ?newContext:Bool; +} + +typedef ConfigureParams = { + final ?noModuleChecks:Bool; + final ?print:ConfigurePrintParams; +} + +/* Contexts */ +typedef HaxeServerContext = { + final index:Int; + final desc:String; + final signature:String; + final platform:String; + final classPaths:Array; + final defines:Array<{key:String, value:String}>; +} + +typedef ModuleId = { + final path:String; + final sign:String; +} + +typedef JsonModule = { + final id:Int; + final path:JsonModulePath; + final types:Array; + final file:String; + final sign:String; + final dependencies:Array; +} + +typedef JsonServerFile = { + final file:String; + final time:Float; + final pack:String; + final moduleName:Null; +} + +/* Memory */ +typedef HaxeMemoryResult = { + final contexts:Array<{ + final context:Null; + final size:Int; + final modules:Array; + }>; + final memory:{ + final totalCache:Int; + final haxelibCache:Int; + final parserCache:Int; + final moduleCache:Int; + final nativeLibCache:Int; + } +} + +typedef SizeResult = { + final path:String; + final size:Int; +} + +typedef ModuleTypeSizeResult = SizeResult & { + final fields:Array; +} + +typedef ModulesSizeResult = SizeResult & { + final types:Array; +} + +typedef ContextParams = { + final signature:String; +} + +typedef ModuleParams = ContextParams & { + final path:String; +} diff --git a/std/haxe/ds/ArraySort.hx b/std/haxe/ds/ArraySort.hx index eb425716df2..7467fdd3837 100644 --- a/std/haxe/ds/ArraySort.hx +++ b/std/haxe/ds/ArraySort.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,7 +28,6 @@ package haxe.ds; of equal elements has to be retained on all targets. **/ class ArraySort { - /** Sorts Array `a` according to the comparison function `cmp`, where `cmp(x,y)` returns 0 if `x == y`, a positive Int if `x > y` and a @@ -40,14 +39,15 @@ class ArraySort { If `a` or `cmp` are null, the result is unspecified. **/ - static public function sort(a:Array, cmp:T -> T -> Int) { + static public function sort(a:Array, cmp:T->T->Int) { rec(a, cmp, 0, a.length); } static function rec(a:Array, cmp, from, to) { var middle = (from + to) >> 1; if (to - from < 12) { - if (to <= from) return; + if (to <= from) + return; for (i in (from + 1)...to) { var j = i; while (j > from) { @@ -91,9 +91,10 @@ class ArraySort { doMerge(a, cmp, new_mid, second_cut, to, len1 - len11, len2 - len22); } - static function rotate(a:Array, cmp:T -> T -> Int, from, mid, to) { + static function rotate(a:Array, cmp:T->T->Int, from, mid, to) { var n; - if (from == mid || mid == to) return; + if (from == mid || mid == to) + return; n = gcd(to - from, mid - from); while (n-- != 0) { var val = a[from + n]; @@ -102,8 +103,10 @@ class ArraySort { while (p2 != from + n) { a[p1] = a[p2]; p1 = p2; - if (to - p2 > shift) p2 += shift; - else p2 = from + (shift - (to - p2)); + if (to - p2 > shift) + p2 += shift; + else + p2 = from + (shift - (to - p2)); } a[p1] = val; } @@ -153,7 +156,7 @@ class ArraySort { a[j] = tmp; } - static inline function compare(a:Array, cmp:T -> T -> Int, i, j) { + static inline function compare(a:Array, cmp:T->T->Int, i, j) { return cmp(a[i], a[j]); } -} \ No newline at end of file +} diff --git a/std/haxe/ds/BalancedTree.hx b/std/haxe/ds/BalancedTree.hx index c571f6fc4cc..3cfe640bf16 100644 --- a/std/haxe/ds/BalancedTree.hx +++ b/std/haxe/ds/BalancedTree.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,13 +32,13 @@ package haxe.ds; Iteration over keys and values, using `keys` and `iterator` respectively, are in-order. **/ -class BalancedTree implements haxe.Constraints.IMap { - var root:TreeNode; +class BalancedTree implements haxe.Constraints.IMap { + var root:TreeNode; /** Creates a new BalancedTree, which is initially empty. **/ - public function new() { } + public function new() {} /** Binds `key` to `value`. @@ -62,9 +62,12 @@ class BalancedTree implements haxe.Constraints.IMap { var node = root; while (node != null) { var c = compare(key, node.key); - if (c == 0) return node.value; - if (c < 0) node = node.left; - else node = node.right; + if (c == 0) + return node.value; + if (c < 0) + node = node.left; + else + node = node.right; } return null; } @@ -83,8 +86,7 @@ class BalancedTree implements haxe.Constraints.IMap { try { root = removeLoop(key, root); return true; - } - catch (e:String) { + } catch (e:String) { return false; } } @@ -100,9 +102,12 @@ class BalancedTree implements haxe.Constraints.IMap { var node = root; while (node != null) { var c = compare(key, node.key); - if (c == 0) return true; - else if (c < 0) node = node.left; - else node = node.right; + if (c == 0) + return true; + else if (c < 0) + node = node.left; + else + node = node.right; } return false; } @@ -118,6 +123,13 @@ class BalancedTree implements haxe.Constraints.IMap { return ret.iterator(); } + /** + See `Map.keyValueIterator` + **/ + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + /** Iterates over the keys of `this` BalancedTree. @@ -128,18 +140,18 @@ class BalancedTree implements haxe.Constraints.IMap { keysLoop(root, ret); return ret.iterator(); } - + public function copy():BalancedTree { var copied = new BalancedTree(); copied.root = root; return copied; } - function setLoop(k:K, v:V, node:TreeNode) { - if (node == null) return new TreeNode(null, k, v, null); + function setLoop(k:K, v:V, node:TreeNode) { + if (node == null) + return new TreeNode(null, k, v, null); var c = compare(k, node.key); - return if (c == 0) new TreeNode(node.left, k, v, node.right, node.get_height()); - else if (c < 0) { + return if (c == 0) new TreeNode(node.left, k, v, node.right, node.get_height()); else if (c < 0) { var nl = setLoop(k, v, node.left); balance(nl, node.key, node.value, node.right); } else { @@ -148,15 +160,16 @@ class BalancedTree implements haxe.Constraints.IMap { } } - function removeLoop(k:K, node:TreeNode) { - if (node == null) throw "Not_found"; + function removeLoop(k:K, node:TreeNode) { + if (node == null) + throw "Not_found"; var c = compare(k, node.key); - return if (c == 0) merge(node.left, node.right); - else if (c < 0) balance(removeLoop(k, node.left), node.key, node.value, node.right); - else balance(node.left, node.key, node.value, removeLoop(k, node.right)); + return if (c == 0) merge(node.left, + node.right); else if (c < 0) balance(removeLoop(k, node.left), node.key, node.value, + node.right); else balance(node.left, node.key, node.value, removeLoop(k, node.right)); } - function iteratorLoop(node:TreeNode, acc:Array) { + function iteratorLoop(node:TreeNode, acc:Array) { if (node != null) { iteratorLoop(node.left, acc); acc.push(node.value); @@ -164,7 +177,7 @@ class BalancedTree implements haxe.Constraints.IMap { } } - function keysLoop(node:TreeNode, acc:Array) { + function keysLoop(node:TreeNode, acc:Array) { if (node != null) { keysLoop(node.left, acc); acc.push(node.key); @@ -173,34 +186,39 @@ class BalancedTree implements haxe.Constraints.IMap { } function merge(t1, t2) { - if (t1 == null) return t2; - if (t2 == null) return t1; + if (t1 == null) + return t2; + if (t2 == null) + return t1; var t = minBinding(t2); return balance(t1, t.key, t.value, removeMinBinding(t2)); } - function minBinding(t:TreeNode) { - return if (t == null) throw "Not_found"; - else if (t.left == null) t; - else minBinding(t.left); + function minBinding(t:TreeNode) { + return if (t == null) throw "Not_found"; else if (t.left == null) t; else minBinding(t.left); } - function removeMinBinding(t:TreeNode) { - return if (t.left == null) t.right; - else balance(removeMinBinding(t.left), t.key, t.value, t.right); + function removeMinBinding(t:TreeNode) { + return if (t.left == null) t.right; else balance(removeMinBinding(t.left), t.key, t.value, t.right); } - function balance(l:TreeNode, k:K, v:V, r:TreeNode):TreeNode { + function balance(l:TreeNode, k:K, v:V, r:TreeNode):TreeNode { var hl = l.get_height(); var hr = r.get_height(); return if (hl > hr + 2) { - if (l.left.get_height() >= l.right.get_height()) new TreeNode(l.left, l.key, l.value, new TreeNode(l.right, k, v, r)); - else new TreeNode(new TreeNode(l.left,l.key, l.value, l.right.left), l.right.key, l.right.value, new TreeNode(l.right.right, k, v, r)); + if (l.left.get_height() >= l.right.get_height()) + new TreeNode(l.left, l.key, l.value, new TreeNode(l.right, k, v, r)); + else + new TreeNode(new TreeNode(l.left, l.key, l.value, l.right.left), l.right.key, l.right.value, + new TreeNode(l.right.right, k, v, r)); } else if (hr > hl + 2) { - if (r.right.get_height() > r.left.get_height()) new TreeNode(new TreeNode(l, k, v, r.left), r.key, r.value, r.right); - else new TreeNode(new TreeNode(l, k, v, r.left.left), r.left.key, r.left.value, new TreeNode(r.left.right, r.key, r.value, r.right)); + if (r.right.get_height() > r.left.get_height()) + new TreeNode(new TreeNode(l, k, v, r.left), r.key, r.value, r.right); + else + new TreeNode(new TreeNode(l, k, v, r.left.left), r.left.key, r.left.value, + new TreeNode(r.left.right, r.key, r.value, r.right)); } else { - new TreeNode(l, k, v, r, (hl > hr ? hl : hr) + 1); + new TreeNode(l, k, v, r, (hl > hr ? hl : hr) + 1); } } @@ -216,15 +234,16 @@ class BalancedTree implements haxe.Constraints.IMap { /** A tree node of `haxe.ds.BalancedTree`. **/ -class TreeNode { - public var left : TreeNode; - public var right : TreeNode; - public var key : K; - public var value : V; +class TreeNode { + public var left:TreeNode; + public var right:TreeNode; + public var key:K; + public var value:V; + #if as3 public #end - var _height : Int; + var _height:Int; public function new(l, k, v, r, h = -1) { left = l; @@ -237,9 +256,10 @@ class TreeNode { _height = h; } - @:extern public inline function get_height() return this == null ? 0 : _height; + extern public inline function get_height() + return this == null ? 0 : _height; public function toString() { - return (left == null ? "" : left.toString() + ", ") + '$key=$value' + (right == null ? "" : ", " +right.toString()); + return (left == null ? "" : left.toString() + ", ") + '$key=$value' + (right == null ? "" : ", " + right.toString()); } -} \ No newline at end of file +} diff --git a/std/haxe/ds/Either.hx b/std/haxe/ds/Either.hx index 3f405a230bb..24bf6f1c45e 100644 --- a/std/haxe/ds/Either.hx +++ b/std/haxe/ds/Either.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -29,4 +29,4 @@ package haxe.ds; enum Either { Left(v:L); Right(v:R); -} \ No newline at end of file +} diff --git a/std/haxe/ds/EnumValueMap.hx b/std/haxe/ds/EnumValueMap.hx index 32f031551c8..742e3c1228f 100644 --- a/std/haxe/ds/EnumValueMap.hx +++ b/std/haxe/ds/EnumValueMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,23 +28,26 @@ package haxe.ds; Keys are compared by value and recursively over their parameters. If any parameter is not an enum value, `Reflect.compare` is used to compare them. **/ -class EnumValueMap extends haxe.ds.BalancedTree implements haxe.Constraints.IMap { - +class EnumValueMap extends haxe.ds.BalancedTree implements haxe.Constraints.IMap { override function compare(k1:EnumValue, k2:EnumValue):Int { var d = k1.getIndex() - k2.getIndex(); - if (d != 0) return d; + if (d != 0) + return d; var p1 = k1.getParameters(); var p2 = k2.getParameters(); - if (p1.length == 0 && p2.length == 0) return 0; + if (p1.length == 0 && p2.length == 0) + return 0; return compareArgs(p1, p2); } function compareArgs(a1:Array, a2:Array):Int { var ld = a1.length - a2.length; - if (ld != 0) return ld; + if (ld != 0) + return ld; for (i in 0...a1.length) { var d = compareArg(a1[i], a2[i]); - if (d != 0) return d; + if (d != 0) + return d; } return 0; } @@ -58,4 +61,10 @@ class EnumValueMap extends haxe.ds.BalancedTree implements Reflect.compare(v1, v2); } } -} \ No newline at end of file + + override function copy():EnumValueMap { + var copied = new EnumValueMap(); + copied.root = root; + return copied; + } +} diff --git a/std/haxe/ds/GenericStack.hx b/std/haxe/ds/GenericStack.hx index c6444f02284..253b6f2ca1c 100644 --- a/std/haxe/ds/GenericStack.hx +++ b/std/haxe/ds/GenericStack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,43 +19,66 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; /** A cell of `haxe.ds.GenericStack`. - + @see https://haxe.org/manual/std-GenericStack.html **/ #if (flash || cpp) @:generic #end class GenericCell { - public var elt : T; - public var next : GenericCell; - public function new(elt,next) { this.elt = elt; this.next = next; } + public var elt:T; + public var next:GenericCell; + + public function new(elt, next) { + this.elt = elt; + this.next = next; + } } #if cpp @:generic #if cppia private class GenericStackIterator { - public var current : GenericCell; - public function hasNext():Bool { return current!=null; } - public function next():T { var result = current.elt; current = current.next; return result; } + public var current:GenericCell; + + public function hasNext():Bool { + return current != null; + } - public function new(head) { current = head; } + public function next():T { + var result = current.elt; + current = current.next; + return result; + } + + public function new(head) { + current = head; + } } #else private class GenericStackIterator extends cpp.FastIterator { - public var current : GenericCell; - override public function hasNext():Bool { return current!=null; } - override public function next():T { var result = current.elt; current = current.next; return result; } + public var current:GenericCell; - public function new(head) { current = head; } -} -#end + override public function hasNext():Bool { + return current != null; + } + override public function next():T { + var result = current.elt; + current = current.next; + return result; + } + public function new(head) { + current = head; + } +} +#end #end /** @@ -76,20 +99,18 @@ private class GenericStackIterator extends cpp.FastIterator { @:generic #end class GenericStack { - - public var head : GenericCell; + public var head:GenericCell; /** Creates a new empty GenericStack. **/ - public function new() { - } + public function new() {} /** Pushes element `item` onto the stack. **/ - public inline function add( item : T ) { - head = new GenericCell(item,head); + public inline function add(item:T) { + head = new GenericCell(item, head); } /** @@ -97,8 +118,8 @@ class GenericStack { If the stack is empty, null is returned. **/ - public inline function first() : Null { - return if( head == null ) null else head.elt; + public inline function first():Null { + return if (head == null) null else head.elt; } /** @@ -106,9 +127,9 @@ class GenericStack { If the stack is empty, null is returned. **/ - public inline function pop() : Null { + public inline function pop():Null { var k = head; - if( k== null ) + if (k == null) return null; else { head = k.next; @@ -119,7 +140,7 @@ class GenericStack { /** Tells if the stack is empty. **/ - public inline function isEmpty() : Bool { + public inline function isEmpty():Bool { return (head == null); } @@ -132,12 +153,12 @@ class GenericStack { If no matching element is found, false is returned. **/ - public function remove( v : T ) : Bool { + public function remove(v:T):Bool { var prev:GenericCell = null; var l = head; - while( l != null ) { - if( l.elt == v ) { - if( prev == null ) + while (l != null) { + if (l.elt == v) { + if (prev == null) head = l.next; else prev.next = l.next; @@ -150,33 +171,31 @@ class GenericStack { } #if cpp - /** Returns an iterator over the elements of `this` GenericStack. **/ - public function iterator() : Iterator { + public function iterator():Iterator { return new GenericStackIterator(head); } - #else /** Returns an iterator over the elements of `this` GenericStack. **/ - public function iterator() : Iterator { + public function iterator():Iterator { var l = head; return { - hasNext : function() { + hasNext: function() { return l != null; }, - next : function() { + next: function() { var k = l; l = k.next; return k.elt; } }; } - #end + #end /** Returns a String representation of `this` GenericStack. @@ -184,11 +203,10 @@ class GenericStack { public function toString() { var a = new Array(); var l = head; - while( l != null ) { + while (l != null) { a.push(l.elt); l = l.next; } - return "{"+a.join(",")+"}"; + return "{" + a.join(",") + "}"; } - } diff --git a/std/haxe/ds/HashMap.hx b/std/haxe/ds/HashMap.hx index 3db36c6c77f..a24531a1d9b 100644 --- a/std/haxe/ds/HashMap.hx +++ b/std/haxe/ds/HashMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; /** @@ -28,7 +29,7 @@ package haxe.ds; @see https://haxe.org/manual/std-Map.html **/ -abstract HashMap(HashMapData) { +abstract HashMap(HashMapData) { /** Creates a new HashMap. **/ @@ -72,11 +73,11 @@ abstract HashMap(HashMapData) { public inline function keys() { return this.keys.iterator(); } - + /** See `Map.copy` **/ - public function copy() : HashMap { + public function copy():HashMap { var copied = new HashMapData(); copied.keys = this.keys.copy(); copied.values = this.values.copy(); @@ -91,11 +92,12 @@ abstract HashMap(HashMapData) { } } -private class HashMapData { +private class HashMapData { public var keys:IntMap; public var values:IntMap; + public inline function new() { keys = new IntMap(); values = new IntMap(); } -} \ No newline at end of file +} diff --git a/std/haxe/ds/IntMap.hx b/std/haxe/ds/IntMap.hx index 36c1a545b0c..8a905c6dc1c 100644 --- a/std/haxe/ds/IntMap.hx +++ b/std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; /** @@ -28,51 +29,66 @@ package haxe.ds; @see https://haxe.org/manual/std-Map.html **/ -extern class IntMap implements haxe.Constraints.IMap { - +extern class IntMap implements haxe.Constraints.IMap { /** Creates a new IntMap. **/ - public function new() : Void; + public function new():Void; /** See `Map.set` **/ - public function set( key : Int, value : T ) : Void; + public function set(key:Int, value:T):Void; /** See `Map.get` **/ - public function get( key : Int ) : Null; + public function get(key:Int):Null; /** See `Map.exists` **/ - public function exists( key : Int ) : Bool; + public function exists(key:Int):Bool; /** See `Map.remove` **/ - public function remove( key : Int ) : Bool; + public function remove(key:Int):Bool; /** See `Map.keys` + + (cs, java) Implementation detail: Do not `set()` any new value while + iterating, as it may cause a resize, which will break iteration. **/ - public function keys() : Iterator; + public function keys():Iterator; /** See `Map.iterator` + + (cs, java) Implementation detail: Do not `set()` any new value while + iterating, as it may cause a resize, which will break iteration. **/ - public function iterator() : Iterator; + public function iterator():Iterator; + + /** + See `Map.keyValueIterator` + **/ + #if eval + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + #else + public function keyValueIterator():KeyValueIterator; + #end /** See `Map.copy` **/ - public function copy() : IntMap; - + public function copy():IntMap; + /** See `Map.toString` **/ - public function toString() : String; - + public function toString():String; } diff --git a/std/haxe/ds/List.hx b/std/haxe/ds/List.hx index 5596079921e..8920c93a5de 100644 --- a/std/haxe/ds/List.hx +++ b/std/haxe/ds/List.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; /** @@ -29,14 +30,13 @@ package haxe.ds; @see https://haxe.org/manual/std-List.html **/ class List { - - private var h : ListNode; - private var q : ListNode; + private var h:ListNode; + private var q:ListNode; /** The length of `this` List. **/ - public var length(default,null) : Int; + public var length(default, null):Int; /** Creates a new empty list. @@ -50,9 +50,9 @@ class List { `this.length` increases by 1. **/ - public function add( item : T ) { + public function add(item:T) { var x = ListNode.create(item, null); - if( h == null ) + if (h == null) h = x; else q.next = x; @@ -65,10 +65,10 @@ class List { `this.length` increases by 1. **/ - public function push( item : T ) { + public function push(item:T) { var x = ListNode.create(item, h); h = x; - if( q == null ) + if (q == null) q = x; length++; } @@ -78,8 +78,8 @@ class List { This function does not modify `this` List. **/ - public function first() : Null { - return if( h == null ) null else h.item; + public function first():Null { + return if (h == null) null else h.item; } /** @@ -87,22 +87,21 @@ class List { This function does not modify `this` List. **/ - public function last() : Null { - return if( q == null ) null else q.item; + public function last():Null { + return if (q == null) null else q.item; } - /** Returns the first element of `this` List, or null if no elements exist. The element is removed from `this` List. **/ - public function pop() : Null { - if( h == null ) + public function pop():Null { + if (h == null) return null; var x = h.item; h = h.next; - if( h == null ) + if (h == null) q = null; length--; return x; @@ -111,7 +110,7 @@ class List { /** Tells if `this` List is empty. **/ - public function isEmpty() : Bool { + public function isEmpty():Bool { return (h == null); } @@ -121,7 +120,7 @@ class List { This function does not traverse the elements, but simply sets the internal references to null and `this.length` to 0. **/ - public function clear() : Void { + public function clear():Void { h = null; q = null; length = 0; @@ -135,16 +134,16 @@ class List { Otherwise, false is returned. **/ - public function remove( v : T ) : Bool { + public function remove(v:T):Bool { var prev:ListNode = null; var l = h; - while( l != null ) { - if( l.item == v ) { - if( prev == null ) + while (l != null) { + if (l.item == v) { + if (prev == null) h = l.next; else prev.next = l.next; - if( q == l ) + if (q == l) q = prev; length--; return true; @@ -158,10 +157,17 @@ class List { /** Returns an iterator on the elements of the list. **/ - public inline function iterator() : ListIterator { + public inline function iterator():ListIterator { return new ListIterator(h); } + /** + Returns an iterator of the List indices and values. + **/ + @:pure @:runtime public inline function keyValueIterator():ListKeyValueIterator { + return new ListKeyValueIterator(h); + } + /** Returns a string representation of `this` List. @@ -173,8 +179,8 @@ class List { var first = true; var l = h; s.add("{"); - while( l != null ) { - if( first ) + while (l != null) { + if (first) first = false; else s.add(", "); @@ -189,12 +195,12 @@ class List { Returns a string representation of `this` List, with `sep` separating each element. **/ - public function join(sep : String) { + public function join(sep:String) { var s = new StringBuf(); var first = true; var l = h; - while( l != null ) { - if( first ) + while (l != null) { + if (first) first = false; else s.add(sep); @@ -208,13 +214,13 @@ class List { Returns a list filtered with `f`. The returned list will contain all elements for which `f(x) == true`. **/ - public function filter( f : T -> Bool ) { + public function filter(f:T->Bool) { var l2 = new List(); var l = h; - while( l != null ) { + while (l != null) { var v = l.item; l = l.next; - if( f(v) ) + if (f(v)) l2.add(v); } return l2; @@ -224,27 +230,30 @@ class List { Returns a new list where all elements have been converted by the function `f`. **/ - public function map(f : T -> X) : List { + public function map(f:T->X):List { var b = new List(); var l = h; - while( l != null ) { + while (l != null) { var v = l.item; l = l.next; b.add(f(v)); } return b; } - } #if neko private extern class ListNode extends neko.NativeArray { - var item(get,set):T; - var next(get,set):ListNode; - private inline function get_item():T return this[0]; - private inline function set_item(v:T):T return this[0] = v; - private inline function get_next():ListNode return this[1]; - private inline function set_next(v:ListNode):ListNode return this[1] = v; + var item(get, set):T; + var next(get, set):ListNode; + private inline function get_item():T + return this[0]; + private inline function set_item(v:T):T + return this[0] = v; + private inline function get_next():ListNode + return this[1]; + private inline function set_next(v:ListNode):ListNode + return this[1] = v; inline static function create(item:T, next:ListNode):ListNode { return untyped __dollar__array(item, next); } @@ -253,11 +262,13 @@ private extern class ListNode extends neko.NativeArray { private class ListNode { public var item:T; public var next:ListNode; + public function new(item:T, next:ListNode) { this.item = item; this.next = next; } - @:extern public inline static function create(item:T, next:ListNode):ListNode { + + extern public inline static function create(item:T, next:ListNode):ListNode { return new ListNode(item, next); } } @@ -280,3 +291,23 @@ private class ListIterator { return val; } } + +private class ListKeyValueIterator { + var idx:Int; + var head:ListNode; + + public inline function new(head:ListNode) { + this.head = head; + this.idx = 0; + } + + public inline function hasNext():Bool { + return head != null; + } + + public inline function next():{key:Int, value:T} { + var val = head.item; + head = head.next; + return {value: val, key: idx++}; + } +} diff --git a/std/haxe/ds/ListSort.hx b/std/haxe/ds/ListSort.hx index a1f76afa197..82710c746a7 100644 --- a/std/haxe/ds/ListSort.hx +++ b/std/haxe/ds/ListSort.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,7 +27,6 @@ package haxe.ds; method. It has a O(N.log(N)) complexity and does not require additional memory allocation. **/ class ListSort { - // Note : we prefer [inline] over [@:generic] here since we want to inline the comparison function as well /** @@ -40,33 +39,34 @@ class ListSort { If `list` or `cmp` are null, the result is unspecified. **/ - public static inline function sort(list:T, cmp : T -> T -> Int) : T { + public static inline function sort(list:T, cmp:T->T->Int):T { // ported from http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html - if( list == null ) + if (list == null) return null; var insize = 1, nmerges, psize = 0, qsize = 0; - var p, q, e, tail : T = null; - while( true ) { + var p, q, e, tail:T = null; + while (true) { p = list; list = null; tail = null; nmerges = 0; - while( p != null ) { + while (p != null) { nmerges++; q = p; psize = 0; - for( i in 0...insize ) { + for (i in 0...insize) { psize++; q = q.next; - if( q == null ) break; + if (q == null) + break; } qsize = insize; - while( psize > 0 || (qsize > 0 && q != null) ) { - if( psize == 0 ) { + while (psize > 0 || (qsize > 0 && q != null)) { + if (psize == 0) { e = q; q = q.next; qsize--; - } else if( qsize == 0 || q == null || cmp(p,q) <= 0 ) { + } else if (qsize == 0 || q == null || cmp(p, q) <= 0) { e = p; p = p.next; psize--; @@ -75,7 +75,7 @@ class ListSort { q = q.next; qsize--; } - if( tail != null ) + if (tail != null) tail.next = e; else list = e; @@ -85,7 +85,7 @@ class ListSort { p = q; } tail.next = null; - if( nmerges <= 1 ) + if (nmerges <= 1) break; insize *= 2; } @@ -93,36 +93,36 @@ class ListSort { return list; } - /** Same as `sort` but on single linked list. **/ - public static inline function sortSingleLinked(list:T, cmp : T -> T -> Int) : T { - if( list == null ) + public static inline function sortSingleLinked(list:T, cmp:T->T->Int):T { + if (list == null) return null; var insize = 1, nmerges, psize = 0, qsize = 0; - var p, q, e, tail : T; - while( true ) { + var p, q, e, tail:T; + while (true) { p = list; list = null; tail = null; nmerges = 0; - while( p != null ) { + while (p != null) { nmerges++; q = p; psize = 0; - for( i in 0...insize ) { + for (i in 0...insize) { psize++; q = q.next; - if( q == null ) break; + if (q == null) + break; } qsize = insize; - while( psize > 0 || (qsize > 0 && q != null) ) { - if( psize == 0 ) { + while (psize > 0 || (qsize > 0 && q != null)) { + if (psize == 0) { e = q; q = q.next; qsize--; - } else if( qsize == 0 || q == null || cmp(p,q) <= 0 ) { + } else if (qsize == 0 || q == null || cmp(p, q) <= 0) { e = p; p = p.next; psize--; @@ -131,7 +131,7 @@ class ListSort { q = q.next; qsize--; } - if( tail != null ) + if (tail != null) tail.next = e; else list = e; @@ -140,11 +140,10 @@ class ListSort { p = q; } tail.next = null; - if( nmerges <= 1 ) + if (nmerges <= 1) break; insize *= 2; } return list; } - -} \ No newline at end of file +} diff --git a/std/haxe/ds/Map.hx b/std/haxe/ds/Map.hx index 60914a4c72e..27dd6fdccfa 100644 --- a/std/haxe/ds/Map.hx +++ b/std/haxe/ds/Map.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -30,7 +30,7 @@ import haxe.ds.WeakMap; import haxe.ds.EnumValueMap; import haxe.Constraints.IMap; - /** +/** Map allows key to value mapping for arbitrary value types, and many key types. @@ -40,28 +40,27 @@ import haxe.Constraints.IMap; A Map can be instantiated without explicit type parameters. Type inference will then determine the type parameters from the usage. - Maps can also be created with `key1 => value1, key2 => value2` syntax. + Maps can also be created with `[key1 => value1, key2 => value2]` syntax. Map is an abstract type, it is not available at runtime. @see https://haxe.org/manual/std-Map.html **/ @:multiType(@:followWithAbstracts K) -abstract Map(IMap ) { - +abstract Map(IMap) { /** Creates a new Map. This becomes a constructor call to one of the specialization types in the output. The rules for that are as follows: - 1. if K is a `String`, `haxe.ds.StringMap` is used - 2. if K is an `Int`, `haxe.ds.IntMap` is used - 3. if K is an `EnumValue`, `haxe.ds.EnumValueMap` is used - 4. if K is any other class or structure, `haxe.ds.ObjectMap` is used - 5. if K is any other type, it causes a compile-time error + 1. if `K` is a `String`, `haxe.ds.StringMap` is used + 2. if `K` is an `Int`, `haxe.ds.IntMap` is used + 3. if `K` is an `EnumValue`, `haxe.ds.EnumValueMap` is used + 4. if `K` is any other class or structure, `haxe.ds.ObjectMap` is used + 5. if `K` is any other type, it causes a compile-time error - (Cpp) Map does not use weak keys on ObjectMap by default. + (Cpp) Map does not use weak keys on `ObjectMap` by default. **/ public function new(); @@ -70,14 +69,15 @@ abstract Map(IMap ) { If `key` already has a mapping, the previous value disappears. - If `key` is null, the result is unspecified. + If `key` is `null`, the result is unspecified. **/ - public inline function set(key:K, value:V) this.set(key, value); + public inline function set(key:K, value:V) + this.set(key, value); /** Returns the current mapping of `key`. - If no such mapping exists, null is returned. + If no such mapping exists, `null` is returned. Note that a check like `map.get(key) == null` can hold for two reasons: @@ -87,24 +87,27 @@ abstract Map(IMap ) { If it is important to distinguish these cases, `exists()` should be used. - If `key` is null, the result is unspecified. + If `key` is `null`, the result is unspecified. **/ - @:arrayAccess public inline function get(key:K) return this.get(key); + @:arrayAccess public inline function get(key:K) + return this.get(key); /** Returns true if `key` has a mapping, false otherwise. - If `key` is null, the result is unspecified. + If `key` is `null`, the result is unspecified. **/ - public inline function exists(key:K) return this.exists(key); + public inline function exists(key:K) + return this.exists(key); /** Removes the mapping of `key` and returns true if such a mapping existed, false otherwise. - If `key` is null, the result is unspecified. + If `key` is `null`, the result is unspecified. **/ - public inline function remove(key:K) return this.remove(key); + public inline function remove(key:K) + return this.remove(key); /** Returns an Iterator over the keys of `this` Map. @@ -124,12 +127,21 @@ abstract Map(IMap ) { return this.iterator(); } + /** + Returns an Iterator over the keys and values of `this` Map. + + The order of values is undefined. + **/ + public inline function keyValueIterator():KeyValueIterator { + return this.keyValueIterator(); + } + /** Returns a shallow copy of `this` map. The order of values is undefined. **/ - public inline function copy():Map { + public inline function copy():Map { return cast this.copy(); } @@ -147,31 +159,31 @@ abstract Map(IMap ) { return v; } - @:to static inline function toStringMap(t:IMap):StringMap { + @:to static inline function toStringMap(t:IMap):StringMap { return new StringMap(); } - @:to static inline function toIntMap(t:IMap):IntMap { + @:to static inline function toIntMap(t:IMap):IntMap { return new IntMap(); } - @:to static inline function toEnumValueMapMap(t:IMap):EnumValueMap { + @:to static inline function toEnumValueMapMap(t:IMap):EnumValueMap { return new EnumValueMap(); } - @:to static inline function toObjectMap(t:IMap):ObjectMap { + @:to static inline function toObjectMap(t:IMap):ObjectMap { return new ObjectMap(); } - @:from static inline function fromStringMap(map:StringMap):Map< String, V > { + @:from static inline function fromStringMap(map:StringMap):Map { return cast map; } - @:from static inline function fromIntMap(map:IntMap):Map< Int, V > { + @:from static inline function fromIntMap(map:IntMap):Map { return cast map; } - @:from static inline function fromObjectMap(map:ObjectMap):Map { + @:from static inline function fromObjectMap(map:ObjectMap):Map { return cast map; } -} \ No newline at end of file +} diff --git a/std/haxe/ds/ObjectMap.hx b/std/haxe/ds/ObjectMap.hx index 5cd11b8b686..115ffba86b0 100644 --- a/std/haxe/ds/ObjectMap.hx +++ b/std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package haxe.ds; @see https://haxe.org/manual/std-Map.html **/ -extern class ObjectMap < K: { }, V > implements haxe.Constraints.IMap { - +extern class ObjectMap implements haxe.Constraints.IMap { /** Creates a new ObjectMap. **/ @@ -61,21 +60,38 @@ extern class ObjectMap < K: { }, V > implements haxe.Constraints.IMap { /** See `Map.keys` + + (cs, java) Implementation detail: Do not `set()` any new value while + iterating, as it may cause a resize, which will break iteration. **/ public function keys():Iterator; /** See `Map.iterator` + + (cs, java) Implementation detail: Do not `set()` any new value while + iterating, as it may cause a resize, which will break iteration. **/ public function iterator():Iterator; - + + /** + See `Map.keyValueIterator` + **/ + #if eval + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + #else + public function keyValueIterator():KeyValueIterator; + #end + /** See `Map.copy` **/ - public function copy() : ObjectMap; + public function copy():ObjectMap; /** See `Map.toString` **/ public function toString():String; -} \ No newline at end of file +} diff --git a/std/haxe/ds/Option.hx b/std/haxe/ds/Option.hx index 69037fcda1c..060b5b6e59a 100644 --- a/std/haxe/ds/Option.hx +++ b/std/haxe/ds/Option.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,4 +31,4 @@ package haxe.ds; enum Option { Some(v:T); None; -} \ No newline at end of file +} diff --git a/std/haxe/ds/ReadOnlyArray.hx b/std/haxe/ds/ReadOnlyArray.hx new file mode 100644 index 00000000000..86197bc6e03 --- /dev/null +++ b/std/haxe/ds/ReadOnlyArray.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.ds; + +/** + `ReadOnlyArray` is an abstract over an ordinary `Array` which only exposes + APIs that don't modify the instance, hence "read-only". + + Note that this doesn't necessarily mean that the instance is *immutable*. + Other code holding a reference to the underlying `Array` can still modify it, + and the reference can be obtained with a `cast`. +**/ +@:forward(concat, copy, filter, indexOf, iterator, join, lastIndexOf, map, slice, toString) +abstract ReadOnlyArray(Array) from Array { + /** + The length of `this` Array. + **/ + public var length(get, never):Int; + + inline function get_length() + return this.length; + + @:arrayAccess inline function get(i:Int) + return this[i]; +} diff --git a/std/haxe/ds/StringMap.hx b/std/haxe/ds/StringMap.hx index f7109347da8..8be883257f7 100644 --- a/std/haxe/ds/StringMap.hx +++ b/std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -29,51 +29,66 @@ package haxe.ds; @see https://haxe.org/manual/std-Map.html **/ -extern class StringMap implements haxe.Constraints.IMap { - +extern class StringMap implements haxe.Constraints.IMap { /** Creates a new StringMap. **/ - public function new() : Void; + public function new():Void; /** See `Map.set` **/ - public function set( key : String, value : T ) : Void; + public function set(key:String, value:T):Void; /** See `Map.get` **/ - public function get( key : String ) : Null; + public function get(key:String):Null; /** See `Map.exists` **/ - public function exists( key : String ) : Bool; + public function exists(key:String):Bool; /** See `Map.remove` **/ - public function remove( key : String ) : Bool; + public function remove(key:String):Bool; /** See `Map.keys` + + (cs, java) Implementation detail: Do not `set()` any new value while + iterating, as it may cause a resize, which will break iteration. **/ - public function keys() : Iterator; + public function keys():Iterator; /** See `Map.iterator` + + (cs, java) Implementation detail: Do not `set()` any new value while + iterating, as it may cause a resize, which will break iteration. + **/ + public function iterator():Iterator; + + /** + See `Map.keyValueIterator` **/ - public function iterator() : Iterator; + #if eval + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + #else + public function keyValueIterator():KeyValueIterator; + #end /** See `Map.copy` **/ - public function copy() : StringMap; - + public function copy():StringMap; + /** See `Map.toString` **/ - public function toString() : String; - + public function toString():String; } diff --git a/std/haxe/ds/Vector.hx b/std/haxe/ds/Vector.hx index 3a38a95a737..50eff3a974b 100644 --- a/std/haxe/ds/Vector.hx +++ b/std/haxe/ds/Vector.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,27 +19,29 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; #if cpp using cpp.NativeArray; #end -private typedef VectorData = #if flash10 +private typedef VectorData = + #if flash10 flash.Vector -#elseif neko + #elseif neko neko.NativeArray -#elseif cs + #elseif cs cs.NativeArray -#elseif java + #elseif java java.NativeArray -#elseif lua - lua.Table -#elseif eval - eval.Vector -#else + #elseif lua + lua.Table + #elseif eval + eval.Vector + #else Array -#end + #end /** A Vector is a storage of fixed size. It can be faster than Array on some @@ -61,26 +63,26 @@ abstract Vector(VectorData) { **/ public inline function new(length:Int) { #if flash10 - this = new flash.Vector(length, true); + this = new flash.Vector(length, true); #elseif neko - this = untyped __dollar__amake(length); + this = untyped __dollar__amake(length); #elseif js - this = untyped __new__(Array, length); + this = js.Syntax.construct(Array, length); #elseif cs - this = new cs.NativeArray(length); + this = new cs.NativeArray(length); #elseif java - this = new java.NativeArray(length); + this = new java.NativeArray(length); #elseif cpp - this = NativeArray.create(length); + this = NativeArray.create(length); #elseif python - this = python.Syntax.pythonCode("[{0}]*{1}", null, length); + this = python.Syntax.code("[{0}]*{1}", null, length); #elseif lua - this = untyped __lua_table__({length:length}); + this = untyped __lua_table__({length: length}); #elseif eval - this = new eval.Vector(length); + this = new eval.Vector(length); #else - this = []; - untyped this.length = length; + this = []; + untyped this.length = length; #end } @@ -110,7 +112,7 @@ abstract Vector(VectorData) { **/ @:op([]) public inline function set(index:Int, val:T):T { #if cpp - return this.unsafeSet(index,val); + return this.unsafeSet(index, val); #elseif python return python.internal.ArrayImpl.unsafeSet(this, index, val); #elseif eval @@ -127,15 +129,15 @@ abstract Vector(VectorData) { inline function get_length():Int { #if neko - return untyped __dollar__asize(this); + return untyped __dollar__asize(this); #elseif cs - return this.Length; + return this.Length; #elseif java - return this.length; + return this.length; #elseif python - return this.length; + return this.length; #else - return untyped this.length; + return untyped this.length; #end } @@ -146,42 +148,41 @@ abstract Vector(VectorData) { The results are unspecified if `length` results in out-of-bounds access, or if `src` or `dest` are null **/ - public static #if (cs || java || neko || cpp || eval) inline #end function blit(src:Vector, srcPos:Int, dest:Vector, destPos:Int, len:Int):Void - { + public static #if (cs || java || neko || cpp || eval) inline #end function blit(src:Vector, srcPos:Int, dest:Vector, destPos:Int, len:Int):Void { #if neko - untyped __dollar__ablit(dest,destPos,src,srcPos,len); + untyped __dollar__ablit(dest, destPos, src, srcPos, len); #elseif java - java.lang.System.arraycopy(src, srcPos, dest, destPos, len); + java.lang.System.arraycopy(src, srcPos, dest, destPos, len); #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); + dest.toData().blit(destPos, src.toData(), srcPos, len); #elseif eval - src.toData().blit(srcPos, dest.toData(), destPos, len); + src.toData().blit(srcPos, dest.toData(), destPos, len); #else - if (src == dest) { - if (srcPos < destPos) { - var i = srcPos + len; - var j = destPos + len; - for (k in 0...len) { - i--; - j--; - src[j] = src[i]; - } - } else if (srcPos > destPos) { - var i = srcPos; - var j = destPos; - for (k in 0...len) { - src[j] = src[i]; - i++; - j++; - } + if (src == dest) { + if (srcPos < destPos) { + var i = srcPos + len; + var j = destPos + len; + for (k in 0...len) { + i--; + j--; + src[j] = src[i]; } - } else { - for (i in 0...len) { - dest[destPos + i] = src[srcPos + i]; + } else if (srcPos > destPos) { + var i = srcPos; + var j = destPos; + for (k in 0...len) { + src[j] = src[i]; + i++; + j++; } } + } else { + for (i in 0...len) { + dest[destPos + i] = src[srcPos + i]; + } + } #end } @@ -190,23 +191,24 @@ abstract Vector(VectorData) { **/ public #if (flash || cpp || js || java || eval) inline #end function toArray():Array { #if cpp - return this.copy(); + return this.copy(); #elseif python - return this.copy(); + return this.copy(); #elseif js - return this.slice(0); + return this.slice(0); #elseif eval - return this.toArray(); + return this.toArray(); #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; + 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 } @@ -239,16 +241,18 @@ abstract Vector(VectorData) { If `array` is null, the result is unspecified. **/ - #if as3 @:extern #end + #if as3 + extern + #end static public inline function fromArrayCopy(array:Array):Vector { #if python return cast array.copy(); #elseif flash10 return fromData(flash.Vector.ofArray(array)); #elseif java - return fromData(java.Lib.nativeArray(array,false)); + return fromData(java.Lib.nativeArray(array, false)); #elseif cs - return fromData(cs.Lib.nativeArray(array,false)); + return fromData(cs.Lib.nativeArray(array, false)); #elseif cpp return cast array.copy(); #elseif js @@ -271,7 +275,7 @@ abstract Vector(VectorData) { `a[i] == a.copy()[i]` is true for any valid `i`. However, `a == a.copy()` is always false. **/ - #if cs @:extern #end public inline function copy():Vector { + #if cs extern #end public inline function copy():Vector { #if eval return fromData(this.copy()); #else @@ -294,16 +298,15 @@ abstract Vector(VectorData) { If `sep` is null, the result is unspecified. **/ - #if cs @:extern #end public inline function join(sep:String):String { + #if cs extern #end public inline function join(sep:String):String { #if (flash10 || cpp || eval) return this.join(sep); #else var b = new StringBuf(); - var i = 0; var len = length; - for(i in 0...len) { - b.add( Std.string(get(i)) ); - if(i < len-1) { + for (i in 0...len) { + b.add(Std.string(get(i))); + if (i < len - 1) { b.add(sep); } } @@ -318,15 +321,14 @@ abstract Vector(VectorData) { If `f` is null, the result is unspecified. **/ - #if cs @:extern #end public inline function map(f:T->S):Vector { + #if cs extern #end public inline function map(f:T->S):Vector { #if eval - return fromData(this.map(f)); + return fromData(this.map(f)); #else var length = length; var r = new Vector(length); - var i = 0; var len = length; - for(i in 0...len) { + for (i in 0...len) { var v = f(get(i)); r.set(i, v); } diff --git a/std/haxe/ds/WeakMap.hx b/std/haxe/ds/WeakMap.hx index 7971abac1c6..d2de997b5aa 100644 --- a/std/haxe/ds/WeakMap.hx +++ b/std/haxe/ds/WeakMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,8 +31,7 @@ package haxe.ds; @see https://haxe.org/manual/std-Map.html **/ -class WeakMap implements haxe.Constraints.IMap { - +class WeakMap implements haxe.Constraints.IMap { /** Creates a new WeakMap. **/ @@ -43,8 +42,7 @@ class WeakMap implements haxe.Constraints.IMap { /** See `Map.set` **/ - public function set(key:K, value:V):Void { - } + public function set(key:K, value:V):Void {} /** See `Map.get` @@ -80,11 +78,18 @@ class WeakMap implements haxe.Constraints.IMap { public function iterator():Iterator { return null; } - + + /** + See `Map.keyValueIterator` + **/ + public inline function keyValueIterator():KeyValueIterator { + return null; + } + /** See `Map.copy` **/ - public function copy() : WeakMap { + public function copy():WeakMap { return null; } @@ -94,4 +99,4 @@ class WeakMap implements haxe.Constraints.IMap { public function toString():String { return null; } -} \ No newline at end of file +} diff --git a/std/haxe/extern/AsVar.hx b/std/haxe/extern/AsVar.hx index 3e95a1c5807..c4990764efe 100644 --- a/std/haxe/extern/AsVar.hx +++ b/std/haxe/extern/AsVar.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,5 +27,5 @@ package haxe.extern; argument expressions are bound to a local variable. **/ @:forward -@:analyzer(as_var) -abstract AsVar(T) from T to T {} \ No newline at end of file +@:semantics(variable) +abstract AsVar(T) from T to T {} diff --git a/std/haxe/extern/EitherType.hx b/std/haxe/extern/EitherType.hx index 264bb1b4b4e..5b57b77f622 100644 --- a/std/haxe/extern/EitherType.hx +++ b/std/haxe/extern/EitherType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.extern; /** @@ -29,7 +30,7 @@ package haxe.extern; such as JavaScript or Python. Otherwise, use of this type is discouraged. - + @see **/ -abstract EitherType(Dynamic) from T1 to T1 from T2 to T2 {} +abstract EitherType(Dynamic) from T1 to T1 from T2 to T2 {} diff --git a/std/haxe/extern/Rest.hx b/std/haxe/extern/Rest.hx index f15328a8608..2aba9b22343 100644 --- a/std/haxe/extern/Rest.hx +++ b/std/haxe/extern/Rest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,7 +28,7 @@ package haxe.extern; Should be used as a type for the last argument of an extern method, representing that arbitrary number of arguments of given type can be passed to that method. - + @see **/ abstract Rest(Array) {} diff --git a/std/haxe/format/JsonParser.hx b/std/haxe/format/JsonParser.hx index 55b0ad86522..e01b5c7c59f 100644 --- a/std/haxe/format/JsonParser.hx +++ b/std/haxe/format/JsonParser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.format; /** @@ -30,7 +31,6 @@ package haxe.format; @see https://haxe.org/manual/std-Json-parsing.html **/ class JsonParser { - /** Parses given JSON-encoded `str` and returns the resulting object. @@ -41,217 +41,280 @@ class JsonParser { If `str` is null, the result is unspecified. **/ - static public inline function parse(str : String) : Dynamic { - return new JsonParser(str).parseRec(); + static public inline function parse(str:String):Dynamic { + return new JsonParser(str).doParse(); } - var str : String; - var pos : Int; + var str:String; + var pos:Int; - function new( str : String ) { + function new(str:String) { this.str = str; this.pos = 0; } - function parseRec() : Dynamic { - while( true ) { + function doParse():Dynamic { + var result = parseRec(); + var c; + while (!StringTools.isEof(c = nextChar())) { + switch (c) { + case ' '.code, '\r'.code, '\n'.code, '\t'.code: + // allow trailing whitespace + default: + invalidChar(); + } + } + return result; + } + + function parseRec():Dynamic { + while (true) { var c = nextChar(); - switch( c ) { - case ' '.code, '\r'.code, '\n'.code, '\t'.code: + switch (c) { + case ' '.code, '\r'.code, '\n'.code, '\t'.code: // loop - case '{'.code: - var obj = {}, field = null, comma : Null = null; - while( true ) { - var c = nextChar(); - switch( c ) { - case ' '.code, '\r'.code, '\n'.code, '\t'.code: - // loop - case '}'.code: - if( field != null || comma == false ) - invalidChar(); - return obj; - case ':'.code: - if( field == null ) - invalidChar(); - Reflect.setField(obj,field,parseRec()); - field = null; - comma = true; - case ','.code: - if( comma ) comma = false else invalidChar(); - case '"'.code: - if( field != null || comma ) invalidChar(); - field = parseString(); - default: + case '{'.code: + var obj = {}, field = null, comma:Null = null; + while (true) { + var c = nextChar(); + switch (c) { + case ' '.code, '\r'.code, '\n'.code, '\t'.code: + // loop + case '}'.code: + if (field != null || comma == false) + invalidChar(); + return obj; + case ':'.code: + if (field == null) + invalidChar(); + Reflect.setField(obj, field, parseRec()); + field = null; + comma = true; + case ','.code: + if (comma) comma = false else invalidChar(); + case '"'.code: + if (field != null || comma) invalidChar(); + field = parseString(); + default: + invalidChar(); + } + } + case '['.code: + var arr = [], comma:Null = null; + while (true) { + var c = nextChar(); + switch (c) { + case ' '.code, '\r'.code, '\n'.code, '\t'.code: + // loop + case ']'.code: + if (comma == false) invalidChar(); + return arr; + case ','.code: + if (comma) comma = false else invalidChar(); + default: + if (comma) invalidChar(); + pos--; + arr.push(parseRec()); + comma = true; + } + } + case 't'.code: + var save = pos; + if (nextChar() != 'r'.code || nextChar() != 'u'.code || nextChar() != 'e'.code) { + pos = save; invalidChar(); } - } - case '['.code: - var arr = [], comma : Null = null; - while( true ) { - var c = nextChar(); - switch( c ) { - case ' '.code, '\r'.code, '\n'.code, '\t'.code: - // loop - case ']'.code: - if( comma == false ) invalidChar(); - return arr; - case ','.code: - if( comma ) comma = false else invalidChar(); - default: - if( comma ) invalidChar(); - pos--; - arr.push(parseRec()); - comma = true; + return true; + case 'f'.code: + var save = pos; + if (nextChar() != 'a'.code || nextChar() != 'l'.code || nextChar() != 's'.code || nextChar() != 'e'.code) { + pos = save; + invalidChar(); } - } - case 't'.code: - var save = pos; - if( nextChar() != 'r'.code || nextChar() != 'u'.code || nextChar() != 'e'.code ) { - pos = save; - invalidChar(); - } - return true; - case 'f'.code: - var save = pos; - if( nextChar() != 'a'.code || nextChar() != 'l'.code || nextChar() != 's'.code || nextChar() != 'e'.code ) { - pos = save; - invalidChar(); - } - return false; - case 'n'.code: - var save = pos; - if( nextChar() != 'u'.code || nextChar() != 'l'.code || nextChar() != 'l'.code ) { - pos = save; + return false; + case 'n'.code: + var save = pos; + if (nextChar() != 'u'.code || nextChar() != 'l'.code || nextChar() != 'l'.code) { + pos = save; + invalidChar(); + } + return null; + case '"'.code: + return parseString(); + case '0'.code, '1'.code, '2'.code, '3'.code, '4'.code, '5'.code, '6'.code, '7'.code, '8'.code, '9'.code, '-'.code: + return parseNumber(c); + default: invalidChar(); - } - return null; - case '"'.code: - return parseString(); - case '0'.code, '1'.code,'2'.code,'3'.code,'4'.code,'5'.code,'6'.code,'7'.code,'8'.code,'9'.code,'-'.code: - return parseNumber(c); - default: - invalidChar(); } } } function parseString() { var start = pos; - var buf = null; - while( true ) { + var buf:StringBuf = null; + #if target.unicode + var prev = -1; + inline function cancelSurrogate() { + // invalid high surrogate (not followed by low surrogate) + buf.addChar(0xFFFD); + prev = -1; + } + #end + while (true) { var c = nextChar(); - if( c == '"'.code ) + if (c == '"'.code) break; - if( c == '\\'.code ) { + if (c == '\\'.code) { if (buf == null) { buf = new StringBuf(); } - buf.addSub(str,start, pos - start - 1); + buf.addSub(str, start, pos - start - 1); c = nextChar(); - switch( c ) { - case "r".code: buf.addChar("\r".code); - case "n".code: buf.addChar("\n".code); - case "t".code: buf.addChar("\t".code); - case "b".code: buf.addChar(8); - case "f".code: buf.addChar(12); - case "/".code, '\\'.code, '"'.code: buf.addChar(c); - case 'u'.code: - var uc = Std.parseInt("0x" + str.substr(pos, 4)); - pos += 4; - #if (neko || php || cpp || lua || eval) - if( uc <= 0x7F ) - buf.addChar(uc); - else if( uc <= 0x7FF ) { - buf.addChar(0xC0 | (uc >> 6)); - buf.addChar(0x80 | (uc & 63)); - } else if( uc <= 0xFFFF ) { - buf.addChar(0xE0 | (uc >> 12)); - buf.addChar(0x80 | ((uc >> 6) & 63)); - buf.addChar(0x80 | (uc & 63)); - } else { - buf.addChar(0xF0 | (uc >> 18)); - buf.addChar(0x80 | ((uc >> 12) & 63)); - buf.addChar(0x80 | ((uc >> 6) & 63)); - buf.addChar(0x80 | (uc & 63)); - } - #else - buf.addChar(uc); - #end - default: - throw "Invalid escape sequence \\" + String.fromCharCode(c) + " at position " + (pos - 1); + #if target.unicode + if (c != "u".code && prev != -1) + cancelSurrogate(); + #end + switch (c) { + case "r".code: + buf.addChar("\r".code); + case "n".code: + buf.addChar("\n".code); + case "t".code: + buf.addChar("\t".code); + case "b".code: + buf.addChar(8); + case "f".code: + buf.addChar(12); + case "/".code, '\\'.code, '"'.code: + buf.addChar(c); + case 'u'.code: + var uc:Int = Std.parseInt("0x" + str.substr(pos, 4)); + pos += 4; + #if !target.unicode + if (uc <= 0x7F) + buf.addChar(uc); + else if (uc <= 0x7FF) { + buf.addChar(0xC0 | (uc >> 6)); + buf.addChar(0x80 | (uc & 63)); + } else if (uc <= 0xFFFF) { + buf.addChar(0xE0 | (uc >> 12)); + buf.addChar(0x80 | ((uc >> 6) & 63)); + buf.addChar(0x80 | (uc & 63)); + } else { + buf.addChar(0xF0 | (uc >> 18)); + buf.addChar(0x80 | ((uc >> 12) & 63)); + buf.addChar(0x80 | ((uc >> 6) & 63)); + buf.addChar(0x80 | (uc & 63)); + } + #else + if (prev != -1) { + if (uc < 0xDC00 || uc > 0xDFFF) + cancelSurrogate(); + else { + buf.addChar(((prev - 0xD800) << 10) + (uc - 0xDC00) + 0x10000); + prev = -1; + } + } else if (uc >= 0xD800 && uc <= 0xDBFF) + prev = uc; + else + buf.addChar(uc); + #end + default: + throw "Invalid escape sequence \\" + String.fromCharCode(c) + " at position " + (pos - 1); } start = pos; } - #if (neko || php || cpp) + #if !(target.unicode) // ensure utf8 chars are not cut - else if( c >= 0x80 ) { + else if (c >= 0x80) { pos++; - if( c >= 0xFC ) pos += 4; - else if( c >= 0xF8 ) pos += 3; - else if( c >= 0xF0 ) pos += 2; - else if( c >= 0xE0 ) pos++; + if (c >= 0xFC) + pos += 4; + else if (c >= 0xF8) + pos += 3; + else if (c >= 0xF0) + pos += 2; + else if (c >= 0xE0) + pos++; } #end - else if( StringTools.isEof(c) ) - throw "Unclosed string"; + else if (StringTools.isEof(c)) + throw "Unclosed string"; } + #if target.unicode + if (prev != -1) + cancelSurrogate(); + #end if (buf == null) { return str.substr(start, pos - start - 1); - } - else { - buf.addSub(str,start, pos - start - 1); + } else { + buf.addSub(str, start, pos - start - 1); return buf.toString(); } } - inline function parseNumber( c : Int ) : Dynamic { + inline function parseNumber(c:Int):Dynamic { var start = pos - 1; var minus = c == '-'.code, digit = !minus, zero = c == '0'.code; var point = false, e = false, pm = false, end = false; - while( true ) { + while (true) { c = nextChar(); - switch( c ) { - case '0'.code : - if (zero && !point) invalidNumber(start); + switch (c) { + case '0'.code: + if (zero && !point) + invalidNumber(start); if (minus) { - minus = false; zero = true; + minus = false; + zero = true; } digit = true; - case '1'.code,'2'.code,'3'.code,'4'.code,'5'.code,'6'.code,'7'.code,'8'.code,'9'.code : - if (zero && !point) invalidNumber(start); - if (minus) minus = false; - digit = true; zero = false; - case '.'.code : - if (minus || point) invalidNumber(start); - digit = false; point = true; - case 'e'.code, 'E'.code : - if (minus || zero || e) invalidNumber(start); - digit = false; e = true; - case '+'.code, '-'.code : - if (!e || pm) invalidNumber(start); - digit = false; pm = true; - default : - if (!digit) invalidNumber(start); + case '1'.code, '2'.code, '3'.code, '4'.code, '5'.code, '6'.code, '7'.code, '8'.code, '9'.code: + if (zero && !point) + invalidNumber(start); + if (minus) + minus = false; + digit = true; + zero = false; + case '.'.code: + if (minus || point || e) + invalidNumber(start); + digit = false; + point = true; + case 'e'.code, 'E'.code: + if (minus || zero || e) + invalidNumber(start); + digit = false; + e = true; + case '+'.code, '-'.code: + if (!e || pm) + invalidNumber(start); + digit = false; + pm = true; + default: + if (!digit) + invalidNumber(start); pos--; end = true; } - if (end) break; + if (end) + break; } + var f = Std.parseFloat(str.substr(start, pos - start)); var i = Std.int(f); - return if( i == f ) i else f; + return if (i == f) i else f; } inline function nextChar() { - return StringTools.fastCodeAt(str,pos++); + return StringTools.fastCodeAt(str, pos++); } function invalidChar() { pos--; // rewind - throw "Invalid char "+StringTools.fastCodeAt(str,pos)+" at position "+pos; + throw "Invalid char " + StringTools.fastCodeAt(str, pos) + " at position " + pos; } - function invalidNumber( start : Int ) { - throw "Invalid number at position "+start+": " + str.substr(start, pos - start); + function invalidNumber(start:Int) { + throw "Invalid number at position " + start + ": " + str.substr(start, pos - start); } } diff --git a/std/haxe/format/JsonPrinter.hx b/std/haxe/format/JsonPrinter.hx index 38a4e9b471a..093b037754d 100644 --- a/std/haxe/format/JsonPrinter.hx +++ b/std/haxe/format/JsonPrinter.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.format; /** @@ -30,7 +31,6 @@ package haxe.format; @see https://haxe.org/manual/std-Json-encoding.html **/ class JsonPrinter { - /** Encodes `o`'s value and returns the resulting JSON string. @@ -41,19 +41,19 @@ class JsonPrinter { If `space` is given and is not null, the result will be pretty-printed. Successive levels will be indented by this string. **/ - static public function print(o:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String) : String { + static public function print(o:Dynamic, ?replacer:(key:Dynamic, value:Dynamic) -> Dynamic, ?space:String):String { var printer = new JsonPrinter(replacer, space); printer.write("", o); return printer.buf.toString(); } - var buf : #if flash flash.utils.ByteArray #else StringBuf #end; - var replacer : Dynamic -> Dynamic -> Dynamic; + var buf:#if flash flash.utils.ByteArray #else StringBuf #end; + var replacer:(key:Dynamic, value:Dynamic) -> Dynamic; var indent:String; var pretty:Bool; var nind:Int; - function new(replacer:Dynamic -> Dynamic -> Dynamic, space:String) { + function new(replacer:(key:Dynamic, value:Dynamic) -> Dynamic, space:String) { this.replacer = replacer; this.indent = space; this.pretty = space != null; @@ -68,76 +68,76 @@ class JsonPrinter { #end } - inline function ipad ():Void { - if (pretty) add(StringTools.lpad('', indent, nind * indent.length)); + inline function ipad():Void { + if (pretty) + add(StringTools.lpad('', indent, nind * indent.length)); } - inline function newl ():Void { - if (pretty) addChar('\n'.code); + inline function newl():Void { + if (pretty) + addChar('\n'.code); } function write(k:Dynamic, v:Dynamic) { - if (replacer != null) v = replacer(k, v); - switch( Type.typeof(v) ) { - case TUnknown: - add('"???"'); - case TObject: - objString(v); - case TInt: - add(#if as3 Std.string(v) #else v #end); - case TFloat: - add(Math.isFinite(v) ? v : 'null'); - case TFunction: - add('""'); - case TClass(c): - if( c == String ) - quote(v); - else if( c == Array ) { - var v : Array = v; - addChar('['.code); - - var len = v.length; - 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--; + if (replacer != null) + v = replacer(k, v); + switch (Type.typeof(v)) { + case TUnknown: + add('"???"'); + case TObject: + objString(v); + case TInt: + add(#if (as3 || jvm) Std.string(v) #else v #end); + case TFloat: + add(Math.isFinite(v) ? Std.string(v) : 'null'); + case TFunction: + add('""'); + case TClass(c): + if (c == String) + quote(v); + else if (c == Array) { + var v:Array = v; + addChar('['.code); + + var len = v.length; + 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); - } else if( c == haxe.ds.StringMap ) { - var v : haxe.ds.StringMap = v; - var o = {}; - for( k in v.keys() ) - Reflect.setField(o,k,v.get(k)); - objString(o); - } else if( c == Date ) { - var v : Date = v; - quote(v.toString()); - } else - #if flash - classString(v); - #else - objString(v); - #end - case TEnum(_): - var i : Dynamic = Type.enumIndex(v); - add(i); - case TBool: - add(#if (php || as3) (v ? 'true' : 'false') #else v #end); - case TNull: - add('null'); + addChar(']'.code); + } else if (c == haxe.ds.StringMap) { + var v:haxe.ds.StringMap = v; + var o = {}; + for (k in v.keys()) + Reflect.setField(o, k, v.get(k)); + objString(o); + } else if (c == Date) { + var v:Date = v; + quote(v.toString()); + } else + classString(v); + case TEnum(_): + var i:Dynamic = Type.enumIndex(v); + add(i); + case TBool: + add(#if (php || as3 || jvm) (v ? 'true' : 'false') #else v #end); + case TNull: + add('null'); } } - @:extern inline function addChar(c:Int) { + extern inline function addChar(c:Int) { #if flash buf.writeByte(c); #else @@ -145,7 +145,7 @@ class JsonPrinter { #end } - @:extern inline function add(v:String) { + extern inline function add(v:String) { #if flash // argument is not always a string but will be automatically casted buf.writeUTFBytes(v); @@ -154,34 +154,37 @@ class JsonPrinter { #end } - #if flash - function classString ( v : Dynamic ) { - fieldsString(v,Type.getInstanceFields(Type.getClass(v))); + function classString(v:Dynamic) { + fieldsString(v, Type.getInstanceFields(Type.getClass(v))); } - #end - inline function objString( v : Dynamic ) { - fieldsString(v,Reflect.fields(v)); + inline function objString(v:Dynamic) { + fieldsString(v, Reflect.fields(v)); } - function fieldsString( v : Dynamic, fields : Array ) { + function fieldsString(v:Dynamic, fields:Array) { addChar('{'.code); var len = fields.length; var last = len - 1; var first = true; - for( i in 0...len ) { + for (i in 0...len) { var f = fields[i]; - var value = Reflect.field(v,f); - if( Reflect.isFunction(value) ) continue; - if( first ) { nind++; first = false; } else addChar(','.code); + var value = Reflect.field(v, f); + if (Reflect.isFunction(value)) + continue; + if (first) { + nind++; + first = false; + } else + addChar(','.code); newl(); ipad(); quote(f); addChar(':'.code); - if (pretty) addChar(' '.code); + if (pretty) + addChar(' '.code); write(f, value); - if (i == last) - { + if (i == last) { nind--; newl(); ipad(); @@ -190,49 +193,95 @@ class JsonPrinter { addChar('}'.code); } - function quote( s : String ) { - #if (neko || php || cpp) - if( s.length != haxe.Utf8.length(s) ) { + function quote(s:String) { + #if neko + if (s.length != neko.Utf8.length(s)) { quoteUtf8(s); return; } #end addChar('"'.code); var i = 0; - while( true ) { + #if hl + var prev = -1; + #end + while (true) { var c = StringTools.fastCodeAt(s, i++); - if( StringTools.isEof(c) ) break; - switch( c ) { - case '"'.code: add('\\"'); - case '\\'.code: add('\\\\'); - case '\n'.code: add('\\n'); - case '\r'.code: add('\\r'); - case '\t'.code: add('\\t'); - case 8: add('\\b'); - case 12: add('\\f'); - default: - #if flash - if( c >= 128 ) add(String.fromCharCode(c)) else addChar(c); - #else - addChar(c); - #end + if (StringTools.isEof(c)) + break; + switch (c) { + case '"'.code: + add('\\"'); + case '\\'.code: + add('\\\\'); + case '\n'.code: + add('\\n'); + case '\r'.code: + add('\\r'); + case '\t'.code: + add('\\t'); + case 8: + add('\\b'); + case 12: + add('\\f'); + default: + #if flash + if (c >= 128) + add(String.fromCharCode(c)) + else + addChar(c); + #elseif hl + if (prev >= 0) { + if (c >= 0xD800 && c <= 0xDFFF) { + addChar((((prev - 0xD800) << 10) | (c - 0xDC00)) + 0x10000); + prev = -1; + } else { + addChar("□".code); + prev = c; + } + } else { + if (c >= 0xD800 && c <= 0xDFFF) + prev = c; + else + addChar(c); + } + #else + addChar(c); + #end } } + #if hl + if (prev >= 0) + addChar("□".code); + #end addChar('"'.code); } - #if (neko || php || cpp) - function quoteUtf8( s : String ) { - var u = new haxe.Utf8(); - haxe.Utf8.iter(s,function(c) { - switch( c ) { - case '\\'.code, '"'.code: u.addChar('\\'.code); u.addChar(c); - case '\n'.code: u.addChar('\\'.code); u.addChar('n'.code); - case '\r'.code: u.addChar('\\'.code); u.addChar('r'.code); - case '\t'.code: u.addChar('\\'.code); u.addChar('t'.code); - case 8: u.addChar('\\'.code); u.addChar('b'.code); - case 12: u.addChar('\\'.code); u.addChar('f'.code); - default: u.addChar(c); + #if neko + function quoteUtf8(s:String) { + var u = new neko.Utf8(); + neko.Utf8.iter(s, function(c) { + switch (c) { + case '\\'.code, '"'.code: + u.addChar('\\'.code); + u.addChar(c); + case '\n'.code: + u.addChar('\\'.code); + u.addChar('n'.code); + case '\r'.code: + u.addChar('\\'.code); + u.addChar('r'.code); + case '\t'.code: + u.addChar('\\'.code); + u.addChar('t'.code); + case 8: + u.addChar('\\'.code); + u.addChar('b'.code); + case 12: + u.addChar('\\'.code); + u.addChar('f'.code); + default: + u.addChar(c); } }); buf.add('"'); diff --git a/std/haxe/http/HttpBase.hx b/std/haxe/http/HttpBase.hx new file mode 100644 index 00000000000..899bc1663f4 --- /dev/null +++ b/std/haxe/http/HttpBase.hx @@ -0,0 +1,250 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.http; + +import haxe.io.Bytes; + +private typedef StringKeyValue = { + var name:String; + var value:String; +} + +/** + This class can be used to handle Http requests consistently across + platforms. There are two intended usages: + + - call `haxe.Http.requestUrl(url)` and receive the result as a `String` + (not available on flash) + - create a `new haxe.Http(url)`, register your callbacks for `onData`, + `onError` and `onStatus`, then call `request()`. +**/ +class HttpBase { + /** + The url of `this` request. It is used only by the `request()` method and + can be changed in order to send the same request to different target + Urls. + **/ + public var url:String; + + public var responseData(get,never):Null; + public var responseBytes(default,null):Null; + + var responseAsString:Null; + var postData:Null; + var postBytes:Null; + var headers:Array; + var params:Array; + + final emptyOnData:(String)->Void; + + /** + Creates a new Http instance with `url` as parameter. + + This does not do a request until `request()` is called. + + If `url` is null, the field url must be set to a value before making the + call to `request()`, or the result is unspecified. + + (Php) Https (SSL) connections are allowed only if the OpenSSL extension + is enabled. + **/ + public function new(url:String) { + this.url = url; + headers = []; + params = []; + emptyOnData = onData; + } + + /** + Sets the header identified as `header` to value `value`. + + If `header` or `value` are null, the result is unspecified. + + This method provides a fluent interface. + **/ + public function setHeader(name:String, value:String) { + for (i in 0...headers.length) { + if (headers[i].name == name) { + headers[i] = {name: name, value: value}; + return #if hx3compat this #end; + } + } + headers.push({name: name, value: value}); + #if hx3compat + return this; + #end + } + + public function addHeader(header:String, value:String) { + headers.push({name: header, value: value}); + #if hx3compat + return this; + #end + } + + /** + Sets the parameter identified as `param` to value `value`. + + If `header` or `value` are null, the result is unspecified. + + This method provides a fluent interface. + **/ + public function setParameter(name:String, value:String) { + for (i in 0...params.length) { + if (params[i].name == name) { + params[i] = {name: name, value: value}; + return #if hx3compat this #end; + } + } + params.push({name: name, value: value}); + #if hx3compat + return this; + #end + } + + public function addParameter(name:String, value:String) { + params.push({name: name, value: value}); + #if hx3compat + return this; + #end + } + + /** + Sets the post data of `this` Http request to `data` string. + + There can only be one post data per request. Subsequent calls to + this method or to `setPostBytes()` overwrite the previously set value. + + If `data` is null, the post data is considered to be absent. + + This method provides a fluent interface. + **/ + public function setPostData(data:Null) { + postData = data; + postBytes = null; + #if hx3compat + return this; + #end + } + + /** + Sets the post data of `this` Http request to `data` bytes. + + There can only be one post data per request. Subsequent calls to + this method or to `setPostData()` overwrite the previously set value. + + If `data` is null, the post data is considered to be absent. + + This method provides a fluent interface. + **/ + public function setPostBytes(data:Null) { + postBytes = data; + postData = null; + #if hx3compat + return this; + #end + } + + /** + Sends `this` Http request to the Url specified by `this.url`. + + If `post` is true, the request is sent as POST request, otherwise it is + sent as GET request. + + Depending on the outcome of the request, this method calls the + `onStatus()`, `onError()`, `onData()` or `onBytes()` callback functions. + + If `this.url` is null, the result is unspecified. + + If `this.url` is an invalid or inaccessible Url, the `onError()` callback + function is called. + + [js] If `this.async` is false, the callback functions are called before + this method returns. + **/ + public function request(?post:Bool):Void { + throw "not implemented"; + } + + /** + This method is called upon a successful request, with `data` containing + the result String. + + The intended usage is to bind it to a custom function: + `httpInstance.onData = function(data) { // handle result }` + **/ + public dynamic function onData(data:String) {} + + /** + This method is called upon a successful request, with `data` containing + the result String. + + The intended usage is to bind it to a custom function: + `httpInstance.onBytes = function(data) { // handle result }` + **/ + public dynamic function onBytes(data:Bytes) {} + + /** + This method is called upon a request error, with `msg` containing the + error description. + + The intended usage is to bind it to a custom function: + `httpInstance.onError = function(msg) { // handle error }` + **/ + public dynamic function onError(msg:String) {} + + /** + This method is called upon a Http status change, with `status` being the + new status. + + The intended usage is to bind it to a custom function: + `httpInstance.onStatus = function(status) { // handle status }` + **/ + public dynamic function onStatus(status:Int) {} + + /** + Override this if extending `haxe.Http` with overriding `onData` + **/ + function hasOnData():Bool { + return !Reflect.compareMethods(onData, emptyOnData); + } + + function success(data:Bytes) { + responseBytes = data; + if (hasOnData()) { + onData(responseData); + } + onBytes(responseBytes); + } + + function get_responseData() { + if (responseAsString == null && responseBytes != null) { + #if neko + responseAsString = neko.Lib.stringReference(responseBytes); + #else + responseAsString = responseBytes.getString(0, responseBytes.length, UTF8); + #end + } + return responseAsString; + } +} diff --git a/std/haxe/http/HttpJs.hx b/std/haxe/http/HttpJs.hx new file mode 100644 index 00000000000..e768932329e --- /dev/null +++ b/std/haxe/http/HttpJs.hx @@ -0,0 +1,160 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.http; + +#if js +import js.html.XMLHttpRequestResponseType; +import js.html.Blob; +import haxe.io.Bytes; + +class HttpJs extends haxe.http.HttpBase { + public var async:Bool; + public var withCredentials:Bool; + + var req:js.html.XMLHttpRequest; + + public function new(url:String) { + async = true; + withCredentials = false; + super(url); + } + + /** + Cancels `this` Http request if `request` has been called and a response + has not yet been received. + **/ + public function cancel() { + if (req == null) + return; + req.abort(); + req = null; + } + + public override function request(?post:Bool) { + this.responseAsString = null; + this.responseBytes = null; + var r = req = js.Browser.createXMLHttpRequest(); + var onreadystatechange = function(_) { + if (r.readyState != 4) + return; + var s = try r.status catch (e:Dynamic) null; + if (s == 0 && js.Browser.supported) { + // If the request is local and we have data: assume a success (jQuery approach): + var protocol = js.Browser.location.protocol.toLowerCase(); + var rlocalProtocol = ~/^(?:about|app|app-storage|.+-extension|file|res|widget):$/; + var isLocal = rlocalProtocol.match(protocol); + if (isLocal) { + s = r.response != null ? 200 : 404; + } + } + if (s == js.Lib.undefined) + s = null; + if (s != null) + onStatus(s); + if (s != null && s >= 200 && s < 400) { + req = null; + success(Bytes.ofData(r.response)); + } else if (s == null) { + req = null; + onError("Failed to connect or resolve host"); + } else + switch (s) { + case 12029: + req = null; + onError("Failed to connect to host"); + case 12007: + req = null; + onError("Unknown host"); + default: + req = null; + responseBytes = Bytes.ofData(r.response); + onError("Http Error #" + r.status); + } + }; + if (async) + r.onreadystatechange = onreadystatechange; + var uri:Null = switch [postData, postBytes] { + case [null, null]: null; + case [str, null]: str; + case [null, bytes]: new Blob([bytes.getData()]); + case _: null; + } + if (uri != null) + post = true; + else + for (p in params) { + if (uri == null) + uri = ""; + else + uri = uri + "&"; + uri = uri + StringTools.urlEncode(p.name) + "=" + StringTools.urlEncode(p.value); + } + try { + if (post) + r.open("POST", url, async); + else if (uri != null) { + var question = url.split("?").length <= 1; + r.open("GET", url + (if (question) "?" else "&") + uri, async); + uri = null; + } else + r.open("GET", url, async); + r.responseType = ARRAYBUFFER; + } catch (e:Dynamic) { + req = null; + onError(e.toString()); + return; + } + r.withCredentials = withCredentials; + if (!Lambda.exists(headers, function(h) return h.name == "Content-Type") && post && postData == null) + r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + + for (h in headers) + r.setRequestHeader(h.name, h.value); + r.send(uri); + if (!async) + onreadystatechange(null); + } + + /** + Makes a synchronous request to `url`. + + This creates a new Http instance and makes a GET request by calling its + `request(false)` method. + + If `url` is null, the result is unspecified. + **/ + public static function requestUrl(url:String):String { + var h = new Http(url); + h.async = false; + var r = null; + h.onData = function(d) { + r = d; + } + h.onError = function(e) { + throw e; + } + h.request(false); + return r; + } +} +#end diff --git a/std/haxe/http/HttpMethod.hx b/std/haxe/http/HttpMethod.hx new file mode 100644 index 00000000000..d0f8fe2a7e0 --- /dev/null +++ b/std/haxe/http/HttpMethod.hx @@ -0,0 +1,84 @@ +package haxe.http; + +/** + HTTP defines methods (sometimes referred to as _verbs_) to indicate the desired action to be + performed on the identified resource. What this resource represents, whether pre-existing data + or data that is generated dynamically, depends on the implementation of the server. + + Often, the resource corresponds to a file or the output of an executable residing on the server. + The HTTP/1.0 specification defined the `GET`, `POST` and `HEAD` methods and the HTTP/1.1 + specification added 5 new methods: `OPTIONS`, `PUT`, `DELETE`, `TRACE` and `CONNECT`. + + By being specified in these documents their semantics are well known and can be depended upon. + Any client can use any method and the server can be configured to support any combination of methods. + If a method is unknown to an intermediate it will be treated as an unsafe and non-idempotent method. + There is no limit to the number of methods that can be defined and this allows for future methods to + be specified without breaking existing infrastructure. +**/ +enum abstract HttpMethod(String) from String to String { + /** + The `POST` method requests that the server accept the entity enclosed in the request as + a new subordinate of the web resource identified by the URI. + + The data `POST`ed might be, for example, an annotation for existing resources; + a message for a bulletin board, newsgroup, mailing list, or comment thread; + a block of data that is the result of submitting a web form to a data-handling process; + or an item to add to a database. + **/ + var Post = 'POST'; + + /** + The `GET` method requests a representation of the specified resource. + + Requests using `GET` should only retrieve data and should have no other effect. + (This is also true of some other HTTP methods.) The W3C has published guidance + principles on this distinction, saying, _"Web application design should be informed + by the above principles, but also by the relevant limitations."_ + + See safe methods below. + **/ + var Get = 'GET'; + + /** + The `HEAD` method asks for a response identical to that of a `GET` request, + but without the response body. This is useful for retrieving meta-information + written in response headers, without having to transport the entire content. + **/ + var Head = 'HEAD'; + + /** + The `PUT` method requests that the enclosed entity be stored under the supplied URI. + If the URI refers to an already existing resource, it is modified; if the URI does + not point to an existing resource, then the server can create the resource with that URI. + **/ + var Put = 'PUT'; + + /** + The `DELETE` method deletes the specified resource. + **/ + var Delete = 'DELETE'; + + /** + The `TRACE` method echoes the received request so that a client can see + what (if any) changes or additions have been made by intermediate servers. + **/ + var Trace = 'TRACE'; + + /** + The `OPTIONS` method returns the HTTP methods that the server supports for the + specified URL. This can be used to check the functionality of a web server by + requesting `*` instead of a specific resource. + **/ + var Options = 'OPTIONS'; + + /** + The `CONNECT` method converts the request connection to a transparent TCP/IP tunnel, + usually to facilitate SSL-encrypted communication (HTTPS) through an unencrypted HTTP proxy. + **/ + var Connect = 'CONNECT'; + + /** + The `PATCH` method applies partial modifications to a resource. + **/ + var Patch = 'PATCH'; +} diff --git a/std/haxe/http/HttpNodeJs.hx b/std/haxe/http/HttpNodeJs.hx new file mode 100644 index 00000000000..50e0d45c415 --- /dev/null +++ b/std/haxe/http/HttpNodeJs.hx @@ -0,0 +1,119 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.http; + +#if nodejs +import js.node.Buffer; +import haxe.io.Bytes; + +class HttpNodeJs extends haxe.http.HttpBase { + var req:js.node.http.ClientRequest; + + public function new(url:String) { + super(url); + } + + /** + Cancels `this` Http request if `request` has been called and a response + has not yet been received. + **/ + public function cancel() { + if (req == null) + return; + req.abort(); + req = null; + } + + public override function request(?post:Bool) { + responseAsString = null; + responseBytes = null; + var parsedUrl = js.node.Url.parse(url); + var secure = (parsedUrl.protocol == "https:"); + var host = parsedUrl.hostname; + var path = parsedUrl.path; + var port = if (parsedUrl.port != null) Std.parseInt(parsedUrl.port) else (secure ? 443 : 80); + var h:Dynamic = {}; + for (i in headers) { + var arr = Reflect.field(h, i.name); + if (arr == null) { + arr = new Array(); + Reflect.setField(h, i.name, arr); + } + + arr.push(i.value); + } + if (postData != null || postBytes != null) + post = true; + var uri = null; + for (p in params) { + if (uri == null) + uri = ""; + else + uri += "&"; + uri += StringTools.urlEncode(p.name) + "=" + StringTools.urlEncode(p.value); + } + var question = path.split("?").length <= 1; + if (uri != null) + path += (if (question) "?" else "&") + uri; + + var opts = { + protocol: parsedUrl.protocol, + hostname: host, + port: port, + method: post ? 'POST' : 'GET', + path: path, + headers: h + }; + function httpResponse(res) { + res.setEncoding('binary'); + var s = res.statusCode; + if (s != null) + onStatus(s); + var data = []; + res.on('data', function(chunk:String) { + data.push(Buffer.from(chunk, 'binary')); + }); + res.on('end', function(_) { + var buf = (data.length == 1 ? data[0] : Buffer.concat(data)); + responseBytes = Bytes.ofData(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)); + req = null; + if (s != null && s >= 200 && s < 400) { + success(responseBytes); + } else { + onError("Http Error #" + s); + } + }); + } + req = secure ? js.node.Https.request(untyped opts, httpResponse) : js.node.Http.request(untyped opts, httpResponse); + if (post) + if (postData != null) { + req.write(postData); + } else if(postBytes != null) { + req.setHeader("Content-Length", '${postBytes.length}'); + req.write(Buffer.from(postBytes.getData())); + } + + req.end(); + } +} +#end diff --git a/std/haxe/http/HttpStatus.hx b/std/haxe/http/HttpStatus.hx new file mode 100644 index 00000000000..65008177ba3 --- /dev/null +++ b/std/haxe/http/HttpStatus.hx @@ -0,0 +1,68 @@ +package haxe.http; + +/** + HTTP Request Status +**/ +enum abstract HttpStatus(Int) from Int to Int { + var Continue = 100; + var SwitchingProtocols = 101; + var Processing = 102; + var OK = 200; + var Created = 201; + var Accepted = 202; + var NonAuthoritativeInformation = 203; + var NoContent = 204; + var ResetContent = 205; + var PartialContent = 206; + var MultiStatus = 207; + var AlreadyReported = 208; + var IMUsed = 226; + var MultipleChoices = 300; + var MovedPermanently = 301; + var Found = 302; + var SeeOther = 303; + var NotModified = 304; + var UseProxy = 305; + var SwitchProxy = 306; + var TemporaryRedirect = 307; + var PermanentRedirect = 308; + var BadRequest = 400; + var Unauthorized = 401; + var PaymentRequired = 402; + var Forbidden = 403; + var NotFound = 404; + var MethodNotAllowed = 405; + var NotAcceptable = 406; + var ProxyAuthenticationRequired = 407; + var RequestTimeout = 408; + var Conflict = 409; + var Gone = 410; + var LengthRequired = 411; + var PreconditionFailed = 412; + var PayloadTooLarge = 413; + var URITooLong = 414; + var UnsupportedMediaType = 415; + var RangeNotSatisfiable = 416; + var ExpectationFailed = 417; + var ImATeapot = 418; + var MisdirectedRequest = 421; + var UnprocessableEntity = 422; + var Locked = 423; + var FailedDependency = 424; + var UpgradeRequired = 426; + var PreconditionRequired = 428; + var TooManyRequests = 429; + var RequestHeaderFieldsTooLarge = 431; + var UnavailableForLegalReasons = 451; + var InternalServerError = 500; + var NotImplemented = 501; + var BadGateway = 502; + var ServiceUnavailable = 503; + var GatewayTimeout = 504; + var HTTPVersionNotSupported = 505; + var VariantAlsoNegotiates = 506; + var InsufficientStorage = 507; + var LoopDetected = 508; + var NotExtended = 510; + var NetworkAuthenticationRequired = 511; +} diff --git a/std/haxe/io/ArrayBufferView.hx b/std/haxe/io/ArrayBufferView.hx index 475775be68a..b65a46b7bd2 100644 --- a/std/haxe/io/ArrayBufferView.hx +++ b/std/haxe/io/ArrayBufferView.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,76 +19,78 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package haxe.io; + +package haxe.io; typedef ArrayBufferViewData = ArrayBufferViewImpl; class ArrayBufferViewImpl { - public var bytes : haxe.io.Bytes; - public var byteOffset : Int; - public var byteLength : Int; + public var bytes:haxe.io.Bytes; + public var byteOffset:Int; + public var byteLength:Int; + public function new(bytes, pos, length) { this.bytes = bytes; this.byteOffset = pos; this.byteLength = length; } - public function sub( begin : Int, ?length : Int ) { - if( length == null ) length = byteLength - begin; - if( begin < 0 || length < 0 || begin + length > byteLength ) throw Error.OutsideBounds; + + public function sub(begin:Int, ?length:Int) { + if (length == null) + length = byteLength - begin; + if (begin < 0 || length < 0 || begin + length > byteLength) + throw Error.OutsideBounds; return new ArrayBufferViewImpl(bytes, byteOffset + begin, length); } - public function subarray( ?begin : Int, ?end : Int ) { - if( begin == null ) begin = 0; - if( end == null ) end = byteLength - begin; + + public function subarray(?begin:Int, ?end:Int) { + if (begin == null) + begin = 0; + if (end == null) + end = byteLength - begin; return sub(begin, end - begin); } } abstract ArrayBufferView(ArrayBufferViewData) { + public var buffer(get, never):haxe.io.Bytes; + public var byteOffset(get, never):Int; + public var byteLength(get, never):Int; - /** - On some platforms configurations (for instance JS with no TypedArray support as in IE8-), Haxe will - try to emulate the array buffers API. However in that case memory sharing will not be supported : - each typed array or will copy its own data set. This flag allows users to detect if we are doing such emulation. - At the moment only JavaScript is concerned. - **/ - public static var EMULATED(get,never) : Bool; - static inline function get_EMULATED() : Bool { - return false; + public inline function new(size:Int) { + this = new ArrayBufferViewData(haxe.io.Bytes.alloc(size), 0, size); } - public var buffer(get,never) : haxe.io.Bytes; - public var byteOffset(get, never) : Int; - public var byteLength(get, never) : Int; + inline function get_byteOffset():Int + return this.byteOffset; - public inline function new( size : Int ) { - this = new ArrayBufferViewData(haxe.io.Bytes.alloc(size), 0, size); - } + inline function get_byteLength():Int + return this.byteLength; - inline function get_byteOffset() : Int return this.byteOffset; - inline function get_byteLength() : Int return this.byteLength; - inline function get_buffer() : haxe.io.Bytes return this.bytes; + inline function get_buffer():haxe.io.Bytes + return this.bytes; - public inline function sub( begin : Int, ?length : Int ) : ArrayBufferView { - return fromData(this.sub(begin,length)); + public inline function sub(begin:Int, ?length:Int):ArrayBufferView { + return fromData(this.sub(begin, length)); } - public inline function subarray( ?begin : Int, ?end : Int ) : ArrayBufferView { - return fromData(this.subarray(begin,end)); + public inline function subarray(?begin:Int, ?end:Int):ArrayBufferView { + return fromData(this.subarray(begin, end)); } - public inline function getData() : ArrayBufferViewData { + public inline function getData():ArrayBufferViewData { return this; } - public static inline function fromData( a : ArrayBufferViewData ) : ArrayBufferView { + public static inline function fromData(a:ArrayBufferViewData):ArrayBufferView { return cast a; } - public static function fromBytes( bytes : haxe.io.Bytes, pos = 0, ?length : Int ) : ArrayBufferView { - if( length == null ) length = bytes.length - pos; - if( pos < 0 || length < 0 || pos + length > bytes.length ) throw Error.OutsideBounds; + public static function fromBytes(bytes:haxe.io.Bytes, pos = 0, ?length:Int):ArrayBufferView { + if (length == null) + length = bytes.length - pos; + if (pos < 0 || length < 0 || pos + length > bytes.length) + throw Error.OutsideBounds; return fromData(new ArrayBufferViewData(bytes, pos, length)); } - -} \ No newline at end of file +} diff --git a/std/haxe/io/BufferInput.hx b/std/haxe/io/BufferInput.hx index 4802f553b64..a60e08ae654 100644 --- a/std/haxe/io/BufferInput.hx +++ b/std/haxe/io/BufferInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; class BufferInput extends haxe.io.Input { - - public var i : haxe.io.Input; - public var buf : haxe.io.Bytes; - public var available : Int; - public var pos : Int; + public var i:haxe.io.Input; + public var buf:haxe.io.Bytes; + public var available:Int; + public var pos:Int; public function new(i, buf, ?pos = 0, ?available = 0) { this.i = i; @@ -36,7 +36,7 @@ class BufferInput extends haxe.io.Input { } public function refill() { - if( pos > 0 ) { + if (pos > 0) { buf.blit(0, buf, pos, available); pos = 0; } @@ -44,20 +44,21 @@ class BufferInput extends haxe.io.Input { } override function readByte() { - if( available == 0 ) refill(); + if (available == 0) + refill(); var c = buf.get(pos); pos++; available--; return c; } - override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) { - if( available == 0 ) refill(); - var size = if( len > available ) available else len; + override function readBytes(buf:haxe.io.Bytes, pos:Int, len:Int) { + if (available == 0) + refill(); + var size = if (len > available) available else len; buf.blit(pos, this.buf, this.pos, size); this.pos += size; this.available -= size; return size; } - -} \ No newline at end of file +} diff --git a/std/haxe/io/Bytes.hx b/std/haxe/io/Bytes.hx index ab957bc7f0b..74443cf5f3a 100644 --- a/std/haxe/io/Bytes.hx +++ b/std/haxe/io/Bytes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; #if cpp @@ -26,11 +27,11 @@ using cpp.NativeArray; #end class Bytes { + public var length(default, null):Int; - public var length(default,null) : Int; - var b : BytesData; + var b:BytesData; - function new(length,b) { + function new(length, b) { this.length = length; this.b = b; #if flash @@ -38,9 +39,12 @@ class Bytes { #end } - public inline function get( pos : Int ) : Int { + /** + Returns the byte at index `pos`. + **/ + public inline function get(pos:Int):Int { #if neko - return untyped $sget(b,pos); + return untyped $sget(b, pos); #elseif flash return b[pos]; #elseif cpp @@ -54,9 +58,12 @@ class Bytes { #end } - public inline function set( pos : Int, v : Int ) : Void { + /** + Stores the given byte `v` at the given position `pos`. + **/ + public inline function set(pos:Int, v:Int):Void { #if neko - untyped $sset(b,pos,v); + untyped $sset(b, pos, v); #elseif flash b[pos] = v; #elseif cpp @@ -72,69 +79,91 @@ class Bytes { #end } - public function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void { + /** + Copies `len` bytes from `src` into this instance. + @param pos Zero-based location in `this` instance at which to start writing + bytes. + @param src Source `Bytes` instance from which to copy bytes. + @param srcpos Zero-based location at `src` from which bytes will be copied. + @param len Number of bytes to be copied. + **/ + public function blit(pos:Int, src:Bytes, srcpos:Int, len:Int):Void { #if !neko - if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) throw Error.OutsideBounds; + if (pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length) + throw Error.OutsideBounds; #end #if neko - try untyped $sblit(b,pos,src.b,srcpos,len) catch( e : Dynamic ) throw Error.OutsideBounds; + try + untyped $sblit(b, pos, src.b, srcpos, len) + catch (e:Dynamic) + throw Error.OutsideBounds; #elseif flash b.position = pos; - if( len > 0 ) b.writeBytes(src.b,srcpos,len); + if (len > 0) + b.writeBytes(src.b, srcpos, len); #elseif java java.lang.System.arraycopy(src.b, srcpos, b, pos, len); #elseif cs cs.system.Array.Copy(src.b, srcpos, b, pos, len); #elseif python - python.Syntax.pythonCode("self.b[{0}:{0}+{1}] = src.b[srcpos:srcpos+{1}]", pos, len); + python.Syntax.code("self.b[{0}:{0}+{1}] = src.b[srcpos:srcpos+{1}]", pos, len); #elseif cpp b.blit(pos, src.b, srcpos, len); #else var b1 = b; var b2 = src.b; - if( b1 == b2 && pos > srcpos ) { + if (b1 == b2 && pos > srcpos) { var i = len; - while( i > 0 ) { + while (i > 0) { i--; b1[i + pos] = b2[i + srcpos]; } return; } - for( i in 0...len ) - b1[i+pos] = b2[i+srcpos]; + for (i in 0...len) + b1[i + pos] = b2[i + srcpos]; #end } - public function fill( pos : Int, len : Int, value : Int ) { + /** + Sets `len` consecutive bytes starting from index `pos` of `this` instance + to `value`. + **/ + public function fill(pos:Int, len:Int, value:Int) { #if flash - var v4 = value&0xFF; - v4 |= v4<<8; - v4 |= v4<<16; + var v4 = value & 0xFF; + v4 |= v4 << 8; + v4 |= v4 << 16; b.position = pos; - for( i in 0...len>>2 ) + for (i in 0...len >> 2) b.writeUnsignedInt(v4); - pos += len&~3; - for( i in 0...len&3 ) - set(pos++,value); + pos += len & ~3; + for (i in 0...len & 3) + set(pos++, value); #elseif cpp - untyped __global__.__hxcpp_memory_memset(b,pos,len,value); + untyped __global__.__hxcpp_memory_memset(b, pos, len, value); #else - for( i in 0...len ) + for (i in 0...len) set(pos++, value); #end } - public function sub( pos : Int, len : Int ) : Bytes { + /** + Returns a new `Bytes` instance that contains a copy of `len` bytes of + `this` instance, starting at index `pos`. + **/ + public function sub(pos:Int, len:Int):Bytes { #if !neko - if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; + if (pos < 0 || len < 0 || pos + len > length) + throw Error.OutsideBounds; #end #if neko - return try new Bytes(len,untyped __dollar__ssub(b,pos,len)) catch( e : Dynamic ) throw Error.OutsideBounds; + return try new Bytes(len, untyped __dollar__ssub(b, pos, len)) catch (e:Dynamic) throw Error.OutsideBounds; #elseif flash b.position = pos; var b2 = new flash.utils.ByteArray(); - b.readBytes(b2,0,len); - return new Bytes(len,b2); + b.readBytes(b2, 0, len); + return new Bytes(len, b2); #elseif java var newarr = new java.NativeArray(len); java.lang.System.arraycopy(b, pos, newarr, 0, len); @@ -144,15 +173,27 @@ class Bytes { cs.system.Array.Copy(b, pos, newarr, 0, len); return new Bytes(len, newarr); #elseif python - return new Bytes(len, python.Syntax.arrayAccess(b, pos, pos+len) ); + return new Bytes(len, python.Syntax.arrayAccess(b, pos, pos + len)); #else - return new Bytes(len,b.slice(pos,pos+len)); + return new Bytes(len, b.slice(pos, pos + len)); #end } + + /** + Returns `0` if the bytes of `this` instance and the bytes of `other` are + identical. - public function compare( other : Bytes ) : Int { + Returns a negative value if the `length` of `this` instance is less than + the `length` of `other`, or a positive value if the `length` of `this` + instance is greater than the `length` of `other`. + + In case of equal `length`s, returns a negative value if the first different + value in `other` is greater than the corresponding value in `this` + instance; otherwise returns a positive value. + **/ + public function compare(other:Bytes):Int { #if neko - return untyped __dollar__compare(b,other.b); + return untyped __dollar__compare(b, other.b); #elseif flash var len = (length < other.length) ? length : other.length; var b1 = b; @@ -161,8 +202,8 @@ class Bytes { b2.position = 0; b1.endian = flash.utils.Endian.BIG_ENDIAN; b2.endian = flash.utils.Endian.BIG_ENDIAN; - for( i in 0...len>>2 ) - if( b1.readUnsignedInt() != b2.readUnsignedInt() ) { + for (i in 0...len >> 2) + if (b1.readUnsignedInt() != b2.readUnsignedInt()) { b1.position -= 4; b2.position -= 4; var d = b1.readUnsignedInt() - b2.readUnsignedInt(); @@ -170,85 +211,96 @@ class Bytes { b2.endian = flash.utils.Endian.LITTLE_ENDIAN; return d; } - for( i in 0...len & 3 ) - if( b1.readUnsignedByte() != b2.readUnsignedByte() ) { + for (i in 0...len & 3) + if (b1.readUnsignedByte() != b2.readUnsignedByte()) { b1.endian = flash.utils.Endian.LITTLE_ENDIAN; b2.endian = flash.utils.Endian.LITTLE_ENDIAN; - return b1[b1.position-1] - b2[b2.position-1]; + return b1[b1.position - 1] - b2[b2.position - 1]; } b1.endian = flash.utils.Endian.LITTLE_ENDIAN; b2.endian = flash.utils.Endian.LITTLE_ENDIAN; return length - other.length; - //#elseif cs - //TODO: memcmp if unsafe flag is on + // #elseif cs + // TODO: memcmp if unsafe flag is on #elseif cpp return b.memcmp(other.b); #else var b1 = b; var b2 = other.b; var len = (length < other.length) ? length : other.length; - for( i in 0...len ) - if( b1[i] != b2[i] ) - return untyped b1[i] - untyped b2[i]; + for (i in 0...len) + if (b1[i] != b2[i]) + return untyped b1[i] - b2[i]; return length - other.length; #end } - /** - Returns the IEEE double precision value at given position (in low endian encoding). - Result is unspecified if reading outside of the bounds + Returns the IEEE double-precision value at the given position `pos` (in + little-endian encoding). Result is unspecified if `pos` is outside the + bounds. **/ - #if (neko_v21 || (cpp && !cppia) || flash) inline #end - public function getDouble( pos : Int ) : Float { + #if (neko_v21 || (cpp && !cppia) || flash) + inline + #end + public function getDouble(pos:Int):Float { #if neko_v21 return untyped $sgetd(b, pos, false); #elseif flash b.position = pos; return b.readDouble(); #elseif cpp - if( pos < 0 || pos + 8 > length ) throw Error.OutsideBounds; - return untyped __global__.__hxcpp_memory_get_double(b,pos); + if (pos < 0 || pos + 8 > length) + throw Error.OutsideBounds; + return untyped __global__.__hxcpp_memory_get_double(b, pos); #else - return FPHelper.i64ToDouble(getInt32(pos),getInt32(pos+4)); + return FPHelper.i64ToDouble(getInt32(pos), getInt32(pos + 4)); #end } /** - Returns the IEEE single precision value at given position (in low endian encoding). - Result is unspecified if reading outside of the bounds + Returns the IEEE single-precision value at the given position `pos` (in + little-endian encoding). Result is unspecified if `pos` is outside the + bounds. **/ - #if (neko_v21 || (cpp && !cppia) || flash) inline #end - public function getFloat( pos : Int ) : Float { + #if (neko_v21 || (cpp && !cppia) || flash) + inline + #end + public function getFloat(pos:Int):Float { #if neko_v21 return untyped $sgetf(b, pos, false); #elseif flash b.position = pos; return b.readFloat(); #elseif cpp - if( pos < 0 || pos + 4 > length ) throw Error.OutsideBounds; - return untyped __global__.__hxcpp_memory_get_float(b,pos); + if (pos < 0 || pos + 4 > length) + throw Error.OutsideBounds; + return untyped __global__.__hxcpp_memory_get_float(b, pos); #else return FPHelper.i32ToFloat(getInt32(pos)); #end } /** - Store the IEEE double precision value at given position in low endian encoding. - Result is unspecified if writing outside of the bounds. + Stores the given IEEE double-precision value `v` at the given position + `pos` in little-endian encoding. Result is unspecified if writing outside + of bounds. **/ - #if (neko_v21 || flash) inline #end - public function setDouble( pos : Int, v : Float ) : Void { + #if (neko_v21 || flash) + inline + #end + public function setDouble(pos:Int, v:Float):Void { #if neko_v21 untyped $ssetd(b, pos, v, false); #elseif neko - untyped $sblit(b, pos, FPHelper._double_bytes(v,false), 0, 8); + untyped $sblit(b, pos, FPHelper._double_bytes(v, false), 0, 8); #elseif flash b.position = pos; b.writeDouble(v); #elseif cpp - if( pos < 0 || pos + 8 > length ) throw Error.OutsideBounds; - untyped __global__.__hxcpp_memory_set_double(b,pos,v); + if (pos < 0 || pos + 8 > length) + throw Error.OutsideBounds; + untyped __global__.__hxcpp_memory_set_double(b, pos, v); #else var i = FPHelper.doubleToI64(v); setInt32(pos, i.low); @@ -257,30 +309,35 @@ class Bytes { } /** - Store the IEEE single precision value at given position in low endian encoding. - Result is unspecified if writing outside of the bounds. + Stores the given IEEE single-precision value `v` at the given position + `pos` in little-endian encoding. Result is unspecified if writing outside + of bounds. **/ - #if (neko_v21 || flash) inline #end - public function setFloat( pos : Int, v : Float ) : Void { + #if (neko_v21 || flash) + inline + #end + public function setFloat(pos:Int, v:Float):Void { #if neko_v21 untyped $ssetf(b, pos, v, false); #elseif neko - untyped $sblit(b, pos, FPHelper._float_bytes(v,false), 0, 4); + untyped $sblit(b, pos, FPHelper._float_bytes(v, false), 0, 4); #elseif flash b.position = pos; b.writeFloat(v); #elseif cpp - if( pos < 0 || pos + 4 > length ) throw Error.OutsideBounds; - untyped __global__.__hxcpp_memory_set_float(b,pos,v); + if (pos < 0 || pos + 4 > length) + throw Error.OutsideBounds; + untyped __global__.__hxcpp_memory_set_float(b, pos, v); #else setInt32(pos, FPHelper.floatToI32(v)); #end } /** - Returns the 16 bit unsigned integer at given position (in low endian encoding). + Returns the 16-bit unsigned integer at the given position `pos` (in + little-endian encoding). **/ - public inline function getUInt16( pos : Int ) : Int { + public inline function getUInt16(pos:Int):Int { #if neko_v21 return untyped $sget16(b, pos, false); #else @@ -289,9 +346,10 @@ class Bytes { } /** - Store the 16 bit unsigned integer at given position (in low endian encoding). + Stores the given 16-bit unsigned integer `v` at the given position `pos` + (in little-endian encoding). **/ - public inline function setUInt16( pos : Int, v : Int ) : Void { + public inline function setUInt16(pos:Int, v:Int):Void { #if neko_v21 untyped $sset16(b, pos, v, false); #else @@ -301,33 +359,36 @@ class Bytes { } /** - Returns the 32 bit integer at given position (in low endian encoding). + Returns the 32-bit integer at the given position `pos` (in little-endian + encoding). **/ - public inline function getInt32( pos : Int ) : Int { + public inline function getInt32(pos:Int):Int { #if neko_v21 return untyped $sget32(b, pos, false); #elseif python - var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos+3) << 24); - return if( v & 0x80000000 != 0 ) v | 0x80000000 else v; + var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos + 3) << 24); + return if (v & 0x80000000 != 0) v | 0x80000000 else v; #elseif lua - var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos+3) << 24); - return lua.Boot.clamp(if( v & 0x80000000 != 0 ) v | 0x80000000 else v); + var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos + 3) << 24); + return lua.Boot.clampInt32(if (v & 0x80000000 != 0) v | 0x80000000 else v); #else - return get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos+3) << 24); + return get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos + 3) << 24); #end } /** - Returns the 64 bit integer at given position (in low endian encoding). + Returns the 64-bit integer at the given position `pos` (in little-endian + encoding). **/ - public inline function getInt64( pos : Int ) : haxe.Int64 { - return haxe.Int64.make(getInt32(pos+4),getInt32(pos)); + public inline function getInt64(pos:Int):haxe.Int64 { + return haxe.Int64.make(getInt32(pos + 4), getInt32(pos)); } /** - Store the 32 bit integer at given position (in low endian encoding). + Stores the given 32-bit integer `v` at the given position `pos` (in + little-endian encoding). **/ - public inline function setInt32( pos : Int, v : Int ) : Void { + public inline function setInt32(pos:Int, v:Int):Void { #if neko_v21 untyped $sset32(b, pos, v, false); #else @@ -339,62 +400,90 @@ class Bytes { } /** - Store the 64 bit integer at given position (in low endian encoding). + Stores the given 64-bit integer `v` at the given position `pos` (in + little-endian encoding). **/ - public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { + public inline function setInt64(pos:Int, v:haxe.Int64):Void { setInt32(pos, v.low); setInt32(pos + 4, v.high); } - public function getString( pos : Int, len : Int ) : String { + /** + Returns the `len`-bytes long string stored at the given position `pos`, + interpreted with the given `encoding` (UTF-8 by default). + **/ + public function getString(pos:Int, len:Int, ?encoding:Encoding):String { + if (encoding == null) + encoding == UTF8; #if !neko - if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; + if (pos < 0 || len < 0 || pos + len > length) + throw Error.OutsideBounds; #end #if neko - return try new String(untyped __dollar__ssub(b,pos,len)) catch( e : Dynamic ) throw Error.OutsideBounds; + return try new String(untyped __dollar__ssub(b, pos, len)) catch (e:Dynamic) throw Error.OutsideBounds; #elseif flash b.position = pos; - return b.readUTFBytes(len); + return encoding == RawNative ? b.readMultiByte(len, "unicode") : b.readUTFBytes(len); #elseif cpp - var result:String=""; - untyped __global__.__hxcpp_string_of_bytes(b,result,pos,len); + var result:String = ""; + untyped __global__.__hxcpp_string_of_bytes(b, result, pos, len); return result; #elseif cs - return cs.system.text.Encoding.UTF8.GetString(b, pos, len); + switch (encoding) { + case UTF8 | null: + return cs.system.text.Encoding.UTF8.GetString(b, pos, len); + case RawNative: + return cs.system.text.Encoding.Unicode.GetString(b, pos, len); + } #elseif java - try - return new String(b, pos, len, "UTF-8") - catch (e:Dynamic) throw e; + try { + switch (encoding) { + case UTF8 | null: + return new String(b, pos, len, "UTF-8"); + case RawNative: + return new String(b, pos, len, "UTF-16LE"); + } + } catch (e:Dynamic) { + throw e; + } #elseif python - return python.Syntax.pythonCode("self.b[{0}:{0}+{1}].decode('UTF-8','replace')", pos, len); + return python.Syntax.code("self.b[{0}:{0}+{1}].decode('UTF-8','replace')", pos, len); #elseif lua - var begin = cast(Math.min(pos,b.length),Int); - var end = cast(Math.min(pos+len,b.length),Int); - return [for (i in begin...end) String.fromCharCode(b[i])].join(""); + if (b.length - pos <= lua.Boot.MAXSTACKSIZE) { + var end:Int = cast Math.min(b.length, pos + len) - 1; + return lua.NativeStringTools.char(lua.TableTools.unpack(untyped b, pos, end)); + } else { + var tbl:lua.Table = lua.Table.create(); + for (idx in pos...pos + len) { + lua.Table.insert(tbl, lua.NativeStringTools.char(b[idx])); + } + return lua.Table.concat(tbl, ''); + } #else var s = ""; var b = b; var fcc = String.fromCharCode; var i = pos; - var max = pos+len; + var max = pos + len; // utf8-decode and utf16-encode - while( i < max ) { + while (i < max) { var c = b[i++]; - if( c < 0x80 ) { - if( c == 0 ) break; + if (c < 0x80) { + if (c == 0) + break; s += fcc(c); - } else if( c < 0xE0 ) - s += fcc( ((c & 0x3F) << 6) | (b[i++] & 0x7F) ); - else if( c < 0xF0 ) { + } else if (c < 0xE0) + s += fcc(((c & 0x3F) << 6) | (b[i++] & 0x7F)); + else if (c < 0xF0) { var c2 = b[i++]; - s += fcc( ((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | (b[i++] & 0x7F) ); + s += fcc(((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | (b[i++] & 0x7F)); } else { var c2 = b[i++]; var c3 = b[i++]; var u = ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 & 0x7F) << 6) | (b[i++] & 0x7F); // surrogate pair - s += fcc( (u >> 10) + 0xD7C0 ); - s += fcc( (u & 0x3FF) | 0xDC00 ); + s += fcc((u >> 10) + 0xD7C0); + s += fcc((u & 0x3FF) | 0xDC00); } } return s; @@ -407,32 +496,38 @@ class Bytes { return getString(pos, len); } - public function toString() : String { + /** + Returns a `String` representation of the bytes interpreted as UTF-8. + **/ + public function toString():String { #if neko - return new String(untyped __dollar__ssub(b,0,length)); + return new String(untyped __dollar__ssub(b, 0, length)); #elseif flash b.position = 0; return b.toString(); #elseif cs return cs.system.text.Encoding.UTF8.GetString(b, 0, length); #elseif java - try - { + try { return new String(b, 0, length, "UTF-8"); - } - catch (e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; #else - return getString(0,length); + return getString(0, length); #end } - public function toHex() : String { + /** + Returns a hexadecimal `String` representation of the bytes of `this` + instance. + **/ + public function toHex():String { var s = new StringBuf(); var chars = []; var str = "0123456789abcdef"; - for( i in 0...str.length ) + for (i in 0...str.length) chars.push(str.charCodeAt(i)); - for( i in 0...length ) { + for (i in 0...length) { var c = get(i); s.addChar(chars[c >> 4]); s.addChar(chars[c & 15]); @@ -440,20 +535,28 @@ class Bytes { return s.toString(); } - public inline function getData() : BytesData { + /** + Returns the bytes of `this` instance as `BytesData`. + **/ + public inline function getData():BytesData { return b; } - public static function alloc( length : Int ) : Bytes { + /** + Returns a new `Bytes` instance with the given `length`. The values of the + bytes are not initialized and may not be zero. + **/ + public static function alloc(length:Int):Bytes { #if neko - return new Bytes(length,untyped __dollar__smake(length)); + return new Bytes(length, untyped __dollar__smake(length)); #elseif flash var b = new flash.utils.ByteArray(); b.length = length; - return new Bytes(length,b); + return new Bytes(length, b); #elseif cpp var a = new BytesData(); - if (length>0) cpp.NativeArray.setSize(a, length); + if (length > 0) + cpp.NativeArray.setSize(a, length); return new Bytes(length, a); #elseif cs return new Bytes(length, new cs.NativeArray(length)); @@ -463,90 +566,134 @@ class Bytes { return new Bytes(length, new python.Bytearray(length)); #else var a = new Array(); - for( i in 0...length ) + for (i in 0...length) a.push(0); - return new Bytes(length,a); + return new Bytes(length, a); #end } + /** + Returns the `Bytes` representation of the given `String`, using the + specified encoding (UTF-8 by default). + **/ @:pure - public static function ofString( s : String ) : Bytes { + public static function ofString(s:String, ?encoding:Encoding):Bytes { #if neko - return new Bytes(s.length,untyped __dollar__ssub(s.__s,0,s.length)); + return new Bytes(s.length, untyped __dollar__ssub(s.__s, 0, s.length)); #elseif flash var b = new flash.utils.ByteArray(); - b.writeUTFBytes(s); - return new Bytes(b.length,b); + if (encoding == RawNative) + b.writeMultiByte(s, "unicode") + else + b.writeUTFBytes(s); + return new Bytes(b.length, b); #elseif cpp var a = new BytesData(); - untyped __global__.__hxcpp_bytes_of_string(a,s); + untyped __global__.__hxcpp_bytes_of_string(a, s); return new Bytes(a.length, a); #elseif cs - var b = cs.system.text.Encoding.UTF8.GetBytes(s); + var b = switch (encoding) { + case UTF8 | null: + cs.system.text.Encoding.UTF8.GetBytes(s); + case RawNative: + cs.system.text.Encoding.Unicode.GetBytes(s); + }; return new Bytes(b.Length, b); #elseif java - try - { - var b:BytesData = untyped s.getBytes("UTF-8"); + try { + var b:BytesData = switch (encoding) { + case UTF8 | null: + @:privateAccess s.getBytes("UTF-8"); + case RawNative: + @:privateAccess s.getBytes("UTF-16LE"); + }; return new Bytes(b.length, b); + } catch (e:Dynamic) { + throw e; } - catch (e:Dynamic) throw e; - #elseif python - var b:BytesData = new python.Bytearray(s, "UTF-8"); - return new Bytes(b.length, b); - + var b:BytesData = new python.Bytearray(s, "UTF-8"); + return new Bytes(b.length, b); #elseif lua - var bytes = [for (c in 0...s.length) StringTools.fastCodeAt(s,c)]; - return new Bytes(bytes.length, bytes); + var bytes = [ + for (i in 0...lua.NativeStringTools.len(s)) { + lua.NativeStringTools.byte(s, i + 1); + } + ]; + return new Bytes(bytes.length, bytes); #else var a = new Array(); // utf16-decode and utf8-encode var i = 0; - while( i < s.length ) { - var c : Int = StringTools.fastCodeAt(s,i++); + while (i < s.length) { + var c:Int = StringTools.fastCodeAt(s, i++); // surrogate pair - if( 0xD800 <= c && c <= 0xDBFF ) - c = (c - 0xD7C0 << 10) | (StringTools.fastCodeAt(s,i++) & 0x3FF); - if( c <= 0x7F ) + if (0xD800 <= c && c <= 0xDBFF) + c = (c - 0xD7C0 << 10) | (StringTools.fastCodeAt(s, i++) & 0x3FF); + if (c <= 0x7F) a.push(c); - else if( c <= 0x7FF ) { - a.push( 0xC0 | (c >> 6) ); - a.push( 0x80 | (c & 63) ); - } else if( c <= 0xFFFF ) { - a.push( 0xE0 | (c >> 12) ); - a.push( 0x80 | ((c >> 6) & 63) ); - a.push( 0x80 | (c & 63) ); + else if (c <= 0x7FF) { + a.push(0xC0 | (c >> 6)); + a.push(0x80 | (c & 63)); + } else if (c <= 0xFFFF) { + a.push(0xE0 | (c >> 12)); + a.push(0x80 | ((c >> 6) & 63)); + a.push(0x80 | (c & 63)); } else { - a.push( 0xF0 | (c >> 18) ); - a.push( 0x80 | ((c >> 12) & 63) ); - a.push( 0x80 | ((c >> 6) & 63) ); - a.push( 0x80 | (c & 63) ); + a.push(0xF0 | (c >> 18)); + a.push(0x80 | ((c >> 12) & 63)); + a.push(0x80 | ((c >> 6) & 63)); + a.push(0x80 | (c & 63)); } } - return new Bytes(a.length,a); + return new Bytes(a.length, a); #end } - public static function ofData( b : BytesData ) { + /** + Returns the `Bytes` representation of the given `BytesData`. + **/ + public static function ofData(b:BytesData) { #if flash - return new Bytes(b.length,b); + return new Bytes(b.length, b); #elseif neko - return new Bytes(untyped __dollar__ssize(b),b); + return new Bytes(untyped __dollar__ssize(b), b); #elseif cs - return new Bytes(b.Length,b); + return new Bytes(b.Length, b); #else - return new Bytes(b.length,b); + return new Bytes(b.length, b); #end } /** - Read the most efficiently possible the n-th byte of the data. - Behavior when reading outside of the available data is unspecified. + Converts the given hexadecimal `String` to `Bytes`. `s` must be a string of + even length consisting only of hexadecimal digits. For example: + `"0FDA14058916052309"`. **/ - public inline static function fastGet( b : BytesData, pos : Int ) : Int { + public static function ofHex(s:String):Bytes { + var len:Int = s.length; + if ((len & 1) != 0) + throw "Not a hex string (odd number of digits)"; + var ret:Bytes = Bytes.alloc(len >> 1); + for (i in 0...ret.length) { + var high = StringTools.fastCodeAt(s, i * 2); + var low = StringTools.fastCodeAt(s, i * 2 + 1); + high = (high & 0xF) + ((high & 0x40) >> 6) * 9; + low = (low & 0xF) + ((low & 0x40) >> 6) * 9; + ret.set(i, ((high << 4) | low) & 0xFF); + } + + return ret; + } + + /** + Reads the `pos`-th byte of the given `b` bytes, in the most efficient way + possible. Behavior when reading outside of the available data is + unspecified. + **/ + public inline static function fastGet(b:BytesData, pos:Int):Int { #if neko - return untyped __dollar__sget(b,pos); + return untyped __dollar__sget(b, pos); #elseif flash return b[pos]; #elseif cpp @@ -557,5 +704,4 @@ class Bytes { return b[pos]; #end } - } diff --git a/std/haxe/io/BytesBuffer.hx b/std/haxe/io/BytesBuffer.hx index 3f2ab1fa9bc..e7c878e4fef 100644 --- a/std/haxe/io/BytesBuffer.hx +++ b/std/haxe/io/BytesBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,26 +19,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; class BytesBuffer { - #if neko - var b : Dynamic; // neko string buffer + var b:Dynamic; // neko string buffer #elseif flash - var b : flash.utils.ByteArray; + var b:flash.utils.ByteArray; #elseif cpp - var b : BytesData; + var b:BytesData; #elseif cs - var b : cs.system.io.MemoryStream; + var b:cs.system.io.MemoryStream; #elseif java - var b : java.io.ByteArrayOutputStream; + var b:java.io.ByteArrayOutputStream; + #elseif python + var b:python.Bytearray; #else - var b : Array; + var b:Array; #end /** The length of the buffer in bytes. **/ - public var length(get,never) : Int; + public var length(get, never):Int; public function new() { #if neko @@ -52,16 +54,18 @@ class BytesBuffer { b = new cs.system.io.MemoryStream(); #elseif java b = new java.io.ByteArrayOutputStream(); + #elseif python + b = new python.Bytearray(); #else b = new Array(); #end } - inline function get_length() : Int { + inline function get_length():Int { #if neko - return untyped __dollar__ssize( StringBuf.__to_string(b) ); + return untyped __dollar__ssize(StringBuf.__to_string(b)); #elseif cs - return haxe.Int64.toInt( b.Length ); + return haxe.Int64.toInt(b.Length); #elseif java return b.size(); #else @@ -69,9 +73,9 @@ class BytesBuffer { #end } - public inline function addByte( byte : Int ) { + public inline function addByte(byte:Int) { #if neko - untyped StringBuf.__add_char(b,byte); + untyped StringBuf.__add_char(b, byte); #elseif flash b.writeByte(byte); #elseif cpp @@ -80,14 +84,16 @@ class BytesBuffer { b.WriteByte(cast byte); #elseif java b.write(byte); + #elseif python + b.append(byte); #else b.push(byte); #end } - public inline function add( src : Bytes ) { + public inline function add(src:Bytes) { #if neko - untyped StringBuf.__add(b,src.getData()); + untyped StringBuf.__add(b, src.getData()); #elseif flash b.writeBytes(src.getData()); #elseif cs @@ -97,43 +103,50 @@ class BytesBuffer { #elseif js var b1 = b; var b2 = @:privateAccess src.b; - for( i in 0...src.length ) + for (i in 0...src.length) b.push(b2[i]); + #elseif python + b.extend(src.getData()); #else var b1 = b; var b2 = src.getData(); - for( i in 0...src.length ) + for (i in 0...src.length) b.push(b2[i]); #end } - public inline function addString( v : String ) { + public inline function addString(v:String, ?encoding:Encoding) { #if neko untyped StringBuf.__add(b, v.__s); #elseif flash - b.writeUTFBytes(v); + if (encoding == RawNative) + b.writeMultiByte(v, "unicode") + else + b.writeUTFBytes(v); + #elseif python + b.extend(new python.Bytearray(v, "UTF-8")); #else - add(Bytes.ofString(v)); + add(Bytes.ofString(v, encoding)); #end } - public #if flash inline #end function addInt32( v : Int ) { + public #if flash inline #end function addInt32(v:Int) { #if flash b.writeUnsignedInt(v); #else - addByte(v&0xFF); - addByte((v>>8)&0xFF); - addByte((v>>16)&0xFF); - addByte(v>>>24); + addByte(v & 0xFF); + addByte((v >> 8) & 0xFF); + addByte((v >> 16) & 0xFF); + addByte(v >>> 24); #end } - public #if flash inline #end function addInt64( v : haxe.Int64 ) { + public #if flash inline #end function addInt64(v:haxe.Int64) { addInt32(v.low); addInt32(v.high); } - public inline function addFloat( v : Float ) { + public inline function addFloat(v:Float) { #if flash b.writeFloat(v); #else @@ -141,7 +154,7 @@ class BytesBuffer { #end } - public inline function addDouble( v : Float ) { + public inline function addDouble(v:Float) { #if flash b.writeDouble(v); #else @@ -149,14 +162,19 @@ class BytesBuffer { #end } - public inline function addBytes( src : Bytes, pos : Int, len : Int ) { + public inline function addBytes(src:Bytes, pos:Int, len:Int) { #if !neko - if( pos < 0 || len < 0 || pos + len > src.length ) throw Error.OutsideBounds; + if (pos < 0 || len < 0 || pos + len > src.length) + throw Error.OutsideBounds; #end #if neko - try untyped StringBuf.__add_sub(b,src.getData(),pos,len) catch( e : Dynamic ) throw Error.OutsideBounds; + try + untyped StringBuf.__add_sub(b, src.getData(), pos, len) + catch (e:Dynamic) + throw Error.OutsideBounds; #elseif flash - if( len > 0 ) b.writeBytes(src.getData(),pos,len); + if (len > 0) + b.writeBytes(src.getData(), pos, len); #elseif cs b.Write(src.getData(), pos, len); #elseif java @@ -164,43 +182,44 @@ class BytesBuffer { #elseif js var b1 = b; var b2 = @:privateAccess src.b; - for( i in pos...pos+len ) + for (i in pos...pos + len) b.push(b2[i]); + #elseif python + b.extend(python.Syntax.code("{0}[{1}:{2}]", src.getData(), pos, pos + len)); #else var b1 = b; var b2 = src.getData(); - for( i in pos...pos+len ) + for (i in pos...pos + len) b.push(b2[i]); #end } /** Returns either a copy or a reference of the current bytes. - Once called, the buffer can no longer be used. + Once called, the buffer should no longer be used. **/ - public function getBytes() : Bytes untyped { - #if neko - var str = StringBuf.__to_string(b); - var bytes = new Bytes(__dollar__ssize(str),str); - #elseif flash - var bytes = new Bytes(b.length,b); - b.position = 0; - #elseif cs - var buf = b.GetBuffer(); - var bytes = new Bytes(cast b.Length, buf); - #elseif java - var buf = b.toByteArray(); - var bytes = new Bytes(buf.length, buf); - #elseif python - var buf = new python.Bytearray(b); - var bytes = new Bytes(buf.length, buf); - #elseif js - var bytes = new Bytes(new js.html.Uint8Array(b).buffer); - #else - var bytes = new Bytes(b.length,b); - #end - b = null; - return bytes; - } - + public function getBytes():Bytes + untyped { + #if neko + var str = StringBuf.__to_string(b); + var bytes = new Bytes(__dollar__ssize(str), str); + #elseif flash + var bytes = new Bytes(b.length, b); + b.position = 0; + #elseif cs + var buf = b.GetBuffer(); + var bytes = new Bytes(cast b.Length, buf); + #elseif java + var buf = b.toByteArray(); + var bytes = new Bytes(buf.length, buf); + #elseif python + var bytes = new Bytes(b.length, b); + #elseif js + var bytes = new Bytes(new js.lib.Uint8Array(b).buffer); + #else + var bytes = new Bytes(b.length, b); + #end + b = null; + return bytes; + } } diff --git a/std/haxe/io/BytesData.hx b/std/haxe/io/BytesData.hx index d3730e8490c..a7a443c713f 100644 --- a/std/haxe/io/BytesData.hx +++ b/std/haxe/io/BytesData.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,43 +19,52 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; #if neko - typedef BytesData = neko.NativeString; +typedef BytesData = neko.NativeString; #elseif flash - typedef BytesData = flash.utils.ByteArray; +typedef BytesData = flash.utils.ByteArray; #elseif cpp - typedef BytesData = Array< cpp.UInt8 >; +typedef BytesData = Array; #elseif java - typedef BytesData = java.NativeArray; +typedef BytesData = java.NativeArray; #elseif cs - typedef BytesData = cs.NativeArray; +typedef BytesData = cs.NativeArray; #elseif python - typedef BytesData = python.Bytearray; +typedef BytesData = python.Bytearray; #elseif js - typedef BytesData = js.html.ArrayBuffer; +typedef BytesData = js.lib.ArrayBuffer; #elseif hl - class BytesDataImpl { - public var bytes : hl.Bytes; - public var length : Int; - public function new(b,length) { - this.bytes = b; - this.length = length; - } +class BytesDataImpl { + public var bytes:hl.Bytes; + public var length:Int; + + public function new(b, length) { + this.bytes = b; + this.length = length; + } +} + +@:forward(bytes, length) +abstract BytesDataAbstract(BytesDataImpl) { + public inline function new(b, length) { + this = new BytesDataImpl(b, length); } - @:forward(bytes,length) - abstract BytesDataAbstract(BytesDataImpl) { - public inline function new(b, length) { - this = new BytesDataImpl(b, length); - } - @:arrayAccess inline function get(i:Int) return this.bytes[i]; - @:arrayAccess inline function set(i:Int,v:Int) return this.bytes[i] = v; - @:to inline function toBytes() : hl.Bytes { - return this == null ? null : this.bytes; - } + + @:arrayAccess inline function get(i:Int) + return this.bytes[i]; + + @:arrayAccess inline function set(i:Int, v:Int) + return this.bytes[i] = v; + + @:to inline function toBytes():hl.Bytes { + return this == null ? null : this.bytes; } - typedef BytesData = BytesDataAbstract; +} + +typedef BytesData = BytesDataAbstract; #else - typedef BytesData = Array; +typedef BytesData = Array; #end diff --git a/std/haxe/io/BytesInput.hx b/std/haxe/io/BytesInput.hx index 1d03429301b..9d63d365855 100644 --- a/std/haxe/io/BytesInput.hx +++ b/std/haxe/io/BytesInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,33 +19,37 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; class BytesInput extends Input { - var b : #if js js.html.Uint8Array #elseif hl hl.Bytes #else BytesData #end; + var b:#if js js.lib.Uint8Array #elseif hl hl.Bytes #else BytesData #end; #if !flash - var pos : Int; - var len : Int; - var totlen : Int; + var pos:Int; + var len:Int; + var totlen:Int; #end /** The current position in the stream in bytes. */ - public var position(get,set) : Int; + public var position(get, set):Int; /** The length of the stream in bytes. */ - public var length(get,never) : Int; - - public function new( b : Bytes, ?pos : Int, ?len : Int ) { - if( pos == null ) pos = 0; - if( len == null ) len = b.length - pos; - if( pos < 0 || len < 0 || pos + len > b.length ) throw Error.OutsideBounds; + public var length(get, never):Int; + + public function new(b:Bytes, ?pos:Int, ?len:Int) { + if (pos == null) + pos = 0; + if (len == null) + len = b.length - pos; + if (pos < 0 || len < 0 || pos + len > b.length) + throw Error.OutsideBounds; #if flash var ba = b.getData(); ba.position = pos; - if( len != ba.bytesAvailable ) { + if (len != ba.bytesAvailable) { // truncate this.b = new flash.utils.ByteArray(); - ba.readBytes(this.b,0,len); + ba.readBytes(this.b, 0, len); } else this.b = ba; this.b.endian = flash.utils.Endian.LITTLE_ENDIAN; @@ -60,7 +64,7 @@ class BytesInput extends Input { #end } - inline function get_position() : Int { + inline function get_position():Int { #if flash return b.position; #else @@ -68,7 +72,7 @@ class BytesInput extends Input { #end } - inline function get_length() : Int { + inline function get_length():Int { #if flash return b.length; #else @@ -76,9 +80,11 @@ class BytesInput extends Input { #end } - function set_position( p : Int ) : Int { - if( p < 0 ) p = 0; - else if( p > length ) p = length; + function set_position(p:Int):Int { + if (p < 0) + p = 0; + else if (p > length) + p = length; #if flash return b.position = p; #else @@ -87,67 +93,80 @@ class BytesInput extends Input { #end } - public override function readByte() : Int { + public override function readByte():Int { #if flash - return try b.readUnsignedByte() catch( e : Dynamic ) throw new Eof(); + return try b.readUnsignedByte() catch (e:Dynamic) throw new Eof(); #else - if( this.len == 0 ) - throw new Eof(); - len--; - #if neko - return untyped __dollar__sget(b,pos++); - #elseif cpp - return untyped b[pos++]; - #elseif java - return untyped b[pos++] & 0xFF; - #else - return b[pos++]; - #end + if (this.len == 0) + throw new Eof(); + len--; + #if neko + return untyped __dollar__sget(b, pos++); + #elseif cpp + return untyped b[pos++]; + #elseif java + return untyped b[pos++] & 0xFF; + #elseif python // dodge https://github.com/HaxeFoundation/haxe/issues/5080 + var b = b[pos]; + pos++; + return b; + #else + return b[pos++]; + #end #end } - public override function readBytes( buf : Bytes, pos : Int, len : Int ) : Int { + public override function readBytes(buf:Bytes, pos:Int, len:Int):Int { #if !neko - if( pos < 0 || len < 0 || pos + len > buf.length ) - throw Error.OutsideBounds; + if (pos < 0 || len < 0 || pos + len > buf.length) + throw Error.OutsideBounds; #end #if flash - var avail : Int = b.bytesAvailable; - if( len > avail && avail > 0 ) len = avail; - try b.readBytes(buf.getData(),pos,len) catch( e : Dynamic ) throw new Eof(); + var avail:Int = b.bytesAvailable; + if (len > avail && avail > 0) + len = avail; + try + b.readBytes(buf.getData(), pos, len) + catch (e:Dynamic) + throw new Eof(); #elseif java - var avail : Int = this.len; - if ( len > avail ) len = avail; - if (len == 0) - throw new Eof(); - java.lang.System.arraycopy(this.b, this.pos, buf.getData(), pos, len); - this.pos += len; - this.len -= len; + var avail:Int = this.len; + if (len > avail) + len = avail; + if (len == 0) + throw new Eof(); + java.lang.System.arraycopy(this.b, this.pos, buf.getData(), pos, len); + this.pos += len; + this.len -= len; #elseif cs - var avail : Int = this.len; - if ( len > avail ) len = avail; - if (len == 0) - throw new Eof(); - cs.system.Array.Copy(this.b,this.pos, buf.getData(), pos, len); - this.pos += len; - this.len -= len; + var avail:Int = this.len; + if (len > avail) + len = avail; + if (len == 0) + throw new Eof(); + cs.system.Array.Copy(this.b, this.pos, buf.getData(), pos, len); + this.pos += len; + this.len -= len; #else - if( this.len == 0 && len > 0 ) - throw new Eof(); - if( this.len < len ) - len = this.len; - #if neko - try untyped __dollar__sblit(buf.getData(),pos,b,this.pos,len) catch( e : Dynamic ) throw Error.OutsideBounds; - #elseif hl - @:privateAccess buf.b.blit(pos, b, this.pos, len); - #else - var b1 = b; - var b2 = #if js @:privateAccess buf.b #else buf.getData() #end; - for( i in 0...len ) - b2[pos+i] = b1[this.pos+i]; - #end - this.pos += len; - this.len -= len; + if (this.len == 0 && len > 0) + throw new Eof(); + if (this.len < len) + len = this.len; + #if neko + try + untyped __dollar__sblit(buf.getData(), pos, b, this.pos, len) + catch (e:Dynamic) + throw Error.OutsideBounds; + #elseif hl + @:privateAccess buf.b.blit(pos, b, this.pos, len); + #else + var b1 = b; + var b2 = #if js @:privateAccess buf.b #else buf.getData() #end; + for (i in 0...len) + b2[pos + i] = b1[this.pos + i]; + #end + this.pos += len; + this.len -= len; #end return len; } @@ -162,39 +181,37 @@ class BytesInput extends Input { @:dox(hide) override function readFloat() { - return try b.readFloat() catch( e : Dynamic ) throw new Eof(); + return try b.readFloat() catch (e:Dynamic) throw new Eof(); } @:dox(hide) override function readDouble() { - return try b.readDouble() catch( e : Dynamic ) throw new Eof(); + return try b.readDouble() catch (e:Dynamic) throw new Eof(); } @:dox(hide) override function readInt8() { - return try b.readByte() catch( e : Dynamic ) throw new Eof(); + return try b.readByte() catch (e:Dynamic) throw new Eof(); } @:dox(hide) override function readInt16() { - return try b.readShort() catch( e : Dynamic ) throw new Eof(); + return try b.readShort() catch (e:Dynamic) throw new Eof(); } @:dox(hide) - override function readUInt16() : Int { - return try b.readUnsignedShort() catch( e : Dynamic ) throw new Eof(); + override function readUInt16():Int { + return try b.readUnsignedShort() catch (e:Dynamic) throw new Eof(); } @:dox(hide) - override function readInt32() : Int { - return try b.readInt() catch( e : Dynamic ) throw new Eof(); + override function readInt32():Int { + return try b.readInt() catch (e:Dynamic) throw new Eof(); } @:dox(hide) - override function readString( len : Int ) { - return try b.readUTFBytes(len) catch( e : Dynamic ) throw new Eof(); + override function readString(len:Int, ?encoding:Encoding) { + return try encoding == RawNative ? b.readMultiByte(len, "unicode") : b.readUTFBytes(len) catch (e:Dynamic) throw new Eof(); } - #end - } diff --git a/std/haxe/io/BytesOutput.hx b/std/haxe/io/BytesOutput.hx index 8f5ea7fa0d3..f6391615e29 100644 --- a/std/haxe/io/BytesOutput.hx +++ b/std/haxe/io/BytesOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,18 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; class BytesOutput extends Output { - #if flash - var b : flash.utils.ByteArray; + var b:flash.utils.ByteArray; #else - var b : BytesBuffer; + var b:BytesBuffer; #end /** The length of the stream in bytes. **/ - public var length(get,never) : Int; + public var length(get, never):Int; public function new() { #if flash @@ -44,7 +44,7 @@ class BytesOutput extends Output { #end } - inline function get_length() : Int { + inline function get_length():Int { return b.length; } @@ -56,12 +56,13 @@ class BytesOutput extends Output { #end } - override function writeBytes( buf : Bytes, pos, len ) : Int { + override function writeBytes(buf:Bytes, pos, len):Int { #if flash - if( pos < 0 || len < 0 || pos + len > buf.length ) throw Error.OutsideBounds; - b.writeBytes(buf.getData(),pos,len); + if (pos < 0 || len < 0 || pos + len > buf.length) + throw Error.OutsideBounds; + b.writeBytes(buf.getData(), pos, len); #else - b.addBytes(buf,pos,len); + b.addBytes(buf, pos, len); #end return len; } @@ -77,49 +78,54 @@ class BytesOutput extends Output { } @:dox(hide) - override function writeFloat( f : Float ) { + override function writeFloat(f:Float) { b.writeFloat(f); } @:dox(hide) - override function writeDouble( f : Float ) { + override function writeDouble(f:Float) { b.writeDouble(f); } @:dox(hide) - override function writeInt8( x : Int ) { - if( x < -0x80 || x >= 0x80 ) + override function writeInt8(x:Int) { + if (x < -0x80 || x >= 0x80) throw Error.Overflow; b.writeByte(x); } @:dox(hide) - override function writeInt16( x : Int ) { - if( x < -0x8000 || x >= 0x8000 ) throw Error.Overflow; + override function writeInt16(x:Int) { + if (x < -0x8000 || x >= 0x8000) + throw Error.Overflow; b.writeShort(x); } @:dox(hide) - override function writeUInt16( x : Int ) { - if( x < 0 || x >= 0x10000 ) throw Error.Overflow; + override function writeUInt16(x:Int) { + if (x < 0 || x >= 0x10000) + throw Error.Overflow; b.writeShort(x); } @:dox(hide) - override function writeInt32( x : Int ) { + override function writeInt32(x:Int) { b.writeInt(x); } @:dox(hide) - override function prepare( size : Int ) { - if( size > 0 ) b[size-1] = b[size-1]; + override function prepare(size:Int) { + if (size > 0) + b[size - 1] = b[size - 1]; } @:dox(hide) - override function writeString( s : String ) { - b.writeUTFBytes(s); + override function writeString(s:String, ?encoding:Encoding) { + if (encoding == RawNative) + b.writeMultiByte(s, "unicode"); + else + b.writeUTFBytes(s); } - #end /** @@ -128,14 +134,13 @@ class BytesOutput extends Output { This function should not be called more than once on a given `BytesOutput` instance. **/ - public function getBytes() : Bytes { + public function getBytes():Bytes { #if flash var bytes = b; b = null; - return untyped new Bytes(bytes.length,bytes); + return untyped new Bytes(bytes.length, bytes); #else return b.getBytes(); #end } - } diff --git a/std/lua/lib/environ/Environ.hx b/std/haxe/io/Encoding.hx similarity index 79% rename from std/lua/lib/environ/Environ.hx rename to std/haxe/io/Encoding.hx index 769287f6d25..d51cdd65b44 100644 --- a/std/lua/lib/environ/Environ.hx +++ b/std/haxe/io/Encoding.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,11 +20,16 @@ * DEALINGS IN THE SOFTWARE. */ -package lua.lib.environ; -@:luaRequire("environ.process") -extern class Environ { - static function getenv(arg : String) : String; - static function setenv(arg : String, value : String) : Bool; - static var ENV : Table; -} +package haxe.io; + +/** + String binary encoding supported by Haxe I/O +**/ +enum Encoding { + UTF8; + /** + Output the string the way the platform represent it in memory. This is the most efficient but is platform-specific + **/ + RawNative; +} diff --git a/std/haxe/io/Eof.hx b/std/haxe/io/Eof.hx index 44548c9c578..75dea4098cc 100644 --- a/std/haxe/io/Eof.hx +++ b/std/haxe/io/Eof.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; /** This exception is raised when reading while data is no longer available in the `haxe.io.Input`. **/ class Eof { - public function new() { - } + public function new() {} @:ifFeature("haxe.io.Eof.*") function toString() { diff --git a/std/haxe/io/Error.hx b/std/haxe/io/Error.hx index 86c9dc5951e..7dece351d33 100644 --- a/std/haxe/io/Error.hx +++ b/std/haxe/io/Error.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; /** @@ -27,10 +28,13 @@ package haxe.io; enum Error { /** The IO is set into nonblocking mode and some data cannot be read or written **/ Blocked; + /** An integer value is outside its allowed range **/ Overflow; + /** An operation on Bytes is outside of its valid range **/ OutsideBounds; + /** Other errors **/ - Custom( e : Dynamic ); + Custom(e:Dynamic); } diff --git a/std/haxe/io/FPHelper.hx b/std/haxe/io/FPHelper.hx index ac1430dee58..0d7af0e8722 100644 --- a/std/haxe/io/FPHelper.hx +++ b/std/haxe/io/FPHelper.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; /** @@ -26,192 +27,236 @@ package haxe.io; Always works in low-endian encoding. **/ class FPHelper { - #if neko_v21 // stored in helper #elseif neko - static var i64tmp = new neko.vm.Tls(); - #elseif !(java || cs) + static var i64tmp = new sys.thread.Tls(); + #elseif !(java || cs || cpp) static var i64tmp = Int64.ofInt(0); + + static inline var LN2 = 0.6931471805599453; // Math.log(2) + + static inline function _i32ToFloat(i:Int):Float { + var sign = 1 - ((i >>> 31) << 1); + var e = (i >> 23) & 0xff; + if (e == 255) + return i & 0x7fffff == 0 ? (sign > 0 ? Math.POSITIVE_INFINITY : Math.NEGATIVE_INFINITY) : Math.NaN; + var m = e == 0 ? (i & 0x7fffff) << 1 : (i & 0x7fffff) | 0x800000; + return sign * m * Math.pow(2, e - 150); + } + + static inline function _i64ToDouble(lo:Int, hi:Int):Float { + var sign = 1 - ((hi >>> 31) << 1); + var e = (hi >> 20) & 0x7ff; + if (e == 2047) + return lo == 0 && (hi & 0xFFFFF) == 0 ? (sign > 0 ? Math.POSITIVE_INFINITY : Math.NEGATIVE_INFINITY) : Math.NaN; + var m = 2.220446049250313e-16 * ((hi & 0xFFFFF) * 4294967296. + (lo >>> 31) * 2147483648. + (lo & 0x7FFFFFFF)); + m = e == 0 ? m * 2.0 : m + 1.0; + return sign * m * Math.pow(2, e - 1023); + } + + static inline function _floatToI32(f:Float):Int { + if (f == 0) + return 0; + var af = f < 0 ? -f : f; + var exp = Math.floor(Math.log(af) / LN2); + if (exp > 127) { + return 0x7F800000; + } else { + if (exp <= -127) { + exp = -127; + af *= 7.1362384635298e+44; // af * 0.5 * 0x800000 / Math.pow(2, -127) + } else { + af = (af / Math.pow(2, exp) - 1.0) * 0x800000; + } + return (f < 0 ? 0x80000000 : 0) | ((exp + 127) << 23) | Math.round(af); + } + } + + static inline function _doubleToI64(v:Float):Int64@:privateAccess { + var i64 = i64tmp; + if (v == 0) { + i64.set_low(0); + i64.set_high(0); + } else if (!Math.isFinite(v)) { + i64.set_low(0); + i64.set_high(v > 0 ? 0x7FF00000 : 0xFFF00000); + } else { + var av = v < 0 ? -v : v; + var exp = Math.floor(Math.log(av) / LN2); + if (exp > 1023) { + i64.set_low(0xFFFFFFFF); + i64.set_high(0x7FEFFFFF); + } else { + if (exp <= -1023) { + exp = -1023; + av = av / 2.2250738585072014e-308; + } else { + av = av / Math.pow(2, exp) - 1.0; + } + var sig = Math.fround(av * 4503599627370496.); // 2^52 + // Note: If "sig" is outside of the signed Int32 range, the result is unspecified in HL, C#, Java and Neko, + var sig_l = Std.int(sig); + var sig_h = Std.int(sig / 4294967296.0); + i64.set_low(sig_l); + i64.set_high((v < 0 ? 0x80000000 : 0) | ((exp + 1023) << 20) | sig_h); + } + } + return i64; + } #end #if neko - #if neko_v21 - static var helpers = new neko.vm.Tls>(); - #else - static var helperf = new neko.vm.Tls(); - static var helperd = new neko.vm.Tls(); - static var _float_of_bytes = neko.Lib.load("std","float_of_bytes",2); - static var _double_of_bytes = neko.Lib.load("std","double_of_bytes",2); - static var _float_bytes = neko.Lib.load("std","float_bytes",2); - static var _double_bytes = neko.Lib.load("std","double_bytes",2); - #end + #if neko_v21 + static var helpers = new sys.thread.Tls>(); + #else + static var helperf = new sys.thread.Tls(); + static var helperd = new sys.thread.Tls(); + static var _float_of_bytes = neko.Lib.load("std", "float_of_bytes", 2); + static var _double_of_bytes = neko.Lib.load("std", "double_of_bytes", 2); + static var _float_bytes = neko.Lib.load("std", "float_bytes", 2); + static var _double_bytes = neko.Lib.load("std", "double_bytes", 2); + #end #elseif flash - static var helper = { - var b = new flash.utils.ByteArray(); - b.endian = flash.utils.Endian.LITTLE_ENDIAN; - b; - } + static var helper = { + var b = new flash.utils.ByteArray(); + b.endian = flash.utils.Endian.LITTLE_ENDIAN; + b; + } #elseif js - static var helper = new js.html.DataView(new js.html.ArrayBuffer(8)); - #else - static inline var LN2 = 0.6931471805599453; // Math.log(2) + static var helper = new js.lib.DataView(new js.lib.ArrayBuffer(8)); #end - #if neko_v21 inline #end - public static function i32ToFloat( i : Int ) : Float { + #if neko_v21 + inline + #end + public static function i32ToFloat(i:Int):Float { #if neko - #if neko_v21 - return untyped $itof(i,false); - #else - var helper = helperf.value; - if( helper == null ) - helperf.value = helper = neko.NativeString.alloc(4); - untyped $sset(helper,0,i&0xFF); - untyped $sset(helper,1,(i>>8)&0xFF); - untyped $sset(helper,2,(i>>16)&0xFF); - untyped $sset(helper,3,i>>>24); - return _float_of_bytes(helper,false); - #end + #if neko_v21 + return untyped $itof(i, false); + #else + var helper = helperf.value; + if (helper == null) + helperf.value = helper = neko.NativeString.alloc(4); + untyped $sset(helper, 0, i & 0xFF); + untyped $sset(helper, 1, (i >> 8) & 0xFF); + untyped $sset(helper, 2, (i >> 16) & 0xFF); + untyped $sset(helper, 3, i >>> 24); + return _float_of_bytes(helper, false); + #end #elseif cpp - return untyped __global__.__hxcpp_reinterpret_le_int32_as_float32(i); + return untyped __global__.__hxcpp_reinterpret_le_int32_as_float32(i); #elseif cs - var helper = new SingleHelper(0); - if( cs.system.BitConverter.IsLittleEndian ) - { - helper.i = i; - } else { - helper.i = ((i >>> 24) & 0xFF) | (((i >> 16) & 0xFF) << 8) | (((i >> 8) & 0xFF) << 16) | ((i & 0xFF) << 24); - } + var helper = new SingleHelper(0); + if (cs.system.BitConverter.IsLittleEndian) { + helper.i = i; + } else { + helper.i = ((i >>> 24) & 0xFF) | (((i >> 16) & 0xFF) << 8) | (((i >> 8) & 0xFF) << 16) | ((i & 0xFF) << 24); + } - return helper.f; + return helper.f; #elseif java - return java.lang.Float.FloatClass.intBitsToFloat(i); + return java.lang.Float.FloatClass.intBitsToFloat(i); #elseif flash - var helper = helper; - helper.position = 0; - helper.writeUnsignedInt(i); - helper.position = 0; - return helper.readFloat(); + var helper = helper; + helper.position = 0; + helper.writeUnsignedInt(i); + helper.position = 0; + return helper.readFloat(); #elseif js - helper.setInt32(0, i, true); - return helper.getFloat32(0, true); + helper.setInt32(0, i, true); + return helper.getFloat32(0, true); #else - var sign = 1 - ((i >>> 31) << 1); - var exp = (i >>> 23) & 0xFF; - var sig = i & 0x7FFFFF; - if( sig == 0 && exp == 0 ) - return 0.0; - return sign*(1 + Math.pow(2, -23)*sig) * Math.pow(2, exp-127); + return _i32ToFloat(i); #end } - #if neko_v21 inline #end - public static function floatToI32( f : Float ) : Int { + #if neko_v21 + inline + #end + public static function floatToI32(f:Float):Int { #if neko - #if neko_v21 - return untyped $ftoi(f,false); - #else - var r = _float_bytes(f,false); - return untyped $sget(r,0) | ($sget(r,1)<<8) | ($sget(r,2)<<16) | ($sget(r,3)<<24); - #end + #if neko_v21 + return untyped $ftoi(f, false); + #else + var r = _float_bytes(f, false); + return untyped $sget(r, 0) | ($sget(r, 1) << 8) | ($sget(r, 2) << 16) | ($sget(r, 3) << 24); + #end #elseif cpp - return untyped __global__.__hxcpp_reinterpret_float32_as_le_int32(f); + return untyped __global__.__hxcpp_reinterpret_float32_as_le_int32(f); #elseif cs - var helper = new SingleHelper(f); - if( cs.system.BitConverter.IsLittleEndian ) - { - return helper.i; - } else { - var i = helper.i; - return ((i >>> 24) & 0xFF) | (((i >> 16) & 0xFF) << 8) | (((i >> 8) & 0xFF) << 16) | ((i & 0xFF) << 24); - } + var helper = new SingleHelper(f); + if (cs.system.BitConverter.IsLittleEndian) { + return helper.i; + } else { + var i = helper.i; + return ((i >>> 24) & 0xFF) | (((i >> 16) & 0xFF) << 8) | (((i >> 8) & 0xFF) << 16) | ((i & 0xFF) << 24); + } #elseif java - return java.lang.Float.FloatClass.floatToRawIntBits(f); + return java.lang.Float.FloatClass.floatToRawIntBits(f); #elseif flash - var helper = helper; - helper.position = 0; - helper.writeFloat(f); - helper.position = 0; - return helper.readUnsignedInt(); + var helper = helper; + helper.position = 0; + helper.writeFloat(f); + helper.position = 0; + return helper.readUnsignedInt(); #elseif js - helper.setFloat32(0, f, true); - return helper.getInt32(0,true); + helper.setFloat32(0, f, true); + return helper.getInt32(0, true); #else - if( f == 0 ) return 0; - var af = f < 0 ? -f : f; - var exp = Math.floor(Math.log(af) / LN2); - if( exp < -127 ) exp = -127 else if( exp > 128 ) exp = 128; - var sig = Math.round((af / Math.pow(2, exp) - 1) * 0x800000); - if( sig == 0x800000 && exp < 128 ){ - sig = 0; - exp++; - } - return (f < 0 ? 0x80000000 : 0) | ((exp + 127) << 23) | sig; + return _floatToI32(f); #end } - #if neko_v21 inline #end - public static function i64ToDouble( low : Int, high : Int ) : Float { + #if neko_v21 + inline + #end + public static function i64ToDouble(low:Int, high:Int):Float { #if neko - #if neko_v21 - return untyped $itod(low,high,false); - #else - var helper = helperd.value; - if( helper == null ) - helperd.value = helper = neko.NativeString.alloc(8); - untyped $sset(helper,0,low&0xFF); - untyped $sset(helper,1,(low>>8)&0xFF); - untyped $sset(helper,2,(low>>16)&0xFF); - untyped $sset(helper,3,low>>>24); - untyped $sset(helper,4,high&0xFF); - untyped $sset(helper,5,(high>>8)&0xFF); - untyped $sset(helper,6,(high>>16)&0xFF); - untyped $sset(helper,7,high>>>24); - return _double_of_bytes(helper,false); - #end + #if neko_v21 + return untyped $itod(low, high, false); + #else + var helper = helperd.value; + if (helper == null) + helperd.value = helper = neko.NativeString.alloc(8); + untyped $sset(helper, 0, low & 0xFF); + untyped $sset(helper, 1, (low >> 8) & 0xFF); + untyped $sset(helper, 2, (low >> 16) & 0xFF); + untyped $sset(helper, 3, low >>> 24); + untyped $sset(helper, 4, high & 0xFF); + untyped $sset(helper, 5, (high >> 8) & 0xFF); + untyped $sset(helper, 6, (high >> 16) & 0xFF); + untyped $sset(helper, 7, high >>> 24); + return _double_of_bytes(helper, false); + #end #elseif cpp - return untyped __global__.__hxcpp_reinterpret_le_int32s_as_float64(low,high); + return untyped __global__.__hxcpp_reinterpret_le_int32s_as_float64(low, high); #elseif cs - var helper = new FloatHelper(0); - if( cs.system.BitConverter.IsLittleEndian ) - { - helper.i = haxe.Int64.make(high,low); - } else { - var i1 = high, - i2 = low; - var j2 = ((i1 >>> 24) & 0xFF) | (((i1 >> 16) & 0xFF) << 8) | (((i1 >> 8) & 0xFF) << 16) | ((i1 & 0xFF) << 24); - var j1 = ((i2 >>> 24) & 0xFF) | (((i2 >> 16) & 0xFF) << 8) | (((i2 >> 8) & 0xFF) << 16) | ((i2 & 0xFF) << 24); - helper.i = haxe.Int64.make(j1,j2); - } - return helper.f; + var helper = new FloatHelper(0); + if (cs.system.BitConverter.IsLittleEndian) { + helper.i = haxe.Int64.make(high, low); + } else { + var i1 = high, i2 = low; + var j2 = ((i1 >>> 24) & 0xFF) | (((i1 >> 16) & 0xFF) << 8) | (((i1 >> 8) & 0xFF) << 16) | ((i1 & 0xFF) << 24); + var j1 = ((i2 >>> 24) & 0xFF) | (((i2 >> 16) & 0xFF) << 8) | (((i2 >> 8) & 0xFF) << 16) | ((i2 & 0xFF) << 24); + helper.i = haxe.Int64.make(j1, j2); + } + return helper.f; #elseif java - return java.lang.Double.DoubleClass.longBitsToDouble( Int64.make(high,low) ); + return java.lang.Double.DoubleClass.longBitsToDouble(Int64.make(high, low)); #elseif flash - var helper = helper; - helper.position = 0; - helper.writeUnsignedInt(low); - helper.writeUnsignedInt(high); - helper.position = 0; - return helper.readDouble(); + var helper = helper; + helper.position = 0; + helper.writeUnsignedInt(low); + helper.writeUnsignedInt(high); + helper.position = 0; + return helper.readDouble(); #elseif js - helper.setInt32(0, low , true); - helper.setInt32(4, high, true); - return helper.getFloat64(0,true); + helper.setInt32(0, low, true); + helper.setInt32(4, high, true); + return helper.getFloat64(0, true); #else - #if python - if (low == 0 && high == 2146435072) { - return Math.POSITIVE_INFINITY; - } else if (low == 0 && high == -1048576 ) { - return Math.NEGATIVE_INFINITY; - } - #end - var sign = 1 - ((high >>> 31) << 1); - var exp = ((high >> 20) & 0x7FF) - 1023; - var sig = (high&0xFFFFF) * 4294967296. + (low>>>31) * 2147483648. + (low&0x7FFFFFFF); - if( sig == 0 && exp == -1023 ) - return 0.0; - return sign*(1.0 + Math.pow(2, -52)*sig) * Math.pow(2, exp); + return _i64ToDouble(low, high); #end } @@ -220,131 +265,98 @@ class FPHelper { WARNING : for performance reason, the same Int64 value might be reused every time. Copy its low/high values before calling again. We still ensure that this is safe to use in a multithread environment **/ - public static function doubleToI64( v : Float ) : Int64 { + public static function doubleToI64(v:Float):Int64 { #if neko - #if neko_v21 - var helper = helpers.value; - if( helper == null ) { - helpers.value = helper = neko.NativeArray.alloc(2); - helper[0] = neko.NativeArray.alloc(2); - helper[1] = haxe.Int64.ofInt(0); - } - var i64 : haxe.Int64 = helper[1], int2 = helper[0]; - untyped $dtoi(v,int2,false); - @:privateAccess { - i64.set_low(int2[0]); - i64.set_high(int2[1]); - } - return i64; - #else - var r = _double_bytes(v,false), i64 = i64tmp.value; - if( i64 == null ) - i64 = i64tmp.value = haxe.Int64.ofInt(0); - @:privateAccess { - i64.set_low(untyped $sget(r,0) | ($sget(r,1)<<8) | ($sget(r,2)<<16) | ($sget(r,3)<<24)); - i64.set_high(untyped $sget(r,4) | ($sget(r,5)<<8) | ($sget(r,6)<<16) | ($sget(r,7)<<24)); - } - return i64; - #end + #if neko_v21 + var helper = helpers.value; + if (helper == null) { + helpers.value = helper = neko.NativeArray.alloc(2); + helper[0] = neko.NativeArray.alloc(2); + helper[1] = haxe.Int64.ofInt(0); + } + var i64:haxe.Int64 = helper[1], int2 = helper[0]; + untyped $dtoi(v, int2, false); + @:privateAccess { + i64.set_low(int2[0]); + i64.set_high(int2[1]); + } + return i64; + #else + var r = _double_bytes(v, false), i64 = i64tmp.value; + if (i64 == null) + i64 = i64tmp.value = haxe.Int64.ofInt(0); + @:privateAccess { + i64.set_low(untyped $sget(r, 0) | ($sget(r, 1) << 8) | ($sget(r, 2) << 16) | ($sget(r, 3) << 24)); + i64.set_high(untyped $sget(r, 4) | ($sget(r, 5) << 8) | ($sget(r, 6) << 16) | ($sget(r, 7) << 24)); + } + return i64; + #end #elseif cpp - return Int64.make(untyped __global__.__hxcpp_reinterpret_float64_as_le_int32_high(v), - untyped __global__.__hxcpp_reinterpret_float64_as_le_int32_low(v) ); + return Int64.make(untyped __global__.__hxcpp_reinterpret_float64_as_le_int32_high(v), + untyped __global__.__hxcpp_reinterpret_float64_as_le_int32_low(v)); #elseif java - return java.lang.Double.DoubleClass.doubleToRawLongBits(v); + return java.lang.Double.DoubleClass.doubleToRawLongBits(v); #elseif cs - var helper = new FloatHelper(v); - if( cs.system.BitConverter.IsLittleEndian ) - { - return helper.i; - } else { - var i = helper.i; - var i1 = haxe.Int64.getHigh(i), - i2 = haxe.Int64.getLow(i); - var j2 = ((i1 >>> 24) & 0xFF) | (((i1 >> 16) & 0xFF) << 8) | (((i1 >> 8) & 0xFF) << 16) | ((i1 & 0xFF) << 24); - var j1 = ((i2 >>> 24) & 0xFF) | (((i2 >> 16) & 0xFF) << 8) | (((i2 >> 8) & 0xFF) << 16) | ((i2 & 0xFF) << 24); + var helper = new FloatHelper(v); + if (cs.system.BitConverter.IsLittleEndian) { + return helper.i; + } else { + var i = helper.i; + var i1 = haxe.Int64.getHigh(i), i2 = haxe.Int64.getLow(i); + var j2 = ((i1 >>> 24) & 0xFF) | (((i1 >> 16) & 0xFF) << 8) | (((i1 >> 8) & 0xFF) << 16) | ((i1 & 0xFF) << 24); + var j1 = ((i2 >>> 24) & 0xFF) | (((i2 >> 16) & 0xFF) << 8) | (((i2 >> 8) & 0xFF) << 16) | ((i2 & 0xFF) << 24); - return haxe.Int64.make(j1,j2); - } + return haxe.Int64.make(j1, j2); + } #elseif flash - var helper = helper; - helper.position = 0; - helper.writeDouble(v); - helper.position = 0; - var i64 = i64tmp; - @:privateAccess { - i64.set_low(cast helper.readUnsignedInt()); - i64.set_high(cast helper.readUnsignedInt()); - } - return i64; + var helper = helper; + helper.position = 0; + helper.writeDouble(v); + helper.position = 0; + var i64 = i64tmp; + @:privateAccess { + i64.set_low(cast helper.readUnsignedInt()); + i64.set_high(cast helper.readUnsignedInt()); + } + return i64; #elseif js - var i64 = i64tmp; - helper.setFloat64(0, v, true); - @:privateAccess { - i64.set_low(helper.getInt32(0,true)); - i64.set_high(helper.getInt32(4,true)); - } - return i64; + var i64 = i64tmp; + helper.setFloat64(0, v, true); + @:privateAccess { + i64.set_low(helper.getInt32(0, true)); + i64.set_high(helper.getInt32(4, true)); + } + return i64; #else - var i64 = i64tmp; - if( v == 0 ) { - @:privateAccess { - i64.set_low(0); - i64.set_high(0); - } - } else if (!Math.isFinite(v)) @:privateAccess { - if (v > 0) { - i64.set_low(0); - i64.set_high(2146435072); - } else { - i64.set_low(0); - i64.set_high(-1048576); - } - } else { - var av = v < 0 ? -v : v; - var exp = Math.floor(Math.log(av) / LN2); - var sig = Math.fround(((av / Math.pow(2, exp)) - 1) * 4503599627370496.); // 2^52 - var sig_l = Std.int(sig); - var sig_h = Std.int(sig / 4294967296.0); - @:privateAccess { - i64.set_low(sig_l); - i64.set_high((v < 0 ? 0x80000000 : 0) | ((exp + 1023) << 20) | sig_h); - } - } - return i64; + return _doubleToI64(v); #end } - } #if cs @:meta(System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)) -@:nativeGen @:struct private class SingleHelper -{ +@:nativeGen @:struct private class SingleHelper { @:meta(System.Runtime.InteropServices.FieldOffset(0)) public var i:Int; @:meta(System.Runtime.InteropServices.FieldOffset(0)) public var f:Single; - public function new(f:Single) - { + public function new(f:Single) { this.i = 0; this.f = f; } } @:meta(System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)) -@:nativeGen @:struct private class FloatHelper -{ +@:nativeGen @:struct private class FloatHelper { @:meta(System.Runtime.InteropServices.FieldOffset(0)) public var i:haxe.Int64; @:meta(System.Runtime.InteropServices.FieldOffset(0)) public var f:Float; - public function new(f:Float) - { + public function new(f:Float) { this.i = haxe.Int64.ofInt(0); this.f = f; } } - #end diff --git a/std/haxe/io/Float32Array.hx b/std/haxe/io/Float32Array.hx index 2fb078b7433..e7e086ff365 100644 --- a/std/haxe/io/Float32Array.hx +++ b/std/haxe/io/Float32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; typedef Float32ArrayData = ArrayBufferView.ArrayBufferViewData; abstract Float32Array(Float32ArrayData) { - public static inline var BYTES_PER_ELEMENT = 4; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int) { this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData(); } @@ -37,49 +38,50 @@ abstract Float32Array(Float32ArrayData) { return this.byteLength >> 2; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : Float { - return this.bytes.getFloat((index<<2) + this.byteOffset); + @:arrayAccess public inline function get(index:Int):Float { + return this.bytes.getFloat((index << 2) + this.byteOffset); } - @:arrayAccess public inline function set( index : Int, value : Float ) : Float { - if( index >= 0 && index < length ) { - this.bytes.setFloat((index<<2) + this.byteOffset, value); + @:arrayAccess public inline function set(index:Int, value:Float):Float { + if (index >= 0 && index < length) { + this.bytes.setFloat((index << 2) + this.byteOffset, value); return value; } return 0; } - public inline function sub( begin : Int, ?length : Int ) : Float32Array { - return fromData(this.sub(begin<<2,length == null ? null : length<<2)); + public inline function sub(begin:Int, ?length:Int):Float32Array { + return fromData(this.sub(begin << 2, length == null ? null : length << 2)); } - public inline function subarray( ?begin : Int, ?end : Int ) : Float32Array { - return fromData(this.subarray(begin==null?null:begin<<2,end==null?null:end<<2)); + public inline function subarray(?begin:Int, ?end:Int):Float32Array { + return fromData(this.subarray(begin == null ? null : begin << 2, end == null ? null : end << 2)); } - public inline function getData() : Float32ArrayData { + public inline function getData():Float32ArrayData { return this; } - public static function fromData( d : Float32ArrayData ) : Float32Array { + public static function fromData(d:Float32ArrayData):Float32Array { return cast d; } - public static function fromArray( a : Array, pos = 0, ?length : Int ) : Float32Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; + public static function fromArray(a:Array, pos = 0, ?length:Int):Float32Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; var i = new Float32Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos = 0, ?length : Int ) : Float32Array { - return fromData(ArrayBufferView.fromBytes(bytes,bytePos,(length == null ? (bytes.length - bytePos)>>2 : length)<<2).getData()); + public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):Float32Array { + return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 2 : length) << 2).getData()); } } - diff --git a/std/haxe/io/Float64Array.hx b/std/haxe/io/Float64Array.hx index 8f5314fe6eb..7221883ce5b 100644 --- a/std/haxe/io/Float64Array.hx +++ b/std/haxe/io/Float64Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; typedef Float64ArrayData = ArrayBufferView.ArrayBufferViewData; abstract Float64Array(Float64ArrayData) { - public static inline var BYTES_PER_ELEMENT = 8; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int) { this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData(); } @@ -37,49 +38,50 @@ abstract Float64Array(Float64ArrayData) { return this.byteLength >> 3; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : Float { - return this.bytes.getFloat((index<<3) + this.byteOffset); + @:arrayAccess public inline function get(index:Int):Float { + return this.bytes.getFloat((index << 3) + this.byteOffset); } - @:arrayAccess public inline function set( index : Int, value : Float ) : Float { - if( index >= 0 && index < length ) { - this.bytes.setFloat((index<<3) + this.byteOffset, value); + @:arrayAccess public inline function set(index:Int, value:Float):Float { + if (index >= 0 && index < length) { + this.bytes.setFloat((index << 3) + this.byteOffset, value); return value; } return 0; } - public inline function sub( begin : Int, ?length : Int ) : Float64Array { - return fromData(this.sub(begin<<3,length == null ? null : length<<3)); + public inline function sub(begin:Int, ?length:Int):Float64Array { + return fromData(this.sub(begin << 3, length == null ? null : length << 3)); } - public inline function subarray( ?begin : Int, ?end : Int ) : Float64Array { - return fromData(this.subarray(begin==null?null:begin<<3,end==null?null:end<<3)); + public inline function subarray(?begin:Int, ?end:Int):Float64Array { + return fromData(this.subarray(begin == null ? null : begin << 3, end == null ? null : end << 3)); } - public inline function getData() : Float64ArrayData { + public inline function getData():Float64ArrayData { return this; } - public static function fromData( d : Float64ArrayData ) : Float64Array { + public static function fromData(d:Float64ArrayData):Float64Array { return cast d; } - public static function fromArray( a : Array, pos = 0, ?length : Int ) : Float64Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; + public static function fromArray(a:Array, pos = 0, ?length:Int):Float64Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; var i = new Float64Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos = 0, ?length : Int ) : Float64Array { - return fromData(ArrayBufferView.fromBytes(bytes,bytePos,(length == null ? (bytes.length - bytePos)>>3 : length)<<3).getData()); + public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):Float64Array { + return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 3 : length) << 3).getData()); } } - diff --git a/std/haxe/io/Input.hx b/std/haxe/io/Input.hx index 158b79560b6..ccc09fb16a6 100644 --- a/std/haxe/io/Input.hx +++ b/std/haxe/io/Input.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; /** @@ -29,13 +30,12 @@ package haxe.io; is reached. **/ class Input { - /** Endianness (word byte order) used when reading numbers. If `true`, big-endian is used, otherwise `little-endian` is used. **/ - public var bigEndian(default,set) : Bool; + public var bigEndian(default, set):Bool; #if cs private var helper:BytesData; @@ -46,12 +46,12 @@ class Input { /** Read and return one byte. **/ - public function readByte() : Int { - #if cpp + public function readByte():Int { + #if cpp throw "Not implemented"; - #else + #else return throw "Not implemented"; - #end + #end } /** @@ -61,27 +61,27 @@ class Input { See `readFullBytes` that tries to read the exact amount of specified bytes. **/ - public function readBytes( s : Bytes, pos : Int, len : Int ) : Int { + public function readBytes(s:Bytes, pos:Int, len:Int):Int { var k = len; var b = #if (js || hl) @:privateAccess s.b #else s.getData() #end; - if( pos < 0 || len < 0 || pos + len > s.length ) + if (pos < 0 || len < 0 || pos + len > s.length) throw Error.OutsideBounds; try { - while( k > 0 ) { + while (k > 0) { #if neko - untyped __dollar__sset(b,pos,readByte()); + untyped __dollar__sset(b, pos, readByte()); #elseif php - b.set(pos, readByte()); + b.set(pos, readByte()); #elseif cpp - b[pos] = untyped readByte(); + b[pos] = untyped readByte(); #else - b[pos] = cast readByte(); + b[pos] = cast readByte(); #end pos++; k--; } - } catch (eof: haxe.io.Eof){} - return len-k; + } catch (eof:haxe.io.Eof) {} + return len - k; } /** @@ -89,40 +89,38 @@ class Input { Behaviour while reading after calling this method is unspecified. **/ - public function close() : Void { - } + public function close():Void {} - function set_bigEndian( b : Bool ) : Bool { + function set_bigEndian(b:Bool):Bool { bigEndian = b; return b; } /* ------------------ API ------------------ */ - /** Read and return all available data. The `bufsize` optional argument specifies the size of chunks by which data is read. Its default value is target-specific. **/ - public function readAll( ?bufsize : Int ) : Bytes { - if( bufsize == null ) - #if php + public function readAll(?bufsize:Int):Bytes { + if (bufsize == null) + #if php bufsize = 8192; // default value for PHP and max under certain circumstances - #else + #else bufsize = (1 << 14); // 16 Ko - #end + #end var buf = Bytes.alloc(bufsize); var total = new haxe.io.BytesBuffer(); try { - while( true ) { - var len = readBytes(buf,0,bufsize); - if( len == 0 ) + while (true) { + var len = readBytes(buf, 0, bufsize); + if (len == 0) throw Error.Blocked; - total.addBytes(buf,0,len); + total.addBytes(buf, 0, len); } - } catch( e : Eof ) { } + } catch (e:Eof) {} return total.getBytes(); } @@ -131,9 +129,9 @@ class Input { Unlike `readBytes`, this method tries to read the exact `len` amount of bytes. **/ - public function readFullBytes( s : Bytes, pos : Int, len : Int ) : Void { - while( len > 0 ) { - var k = readBytes(s,pos,len); + public function readFullBytes(s:Bytes, pos:Int, len:Int):Void { + while (len > 0) { + var k = readBytes(s, pos, len); if (k == 0) throw Error.Blocked; pos += k; @@ -144,12 +142,13 @@ class Input { /** Read and return `nbytes` bytes. **/ - public function read( nbytes : Int ) : Bytes { + public function read(nbytes:Int):Bytes { var s = Bytes.alloc(nbytes); var p = 0; - while( nbytes > 0 ) { - var k = readBytes(s,p,nbytes); - if( k == 0 ) throw Error.Blocked; + while (nbytes > 0) { + var k = readBytes(s, p, nbytes); + if (k == 0) + throw Error.Blocked; p += k; nbytes -= k; } @@ -161,11 +160,11 @@ class Input { The final character is not included in the resulting string. **/ - public function readUntil( end : Int ) : String { + public function readUntil(end:Int):String { var buf = new BytesBuffer(); - var last : Int; - while( (last = readByte()) != end ) - buf.addByte( last ); + var last:Int; + while ((last = readByte()) != end) + buf.addByte(last); return buf.getBytes().toString(); } @@ -174,18 +173,19 @@ class Input { The CR/LF characters are not included in the resulting string. **/ - public function readLine() : String { + public function readLine():String { var buf = new BytesBuffer(); - var last : Int; + var last:Int; var s; try { - while( (last = readByte()) != 10 ) - buf.addByte( last ); + while ((last = readByte()) != 10) + buf.addByte(last); s = buf.getBytes().toString(); - if( s.charCodeAt(s.length-1) == 13 ) s = s.substr(0,-1); - } catch( e : Eof ) { + if (s.charCodeAt(s.length - 1) == 13) + s = s.substr(0, -1); + } catch (e:Eof) { s = buf.getBytes().toString(); - if( s.length == 0 ) + if (s.length == 0) #if neko neko.Lib.rethrow #else throw #end (e); } return s; @@ -196,7 +196,7 @@ class Input { Endianness is specified by the `bigEndian` property. **/ - public function readFloat() : Float { + public function readFloat():Float { return FPHelper.i32ToFloat(readInt32()); } @@ -205,18 +205,18 @@ class Input { Endianness is specified by the `bigEndian` property. **/ - public function readDouble() : Float { + public function readDouble():Float { var i1 = readInt32(); var i2 = readInt32(); - return bigEndian ? FPHelper.i64ToDouble(i2,i1) : FPHelper.i64ToDouble(i1,i2); + return bigEndian ? FPHelper.i64ToDouble(i2, i1) : FPHelper.i64ToDouble(i1, i2); } /** Read a 8-bit signed integer. **/ - public function readInt8() : Int { + public function readInt8():Int { var n = readByte(); - if( n >= 128 ) + if (n >= 128) return n - 256; return n; } @@ -226,11 +226,11 @@ class Input { Endianness is specified by the `bigEndian` property. **/ - public function readInt16() : Int { + public function readInt16():Int { var ch1 = readByte(); var ch2 = readByte(); var n = bigEndian ? ch2 | (ch1 << 8) : ch1 | (ch2 << 8); - if( n & 0x8000 != 0 ) + if (n & 0x8000 != 0) return n - 0x10000; return n; } @@ -240,7 +240,7 @@ class Input { Endianness is specified by the `bigEndian` property. **/ - public function readUInt16() : Int { + public function readUInt16():Int { var ch1 = readByte(); var ch2 = readByte(); return bigEndian ? ch2 | (ch1 << 8) : ch1 | (ch2 << 8); @@ -251,12 +251,12 @@ class Input { Endianness is specified by the `bigEndian` property. **/ - public function readInt24() : Int { + public function readInt24():Int { var ch1 = readByte(); var ch2 = readByte(); var ch3 = readByte(); var n = bigEndian ? ch3 | (ch2 << 8) | (ch1 << 16) : ch1 | (ch2 << 8) | (ch3 << 16); - if( n & 0x800000 != 0 ) + if (n & 0x800000 != 0) return n - 0x1000000; return n; } @@ -266,7 +266,7 @@ class Input { Endianness is specified by the `bigEndian` property. **/ - public function readUInt24() : Int { + public function readUInt24():Int { var ch1 = readByte(); var ch2 = readByte(); var ch3 = readByte(); @@ -278,53 +278,54 @@ class Input { Endianness is specified by the `bigEndian` property. **/ - public function readInt32() : Int { + public function readInt32():Int { var ch1 = readByte(); var ch2 = readByte(); var ch3 = readByte(); var ch4 = readByte(); -#if (php || python) + #if (php || python) // php will overflow integers. Convert them back to signed 32-bit ints. var n = bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24); if (n & 0x80000000 != 0) - return ( n | 0x80000000); - else return n; -#elseif lua + return (n | 0x80000000); + else + return n; + #elseif lua var n = bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24); - return lua.Boot.clamp(n); -#else + return lua.Boot.clampInt32(n); + #else return bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24); -#end + #end } /** Read and `len` bytes as a string. **/ - public function readString( len : Int ) : String { + public function readString(len:Int, ?encoding:Encoding):String { var b = Bytes.alloc(len); - readFullBytes(b,0,len); + readFullBytes(b, 0, len); #if neko return neko.Lib.stringReference(b); #else - return b.toString(); + return b.getString(0, len, encoding); #end } -#if neko - static var _float_of_bytes = neko.Lib.load("std","float_of_bytes",2); - static var _double_of_bytes = neko.Lib.load("std","double_of_bytes",2); - static function __init__() untyped { - Input.prototype.bigEndian = false; - } -#end - -#if (flash || js || python) - function getDoubleSig(bytes:Array) - { - return (((bytes[1]&0xF) << 16) | (bytes[2] << 8) | bytes[3] ) * 4294967296. + - (bytes[4] >> 7) * 2147483648 + - (((bytes[4]&0x7F) << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]); - } -#end + #if neko + static var _float_of_bytes = neko.Lib.load("std", "float_of_bytes", 2); + static var _double_of_bytes = neko.Lib.load("std", "double_of_bytes", 2); + static function __init__() + untyped { + Input.prototype.bigEndian = false; + } + #end + + #if (flash || js || python) + function getDoubleSig(bytes:Array) { + return (((bytes[1] & 0xF) << 16) | (bytes[2] << 8) | bytes[3]) * 4294967296. + + (bytes[4] >> 7) * 2147483648 + + (((bytes[4] & 0x7F) << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]); + } + #end } diff --git a/std/haxe/io/Int32Array.hx b/std/haxe/io/Int32Array.hx index 56131f81a07..26543246ce5 100644 --- a/std/haxe/io/Int32Array.hx +++ b/std/haxe/io/Int32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; typedef Int32ArrayData = ArrayBufferView.ArrayBufferViewData; abstract Int32Array(Int32ArrayData) { - public static inline var BYTES_PER_ELEMENT = 4; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int) { this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData(); } @@ -37,49 +38,50 @@ abstract Int32Array(Int32ArrayData) { return this.byteLength >> 2; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : Int { - return this.bytes.getInt32((index<<2) + this.byteOffset); + @:arrayAccess public inline function get(index:Int):Int { + return this.bytes.getInt32((index << 2) + this.byteOffset); } - @:arrayAccess public inline function set( index : Int, value : Int ) : Int { - if( index >= 0 && index < length ) { - this.bytes.setInt32((index<<2) + this.byteOffset, value); + @:arrayAccess public inline function set(index:Int, value:Int):Int { + if (index >= 0 && index < length) { + this.bytes.setInt32((index << 2) + this.byteOffset, value); return value; } return 0; } - public inline function sub( begin : Int, ?length : Int ) : Int32Array { - return fromData(this.sub(begin<<2,length == null ? null : length<<2)); + public inline function sub(begin:Int, ?length:Int):Int32Array { + return fromData(this.sub(begin << 2, length == null ? null : length << 2)); } - public inline function subarray( ?begin : Int, ?end : Int ) : Int32Array { - return fromData(this.subarray(begin==null?null:begin<<2,end==null?null:end<<2)); + public inline function subarray(?begin:Int, ?end:Int):Int32Array { + return fromData(this.subarray(begin == null ? null : begin << 2, end == null ? null : end << 2)); } - public inline function getData() : Int32ArrayData { + public inline function getData():Int32ArrayData { return this; } - public static function fromData( d : Int32ArrayData ) : Int32Array { + public static function fromData(d:Int32ArrayData):Int32Array { return cast d; } - public static function fromArray( a : Array, pos = 0, ?length : Int ) : Int32Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; + public static function fromArray(a:Array, pos = 0, ?length:Int):Int32Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; var i = new Int32Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos = 0, ?length : Int ) : Int32Array { - return fromData(ArrayBufferView.fromBytes(bytes,bytePos,(length == null ? (bytes.length - bytePos)>>2 : length)<<2).getData()); + public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):Int32Array { + return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 2 : length) << 2).getData()); } } - diff --git a/std/haxe/io/Mime.hx b/std/haxe/io/Mime.hx new file mode 100644 index 00000000000..82a10b35a95 --- /dev/null +++ b/std/haxe/io/Mime.hx @@ -0,0 +1,321 @@ +package haxe.io; + +/** + HTML MimeType Enum + @see http://www.sitepoint.com/web-foundations/mime-types-complete-list/ +**/ +enum abstract Mime(String) from String to String { + var XWorldX3dmf = 'x-world/x-3dmf'; + var ApplicationOctetStream = 'application/octet-stream'; + var ApplicationXAuthorwareBin = 'application/x-authorware-bin'; + var ApplicationXAuthorwareMap = 'application/x-authorware-map'; + var ApplicationXAuthorwareSeg = 'application/x-authorware-seg'; + var TextVndAbc = 'text/vnd.abc'; + var TextHtml = 'text/html'; + var VideoAnimaflex = 'video/animaflex'; + var ApplicationPostscript = 'application/postscript'; + var AudioAiff = 'audio/aiff'; + var AudioXAiff = 'audio/x-aiff'; + var ApplicationXAim = 'application/x-aim'; + var TextXAudiosoftIntra = 'text/x-audiosoft-intra'; + var ApplicationXNaviAnimation = 'application/x-navi-animation'; + var ApplicationXNokia9000CommunicatorAddOnSoftware = 'application/x-nokia-9000-communicator-add-on-software'; + var ApplicationMime = 'application/mime'; + var ApplicationArj = 'application/arj'; + var ImageXJg = 'image/x-jg'; + var VideoXMsAsf = 'video/x-ms-asf'; + var TextXAsm = 'text/x-asm'; + var TextAsp = 'text/asp'; + var ApplicationXMplayer2 = 'application/x-mplayer2'; + var AudioBasic = 'audio/basic'; + var ApplicationXTroffMsvideo = 'application/x-troff-msvideo'; + var VideoAvi = 'video/avi'; + var VideoMsvideo = 'video/msvideo'; + var VideoXMsvideo = 'video/x-msvideo'; + var VideoAvsVideo = 'video/avs-video'; + var ApplicationXBcpio = 'application/x-bcpio'; + var ApplicationMacBinary = 'application/mac-binary'; + var ApplicationMacbinary = 'application/macbinary'; + var ApplicationXBinary = 'application/x-binary'; + var ApplicationXMacbinary = 'application/x-macbinary'; + var ImageBmp = 'image/bmp'; + var ImageXWindowsBmp = 'image/x-windows-bmp'; + var ApplicationBook = 'application/book'; + var ApplicationXBzip2 = 'application/x-bzip2'; + var ApplicationXBsh = 'application/x-bsh'; + var ApplicationXBzip = 'application/x-bzip'; + var TextPlain = 'text/plain'; + var TextXC = 'text/x-c'; + var ApplicationVndMsPkiSeccat = 'application/vnd.ms-pki.seccat'; + var ApplicationClariscad = 'application/clariscad'; + var ApplicationXCocoa = 'application/x-cocoa'; + var ApplicationCdf = 'application/cdf'; + var ApplicationXCdf = 'application/x-cdf'; + var ApplicationXNetcdf = 'application/x-netcdf'; + var ApplicationPkixCert = 'application/pkix-cert'; + var ApplicationXX509CaCert = 'application/x-x509-ca-cert'; + var ApplicationXChat = 'application/x-chat'; + var ApplicationJava = 'application/java'; + var ApplicationJavaByteCode = 'application/java-byte-code'; + var ApplicationXJavaClass = 'application/x-java-class'; + var ApplicationXCpio = 'application/x-cpio'; + var ApplicationMacCompactpro = 'application/mac-compactpro'; + var ApplicationPkcsCrl = 'application/pkcs-crl'; + var ApplicationXCsh = 'application/x-csh'; + var TextCss = 'text/css'; + var ApplicationXDirector = 'application/x-director'; + var ApplicationXDeepv = 'application/x-deepv'; + var VideoXDv = 'video/x-dv'; + var VideoDl = 'video/dl'; + var ApplicationMsword = 'application/msword'; + var ApplicationCommonground = 'application/commonground'; + var ApplicationDrafting = 'application/drafting'; + var ApplicationXDvi = 'application/x-dvi'; + var DrawingXDwf = 'drawing/x-dwf (old)'; + var ApplicationAcad = 'application/acad'; + var ApplicationDxf = 'application/dxf'; + var TextXScriptElisp = 'text/x-script.elisp'; + var ApplicationXBytecodeElisp = 'application/x-bytecode.elisp (compiled elisp)'; + var ApplicationXEnvoy = 'application/x-envoy'; + var ApplicationXEsrehber = 'application/x-esrehber'; + var TextXSetext = 'text/x-setext'; + var ApplicationEnvoy = 'application/envoy'; + var TextXFortran = 'text/x-fortran'; + var ApplicationVndFdf = 'application/vnd.fdf'; + var ImageFif = 'image/fif'; + var VideoFli = 'video/fli'; + var ImageFlorian = 'image/florian'; + var TextVndFmiFlexstor = 'text/vnd.fmi.flexstor'; + var VideoXAtomic3dFeature = 'video/x-atomic3d-feature'; + var ImageVndFpx = 'image/vnd.fpx'; + var ApplicationFreeloader = 'application/freeloader'; + var AudioMake = 'audio/make'; + var ImageG3fax = 'image/g3fax'; + var ImageGif = 'image/gif'; + var VideoGl = 'video/gl'; + var AudioXGsm = 'audio/x-gsm'; + var ApplicationXGsp = 'application/x-gsp'; + var ApplicationXGss = 'application/x-gss'; + var ApplicationXGtar = 'application/x-gtar'; + var ApplicationXCompressed = 'application/x-compressed'; + var ApplicationXGzip = 'application/x-gzip'; + var ApplicationXHdf = 'application/x-hdf'; + var ApplicationXHelpfile = 'application/x-helpfile'; + var TextXScript = 'text/x-script'; + var ApplicationHlp = 'application/hlp'; + var ApplicationVndHpHpgl = 'application/vnd.hp-hpgl'; + var ApplicationBinhex = 'application/binhex'; + var ApplicationHta = 'application/hta'; + var TextXComponent = 'text/x-component'; + var TextWebviewhtml = 'text/webviewhtml'; + var XConferenceXCooltalk = 'x-conference/x-cooltalk'; + var ImageXIcon = 'image/x-icon'; + var ImageIef = 'image/ief'; + var ApplicationIges = 'application/iges'; + var ApplicationXIma = 'application/x-ima'; + var ApplicationXHttpdImap = 'application/x-httpd-imap'; + var ApplicationInf = 'application/inf'; + var ApplicationXInternettSignup = 'application/x-internett-signup'; + var ApplicationXIp2 = 'application/x-ip2'; + var VideoXIsvideo = 'video/x-isvideo'; + var AudioIt = 'audio/it'; + var ApplicationXInventor = 'application/x-inventor'; + var IWorldIVrml = 'i-world/i-vrml'; + var ApplicationXLivescreen = 'application/x-livescreen'; + var AudioXJam = 'audio/x-jam'; + var ApplicationXJavaCommerce = 'application/x-java-commerce'; + var ImageJpeg = 'image/jpeg'; + var ImageXJps = 'image/x-jps'; + var TextJavascript = 'text/javascript'; + var ApplicationJson = 'application/json'; + var ApplicationJavascript = 'application/javascript'; + var ImageJutvision = 'image/jutvision'; + var AudioMidi = 'audio/midi'; + var ApplicationXKsh = 'application/x-ksh'; + var AudioNspaudio = 'audio/nspaudio'; + var AudioXLiveaudio = 'audio/x-liveaudio'; + var ApplicationXLatex = 'application/x-latex'; + var ApplicationXLisp = 'application/x-lisp'; + var TextXLaAsf = 'text/x-la-asf'; + var ApplicationLzx = 'application/lzx'; + var VideoMpeg = 'video/mpeg'; + var AudioMpeg = 'audio/mpeg'; + var AudioXMpequrl = 'audio/x-mpequrl'; + var ApplicationXTroffMan = 'application/x-troff-man'; + var ApplicationXNavimap = 'application/x-navimap'; + var ApplicationMbedlet = 'application/mbedlet'; + var ApplicationXMagicCapPackage10 = 'application/x-magic-cap-package-1.0'; + var ApplicationMcad = 'application/mcad'; + var ImageVasa = 'image/vasa'; + var ApplicationNetmc = 'application/netmc'; + var ApplicationXTroffMe = 'application/x-troff-me'; + var MessageRfc822 = 'message/rfc822'; + var ApplicationXMif = 'application/x-mif'; + var WwwMime = 'www/mime'; + var AudioXVndAudioexplosionMjuicemediafile = 'audio/x-vnd.audioexplosion.mjuicemediafile'; + var VideoXMotionJpeg = 'video/x-motion-jpeg'; + var ApplicationBase64 = 'application/base64'; + var AudioMod = 'audio/mod'; + var VideoQuicktime = 'video/quicktime'; + var VideoXSgiMovie = 'video/x-sgi-movie'; + var AudioMpeg3 = 'audio/mpeg3'; + var ApplicationXProject = 'application/x-project'; + var ApplicationVndMsProject = 'application/vnd.ms-project'; + var ApplicationMarc = 'application/marc'; + var ApplicationXTroffMs = 'application/x-troff-ms'; + var ApplicationXVndAudioexplosionMzz = 'application/x-vnd.audioexplosion.mzz'; + var ImageNaplps = 'image/naplps'; + var ApplicationVndNokiaConfigurationMessage = 'application/vnd.nokia.configuration-message'; + var ImageXNiff = 'image/x-niff'; + var ApplicationXMixTransfer = 'application/x-mix-transfer'; + var ApplicationXConference = 'application/x-conference'; + var ApplicationXNavidoc = 'application/x-navidoc'; + var ApplicationOda = 'application/oda'; + var ApplicationXOmc = 'application/x-omc'; + var ApplicationXOmcdatamaker = 'application/x-omcdatamaker'; + var ApplicationXOmcregerator = 'application/x-omcregerator'; + var TextXPascal = 'text/x-pascal'; + var ApplicationPkcs10 = 'application/pkcs10'; + var ApplicationPkcs12 = 'application/pkcs-12'; + var ApplicationXPkcs7Signature = 'application/x-pkcs7-signature'; + var ApplicationPkcs7Mime = 'application/pkcs7-mime'; + var ApplicationXPkcs7Certreqresp = 'application/x-pkcs7-certreqresp'; + var ApplicationPkcs7Signature = 'application/pkcs7-signature'; + var ApplicationPro_eng = 'application/pro_eng'; + var TextPascal = 'text/pascal'; + var ImageXPortableBitmap = 'image/x-portable-bitmap'; + var ApplicationVndHpPcl = 'application/vnd.hp-pcl'; + var ImageXPict = 'image/x-pict'; + var ImageXPcx = 'image/x-pcx'; + var ChemicalXPdb = 'chemical/x-pdb'; + var ApplicationPdf = 'application/pdf'; + var ImageXPortableGraymap = 'image/x-portable-graymap'; + var ImagePict = 'image/pict'; + var ApplicationXNewtonCompatiblePkg = 'application/x-newton-compatible-pkg'; + var ApplicationVndMsPkiPko = 'application/vnd.ms-pki.pko'; + var ApplicationXPixclscript = 'application/x-pixclscript'; + var ImageXXpixmap = 'image/x-xpixmap'; + var ApplicationXPagemaker = 'application/x-pagemaker'; + var ImagePng = 'image/png'; + var ApplicationXPortableAnymap = 'application/x-portable-anymap'; + var ApplicationMspowerpoint = 'application/mspowerpoint'; + var ModelXPov = 'model/x-pov'; + var ApplicationVndMsPowerpoint = 'application/vnd.ms-powerpoint'; + var ImageXPortablePixmap = 'image/x-portable-pixmap'; + var ApplicationXFreelance = 'application/x-freelance'; + var PaleovuXPv = 'paleovu/x-pv'; + var TextXScriptPhyton = 'text/x-script.phyton'; + var ApplicationXBytecodePython = 'application/x-bytecode.python'; + var AudioVndQcelp = 'audio/vnd.qcelp'; + var ImageXQuicktime = 'image/x-quicktime'; + var VideoXQtc = 'video/x-qtc'; + var AudioXPnRealaudio = 'audio/x-pn-realaudio'; + var ApplicationXCmuRaster = 'application/x-cmu-raster'; + var ImageCmuRaster = 'image/cmu-raster'; + var TextXScriptRexx = 'text/x-script.rexx'; + var ImageVndRnRealflash = 'image/vnd.rn-realflash'; + var ImageXRgb = 'image/x-rgb'; + var ApplicationVndRnRealmedia = 'application/vnd.rn-realmedia'; + var AudioMid = 'audio/mid'; + var ApplicationRingingTones = 'application/ringing-tones'; + var ApplicationVndRnRealplayer = 'application/vnd.rn-realplayer'; + var ApplicationXTroff = 'application/x-troff'; + var ImageVndRnRealpix = 'image/vnd.rn-realpix'; + var AudioXPnRealaudioPlugin = 'audio/x-pn-realaudio-plugin'; + var TextRichtext = 'text/richtext'; + var ApplicationRtf = 'application/rtf'; + var VideoVndRnRealvideo = 'video/vnd.rn-realvideo'; + var AudioS3m = 'audio/s3m'; + var ApplicationXTbook = 'application/x-tbook'; + var ApplicationXLotusscreencam = 'application/x-lotusscreencam'; + var ApplicationSdp = 'application/sdp'; + var ApplicationSounder = 'application/sounder'; + var ApplicationSea = 'application/sea'; + var ApplicationSet = 'application/set'; + var AudioXPsid = 'audio/x-psid'; + var ApplicationXSit = 'application/x-sit'; + var ApplicationXKoan = 'application/x-koan'; + var ApplicationXSeelogo = 'application/x-seelogo'; + var ApplicationSmil = 'application/smil'; + var ApplicationSolids = 'application/solids'; + var ApplicationXPkcs7Certificates = 'application/x-pkcs7-certificates'; + var ApplicationFuturesplash = 'application/futuresplash'; + var ApplicationXSprite = 'application/x-sprite'; + var ApplicationXWaisSource = 'application/x-wais-source'; + var TextXServerParsedHtml = 'text/x-server-parsed-html'; + var ApplicationStreamingmedia = 'application/streamingmedia'; + var ApplicationVndMsPkiCertstore = 'application/vnd.ms-pki.certstore'; + var ApplicationStep = 'application/step'; + var ApplicationSla = 'application/sla'; + var ApplicationXSv4cpio = 'application/x-sv4cpio'; + var ApplicationXSv4crc = 'application/x-sv4crc'; + var ImageVndDwg = 'image/vnd.dwg'; + var ApplicationXWorld = 'application/x-world'; + var ApplicationXShockwaveFlash = 'application/x-shockwave-flash'; + var TextXSpeech = 'text/x-speech'; + var ApplicationXTar = 'application/x-tar'; + var ApplicationToolbook = 'application/toolbook'; + var ApplicationXTcl = 'application/x-tcl'; + var TextXScriptTcsh = 'text/x-script.tcsh'; + var ApplicationXTex = 'application/x-tex'; + var ApplicationXTexinfo = 'application/x-texinfo'; + var ApplicationGnutar = 'application/gnutar'; + var ImageTiff = 'image/tiff'; + var AudioTspAudio = 'audio/tsp-audio'; + var ApplicationDsptype = 'application/dsptype'; + var TextTabSeparatedValues = 'text/tab-separated-values'; + var TextXUil = 'text/x-uil'; + var TextUriList = 'text/uri-list'; + var ApplicationIDeas = 'application/i-deas'; + var ApplicationXUstar = 'application/x-ustar'; + var TextXUuencode = 'text/x-uuencode'; + var ApplicationXCdlink = 'application/x-cdlink'; + var TextXVcalendar = 'text/x-vcalendar'; + var ApplicationVda = 'application/vda'; + var VideoVdo = 'video/vdo'; + var ApplicationGroupwise = 'application/groupwise'; + var VideoVivo = 'video/vivo'; + var ApplicationVocaltecMediaDesc = 'application/vocaltec-media-desc'; + var ApplicationVocaltecMediaFile = 'application/vocaltec-media-file'; + var AudioVoc = 'audio/voc'; + var VideoVosaic = 'video/vosaic'; + var AudioVoxware = 'audio/voxware'; + var AudioXTwinvqPlugin = 'audio/x-twinvq-plugin'; + var AudioXTwinvq = 'audio/x-twinvq'; + var ApplicationXVrml = 'application/x-vrml'; + var XWorldXVrt = 'x-world/x-vrt'; + var ApplicationXVisio = 'application/x-visio'; + var ApplicationWordperfect60 = 'application/wordperfect6.0'; + var ApplicationWordperfect61 = 'application/wordperfect6.1'; + var AudioWav = 'audio/wav'; + var ApplicationXQpro = 'application/x-qpro'; + var ImageVndWapWbmp = 'image/vnd.wap.wbmp'; + var ApplicationVndXara = 'application/vnd.xara'; + var ImageWebp = 'image/webp'; + var ApplicationX123 = 'application/x-123'; + var WindowsMetafile = 'windows/metafile'; + var TextVndWapWml = 'text/vnd.wap.wml'; + var ApplicationVndWapWmlc = 'application/vnd.wap.wmlc'; + var TextVndWapWmlscript = 'text/vnd.wap.wmlscript'; + var ApplicationVndWapWmlscriptc = 'application/vnd.wap.wmlscriptc'; + var ApplicationWordperfect = 'application/wordperfect'; + var ApplicationXLotus = 'application/x-lotus'; + var ApplicationMswrite = 'application/mswrite'; + var ModelVrml = 'model/vrml'; + var TextScriplet = 'text/scriplet'; + var ApplicationXWintalk = 'application/x-wintalk'; + var ImageXXbitmap = 'image/x-xbitmap'; + var VideoXAmtDemorun = 'video/x-amt-demorun'; + var XglDrawing = 'xgl/drawing'; + var ImageVndXiff = 'image/vnd.xiff'; + var ApplicationExcel = 'application/excel'; + var AudioXm = 'audio/xm'; + var ApplicationXml = 'application/xml'; + var XglMovie = 'xgl/movie'; + var ApplicationXVndLsXpix = 'application/x-vnd.ls-xpix'; + var VideoXAmtShowrun = 'video/x-amt-showrun'; + var ImageXXwd = 'image/x-xwd'; + var ApplicationXCompress = 'application/x-compress'; + var MultipartXZip = 'multipart/x-zip'; + var TextXScriptZsh = 'text/x-script.zsh'; +} diff --git a/std/haxe/io/Output.hx b/std/haxe/io/Output.hx index 3a830ecb350..b6ea6351d54 100644 --- a/std/haxe/io/Output.hx +++ b/std/haxe/io/Output.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; /** @@ -28,13 +29,12 @@ package haxe.io; Output. **/ class Output { - /** Endianness (word byte order) used when writing numbers. If `true`, big-endian is used, otherwise `little-endian` is used. **/ - public var bigEndian(default, set) : Bool; + public var bigEndian(default, set):Bool; #if java private var helper:java.nio.ByteBuffer; @@ -43,7 +43,7 @@ class Output { /** Write one byte. **/ - public function writeByte( c : Int ) : Void { + public function writeByte(c:Int):Void { throw "Not implemented"; } @@ -54,24 +54,24 @@ class Output { See `writeFullBytes` that tries to write the exact amount of specified bytes. **/ - public function writeBytes( s : Bytes, pos : Int, len : Int ) : Int { + public function writeBytes(s:Bytes, pos:Int, len:Int):Int { #if !neko - if( pos < 0 || len < 0 || pos + len > s.length ) + if (pos < 0 || len < 0 || pos + len > s.length) throw Error.OutsideBounds; #end var b = #if js @:privateAccess s.b #else s.getData() #end; var k = len; - while( k > 0 ) { + while (k > 0) { #if neko - writeByte(untyped __dollar__sget(b,pos)); + writeByte(untyped __dollar__sget(b, pos)); #elseif php - writeByte(b.get(pos)); + writeByte(b.get(pos)); #elseif cpp - writeByte(untyped b[pos]); + writeByte(untyped b[pos]); #elseif hl - writeByte(b[pos]); + writeByte(b[pos]); #else - writeByte(untyped b[pos]); + writeByte(untyped b[pos]); #end pos++; k--; @@ -82,33 +82,31 @@ class Output { /** Flush any buffered data. **/ - public function flush() { - } + public function flush() {} /** Close the output. Behaviour while writing after calling this method is unspecified. **/ - public function close() { - } + public function close() {} - function set_bigEndian( b ) { + function set_bigEndian(b) { bigEndian = b; return b; } /* ------------------ API ------------------ */ - /** Write all bytes stored in `s`. **/ - public function write( s : Bytes ) : Void { + public function write(s:Bytes):Void { var l = s.length; var p = 0; - while( l > 0 ) { - var k = writeBytes(s,p,l); - if( k == 0 ) throw Error.Blocked; + while (l > 0) { + var k = writeBytes(s, p, l); + if (k == 0) + throw Error.Blocked; p += k; l -= k; } @@ -119,9 +117,9 @@ class Output { Unlike `writeBytes`, this method tries to write the exact `len` amount of bytes. **/ - public function writeFullBytes( s : Bytes, pos : Int, len : Int ) { - while( len > 0 ) { - var k = writeBytes(s,pos,len); + public function writeFullBytes(s:Bytes, pos:Int, len:Int) { + while (len > 0) { + var k = writeBytes(s, pos, len); pos += k; len -= k; } @@ -132,7 +130,7 @@ class Output { Endianness is specified by the `bigEndian` property. **/ - public function writeFloat( x : Float ) { + public function writeFloat(x:Float) { writeInt32(FPHelper.floatToI32(x)); } @@ -141,9 +139,9 @@ class Output { Endianness is specified by the `bigEndian` property. **/ - public function writeDouble( x : Float ) { + public function writeDouble(x:Float) { var i64 = FPHelper.doubleToI64(x); - if( bigEndian ) { + if (bigEndian) { writeInt32(i64.high); writeInt32(i64.low); } else { @@ -155,8 +153,8 @@ class Output { /** Write `x` as 8-bit signed integer. **/ - public function writeInt8( x : Int ) { - if( x < -0x80 || x >= 0x80 ) + public function writeInt8(x:Int) { + if (x < -0x80 || x >= 0x80) throw Error.Overflow; writeByte(x & 0xFF); } @@ -166,8 +164,9 @@ class Output { Endianness is specified by the `bigEndian` property. **/ - public function writeInt16( x : Int ) { - if( x < -0x8000 || x >= 0x8000 ) throw Error.Overflow; + public function writeInt16(x:Int) { + if (x < -0x8000 || x >= 0x8000) + throw Error.Overflow; writeUInt16(x & 0xFFFF); } @@ -176,9 +175,10 @@ class Output { Endianness is specified by the `bigEndian` property. **/ - public function writeUInt16( x : Int ) { - if( x < 0 || x >= 0x10000 ) throw Error.Overflow; - if( bigEndian ) { + public function writeUInt16(x:Int) { + if (x < 0 || x >= 0x10000) + throw Error.Overflow; + if (bigEndian) { writeByte(x >> 8); writeByte(x & 0xFF); } else { @@ -192,8 +192,9 @@ class Output { Endianness is specified by the `bigEndian` property. **/ - public function writeInt24( x : Int ) { - if( x < -0x800000 || x >= 0x800000 ) throw Error.Overflow; + public function writeInt24(x:Int) { + if (x < -0x800000 || x >= 0x800000) + throw Error.Overflow; writeUInt24(x & 0xFFFFFF); } @@ -202,9 +203,10 @@ class Output { Endianness is specified by the `bigEndian` property. **/ - public function writeUInt24( x : Int ) { - if( x < 0 || x >= 0x1000000 ) throw Error.Overflow; - if( bigEndian ) { + public function writeUInt24(x:Int) { + if (x < 0 || x >= 0x1000000) + throw Error.Overflow; + if (bigEndian) { writeByte(x >> 16); writeByte((x >> 8) & 0xFF); writeByte(x & 0xFF); @@ -220,17 +222,17 @@ class Output { Endianness is specified by the `bigEndian` property. **/ - public function writeInt32( x : Int ) { - if( bigEndian ) { - writeByte( x >>> 24 ); - writeByte( (x >> 16) & 0xFF ); - writeByte( (x >> 8) & 0xFF ); - writeByte( x & 0xFF ); + public function writeInt32(x:Int) { + if (bigEndian) { + writeByte(x >>> 24); + writeByte((x >> 16) & 0xFF); + writeByte((x >> 8) & 0xFF); + writeByte(x & 0xFF); } else { - writeByte( x & 0xFF ); - writeByte( (x >> 8) & 0xFF ); - writeByte( (x >> 16) & 0xFF ); - writeByte( x >>> 24 ); + writeByte(x & 0xFF); + writeByte((x >> 8) & 0xFF); + writeByte((x >> 16) & 0xFF); + writeByte(x >>> 24); } } @@ -241,8 +243,7 @@ class Output { on this information, or simply ignore it. This is not a mandatory call but a tip and is only used in some specific cases. **/ - public function prepare( nbytes : Int ) { - } + public function prepare(nbytes:Int) {} /** Read all available data from `i` and write it. @@ -250,44 +251,43 @@ class Output { The `bufsize` optional argument specifies the size of chunks by which data is read and written. Its default value is 4096. **/ - public function writeInput( i : Input, ?bufsize : Int ) { - if( bufsize == null ) + public function writeInput(i:Input, ?bufsize:Int) { + if (bufsize == null) bufsize = 4096; var buf = Bytes.alloc(bufsize); try { - while( true ) { - var len = i.readBytes(buf,0,bufsize); - if( len == 0 ) + while (true) { + var len = i.readBytes(buf, 0, bufsize); + if (len == 0) throw Error.Blocked; var p = 0; - while( len > 0 ) { - var k = writeBytes(buf,p,len); - if( k == 0 ) + while (len > 0) { + var k = writeBytes(buf, p, len); + if (k == 0) throw Error.Blocked; p += k; len -= k; } } - } catch( e : Eof ) { - } + } catch (e:Eof) {} } /** Write `s` string. **/ - public function writeString( s : String ) { + public function writeString(s:String, ?encoding:Encoding) { #if neko - var b = untyped new Bytes(s.length,s.__s); + var b = untyped new Bytes(s.length, s.__s); #else - var b = Bytes.ofString(s); + var b = Bytes.ofString(s, encoding); #end - writeFullBytes(b,0,b.length); + writeFullBytes(b, 0, b.length); } -#if neko - static function __init__() untyped { - Output.prototype.bigEndian = false; - } -#end - + #if neko + static function __init__() + untyped { + Output.prototype.bigEndian = false; + } + #end } diff --git a/std/haxe/io/Path.hx b/std/haxe/io/Path.hx index 938e2f1535a..1bf67251465 100644 --- a/std/haxe/io/Path.hx +++ b/std/haxe/io/Path.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,17 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; /** This class provides a convenient way of working with paths. It supports the common path formats: - - directory1/directory2/filename.extension - - directory1\directory2\filename.extension + - `directory1/directory2/filename.extension` + - `directory1\directory2\filename.extension` **/ class Path { - /** The directory. @@ -38,19 +38,19 @@ class Path { Does not end with a `/` or `\` separator. - If the path has no directory, the value is null. + If the path has no directory, the value is `null`. **/ - public var dir : String; + public var dir:Null; /** The file name. This is the part of the part between the directory and the extension. - If there is no file name, e.g. for ".htaccess" or "/dir/", the value - is the empty String "". + If there is no file name, e.g. for `".htaccess"` or `"/dir/"`, the value + is the empty String `""`. **/ - public var file : String; + public var file:String; /** The file extension. @@ -58,22 +58,22 @@ class Path { It is separated from the file name by a dot. This dot is not part of the extension. - If the path has no extension, the value is null. + If the path has no extension, the value is `null`. **/ - public var ext : String; + public var ext:Null; /** - True if the last directory separator is a backslash, false otherwise. + `true` if the last directory separator is a backslash, `false` otherwise. **/ - public var backslash : Bool; + public var backslash:Bool; /** - Creates a new Path instance by parsing `path`. + Creates a new `Path` instance by parsing `path`. - Path information can be retrieved by accessing the dir, file and ext + Path information can be retrieved by accessing the `dir`, `file` and `ext` properties. **/ - public function new( path : String ) { + public function new(path:String) { switch (path) { case "." | "..": dir = path; @@ -82,19 +82,19 @@ class Path { } var c1 = path.lastIndexOf("/"); var c2 = path.lastIndexOf("\\"); - if( c1 < c2 ) { - dir = path.substr(0,c2); - path = path.substr(c2+1); + if (c1 < c2) { + dir = path.substr(0, c2); + path = path.substr(c2 + 1); backslash = true; - } else if( c2 < c1 ) { - dir = path.substr(0,c1); - path = path.substr(c1+1); + } else if (c2 < c1) { + dir = path.substr(0, c1); + path = path.substr(c1 + 1); } else dir = null; var cp = path.lastIndexOf("."); - if( cp != -1 ) { - ext = path.substr(cp+1); - file = path.substr(0,cp); + if (cp != -1) { + ext = path.substr(cp + 1); + file = path.substr(0, cp); } else { ext = null; file = path; @@ -104,23 +104,23 @@ class Path { /** Returns a String representation of `this` path. - If `this.backslash` is true, backslash is used as directory separator, + If `this.backslash` is `true`, backslash is used as directory separator, otherwise slash is used. This only affects the separator between `this.dir` and `this.file`. - If `this.directory` or `this.extension` is null, their representation - is the empty String "". + If `this.directory` or `this.extension` is `null`, their representation + is the empty String `""`. **/ - public function toString() : String { - return (if( dir == null ) "" else dir + if( backslash ) "\\" else "/") + file + (if( ext == null ) "" else "." + ext); + public function toString():String { + return (if (dir == null) "" else dir + if (backslash) "\\" else "/") + file + (if (ext == null) "" else "." + ext); } /** Returns the String representation of `path` without the file extension. - If `path` is null, the result is unspecified. + If `path` is `null`, the result is unspecified. **/ - public static function withoutExtension( path : String ) : String { + public static function withoutExtension(path:String):String { var s = new Path(path); s.ext = null; return s.toString(); @@ -129,9 +129,9 @@ class Path { /** Returns the String representation of `path` without the directory. - If `path` is null, the result is unspecified. + If `path` is `null`, the result is unspecified. **/ - public static function withoutDirectory( path ) : String { + public static function withoutDirectory(path):String { var s = new Path(path); s.dir = null; return s.toString(); @@ -140,13 +140,13 @@ class Path { /** Returns the directory of `path`. - If the directory is null, the empty String `""` is returned. + If the directory is `null`, the empty String `""` is returned. - If `path` is null, the result is unspecified. + If `path` is `null`, the result is unspecified. **/ - public static function directory( path ) : String { + public static function directory(path):String { var s = new Path(path); - if( s.dir == null ) + if (s.dir == null) return ""; return s.dir; } @@ -154,13 +154,13 @@ class Path { /** Returns the extension of `path`. - If the extension is null, the empty String `""` is returned. + If `path` has no extension, the empty String `""` is returned. - If `path` is null, the result is unspecified. + If `path` is `null`, the result is unspecified. **/ - public static function extension( path ) : String { + public static function extension(path):String { var s = new Path(path); - if( s.ext == null ) + if (s.ext == null) return ""; return s.ext; } @@ -170,9 +170,9 @@ class Path { If `path` has no extension, `ext` is added as extension. - If `path` or `ext` are null, the result is unspecified. + If `path` or `ext` are `null`, the result is unspecified. **/ - public static function withExtension( path, ext ) : String { + public static function withExtension(path, ext):String { var s = new Path(path); s.ext = ext; return s.toString(); @@ -184,9 +184,9 @@ class Path { If `paths` is empty, the empty String `""` is returned. Otherwise the paths are joined with a slash between them. - If `paths` is null, the result is unspecified. + If `paths` is `null`, the result is unspecified. **/ - public static function join(paths:Array) : String { + public static function join(paths:Array):String { var paths = paths.filter(function(s) return s != null && s != ""); if (paths.length == 0) { return ""; @@ -200,36 +200,44 @@ class Path { } /** - Normalize a given `path` (e.g. make '/usr/local/../lib' to '/usr/lib'). + Normalize a given `path` (e.g. turn `'/usr/local/../lib'` into `'/usr/lib'`). - Also replaces backslashes \ with slashes / and afterwards turns + Also replaces backslashes `\` with slashes `/` and afterwards turns multiple slashes into a single one. - If `path` is null, the result is unspecified. + If `path` is `null`, the result is unspecified. **/ - public static function normalize(path : String) : String { + public static function normalize(path:String):String { var slash = "/"; path = path.split("\\").join(slash); - if (path == slash) return slash; + if (path == slash) + return slash; var target = []; - for( token in path.split(slash) ) { - if(token == '..' && target.length > 0 && target[target.length-1] != "..") { + for (token in path.split(slash)) { + if (token == '..' && target.length > 0 && target[target.length - 1] != "..") { target.pop(); - } else if(token != '.') { + } else if (token == '') { + if (target.length > 0 || path.charCodeAt(0) == '/'.code) { + target.push(token); + } + } else if (token != '.') { target.push(token); } } var tmp = target.join(slash); - var regex = ~/([^:])\/+/g; - var result = regex.replace(tmp, "$1" +slash); var acc = new StringBuf(); var colon = false; var slashes = false; + #if utf16 + for (c in haxe.iterators.StringIteratorUnicode.unicodeIterator(tmp)) { + switch (c) { + #else for (i in 0...tmp.length) { switch (StringTools.fastCodeAt(tmp, i)) { + #end case ":".code: acc.add(":"); colon = true; @@ -244,6 +252,7 @@ class Path { acc.addChar(i); } } + return acc.toString(); } @@ -257,19 +266,23 @@ class Path { is appended to `path`. In particular, this applies to the empty String `""`. - If `path` is null, the result is unspecified. + If `path` is `null`, the result is unspecified. **/ - public static function addTrailingSlash( path : String ) : String { + public static function addTrailingSlash(path:String):String { if (path.length == 0) return "/"; var c1 = path.lastIndexOf("/"); var c2 = path.lastIndexOf("\\"); - return if ( c1 < c2 ) { - if (c2 != path.length - 1) path + "\\"; - else path; + return if (c1 < c2) { + if (c2 != path.length - 1) + path + "\\"; + else + path; } else { - if (c1 != path.length - 1) path + "/"; - else path; + if (c1 != path.length - 1) + path + "/"; + else + path; } } @@ -281,36 +294,39 @@ class Path { Otherwise the substring of `path` excluding the trailing slashes or backslashes is returned. - If `path` is null, the result is unspecified. + If `path` is `null`, the result is unspecified. **/ - @:require(haxe_ver >= 3.1) - public static function removeTrailingSlashes ( path : String ) : String { + public static function removeTrailingSlashes(path:String):String { while (true) { - switch(path.charCodeAt(path.length - 1)) { - case '/'.code | '\\'.code: path = path.substr(0, -1); - case _: break; + switch (path.charCodeAt(path.length - 1)) { + case '/'.code | '\\'.code: + path = path.substr(0, -1); + case _: + break; } } return path; } /** - Returns true if the path is an absolute path, and false otherwise. + Returns `true` if the path is an absolute path, and `false` otherwise. **/ - @:require(haxe_ver >= 3.2) - public static function isAbsolute ( path : String ) : Bool { - if (StringTools.startsWith(path, '/')) return true; - if (path.charAt(1) == ':') return true; - if (StringTools.startsWith(path, '\\\\')) return true; + public static function isAbsolute(path:String):Bool { + if (StringTools.startsWith(path, '/')) + return true; + if (path.charAt(1) == ':') + return true; + if (StringTools.startsWith(path, '\\\\')) + return true; return false; } - private static function unescape( path : String ) : String { + private static function unescape(path:String):String { var regex = ~/-x([0-9][0-9])/g; return regex.map(path, function(regex) return String.fromCharCode(Std.parseInt(regex.matched(1)))); } - private static function escape( path : String, allowSlashes : Bool = false ) : String { + private static function escape(path:String, allowSlashes:Bool = false):String { var regex = allowSlashes ? ~/[^A-Za-z0-9_\/\\\.]/g : ~/[^A-Za-z0-9_\.]/g; return regex.map(path, function(v) return '-x' + v.matched(0).charCodeAt(0)); } diff --git a/std/haxe/io/Scheme.hx b/std/haxe/io/Scheme.hx new file mode 100644 index 00000000000..e5acdcfea11 --- /dev/null +++ b/std/haxe/io/Scheme.hx @@ -0,0 +1,18 @@ +package haxe.io; + +/** + A scheme consists of a sequence of characters beginning with a letter and followed + by any combination of letters, digits, plus (`+`, period (`.`), or hyphen (`-`). + + Although schemes are case-insensitive, the canonical form is lowercase + and documents that specify schemes must do so with lowercase letters. + It is followed by a colon (`:`). +**/ +enum abstract Scheme(String) from String to String { + var Http = 'http'; + var Https = 'https'; + var Ftp = 'ftp'; + var MailTo = 'mailto'; + var File = 'file'; + var Data = 'data'; +} diff --git a/std/haxe/io/StringInput.hx b/std/haxe/io/StringInput.hx index 95b0416b407..7d058a4497a 100644 --- a/std/haxe/io/StringInput.hx +++ b/std/haxe/io/StringInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; class StringInput extends BytesInput { - - public function new( s : String ) { + public function new(s:String) { #if neko // don't copy the string - super( neko.Lib.bytesReference(s) ); + super(neko.Lib.bytesReference(s)); #else - super( haxe.io.Bytes.ofString(s) ); + super(haxe.io.Bytes.ofString(s)); #end } - -} \ No newline at end of file +} diff --git a/std/haxe/io/UInt16Array.hx b/std/haxe/io/UInt16Array.hx index 978e406c5b3..bad0aefdcca 100644 --- a/std/haxe/io/UInt16Array.hx +++ b/std/haxe/io/UInt16Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; typedef UInt16ArrayData = ArrayBufferView.ArrayBufferViewData; abstract UInt16Array(UInt16ArrayData) { - public static inline var BYTES_PER_ELEMENT = 2; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int) { this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData(); } @@ -37,49 +38,50 @@ abstract UInt16Array(UInt16ArrayData) { return this.byteLength >> 1; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : Int { - return this.bytes.getUInt16((index<<1) + this.byteOffset); + @:arrayAccess public inline function get(index:Int):Int { + return this.bytes.getUInt16((index << 1) + this.byteOffset); } - @:arrayAccess public inline function set( index : Int, value : Int ) : Int { - if( index >= 0 && index < length ) { - this.bytes.setUInt16((index<<1) + this.byteOffset, value); + @:arrayAccess public inline function set(index:Int, value:Int):Int { + if (index >= 0 && index < length) { + this.bytes.setUInt16((index << 1) + this.byteOffset, value); return value; } return 0; } - public inline function sub( begin : Int, ?length : Int ) : UInt16Array { - return fromData(this.sub(begin<<1,length == null ? null : length<<1)); + public inline function sub(begin:Int, ?length:Int):UInt16Array { + return fromData(this.sub(begin << 1, length == null ? null : length << 1)); } - public inline function subarray( ?begin : Int, ?end : Int ) : UInt16Array { - return fromData(this.subarray(begin==null?null:begin<<1,end==null?null:end<<1)); + public inline function subarray(?begin:Int, ?end:Int):UInt16Array { + return fromData(this.subarray(begin == null ? null : begin << 1, end == null ? null : end << 1)); } - public inline function getData() : UInt16ArrayData { + public inline function getData():UInt16ArrayData { return this; } - public static function fromData( d : UInt16ArrayData ) : UInt16Array { + public static function fromData(d:UInt16ArrayData):UInt16Array { return cast d; } - public static function fromArray( a : Array, pos = 0, ?length : Int ) : UInt16Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; + public static function fromArray(a:Array, pos = 0, ?length:Int):UInt16Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; var i = new UInt16Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos = 0, ?length : Int ) : UInt16Array { - return fromData(ArrayBufferView.fromBytes(bytes,bytePos,(length == null ? (bytes.length - bytePos)>>1 : length)<<1).getData()); + public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):UInt16Array { + return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 1 : length) << 1).getData()); } } - diff --git a/std/haxe/io/UInt32Array.hx b/std/haxe/io/UInt32Array.hx index 128a39bf812..b433f445822 100644 --- a/std/haxe/io/UInt32Array.hx +++ b/std/haxe/io/UInt32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; typedef UInt32ArrayData = ArrayBufferView.ArrayBufferViewData; abstract UInt32Array(UInt32ArrayData) { - public static inline var BYTES_PER_ELEMENT = 4; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int) { this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData(); } @@ -37,49 +38,50 @@ abstract UInt32Array(UInt32ArrayData) { return this.byteLength >> 2; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : UInt { - return this.bytes.getInt32((index<<2) + this.byteOffset); + @:arrayAccess public inline function get(index:Int):UInt { + return this.bytes.getInt32((index << 2) + this.byteOffset); } - @:arrayAccess public inline function set( index : Int, value : UInt ) : UInt { - if( index >= 0 && index < length ) { - this.bytes.setInt32((index<<2) + this.byteOffset, value); + @:arrayAccess public inline function set(index:Int, value:UInt):UInt { + if (index >= 0 && index < length) { + this.bytes.setInt32((index << 2) + this.byteOffset, value); return value; } return 0; } - public inline function sub( begin : Int, ?length : Int ) : UInt32Array { - return fromData(this.sub(begin<<2,length == null ? null : length<<2)); + public inline function sub(begin:Int, ?length:Int):UInt32Array { + return fromData(this.sub(begin << 2, length == null ? null : length << 2)); } - public inline function subarray( ?begin : Int, ?end : Int ) : UInt32Array { - return fromData(this.subarray(begin==null?null:begin<<2,end==null?null:end<<2)); + public inline function subarray(?begin:Int, ?end:Int):UInt32Array { + return fromData(this.subarray(begin == null ? null : begin << 2, end == null ? null : end << 2)); } - public inline function getData() : UInt32ArrayData { + public inline function getData():UInt32ArrayData { return this; } - public static function fromData( d : UInt32ArrayData ) : UInt32Array { + public static function fromData(d:UInt32ArrayData):UInt32Array { return cast d; } - public static function fromArray( a : Array, pos = 0, ?length : Int ) : UInt32Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; + public static function fromArray(a:Array, pos = 0, ?length:Int):UInt32Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; var i = new UInt32Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos = 0, ?length : Int ) : UInt32Array { - return fromData(ArrayBufferView.fromBytes(bytes,bytePos,(length == null ? (bytes.length - bytePos)>>2 : length)<<2).getData()); + public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):UInt32Array { + return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 2 : length) << 2).getData()); } } - diff --git a/std/haxe/io/UInt8Array.hx b/std/haxe/io/UInt8Array.hx index 5f5f64c6a74..696808d2a81 100644 --- a/std/haxe/io/UInt8Array.hx +++ b/std/haxe/io/UInt8Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; typedef UInt8ArrayData = ArrayBufferView.ArrayBufferViewData; abstract UInt8Array(UInt8ArrayData) { - public static inline var BYTES_PER_ELEMENT = 1; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int) { this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData(); } @@ -37,50 +38,50 @@ abstract UInt8Array(UInt8ArrayData) { return this.byteLength; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) { + @:arrayAccess public inline function get(index:Int) { return this.bytes.get(index + this.byteOffset); } - @:arrayAccess public inline function set( index : Int, value : Int ) : Int { - if( index >= 0 && index < length ) { + @:arrayAccess public inline function set(index:Int, value:Int):Int { + if (index >= 0 && index < length) { this.bytes.set(index + this.byteOffset, value); return value; } return 0; } - public inline function sub( begin : Int, ?length : Int ) : UInt8Array { - return fromData(this.sub(begin,length)); + public inline function sub(begin:Int, ?length:Int):UInt8Array { + return fromData(this.sub(begin, length)); } - public inline function subarray( ?begin : Int, ?end : Int ) : UInt8Array { - return fromData(this.subarray(begin,end)); + public inline function subarray(?begin:Int, ?end:Int):UInt8Array { + return fromData(this.subarray(begin, end)); } - public inline function getData() : UInt8ArrayData { + public inline function getData():UInt8ArrayData { return this; } - public static function fromData( d : UInt8ArrayData ) : UInt8Array { + public static function fromData(d:UInt8ArrayData):UInt8Array { return cast d; } - public static function fromArray( a : Array, pos = 0, ?length : Int ) : UInt8Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; + public static function fromArray(a:Array, pos = 0, ?length:Int):UInt8Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; var i = new UInt8Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos : Int = 0, ?length : Int ) : UInt8Array { - return fromData(ArrayBufferView.fromBytes(bytes,bytePos,length).getData()); + public static function fromBytes(bytes:haxe.io.Bytes, bytePos:Int = 0, ?length:Int):UInt8Array { + return fromData(ArrayBufferView.fromBytes(bytes, bytePos, length).getData()); } - } - diff --git a/std/haxe/iterators/DynamicAccessIterator.hx b/std/haxe/iterators/DynamicAccessIterator.hx new file mode 100644 index 00000000000..abf0a6a2926 --- /dev/null +++ b/std/haxe/iterators/DynamicAccessIterator.hx @@ -0,0 +1,52 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.iterators; + +/** + This iterator can be used to iterate over the values of `haxe.DynamicAccess`. +**/ +class DynamicAccessIterator { + final access:DynamicAccess; + final keys:Array; + var index:Int; + + public inline function new(access:DynamicAccess) { + this.access = access; + this.keys = access.keys(); + index = 0; + } + + /** + See `Iterator.hasNext` + **/ + public inline function hasNext():Bool { + return index < keys.length; + } + + /** + See `Iterator.next` + **/ + public inline function next():T { + return access[keys[index++]]; + } +} diff --git a/std/haxe/iterators/DynamicAccessKeyValueIterator.hx b/std/haxe/iterators/DynamicAccessKeyValueIterator.hx new file mode 100644 index 00000000000..08fcde6ab83 --- /dev/null +++ b/std/haxe/iterators/DynamicAccessKeyValueIterator.hx @@ -0,0 +1,53 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.iterators; + +/** + This Key/Value iterator can be used to iterate over `haxe.DynamicAccess`. +**/ +class DynamicAccessKeyValueIterator { + final access:DynamicAccess; + final keys:Array; + var index:Int; + + public inline function new(access:DynamicAccess) { + this.access = access; + this.keys = access.keys(); + index = 0; + } + + /** + See `Iterator.hasNext` + **/ + public inline function hasNext():Bool { + return index < keys.length; + } + + /** + See `Iterator.next` + **/ + public inline function next():{key:String, value:T} { + var key = keys[index++]; + return {value: access[key], key: key}; + } +} diff --git a/std/haxe/iterators/MapKeyValueIterator.hx b/std/haxe/iterators/MapKeyValueIterator.hx new file mode 100644 index 00000000000..fa9b7c47920 --- /dev/null +++ b/std/haxe/iterators/MapKeyValueIterator.hx @@ -0,0 +1,54 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.iterators; + +import haxe.ds.IntMap; + +/** + This Key/Value iterator can be used to iterate across maps. +**/ +@:ifFeature("anon_read.keyValueIterator", "dynamic_read.keyValueIterator") +class MapKeyValueIterator { + var map:haxe.Constraints.IMap; + var keys:Iterator; + + public inline function new(map:haxe.Constraints.IMap) { + this.map = map; + this.keys = map.keys(); + } + + /** + See `Iterator.hasNext` + **/ + public inline function hasNext():Bool { + return keys.hasNext(); + } + + /** + See `Iterator.next` + **/ + public inline function next():{key:K, value:V} { + var key = keys.next(); + return {value: map.get(key), key: key}; + } +} diff --git a/std/haxe/iterators/StringIterator.hx b/std/haxe/iterators/StringIterator.hx new file mode 100644 index 00000000000..7d7005db22a --- /dev/null +++ b/std/haxe/iterators/StringIterator.hx @@ -0,0 +1,55 @@ +/* + * Copyright (C)2005-2018 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.iterators; + +/** + This iterator can be used to iterate over char codes in a string. + + Note that char codes may differ across platforms because of different + internal encoding of strings in different of runtimes. +**/ +class StringIterator { + var offset = 0; + var s:String; + + /** + Create a new `StringIterator` over String `s`. + **/ + public inline function new(s:String) { + this.s = s; + } + + /** + See `Iterator.hasNext` + **/ + public inline function hasNext() { + return offset < s.length; + } + + /** + See `Iterator.next` + **/ + public inline function next() { + return StringTools.fastCodeAt(s, offset++); + } +} diff --git a/std/haxe/iterators/StringIteratorUnicode.hx b/std/haxe/iterators/StringIteratorUnicode.hx new file mode 100644 index 00000000000..ca73609c721 --- /dev/null +++ b/std/haxe/iterators/StringIteratorUnicode.hx @@ -0,0 +1,73 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.iterators; + +/** + This iterator can be used to iterate across strings in a cross-platform + way. It handles surrogate pairs on platforms that require it. On each + iteration, it returns the next character code. + + Note that this has different semantics than a standard for-loop over the + String's length due to the fact that it deals with surrogate pairs. +**/ +class StringIteratorUnicode { + var offset = 0; + var s:String; + + /** + Create a new `StringIteratorUnicode` over String `s`. + **/ + public inline function new(s:String) { + this.s = s; + } + + /** + See `Iterator.hasNext` + **/ + public inline function hasNext() { + return offset < s.length; + } + + /** + See `Iterator.next` + **/ + @:access(StringTools) + public inline function next() { + #if utf16 + var c = StringTools.utf16CodePointAt(s, offset++); + if (c >= StringTools.MIN_SURROGATE_CODE_POINT) { + offset++; + } + return c; + #else + return StringTools.fastCodeAt(s, offset++); + #end + } + + /** + Convenience function which can be used as a static extension. + **/ + static public inline function unicodeIterator(s:String) { + return new StringIteratorUnicode(s); + } +} diff --git a/std/haxe/iterators/StringKeyValueIterator.hx b/std/haxe/iterators/StringKeyValueIterator.hx new file mode 100644 index 00000000000..8a690789fb6 --- /dev/null +++ b/std/haxe/iterators/StringKeyValueIterator.hx @@ -0,0 +1,55 @@ +/* + * Copyright (C)2005-2018 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.iterators; + +/** + This iterator can be used to iterate over char indexes and char codes in a string. + + Note that char codes may differ across platforms because of different + internal encoding of strings in different runtimes. +**/ +class StringKeyValueIterator { + var offset = 0; + var s:String; + + /** + Create a new `StringKeyValueIterator` over String `s`. + **/ + public inline function new(s:String) { + this.s = s; + } + + /** + See `KeyValueIterator.hasNext` + **/ + public inline function hasNext() { + return offset < s.length; + } + + /** + See `KeyValueIterator.next` + **/ + public inline function next() { + return {key: offset, value: StringTools.fastCodeAt(s, offset++)}; + } +} diff --git a/std/haxe/iterators/StringKeyValueIteratorUnicode.hx b/std/haxe/iterators/StringKeyValueIteratorUnicode.hx new file mode 100644 index 00000000000..3647c6d76f1 --- /dev/null +++ b/std/haxe/iterators/StringKeyValueIteratorUnicode.hx @@ -0,0 +1,76 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.iterators; + +/** + This iterator can be used to iterate across strings in a cross-platform + way. It handles surrogate pairs on platforms that require it. On each + iteration, it returns the next character offset as key and the next + character code as value. + + Note that in the general case, because of surrogate pairs, the key values + should not be used as offsets for various String API operations. For the + same reason, the last key value returned might be less than `s.length - 1`. +**/ +class StringKeyValueIteratorUnicode { + var byteOffset = 0; + var charOffset = 0; + var s:String; + + /** + Create a new `StringKeyValueIteratorUnicode` over String `s`. + **/ + public inline function new(s:String) { + this.s = s; + } + + /** + See `Iterator.hasNext` + **/ + public inline function hasNext() { + return byteOffset < s.length; + } + + /** + See `Iterator.next` + **/ + @:access(StringTools) + public inline function next() { + #if utf16 + var c = StringTools.utf16CodePointAt(s, byteOffset++); + if (c >= StringTools.MIN_SURROGATE_CODE_POINT) { + byteOffset++; + } + return {key: charOffset++, value: c}; + #else + return {key: charOffset++, value: StringTools.fastCodeAt(s, byteOffset++)}; + #end + } + + /** + Convenience function which can be used as a static extension. + **/ + static public inline function unicodeKeyValueIterator(s:String) { + return new StringKeyValueIteratorUnicode(s); + } +} diff --git a/std/haxe/macro/CompilationServer.hx b/std/haxe/macro/CompilationServer.hx index a30ced04a32..fe58998c52f 100644 --- a/std/haxe/macro/CompilationServer.hx +++ b/std/haxe/macro/CompilationServer.hx @@ -1,9 +1,30 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package haxe.macro; import haxe.macro.Compiler; -@:enum -abstract ModuleCheckPolicy(Int) { +enum abstract ModuleCheckPolicy(Int) { /** Disables file modification checks, avoiding some filesystem operations. **/ @@ -17,6 +38,11 @@ abstract ModuleCheckPolicy(Int) { /** Disables dependency checks of the module. + + This should only be used for modules that don't depend on any module that + might change. It is effectively a promise to the compiler that the module + is unaffected by changes made to other modules. If that promise is broken, + the compiler is sad and things probably stop working. **/ var NoCheckDependencies = 2; @@ -28,7 +54,7 @@ abstract ModuleCheckPolicy(Int) { var NoCheckShadowing = 3; } -@:enum abstract ContextOptions(Int) { +enum abstract ContextOptions(Int) { /** Affects only the normal context. **/ @@ -50,8 +76,7 @@ abstract ModuleCheckPolicy(Int) { `--macro server.field(args)`. **/ class CompilationServer { - #if macro - + #if (macro || display) /** Sets the `ModuleCheckPolicy` of all files whose dot-path matches an element of `pathFilters`. @@ -70,7 +95,8 @@ class CompilationServer { If a call to this function is added to the compilation parameters, the compilation server should be restarted to ensure it takes effect. **/ - static public function setModuleCheckPolicy(pathFilters:Array, policy:Array, ?recursive = true, ?contextOptions:ContextOptions = NormalContext) { + static public function setModuleCheckPolicy(pathFilters:Array, policy:Array, ?recursive = true, + ?contextOptions:ContextOptions = NormalContext) { @:privateAccess Compiler.load("server_add_module_check_policy", 4)(pathFilters, policy, recursive, contextOptions); } @@ -81,4 +107,4 @@ class CompilationServer { @:privateAccess Compiler.load("server_invalidate_files", 1)(filePaths); } #end -} \ No newline at end of file +} diff --git a/std/haxe/macro/Compiler.hx b/std/haxe/macro/Compiler.hx index deb3b137abe..e9aed53946b 100644 --- a/std/haxe/macro/Compiler.hx +++ b/std/haxe/macro/Compiler.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.macro; + import haxe.macro.Expr; /** @@ -30,7 +32,7 @@ import haxe.macro.Expr; #end class Compiler { /** - A conditional compiler flag can be set command line using + A conditional compilation flag can be set on the command line using `-D key=value`. Returns the value of a compiler flag. @@ -41,18 +43,20 @@ class Compiler { If the compiler flag is not defined, `Compiler.getDefine` returns `null`. + Note: This is a macro and cannot be called from within other macros. Refer + to `haxe.macro.Context.definedValue` to obtain defined values in macro context. + @see https://haxe.org/manual/lf-condition-compilation.html **/ - macro static public function getDefine( key : String ) { + macro /* <-- ! */ static public function getDefine(key:String) { return macro $v{haxe.macro.Context.definedValue(key)}; } -#if (neko || (macro && hl) || (macro && eval)) - + #if (neko || (macro && hl) || (macro && eval)) static var ident = ~/^[A-Za-z_][A-Za-z0-9_]*$/; static var path = ~/^[A-Za-z_][A-Za-z0-9_.]*$/; - public static function allowPackage( v : String ) { + public static function allowPackage(v:String) { #if (neko || eval) load("allow_package", 1)(v); #end @@ -61,28 +65,29 @@ class Compiler { /** Set a conditional compiler flag. **/ - public static function define( flag : String, ?value : String ) { + public static function define(flag:String, ?value:String) { #if (neko || eval) - load("define", 2)(flag,value); + load("define", 2)(flag, value); #end } #if (!neko && !eval) - private static function typePatch( cl : String, f : String, stat : Bool, t : String ) { - } - private static function metaPatch( meta : String, cl : String, f : String, stat : Bool ) { - } - private static function addGlobalMetadataImpl(pathFilter:String, meta:String, recursive:Bool, toTypes:Bool, toFields:Bool) { - } + private static function typePatch(cl:String, f:String, stat:Bool, t:String) {} + + private static function metaPatch(meta:String, cl:String, f:String, stat:Bool) {} + + private static function addGlobalMetadataImpl(pathFilter:String, meta:String, recursive:Bool, toTypes:Bool, toFields:Bool) {} #end /** Removes a (static) field from a given class by name. An error is thrown when `className` or `field` is invalid. **/ - public static function removeField( className : String, field : String, ?isStatic : Bool ) { - if( !path.match(className) ) throw "Invalid "+className; - if( !ident.match(field) ) throw "Invalid " + field; + public static function removeField(className:String, field:String, ?isStatic:Bool) { + if (!path.match(className)) + throw "Invalid " + className; + if (!ident.match(field)) + throw "Invalid " + field; #if (neko || eval) load("type_patch", 4)(className, field, isStatic == true, null); #else @@ -94,9 +99,11 @@ class Compiler { Set the type of a (static) field at a given class by name. An error is thrown when `className` or `field` is invalid. **/ - public static function setFieldType( className : String, field : String, type : String, ?isStatic : Bool ) { - if( !path.match(className) ) throw "Invalid "+className; - if( !ident.match((field.charAt(0) == "$") ? field.substr(1) : field) ) throw "Invalid "+field; + public static function setFieldType(className:String, field:String, type:String, ?isStatic:Bool) { + if (!path.match(className)) + throw "Invalid " + className; + if (!ident.match((field.charAt(0) == "$") ? field.substr(1) : field)) + throw "Invalid " + field; #if (neko || eval) load("type_patch", 4)(className, field, isStatic == true, type); #else @@ -108,9 +115,11 @@ class Compiler { Add metadata to a (static) field or class by name. An error is thrown when `className` or `field` is invalid. **/ - public static function addMetadata( meta : String, className : String, ?field : String, ?isStatic : Bool ) { - if( !path.match(className) ) throw "Invalid "+className; - if( field != null && !ident.match(field) ) throw "Invalid "+field; + public static function addMetadata(meta:String, className:String, ?field:String, ?isStatic:Bool) { + if (!path.match(className)) + throw "Invalid " + className; + if (field != null && !ident.match(field)) + throw "Invalid " + field; #if (neko || eval) load("meta_patch", 4)(meta, className, field, isStatic == true); #else @@ -118,13 +127,13 @@ class Compiler { #end } - public static function addClassPath( path : String ) { + public static function addClassPath(path:String) { #if (neko || eval) load("add_class_path", 1)(path); #end } - public static function getOutput() : String { + public static function getOutput():String { #if (neko || eval) return load("get_output", 0)(); #else @@ -132,13 +141,13 @@ class Compiler { #end } - public static function setOutput( fileOrDir : String ) { + public static function setOutput(fileOrDir:String) { #if (neko || eval) load("set_output", 1)(fileOrDir); #end } - public static function getDisplayPos() : Null<{ file : String, pos : Int }> { + public static function getDisplayPos():Null<{file:String, pos:Int}> { #if (neko || eval) return load("get_display_pos", 0)(); #else @@ -149,7 +158,7 @@ class Compiler { /** Adds a native library depending on the platform (e.g. `-swf-lib` for Flash). **/ - public static function addNativeLib( name : String ) { + public static function addNativeLib(name:String) { #if (neko || eval) load("add_native_lib", 1)(name); #end @@ -157,8 +166,8 @@ class Compiler { /** Adds an argument to be passed to the native compiler (e.g. `-javac-arg` for Java). - **/ - public static function addNativeArg( argument : String ) { + **/ + public static function addNativeArg(argument:String) { #if (neko || eval) load("add_native_arg", 1)(argument); #end @@ -176,49 +185,69 @@ class Compiler { @param rec If true, recursively adds all sub-packages. @param ignore Array of module names to ignore for inclusion. + You can use `module*` with a * at the end for Wildcard matching @param classPaths An alternative array of paths (directory names) to use to search for modules to include. - Note that if you pass this argument, only the specified paths will be used for inclusion. + Note that if you pass this argument, only the specified paths will be used for inclusion. @param strict If true and given package wasn't found in any of class paths, fail with an error. **/ - public static function include( pack : String, ?rec = true, ?ignore : Array, ?classPaths : Array, strict = false ) { - var skip = if( ignore == null ) { + public static function include(pack:String, ?rec = true, ?ignore:Array, ?classPaths:Array, strict = false) { + var ignoreWildcard:Array = []; + var ignoreString:Array = []; + if (ignore != null) { + for (ignoreRule in ignore) { + if (StringTools.endsWith(ignoreRule, "*")) { + ignoreWildcard.push(ignoreRule.substr(0, ignoreRule.length - 1)); + } else { + ignoreString.push(ignoreRule); + } + } + } + var skip = if (ignore == null) { function(c) return false; } else { - function(c) return Lambda.has(ignore, c); + function(c:String) { + if (Lambda.has(ignoreString, c)) + return true; + for (ignoreRule in ignoreWildcard) + if (StringTools.startsWith(c, ignoreRule)) + return true; + return false; + } } var displayValue = Context.definedValue("display"); - if( classPaths == null ) { + if (classPaths == null) { classPaths = Context.getClassPath(); // do not force inclusion when using completion switch (displayValue) { case null: case "usage": - case _: return; + case _: + return; } // normalize class path - for( i in 0...classPaths.length ) { + for (i in 0...classPaths.length) { var cp = StringTools.replace(classPaths[i], "\\", "/"); - if(StringTools.endsWith(cp, "/")) + if (StringTools.endsWith(cp, "/")) cp = cp.substr(0, -1); - if( cp == "" ) + if (cp == "") cp = "."; classPaths[i] = cp; } } var prefix = pack == '' ? '' : pack + '.'; var found = false; - for( cp in classPaths ) { + for (cp in classPaths) { var path = pack == '' ? cp : cp + "/" + pack.split(".").join("/"); - if( !sys.FileSystem.exists(path) || !sys.FileSystem.isDirectory(path) ) + if (!sys.FileSystem.exists(path) || !sys.FileSystem.isDirectory(path)) continue; found = true; - for( file in sys.FileSystem.readDirectory(path) ) { - if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) { + for (file in sys.FileSystem.readDirectory(path)) { + if (StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0) { var cl = prefix + file.substr(0, file.length - 3); - if( skip(cl) ) + if (skip(cl)) continue; Context.getModule(cl); - } else if( rec && sys.FileSystem.isDirectory(path + "/" + file) && !skip(prefix + file) ) + } else if (rec && sys.FileSystem.isDirectory(path + "/" + file) && !skip(prefix + file)) include(prefix + file, true, ignore, classPaths); } } @@ -229,7 +258,7 @@ class Compiler { /** Exclude a class or an enum without changing it to `@:nativeGen`. **/ - static function excludeBaseType( baseType : Type.BaseType ) : Void { + static function excludeBaseType(baseType:Type.BaseType):Void { if (!baseType.isExtern) { var meta = baseType.meta; if (!meta.has(":nativeGen")) { @@ -245,48 +274,52 @@ class Compiler { @param rec If true, recursively excludes all sub-packages. **/ - public static function exclude( pack : String, ?rec = true ) { + public static function exclude(pack:String, ?rec = true) { Context.onGenerate(function(types) { - for( t in types ) { - var b : Type.BaseType, name; - switch( t ) { - case TInst(c, _): - name = c.toString(); - b = c.get(); - case TEnum(e, _): - name = e.toString(); - b = e.get(); - default: continue; + for (t in types) { + var b:Type.BaseType, name; + switch (t) { + case TInst(c, _): + name = c.toString(); + b = c.get(); + case TEnum(e, _): + name = e.toString(); + b = e.get(); + default: + continue; } var p = b.pack.join("."); - if( (p == pack || name == pack) || (rec && StringTools.startsWith(p, pack + ".")) ) + if ((p == pack || name == pack) || (rec && StringTools.startsWith(p, pack + "."))) excludeBaseType(b); } - }); + }, false); } /** Exclude classes and enums listed in an extern file (one per line) from being generated. **/ - public static function excludeFile( fileName : String ) { + public static function excludeFile(fileName:String) { fileName = Context.resolvePath(fileName); - var f = sys.io.File.read(fileName,true); + var f = sys.io.File.read(fileName, true); var classes = new haxe.ds.StringMap(); try { - while( true ) { + while (true) { var l = StringTools.trim(f.readLine()); - if( l == "" || !~/[A-Za-z0-9._]/.match(l) ) + if (l == "" || !~/[A-Za-z0-9._]/.match(l)) continue; - classes.set(l,true); + classes.set(l, true); } - } catch( e : haxe.io.Eof ) { - } + } catch (e:haxe.io.Eof) {} Context.onGenerate(function(types) { - for( t in types ) { - switch( t ) { - case TInst(c, _): if( classes.exists(c.toString()) ) excludeBaseType(c.get()); - case TEnum(e, _): if( classes.exists(e.toString()) ) excludeBaseType(e.get()); - default: + for (t in types) { + switch (t) { + case TInst(c, _): + if (classes.exists(c.toString())) + excludeBaseType(c.get()); + case TEnum(e, _): + if (classes.exists(e.toString())) + excludeBaseType(e.get()); + default: } } }); @@ -295,52 +328,56 @@ class Compiler { /** Load a type patch file that can modify the field types within declared classes and enums. **/ - public static function patchTypes( file : String ) : Void { + public static function patchTypes(file:String):Void { var file = Context.resolvePath(file); var f = sys.io.File.read(file, true); try { - while( true ) { + while (true) { var r = StringTools.trim(f.readLine()); - if( r == "" || r.substr(0,2) == "//" ) continue; - if( StringTools.endsWith(r,";") ) r = r.substr(0,-1); - if( r.charAt(0) == "-" ) { + if (r == "" || r.substr(0, 2) == "//") + continue; + if (StringTools.endsWith(r, ";")) + r = r.substr(0, -1); + if (r.charAt(0) == "-") { r = r.substr(1); - var isStatic = StringTools.startsWith(r,"static "); - if( isStatic ) r = r.substr(7); + var isStatic = StringTools.startsWith(r, "static "); + if (isStatic) + r = r.substr(7); var p = r.split("."); var field = p.pop(); - removeField(p.join("."),field,isStatic); + removeField(p.join("."), field, isStatic); continue; } - if( r.charAt(0) == "@" ) { + if (r.charAt(0) == "@") { var rp = r.split(" "); var type = rp.pop(); var isStatic = rp[rp.length - 1] == "static"; - if( isStatic ) rp.pop(); + if (isStatic) + rp.pop(); var meta = rp.join(" "); var p = type.split("."); - var field = if( p.length > 1 && p[p.length-2].charAt(0) >= "a" ) null else p.pop(); - addMetadata(meta,p.join("."),field,isStatic); + var field = if (p.length > 1 && p[p.length - 2].charAt(0) >= "a") null else p.pop(); + addMetadata(meta, p.join("."), field, isStatic); continue; } - if( StringTools.startsWith(r, "enum ") ) { - define("fakeEnum:" + r.substr(5)); + if (StringTools.startsWith(r, "enum ")) { + define("enumAbstract:" + r.substr(5)); continue; } var rp = r.split(" : "); - if( rp.length > 1 ) { + if (rp.length > 1) { r = rp.shift(); - var isStatic = StringTools.startsWith(r,"static "); - if( isStatic ) r = r.substr(7); + var isStatic = StringTools.startsWith(r, "static "); + if (isStatic) + r = r.substr(7); var p = r.split("."); var field = p.pop(); - setFieldType(p.join("."),field,rp.join(" : "),isStatic); + setFieldType(p.join("."), field, rp.join(" : "), isStatic); continue; } - throw "Invalid type patch "+r; + throw "Invalid type patch " + r; } - } catch( e : haxe.io.Eof ) { - } + } catch (e:haxe.io.Eof) {} } /** @@ -359,7 +396,7 @@ class Compiler { @param paths An Array of package, module or sub-type dot paths to keep. @param recursive If true, recurses into sub-packages for package paths. **/ - public static function keep(?path : String, ?paths : Array, ?recursive:Bool = true) { + public static function keep(?path:String, ?paths:Array, ?recursive:Bool = true) { if (null == paths) paths = []; if (null != path) @@ -369,6 +406,16 @@ class Compiler { } } + /** + Enables null safety for a type or a package. + + @param path A package, module or sub-type dot path to keep. + @param recursive If true, recurses into sub-packages for package paths. + **/ + public static function nullSafety(path:String, mode:NullSafetyMode = Loose, recursive:Bool = true) { + addGlobalMetadata(path, '@:nullSafety($mode)', recursive); + } + /** Adds metadata `meta` to all types (if `toTypes = true`) or fields (if `toFields = true`) whose dot-path matches `pathFilter`. @@ -394,34 +441,43 @@ class Compiler { /** Change the default JS output by using a custom generator callback **/ - public static function setCustomJSGenerator( callb : JSGenApi -> Void ) { + public static function setCustomJSGenerator(callb:JSGenApi->Void) { #if (neko || eval) load("set_custom_js_generator", 1)(callb); #end } #if (neko || eval) - static inline function load( f, nargs ) : Dynamic { + static inline function load(f, nargs):Dynamic { return @:privateAccess Context.load(f, nargs); } #end -#end + /** + Clears cached results of file lookups + **/ + public static function flushDiskCache() { + #if (neko || eval) + load("flush_disk_cache", 0)(); + #end + } + + #end #if (js || lua || macro) /** Embed a JavaScript or Lua file at compile time (can be called by `--macro` or within an `__init__` method). **/ - public static #if !macro macro #end function includeFile( file : String, position:IncludePosition = Top ) { - return switch ((position:String).toLowerCase()) { + public static #if !macro macro #end function includeFile(file:String, position:IncludePosition = Top) { + return switch ((position : String).toLowerCase()) { case Inline: if (Context.getLocalModule() == "") Context.error("Cannot use inline mode when includeFile is called by `--macro`", Context.currentPos()); - var f = try sys.io.File.getContent(Context.resolvePath(file)) catch( e : Dynamic ) Context.error(Std.string(e), Context.currentPos()); + var f = try sys.io.File.getContent(Context.resolvePath(file)) catch (e:Dynamic) Context.error(Std.string(e), Context.currentPos()); var p = Context.currentPos(); var magic = if (Context.defined("js")) "__js__" else "__lua__"; - { expr : EUntyped( { expr : ECall( { expr : EConst(CIdent(magic)), pos : p }, [ { expr : EConst(CString(f)), pos : p } ]), pos : p } ), pos : p }; + {expr: EUntyped({expr: ECall({expr: EConst(CIdent(magic)), pos: p}, [{expr: EConst(CString(f)), pos: p}]), pos: p}), pos: p}; case Top | Closure: @:privateAccess Context.includeFile(file, position); macro {}; @@ -429,24 +485,55 @@ class Compiler { Context.error("unknown includeFile position: " + position, Context.currentPos()); } } - #end - } -@:enum abstract IncludePosition(String) from String to String { +enum abstract IncludePosition(String) from String to String { /** Prepend the file content to the output file. - */ + **/ var Top = "top"; + /** Prepend the file content to the body of the top-level closure. Since the closure is in strict-mode, there may be run-time error if the input is not strict-mode-compatible. - */ + **/ var Closure = "closure"; + /** Directly inject the file content at the call site. - */ + **/ var Inline = "inline"; } + +enum abstract NullSafetyMode(String) to String { + /** + Disable null safety. + **/ + var Off; + + /** + Full scale null safety. + **/ + var Strict; + + /** + Loose safety. + If an expression is checked ` != null`, then it's considered safe even if it could be modified after the check. + E.g. + ```haxe + function example(o:{field:Null}) { + if(o.field != null) { + mutate(o); + var notNullable:String = o.field; //no error + } + } + + function mutate(o:{field:Null}) { + o.field = null; + } + ``` + **/ + var Loose; +} diff --git a/std/haxe/macro/ComplexTypeTools.hx b/std/haxe/macro/ComplexTypeTools.hx index cb546f15a19..efe5144ca67 100644 --- a/std/haxe/macro/ComplexTypeTools.hx +++ b/std/haxe/macro/ComplexTypeTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -30,25 +30,22 @@ import haxe.macro.Expr; additional methods on `haxe.macro.ComplexType` instances. **/ class ComplexTypeTools { - /** Converts type `c` to a human-readable `String` representation. The result is guaranteed to be valid Haxe code, but there may be differences from the original lexical syntax. **/ - static public function toString( c : ComplexType ) : String + static public function toString(c:ComplexType):String return new Printer().printComplexType(c); - #if macro - + #if (macro || display) /** Returns a type corresponding to `c`. If `c` is null, the result is null. **/ - static public function toType( c : ComplexType ) : Null - return c == null ? null : Context.resolveType(c,Context.currentPos()); - + static public function toType(c:ComplexType):Null + return c == null ? null : Context.resolveType(c, Context.currentPos()); #end } diff --git a/std/haxe/macro/Context.hl.hx b/std/haxe/macro/Context.hl.hx deleted file mode 100644 index 2437d9b7684..00000000000 --- a/std/haxe/macro/Context.hl.hx +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.macro; - -import haxe.macro.Expr; -import haxe.macro.Type.TypedExpr; - -@:noDoc @:hlNative("macro") -class Context { - -#if macro - - public static function error( msg : String, pos : Position ) : Dynamic { - return null; - } - - public static function fatalError( msg : String, pos : Position ) : Dynamic { - return null; - } - - public static function warning( msg : String, pos : Position ) : Void { - } - - public static function resolvePath( file : String ) : String { - return null; - } - - public static function getClassPath() : Array { - return null; - } - - public static function currentPos() : Position { - return null; - } - - @:require(haxe_ver >= 3.1) - public static function getExpectedType():Null { - return null; - } - - @:require(haxe_ver >= 3.2) - public static function getCallArguments():Null> { - return null; - } - - public static function getLocalClass() : Null> { - var l = getLocalType(); - if( l == null ) return null; - return switch( l ) { - case TInst(c,_): c; - default: null; - } - } - - public static function getLocalModule() : String { - return null; - } - - public static function getLocalType() : Null { - return null; - } - - public static function getLocalMethod() : Null { - return null; - } - - public static function getLocalUsing() : Array> { - return null; - } - - public static function getLocalImports() : Array { - return null; - } - - private static function localVars(b:Bool) : Map { - return null; - } - - @:deprecated("Use Context.getLocalTVars() instead") - public static function getLocalVars() : Map { - return cast localVars(false); - } - - @:require(haxe_ver >= 3.102) - public static function getLocalTVars() : Map { - return cast localVars(true); - } - - public static function defined( s : String ) : Bool { - return null; - } - - public static function definedValue( key : String ) : String { - return null; - } - - public static function getDefines() : Map { - return null; - } - - public static function getType( name : String ) : Type { - return null; - } - - public static function getModule( name : String ) : Array { - return null; - } - - static function doParse( expr : String, pos : Position, isInline : Bool ) : Expr { - return null; - } - - public static function parse( expr : String, pos : Position ) : Expr { - return doParse(expr,pos,false); - } - - public static function parseInlineString( expr : String, pos : Position ) : Expr { - return doParse(expr,pos,true); - } - - public static function makeExpr( v : Dynamic, pos : Position ) : Expr { - return null; - } - - public static function signature( v : Dynamic ) : String { - return null; - } - - public static function onGenerate( callback : Array -> Void ) : Void { - } - - @:require(haxe_ver >= 3.1) - public static function onAfterGenerate( callback : Void -> Void ) : Void { - } - - public static function onAfterTyping( callback : Array -> Void ) : Void { - } - - public static function onTypeNotFound ( callback : String -> TypeDefinition ) : Void { - } - - public static function typeof( e : Expr ) : Type { - return null; - } - - @:require(haxe_ver >= 3.1) - public static function typeExpr( e : Expr ) : TypedExpr { - return null; - } - - @:require(haxe_ver >= 3.3) - public static function resolveType( t : ComplexType, p : Position ) : Type { - return null; - } - - public static function toComplexType( t : Type ) : Null { - return null; - } - - public static function unify( t1 : Type, t2 : Type) : Bool { - return false; - } - - public static function follow( t : Type, ?once : Bool ) : Type { - return null; - } - - public static function followWithAbstracts(t : Type, once : Bool = false ) : Type { - return null; - } - - public static function getPosInfos( p : Position ) : { min : Int, max : Int, file : String } { - return null; - } - - public static function makePosition( inf : { min : Int, max : Int, file : String } ) : Position { - return null; - } - - public static function getResources():Map { - return null; - } - - public static function addResource( name : String, data : haxe.io.Bytes ) : Void { - } - - public static function getBuildFields() : Array { - return null; - } - - public static function defineType( t : TypeDefinition ) : Void { - } - - public static function defineModule( modulePath : String, types : Array, ?imports: Array, ?usings : Array ) : Void { - } - - public static function getTypedExpr( t : Type.TypedExpr ) : Expr { - return null; - } - - @:require(haxe_ver >= 3.2) - public static function storeTypedExpr( t : Type.TypedExpr ) : Expr { - return null; - } - - public static function registerModuleDependency( modulePath : String, externFile : String ) : Void { - } - - public static function registerModuleReuseCall( modulePath : String, macroCall : String ) : Void { - } - - public static function onMacroContextReused( callb : Void -> Bool ) : Void { - } - - private static function includeFile( file : String, position : String ) { - } - - private static function sExpr( e : TypedExpr, pretty : Bool ) : String { - return null; - } - -#end - -} diff --git a/std/haxe/macro/Context.hx b/std/haxe/macro/Context.hx index bbbf52d531c..c97d8aae600 100644 --- a/std/haxe/macro/Context.hx +++ b/std/haxe/macro/Context.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,17 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.macro; import haxe.macro.Expr; import haxe.macro.Type.TypedExpr; +enum Message { + Info(msg:String, pos:Position); + Warning(msg:String, pos:Position); +} + /** Context provides an API for macro programming. @@ -36,29 +42,50 @@ import haxe.macro.Type.TypedExpr; - `haxe.macro.TypeTools` **/ class Context { - -#if (neko || eval || display) + #if (neko || eval || display) /** Displays a compilation error `msg` at the given `Position` `pos` and aborts the current macro call. **/ - public static function error( msg : String, pos : Position ) : Dynamic { - return load("error",2)(msg, pos); + public static function error(msg:String, pos:Position):Dynamic { + return load("error", 2)(msg, pos); } /** Displays a compilation error `msg` at the given `Position` `pos` and aborts the compilation. **/ - public static function fatalError( msg : String, pos : Position ) : Dynamic { - return load("fatal_error",2)(msg, pos); + public static function fatalError(msg:String, pos:Position):Dynamic { + return load("fatal_error", 2)(msg, pos); } /** Displays a compilation warning `msg` at the given `Position` `pos`. **/ - public static function warning( msg : String, pos : Position ) { - load("warning",2)(msg, pos); + public static function warning(msg:String, pos:Position) { + load("warning", 2)(msg, pos); + } + + /** + Displays a compilation info `msg` at the given `Position` `pos`. + **/ + public static function info(msg:String, pos:Position) { + load("info", 2)(msg, pos); + } + + /** + Gets a list of all current compilation info/warning messages. + **/ + public static function getMessages() : Array { + return load("get_messages",0)(); + } + + /** + Filters all current info/warning messages. Filtered out messages will + not be displayed by the compiler. + **/ + public static function filterMessages( predicate : Message -> Bool ) { + load("filter_messages",1)(predicate); } /** @@ -70,8 +97,8 @@ class Context { If a class path was declared relative, this method returns the relative file path. Otherwise it returns the absolute file path. **/ - public static function resolvePath( file : String ) : String { - return load("resolve_path",1)(file); + public static function resolvePath(file:String):String { + return load("resolve_path", 1)(file); } /** @@ -81,14 +108,14 @@ class Context { Modifying the returned array has no effect on the compiler. Class paths can be added using `haxe.macro.Compiler.addClassPath`. **/ - public static function getClassPath() : Array { - return load("class_path",0)(); + public static function getClassPath():Array { + return load("class_path", 0)(); } /** Returns the position at which the macro was called. **/ - public static function currentPos() : Position { + public static function currentPos():Position { return load("current_pos", 0)(); } @@ -96,12 +123,11 @@ class Context { Returns the type which is expected at the place the macro is called. This affects usages such as `var x:Int = macroCall()`, where the - expected type will be reported as Int. + expected type will be reported as `Int`. - Might return null if no specific type is expected or if the calling + Might return `null` if no specific type is expected or if the calling macro is not an expression-macro. **/ - @:require(haxe_ver >= 3.1) public static function getExpectedType():Null { return load("get_expected_type", 0)(); } @@ -112,7 +138,6 @@ class Context { Returns `null` if the current macro is not a `@:genericBuild` macro. **/ - @:require(haxe_ver >= 3.2) public static function getCallArguments():Null> { return load("get_call_arguments", 0)(); } @@ -120,39 +145,40 @@ class Context { /** Returns the current class in which the macro was called. - If no such class exists, null is returned. + If no such class exists, `null` is returned. **/ - public static function getLocalClass() : Null> { - var l : Type = load("get_local_type", 0)(); - if( l == null ) return null; - return switch( l ) { - case TInst(c,_): c; - default: null; + public static function getLocalClass():Null> { + var l:Type = load("get_local_type", 0)(); + if (l == null) + return null; + return switch (l) { + case TInst(c, _): c; + default: null; } } /** Returns the current module path in/on which the macro was called. **/ - public static function getLocalModule() : String { + public static function getLocalModule():String { return load("get_local_module", 0)(); } /** Returns the current type in/on which the macro was called. - If no such type exists, null is returned. + If no such type exists, `null` is returned. **/ - public static function getLocalType() : Null { + public static function getLocalType():Null { return load("get_local_type", 0)(); } /** Returns the name of the method from which the macro was called. - If no such method exists, null is returned. + If no such method exists, `null` is returned. **/ - public static function getLocalMethod() : Null { + public static function getLocalMethod():Null { return load("get_local_method", 0)(); } @@ -162,7 +188,7 @@ class Context { Modifying the returned array has no effect on the compiler. **/ - public static function getLocalUsing() : Array> { + public static function getLocalUsing():Array> { return load("get_local_using", 0)(); } @@ -171,7 +197,7 @@ class Context { Modifying the returned array has no effect on the compiler. **/ - public static function getLocalImports() : Array { + public static function getLocalImports():Array { return load("get_local_imports", 0)(); } @@ -185,7 +211,7 @@ class Context { Modifying the returned map has no effect on the compiler. **/ @:deprecated("Use Context.getLocalTVars() instead") - public static function getLocalVars() : Map { + public static function getLocalVars():Map { return load("local_vars", 1)(false); } @@ -193,44 +219,49 @@ class Context { Similar to `getLocalVars`, but returns elements of type `TVar` instead of `Type`. **/ - @:require(haxe_ver >= 3.102) - public static function getLocalTVars() : Map { + public static function getLocalTVars():Map { return load("local_vars", 1)(true); } /** - Tells if compiler directive `s` has been set. + Tells if the conditional compilation flag `s` has been set. - Compiler directives are set using the `-D` command line parameter, or + Compiler flags are set using the `-D` command line parameter, or by calling `haxe.macro.Compiler.define`. + + @see https://haxe.org/manual/lf-condition-compilation.html **/ - public static function defined( s : String ) : Bool { + public static function defined(s:String):Bool { return load("defined", 1)(s); } /** - Returns the value defined for compiler directive `key`. + Returns the value defined for the conditional compilation flag `key`. - If no value is defined for `key`, null is returned. + If no value is defined for `key`, `null` is returned. - Compiler directive values are set using the `-D key=value` command line + Compiler flags values are set using the `-D key=value` command line parameter, or by calling `haxe.macro.Compiler.define`. The default value is `"1"`. + + @see https://haxe.org/manual/lf-condition-compilation.html **/ - public static function definedValue( key : String ) : String { + public static function definedValue(key:String):String { return load("defined_value", 1)(key); } /** - Returns a map of all compiler directives that have been set. + Returns a map of all conditional compilation flags that have been set. - Compiler directives are set using the `-D` command line parameter, or + Compiler flags are set using the `-D` command line parameter, or by calling `haxe.macro.Compiler.define`. Modifying the returned map has no effect on the compiler. - */ - public static function getDefines() : Map { + + @see https://haxe.org/manual/lf-condition-compilation.html + **/ + public static function getDefines():Map { return load("get_defines", 0)(); } @@ -242,7 +273,7 @@ class Context { If no type can be found, an exception of type `String` is thrown. **/ - public static function getType( name : String ) : Type { + public static function getType(name:String):Type { return load("get_type", 1)(name); } @@ -253,9 +284,9 @@ class Context { The resolution follows the usual class path rules where the last declared class path has priority. - If no module can be found, null is returned. + If no module can be found, `null` is returned. **/ - public static function getModule( name : String ) : Array { + public static function getModule(name:String):Array { return load("get_module", 1)(name); } @@ -267,7 +298,7 @@ class Context { The provided `Position` `pos` is used for all generated inner AST nodes. **/ - public static function parse( expr : String, pos : Position ) : Expr { + public static function parse(expr:String, pos:Position):Expr { return load("do_parse", 3)(expr, pos, false); } @@ -275,7 +306,7 @@ class Context { Similar to `parse`, but error positions are reported within the provided String `expr`. **/ - public static function parseInlineString( expr : String, pos : Position ) : Expr { + public static function parseInlineString(expr:String, pos:Position):Expr { return load("do_parse", 3)(expr, pos, true); } @@ -288,14 +319,14 @@ class Context { The provided `Position` `pos` is used for all generated inner AST nodes. **/ - public static function makeExpr( v : Dynamic, pos : Position ) : Expr { + public static function makeExpr(v:Dynamic, pos:Position):Expr { return load("make_expr", 2)(v, pos); } /** Returns a hashed MD5 signature of value `v`. **/ - public static function signature( v : Dynamic ) : String { + public static function signature(v:Dynamic):String { return load("signature", 1)(v); } @@ -306,9 +337,17 @@ class Context { The callback receives an `Array` containing all types which are about to be generated. Modifications are limited to metadata, it is mainly intended to obtain information. + + By default, the callback is made before types are stored in the compilation + server, if active. This means that any effect persists for the next compilation. + If `persistent` is set to `false`, changes to types made by the callback only + affect the current compilation. If no compilation server is used, this flag has + no effect. + + *Note*: the callback is still invoked when generation is disabled with `--no-output`. **/ - public static function onGenerate( callback : Array -> Void ) { - load("on_generate",1)(callback); + public static function onGenerate(callback:Array->Void, persistent:Bool = true) { + load("on_generate", 2)(callback, persistent); } /** @@ -317,10 +356,11 @@ class Context { Compilation has completed at this point and cannot be influenced anymore. However, contextual information is still available. + + *Note*: the callback is still invoked when generation is disabled with `--no-output`. **/ - @:require(haxe_ver >= 3.1) - public static function onAfterGenerate( callback : Void -> Void ) { - load("on_after_generate",1)(callback); + public static function onAfterGenerate(callback:Void->Void) { + load("on_after_generate", 1)(callback); } /** @@ -331,8 +371,8 @@ class Context { It is possible to define new types in the callback, in which case it will be called again with the new types as argument. **/ - public static function onAfterTyping( callback : Array -> Void ) { - load("on_after_typing",1)(callback); + public static function onAfterTyping(callback:Array->Void) { + load("on_after_typing", 1)(callback); } /** @@ -340,11 +380,11 @@ class Context { cannot be resolved. The callback may return a type definition, which is then used for the - expected type. If it returns null, the type is considered to still not + expected type. If it returns `null`, the type is considered to still not exist. **/ - public static function onTypeNotFound ( callback : String -> TypeDefinition ) { - load("on_type_not_found",1)(callback); + public static function onTypeNotFound(callback:String->TypeDefinition) { + load("on_type_not_found", 1)(callback); } /** @@ -353,7 +393,7 @@ class Context { Typing the expression may result in a compiler error which can be caught using `try ... catch`. **/ - public static function typeof( e : Expr ) : Type { + public static function typeof(e:Expr):Type { return load("typeof", 1)(e); } @@ -363,8 +403,7 @@ class Context { Typing the expression may result in a compiler error which can be caught using `try ... catch`. **/ - @:require(haxe_ver >= 3.1) - public static function typeExpr( e : Expr ) : TypedExpr { + public static function typeExpr(e:Expr):TypedExpr { return load("type_expr", 1)(e); } @@ -375,9 +414,8 @@ class Context { caught using `try ... catch`. Resolution is performed based on the current context in which the macro is called. **/ - @:require(haxe_ver >= 3.3) - public static function resolveType( t : ComplexType, p : Position ) : Type { - return load("resolve_type", 2)(t,p); + public static function resolveType(t:ComplexType, p:Position):Type { + return load("resolve_type", 2)(t, p); } /** @@ -385,14 +423,14 @@ class Context { See `haxe.macro.TypeTools.toComplexType` for details. **/ - public static function toComplexType( t : Type ) : Null { + public static function toComplexType(t:Type):Null { return load("to_complex_type", 1)(t); } /** Tries to unify `t1` and `t2` and returns `true` if successful. **/ - public static function unify( t1 : Type, t2 : Type) : Bool { + public static function unify(t1:Type, t2:Type):Bool { return load("unify", 2)(t1, t2); } @@ -401,8 +439,8 @@ class Context { See `haxe.macro.TypeTools.follow` for details. **/ - public static function follow( t : Type, ?once : Bool ) : Type { - return load("follow", 2)(t,once); + public static function follow(t:Type, ?once:Bool):Type { + return load("follow", 2)(t, once); } /** @@ -410,22 +448,22 @@ class Context { See `haxe.macro.TypeTools.followWithAbstracts` for details. **/ - public static function followWithAbstracts(t : Type, once : Bool = false ) : Type { - return load("follow_with_abstracts", 2)(t,once); + public static function followWithAbstracts(t:Type, once:Bool = false):Type { + return load("follow_with_abstracts", 2)(t, once); } /** Returns the information stored in `Position` `p`. **/ - public static function getPosInfos( p : Position ) : { min : Int, max : Int, file : String } { - return load("get_pos_infos",1)(p); + public static function getPosInfos(p:Position):{min:Int, max:Int, file:String} { + return load("get_pos_infos", 1)(p); } /** Builds a `Position` from `inf`. **/ - public static function makePosition( inf : { min : Int, max : Int, file : String } ) : Position { - return load("make_position",3)(inf.min,inf.max,inf.file); + public static function makePosition(inf:{min:Int, max:Int, file:String}):Position { + return load("make_position", 3)(inf.min, inf.max, inf.file); } /** @@ -434,8 +472,8 @@ class Context { Modifying the returned map has no effect on the compilation, use `haxe.macro.Context.addResource` to add new resources to the compilation unit. **/ - public static function getResources():Map { - return load("get_resources",0)(); + public static function getResources():Map { + return load("get_resources", 0)(); } /** @@ -448,10 +486,10 @@ class Context { Compilation server : when using the compilation server, the resource is bound to the Haxe module which calls the macro, so it will be included again if that module is reused. If this resource concerns several modules, prefix its - name with a $ sign, this will bind it to the macro module instead. + name with a `$` sign, this will bind it to the macro module instead. **/ - public static function addResource( name : String, data : haxe.io.Bytes ) { - load("add_resource",2)(name,data); + public static function addResource(name:String, data:haxe.io.Bytes) { + load("add_resource", 2)(name, data); } /** @@ -459,7 +497,7 @@ class Context { This is only defined for `@:build/@:autoBuild` macros. **/ - public static function getBuildFields() : Array { + public static function getBuildFields():Array { return load("get_build_fields", 0)(); } @@ -470,7 +508,7 @@ class Context { a module path that will be used as a dependency for the newly defined module instead of the current module. **/ - public static function defineType( t : TypeDefinition, ?moduleDependency : String ) : Void { + public static function defineType(t:TypeDefinition, ?moduleDependency:String):Void { load("define_type", 2)(t, moduleDependency); } @@ -480,11 +518,13 @@ class Context { The individual `types` can reference each other and any identifier respects the `imports` and `usings` as usual, expect that imports are - not allowed to have `.*` wildcards or `in s` shorthands. + not allowed to have `.*` wildcards or `as s` shorthands. **/ - public static function defineModule( modulePath : String, types : Array, ?imports: Array, ?usings : Array ) : Void { - if( imports == null ) imports = []; - if( usings == null ) usings = []; + public static function defineModule(modulePath:String, types:Array, ?imports:Array, ?usings:Array):Void { + if (imports == null) + imports = []; + if (usings == null) + usings = []; load("define_module", 4)(modulePath, types, imports, usings); } @@ -493,26 +533,24 @@ class Context { This process may lose some information. **/ - public static function getTypedExpr( t : Type.TypedExpr ) : Expr { - return load("get_typed_expr",1)(t); + public static function getTypedExpr(t:Type.TypedExpr):Expr { + return load("get_typed_expr", 1)(t); } - /** Store typed expression `t` internally and give a syntax-level expression that can be returned from a macro and will be replaced by the stored typed expression. - If `t` is null or invalid, an exception is thrown. + If `t` is `null` or invalid, an exception is thrown. NOTE: the returned value references an internally stored typed expression that is reset between compilations, so care should be taken when storing the expression returned by this method in a static variable and using the compilation server. **/ - @:require(haxe_ver >= 3.2) - public static function storeTypedExpr( t : Type.TypedExpr ) : Expr { - return load("store_typed_expr",1)(t); + public static function storeTypedExpr(t:Type.TypedExpr):Expr { + return load("store_typed_expr", 1)(t); } /** @@ -520,7 +558,7 @@ class Context { returns a syntax-level expression that can be returned from a macro and will be replaced by the stored typed expression. - If `e` is null or invalid, an exception is thrown. + If `e` is `null` or invalid, an exception is thrown. A call to `storeExpr(e)` is equivalent to `storeTypedExpr(typeExpr(e))` without the overhead of encoding and decoding between regular and macro runtime. @@ -530,39 +568,10 @@ class Context { the expression returned by this method in a static variable and using the compilation server. **/ - @:require(haxe_ver >= 4.0) - public static function storeExpr( e : Expr ) : Expr { - return load("store_expr",1)(e); + public static function storeExpr(e:Expr):Expr { + return load("store_expr", 1)(e); } - /** - Evaluates `e` as macro code. - - Any call to this function takes effect when the macro is executed, not - during typing. As a consequence, this function can not introduce new - local variables into the macro context and may have other restrictions. - - Usage example: - - ```haxe - var e = macro function(i) return i * 2; - var f:Int -> Int = haxe.macro.Context.eval(e); - trace(f(2)); // 4 - ``` - - Code passed in from outside the macro cannot reference anything in its - context, such as local variables. However, it is possible to reference - static methods. - - This method should be considered experimental. - - If `e` is null, the result is unspecified. - **/ - //@:require(haxe_ver >= 3.3) - //public static function eval( e : Expr ) : Dynamic { - //return load("eval",1)(e); - //} - /** Manually adds a dependency between module `modulePath` and an external file `externFile`. @@ -572,41 +581,25 @@ class Context { Has no effect if the compilation cache is not used. **/ - public static function registerModuleDependency( modulePath : String, externFile : String ) { - load("register_module_dependency", 2)(modulePath,externFile); + public static function registerModuleDependency(modulePath:String, externFile:String) { + load("register_module_dependency", 2)(modulePath, externFile); } - /** - Register a macro call to be performed every time the module `modulePath` is reused by the compilation cache, - meaning that neither the module itself nor its dependencies was changed since last compilation. - - The `macroCall` should be a String containing valid Haxe expression, similar to `--init` macros (see https://haxe.org/manual/macro-initialization.html). - Multiple calls with the exact same `macroCall` value will only register the callback once. - - This also triggers loading of given module and its dependencies, if it's not yet loaded, - but given macro call will not be called on the first module load. - - If the compilation cache is not used, `macroCall` expressions will not be called, - but calling this function will still trigger loading of given `modulePath`. - **/ - public static function registerModuleReuseCall( modulePath : String, macroCall : String ) { - load("register_module_reuse_call", 2)(modulePath,macroCall); + @:deprecated + public static function registerModuleReuseCall(modulePath:String, macroCall:String) { + throw "This method is no longer supported. See https://github.com/HaxeFoundation/haxe/issues/5746"; } - /** - Register a callback function that will be called every time the macro context cached is reused with a new - compilation. This enable to reset some static vars since the code might have been changed. If the callback - returns false, the macro context is discarded and another one is created. - **/ - public static function onMacroContextReused( callb : Void -> Bool ) { - load("on_macro_context_reused", 1)(callb); + @:deprecated + public static function onMacroContextReused(callb:Void->Bool) { + throw "This method is no longer supported. See https://github.com/HaxeFoundation/haxe/issues/5746"; } @:allow(haxe.macro.TypeTools) @:allow(haxe.macro.MacroStringTools) @:allow(haxe.macro.TypedExprTools) @:allow(haxe.macro.PositionTools) - static function load(f:String, nargs:Int) : Dynamic { + static function load(f:String, nargs:Int):Dynamic { #if neko return neko.Lib.load("macro", f, nargs); #elseif eval @@ -616,14 +609,12 @@ class Context { #end } - private static function includeFile( file : String, position : String ) { + private static function includeFile(file:String, position:String) { load("include_file", 2)(file, position); } - private static function sExpr( e : TypedExpr, pretty : Bool ) : String { + private static function sExpr(e:TypedExpr, pretty:Bool):String { return haxe.macro.Context.load("s_expr", 2)(e, pretty); } - -#end - + #end } diff --git a/std/haxe/macro/ExampleJSGenerator.hx b/std/haxe/macro/ExampleJSGenerator.hx index e1799ff45c3..0468db75dc0 100644 --- a/std/haxe/macro/ExampleJSGenerator.hx +++ b/std/haxe/macro/ExampleJSGenerator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,19 +19,21 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.macro; + import haxe.macro.Type; import haxe.macro.Expr; + using Lambda; class ExampleJSGenerator { - - var api : JSGenApi; - var buf : StringBuf; - var inits : List; - var statics : List<{ c : ClassType, f : ClassField }>; - var packages : haxe.ds.StringMap; - var forbidden : haxe.ds.StringMap; + var api:JSGenApi; + var buf:StringBuf; + var inits:List; + var statics:List<{c:ClassType, f:ClassField}>; + var packages:haxe.ds.StringMap; + var forbidden:haxe.ds.StringMap; public function new(api) { this.api = api; @@ -40,13 +42,13 @@ class ExampleJSGenerator { statics = new List(); packages = new haxe.ds.StringMap(); forbidden = new haxe.ds.StringMap(); - for( x in ["prototype", "__proto__", "constructor"] ) + for (x in ["prototype", "__proto__", "constructor"]) forbidden.set(x, true); api.setTypeAccessor(getType); } - function getType( t : Type ) { - return switch(t) { + function getType(t:Type) { + return switch (t) { case TInst(c, _): getPath(c.get()); case TEnum(e, _): getPath(e.get()); case TAbstract(a, _): getPath(a.get()); @@ -70,15 +72,18 @@ class ExampleJSGenerator { return api.isKeyword(p) ? '["' + p + '"]' : "." + p; } - function genPackage( p : Array ) { + function genPackage(p:Array) { var full = null; - for( x in p ) { + for (x in p) { var prev = full; - if( full == null ) full = x else full += "." + x; - if( packages.exists(full) ) + if (full == null) + full = x + else + full += "." + x; + if (packages.exists(full)) continue; packages.set(full, true); - if( prev == null ) + if (prev == null) print('if(typeof $x==\'undefined\') $x = {}'); else { var p = prev + field(x); @@ -88,21 +93,21 @@ class ExampleJSGenerator { } } - function getPath( t : BaseType ) { + function getPath(t:BaseType) { return (t.pack.length == 0) ? t.name : t.pack.join(".") + "." + t.name; } - function checkFieldName( c : ClassType, f : ClassField ) { - if( forbidden.exists(f.name) ) + function checkFieldName(c:ClassType, f:ClassField) { + if (forbidden.exists(f.name)) Context.error("The field " + f.name + " is not allowed in JS", c.pos); } - function genClassField( c : ClassType, p : String, f : ClassField ) { + function genClassField(c:ClassType, p:String, f:ClassField) { checkFieldName(c, f); var field = field(f.name); print('$p.prototype$field = '); var e = f.expr(); - if( e == null ) + if (e == null) print("null"); else { genExpr(e); @@ -110,56 +115,57 @@ class ExampleJSGenerator { newline(); } - function genStaticField( c : ClassType, p : String, f : ClassField ) { + function genStaticField(c:ClassType, p:String, f:ClassField) { checkFieldName(c, f); var field = field(f.name); var e = f.expr(); - if( e == null ) { + if (e == null) { print('$p$field = null'); newline(); - } else switch( f.kind ) { - case FMethod(_): - print('$p$field = '); - genExpr(e); - newline(); - default: - statics.add( { c : c, f : f } ); - } + } else + switch (f.kind) { + case FMethod(_): + print('$p$field = '); + genExpr(e); + newline(); + default: + statics.add({c: c, f: f}); + } } - function genClass( c : ClassType ) { + function genClass(c:ClassType) { genPackage(c.pack); api.setCurrentClass(c); var p = getPath(c); print('$p = $$hxClasses[\'$p\'] = '); - if( c.constructor != null ) + if (c.constructor != null) genExpr(c.constructor.get().expr()); else print("function() { }"); newline(); - var name = p.split(".").map(api.quoteString).join(","); - print('$p.__name__ = [$name]'); + print('$p.__name__ = "$p"'); newline(); - if( c.superClass != null ) { + if (c.superClass != null) { var psup = getPath(c.superClass.t.get()); print('$p.__super__ = $psup'); newline(); print('for(var k in $psup.prototype ) $p.prototype[k] = $psup.prototype[k]'); newline(); } - for( f in c.statics.get() ) + for (f in c.statics.get()) genStaticField(c, p, f); - for( f in c.fields.get() ) { - switch( f.kind ) { - case FVar(r, _): - if( r == AccResolve ) continue; - default: + for (f in c.fields.get()) { + switch (f.kind) { + case FVar(r, _): + if (r == AccResolve) + continue; + default: } genClassField(c, p, f); } print('$p.prototype.__class__ = $p'); newline(); - if( c.interfaces.length > 0 ) { + if (c.interfaces.length > 0) { var me = this; var inter = c.interfaces.map(function(i) return me.getPath(i.t.get())).join(","); print('$p.__interfaces__ = [$inter]'); @@ -167,40 +173,38 @@ class ExampleJSGenerator { } } - function genEnum( e : EnumType ) { + function genEnum(e:EnumType) { genPackage(e.pack); var p = getPath(e); - var names = p.split(".").map(api.quoteString).join(","); var constructs = e.names.map(api.quoteString).join(","); - print('$p = $$hxClasses[\'$p\'] = { __ename__ : [$names], __constructs__ : [$constructs] }'); + print('$p = $$hxClasses[\'$p\'] = { __ename__ : \'$p\', __constructs__ : [$constructs] }'); newline(); - for( c in e.constructs.keys() ) { + for (c in e.constructs.keys()) { var c = e.constructs.get(c); var f = field(c.name); print('$p$f = '); - switch( c.type ) { - case TFun(args, _): - var sargs = args.map(function(a) return a.name).join(","); - print('function($sargs) { var $$x = ["${c.name}",${c.index},$sargs]; $$x.__enum__ = $p; $$x.toString = $$estr; return $$x; }'); - default: - print("[" + api.quoteString(c.name) + "," + c.index + "]"); - newline(); - print('$p$f.toString = $$estr'); - newline(); - print('$p$f.__enum__ = $p'); + switch (c.type) { + case TFun(args, _): + var sargs = args.map(function(a) return a.name).join(","); + print('function($sargs) { var $$x = ["${c.name}",${c.index},$sargs]; $$x.__enum__ = $p; $$x.toString = $$estr; return $$x; }'); + default: + print("[" + api.quoteString(c.name) + "," + c.index + "]"); + newline(); + print('$p$f.toString = $$estr'); + newline(); + print('$p$f.__enum__ = $p'); } newline(); } var meta = api.buildMetaData(e); - if( meta != null ) { + if (meta != null) { print('$p.__meta__ = '); genExpr(meta); newline(); } } - - function genStaticValue( c : ClassType, cf : ClassField ) { + function genStaticValue(c:ClassType, cf:ClassField) { var p = getPath(c); var f = field(cf.name); print('$p$f = '); @@ -208,17 +212,19 @@ class ExampleJSGenerator { newline(); } - function genType( t : Type ) { - switch( t ) { - case TInst(c, _): - var c = c.get(); - if( c.init != null ) - inits.add(c.init); - if( !c.isExtern ) genClass(c); - case TEnum(r, _): - var e = r.get(); - if( !e.isExtern ) genEnum(e); - default: + function genType(t:Type) { + switch (t) { + case TInst(c, _): + var c = c.get(); + if (c.init != null) + inits.add(c.init); + if (!c.isExtern) + genClass(c); + case TEnum(r, _): + var e = r.get(); + if (!e.isExtern) + genEnum(e); + default: } } @@ -227,27 +233,26 @@ class ExampleJSGenerator { newline(); print("function $bind(o,m) { var f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; return f; };"); newline(); - for( t in api.types ) + for (t in api.types) genType(t); - for( e in inits ) { + for (e in inits) { print(api.generateStatement(e)); newline(); } - for( s in statics ) { - genStaticValue(s.c,s.f); + for (s in statics) { + genStaticValue(s.c, s.f); newline(); } - if( api.main != null ) { + if (api.main != null) { genExpr(api.main); newline(); } sys.io.File.saveContent(api.outputFile, buf.toString()); } - #if macro + #if (macro || display) public static function use() { Compiler.setCustomJSGenerator(function(api) new ExampleJSGenerator(api).generate()); } #end - } diff --git a/std/haxe/macro/Expr.hx b/std/haxe/macro/Expr.hx index 739a5fc8159..98b0c40fa99 100644 --- a/std/haxe/macro/Expr.hx +++ b/std/haxe/macro/Expr.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,12 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.macro; #if (macro && !doc_gen) -@:coreType abstract Position { -} +@:coreType abstract Position {} #else + /** Represents a position in a file. **/ @@ -32,17 +33,17 @@ typedef Position = { /** Reference to the filename. **/ - var file : String; + var file:String; /** Position of the first character. **/ - var min : Int; + var min:Int; /** Position of the last character. **/ - var max : Int; + var max:Int; } #end @@ -54,33 +55,33 @@ enum Constant { /** Represents an integer literal. **/ - CInt( v : String ); + CInt(v:String); /** Represents a float literal. **/ - CFloat( f : String ); + CFloat(f:String); /** Represents a string literal. **/ - CString( s : String ); + CString(s:String); /** Represents an identifier. **/ - CIdent( s : String ); + CIdent(s:String); /** Represents a regular expression literal. Example: `~/haxe/i` - * The first argument _haxe_ is a string with regular expression pattern. - * The second argument _i_ is a string with regular expression flags. + * The first argument _haxe_ is a string with regular expression pattern. + * The second argument _i_ is a string with regular expression flags. @see https://haxe.org/manual/std-regex.html **/ - CRegexp( r : String, opt : String ); + CRegexp(r:String, opt:String); } /** @@ -201,7 +202,7 @@ enum Binop { `^=` `%=` **/ - OpAssignOp( op : Binop ); + OpAssignOp(op:Binop); /** `...` @@ -258,12 +259,12 @@ typedef Expr = { /** The expression kind. **/ - var expr : ExprDef; + var expr:ExprDef; /** The position of the expression. **/ - var pos : Position; + var pos:Position; } /** @@ -281,17 +282,17 @@ typedef Case = { /** The value expressions of the case. **/ - var values : Array; + var values:Array; /** The optional guard expressions of the case, if available. **/ - @:optional var guard : Null; + var ?guard:Null; /** The expression of the case, if available. **/ - var expr: Null; + var expr:Null; } /** @@ -302,17 +303,22 @@ typedef Var = { /** The name of the variable. **/ - var name : String; + var name:String; /** The type-hint of the variable, if available. **/ - var type : Null; + var type:Null; /** The expression of the variable, if available. **/ - var expr : Null; + var expr:Null; + + /** + Whether or not the variable can be assigned to. + **/ + var ?isFinal:Bool; } /** @@ -323,17 +329,17 @@ typedef Catch = { /** The name of the catch variable. **/ - var name : String; + var name:String; /** The type of the catch. **/ - var type : ComplexType; + var type:ComplexType; /** The expression of the catch. **/ - var expr : Expr; + var expr:Expr; } /** @@ -343,12 +349,12 @@ enum QuoteStatus { /** No quotes **/ - NoQuotes; + Unquoted; /** Double quotes `"` **/ - DoubleQuotes; + Quoted; } /** @@ -358,17 +364,17 @@ typedef ObjectField = { /** The name of the field. **/ - var field : String; + var field:String; /** The field expression. **/ - var expr : Expr; + var expr:Expr; /** How the field name is quoted. **/ - @:optional var quotes : QuoteStatus; + var ?quotes:QuoteStatus; } /** @@ -378,47 +384,47 @@ enum ExprDef { /** A constant. **/ - EConst( c : Constant ); + EConst(c:Constant); /** Array access `e1[e2]`. **/ - EArray( e1 : Expr, e2 : Expr ); + EArray(e1:Expr, e2:Expr); /** Binary operator `e1 op e2`. **/ - EBinop( op : Binop, e1 : Expr, e2 : Expr ); + EBinop(op:Binop, e1:Expr, e2:Expr); /** Field access on `e.field`. **/ - EField( e : Expr, field : String ); + EField(e:Expr, field:String); /** Parentheses `(e)`. **/ - EParenthesis( e : Expr ); + EParenthesis(e:Expr); /** An object declaration. **/ - EObjectDecl( fields : Array ); + EObjectDecl(fields:Array); /** An array declaration `[el]`. **/ - EArrayDecl( values : Array ); + EArrayDecl(values:Array); /** A call `e(params)`. **/ - ECall( e : Expr, params : Array ); + ECall(e:Expr, params:Array); /** A constructor call `new t(params)`. **/ - ENew( t : TypePath, params : Array ); + ENew(t:TypePath, params:Array); /** An unary operator `op` on `e`: @@ -431,55 +437,55 @@ enum ExprDef { * !e (op = OpNot, postFix = false) * ~e (op = OpNegBits, postFix = false) **/ - EUnop( op : Unop, postFix : Bool, e : Expr ); + EUnop(op:Unop, postFix:Bool, e:Expr); /** Variable declarations. **/ - EVars( vars : Array ); + EVars(vars:Array); /** A function declaration. **/ - EFunction( name : Null, f : Function ); + EFunction(name:Null, f:Function); /** A block of expressions `{exprs}`. **/ - EBlock( exprs : Array ); + EBlock(exprs:Array); /** A `for` expression. **/ - EFor( it : Expr, expr : Expr ); + EFor(it:Expr, expr:Expr); /** An `if(econd) eif` or `if(econd) eif else eelse` expression. **/ - EIf( econd : Expr, eif : Expr, eelse : Null ); + EIf(econd:Expr, eif:Expr, eelse:Null); /** Represents a `while` expression. When `normalWhile` is `true` it is `while (...)`. When `normalWhile` is `false` it is `do {...} while (...)`. **/ - EWhile( econd : Expr, e : Expr, normalWhile : Bool ); + EWhile(econd:Expr, e:Expr, normalWhile:Bool); /** Represents a `switch` expression with related cases and an optional. `default` case if edef != null. **/ - ESwitch( e : Expr, cases : Array, edef : Null ); + ESwitch(e:Expr, cases:Array, edef:Null); /** Represents a `try`-expression with related catches. **/ - ETry( e : Expr, catches : Array ); + ETry(e:Expr, catches:Array); /** A `return` or `return e` expression. **/ - EReturn( ?e : Null ); + EReturn(?e:Null); /** A `break` expression. @@ -494,42 +500,50 @@ enum ExprDef { /** An `untyped e` source code. **/ - EUntyped( e : Expr ); + EUntyped(e:Expr); /** A `throw e` expression. **/ - EThrow( e : Expr ); + EThrow(e:Expr); /** A `cast e` or `cast (e, m)` expression. **/ - ECast( e : Expr, t : Null ); + ECast(e:Expr, t:Null); /** Internally used to provide completion. **/ - EDisplay( e : Expr, isCall : Bool ); + EDisplay(e:Expr, displayKind:DisplayKind); /** Internally used to provide completion. **/ - EDisplayNew( t : TypePath ); + EDisplayNew(t:TypePath); /** A `(econd) ? eif : eelse` expression. **/ - ETernary( econd : Expr, eif : Expr, eelse : Expr ); + ETernary(econd:Expr, eif:Expr, eelse:Expr); /** A `(e:t)` expression. **/ - ECheckType( e : Expr, t : ComplexType ); + ECheckType(e:Expr, t:ComplexType); /** A `@m e` expression. **/ - EMeta( s : MetadataEntry, e : Expr ); + EMeta(s:MetadataEntry, e:Expr); +} + +enum DisplayKind { + DKCall; + DKDot; + DKStructure; + DKMarked; + DKPattern(outermost:Bool); } /** @@ -539,37 +553,47 @@ enum ComplexType { /** Represents the type path. **/ - TPath( p : TypePath ); + TPath(p:TypePath); /** Represents a function type. @see https://haxe.org/manual/types-function.html **/ - TFunction( args : Array, ret : ComplexType ); + TFunction(args:Array, ret:ComplexType); /** Represents an anonymous structure type. @see https://haxe.org/manual/types-anonymous-structure.html **/ - TAnonymous( fields : Array ); + TAnonymous(fields:Array); /** Represents parentheses around a type, e.g. the `(Int -> Void)` part in `(Int -> Void) -> String`. **/ - TParent( t : ComplexType ); + TParent(t:ComplexType); /** Represents typedef extensions `> Iterable`. The array `p` holds the type paths to the given types. @see https://haxe.org/manual/type-system-extensions.html **/ - TExtend( p : Array, fields : Array ); + TExtend(p:Array, fields:Array); /** Represents an optional type. **/ - TOptional( t : ComplexType ); + TOptional(t:ComplexType); + + /** + Represents a type with a name. + **/ + TNamed(n:String, t:ComplexType); + + /** + Represents an intersection type `T1 & T2 & ... & TN`. + **/ + TIntersection(tl:Array); } /** @@ -579,23 +603,23 @@ typedef TypePath = { /** Represents the package of the type path. **/ - var pack : Array; + var pack:Array; /** The name of the type path. **/ - var name : String; + var name:String; /** Optional parameters of the type path. **/ - @:optional var params : Array; + var ?params:Array; /** Sub is set on module sub-type access: `pack.Module.Type` has name = Module, sub = Type, if available. **/ - @:optional var sub : Null; + var ?sub:Null; } /** @@ -609,12 +633,12 @@ enum TypeParam { /** **/ - TPType( t : ComplexType ); + TPType(t:ComplexType); /** **/ - TPExpr( e : Expr ); + TPExpr(e:Expr); } /** @@ -624,22 +648,22 @@ typedef TypeParamDecl = { /** The name of the type parameter. **/ - var name : String; + var name:String; /** The optional constraints of the type parameter. **/ - @:optional var constraints : Array; + var ?constraints:Array; /** The optional parameters of the type parameter. **/ - @:optional var params : Array; + var ?params:Array; /** The metadata of the type parameter. **/ - @:optional var meta : Metadata; + var ?meta:Metadata; } /** @@ -649,22 +673,22 @@ typedef Function = { /** A list of function arguments. **/ - var args : Array; + var args:Array; /** The return type-hint of the function, if available. **/ - var ret : Null; + var ret:Null; /** The expression of the function body, if available. **/ - var expr : Null; + var expr:Null; /** An optional list of function parameter type declarations. **/ - @:optional var params : Array; + var ?params:Array; } /** @@ -674,27 +698,27 @@ typedef FunctionArg = { /** The name of the function argument. **/ - var name : String; + var name:String; /** Whether or not the function argument is optional. **/ - @:optional var opt : Bool; + var ?opt:Bool; /** The type-hint of the function argument, if available. **/ - var type : Null; + var type:Null; /** The optional value of the function argument, if available. **/ - @:optional var value : Null; + var ?value:Null; /** The metadata of the function argument. **/ - @:optional var meta : Metadata; + var ?meta:Metadata; } /** @@ -704,17 +728,17 @@ typedef MetadataEntry = { /** The name of the metadata entry. **/ - var name : String; + var name:String; /** The optional parameters of the metadata entry. **/ - @:optional var params : Array; + var ?params:Array; /** The position of the metadata entry. **/ - var pos : Position; + var pos:Position; } /** @@ -729,34 +753,34 @@ typedef Field = { /** The name of the field. **/ - var name : String; + var name:String; /** The documentation of the field, if available. If the field has no documentation, the value is `null`. **/ - @:optional var doc : Null; + var ?doc:Null; /** The access modifiers of the field. By default fields have private access. @see https://haxe.org/manual/class-field-access-modifier.html **/ - @:optional var access : Array; + var ?access:Array; /** The kind of the field. **/ - var kind : FieldType; + var kind:FieldType; /** The position of the field. **/ - var pos : Position; + var pos:Position; /** The optional metadata of the field. **/ - @:optional var meta : Metadata; + var ?meta:Metadata; } /** @@ -764,7 +788,6 @@ typedef Field = { @see https://haxe.org/manual/class-field-access-modifier.html **/ enum Access { - /** Public access modifier, grants access from anywhere. @see https://haxe.org/manual/class-field-visibility.html @@ -813,6 +836,11 @@ enum Access { variables, it means they can be assigned to only once. **/ AFinal; + + /** + Extern access modifier. + **/ + AExtern; } /** @@ -822,17 +850,17 @@ enum FieldType { /** Represents a variable field type. **/ - FVar( t : Null, ?e : Null ); + FVar(t:Null, ?e:Null); /** Represents a function field type. **/ - FFun( f : Function ); + FFun(f:Function); /** Represents a property with getter and setter field type. **/ - FProp( get : String, set : String, ?t : Null, ?e : Null ); + FProp(get:String, set:String, ?t:Null, ?e:Null); } /** @@ -842,48 +870,48 @@ typedef TypeDefinition = { /** The package of the type definition. **/ - var pack : Array; + var pack:Array; /** The name of the type definition. **/ - var name : String; + var name:String; /** The documentation of the type, if available. If the type has no documentation, the value is `null`. **/ - @:optional var doc : Null; + var ?doc:Null; /** The position to the type definition. **/ - var pos : Position; + var pos:Position; /** The optional metadata of the type definition. **/ - @:optional var meta : Metadata; + var ?meta:Metadata; /** The parameter type declarations of the type definition. **/ - @:optional var params : Array; + var ?params:Array; /** Whether or not the type is extern. **/ - @:optional var isExtern : Bool; + var ?isExtern:Bool; /** The kind of the type definition. **/ - var kind : TypeDefKind; + var kind:TypeDefKind; /** The fields of the type definition. **/ - var fields : Array; + var fields:Array; } /** @@ -903,38 +931,37 @@ enum TypeDefKind { /** Represents a class kind. **/ - TDClass( ?superClass : TypePath, ?interfaces : Array, ?isInterface : Bool ); + TDClass(?superClass:TypePath, ?interfaces:Array, ?isInterface:Bool, ?isFinal:Bool); /** Represents an alias/typedef kind. **/ - TDAlias( t : ComplexType ); // ignore TypeDefinition.fields + TDAlias(t:ComplexType); // ignore TypeDefinition.fields /** Represents an abstract kind. **/ - TDAbstract( tthis : Null, ?from : Array, ?to: Array ); + TDAbstract(tthis:Null, ?from:Array, ?to:Array); } /** This error can be used to handle or produce compilation errors in macros. **/ class Error { - /** The error message. **/ - public var message : String; + public var message:String; /** The position of the error. **/ - public var pos : Expr.Position; + public var pos:Expr.Position; /** Instantiates an error with given message and position. **/ - public function new(m,p) { + public function new(m, p) { this.message = m; this.pos = p; } @@ -975,10 +1002,10 @@ typedef ImportExpr = { /** The path to the import expression. **/ - var path: Array< { pos: Position, name: String } >; + var path:Array<{pos:Position, name:String}>; /** The mode of the import expression. **/ - var mode: ImportMode; + var mode:ImportMode; } diff --git a/std/haxe/macro/ExprTools.hx b/std/haxe/macro/ExprTools.hx index f53559b94bc..b90c3045f0a 100644 --- a/std/haxe/macro/ExprTools.hx +++ b/std/haxe/macro/ExprTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ package haxe.macro; import haxe.macro.Expr; + using Lambda; /** @@ -34,14 +35,13 @@ using Lambda; well. **/ class ExprTools { - /** Converts expression `e` to a human-readable String representation. The result is guaranteed to be valid Haxe code, but there may be differences from the original lexical syntax. **/ - static public function toString( e : Expr ) : String + static public function toString(e:Expr):String return new Printer().printExpr(e); /** @@ -68,28 +68,14 @@ class ExprTools { } ``` **/ - static public function iter( e : Expr, f : Expr -> Void ) : Void { - switch(e.expr) { - case EConst(_), - EContinue, - EBreak, - EDisplayNew(_): - case EField(e, _), - EParenthesis(e), - EUntyped(e), - EThrow(e), - EDisplay(e, _), - ECheckType(e, _), - EUnop(_, _, e), - ECast(e, _), - EMeta(_, e): - f(e); - case EArray(e1, e2), - EWhile(e1, e2, _), - EBinop(_, e1, e2), - EFor(e1, e2): - f(e1); - f(e2); + static public function iter(e:Expr, f:Expr->Void):Void { + switch (e.expr) { + case EConst(_), EContinue, EBreak, EDisplayNew(_): + case EField(e, _), EParenthesis(e), EUntyped(e), EThrow(e), EDisplay(e, _), ECheckType(e, _), EUnop(_, _, e), ECast(e, _), EMeta(_, e): + f(e); + case EArray(e1, e2), EWhile(e1, e2, _), EBinop(_, e1, e2), EFor(e1, e2): + f(e1); + f(e2); case EVars(vl): for (v in vl) opt2(v.expr, f); @@ -97,15 +83,12 @@ class ExprTools { f(e); for (c in cl) f(c.expr); - case ETernary(e1, e2, e3) - | EIf(e1, e2, e3): + case ETernary(e1, e2, e3) | EIf(e1, e2, e3): f(e1); f(e2); opt2(e3, f); - case EArrayDecl(el), - ENew(_, el), - EBlock(el): - ExprArrayTools.iter(el, f); + case EArrayDecl(el), ENew(_, el), EBlock(el): + ExprArrayTools.iter(el, f); case EObjectDecl(fl): for (fd in fl) f(fd.expr); @@ -152,61 +135,76 @@ class ExprTools { ExprTools.map(e, capitalizeStrings); } } - ```haxe + ``` **/ - static public function map( e : Expr, f : Expr -> Expr ) : Expr { - return {pos: e.pos, expr: switch(e.expr) { - case EConst(_): e.expr; - case EArray(e1, e2): EArray(f(e1), f(e2)); - case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2)); - case EField(e, field): EField(f(e), field); - case EParenthesis(e): EParenthesis(f(e)); - case EObjectDecl(fields): - var ret = []; - for (field in fields) - ret.push( { field: field.field, expr: f(field.expr), quotes: field.quotes } ); - EObjectDecl(ret); - case EArrayDecl(el): EArrayDecl(ExprArrayTools.map(el, f)); - case ECall(e, params): ECall(f(e), ExprArrayTools.map(params, f)); - case ENew(tp, params): ENew(tp, ExprArrayTools.map(params, f)); - case EUnop(op, postFix, e): EUnop(op, postFix, f(e)); - case EVars(vars): - var ret = []; - for (v in vars) - ret.push( { name: v.name, type:v.type, expr: opt(v.expr, f) } ); - EVars(ret); - case EBlock(el): EBlock(ExprArrayTools.map(el, f)); - case EFor(it, expr): EFor(f(it), f(expr)); - case EIf(econd, eif, eelse): EIf(f(econd), f(eif), opt(eelse, f)); - case EWhile(econd, e, normalWhile): EWhile(f(econd), f(e), normalWhile); - case EReturn(e): EReturn(opt(e,f)); - case EUntyped(e): EUntyped(f(e)); - case EThrow(e): EThrow(f(e)); - case ECast(e, t): ECast(f(e), t); - case EDisplay(e, isCall): EDisplay(f(e), isCall); - case ETernary(econd, eif, eelse): ETernary(f(econd), f(eif), f(eelse)); - case ECheckType(e, t): ECheckType(f(e), t); - case EDisplayNew(_), - EContinue, - EBreak: + static public function map(e:Expr, f:Expr->Expr):Expr { + return { + pos: e.pos, + expr: switch (e.expr) { + case EConst(_): e.expr; + case EArray(e1, e2): EArray(f(e1), f(e2)); + case EBinop(op, e1, e2): EBinop(op, f(e1), f(e2)); + case EField(e, field): EField(f(e), field); + case EParenthesis(e): EParenthesis(f(e)); + case EObjectDecl(fields): + var ret = []; + for (field in fields) + ret.push({field: field.field, expr: f(field.expr), quotes: field.quotes}); + EObjectDecl(ret); + case EArrayDecl(el): EArrayDecl(ExprArrayTools.map(el, f)); + case ECall(e, params): ECall(f(e), ExprArrayTools.map(params, f)); + case ENew(tp, params): ENew(tp, ExprArrayTools.map(params, f)); + case EUnop(op, postFix, e): EUnop(op, postFix, f(e)); + case EVars(vars): + var ret = []; + for (v in vars) { + var v2:Var = {name: v.name, type: v.type, expr: opt(v.expr, f)}; + if (v.isFinal != null) + v2.isFinal = v.isFinal; + ret.push(v2); + } + EVars(ret); + case EBlock(el): EBlock(ExprArrayTools.map(el, f)); + case EFor(it, expr): EFor(f(it), f(expr)); + case EIf(econd, eif, eelse): EIf(f(econd), f(eif), opt(eelse, f)); + case EWhile(econd, e, normalWhile): EWhile(f(econd), f(e), normalWhile); + case EReturn(e): EReturn(opt(e, f)); + case EUntyped(e): EUntyped(f(e)); + case EThrow(e): EThrow(f(e)); + case ECast(e, t): ECast(f(e), t); + case EDisplay(e, dk): EDisplay(f(e), dk); + case ETernary(econd, eif, eelse): ETernary(f(econd), f(eif), f(eelse)); + case ECheckType(e, t): ECheckType(f(e), t); + case EDisplayNew(_), EContinue, EBreak: e.expr; - case ETry(e, catches): - var ret = []; - for (c in catches) - ret.push( { name:c.name, type:c.type, expr:f(c.expr) } ); - ETry(f(e), ret); - case ESwitch(e, cases, edef): - var ret = []; - for (c in cases) - ret.push( { expr: opt (c.expr, f), guard: opt(c.guard, f), values: ExprArrayTools.map(c.values, f) } ); - ESwitch(f(e), ret, edef == null || edef.expr == null ? edef : f(edef)); - case EFunction(name, func): - var ret = []; - for (arg in func.args) - ret.push( { name: arg.name, opt: arg.opt, type: arg.type, value: opt(arg.value, f) } ); - EFunction(name, { args: ret, ret: func.ret, params: func.params, expr: f(func.expr) } ); - case EMeta(m, e): EMeta(m, f(e)); - }}; + case ETry(e, catches): + var ret = []; + for (c in catches) + ret.push({name: c.name, type: c.type, expr: f(c.expr)}); + ETry(f(e), ret); + case ESwitch(e, cases, edef): + var ret = []; + for (c in cases) + ret.push({expr: opt(c.expr, f), guard: opt(c.guard, f), values: ExprArrayTools.map(c.values, f)}); + ESwitch(f(e), ret, edef == null || edef.expr == null ? edef : f(edef)); + case EFunction(name, func): + var ret = []; + for (arg in func.args) + ret.push({ + name: arg.name, + opt: arg.opt, + type: arg.type, + value: opt(arg.value, f) + }); + EFunction(name, { + args: ret, + ret: func.ret, + params: func.params, + expr: f(func.expr) + }); + case EMeta(m, e): EMeta(m, f(e)); + } + }; } /** @@ -288,26 +286,27 @@ class ExprTools { } } - static inline function opt(e:Null, f : Expr -> Expr):Expr + static inline function opt(e:Null, f:Expr->Expr):Expr return e == null ? null : f(e); - static inline function opt2(e:Null, f : Expr -> Void):Void - if (e != null) f(e); + static inline function opt2(e:Null, f:Expr->Void):Void + if (e != null) + f(e); } /** This class provides functions on expression arrays for convenience. For a detailed reference on each method, see the documentation of ExprTools. - */ +**/ class ExprArrayTools { - static public function map( el : Array, f : Expr -> Expr):Array { + static public function map(el:Array, f:Expr->Expr):Array { var ret = []; for (e in el) ret.push(f(e)); return ret; } - static public function iter( el : Array, f : Expr -> Void):Void { + static public function iter(el:Array, f:Expr->Void):Void { for (e in el) f(e); } diff --git a/std/haxe/macro/Format.hx b/std/haxe/macro/Format.hx index 9ec9f8360fa..afcb0690643 100644 --- a/std/haxe/macro/Format.hx +++ b/std/haxe/macro/Format.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.macro; + import haxe.macro.Expr; import haxe.macro.Context; @@ -27,14 +29,16 @@ import haxe.macro.Context; The actual macro implemented for Std.format **/ class Format { - - #if macro - public static function format( estr : Expr ) { - var str = switch( estr.expr ) { - case EConst(c): switch(c) { case CString(s): s; default: null; } + #if (macro || display) + public static function format(estr:Expr) { + var str = switch (estr.expr) { + case EConst(c): switch (c) { + case CString(s): s; + default: null; + } default: null; }; - if( str == null ) + if (str == null) Context.error("Constant string required", estr.pos); var pos = Context.getPosInfos(estr.pos); var min = pos.min; @@ -47,34 +51,35 @@ class Format { return p; } function add(e) { - if( expr == null ) + if (expr == null) expr = e; else - expr = { expr : EBinop(OpAdd,expr,e), pos : Context.makePosition({ min : min, max : pos.min, file : pos.file }) }; + expr = {expr: EBinop(OpAdd, expr, e), pos: Context.makePosition({min: min, max: pos.min, file: pos.file})}; } var i = 0, start = 0; var max = str.length; - while( i < max ) { - if( StringTools.fastCodeAt(str,i++) != '$'.code ) + while (i < max) { + if (StringTools.fastCodeAt(str, i++) != '$'.code) continue; var len = i - start - 1; - if( len > 0 || expr == null ) - add({ expr : EConst(CString(str.substr(start,len))), pos : make(len) }); + if (len > 0 || expr == null) + add({expr: EConst(CString(str.substr(start, len))), pos: make(len)}); pos.min++; start = i; var c = StringTools.fastCodeAt(str, i); - if( c == '{'.code ) { + if (c == '{'.code) { var count = 1; i++; - while( i < max ) { - var c = StringTools.fastCodeAt(str,i++); - if( c == "}".code ) { - if( --count == 0 ) break; - } else if( c == "{".code ) + while (i < max) { + var c = StringTools.fastCodeAt(str, i++); + if (c == "}".code) { + if (--count == 0) + break; + } else if (c == "{".code) count++; } - if( count > 0 ) - Context.error("Closing brace not found",make(1)); + if (count > 0) + Context.error("Closing brace not found", make(1)); pos.min++; start++; var len = i - start - 1; @@ -82,19 +87,19 @@ class Format { add(Context.parseInlineString(expr, make(len))); pos.min++; start++; - } else if( (c >= 'a'.code && c <= 'z'.code) || (c >= 'A'.code && c <= 'Z'.code) || c == '_'.code ) { + } else if ((c >= 'a'.code && c <= 'z'.code) || (c >= 'A'.code && c <= 'Z'.code) || c == '_'.code) { i++; - while( true ) { + while (true) { var c = StringTools.fastCodeAt(str, i); - if( (c >= 'a'.code && c <= 'z'.code) || (c >= 'A'.code && c <= 'Z'.code) || (c >= '0'.code && c <= '9'.code) || c == '_'.code ) + if ((c >= 'a'.code && c <= 'z'.code) || (c >= 'A'.code && c <= 'Z'.code) || (c >= '0'.code && c <= '9'.code) || c == '_'.code) i++; else break; } var len = i - start; var ident = str.substr(start, len); - add( { expr : EConst(CIdent(ident)), pos : make(len) } ); - } else if( c == '$'.code ) { + add({expr: EConst(CIdent(ident)), pos: make(len)}); + } else if (c == '$'.code) { start = i++; continue; } else { @@ -104,12 +109,11 @@ class Format { start = i; } var len = i - start; - if( len > 0 ) - add({ expr : EConst(CString(str.substr(start,len))), pos : make(len) }); - if( expr == null ) - expr = { expr : EConst(CString("")), pos : make(0) }; - return { expr : ECheckType(expr,TPath({ pack : [], name : "String", params : [] })), pos : expr.pos }; + if (len > 0) + add({expr: EConst(CString(str.substr(start, len))), pos: make(len)}); + if (expr == null) + expr = {expr: EConst(CString("")), pos: make(0)}; + return {expr: ECheckType(expr, TPath({pack: [], name: "String", params: []})), pos: expr.pos}; } #end - } diff --git a/std/haxe/macro/JSGenApi.hx b/std/haxe/macro/JSGenApi.hx index 4fbb1f52a4d..9f1fa170930 100644 --- a/std/haxe/macro/JSGenApi.hx +++ b/std/haxe/macro/JSGenApi.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.macro; + import haxe.macro.Type; /** @@ -27,27 +29,38 @@ import haxe.macro.Type; **/ typedef JSGenApi = { /** the file in which the JS code can be generated **/ - var outputFile : String; + var outputFile:String; + /** all the types that were compiled by Haxe **/ - var types : Array; + var types:Array; + /** the main call expression, if a -main class is defined **/ - var main : Null; + var main:Null; + /** generate the JS code for any given typed expression **/ - function generateStatement( e : TypedExpr ) : String; + function generateStatement(e:TypedExpr):String; + /** generate the JS code for a given typed expression-value **/ - function generateValue( e : TypedExpr ) : String; + function generateValue(e:TypedExpr):String; + /** define the JS code that gets generated when a class or enum is accessed in a typed expression **/ - function setTypeAccessor( callb : Type -> String ) : Void; + function setTypeAccessor(callb:Type->String):Void; + /** tells if the given identifier is a JS keyword **/ - function isKeyword( ident : String ) : Bool; + function isKeyword(ident:String):Bool; + /** add a feature **/ - function addFeature( f : String ) : Bool; + function addFeature(f:String):Bool; + /** check if a feature is used **/ - function hasFeature( f : String ) : Bool; + function hasFeature(f:String):Bool; + /** quote and escape the given string constant **/ - function quoteString( s : String ) : String; + function quoteString(s:String):String; + /** create the metadata expression for the given type **/ - function buildMetaData( t : BaseType ) : Null; + function buildMetaData(t:BaseType):Null; + /** select the current classe **/ - function setCurrentClass( c : ClassType ) : Void; + function setCurrentClass(c:ClassType):Void; } diff --git a/std/haxe/macro/MacroStringTools.hx b/std/haxe/macro/MacroStringTools.hx index 157b7445dce..8e6375a437c 100644 --- a/std/haxe/macro/MacroStringTools.hx +++ b/std/haxe/macro/MacroStringTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,11 +28,11 @@ import haxe.macro.Expr; This class provides some utility methods to work with strings in macro context. **/ -#if hl @:hlNative("macro") #end +#if hl +@:hlNative("macro") +#end class MacroStringTools { - #if macro - - + #if (macro || display) /** Formats `String` `s` using the usual interpolation rules. @@ -55,7 +55,7 @@ class MacroStringTools { This operation depends on the position of `e`. **/ - static public function isFormatExpr(e:ExprOf) : Bool { + static public function isFormatExpr(e:ExprOf):Bool { #if (neko || eval) return Context.load("is_fmt_string", 1)(e.pos); #else @@ -64,11 +64,10 @@ class MacroStringTools { } #if !neko - static function isFmtString(p:Position) : Bool { + static function isFmtString(p:Position):Bool { return false; } #end - #end /** @@ -82,8 +81,16 @@ class MacroStringTools { If `sl` is null, the result is unspecified. **/ - static public function toFieldExpr(sl:Array):Expr { - return Lambda.fold(sl, function(s, e) return e == null ? (macro $i{s}) : (macro $e.$s), null); + static public function toFieldExpr(sl:Array, ?pos):Expr { + if (pos == null) + return Lambda.fold(sl, function(s, e) return e == null ? (macro $i{s}) : (macro $e.$s), null); + var e = null; + for (v in sl) + if (e == null) + e = {expr: EConst(CIdent(v)), pos: pos}; + else + e = {expr: EField(e, v), pos: pos}; + return e; } /** @@ -98,12 +105,11 @@ class MacroStringTools { an appended dot separating the result from `name`. **/ static public function toDotPath(pack:Array, name:String):String { - return if (pack.length == 0) name else pack.join(".") + "." +name; + return if (pack.length == 0) name else pack.join(".") + "." + name; } - static public function toComplex( path : String ) : ComplexType { + static public function toComplex(path:String):ComplexType { var pack = path.split("."); - return TPath( { pack : pack, name : pack.pop(), params : [] } ); + return TPath({pack: pack, name: pack.pop(), params: []}); } - } diff --git a/std/haxe/macro/MacroType.hx b/std/haxe/macro/MacroType.hx index a1befdd1d14..c9340e52f5e 100644 --- a/std/haxe/macro/MacroType.hx +++ b/std/haxe/macro/MacroType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.macro; /** This type is meant to be used to generate custom types using a macro. For instance by doing MacroType<[my.Class.myMacro(55)]> **/ -extern class MacroType { -} \ No newline at end of file +extern class MacroType {} diff --git a/std/haxe/macro/PositionTools.hx b/std/haxe/macro/PositionTools.hx index 05f93ba0ada..8c4d6f62b7a 100644 --- a/std/haxe/macro/PositionTools.hx +++ b/std/haxe/macro/PositionTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package haxe.macro; -import haxe.display.Position; +package haxe.macro; + +import haxe.display.Position.Location; import haxe.macro.Expr; class PositionTools { - /** Returns the `Position` where the caller of `here` is. **/ @@ -41,7 +41,7 @@ class PositionTools { /** Like `Context.getPosInfos`, except this method is available on all platforms. **/ - public static function getInfos( p : Position ) : { min : Int, max : Int, file : String } { + public static function getInfos(p:Position):{min:Int, max:Int, file:String} { #if macro return Context.getPosInfos(p); #else @@ -52,7 +52,7 @@ class PositionTools { /** Like `Context.makePosition`, except this method is available on all platforms. **/ - public static function make( inf : { min : Int, max : Int, file : String } ) : Position { + public static function make(inf:{min:Int, max:Int, file:String}):Position { #if macro return Context.makePosition(inf); #else @@ -60,14 +60,14 @@ class PositionTools { #end } - #if macro + #if (macro || display) /** - Converts a `haxe.macro.Position` to a `haxe.display.Range`. + Converts a `haxe.macro.Position` to a `haxe.display.Position.Location`. This operation requires the source file the be known to the Haxe lexer in order to determine line breaks. It is thus only available in macro context. **/ - public static function toRange(p:Position):Range { + public static function toLocation(p:Position):Location { return Context.load("position_to_range", 1)(p); } #end diff --git a/std/haxe/macro/Printer.hx b/std/haxe/macro/Printer.hx index 88181cba4bb..932c99c4821 100644 --- a/std/haxe/macro/Printer.hx +++ b/std/haxe/macro/Printer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,13 +23,14 @@ package haxe.macro; import haxe.macro.Expr; + using Lambda; using StringTools; /** This class provides some utility methods to convert elements from the macro context to a human-readable String representation. -*/ + */ class Printer { var tabs:String; var tabString:String; @@ -39,142 +40,159 @@ class Printer { this.tabString = tabString; } - public function printUnop(op:Unop) return switch(op) { - case OpIncrement: "++"; - case OpDecrement: "--"; - case OpNot: "!"; - case OpNeg: "-"; - case OpNegBits: "~"; - } + public function printUnop(op:Unop) + return switch (op) { + case OpIncrement: "++"; + case OpDecrement: "--"; + case OpNot: "!"; + case OpNeg: "-"; + case OpNegBits: "~"; + } - public function printBinop(op:Binop) return switch(op) { - case OpAdd: "+"; - case OpMult: "*"; - case OpDiv: "/"; - case OpSub: "-"; - case OpAssign: "="; - case OpEq: "=="; - case OpNotEq: "!="; - case OpGt: ">"; - case OpGte: ">="; - case OpLt: "<"; - case OpLte: "<="; - case OpAnd: "&"; - case OpOr: "|"; - case OpXor: "^"; - case OpBoolAnd: "&&"; - case OpBoolOr: "||"; - case OpShl: "<<"; - case OpShr: ">>"; - case OpUShr: ">>>"; - case OpMod: "%"; - case OpInterval: "..."; - case OpArrow: "=>"; - case OpIn: "in"; - case OpAssignOp(op): - printBinop(op) - + "="; - } + public function printBinop(op:Binop) + return switch (op) { + case OpAdd: "+"; + case OpMult: "*"; + case OpDiv: "/"; + case OpSub: "-"; + case OpAssign: "="; + case OpEq: "=="; + case OpNotEq: "!="; + case OpGt: ">"; + case OpGte: ">="; + case OpLt: "<"; + case OpLte: "<="; + case OpAnd: "&"; + case OpOr: "|"; + case OpXor: "^"; + case OpBoolAnd: "&&"; + case OpBoolOr: "||"; + case OpShl: "<<"; + case OpShr: ">>"; + case OpUShr: ">>>"; + case OpMod: "%"; + case OpInterval: "..."; + case OpArrow: "=>"; + case OpIn: "in"; + case OpAssignOp(op): + printBinop(op) + "="; + } - function escapeString(s:String,delim:String) { - return delim + s.replace("\n","\\n").replace("\t","\\t").replace("\r","\\r").replace("'","\\'").replace('"',"\\\"") #if sys .replace("\x00","\\x00") #end + delim; + function escapeString(s:String, delim:String) { + return delim + + s.replace("\n", "\\n") + .replace("\t", "\\t") + .replace("\r", "\\r") + .replace("'", "\\'") + .replace('"', "\\\"") #if sys .replace("\x00", "\\x00") #end + delim; } public function printFormatString(s:String) { - return escapeString(s,"'"); + return escapeString(s, "'"); } public function printString(s:String) { - return escapeString(s,'"'); + return escapeString(s, '"'); } - public function printConstant(c:Constant) return switch(c) { - case CString(s): printString(s); - case CIdent(s), - CInt(s), - CFloat(s): + public function printConstant(c:Constant) + return switch (c) { + case CString(s): printString(s); + case CIdent(s), CInt(s), CFloat(s): s; - case CRegexp(s,opt): '~/$s/$opt'; - } + case CRegexp(s, opt): '~/$s/$opt'; + } - public function printTypeParam(param:TypeParam) return switch(param) { - case TPType(ct): printComplexType(ct); - case TPExpr(e): printExpr(e); - } + public function printTypeParam(param:TypeParam) + return switch (param) { + case TPType(ct): printComplexType(ct); + case TPExpr(e): printExpr(e); + } - public function printTypePath(tp:TypePath) return - (tp.pack.length > 0 ? tp.pack.join(".") + "." : "") - + tp.name - + (tp.sub != null ? '.${tp.sub}' : "") - + (tp.params == null ? "" : tp.params.length > 0 ? "<" + tp.params.map(printTypeParam).join(", ") + ">" : ""); + public function printTypePath(tp:TypePath) + return (tp.pack.length > 0 ? tp.pack.join(".") + "." : "") + + tp.name + + (tp.sub != null ? '.${tp.sub}' : "") + + (tp.params == null ? "" : tp.params.length > 0 ? "<" + tp.params.map(printTypeParam).join(", ") + ">" : ""); // TODO: check if this can cause loops - public function printComplexType(ct:ComplexType) return switch(ct) { - case TPath(tp): printTypePath(tp); - case TFunction(args, ret): - function printArg(ct) return switch ct { - case TFunction(_): "(" + printComplexType(ct) + ")"; - default: printComplexType(ct); - }; - (args.length>0 ? args.map(printArg).join(" -> ") :"Void") + " -> " + printComplexType(ret); - case TAnonymous(fields): "{ " + [for (f in fields) printField(f) + "; "].join("") + "}"; - case TParent(ct): "(" + printComplexType(ct) + ")"; - case TOptional(ct): "?" + printComplexType(ct); - case TExtend(tpl, fields): '{> ${tpl.map(printTypePath).join(" >, ")}, ${fields.map(printField).join(", ")} }'; - } - - public function printMetadata(meta:MetadataEntry) return - '@${meta.name}' - + ((meta.params != null && meta.params.length > 0) ? '(${printExprs(meta.params,", ")})' : ""); - - public function printAccess(access:Access) return switch(access) { - case AStatic: "static"; - case APublic: "public"; - case APrivate: "private"; - case AOverride: "override"; - case AInline: "inline"; - case ADynamic: "dynamic"; - case AMacro: "macro"; - case AFinal: "final"; - } + public function printComplexType(ct:ComplexType) + return switch (ct) { + case TPath(tp): printTypePath(tp); + case TFunction(args, ret): + if (args.length == 1 && !(args[0].match(TNamed(_, _)) || args[0].match(TFunction(_, _)))) { + // This special case handles an ambigity between the old function syntax and the new + // (T) -> T parses as `TFunction([TParent(TPath)], ...`, rather than `TFunction([TPath], ...` + // We forgo patenthesis in this case so that (T) -> T doesn't get round-tripped to ((T)) -> T + printComplexType(args[0]) + " -> " + printComplexType(ret); + } else { + '(${args.map(printComplexType).join(", ")})' + " -> " + printComplexType(ret); + } + case TAnonymous(fields): "{ " + [for (f in fields) printField(f) + "; "].join("") + "}"; + case TParent(ct): "(" + printComplexType(ct) + ")"; + case TOptional(ct): "?" + printComplexType(ct); + case TNamed(n, ct): n + ":" + printComplexType(ct); + case TExtend(tpl, fields): '{> ${tpl.map(printTypePath).join(" >, ")}, ${fields.map(printField).join(", ")} }'; + case TIntersection(tl): tl.map(printComplexType).join(" & "); + } - public function printField(field:Field) return - (field.doc != null && field.doc != "" ? "/**\n" + tabs + tabString + StringTools.replace(field.doc, "\n", "\n" + tabs + tabString) + "\n" + tabs + "**/\n" + tabs : "") - + (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join('\n$tabs') + '\n$tabs' : "") - + (field.access != null && field.access.length > 0 ? field.access.map(printAccess).join(" ") + " " : "") - + switch(field.kind) { - case FVar(t, eo): 'var ${field.name}' + opt(t, printComplexType, " : ") + opt(eo, printExpr, " = "); - case FProp(get, set, t, eo): 'var ${field.name}($get, $set)' + opt(t, printComplexType, " : ") + opt(eo, printExpr, " = "); - case FFun(func): 'function ${field.name}' + printFunction(func); + public function printMetadata(meta:MetadataEntry) + return '@${meta.name}' + ((meta.params != null && meta.params.length > 0) ? '(${printExprs(meta.params, ", ")})' : ""); + + public function printAccess(access:Access) + return switch (access) { + case AStatic: "static"; + case APublic: "public"; + case APrivate: "private"; + case AOverride: "override"; + case AInline: "inline"; + case ADynamic: "dynamic"; + case AMacro: "macro"; + case AFinal: "final"; + case AExtern: "extern"; } - public function printTypeParamDecl(tpd:TypeParamDecl) return - tpd.name - + (tpd.params != null && tpd.params.length > 0 ? "<" + tpd.params.map(printTypeParamDecl).join(", ") + ">" : "") - + (tpd.constraints != null && tpd.constraints.length > 0 ? ":(" + tpd.constraints.map(printComplexType).join(", ") + ")" : ""); + public function printField(field:Field) + return (field.doc != null + && field.doc != "" ? "/**\n" + + tabs + + tabString + + StringTools.replace(field.doc, "\n", "\n" + tabs + tabString) + + "\n" + + tabs + + "**/\n" + + tabs : "") + + (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join('\n$tabs') + '\n$tabs' : "") + + (field.access != null && field.access.length > 0 ? field.access.map(printAccess).join(" ") + " " : "") + + switch (field.kind) { + case FVar(t, eo): 'var ${field.name}' + opt(t, printComplexType, " : ") + opt(eo, printExpr, " = "); + case FProp(get, set, t, eo): 'var ${field.name}($get, $set)' + opt(t, printComplexType, " : ") + opt(eo, printExpr, " = "); + case FFun(func): 'function ${field.name}' + printFunction(func); + } - public function printFunctionArg(arg:FunctionArg) return - (arg.opt ? "?" : "") - + arg.name - + opt(arg.type, printComplexType, ":") - + opt(arg.value, printExpr, " = "); + public function printTypeParamDecl(tpd:TypeParamDecl) + return tpd.name + + (tpd.params != null && tpd.params.length > 0 ? "<" + tpd.params.map(printTypeParamDecl).join(", ") + ">" : "") + + (tpd.constraints != null && tpd.constraints.length > 0 ? ":(" + tpd.constraints.map(printComplexType).join(", ") + ")" : ""); - public function printFunction(func:Function) return - (func.params == null ? "" : func.params.length > 0 ? "<" + func.params.map(printTypeParamDecl).join(", ") + ">" : "") - + "(" + func.args.map(printFunctionArg).join(", ") + ")" - + opt(func.ret, printComplexType, ":") - + opt(func.expr, printExpr, " "); + public function printFunctionArg(arg:FunctionArg) + return (arg.opt ? "?" : "") + arg.name + opt(arg.type, printComplexType, ":") + opt(arg.value, printExpr, " = "); - public function printVar(v:Var) return - v.name - + opt(v.type, printComplexType, ":") - + opt(v.expr, printExpr, " = "); + public function printFunction(func:Function) + return (func.params == null ? "" : func.params.length > 0 ? "<" + func.params.map(printTypeParamDecl).join(", ") + ">" : "") + + "(" + + func.args.map(printFunctionArg).join(", ") + + ")" + + opt(func.ret, printComplexType, ":") + + opt(func.expr, printExpr, " "); + public function printVar(v:Var) + return v.name + opt(v.type, printComplexType, ":") + opt(v.expr, printExpr, " = "); public function printObjectFieldKey(of:ObjectField) { return switch (of.quotes) { - case NoQuotes: of.field; - case DoubleQuotes: '"${of.field}"'; // TODO: Have to escape that? + case null | Unquoted: of.field; + case Quoted: '"${of.field}"'; // TODO: Have to escape that? } } @@ -182,151 +200,324 @@ class Printer { return '${printObjectFieldKey(of)} : ${printExpr(of.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 EArray(e1, e2): '${printExpr(e1)}[${printExpr(e2)}]'; - case EBinop(op, e1, e2): '${printExpr(e1)} ${printBinop(op)} ${printExpr(e2)}'; - case EField(e1, n): '${printExpr(e1)}.$n'; - case EParenthesis(e1): '(${printExpr(e1)})'; - case EObjectDecl(fl): - "{ " + fl.map(function(fld) return printObjectField(fld)).join(", ") + " }"; - case EArrayDecl(el): '[${printExprs(el, ", ")}]'; - case ECall(e1, el): '${printExpr(e1)}(${printExprs(el,", ")})'; - case ENew(tp, el): 'new ${printTypePath(tp)}(${printExprs(el,", ")})'; - case EUnop(op, true, e1): printExpr(e1) + printUnop(op); - case EUnop(op, false, e1): printUnop(op) + printExpr(e1); - case EFunction(no, func) if (no != null): 'function $no' + printFunction(func); - case EFunction(_, func): "function" +printFunction(func); - case EVars(vl): "var " +vl.map(printVar).join(", "); - case EBlock([]): '{ }'; - case EBlock(el): - var old = tabs; - tabs += tabString; - var s = '{\n$tabs' + printExprs(el, ';\n$tabs'); - tabs = old; - s + ';\n$tabs}'; - case EFor(e1, e2): 'for (${printExpr(e1)}) ${printExpr(e2)}'; - case EIf(econd, eif, null): 'if (${printExpr(econd)}) ${printExpr(eif)}'; - case EIf(econd, eif, eelse): 'if (${printExpr(econd)}) ${printExpr(eif)} else ${printExpr(eelse)}'; - case EWhile(econd, e1, true): 'while (${printExpr(econd)}) ${printExpr(e1)}'; - case EWhile(econd, e1, false): 'do ${printExpr(e1)} while (${printExpr(econd)})'; - case ESwitch(e1, cl, edef): - var old = tabs; - tabs += tabString; - var s = 'switch ${printExpr(e1)} {\n$tabs' + - cl.map(function(c) - return 'case ${printExprs(c.values, ", ")}' - + (c.guard != null ? ' if (${printExpr(c.guard)}):' : ":") + 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 EArray(e1, e2): '${printExpr(e1)}[${printExpr(e2)}]'; + case EBinop(op, e1, e2): '${printExpr(e1)} ${printBinop(op)} ${printExpr(e2)}'; + case EField(e1, n): '${printExpr(e1)}.$n'; + case EParenthesis(e1): '(${printExpr(e1)})'; + case EObjectDecl(fl): + "{ " + fl.map(function(fld) return printObjectField(fld)).join(", ") + " }"; + case EArrayDecl(el): '[${printExprs(el, ", ")}]'; + case ECall(e1, el): '${printExpr(e1)}(${printExprs(el, ", ")})'; + case ENew(tp, el): 'new ${printTypePath(tp)}(${printExprs(el, ", ")})'; + case EUnop(op, true, e1): printExpr(e1) + printUnop(op); + case EUnop(op, false, e1): printUnop(op) + printExpr(e1); + case EFunction(no, func) if (no != null): 'function $no' + printFunction(func); + case EFunction(_, func): "function" + printFunction(func); + case EVars(vl): "var " + vl.map(printVar).join(", "); + case EBlock([]): '{ }'; + case EBlock(el): + var old = tabs; + tabs += tabString; + var s = '{\n$tabs' + printExprs(el, ';\n$tabs'); + tabs = old; + s + ';\n$tabs}'; + case EFor(e1, e2): 'for (${printExpr(e1)}) ${printExpr(e2)}'; + case EIf(econd, eif, null): 'if (${printExpr(econd)}) ${printExpr(eif)}'; + case EIf(econd, eif, eelse): 'if (${printExpr(econd)}) ${printExpr(eif)} else ${printExpr(eelse)}'; + case EWhile(econd, e1, true): 'while (${printExpr(econd)}) ${printExpr(e1)}'; + case EWhile(econd, e1, false): 'do ${printExpr(e1)} while (${printExpr(econd)})'; + case ESwitch(e1, cl, edef): + var old = tabs; + tabs += tabString; + var s = 'switch ${printExpr(e1)} {\n$tabs' + + cl.map(function(c) return 'case ${printExprs(c.values, ", ")}' + (c.guard != null ? ' if (${printExpr(c.guard)}):' : ":") + (c.expr != null ? (opt(c.expr, printExpr)) + ";" : "")) - .join('\n$tabs'); - if (edef != null) - s += '\n${tabs}default:' + (edef.expr == null ? "" : printExpr(edef) + ";"); - tabs = old; - s + '\n$tabs}'; - case ETry(e1, cl): - 'try ${printExpr(e1)}' - + cl.map(function(c) return ' catch(${c.name}:${printComplexType(c.type)}) ${printExpr(c.expr)}').join(""); - case EReturn(eo): "return" + opt(eo, printExpr, " "); - case EBreak: "break"; - case EContinue: "continue"; - case EUntyped(e1): "untyped " +printExpr(e1); - case EThrow(e1): "throw " +printExpr(e1); - case ECast(e1, cto) if (cto != null): 'cast(${printExpr(e1)}, ${printComplexType(cto)})'; - case ECast(e1, _): "cast " +printExpr(e1); - case EDisplay(e1, _): '#DISPLAY(${printExpr(e1)})'; - case EDisplayNew(tp): '#DISPLAY(${printTypePath(tp)})'; - case ETernary(econd, eif, eelse): '${printExpr(econd)} ? ${printExpr(eif)} : ${printExpr(eelse)}'; - case ECheckType(e1, ct): '(${printExpr(e1)} : ${printComplexType(ct)})'; - case EMeta(meta, e1): printMetadata(meta) + " " +printExpr(e1); - } + .join('\n$tabs'); + if (edef != null) + s += '\n${tabs}default:' + (edef.expr == null ? "" : printExpr(edef) + ";"); + tabs = old; + s + '\n$tabs}'; + case ETry(e1, cl): + 'try ${printExpr(e1)}' + cl.map(function(c) return ' catch(${c.name}:${printComplexType(c.type)}) ${printExpr(c.expr)}').join(""); + case EReturn(eo): "return" + opt(eo, printExpr, " "); + case EBreak: "break"; + case EContinue: "continue"; + case EUntyped(e1): "untyped " + printExpr(e1); + case EThrow(e1): "throw " + printExpr(e1); + case ECast(e1, cto) if (cto != null): 'cast(${printExpr(e1)}, ${printComplexType(cto)})'; + case ECast(e1, _): "cast " + printExpr(e1); + case EDisplay(e1, _): '#DISPLAY(${printExpr(e1)})'; + case EDisplayNew(tp): '#DISPLAY(${printTypePath(tp)})'; + case ETernary(econd, eif, eelse): '${printExpr(econd)} ? ${printExpr(eif)} : ${printExpr(eelse)}'; + case ECheckType(e1, ct): '(${printExpr(e1)} : ${printComplexType(ct)})'; + case EMeta(meta, e1): printMetadata(meta) + " " + printExpr(e1); + } public function printExprs(el:Array, sep:String) { return el.map(printExpr).join(sep); } - function printExtension(tpl:Array, fields: Array) { - return '{\n$tabs>' + tpl.map(printTypePath).join(',\n$tabs>') + "," - + (fields.length > 0 ? ('\n$tabs' + fields.map(printField).join(';\n$tabs') + ";\n}") : ("\n}")); + function printExtension(tpl:Array, fields:Array) { + return '{\n$tabs>' + + tpl.map(printTypePath).join(',\n$tabs>') + + "," + + (fields.length > 0 ? ('\n$tabs' + fields.map(printField).join(';\n$tabs') + ";\n}") : ("\n}")); } function printStructure(fields:Array) { - return fields.length == 0 ? "{ }" : - '{\n$tabs' + fields.map(printField).join(';\n$tabs') + ";\n}"; + return fields.length == 0 ? "{ }" : '{\n$tabs' + fields.map(printField).join(';\n$tabs') + ";\n}"; } public function printTypeDefinition(t:TypeDefinition, printPackage = true):String { var old = tabs; tabs = tabString; - var str = t == null ? "#NULL" : - (printPackage && t.pack.length > 0 && t.pack[0] != "" ? "package " + t.pack.join(".") + ";\n" : "") + - (t.doc != null && t.doc != "" ? "/**\n" + tabString + StringTools.replace(t.doc, "\n", "\n" + tabString) + "\n**/\n" : "") + - (t.meta != null && t.meta.length > 0 ? t.meta.map(printMetadata).join(" ") + " " : "") + (t.isExtern ? "extern " : "") + switch (t.kind) { + var str = t == null ? "#NULL" : (printPackage && t.pack.length > 0 && t.pack[0] != "" ? "package " + t.pack.join(".") + ";\n" : "") + + (t.doc != null && t.doc != "" ? "/**\n" + tabString + StringTools.replace(t.doc, "\n", "\n" + tabString) + "\n**/\n" : "") + + (t.meta != null && t.meta.length > 0 ? t.meta.map(printMetadata).join(" ") + " " : "") + + (t.isExtern ? "extern " : "") + + switch (t.kind) { case TDEnum: - "enum " + t.name + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " {\n" - + [for (field in t.fields) - tabs + (field.doc != null && field.doc != "" ? "/**\n" + tabs + tabString + StringTools.replace(field.doc, "\n", "\n" + tabs + tabString) + "\n" + tabs + "**/\n" + tabs : "") - + (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join(" ") + " " : "") - + (switch(field.kind) { - case FVar(t, _): field.name + opt(t, printComplexType, ":"); - case FProp(_, _, _, _): throw "FProp is invalid for TDEnum."; - case FFun(func): field.name + printFunction(func); - }) + ";" - ].join("\n") + "enum " + + t.name + + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + + " {\n" + + [ + for (field in t.fields) + tabs + + (field.doc != null + && field.doc != "" ? "/**\n" + + tabs + + tabString + + StringTools.replace(field.doc, "\n", "\n" + tabs + tabString) + + "\n" + + tabs + + "**/\n" + + tabs : "") + + (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join(" ") + " " : "") + + (switch (field.kind) { + case FVar(t, _): field.name + opt(t, printComplexType, ":"); + case FProp(_, _, _, _): throw "FProp is invalid for TDEnum."; + case FFun(func): field.name + printFunction(func); + }) + + ";"].join("\n") + "\n}"; case TDStructure: - "typedef " + t.name + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " = {\n" - + [for (f in t.fields) { - tabs + printField(f) + ";"; - }].join("\n") - + "\n}"; - case TDClass(superClass, interfaces, isInterface): - (isInterface ? "interface " : "class ") + t.name + (t.params != null && t.params.length > 0 ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") - + (superClass != null ? " extends " + printTypePath(superClass) : "") - + (interfaces != null ? (isInterface ? [for (tp in interfaces) " extends " + printTypePath(tp)] : [for (tp in interfaces) " implements " + printTypePath(tp)]).join("") : "") - + " {\n" - + [for (f in t.fields) { - tabs + printFieldWithDelimiter(f); - }].join("\n") + "typedef " + + t.name + + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + + " = {\n" + + [ + for (f in t.fields) { + tabs + printField(f) + ";"; + } + ].join("\n") + "\n}"; + case TDClass(superClass, interfaces, isInterface, isFinal): + (isFinal ? "final " : "") + + (isInterface ? "interface " : "class ") + + t.name + + (t.params != null && t.params.length > 0 ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + + (superClass != null ? " extends " + printTypePath(superClass) : "") + + (interfaces != null ? (isInterface ? [for (tp in interfaces) " extends " + printTypePath(tp)] : [ + for (tp in interfaces) + " implements " + printTypePath(tp) + ]).join("") : "") + + " {\n" + + [ + for (f in t.fields) { + tabs + printFieldWithDelimiter(f); + } + ].join("\n") + + "\n}"; case TDAlias(ct): - "typedef " + t.name + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " = " - + (switch(ct) { + "typedef " + + t.name + + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + + " = " + + (switch (ct) { case TExtend(tpl, fields): printExtension(tpl, fields); case TAnonymous(fields): printStructure(fields); case _: printComplexType(ct); }) + ";"; case TDAbstract(tthis, from, to): - "abstract " + t.name + "abstract " + + t.name + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + (tthis == null ? "" : "(" + printComplexType(tthis) + ")") + (from == null ? "" : [for (f in from) " from " + printComplexType(f)].join("")) + (to == null ? "" : [for (t in to) " to " + printComplexType(t)].join("")) + " {\n" - + [for (f in t.fields) { - tabs + printFieldWithDelimiter(f); - }].join("\n") + + [ + for (f in t.fields) { + tabs + printFieldWithDelimiter(f); + } + ].join("\n") + "\n}"; - } + } tabs = old; - tabs = old; return str; } - function printFieldWithDelimiter(f:Field):String - { - return printField(f) + switch(f.kind) { + function printFieldWithDelimiter(f:Field):String { + return printField(f) + switch (f.kind) { case FVar(_, _), FProp(_, _, _, _): ";"; - case FFun({expr:null}): ";"; - case FFun({expr:{expr:EBlock(_)}}): ""; + case FFun({expr: null}): ";"; + case FFun({expr: {expr: EBlock(_)}}): ""; case FFun(_): ";"; case _: ""; }; } - function opt(v:T, f:T->String, prefix = "") return v == null ? "" : (prefix + f(v)); + function opt(v:T, f:T->String, prefix = "") + return v == null ? "" : (prefix + f(v)); + + public function printExprWithPositions(e:Expr) { + var buffer = new StringBuf(); + function format4(i:Int) { + return StringTools.lpad(Std.string(i), " ", 4); + } + function loop(tabs:String, e:Expr) { + function add(s:String, ?p = null) { + if (p == null) { + p = e.pos; + } + var p = #if macro haxe.macro.Context.getPosInfos(p) #else e.pos #end; + buffer.add('${format4(p.min)}-${format4(p.max)} $tabs$s\n'); + } + function loopI(e:Expr) + loop(tabs + tabString, e); + switch (e.expr) { + case EConst(c): + add(printConstant(c)); + case EArray(e1, e2): + add("EArray"); + loopI(e1); + loopI(e2); + case EBinop(op, e1, e2): + add("EBinop " + printBinop(op)); + loopI(e1); + loopI(e2); + case EField(e, field): + add("EField " + field); + loopI(e); + case EParenthesis(e): + add("EParenthesis"); + loopI(e); + case EObjectDecl(fields): + add("EObjectDecl"); + for (field in fields) { + add(field.field); // TODO: we don't have the field pos? + loopI(field.expr); + } + case EArrayDecl(values): + add("EArrayDecl"); + values.iter(loopI); + case ECall(e, params): + add("ECall"); + loopI(e); + params.iter(loopI); + case ENew(tp, params): + add("ENew " + printTypePath(tp)); + params.iter(loopI); + case EUnop(op, postFix, e): + add("EUnop " + printUnop(op)); + loopI(e); + case EVars(vars): + add("EVars"); + for (v in vars) { + if (v.expr != null) { + add(v.name); + loopI(v.expr); + } + } + case EFunction(name, f): + add("EFunction"); + if (f.expr != null) { + loopI(f.expr); + } + case EBlock(exprs): + add("EBlock"); + exprs.iter(loopI); + case EFor(it, expr): + add("EFor"); + loopI(it); + loopI(expr); + case EIf(econd, eif, eelse): + add("EIf"); + loopI(econd); + loopI(eif); + if (eelse != null) { + loopI(eelse); + } + case EWhile(econd, e, normalWhile): + add("EWhile"); + loopI(econd); + loopI(e); + case ESwitch(e, cases, edef): + add("ESwitch"); + loopI(e); + for (c in cases) { + for (pat in c.values) { + loop(tabs + tabString + tabString, pat); + } + if (c.expr != null) { + loop(tabs + tabString + tabString + tabString, c.expr); + } + } + if (edef != null) { + loop(tabs + tabString + tabString + tabString, edef); + } + case ETry(e, catches): + add("ETry"); + loopI(e); + for (c in catches) { + loop(tabs + tabString + tabString, c.expr); + } + case EReturn(e): + add("EReturn"); + if (e != null) { + loopI(e); + } + case EBreak: + add("EBreak"); + case EContinue: + add("EContinue"); + case EUntyped(e): + add("EUntyped"); + loopI(e); + case EThrow(e): + add("EThrow"); + loopI(e); + case ECast(e, t): + add("ECast"); + loopI(e); + case EDisplay(e, displayKind): + add("EDisplay"); + loopI(e); + case EDisplayNew(t): + add("EDisplayNew"); + case ETernary(econd, eif, eelse): + add("ETernary"); + loopI(econd); + loopI(eif); + loopI(eelse); + case ECheckType(e, t): + add("ECheckType"); + loopI(e); + case EMeta(s, e): + add("EMeta " + printMetadata(s)); + loopI(e); + } + } + loop("", e); + return buffer.toString(); + } } diff --git a/std/haxe/macro/Tools.hx b/std/haxe/macro/Tools.hx index 56d1e4f5dcc..89f8beb5a09 100644 --- a/std/haxe/macro/Tools.hx +++ b/std/haxe/macro/Tools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.macro; /** @@ -31,8 +32,8 @@ package haxe.macro; - `haxe.macro.MacroStringTools` - `haxe.macro.TypedExprTools` - `haxe.macro.PositionTools` - - @see + + @see **/ @:dox(hide) typedef TExprTools = ExprTools; diff --git a/std/haxe/macro/Type.hx b/std/haxe/macro/Type.hx index 5bd7b6c0ad7..85e4f9cc8cf 100644 --- a/std/haxe/macro/Type.hx +++ b/std/haxe/macro/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,103 +19,104 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.macro; /* - Warning: Some of these types correspond to compiler-internal data structures - and might change in minor Haxe releases in order to adapt to internal changes. -*/ - + Warning: Some of these types correspond to compiler-internal data structures + and might change in minor Haxe releases in order to adapt to internal changes. + */ /** Represents a reference to internal compiler structure. It exists to avoid expensive encoding if it is not required and to ensure that physical equality remains intact. A structure is only encoded when user requests it through `ref.get()`. -*/ + */ typedef Ref = { - public function get() : T; - public function toString() : String; + public function get():T; + public function toString():String; } /** Represents a type. -*/ + */ enum Type { /** Represents a monomorph. @see https://haxe.org/manual/types-monomorph.html **/ - TMono( t : Ref> ); + TMono(t:Ref>); /** Represents an enum instance. @see https://haxe.org/manual/types-enum-instance.html **/ - TEnum( t : Ref, params : Array ); + TEnum(t:Ref, params:Array); /** Represents a class instance. @see https://haxe.org/manual/types-class-instance.html **/ - TInst( t : Ref, params : Array ); + TInst(t:Ref, params:Array); /** Represents a typedef. @see https://haxe.org/manual/type-system-typedef.html **/ - TType( t : Ref, params : Array ); + TType(t:Ref, params:Array); /** Represents a function type. @see https://haxe.org/manual/types-function.html **/ - TFun( args : Array<{ name : String, opt : Bool, t : Type }>, ret : Type ); + TFun(args:Array<{name:String, opt:Bool, t:Type}>, ret:Type); /** Represents an anonymous structure type. @see https://haxe.org/manual/types-anonymous-structure.html **/ - TAnonymous( a : Ref ); + TAnonymous(a:Ref); /** Represents Dynamic. @see https://haxe.org/manual/types-dynamic.html **/ - TDynamic( t : Null ); + TDynamic(t:Null); /** Used internally by the compiler to delay some typing. **/ - TLazy( f : Void -> Type ); + TLazy(f:Void->Type); /** Represents an abstract type. @see https://haxe.org/manual/types-abstract.html **/ - TAbstract( t : Ref, params : Array ); + TAbstract(t:Ref, params:Array); } /** Represents information for anonymous structure types. -*/ + */ typedef AnonType = { /** The class fields of the structure. **/ - var fields : Array; + var fields:Array; + /** The status/kind of the structure. **/ - var status : AnonStatus; + var status:AnonStatus; } /** @@ -147,140 +148,149 @@ enum AnonStatus { @see https://haxe.org/manual/type-system-extensions.html **/ - AExtend( tl:Ref> ); + AExtend(tl:Ref>); /** A structure that represents the static fields of a class. **/ - AClassStatics( t : Ref ); + AClassStatics(t:Ref); /** A structure that represents the constructors of an enum. **/ - AEnumStatics( t : Ref ); + AEnumStatics(t:Ref); /** A structure that represents the static fields of an abstract. **/ - AAbstractStatics( t : Ref ); + AAbstractStatics(t:Ref); } /** Represents the declaration of type parameters. -*/ + */ typedef TypeParameter = { /** The name of the type parameter. **/ - var name: String; + var name:String; /** The type of the type parameter. It is guaranteed to be a `TInst` with a `KTypeParameter` kind. **/ - var t: Type; + var t:Type; } /** Represents a class field. -*/ + */ typedef ClassField = { /** The name of the class field. **/ - var name : String; + var name:String; /** The type of the class field. **/ - var type : Type; + var type:Type; /** Whether or not the class field is public. **/ - var isPublic : Bool; + var isPublic:Bool; + + /** + Whether or not the class field is extern. + **/ + var isExtern:Bool; + + /** + Whether or not the class field is final. + **/ + var isFinal:Bool; /** The type parameters of the class field. **/ - var params : Array; + var params:Array; /** The metadata of the class field. **/ - var meta : MetaAccess; + var meta:MetaAccess; /** The class field kind. **/ - var kind : FieldKind; + var kind:FieldKind; /** Returns the typed expression of the class field. **/ - function expr() : Null; + function expr():Null; /** The position of the class field. **/ - var pos : Expr.Position; + var pos:Expr.Position; /** The associated documentation of the class field. **/ - var doc : Null; + var doc:Null; /** The overload fields of the class field. **/ - var overloads : Ref>; + var overloads:Ref>; } /** Represents an enum constructor. -*/ + */ typedef EnumField = { /** The name of the enum constructor. **/ - var name : String; + var name:String; /** The type of the enum constructor. **/ - var type : Type; + var type:Type; /** The position of the enum constructor. **/ - var pos : Expr.Position; + var pos:Expr.Position; /** The metadata of the enum constructor. **/ - var meta : MetaAccess; + var meta:MetaAccess; /** The index of the enum constructor, i.e. in which position it appears in the syntax. **/ - var index : Int; + var index:Int; /** The associated documentation of the enum constructor. **/ - var doc : Null; + var doc:Null; /** The type parameters of the enum constructor. **/ - var params : Array; + var params:Array; } - /** Represents the kind of a class. -*/ + */ enum ClassKind { /** A normal class. @@ -342,180 +352,189 @@ typedef BaseType = { /** The package of the type. **/ - var pack : Array; + var pack:Array; /** The name of the type. **/ - var name : String; + var name:String; /** The module name of the type, which might be different. **/ - var module : String; + var module:String; /** The position of the type. **/ - var pos : Expr.Position; + var pos:Expr.Position; /** Whether or not the type is private. **/ - var isPrivate : Bool; + var isPrivate:Bool; /** Whether or not the type is extern. **/ - var isExtern : Bool; + var isExtern:Bool; /** The type parameters of the type. **/ - var params : Array; + var params:Array; /** The metadata of the type. **/ - var meta : MetaAccess; + var meta:MetaAccess; /** The associated documentation of the class field. **/ - var doc : Null; + var doc:Null; /** Allows excluding the type from compilation. **/ - function exclude() : Void; + function exclude():Void; } /** Represents a class type. -*/ -typedef ClassType = {> BaseType, + */ +typedef ClassType = BaseType & { /** The kind of the class. **/ - var kind : ClassKind; + var kind:ClassKind; /** If true the type is an interface, otherwise it is a class. **/ - var isInterface : Bool; + var isInterface:Bool; + + /** + If true the class is final and cannot be extended. + **/ + var isFinal:Bool; /** The parent class and its type parameters, if available. **/ - var superClass : Null<{ t : Ref, params : Array }>; + var superClass:Null<{t:Ref, params:Array}>; /** The implemented interfaces and their type parameters. **/ - var interfaces : Array<{ t : Ref, params : Array }>; + var interfaces:Array<{t:Ref, params:Array}>; /** The member fields of the class. **/ - var fields : Ref>; + var fields:Ref>; /** The static fields of the class. **/ - var statics : Ref>; + var statics:Ref>; - //var dynamic : Null; - //var arrayAccess : Null; + // var dynamic : Null; + // var arrayAccess : Null; /** The constructor of the class, if available. **/ - var constructor : Null>; + var constructor:Null>; /** The `__init__` expression of the class, if available. **/ - var init : Null; + var init:Null; /** The list of fields that have override status. **/ - var overrides : Array>; + var overrides:Array>; } /** Represents an enum type. -*/ -typedef EnumType = {> BaseType, + */ +typedef EnumType = BaseType & { /** The available enum constructors. **/ - var constructs : Map; + var constructs:Map; /** An ordered list of enum constructor names. **/ - var names : Array; + var names:Array; } /** Represents a typedef. -*/ -typedef DefType = {> BaseType, + */ +typedef DefType = BaseType & { /** The target type of the typedef. **/ - var type : Type; + var type:Type; } /** Represents an abstract type. -*/ -typedef AbstractType = {>BaseType, + */ +typedef AbstractType = BaseType & { /** The underlying type of the abstract. **/ - var type : Type; + var type:Type; /** The implementation class of the abstract, if available. **/ - var impl : Null>; + var impl:Null>; /** The defined binary operators of the abstract. **/ - var binops : Array<{op:Expr.Binop, field:ClassField}>; + var binops:Array<{op:Expr.Binop, field:ClassField}>; /** The defined unary operators of the abstract. **/ - var unops : Array<{op:Expr.Unop, postFix:Bool, field:ClassField}>; + var unops:Array<{op:Expr.Unop, postFix:Bool, field:ClassField}>; /** The available implicit from-casts of the abstract. @see https://haxe.org/manual/types-abstract-implicit-casts.html **/ - var from : Array<{t:Type, field:Null}>; + var from:Array<{t:Type, field:Null}>; /** The available implicit to-casts of the abstract. @see https://haxe.org/manual/types-abstract-implicit-casts.html **/ - var to : Array<{t:Type, field:Null}>; + var to:Array<{t:Type, field:Null}>; /** The defined array-access fields of the abstract. **/ - var array : Array; + var array:Array; /** The method used for resolving unknown field access, if available. **/ - @:require(haxe_ver >= 3.3) - var resolve : Null; + var resolve:Null; + + /** + The method used for resolving unknown field access, if available. + **/ + var resolveWrite:Null; } /** @@ -529,7 +548,7 @@ typedef MetaAccess = { Modifying this array has no effect on the origin of `this` MetaAccess. The `add` and `remove` methods can be used for that. **/ - function get() : Expr.Metadata; + function get():Expr.Metadata; /** Extract metadata entries by given `name`. @@ -538,7 +557,7 @@ typedef MetaAccess = { If `name` is null, compilation fails with an error. **/ - function extract( name : String ) : Array; + function extract(name:String):Array; /** Adds the metadata specified by `name`, `params` and `pos` to the origin @@ -552,7 +571,7 @@ typedef MetaAccess = { If any argument is null, compilation fails with an error. **/ - function add( name : String, params : Array, pos : Expr.Position ) : Void; + function add(name:String, params:Array, pos:Expr.Position):Void; /** Removes all `name` metadata entries from the origin of `this` @@ -565,34 +584,34 @@ typedef MetaAccess = { If `name` is null, compilation fails with an error. **/ - function remove( name : String ) : Void; + function remove(name:String):Void; /** Tells if the origin of `this` MetaAccess has a `name` metadata entry. If `name` is null, compilation fails with an error. **/ - function has( name : String ) : Bool; + function has(name:String):Bool; } /** Represents a field kind. -*/ + */ enum FieldKind { /** A variable of property, depending on the `read` and `write` values. **/ - FVar( read : VarAccess, write : VarAccess ); + FVar(read:VarAccess, write:VarAccess); /** A method **/ - FMethod( k : MethodKind ); + FMethod(k:MethodKind); } /** Represents the variable accessor. -*/ + */ enum VarAccess { /** Normal access (`default`). @@ -627,7 +646,7 @@ enum VarAccess { /** Failed access due to a `@:require` metadata. **/ - AccRequire( r : String, ?msg : String ); + AccRequire(r:String, ?msg:String); /** Access is only allowed from the constructor. @@ -637,7 +656,7 @@ enum VarAccess { /** Represents the method kind. -*/ + */ enum MethodKind { /** A normal method. @@ -666,7 +685,7 @@ enum MethodKind { /** Represents typed constant. -*/ + */ enum TConstant { /** An `Int` literal. @@ -706,7 +725,7 @@ enum TConstant { /** Represents a variable in the typed AST. -*/ + */ typedef TVar = { /** The unique ID of the variable. @@ -732,18 +751,18 @@ typedef TVar = { Special information which is internally used to keep track of closure. information **/ - public var extra(default,never):Null<{params: Array, expr: Null}>; + public var extra(default, never):Null<{params:Array, expr:Null}>; /** The metadata of the variable. **/ - public var meta(default,never):Null; + public var meta(default, never):Null; } /** Represents a module type. These are the types that can be declared in a Haxe module and which are passed to the generators (except `TTypeDecl`). -*/ + */ enum ModuleType { /** A class. @@ -768,28 +787,28 @@ enum ModuleType { /** Represents a function in the typed AST. -*/ + */ typedef TFunc = { /** A list of function arguments identified by an argument variable `v` and an optional initialization `value`. **/ - var args: Array<{v:TVar, value:Null}>; + var args:Array<{v:TVar, value:Null}>; /** The return type of the function. **/ - var t: Type; + var t:Type; /** The expression of the function body. **/ - var expr: TypedExpr; + var expr:TypedExpr; } /** Represents the kind of field access in the typed AST. -*/ + */ enum FieldAccess { /** Access of field `cf` on a class instance `c` with type parameters @@ -826,7 +845,7 @@ enum FieldAccess { /** Represents kind of a node in the typed AST. -*/ + */ enum TypedExprDef { /** A constant. @@ -846,7 +865,6 @@ enum TypedExprDef { /** Binary operator `e1 op e2`. **/ - TBinop(op:Expr.Binop, e1:TypedExpr, e2:TypedExpr); /** @@ -882,7 +900,7 @@ enum TypedExprDef { /** A constructor call `new c(el)`. **/ - TNew(c:Ref, params: Array, el:Array); + TNew(c:Ref, params:Array, el:Array); /** An unary operator `op` on `e`: @@ -988,20 +1006,20 @@ enum TypedExprDef { /** Represents a typed AST node. -*/ + */ typedef TypedExpr = { /** The expression kind. **/ - var expr: TypedExprDef; + var expr:TypedExprDef; /** The position of the expression. **/ - var pos: Expr.Position; + var pos:Expr.Position; /** The type of the expression. **/ - var t: Type; + var t:Type; } diff --git a/std/haxe/macro/TypeTools.hx b/std/haxe/macro/TypeTools.hx index 9f2cc3589d3..eadf7014941 100644 --- a/std/haxe/macro/TypeTools.hx +++ b/std/haxe/macro/TypeTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -37,58 +37,57 @@ using Lambda; @:hlNative("macro") #end class TypeTools { - - static function nullable(complexType : ComplexType) : ComplexType return macro : Null<$complexType>; - - static function toField(cf : ClassField) : Field return { - function varAccessToString(va : VarAccess, getOrSet : String) : String return { - switch (va) { - case AccNormal | AccCtor: "default"; - case AccNo: "null"; - case AccNever: "never"; - case AccResolve: throw "Invalid TAnonymous"; - case AccCall: getOrSet; - case AccInline: "default"; - case AccRequire(_, _): "default"; + static function nullable(complexType:ComplexType):ComplexType + return macro:Null<$complexType>; + + static function toField(cf:ClassField):Field + return { + function varAccessToString(va:VarAccess, getOrSet:String):String + return { + switch (va) { + case AccNormal | AccCtor: "default"; + case AccNo: "null"; + case AccNever: "never"; + case AccResolve: throw "Invalid TAnonymous"; + case AccCall: getOrSet; + case AccInline: "default"; + case AccRequire(_, _): "default"; + } + } + var access = cf.isPublic ? [APublic] : [APrivate]; + if (cf.meta.has(":final")) { + access.push(AFinal); + } + if (cf.params.length == 0) + { + name: cf.name, + doc: cf.doc, + access: access, + kind: switch ([cf.kind, cf.type]) { + case [FVar(read, write), ret]: + FProp(varAccessToString(read, "get"), varAccessToString(write, "set"), toComplexType(ret), null); + case [FMethod(_), TFun(args, ret)]: + FFun({ + args: [ + for (a in args) + { + name: a.name, + opt: a.opt, + type: toComplexType(a.t), + } + ], + ret: toComplexType(ret), + expr: null, + }); + default: + throw "Invalid TAnonymous"; + }, + pos: cf.pos, + meta: cf.meta.get(), + } else { + throw "Invalid TAnonymous"; } } - var access = cf.isPublic ? [ APublic ] : [ APrivate ]; - if (cf.meta.has(":final")) { - access.push(AFinal); - } - if (cf.params.length == 0) { - name: cf.name, - doc: cf.doc, - access: access, - kind: switch([ cf.kind, cf.type ]) { - case [ FVar(read, write), ret ]: - FProp( - varAccessToString(read, "get"), - varAccessToString(write, "set"), - toComplexType(ret), - null); - case [ FMethod(_), TFun(args, ret) ]: - FFun({ - args: [ - for (a in args) { - name: a.name, - opt: a.opt, - type: toComplexType(a.t), - } - ], - ret: toComplexType(ret), - expr: null, - }); - default: - throw "Invalid TAnonymous"; - }, - pos: cf.pos, - meta: cf.meta.get(), - } else { - throw "Invalid TAnonymous"; - } - } - /** Returns a syntax-level type corresponding to Type `t`. @@ -99,66 +98,71 @@ class TypeTools { If `t` is null, an internal exception is thrown. **/ - public static function toComplexType(type : Null) : Null return - { - #if macro - Context.toComplexType(type); - #else - switch (type) { - case null: - null; - case TMono(_.get() => t): - t == null ? null : toComplexType(t); - case TEnum(_.get() => baseType, params): - TPath(toTypePath(baseType, params)); - case TInst(_.get() => classType, params): - switch (classType.kind) { - case KTypeParameter(_): - TPath({ - name: classType.name, - pack: [], - }); - default: - TPath(toTypePath(classType, params)); - } - case TType(_.get() => baseType, params): - TPath(toTypePath(baseType, params)); - case TFun(args, ret): - TFunction( - [ for (a in args) a.opt ? nullable(toComplexType(a.t)) : toComplexType(a.t) ], - toComplexType(ret)); - case TAnonymous(_.get() => { fields: fields }): - TAnonymous([ for (cf in fields) toField(cf) ]); - case TDynamic(t): - if (t == null) { - macro : Dynamic; - } else { - var ct = toComplexType(t); - macro : Dynamic<$ct>; - } - case TLazy(f): - toComplexType(f()); - case TAbstract(_.get() => baseType, params): - TPath(toTypePath(baseType, params)); - default: - throw "Invalid type"; + public static function toComplexType(type:Null):Null + return { + #if macro + Context.toComplexType(type); + #else + switch (type) { + case null: + null; + case TMono(_.get() => t): + t == null ? null : toComplexType(t); + case TEnum(_.get() => baseType, params): + TPath(toTypePath(baseType, params)); + case TInst(_.get() => classType, params): + switch (classType.kind) { + case KTypeParameter(_): + TPath({ + name: classType.name, + pack: [], + }); + default: + TPath(toTypePath(classType, params)); + } + case TType(_.get() => baseType, params): + TPath(toTypePath(baseType, params)); + case TFun(args, ret): + TFunction([for (a in args) a.opt ? nullable(toComplexType(a.t)) : toComplexType(a.t)], toComplexType(ret)); + case TAnonymous(_.get() => {fields: fields}): + TAnonymous([for (cf in fields) toField(cf)]); + case TDynamic(t): + if (t == null) { + macro:Dynamic; + } else { + var ct = toComplexType(t); + macro:Dynamic<$ct>; + } + case TLazy(f): + toComplexType(f()); + case TAbstract(_.get() => baseType, params): + TPath(toTypePath(baseType, params)); + default: + throw "Invalid type"; + } + #end } - #end - } - static function toTypePath(baseType : BaseType, params : Array) : TypePath return { - var module = baseType.module; - { - pack: baseType.pack, - name: module.substring(module.lastIndexOf(".") + 1), - sub: baseType.name, - params: [ for (t in params) TPType(toComplexType(t)) ], + static function toTypeParam(type:Type):TypeParam + return { + switch (type) { + case TInst(_.get() => {kind: KExpr(e)}, _): TPExpr(e); + case _: TPType(toComplexType(type)); + } } - } - - #if macro + static function toTypePath(baseType:BaseType, params:Array):TypePath + return { + var module = baseType.module; + { + pack: baseType.pack, + name: module.substring(module.lastIndexOf(".") + 1), + sub: baseType.name, + params: [for (t in params) toTypeParam(t)], + } + } + #if (macro || display) /** Follows all typedefs of `t` to reach the actual type. @@ -177,7 +181,7 @@ class TypeTools { trace(t); // TMono() trace(t.follow()); //TInst(String,[]) **/ - static public inline function follow( t : Type, ?once : Bool ) : Type + static public inline function follow(t:Type, ?once:Bool):Type return Context.follow(t, once); /** @@ -193,13 +197,13 @@ class TypeTools { trace(t); // TAbstract(Map,[TInst(String,[]),TInst(String,[])]) trace(t.followWithAbstracts()); // TInst(haxe.ds.StringMap, [TInst(String,[])]) **/ - static public inline function followWithAbstracts( t : Type, once : Bool = false ) : Type + static public inline function followWithAbstracts(t:Type, once:Bool = false):Type return Context.followWithAbstracts(t, once); /** Returns true if `t1` and `t2` unify, false otherwise. **/ - static public inline function unify( t1 : Type, t2:Type ) : Bool + static public inline function unify(t1:Type, t2:Type):Bool return Context.unify(t1, t2); /** @@ -211,10 +215,11 @@ class TypeTools { If `t` is null, the result is null. **/ - static public function getClass( t : Type ) return t == null ? null : switch(follow(t)) { - case TInst(c, _): c.get(); - case _: throw "Class instance expected"; - } + static public function getClass(t:Type) + return t == null ? null : switch (follow(t)) { + case TInst(c, _): c.get(); + case _: throw "Class instance expected"; + } /** Tries to extract the enum instance stored inside `t`. @@ -225,10 +230,11 @@ class TypeTools { If `t` is null, the result is null. **/ - static public function getEnum( t : Type ) return t == null ? null : switch(follow(t)) { - case TEnum(e, _): e.get(); - case _: throw "Enum instance expected"; - } + static public function getEnum(t:Type) + return t == null ? null : switch (follow(t)) { + case TEnum(e, _): e.get(); + case _: throw "Enum instance expected"; + } /** Applies the type parameters `typeParameters` to type `t` with the given @@ -258,12 +264,11 @@ class TypeTools { } #if !neko - private static function applyParams( typeParameters:Array, concreteTypes:Array, t:Type ) : Type { + private static function applyParams(typeParameters:Array, concreteTypes:Array, t:Type):Type { return null; } #end - /** Transforms `t` by calling `f` on each of its subtypes. @@ -278,10 +283,10 @@ class TypeTools { If `t` or `f` are null, the result is unspecified. **/ - static public function map(t:Type, f:Type -> Type):Type { - return switch(t) { + static public function map(t:Type, f:Type->Type):Type { + return switch (t) { case TMono(tm): - switch(tm.get()) { + switch (tm.get()) { case null: t; case var t: f(t); } @@ -324,21 +329,26 @@ class TypeTools { If `t` or `f` are null, the result is unspecified. **/ - static public function iter(t:Type, f:Type -> Void):Void { + static public function iter(t:Type, f:Type->Void):Void { switch (t) { case TMono(tm): var t = tm.get(); - if (t != null) f(t); + if (t != null) + f(t); case TEnum(_, tl) | TInst(_, tl) | TType(_, tl) | TAbstract(_, tl): - for (t in tl) f(t); + for (t in tl) + f(t); case TDynamic(t2): - if (t != t2) f(t2); + if (t != t2) + f(t2); case TLazy(ft): f(ft()); case TAnonymous(an): - for (field in an.get().fields) f(field.type); + for (field in an.get().fields) + f(field.type); case TFun(args, ret): - for (arg in args) f(arg.t); + for (arg in args) + f(arg.t); f(ret); } } @@ -346,14 +356,13 @@ class TypeTools { /** Converts type `t` to a human-readable String representation. **/ - static public function toString( t : Type ) : String { + static public function toString(t:Type):String { #if (neko || eval) return Context.load("s_type", 1)(t); #else return null; #end } - #end /** @@ -370,8 +379,6 @@ class TypeTools { **/ static public function findField(c:ClassType, name:String, isStatic:Bool = false):Null { var field = (isStatic ? c.statics : c.fields).get().find(function(field) return field.name == name); - return if(field != null) field; - else if (c.superClass != null) findField(c.superClass.t.get(), name, isStatic); - else null; + return if (field != null) field; else if (c.superClass != null) findField(c.superClass.t.get(), name, isStatic); else null; } } diff --git a/std/haxe/macro/TypedExprTools.hx b/std/haxe/macro/TypedExprTools.hx index 8ef9f396430..d0f81bf5dbc 100644 --- a/std/haxe/macro/TypedExprTools.hx +++ b/std/haxe/macro/TypedExprTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -45,8 +45,8 @@ class TypedExprTools { general. This function works the same way, but with a different data structure. **/ - static public function map(e:TypedExpr, f:TypedExpr -> TypedExpr):TypedExpr { - return switch(e.expr) { + static public function map(e:TypedExpr, f:TypedExpr->TypedExpr):TypedExpr { + return switch (e.expr) { case TConst(_) | TLocal(_) | TBreak | TContinue | TTypeExpr(_) | TIdent(_): e; case TArray(e1, e2): with(e, TArray(f(e1), f(e2))); case TBinop(op, e1, e2): with(e, TBinop(op, f(e1), f(e2))); @@ -61,13 +61,14 @@ class TypedExprTools { case TArrayDecl(el): with(e, TArrayDecl(el.map(f))); case TNew(t, pl, el): with(e, TNew(t, pl, el.map(f))); case TBlock(el): with(e, TBlock(el.map(f))); - case TObjectDecl(fl): with(e, TObjectDecl(fl.map(function(field) return { name: field.name, expr: f(field.expr) }))); + case TObjectDecl(fl): with(e, TObjectDecl(fl.map(function(field) return {name: field.name, expr: f(field.expr)}))); case TCall(e1, el): with(e, TCall(f(e1), el.map(f))); - case TVar(v,eo): with(e, TVar(v, eo == null ? null : f(eo))); - case TFunction(fu): with(e, TFunction({ t: fu.t, args: fu.args, expr: f(fu.expr)})); + case TVar(v, eo): with(e, TVar(v, eo == null ? null : f(eo))); + case TFunction(fu): with(e, TFunction({t: fu.t, args: fu.args, expr: f(fu.expr)})); case TIf(e1, e2, e3): with(e, TIf(f(e1), f(e2), e3 == null ? null : f(e3))); - case TSwitch(e1, cases, e2): with(e, TSwitch(f(e1), cases.map(function(c) return { values: c.values.map(f), expr: f(c.expr) }), e2 == null ? null : f(e2))); - case TTry(e1, catches): with(e, TTry(f(e1), catches.map(function(c) return { v:c.v, expr: f(c.expr) }))); + case TSwitch(e1, cases, + e2): with(e, TSwitch(f(e1), cases.map(function(c) return {values: c.values.map(f), expr: f(c.expr)}), e2 == null ? null : f(e2))); + case TTry(e1, catches): with(e, TTry(f(e1), catches.map(function(c) return {v: c.v, expr: f(c.expr)}))); case TReturn(e1): with(e, TReturn(e1 == null ? null : f(e1))); case TCast(e1, mt): with(e, TCast(f(e1), mt)); case TMeta(m, e1): with(e, TMeta(m, f(e1))); @@ -81,8 +82,8 @@ class TypedExprTools { general. This function works the same way, but with a different data structure. **/ - static public function iter(e:TypedExpr, f:TypedExpr -> Void):Void { - switch(e.expr) { + static public function iter(e:TypedExpr, f:TypedExpr->Void):Void { + switch (e.expr) { case TConst(_) | TLocal(_) | TBreak | TContinue | TTypeExpr(_) | TIdent(_): case TArray(e1, e2) | TBinop(_, e1, e2) | TFor(_, e1, e2) | TWhile(e1, e2, _): f(e1); @@ -90,30 +91,38 @@ class TypedExprTools { case TThrow(e1) | TEnumParameter(e1, _, _) | TEnumIndex(e1) | TField(e1, _) | TParenthesis(e1) | TUnop(_, _, e1) | TCast(e1, _) | TMeta(_, e1): f(e1); case TArrayDecl(el) | TNew(_, _, el) | TBlock(el): - for (e in el) f(e); + for (e in el) + f(e); case TObjectDecl(fl): - for (field in fl) f(field.expr); + for (field in fl) + f(field.expr); case TCall(e1, el): f(e1); - for (e in el) f(e); + for (e in el) + f(e); case TVar(_, e1) | TReturn(e1): - if (e1 != null) f(e1); + if (e1 != null) + f(e1); case TFunction(fu): f(fu.expr); case TIf(e1, e2, e3): f(e1); f(e2); - if (e3 != null) f(e3); + if (e3 != null) + f(e3); case TSwitch(e1, cases, e2): f(e1); for (c in cases) { - for (v in c.values) f(v); + for (v in c.values) + f(v); f(c.expr); } - if (e2 != null) f(e2); + if (e2 != null) + f(e2); case TTry(e1, catches): f(e1); - for (c in catches) f(c.expr); + for (c in catches) + f(c.expr); } } @@ -126,8 +135,8 @@ class TypedExprTools { general. This function works the same way, but with a different data structure. **/ - static public function mapWithType(e:TypedExpr, f:TypedExpr -> TypedExpr, ft:Type -> Type, fv:TVar -> TVar):TypedExpr { - return switch(e.expr) { + static public function mapWithType(e:TypedExpr, f:TypedExpr->TypedExpr, ft:Type->Type, fv:TVar->TVar):TypedExpr { + return switch (e.expr) { case TConst(_) | TBreak | TContinue | TTypeExpr(_) | TIdent(_): with(e, ft(e.t)); case TLocal(v): with(e, TLocal(fv(v)), ft(e.t)); case TArray(e1, e2): with(e, TArray(f(e1), f(e2)), ft(e.t)); @@ -143,20 +152,22 @@ class TypedExprTools { case TArrayDecl(el): with(e, TArrayDecl(el.map(f)), ft(e.t)); case TNew(t, pl, el): with(e, TNew(t, pl, el.map(f)), ft(e.t)); case TBlock(el): with(e, TBlock(el.map(f)), ft(e.t)); - case TObjectDecl(fl): with(e, TObjectDecl(fl.map(function(field) return { name: field.name, expr: f(field.expr) })), ft(e.t)); + case TObjectDecl(fl): with(e, TObjectDecl(fl.map(function(field) return {name: field.name, expr: f(field.expr)})), ft(e.t)); case TCall(e1, el): with(e, TCall(f(e1), el.map(f)), ft(e.t)); - case TVar(v,eo): with(e, TVar(fv(v), eo == null ? null : f(eo)), ft(e.t)); - case TFunction(fu): with(e, TFunction({ t: ft(fu.t), args: fu.args.map(function(arg) return { v: fv(arg.v), value: arg.value }), expr: f(fu.expr)}), ft(e.t)); + case TVar(v, eo): with(e, TVar(fv(v), eo == null ? null : f(eo)), ft(e.t)); + case TFunction(fu): with(e, TFunction({t: ft(fu.t), args: fu.args.map(function(arg) return {v: fv(arg.v), value: arg.value}), expr: f(fu.expr)}), + ft(e.t)); case TIf(e1, e2, e3): with(e, TIf(f(e1), f(e2), e3 == null ? null : f(e3)), ft(e.t)); - case TSwitch(e1, cases, e2): with(e, TSwitch(f(e1), cases.map(function(c) return { values: c.values.map(f), expr: f(c.expr) }), e2 == null ? null : f(e2)), ft(e.t)); - case TTry(e1, catches): with(e, TTry(f(e1), catches.map(function(c) return { v:fv(c.v), expr: f(c.expr) })), ft(e.t)); + case TSwitch(e1, cases, + e2): with(e, TSwitch(f(e1), cases.map(function(c) return {values: c.values.map(f), expr: f(c.expr)}), e2 == null ? null : f(e2)), ft(e.t)); + case TTry(e1, catches): with(e, TTry(f(e1), catches.map(function(c) return {v: fv(c.v), expr: f(c.expr)})), ft(e.t)); case TReturn(e1): with(e, TReturn(e1 == null ? null : f(e1)), ft(e.t)); case TCast(e1, mt): with(e, TCast(f(e1), mt), ft(e.t)); case TMeta(m, e1): with(e, TMeta(m, f(e1)), ft(e.t)); } } - #if macro + #if (macro || display) static public function toString(t:TypedExpr, ?pretty = false):String { return @:privateAccess haxe.macro.Context.sExpr(t, pretty); } diff --git a/std/haxe/remoting/AMFConnection.hx b/std/haxe/remoting/AMFConnection.hx deleted file mode 100644 index 984704c10b0..00000000000 --- a/std/haxe/remoting/AMFConnection.hx +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -/** - Allows a connection to an AMF Remoting server such as Flash Media Server or AMFPHP. -*/ -class AMFConnection implements AsyncConnection implements Dynamic { - - var __data : { - error : Dynamic -> Void, - #if flash - cnx : flash.net.NetConnection, - #else - cnx : Dynamic, - #end - }; - var __path : Array; - - function new( data, path ) { - __data = data; - __path = path; - } - - public function resolve( name ) : AsyncConnection { - var s = new AMFConnection(__data,__path.copy()); - s.__path.push(name); - return s; - } - - public function setErrorHandler(h) { - __data.error = h; - } - - public function close() { - __data.cnx.close(); - } - - public function call( params : Array, ?onResult : Dynamic -> Void ) : Void { - if( onResult == null ) onResult = function(e) {}; - var p = params.copy(); - #if flash - p.unshift(new flash.net.Responder(onResult,__data.error)); - #else - p.unshift({ onStatus : __data.error, onResult : onResult }); - #end - p.unshift(__path.join(".")); - untyped __data.cnx.call.apply(__data,p); - } - - #if flash - public static function urlConnect( gatewayUrl : String ) { - var c = new flash.net.NetConnection(); - var cnx = new AMFConnection({ cnx : c, error : function(e) throw e },[]); - c.addEventListener(flash.events.NetStatusEvent.NET_STATUS,function(e:flash.events.NetStatusEvent) { - cnx.__data.error(e); - }); - c.connect(gatewayUrl); - return cnx; - } - - public static function connect( nc ) { - return new AMFConnection({ cnx : nc, error : function(e) throw e },[]); - } - - public static function registerClassAlias( s : String, cl : Class ) { - untyped __global__[ "flash.net.registerClassAlias" ]( s, cl ); - } - #end - -} diff --git a/std/haxe/remoting/AsyncDebugConnection.hx b/std/haxe/remoting/AsyncDebugConnection.hx deleted file mode 100644 index f6ae1d50ca1..00000000000 --- a/std/haxe/remoting/AsyncDebugConnection.hx +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -class AsyncDebugConnection implements AsyncConnection implements Dynamic { - - var __path : Array; - var __cnx : AsyncConnection; - var __data : { - error : Dynamic -> Void, - oncall : Array -> Array -> Void, - onerror : Array -> Array -> Dynamic -> Void, - onresult : Array -> Array -> Dynamic -> Void, - }; - - function new(path,cnx,data) { - __path = path; - __cnx = cnx; - __data = data; - } - - public function resolve( name ) : AsyncConnection { - var cnx = new AsyncDebugConnection(__path.copy(),__cnx.resolve(name),__data); - cnx.__path.push(name); - return cnx; - } - - public function setErrorHandler(h) { - __data.error = h; - } - - public function setErrorDebug(h) { - __data.onerror = h; - } - - public function setResultDebug(h) { - __data.onresult = h; - } - - public function setCallDebug(h) { - __data.oncall = h; - } - - public function call( params : Array, ?onResult : Dynamic -> Void ) { - var me = this; - __data.oncall(__path,params); - __cnx.setErrorHandler(function(e) { - me.__data.onerror(me.__path,params,e); - me.__data.error(e); - }); - __cnx.call(params,function(r) { - me.__data.onresult(me.__path,params,r); - if( onResult != null ) onResult(r); - }); - } - - public static function create( cnx : AsyncConnection ) { - var cnx = new AsyncDebugConnection([],cnx,{ - error : function(e) throw e, - oncall : function(path,params) {}, - onerror : null, - onresult : null, - }); - cnx.setErrorDebug(function(path,params,e) trace(path.join(".")+"("+params.join(",")+") = ERROR "+Std.string(e))); - cnx.setResultDebug(function(path,params,e) trace(path.join(".")+"("+params.join(",")+") = "+Std.string(e))); - return cnx; - } - -} diff --git a/std/haxe/remoting/Context.hx b/std/haxe/remoting/Context.hx deleted file mode 100644 index d42f8e9933d..00000000000 --- a/std/haxe/remoting/Context.hx +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -/** - Allows communication between platforms. This is a shared API that can be called on the connection at the client code. -*/ -class Context { - - var objects : haxe.ds.StringMap<{ obj : Dynamic, rec : Bool }>; - - public function new() { - objects = new haxe.ds.StringMap(); - } - - public function addObject( name : String, obj : {}, ?recursive ) { - objects.set(name,{ obj : obj, rec : recursive }); - } - - public function call( path : Array, params : Array ) : Dynamic { - if( path.length < 2 ) throw "Invalid path '"+path.join(".")+"'"; - var inf = objects.get(path[0]); - if( inf == null ) - throw "No such object "+path[0]; - var o = inf.obj; - var m = Reflect.field(o,path[1]); - if( path.length > 2 ) { - if( !inf.rec ) throw "Can't access "+path.join("."); - for( i in 2...path.length ) { - o = m; - m = Reflect.field(o,path[i]); - } - } - if( !Reflect.isFunction(m) ) - throw "No such method "+path.join("."); - return Reflect.callMethod(o,m,params); - } - - public static function share( name : String, obj : {} ) : Context { - var ctx = new Context(); - ctx.addObject(name,obj); - return ctx; - } - -} diff --git a/std/haxe/remoting/ContextAll.hx b/std/haxe/remoting/ContextAll.hx deleted file mode 100644 index f8b7c2aa1e5..00000000000 --- a/std/haxe/remoting/ContextAll.hx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -class ContextAll extends Context { - - public override function call( path : Array, params : Array ) : Dynamic { - #if neko - var o : Dynamic = null; - var m : Dynamic = neko.Lib.getClasses(); - for( p in path ) { - o = m; - m = Reflect.field(o,p); - } - #elseif js - var path2 = path.copy(); - var f = path2.pop(); - var o; - try { - o = js.Lib.eval(path2.join(".")); - } catch( e : Dynamic ) { - o = null; - } - var m = Reflect.field(o,f); - #elseif flash - var path2 = path.copy(); - var f = path2.pop(); - var o = flash.Lib.eval(path2.join(".")); - var m = Reflect.field(o,f); - #elseif php - var path2 = path.copy(); - var f = path2.pop(); - var o = Type.resolveClass(path2.join(".")); - var m = Reflect.field(o,f); - #else - var o = null; - var m = null; - #end - if( m == null ) - return super.call(path,params); - return Reflect.callMethod(o,m,params); - } - -} \ No newline at end of file diff --git a/std/haxe/remoting/DelayedConnection.hx b/std/haxe/remoting/DelayedConnection.hx deleted file mode 100644 index ccc84e28d13..00000000000 --- a/std/haxe/remoting/DelayedConnection.hx +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -class DelayedConnection implements AsyncConnection implements Dynamic { - - public var connection(get,set) : AsyncConnection; - - var __path : Array; - var __data : { - cnx : AsyncConnection, - error : Dynamic -> Void, - cache : Array<{ - path : Array, - params : Array, - onResult : Dynamic -> Void, - onError : Dynamic -> Void - }>, - }; - - function new(data,path) { - __data = data; - __path = path; - } - - public function setErrorHandler(h) { - __data.error = h; - } - - public function resolve( name ) : AsyncConnection { - var d = new DelayedConnection(__data,__path.copy()); - d.__path.push(name); - return d; - } - - function get_connection() { - return __data.cnx; - } - - function set_connection(cnx) { - __data.cnx = cnx; - process(this); - return cnx; - } - - public function call( params : Array, ?onResult ) { - __data.cache.push({ path : __path, params : params, onResult : onResult, onError : __data.error }); - process(this); - } - - static function process( d : DelayedConnection ) { - var cnx = d.__data.cnx; - if( cnx == null ) - return; - while( true ) { - var m = d.__data.cache.shift(); - if( m == null ) - break; - var c = cnx; - for( p in m.path ) - c = c.resolve(p); - c.setErrorHandler(m.onError); - c.call(m.params,m.onResult); - } - } - - public static function create() { - return new DelayedConnection({ cnx : null, error : function(e) throw e, cache : new Array() },[]); - } - -} diff --git a/std/haxe/remoting/ExternalConnection.hx b/std/haxe/remoting/ExternalConnection.hx deleted file mode 100644 index 2ad8b195167..00000000000 --- a/std/haxe/remoting/ExternalConnection.hx +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -/** - Synchronous communications between Flash and Javascript. -**/ -@:expose -class ExternalConnection implements Connection implements Dynamic { - - var __data : { name : String, ctx : Context, #if js flash : String #end }; - var __path : Array; - - function new( data, path ) { - __data = data; - __path = path; - } - - public function resolve(field) : Connection { - var e = new ExternalConnection(__data,__path.copy()); - e.__path.push(field); - return e; - } - - public function close() { - connections.remove(__data.name); - } - - #if flash - static function escapeString( s : String ) { - return s.split("\\").join("\\\\"); - } - #else - static inline function escapeString(s:String) { - return s; - } - #end - - public function call( params : Array ) : Dynamic { - var s = new haxe.Serializer(); - s.serialize(params); - var params = escapeString(s.toString()); - var data = null; - #if flash - #if js_unflatten - data = flash.external.ExternalInterface.call("haxe.remoting.ExternalConnection.doCall",__data.name,__path.join("."),params); - #else - data = flash.external.ExternalInterface.call("haxe_remoting_ExternalConnection.doCall",__data.name,__path.join("."),params); - #end - #elseif js - var fobj : Dynamic = (untyped js.Browser.document)[cast __data.flash]; // FIXME(bruno): Why is this necessary? - if( fobj == null ) fobj = js.Browser.document.getElementById(__data.flash); - if( fobj == null ) throw "Could not find flash object '"+__data.flash+"'"; - try data = fobj.externalRemotingCall(__data.name,__path.join("."),params) catch( e : Dynamic ) {}; - #end - if( data == null ) { - #if js - var domain, pageDomain; - try { - // check that swf in on the same domain - domain = fobj.src.split("/")[2]; - pageDomain = js.Browser.location.host; - } catch( e : Dynamic ) { - domain = null; - pageDomain = null; - } - if( domain != pageDomain ) - throw "ExternalConnection call failure : SWF need allowDomain('"+pageDomain+"')"; - #end - throw "Call failure : ExternalConnection is not " + #if flash "compiled in JS" #else "initialized in Flash" #end; - } - return new haxe.Unserializer(data).unserialize(); - } - - static var connections = new haxe.ds.StringMap(); - - @:keep - static function doCall( name : String, path : String, params : String ) : String { - try { - var cnx = connections.get(name); - if( cnx == null ) throw "Unknown connection : "+name; - if( cnx.__data.ctx == null ) throw "No context shared for the connection "+name; - var params = new haxe.Unserializer(params).unserialize(); - var ret = cnx.__data.ctx.call(path.split("."),params); - var s = new haxe.Serializer(); - s.serialize(ret); - #if flash - return escapeString(s.toString()); - #else - return s.toString()+"#"; - #end - } catch( e : Dynamic ) { - var s = new haxe.Serializer(); - s.serializeException(e); - return s.toString(); - } - #if as3 - return ""; - #end - } - - #if flash - - public static function jsConnect( name : String, ?ctx : Context ) { - if( !flash.external.ExternalInterface.available ) - throw "External Interface not available"; - try flash.external.ExternalInterface.addCallback("externalRemotingCall",doCall) catch( e : Dynamic ) {}; - var cnx = new ExternalConnection({ name : name, ctx : ctx },[]); - connections.set(name,cnx); - return cnx; - } - - #elseif js - - public static function flashConnect( name : String, flashObjectID : String, ?ctx : Context ) { - var cnx = new ExternalConnection({ ctx : ctx, name : name, flash : flashObjectID },[]); - connections.set(name,cnx); - return cnx; - } - - #end - -} diff --git a/std/haxe/remoting/FlashJsConnection.hx b/std/haxe/remoting/FlashJsConnection.hx deleted file mode 100644 index 316732cd610..00000000000 --- a/std/haxe/remoting/FlashJsConnection.hx +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -class FlashJsConnection #if flash implements AsyncConnection implements Dynamic #end { - -#if flash - - var __path : Array; - var __data : { - id : String, - name : String, - ctx : Context, - error : Dynamic -> Void, - timer : haxe.Timer, - queue : Array Void>, - }; - - function new( data, path ) { - __data = data; - __path = path; - } - - public function close() { - connections.remove(__data.name); - } - - public function resolve( name ) : AsyncConnection { - var c = new FlashJsConnection(__data,__path.copy()); - c.__path.push(name); - return c; - } - - public function setErrorHandler(h) { - __data.error = h; - } - - public function call( params : Array, ?onResult : Dynamic -> Void ) { - var s = new haxe.Serializer(); - s.serialize(params); - var params = escapeString(s.toString()); - var error = __data.error; - __data.queue.push(function() { - var data = flash.external.ExternalInterface.call("haxe.remoting.FlashJsConnection.flashCall",__data.id,__data.name,__path.join("."),params); - var v : Dynamic; - try { - if( data == null ) - throw "Call failure : FlashJsConnection is not compiled in JS"; - v = new haxe.Unserializer(data).unserialize(); - } catch( e : Dynamic ) { - error(e); - return; - } - if( onResult != null ) - onResult(v); - }); - if( __data.timer == null ) { - __data.timer = new haxe.Timer(1); - __data.timer.run = function() { - var q = __data.queue.shift(); - if( q == null ) { - __data.timer.stop(); - __data.timer = null; - return; - } - q(); - }; - } - } - - static var connections = new haxe.ds.StringMap(); - - static function escapeString( s : String ) { - #if flash - return s.split("\\").join("\\\\"); - #else - return s.split("\\").join("\\\\").split("&").join("&"); - #end - } - - static function doCall( name : String, path : String, params : String ) : String { - try { - var cnx = connections.get(name); - if( cnx == null ) throw "Unknown connection : "+name; - if( cnx.__data.ctx == null ) throw "No context shared for the connection "+name; - var params = new haxe.Unserializer(params).unserialize(); - var ret = cnx.__data.ctx.call(path.split("."),params); - var s = new haxe.Serializer(); - s.serialize(ret); - return escapeString(s.toString()); - } catch( e : Dynamic ) { - var s = new haxe.Serializer(); - s.serializeException(e); - return s.toString(); - } - #if as3 - return ""; - #end - } - - public static function connect( name : String, objId : String, ?ctx : Context ) { - if( !flash.external.ExternalInterface.available ) - throw "External Interface not available"; - try flash.external.ExternalInterface.addCallback("flashJsRemotingCall",doCall) catch( e : Dynamic ) {}; - var cnx = new FlashJsConnection({ - id : objId, - name : name, - ctx : ctx, - error : function(e) throw e, - queue : [], - timer : null, - },[]); - connections.set(name,cnx); - return cnx; - } - -#elseif js - - static function flashCall( flashObj : String, name : String, path : String, params : String ) : String { - try { - var fobj : Dynamic = untyped (untyped js.Browser.document)[__data.flash]; // FIXME(bruno): Why is this necessary? - if( fobj == null ) fobj = js.Browser.document.getElementById(flashObj); - if( fobj == null ) throw "Could not find flash object '"+flashObj+"'"; - var data = null; - try data = fobj.flashJsRemotingCall(name,path,params) catch( e : Dynamic ) {}; - if( data == null ) throw "Flash object "+flashObj+" does not have an active FlashJsConnection"; - return data; - } catch( e : Dynamic ) { - var s = new haxe.Serializer(); - s.serializeException(e); - return s.toString(); - } - } - -#end - -} diff --git a/std/haxe/remoting/HttpAsyncConnection.hx b/std/haxe/remoting/HttpAsyncConnection.hx deleted file mode 100644 index 99091f51fc7..00000000000 --- a/std/haxe/remoting/HttpAsyncConnection.hx +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -/** - Allows an asynchronous connection to the given URL which should link to a Haxe server application. -*/ -class HttpAsyncConnection implements AsyncConnection implements Dynamic { - - var __data : { url : String, error : Dynamic -> Void }; - var __path : Array; - - function new(data,path) { - __data = data; - __path = path; - } - - public function resolve( name ) : AsyncConnection { - var c = new HttpAsyncConnection(__data,__path.copy()); - c.__path.push(name); - return c; - } - - public function setErrorHandler(h) { - __data.error = h; - } - - public function call( params : Array, ?onResult : Dynamic -> Void ) { - var h = new haxe.Http(__data.url); - #if (neko && no_remoting_shutdown) - h.noShutdown = true; - #end - var s = new haxe.Serializer(); - s.serialize(__path); - s.serialize(params); - h.setHeader("X-Haxe-Remoting","1"); - h.setParameter("__x",s.toString()); - var error = __data.error; - h.onData = function( response : String ) { - var ok = true; - var ret; - try { - if( response.substr(0,3) != "hxr" ) throw "Invalid response : '"+response+"'"; - var s = new haxe.Unserializer(response.substr(3)); - ret = s.unserialize(); - } catch( err : Dynamic ) { - ret = null; - ok = false; - error(err); - } - if( ok && onResult != null ) onResult(ret); - }; - h.onError = error; - h.request(true); - } - - public static function urlConnect( url : String ) { - return new HttpAsyncConnection({ url : url, error : function(e) throw e },[]); - } - -} diff --git a/std/haxe/remoting/HttpConnection.hx b/std/haxe/remoting/HttpConnection.hx deleted file mode 100644 index efcbecdc586..00000000000 --- a/std/haxe/remoting/HttpConnection.hx +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -/** - Allows a synchronous connection to the given URL which should link to a Haxe server application. -*/ -class HttpConnection implements Connection implements Dynamic { - - public static var TIMEOUT = 10.; - - var __url : String; - var __path : Array; - - function new(url,path) { - __url = url; - __path = path; - } - - public function resolve( name ) : Connection { - var c = new HttpConnection(__url,__path.copy()); - c.__path.push(name); - return c; - } - - public function call( params : Array ) : Dynamic { - var data = null; - var h = new haxe.Http(__url); - #if (js && !nodejs) - h.async = false; - #end - #if (neko && no_remoting_shutdown) - h.noShutdown = true; - #end - #if (neko || php || cpp) - h.cnxTimeout = TIMEOUT; - #end - var s = new haxe.Serializer(); - s.serialize(__path); - s.serialize(params); - h.setHeader("X-Haxe-Remoting","1"); - h.setParameter("__x",s.toString()); - h.onData = function(d) { data = d; }; - h.onError = function(e) { throw e; }; - h.request(true); - if( data.substr(0,3) != "hxr" ) - throw "Invalid response : '"+data+"'"; - data = data.substr(3); - return new haxe.Unserializer(data).unserialize(); - } - - #if !flash - - public static function urlConnect( url : String ) { - return new HttpConnection(url,[]); - } - - #end - - #if neko - public static function handleRequest( ctx : Context ) { - var v = neko.Web.getParams().get("__x"); - if( neko.Web.getClientHeader("X-Haxe-Remoting") == null || v == null ) - return false; - neko.Lib.print(processRequest(v,ctx)); - return true; - } - #elseif php - public static function handleRequest( ctx : Context ) { - var v = php.Web.getParams().get("__x"); - if( php.Web.getClientHeader("X-Haxe-Remoting") == null || v == null ) - return false; - php.Lib.print(processRequest(v,ctx)); - return true; - } - #end - - public static function processRequest( requestData : String, ctx : Context ) : String { - try { - var u = new haxe.Unserializer(requestData); - var path = u.unserialize(); - var args = u.unserialize(); - var data = ctx.call(path,args); - var s = new haxe.Serializer(); - s.serialize(data); - return "hxr" + s.toString(); - } catch( e : Dynamic ) { - var s = new haxe.Serializer(); - s.serializeException(e); - return "hxr" + s.toString(); - } - } - -} diff --git a/std/haxe/remoting/LocalConnection.hx b/std/haxe/remoting/LocalConnection.hx deleted file mode 100644 index 7b534976d4a..00000000000 --- a/std/haxe/remoting/LocalConnection.hx +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -/** - Allows communications to a different application that runs on the same client device -*/ -class LocalConnection implements AsyncConnection implements Dynamic { - - static var ID = 0; - - var __path : Array; - var __data : { - ctx : Context, - results : haxe.ds.IntMap<{ error : Dynamic -> Void, result : Dynamic -> Void }>, - error : Dynamic -> Void, - target : String, - #if flash - cnx : flash.net.LocalConnection, - #else - cnx : Dynamic, - #end - }; - - function new(data,path) { - this.__path = path; - this.__data = data; - } - - public function resolve( name ) : AsyncConnection { - var s = new LocalConnection(__data,__path.copy()); - s.__path.push(name); - return s; - } - - public function setErrorHandler(h) { - __data.error = h; - } - - public function call( params : Array, ?onResult : Dynamic -> Void ) : Void { - try { - var id = ID++; - #if flash - __data.cnx.send(__data.target,"remotingCall",id,__path.join("."),haxe.Serializer.run(params)); - #else - if( !__data.cnx.send(__data.target,"remotingCall",id,__path.join("."),haxe.Serializer.run(params)) ) - throw "Remoting call failure"; - #end - __data.results.set(id,{ error : __data.error, result : onResult }); - } catch( e : Dynamic ) { - __data.error(e); - } - } - - public function close() { - __data.cnx.close(); - } - - static function remotingCall( c : LocalConnection, id : Int, path : String, args : String ) { - var r; - try { - if( c.__data.ctx == null ) throw "No context shared for this connection"; - var ret = c.__data.ctx.call(path.split("."),haxe.Unserializer.run(args)); - r = haxe.Serializer.run(ret); - } catch( e : Dynamic ) { - var s = new haxe.Serializer(); - s.serializeException(e); - r = s.toString(); - } - // don't forward 'send' errors on connection since it's only the receiving side - c.__data.cnx.send(c.__data.target,"remotingResult",id,r); - } - - static function remotingResult( c : LocalConnection, id : Int, result : String ) { - var f = c.__data.results.get(id); - if( f == null ) - c.__data.error("Invalid result ID "+id); - c.__data.results.remove(id); - var val : Dynamic; - try { - val = new haxe.Unserializer(result).unserialize(); - } catch( e : Dynamic ) { - f.error(e); - return; - } - if( f.result != null ) - f.result(val); - } - - #if flash - public static function connect( name : String, ?ctx : Context, ?allowDomains : Array ) { - var l = new flash.net.LocalConnection(); - var recv = name + "_recv"; - var c = new LocalConnection({ - ctx : ctx, - error : function(e) throw e, - results : new haxe.ds.IntMap(), - cnx : l, - target : recv, - },[]); - l.client = { - remotingCall : remotingCall.bind(c), - remotingResult : remotingResult.bind(c), - }; - l.addEventListener(flash.events.StatusEvent.STATUS, function(s:flash.events.StatusEvent) { - if( s.level != "status" ) - c.__data.error("Failed to send data on LocalConnection"); - }); - try - l.connect(name) - catch( e : Dynamic ) { - l.connect(recv); - c.__data.target = name; - } - if( allowDomains != null ) - for( d in allowDomains ) - l.allowDomain(d); - return c; - } - #end - -} diff --git a/std/haxe/remoting/SocketConnection.hx b/std/haxe/remoting/SocketConnection.hx deleted file mode 100644 index c6343293a47..00000000000 --- a/std/haxe/remoting/SocketConnection.hx +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; -import haxe.remoting.SocketProtocol.Socket; - -/** - Allows remoting communications over a socket connection -*/ -class SocketConnection implements AsyncConnection implements Dynamic { - - var __path : Array; - var __data : { - protocol : SocketProtocol, - results : List<{ onResult : Dynamic -> Void, onError : Dynamic -> Void }>, - log : Array -> Array -> Dynamic -> Void, - error : Dynamic -> Void, - #if js - queue : Array Void>, - timer : haxe.Timer, - #end - }; - - function new(data,path) { - __data = data; - __path = path; - } - - public function resolve(name) : AsyncConnection { - var s = new SocketConnection(__data,__path.copy()); - s.__path.push(name); - return s; - } - - public function call( params : Array, ?onResult : Dynamic -> Void ) { - try { - __data.protocol.sendRequest(__path,params); - __data.results.add({ onResult : onResult, onError : __data.error }); - } catch( e : Dynamic ) { - __data.error(e); - } - } - - public function setErrorHandler(h) { - __data.error = h; - } - - public function setErrorLogger(h) { - __data.log = h; - } - - public function setProtocol( p : SocketProtocol ) { - __data.protocol = p; - } - - public function getProtocol() : SocketProtocol { - return __data.protocol; - } - - public function close() { - try __data.protocol.socket.close() catch( e : Dynamic ) { }; - } - - public function processMessage( data : String ) { - var request; - var proto = __data.protocol; - data = proto.decodeData(data); - try { - request = proto.isRequest(data); - } catch( e : Dynamic ) { - var msg = Std.string(e) + " (in "+StringTools.urlEncode(data)+")"; - __data.error(msg); // protocol error - return; - } - // request - if( request ) { - try proto.processRequest(data,__data.log) catch( e : Dynamic ) __data.error(e); - return; - } - // answer - var f = __data.results.pop(); - if( f == null ) { - __data.error("No response excepted ("+data+")"); - return; - } - var ret; - try { - ret = proto.processAnswer(data); - } catch( e : Dynamic ) { - f.onError(e); - return; - } - if( f.onResult != null ) f.onResult(ret); - } - - function defaultLog(path,args,e:Dynamic) { - // exception inside the called method - var astr, estr; - try astr = args.join(",") catch( e : Dynamic ) astr = "???"; - try estr = Std.string(e) catch( e : Dynamic ) estr = "???"; - var header = "Error in call to "+path.join(".")+"("+astr+") : "; - __data.error(header + estr); - } - - public static function create( s : Socket, ?ctx : Context ) { - var data = { - protocol : new SocketProtocol(s,ctx), - results : new List(), - error : function(e) throw e, - log : null, - #if js - queue : [], - timer : null, - #end - }; - var sc = new SocketConnection(data,[]); - data.log = sc.defaultLog; - #if flash - s.addEventListener(flash.events.DataEvent.DATA, function(e : flash.events.DataEvent) { - var data = e.data; - var msgLen = sc.__data.protocol.messageLength(data.charCodeAt(0),data.charCodeAt(1)); - if( msgLen == null || data.length != msgLen - 1 ) { - sc.__data.error("Invalid message header"); - return; - } - sc.processMessage(e.data.substr(2,e.data.length-2)); - }); - #elseif js - // we can't deliver directly the message - // since it might trigger a blocking action on JS side - // and in that case this will trigger a Flash bug - // where a new onData is called is a parallel thread - // ...with the buffer of the previous onData (!) - s.onData = function( data : String ) { - sc.__data.queue.push(function() { - var msgLen = sc.__data.protocol.messageLength(data.charCodeAt(0),data.charCodeAt(1)); - if( msgLen == null || data.length != msgLen - 1 ) { - sc.__data.error("Invalid message header"); - return; - } - sc.processMessage(data.substr(2,data.length-2)); - }); - if( sc.__data.timer == null ) { - sc.__data.timer = new haxe.Timer(1); - sc.__data.timer.run = function() { - var q = sc.__data.queue.shift(); - if( q == null ) { - sc.__data.timer.stop(); - sc.__data.timer = null; - return; - } - q(); - }; - } - }; - #end - return sc; - } - -} diff --git a/std/haxe/remoting/SocketProtocol.hx b/std/haxe/remoting/SocketProtocol.hx deleted file mode 100644 index 34d9bd19efd..00000000000 --- a/std/haxe/remoting/SocketProtocol.hx +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; - -typedef Socket = - #if flash - flash.net.XMLSocket - #elseif js - js.XMLSocket - #elseif sys - sys.net.Socket - #else - Dynamic - #end - -/** - The Haxe Remoting Socket Protocol is composed of serialized string exchanges. - Each string is prefixed with a 2-chars header encoding the string size (up to 4KB) - and postfixed with the `\0` message delimiting char. - - A request string is composed of the following serialized values : - - - the boolean true for a request - - an array of strings representing the object+method path - - an array of parameters - - A response string is composed of the following serialized values : - - - the boolean false for a response - - a serialized value representing the result - - Exceptions are serialized with `serializeException` so they will be thrown immediately - when they are unserialized. -**/ -class SocketProtocol { - - public var socket : Socket; - public var context : Context; - - public function new( sock, ctx ) { - this.socket = sock; - this.context = ctx; - } - - function decodeChar(c) : Null { - // A...Z - if( c >= 65 && c <= 90 ) - return c - 65; - // a...z - if( c >= 97 && c <= 122 ) - return c - 97 + 26; - // 0...9 - if( c >= 48 && c <= 57 ) - return c - 48 + 52; - // + - if( c == 43 ) - return 62; - // / - if( c == 47 ) - return 63; - return null; - } - - function encodeChar(c) : Null { - if( c < 0 ) - return null; - // A...Z - if( c < 26 ) - return c + 65; - // a...z - if( c < 52 ) - return (c - 26) + 97; - // 0...9 - if( c < 62 ) - return (c - 52) + 48; - // + - if( c == 62 ) - return 43; - // / - if( c == 63 ) - return 47; - return null; - } - - public function messageLength( c1 : Int, c2 : Int ) : Null { - var e1 = decodeChar(c1); - var e2 = decodeChar(c2); - if( e1 == null || e2 == null ) - return null; - return (e1 << 6) | e2; - } - - public function encodeMessageLength( len : Int ) { - var c1 = encodeChar(len>>6); - if( c1 == null ) - throw "Message is too big"; - var c2 = encodeChar(len&63); - return { c1 : c1, c2 : c2 }; - } - - public function sendRequest( path : Array, params : Array ) { - var s = new haxe.Serializer(); - s.serialize(true); - s.serialize(path); - s.serialize(params); - sendMessage(s.toString()); - } - - public function sendAnswer( answer : Dynamic, ?isException : Bool ) { - var s = new haxe.Serializer(); - s.serialize(false); - if( isException ) - s.serializeException(answer); - else - s.serialize(answer); - sendMessage(s.toString()); - } - - public function sendMessage( msg : String ) { - var e = encodeMessageLength(msg.length + 3); - #if sys - var o = socket.output; - o.writeByte(e.c1); - o.writeByte(e.c2); - o.writeString(msg); - o.writeByte(0); - #else - socket.send(String.fromCharCode(e.c1)+String.fromCharCode(e.c2)+msg); - #end - } - - public dynamic function decodeData( data : String ) { - return data; - } - - public function isRequest( data : String ) { - return switch( haxe.Unserializer.run(data) ) { - case true: true; - case false: false; - default: throw "Invalid data"; - } - } - - public function processRequest( data : String, ?onError : Array -> Array -> Dynamic -> Void ) { - var s = new haxe.Unserializer(data); - var result : Dynamic; - var isException = false; - if( s.unserialize() != true ) - throw "Not a request"; - var path : Array = s.unserialize(); - var args : Array = s.unserialize(); - try { - if( context == null ) throw "No context is shared"; - result = context.call(path,args); - } catch( e : Dynamic ) { - result = e; - isException = true; - } - // send back result/exception over network - sendAnswer(result,isException); - // send the error event - if( isException && onError != null ) - onError(path,args,result); - } - - public function processAnswer( data : String ) : Dynamic { - var s = new haxe.Unserializer(data); - if( s.unserialize() != false ) - throw "Not an answer"; - return s.unserialize(); - } - - #if sys - - public function readMessage() { - var i = socket.input; - var c1 = i.readByte(); - var c2 = i.readByte(); - var len = messageLength(c1,c2); - if( len == null ) - throw "Invalid header"; - var data = i.readString(len - 3); - if( i.readByte() != 0 ) - throw "Invalid message"; - return decodeData(data); - } - - #end - -} diff --git a/std/haxe/remoting/SocketWrapper.hx b/std/haxe/remoting/SocketWrapper.hx deleted file mode 100644 index c2bc67e9cfb..00000000000 --- a/std/haxe/remoting/SocketWrapper.hx +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; -import haxe.remoting.SocketProtocol.Socket; - -/** - @see `js.XMLSocket` -**/ -class SocketWrapper { - - static var ID = 0; - - static function create( prefix : String ) : String { - var id = prefix + "WrappedSocket"+(ID++); - var s = new Socket(); - var ctx = new Context(); - var cnx = haxe.remoting.ExternalConnection.jsConnect(id,ctx); - ctx.addObject("sock",s); - var o = {}; - Reflect.setField(o,"close",cnx.close); - ctx.addObject("api",o); - #if flash - var connected = false; - s.addEventListener(flash.events.Event.CONNECT,function(_) { - connected = true; - cnx.api.onConnect.call([true]); - }); - s.addEventListener(flash.events.SecurityErrorEvent.SECURITY_ERROR,function(_) { - if( connected ) - cnx.api.onClose.call([]); - else - cnx.api.onConnect.call([false]); - }); - s.addEventListener(flash.events.Event.CLOSE,function(_) { - cnx.api.onClose.call([]); - }); - s.addEventListener(flash.events.DataEvent.DATA,function(e:flash.events.DataEvent) { - cnx.api.onData.call([e.data]); - }); - #end - return id; - } - - static function init() { - if( !flash.external.ExternalInterface.available ) return null; - var ctx = new Context(); - var o = {}; - Reflect.setField(o,"create",create); - ctx.addObject("api",o); - haxe.remoting.ExternalConnection.jsConnect("SocketWrapper", ctx); - return null; - } - - static var _ = init(); - -} diff --git a/std/haxe/remoting/SyncSocketConnection.hx b/std/haxe/remoting/SyncSocketConnection.hx deleted file mode 100644 index 41cf2104997..00000000000 --- a/std/haxe/remoting/SyncSocketConnection.hx +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe.remoting; -import haxe.remoting.SocketProtocol.Socket; - -class SyncSocketConnection implements Connection implements Dynamic { - - var __path : Array; - var __proto : SocketProtocol; - - function new(proto,path) { - __proto = proto; - __path = path; - } - - public function resolve( name ) : Connection { - var s = new SyncSocketConnection(__proto,__path.copy()); - s.__path.push(name); - return s; - } - - public function call( params : Array ) : Dynamic { - var proto = __proto; - proto.sendRequest(__path,params); - while( true ) { - var data = proto.readMessage(); - if( proto.isRequest(data) ) { - if( proto.context == null ) - throw "Request received"; - proto.processRequest(data,onRequestError); - continue; - } - return proto.processAnswer(data); - } - } - - public function processRequest() { - if( __proto.context == null ) - throw "Can't process request"; - var data = __proto.readMessage(); - __proto.processRequest(data,onRequestError); - } - - public function onRequestError( path : Array, args : Array, exc : Dynamic ) { - } - - public function setProtocol( p : SocketProtocol ) { - __proto = p; - } - - public function getProtocol() : SocketProtocol { - return __proto; - } - - public function close() { - try __proto.socket.close() catch( e : Dynamic ) { }; - } - - public static function create( s : Socket, ?ctx : Context ) { - return new SyncSocketConnection(new SocketProtocol(s,ctx),[]); - } - -} diff --git a/std/haxe/rtti/CType.hx b/std/haxe/rtti/CType.hx index 13647b469f6..e2e4ecbd4eb 100644 --- a/std/haxe/rtti/CType.hx +++ b/std/haxe/rtti/CType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.rtti; import haxe.ds.List; @@ -26,30 +27,30 @@ import haxe.ds.List; /** The (dot-)path of the runtime type. **/ -typedef Path = String +typedef Path = String; /** A list of strings representing the targets where the type is available. **/ -typedef Platforms = Array +typedef Platforms = Array; /** The function argument runtime type information. **/ -typedef FunctionArgument = { name : String, opt : Bool, t : CType, ?value:String } +typedef FunctionArgument = {name:String, opt:Bool, t:CType, ?value:String}; /** The runtime member types. **/ enum CType { CUnknown; - CEnum( name : Path, params : Array ); - CClass( name : Path, params : Array ); - CTypedef( name : Path, params : Array ); - CFunction( args : Array, ret : CType ); - CAnonymous( fields : Array ); - CDynamic( ?t : CType ); - CAbstract( name : Path, params : Array ); + CEnum(name:Path, params:Array); + CClass(name:Path, params:Array); + CTypedef(name:Path, params:Array); + CFunction(args:Array, ret:CType); + CAnonymous(fields:Array); + CDynamic(?t:CType); + CAbstract(name:Path, params:Array); } /** @@ -59,19 +60,19 @@ typedef PathParams = { /** The path of the type. **/ - var path : Path; + var path:Path; /** The array of parameters types. **/ - var params : Array; -} + var params:Array; +}; /** An array of strings representing the names of the type parameters the type has. As of Haxe 3.2.0, this does not include the constraints. **/ -typedef TypeParams = Array // no constraints +typedef TypeParams = Array; // no constraints /** Represents the runtime rights of a type. @@ -79,7 +80,7 @@ typedef TypeParams = Array // no constraints enum Rights { RNormal; RNo; - RCall( m : String ); + RCall(m:String); RMethod; RDynamic; RInline; @@ -88,7 +89,7 @@ enum Rights { /** The list of runtime metadata. **/ -typedef MetaData = Array<{ name : String, params : Array }>; +typedef MetaData = Array<{name:String, params:Array}>; /** The runtime class field information. @@ -99,81 +100,81 @@ typedef ClassField = { /** The name of the field. **/ - var name : String; + var name:String; /** The type of the field. **/ - var type : CType; + var type:CType; /** Whether or not the field is public. **/ - var isPublic : Bool; + var isPublic:Bool; /** Whether or not the field is final. **/ - var isFinal : Bool; + var isFinal:Bool; /** Whether or not the field overrides another field. **/ - var isOverride : Bool; + var isOverride:Bool; /** The documentation of the field. This information is only available if the compiler flag `-D use_rtti_doc` was in place. Otherwise, or if the field has no documentation, the value is `null`. **/ - var doc : Null; + var doc:Null; /** The [read access](https://haxe.org/manual/dictionary.html#define-read-access) behavior of the field. **/ - var get : Rights; + var get:Rights; /** The [write access](https://haxe.org/manual/dictionary.html#define-write-access) behavior of the field. **/ - var set : Rights; + var set:Rights; /** An array of strings representing the names of the type parameters the field has. **/ - var params : TypeParams; + var params:TypeParams; /** A list of strings representing the targets where the field is available. **/ - var platforms : Platforms; + var platforms:Platforms; /** The meta data the field was annotated with. **/ - var meta : MetaData; + var meta:MetaData; /** The line number where the field is defined. This information is only available if the field has an expression. Otherwise the value is `null`. **/ - var line : Null; + var line:Null; /** The list of available overloads for the fields or `null` if no overloads exists. **/ - var overloads : Null>; + var overloads:Null>; /** The actual expression of the field or `null` if there is no expression. **/ - var expr : Null; -} + var expr:Null; +}; /** The general runtime type information. @@ -182,92 +183,92 @@ typedef TypeInfos = { /** The type path of the type. **/ - var path : Path; + var path:Path; /** The type path of the module containing the type. **/ - var module : Path; + var module:Path; /** The full slash path of the .hx file containing the type. This might be `null` in case there is no such file, e.g. if the type is defined through a macro. **/ - var file : Null; + var file:Null; /** An array of strings representing the names of the type parameters the type has. **/ - var params : TypeParams; + var params:TypeParams; /** The documentation of the type. This information is only available if the compiler flag `-D use_rtti_doc` was in place. Otherwise, or if the constructor has no documentation, the value is `null`. **/ - var doc : Null; + var doc:Null; /** Whether or not the type is [private](https://haxe.org/manual/dictionary.html#define-private-type). **/ - var isPrivate : Bool; + var isPrivate:Bool; /** A list of strings representing the targets where the type is available. **/ - var platforms : Platforms; + var platforms:Platforms; /** The [metadata](https://haxe.org/manual/lf-metadata.html) the type was annotated with. **/ - var meta : MetaData; -} + var meta:MetaData; +}; /** The runtime class definition information. **/ -typedef Classdef = {> TypeInfos, +typedef Classdef = TypeInfos & { /** Whether or not the class is [extern](https://haxe.org/manual/lf-externs.html). **/ - var isExtern : Bool; + var isExtern:Bool; /** Whether or not the class is actually an [interface](https://haxe.org/manual/types-interfaces.html). **/ - var isInterface : Bool; + var isInterface:Bool; /** The class' parent class defined by its type path and list of type parameters. **/ - var superClass : Null; + var superClass:Null; /** The list of interfaces defined by their type path and list of type parameters. **/ - var interfaces : Array; + var interfaces:Array; /** The list of member [class fields](https://haxe.org/manual/class-field.html). **/ - var fields : Array; + var fields:Array; /** The list of static class fields. **/ - var statics : Array; + var statics:Array; /** The type which is dynamically implemented by the class or `null` if no such type exists. **/ - var tdynamic : Null; -} + var tdynamic:Null; +}; /** The runtime enum constructor information. @@ -278,106 +279,111 @@ typedef EnumField = { /** The name of the constructor. **/ - var name : String; + var name:String; /** The list of arguments the constructor has or `null` if no arguments are available. **/ - var args : Null>; + var args:Null>; /** The documentation of the constructor. This information is only available if the compiler flag `-D use_rtti_doc` was in place. Otherwise, or if the constructor has no documentation, the value is `null`. **/ - var doc : String; + var doc:String; /** A list of strings representing the targets where the constructor is available. **/ - var platforms : Platforms; + var platforms:Platforms; /** The meta data the constructor was annotated with. **/ - var meta : MetaData; -} + var meta:MetaData; +}; /** The enum runtime type information. @see **/ -typedef Enumdef = {> TypeInfos, +typedef Enumdef = TypeInfos & { /** Whether or not the enum is [extern](https://haxe.org/manual/lf-externs.html). **/ - var isExtern : Bool; + var isExtern:Bool; /** The list of enum constructors. **/ - var constructors : Array; -} + var constructors:Array; +}; /** The typedef runtime information. **/ -typedef Typedef = {> TypeInfos, +typedef Typedef = TypeInfos & { /** The type of the typedef. **/ - var type : CType; + var type:CType; /** The types of the typedef, by platform. **/ - var types : Map; // by platform -} + var types:Map; // by platform + +}; /** The abstract type runtime information. @see **/ -typedef Abstractdef = {> TypeInfos, - var to : Array<{t:CType, field:Null}>; - var from : Array<{t:CType, field:Null}>; - var impl : Classdef; - var athis : CType; -} +typedef Abstractdef = TypeInfos & { + var to:Array<{t:CType, field:Null}>; + var from:Array<{t:CType, field:Null}>; + var impl:Classdef; + var athis:CType; +}; /** The tree types of the runtime type. **/ enum TypeTree { - TPackage( name : String, full : String, subs : Array ); - TClassdecl( c : Classdef ); - TEnumdecl( e : Enumdef ); - TTypedecl( t : Typedef ); - TAbstractdecl( a : Abstractdef ); + TPackage(name:String, full:String, subs:Array); + TClassdecl(c:Classdef); + TEnumdecl(e:Enumdef); + TTypedecl(t:Typedef); + TAbstractdecl(a:Abstractdef); } /** Array of `TypeTree`. **/ -typedef TypeRoot = Array +typedef TypeRoot = Array; /** Contains type and equality checks functionalities for RTTI. **/ class TypeApi { - - public static function typeInfos( t : TypeTree ) : TypeInfos { - var inf : TypeInfos; - switch( t ) { - case TClassdecl(c): inf = c; - case TEnumdecl(e): inf = e; - case TTypedecl(t): inf = t; - case TAbstractdecl(a): inf = a; - case TPackage(_,_,_): throw "Unexpected Package"; + public static function typeInfos(t:TypeTree):TypeInfos { + var inf:TypeInfos; + switch (t) { + case TClassdecl(c): + inf = c; + case TEnumdecl(e): + inf = e; + case TTypedecl(t): + inf = t; + case TAbstractdecl(a): + inf = a; + case TPackage(_, _, _): + throw "Unexpected Package"; } return inf; } @@ -386,23 +392,23 @@ class TypeApi { Returns `true` if the given `CType` is a variable or `false` if it is a function. **/ - public static function isVar( t : CType ) { - return switch( t ) { - case CFunction(_,_): false; - default: true; + public static function isVar(t:CType) { + return switch (t) { + case CFunction(_, _): false; + default: true; } } - static function leq( f : T -> T -> Bool, l1 : Array, l2 : Array ) { + static function leq(f:T->T->Bool, l1:Array, l2:Array) { var it = l2.iterator(); - for( e1 in l1 ) { - if( !it.hasNext() ) + for (e1 in l1) { + if (!it.hasNext()) return false; var e2 = it.next(); - if( !f(e1,e2) ) + if (!f(e1, e2)) return false; } - if( it.hasNext() ) + if (it.hasNext()) return false; return true; } @@ -413,17 +419,17 @@ class TypeApi { If `r1` or `r2` are `null`, the result is unspecified. **/ - public static function rightsEq( r1 : Rights, r2 : Rights ) { - if( r1 == r2 ) + public static function rightsEq(r1:Rights, r2:Rights) { + if (r1 == r2) return true; - switch( r1 ) { - case RCall(m1): - switch( r2 ) { - case RCall(m2): - return m1 == m2; + switch (r1) { + case RCall(m1): + switch (r2) { + case RCall(m2): + return m1 == m2; + default: + } default: - } - default: } return false; } @@ -434,55 +440,56 @@ class TypeApi { If `t1` or `t2` are `null`, the result is unspecified. **/ - public static function typeEq( t1 : CType, t2 : CType ) { - switch( t1 ) { - case CUnknown: return t2 == CUnknown; - case CEnum(name,params): - switch( t2 ) { - case CEnum(name2,params2): - return name == name2 && leq(typeEq,params,params2); - default: - } - case CClass(name,params): - switch( t2 ) { - case CClass(name2,params2): - return name == name2 && leq(typeEq,params,params2); - default: - } - case CAbstract(name,params): - switch( t2 ) { - case CAbstract(name2,params2): - return name == name2 && leq(typeEq,params,params2); - default: - } - case CTypedef(name,params): - switch( t2 ) { - case CTypedef(name2,params2): - return name == name2 && leq(typeEq,params,params2); - default: - } - case CFunction(args,ret): - switch( t2 ) { - case CFunction(args2,ret2): - return leq(function(a:FunctionArgument,b:FunctionArgument) { - return a.name == b.name && a.opt == b.opt && typeEq(a.t,b.t); - },args,args2) && typeEq(ret,ret2); - default: - } - case CAnonymous(fields): - switch( t2 ) { - case CAnonymous(fields2): - return leq(function(a,b) return fieldEq(a,b),fields,fields2); - default: - } - case CDynamic(t): - switch( t2 ) { - case CDynamic(t2): - if( (t == null) != (t2 == null) ) - return false; - return t == null || typeEq(t,t2); - default: - } + public static function typeEq(t1:CType, t2:CType) { + switch (t1) { + case CUnknown: + return t2 == CUnknown; + case CEnum(name, params): + switch (t2) { + case CEnum(name2, params2): + return name == name2 && leq(typeEq, params, params2); + default: + } + case CClass(name, params): + switch (t2) { + case CClass(name2, params2): + return name == name2 && leq(typeEq, params, params2); + default: + } + case CAbstract(name, params): + switch (t2) { + case CAbstract(name2, params2): + return name == name2 && leq(typeEq, params, params2); + default: + } + case CTypedef(name, params): + switch (t2) { + case CTypedef(name2, params2): + return name == name2 && leq(typeEq, params, params2); + default: + } + case CFunction(args, ret): + switch (t2) { + case CFunction(args2, ret2): + return leq(function(a:FunctionArgument, b:FunctionArgument) { + return a.name == b.name && a.opt == b.opt && typeEq(a.t, b.t); + }, args, args2) && typeEq(ret, ret2); + default: + } + case CAnonymous(fields): + switch (t2) { + case CAnonymous(fields2): + return leq(function(a, b) return fieldEq(a, b), fields, fields2); + default: + } + case CDynamic(t): + switch (t2) { + case CDynamic(t2): + if ((t == null) != (t2 == null)) + return false; + return t == null || typeEq(t, t2); + default: + } } return false; } @@ -493,22 +500,22 @@ class TypeApi { If `f1` or `f2` are `null`, the result is unspecified. **/ - public static function fieldEq( f1 : ClassField, f2 : ClassField ) { - if( f1.name != f2.name ) + public static function fieldEq(f1:ClassField, f2:ClassField) { + if (f1.name != f2.name) return false; - if( !typeEq(f1.type,f2.type) ) + if (!typeEq(f1.type, f2.type)) return false; - if( f1.isPublic != f2.isPublic ) + if (f1.isPublic != f2.isPublic) return false; - if( f1.doc != f2.doc ) + if (f1.doc != f2.doc) return false; - if( !rightsEq(f1.get,f2.get) ) + if (!rightsEq(f1.get, f2.get)) return false; - if( !rightsEq(f1.set,f2.set) ) + if (!rightsEq(f1.set, f2.set)) return false; - if( (f1.params == null) != (f2.params == null) ) + if ((f1.params == null) != (f2.params == null)) return false; - if( f1.params != null && f1.params.join(":") != f2.params.join(":") ) + if (f1.params != null && f1.params.join(":") != f2.params.join(":")) return false; return true; } @@ -519,18 +526,19 @@ class TypeApi { If `c1` or `c2` are `null`, the result is unspecified. **/ - public static function constructorEq( c1 : EnumField, c2: EnumField ) { - if( c1.name != c2.name ) + public static function constructorEq(c1:EnumField, c2:EnumField) { + if (c1.name != c2.name) return false; - if( c1.doc != c2.doc ) + if (c1.doc != c2.doc) return false; - if( (c1.args == null) != (c2.args == null) ) + if ((c1.args == null) != (c2.args == null)) return false; - if( c1.args != null && !leq(function(a,b) { return a.name == b.name && a.opt == b.opt && typeEq(a.t,b.t); },c1.args,c2.args) ) + if (c1.args != null && !leq(function(a, b) { + return a.name == b.name && a.opt == b.opt && typeEq(a.t, b.t); + }, c1.args, c2.args)) return false; return true; } - } /** @@ -549,9 +557,9 @@ class CTypeTools { nameWithParams(name, params); case CFunction(args, ret): if (args.length == 0) { - "Void -> " +toString(ret); + "Void -> " + toString(ret); } else { - args.map(functionArgumentName).join(" -> ")+" -> "+toString(ret); + args.map(functionArgumentName).join(" -> ") + " -> " + toString(ret); } case CDynamic(d): if (d == null) { @@ -560,7 +568,7 @@ class CTypeTools { "Dynamic<" + toString(d) + ">"; } case CAnonymous(fields): - "{ " + fields.map(classField).join(", "); + "{ " + fields.map(classField).join(", ") + "}"; } } @@ -572,10 +580,13 @@ class CTypeTools { } static function functionArgumentName(arg:FunctionArgument) { - return (arg.opt ? "?" : "") + (arg.name == "" ? "" : arg.name + ":") + toString(arg.t) + (arg.value == null ? "" : " = " +arg.value); + return (arg.opt ? "?" : "") + + (arg.name == "" ? "" : arg.name + ":") + + toString(arg.t) + + (arg.value == null ? "" : " = " + arg.value); } static function classField(cf:ClassField) { - return cf.name + ":" +toString(cf.type); + return cf.name + ":" + toString(cf.type); } -} \ No newline at end of file +} diff --git a/std/haxe/rtti/Meta.hx b/std/haxe/rtti/Meta.hx index fd2cd6305ba..adca8dc0c23 100644 --- a/std/haxe/rtti/Meta.hx +++ b/std/haxe/rtti/Meta.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.rtti; private typedef MetaObject = { ?fields:Dynamic>>>, ?statics:Dynamic>>>, - ?obj:Dynamic>>, -} + ?obj:Dynamic>> +}; /** An API to access classes and enums metadata at runtime. @@ -33,11 +34,10 @@ private typedef MetaObject = { @see **/ class Meta { - /** Returns the metadata that were declared for the given type (class or enum) **/ - public static function getType( t : Dynamic ) : Dynamic> { + public static function getType(t:Dynamic):Dynamic> { var meta = getMeta(t); return (meta == null || meta.obj == null) ? {} : meta.obj; } @@ -45,44 +45,42 @@ class Meta { // Could move this to Type.hx? private static function isInterface(t:Dynamic):Bool { #if java - return java.Lib.toNativeType(t).isInterface(); + return java.Lib.toNativeType(t).isInterface(); #elseif cs - return cs.Lib.toNativeType(t).IsInterface; + return cs.Lib.toNativeType(t).IsInterface; #elseif (flash && as3) - return untyped flash.Lib.describeType(t).factory.extendsClass.length() == 0; + return untyped flash.Lib.describeType(t).factory.extendsClass.length() == 0; #else - throw "Something went wrong"; + throw "Something went wrong"; #end } private static function getMeta(t:Dynamic):MetaObject { #if php - return php.Boot.getMeta(t.phpClassName); + return php.Boot.getMeta(t.phpClassName); #elseif (java || cs || (flash && as3)) - var ret = Reflect.field(t, "__meta__"); - if (ret == null && Std.is(t,Class)) - { - if (isInterface(t)) - { - var name = Type.getClassName(t), - cls = Type.resolveClass(name + '_HxMeta'); - if (cls != null) - return Reflect.field(cls, "__meta__"); - } + var ret = Reflect.field(t, "__meta__"); + if (ret == null && Std.is(t, Class)) { + if (isInterface(t)) { + var name = Type.getClassName(t), + cls = Type.resolveClass(name + '_HxMeta'); + if (cls != null) + return Reflect.field(cls, "__meta__"); } - return ret; + } + return ret; #elseif hl - var t : hl.BaseType = t; - return t.__meta__; + var t:hl.BaseType = t; + return t.__meta__; #else - return untyped t.__meta__; + return untyped t.__meta__; #end } /** Returns the metadata that were declared for the given class static fields **/ - public static function getStatics( t : Dynamic ) : Dynamic>> { + public static function getStatics(t:Dynamic):Dynamic>> { var meta = getMeta(t); return (meta == null || meta.statics == null) ? {} : meta.statics; } @@ -90,9 +88,8 @@ class Meta { /** Returns the metadata that were declared for the given class fields or enum constructors **/ - public static function getFields( t : Dynamic ) : Dynamic>> { + public static function getFields(t:Dynamic):Dynamic>> { var meta = getMeta(t); return (meta == null || meta.fields == null) ? {} : meta.fields; } - } diff --git a/std/haxe/rtti/Rtti.hx b/std/haxe/rtti/Rtti.hx index 65c8b494840..958e28c076c 100644 --- a/std/haxe/rtti/Rtti.hx +++ b/std/haxe/rtti/Rtti.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,6 +21,7 @@ */ package haxe.rtti; + import haxe.rtti.CType; /** @@ -29,14 +30,13 @@ import haxe.rtti.CType; @see **/ class Rtti { - /** Returns the `haxe.rtti.CType.Classdef` corresponding to class `c`. - If `c` has no runtime type information, e.g. because no `@:rtti@` was - added, `null` is returned. + If `c` has no runtime type information, e.g. because no `@:rtti` was + added, an exception of type `String` is thrown. - If `c` is null, the result is unspecified. + If `c` is `null`, the result is unspecified. **/ static public function getRtti(c:Class):Classdef { var rtti = Reflect.field(c, "__rtti"); @@ -46,17 +46,19 @@ class Rtti { var x = Xml.parse(rtti).firstElement(); var infos = new haxe.rtti.XmlParser().processElement(x); switch (infos) { - case TClassdecl(c): return c; - case var t: throw 'Enum mismatch: expected TClassDecl but found $t'; + case TClassdecl(c): + return c; + case var t: + throw 'Enum mismatch: expected TClassDecl but found $t'; } } /** Tells if `c` has runtime type information. - If `c` is null, the result is unspecified. + If `c` is `null`, the result is unspecified. **/ static public function hasRtti(c:Class):Bool { return Lambda.has(Type.getClassFields(c), "__rtti"); } -} \ No newline at end of file +} diff --git a/std/haxe/rtti/XmlParser.hx b/std/haxe/rtti/XmlParser.hx index 64ad9d22584..7773fbef7f0 100644 --- a/std/haxe/rtti/XmlParser.hx +++ b/std/haxe/rtti/XmlParser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,9 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.rtti; + import haxe.rtti.CType; -import haxe.xml.Fast; +import haxe.xml.Access; /** XmlParser processes the runtime type information (RTTI) which @@ -30,67 +32,69 @@ import haxe.xml.Fast; @see **/ class XmlParser { + public var root:TypeRoot; - public var root : TypeRoot; - var curplatform : String; + var curplatform:String; public function new() { root = new Array(); } - public function sort( ?l:TypeRoot ) { - if( l == null ) l = root; - l.sort(function(e1,e2) { + public function sort(?l:TypeRoot) { + if (l == null) + l = root; + l.sort(function(e1, e2) { var n1 = switch e1 { - case TPackage(p,_,_) : " "+p; + case TPackage(p, _, _): " " + p; default: TypeApi.typeInfos(e1).path; }; var n2 = switch e2 { - case TPackage(p,_,_) : " "+p; + case TPackage(p, _, _): " " + p; default: TypeApi.typeInfos(e2).path; }; - if( n1 > n2 ) + if (n1 > n2) return 1; return -1; }); - for( x in l ) - switch( x ) { - case TPackage(_,_,l): sort(l); - case TClassdecl(c): - sortFields(c.fields); - sortFields(c.statics); - case TEnumdecl(_): - case TAbstractdecl(_): - case TTypedecl(_): + for (x in l) + switch (x) { + case TPackage(_, _, l): + sort(l); + case TClassdecl(c): + sortFields(c.fields); + sortFields(c.statics); + case TEnumdecl(_): + case TAbstractdecl(_): + case TTypedecl(_): } } function sortFields(a:Array) { - a.sort(function(f1 : ClassField,f2 : ClassField) { + a.sort(function(f1:ClassField, f2:ClassField) { var v1 = TypeApi.isVar(f1.type); var v2 = TypeApi.isVar(f2.type); - if( v1 && !v2 ) + if (v1 && !v2) return -1; - if( v2 && !v1 ) + if (v2 && !v1) return 1; - if( f1.name == "new" ) + if (f1.name == "new") return -1; - if( f2.name == "new" ) + if (f2.name == "new") return 1; - if( f1.name > f2.name ) + if (f1.name > f2.name) return 1; return -1; }); } - public function process( x : Xml, platform : String ) { + public function process(x:Xml, platform:String) { curplatform = platform; - xroot(new Fast(x)); + xroot(new Access(x)); } // merge inline and not inline - function mergeRights( f1 : ClassField, f2 : ClassField ) { - if( f1.get == RInline && f1.set == RNo && f2.get == RNormal && f2.set == RMethod ) { + function mergeRights(f1:ClassField, f2:ClassField) { + if (f1.get == RInline && f1.set == RNo && f2.get == RNormal && f2.set == RMethod) { f1.get = RNormal; f1.set = RMethod; return true; @@ -98,266 +102,268 @@ class XmlParser { return Type.enumEq(f1.get, f2.get) && Type.enumEq(f1.set, f2.set); } - function mergeDoc( f1 : ClassField, f2 : ClassField ) { - if( f1.doc == null ) + function mergeDoc(f1:ClassField, f2:ClassField) { + if (f1.doc == null) f1.doc = f2.doc; - else if( f2.doc == null ) + else if (f2.doc == null) f2.doc = f1.doc; return true; } - function mergeFields( f : ClassField, f2 : ClassField ) { - return TypeApi.fieldEq(f,f2) || (f.name == f2.name && (mergeRights(f,f2) || mergeRights(f2,f)) && mergeDoc(f,f2) && TypeApi.fieldEq(f,f2)); + function mergeFields(f:ClassField, f2:ClassField) { + return TypeApi.fieldEq(f, f2) + || (f.name == f2.name && (mergeRights(f, f2) || mergeRights(f2, f)) && mergeDoc(f, f2) && TypeApi.fieldEq(f, f2)); } - public dynamic function newField( c : Classdef, f : ClassField ) { - } + public dynamic function newField(c:Classdef, f:ClassField) {} - function mergeClasses( c : Classdef, c2 : Classdef ) { + function mergeClasses(c:Classdef, c2:Classdef) { // todo : compare supers & interfaces - if( c.isInterface != c2.isInterface ) + if (c.isInterface != c2.isInterface) return false; - if( curplatform != null ) + if (curplatform != null) c.platforms.push(curplatform); - if( c.isExtern != c2.isExtern ) + if (c.isExtern != c2.isExtern) c.isExtern = false; - for( f2 in c2.fields ) { + for (f2 in c2.fields) { var found = null; - for( f in c.fields ) - if( mergeFields(f,f2) ) { + for (f in c.fields) + if (mergeFields(f, f2)) { found = f; break; } - if( found == null ) { - newField(c,f2); + if (found == null) { + newField(c, f2); c.fields.push(f2); - } else if( curplatform != null ) + } else if (curplatform != null) found.platforms.push(curplatform); } - for( f2 in c2.statics ) { + for (f2 in c2.statics) { var found = null; - for( f in c.statics ) - if( mergeFields(f,f2) ) { + for (f in c.statics) + if (mergeFields(f, f2)) { found = f; break; } - if( found == null ) { - newField(c,f2); + if (found == null) { + newField(c, f2); c.statics.push(f2); - } else if( curplatform != null ) + } else if (curplatform != null) found.platforms.push(curplatform); } return true; } - function mergeEnums( e : Enumdef, e2 : Enumdef ) { - if( e.isExtern != e2.isExtern ) + function mergeEnums(e:Enumdef, e2:Enumdef) { + if (e.isExtern != e2.isExtern) return false; - if( curplatform != null ) + if (curplatform != null) e.platforms.push(curplatform); - for( c2 in e2.constructors ) { + for (c2 in e2.constructors) { var found = null; - for( c in e.constructors ) - if( TypeApi.constructorEq(c,c2) ) { + for (c in e.constructors) + if (TypeApi.constructorEq(c, c2)) { found = c; break; } - if( found == null ) + if (found == null) return false; // don't allow by-platform constructor ? - if( curplatform != null ) + if (curplatform != null) found.platforms.push(curplatform); } return true; } - function mergeTypedefs( t : Typedef, t2 : Typedef ) { - if( curplatform == null ) + function mergeTypedefs(t:Typedef, t2:Typedef) { + if (curplatform == null) return false; t.platforms.push(curplatform); - t.types.set(curplatform,t2.type); + t.types.set(curplatform, t2.type); return true; } - function mergeAbstracts( a : Abstractdef, a2 : Abstractdef ) { - if( curplatform == null ) + function mergeAbstracts(a:Abstractdef, a2:Abstractdef) { + if (curplatform == null) return false; - if( a.to.length != a2.to.length || a.from.length != a2.from.length ) + if (a.to.length != a2.to.length || a.from.length != a2.from.length) return false; - for( i in 0...a.to.length ) - if( !TypeApi.typeEq(a.to[i].t,a2.to[i].t) ) + for (i in 0...a.to.length) + if (!TypeApi.typeEq(a.to[i].t, a2.to[i].t)) return false; - for( i in 0...a.from.length ) - if( !TypeApi.typeEq(a.from[i].t,a2.from[i].t) ) + for (i in 0...a.from.length) + if (!TypeApi.typeEq(a.from[i].t, a2.from[i].t)) return false; - if (a2.impl != null) mergeClasses(a.impl, a2.impl); + if (a2.impl != null) + mergeClasses(a.impl, a2.impl); a.platforms.push(curplatform); return true; } - function merge( t : TypeTree ) { + function merge(t:TypeTree) { var inf = TypeApi.typeInfos(t); var pack = inf.path.split("."); var cur = root; var curpack = new Array(); pack.pop(); - for( p in pack ) { + for (p in pack) { var found = false; - for( pk in cur ) - switch( pk ) { - case TPackage(pname,_,subs): - if( pname == p ) { - found = true; - cur = subs; - break; - } - default: + for (pk in cur) + switch (pk) { + case TPackage(pname, _, subs): + if (pname == p) { + found = true; + cur = subs; + break; + } + default: } curpack.push(p); - if( !found ) { + if (!found) { var pk = new Array(); - cur.push(TPackage(p,curpack.join("."),pk)); + cur.push(TPackage(p, curpack.join("."), pk)); cur = pk; } } - var prev = null; - for( ct in cur ) { - var tinf; - try - tinf = TypeApi.typeInfos(ct) - catch( e : Dynamic ) + for (ct in cur) { + if (ct.match(TPackage(_))) continue; + var tinf = TypeApi.typeInfos(ct); + // compare params ? - if( tinf.path == inf.path ) { + if (tinf.path == inf.path) { var sameType = true; - if( (tinf.doc == null) != (inf.doc == null) ) { - if( inf.doc == null ) + if ((tinf.doc == null) != (inf.doc == null)) { + if (inf.doc == null) inf.doc = tinf.doc; else tinf.doc = inf.doc; } - if (tinf.path == "haxe._Int64.NativeInt64") continue; - if( tinf.module == inf.module && tinf.doc == inf.doc && tinf.isPrivate == inf.isPrivate ) - switch( ct ) { - case TClassdecl(c): - switch( t ) { - case TClassdecl(c2): - if( mergeClasses(c,c2) ) - return; - default: - sameType = false; - } - case TEnumdecl(e): - switch( t ) { - case TEnumdecl(e2): - if( mergeEnums(e,e2) ) - return; - default: - sameType = false; - } - case TTypedecl(td): - switch( t ) { - case TTypedecl(td2): - if( mergeTypedefs(td,td2) ) - return; - default: - } - case TAbstractdecl(a): - switch( t ) { - case TAbstractdecl(a2): - if( mergeAbstracts(a,a2) ) - return; - default: + if (tinf.path == "haxe._Int64.NativeInt64") + continue; + if (tinf.module == inf.module && tinf.doc == inf.doc && tinf.isPrivate == inf.isPrivate) + switch (ct) { + case TClassdecl(c): + switch (t) { + case TClassdecl(c2): + if (mergeClasses(c, c2)) + return; + default: + sameType = false; + } + case TEnumdecl(e): + switch (t) { + case TEnumdecl(e2): + if (mergeEnums(e, e2)) + return; + default: + sameType = false; + } + case TTypedecl(td): + switch (t) { + case TTypedecl(td2): + if (mergeTypedefs(td, td2)) + return; + default: + } + case TAbstractdecl(a): + switch (t) { + case TAbstractdecl(a2): + if (mergeAbstracts(a, a2)) + return; + default: + sameType = false; + } + case TPackage(_, _, _): sameType = false; - } - case TPackage(_,_,_): - sameType = false; } // we already have a mapping, but which is incompatible - var msg = if( tinf.module != inf.module ) "module "+inf.module+" should be "+tinf.module; - else if( tinf.doc != inf.doc ) "documentation is different"; - else if( tinf.isPrivate != inf.isPrivate ) "private flag is different"; - else if( !sameType ) "type kind is different"; - else "could not merge definition"; - throw "Incompatibilities between "+tinf.path+" in "+tinf.platforms.join(",")+" and "+curplatform+" ("+msg+")"; + var msg = if (tinf.module != inf.module) "module " + inf.module + " should be " + tinf.module; else if (tinf.doc != inf.doc) + "documentation is different"; + else if (tinf.isPrivate != inf.isPrivate) + "private flag is different"; + else if (!sameType) + "type kind is different"; + else + "could not merge definition"; + throw "Incompatibilities between " + tinf.path + " in " + tinf.platforms.join(",") + " and " + curplatform + " (" + msg + ")"; } } cur.push(t); } - function mkPath( p : String ) : Path { + function mkPath(p:String):Path { return p; } - function mkTypeParams( p : String ) : TypeParams { + function mkTypeParams(p:String):TypeParams { var pl = p.split(":"); - if( pl[0] == "" ) + if (pl[0] == "") return new Array(); return pl; } - function mkRights( r : String ) : Rights { - return switch( r ) { - case "null": RNo; - case "method": RMethod; - case "dynamic": RDynamic; - case "inline": RInline; - default: RCall(r); + function mkRights(r:String):Rights { + return switch (r) { + case "null": RNo; + case "method": RMethod; + case "dynamic": RDynamic; + case "inline": RInline; + default: RCall(r); } } - function xerror( c : Fast ) : Dynamic { - return throw "Invalid "+c.name; + function xerror(c:Access):Dynamic { + return throw "Invalid " + c.name; } - function xroot( x : Fast ) { - for( c in x.x.elements() ) + function xroot(x:Access) { + for (c in x.x.elements()) merge(processElement(c)); - } - public function processElement( x : Xml ) { - var c = new haxe.xml.Fast(x); - return switch( c.name ) { - case "class": TClassdecl(xclass(c)); - case "enum": TEnumdecl(xenum(c)); - case "typedef": TTypedecl(xtypedef(c)); - case "abstract": TAbstractdecl(xabstract(c)); - default: xerror(c); + public function processElement(x:Xml) { + var c = new haxe.xml.Access(x); + return switch (c.name) { + case "class": TClassdecl(xclass(c)); + case "enum": TEnumdecl(xenum(c)); + case "typedef": TTypedecl(xtypedef(c)); + case "abstract": TAbstractdecl(xabstract(c)); + default: xerror(c); } } - function xmeta( x : Fast ) : MetaData { + function xmeta(x:Access):MetaData { var ml = []; - for( m in x.nodes.m ) { + for (m in x.nodes.m) { var pl = []; - for( p in m.nodes.e ) + for (p in m.nodes.e) pl.push(p.innerHTML); - ml.push({ name : m.att.n, params : pl }); + ml.push({name: m.att.n, params: pl}); } return ml; } - function xoverloads( x : Fast ) : Array { + function xoverloads(x:Access):Array { var l = new Array(); - for ( m in x.elements ) { + for (m in x.elements) { l.push(xclassfield(m)); } return l; } - function xpath( x : Fast ) : PathParams { + function xpath(x:Access):PathParams { var path = mkPath(x.att.path); var params = new Array(); - for( c in x.elements ) + for (c in x.elements) params.push(xtype(c)); return { - path : path, - params : params, + path: path, + params: params, }; } - function xclass( x : Fast ) : Classdef { + function xclass(x:Access):Classdef { var csuper = null; var doc = null; var tdynamic = null; @@ -365,259 +371,261 @@ class XmlParser { var fields = new Array(); var statics = new Array(); var meta = []; - for( c in x.elements ) - switch( c.name ) { - case "haxe_doc": doc = c.innerData; - case "extends": csuper = xpath(c); - case "implements": interfaces.push(xpath(c)); - case "haxe_dynamic": tdynamic = xtype(new Fast(c.x.firstElement())); - case "meta": meta = xmeta(c); - default: - if( c.x.exists("static") ) - statics.push(xclassfield(c)); - else - fields.push(xclassfield(c)); + for (c in x.elements) + switch (c.name) { + case "haxe_doc": + doc = c.innerData; + case "extends": + csuper = xpath(c); + case "implements": + interfaces.push(xpath(c)); + case "haxe_dynamic": + tdynamic = xtype(new Access(c.x.firstElement())); + case "meta": + meta = xmeta(c); + default: + if (c.x.exists("static")) + statics.push(xclassfield(c)); + else + fields.push(xclassfield(c)); } return { - file : if(x.has.file) x.att.file else null, - path : mkPath(x.att.path), - module : if( x.has.module ) mkPath(x.att.module) else null, - doc : doc, - isPrivate : x.x.exists("private"), - isExtern : x.x.exists("extern"), - isInterface : x.x.exists("interface"), - params : mkTypeParams(x.att.params), - superClass : csuper, - interfaces : interfaces, - fields : fields, - statics : statics, - tdynamic : tdynamic, - platforms : defplat(), - meta : meta, + file: if (x.has.file) x.att.file else null, + path: mkPath(x.att.path), + module: if (x.has.module) mkPath(x.att.module) else null, + doc: doc, + isPrivate: x.x.exists("private"), + isExtern: x.x.exists("extern"), + isInterface: x.x.exists("interface"), + params: mkTypeParams(x.att.params), + superClass: csuper, + interfaces: interfaces, + fields: fields, + statics: statics, + tdynamic: tdynamic, + platforms: defplat(), + meta: meta, }; } - function xclassfield( x : Fast, ?defPublic = false ) : ClassField { + function xclassfield(x:Access, ?defPublic = false):ClassField { var e = x.elements; var t = xtype(e.next()); var doc = null; var meta = []; var overloads = null; - for( c in e ) - switch( c.name ) { - case "haxe_doc": doc = c.innerData; - case "meta": meta = xmeta(c); - case "overloads": overloads = xoverloads(c); - default: xerror(c); + for (c in e) + switch (c.name) { + case "haxe_doc": + doc = c.innerData; + case "meta": + meta = xmeta(c); + case "overloads": + overloads = xoverloads(c); + default: + xerror(c); } return { - name : x.name, - type : t, - isPublic : x.x.exists("public") || defPublic, - isFinal : x.x.exists("final"), - isOverride : x.x.exists("override"), - line : if( x.has.line ) Std.parseInt(x.att.line) else null, - doc : doc, - get : if( x.has.get ) mkRights(x.att.get) else RNormal, - set : if( x.has.set ) mkRights(x.att.set) else RNormal, - params : if( x.has.params ) mkTypeParams(x.att.params) else [], - platforms : defplat(), - meta : meta, - overloads: overloads, - expr : if( x.has.expr ) x.att.expr else null + name:x.name, type:t, isPublic:x.x.exists("public") || defPublic, isFinal:x.x.exists("final"), isOverride:x.x.exists("override"), + line:if (x.has.line) Std.parseInt(x.att.line) else null, doc:doc, get:if (x.has.get) mkRights(x.att.get) else RNormal, set:if (x.has.set) + mkRights(x.att.set) + else + RNormal, params:if (x.has.params) mkTypeParams(x.att.params) else [], platforms:defplat(), meta:meta, overloads:overloads, expr:if (x.has.expr) + x.att.expr + else + null }; } - function xenum( x : Fast ) : Enumdef { + function xenum(x:Access):Enumdef { var cl = new Array(); var doc = null; var meta = []; - for( c in x.elements ) - if( c.name == "haxe_doc" ) + for (c in x.elements) + if (c.name == "haxe_doc") doc = c.innerData; - else if ( c.name == "meta" ) + else if (c.name == "meta") meta = xmeta(c); else cl.push(xenumfield(c)); return { - file : if(x.has.file) x.att.file else null, - path : mkPath(x.att.path), - module : if( x.has.module ) mkPath(x.att.module) else null, - doc : doc, - isPrivate : x.x.exists("private"), - isExtern : x.x.exists("extern"), - params : mkTypeParams(x.att.params), - constructors : cl, - platforms : defplat(), - meta : meta, + file: if (x.has.file) x.att.file else null, + path: mkPath(x.att.path), + module: if (x.has.module) mkPath(x.att.module) else null, + doc: doc, + isPrivate: x.x.exists("private"), + isExtern: x.x.exists("extern"), + params: mkTypeParams(x.att.params), + constructors: cl, + platforms: defplat(), + meta: meta, }; } - function xenumfield( x : Fast ) : EnumField { + function xenumfield(x:Access):EnumField { var args = null; - var xdoc = x.x.elementsNamed("haxe_doc").next(); - var meta = if( x.hasNode.meta ) xmeta(x.node.meta) else []; - if( x.has.a ) { + var docElements = x.x.elementsNamed("haxe_doc"); + var xdoc = if (docElements.hasNext()) docElements.next() else null; + var meta = if (x.hasNode.meta) xmeta(x.node.meta) else []; + if (x.has.a) { var names = x.att.a.split(":"); var elts = x.elements; args = new Array(); - for( c in names ) { + for (c in names) { var opt = false; - if( c.charAt(0) == "?" ) { + if (c.charAt(0) == "?") { opt = true; c = c.substr(1); } args.push({ - name : c, - opt : opt, - t : xtype(elts.next()), + name: c, + opt: opt, + t: xtype(elts.next()), }); } } return { - name : x.name, - args : args, - doc : if( xdoc == null ) null else new Fast(xdoc).innerData, - meta : meta, - platforms : defplat(), + name: x.name, + args: args, + doc: if (xdoc == null) null else new Access(xdoc).innerData, + meta: meta, + platforms: defplat(), }; } - function xabstract( x : Fast ) : Abstractdef { + function xabstract(x:Access):Abstractdef { var doc = null, impl = null, athis = null; var meta = [], to = [], from = []; - for( c in x.elements ) - switch( c.name ) { - case "haxe_doc": - doc = c.innerData; - case "meta": - meta = xmeta(c); - case "to": - for( t in c.elements ) - to.push({t: xtype(new Fast(t.x.firstElement())), field: t.has.field ? t.att.field : null}); - case "from": - for( t in c.elements ) - from.push({t: xtype(new Fast(t.x.firstElement())), field: t.has.field ? t.att.field : null}); - case "impl": - impl = xclass(c.node.resolve("class")); - case "this": - athis = xtype(new Fast(c.x.firstElement())); - default: - xerror(c); + for (c in x.elements) + switch (c.name) { + case "haxe_doc": + doc = c.innerData; + case "meta": + meta = xmeta(c); + case "to": + for (t in c.elements) + to.push({t: xtype(new Access(t.x.firstElement())), field: t.has.field ? t.att.field : null}); + case "from": + for (t in c.elements) + from.push({t: xtype(new Access(t.x.firstElement())), field: t.has.field ? t.att.field : null}); + case "impl": + impl = xclass(c.node.resolve("class")); + case "this": + athis = xtype(new Access(c.x.firstElement())); + default: + xerror(c); } return { - file : if(x.has.file) x.att.file else null, - path : mkPath(x.att.path), - module : if( x.has.module ) mkPath(x.att.module) else null, - doc : doc, - isPrivate : x.x.exists("private"), - params : mkTypeParams(x.att.params), - platforms : defplat(), - meta : meta, - athis : athis, - to : to, - from : from, + file: if (x.has.file) x.att.file else null, + path: mkPath(x.att.path), + module: if (x.has.module) mkPath(x.att.module) else null, + doc: doc, + isPrivate: x.x.exists("private"), + params: mkTypeParams(x.att.params), + platforms: defplat(), + meta: meta, + athis: athis, + to: to, + from: from, impl: impl }; } - - function xtypedef( x : Fast ) : Typedef { + function xtypedef(x:Access):Typedef { var doc = null; var t = null; var meta = []; - for( c in x.elements ) - if( c.name == "haxe_doc" ) + for (c in x.elements) + if (c.name == "haxe_doc") doc = c.innerData; - else if ( c.name == "meta" ) + else if (c.name == "meta") meta = xmeta(c); else t = xtype(c); var types = new haxe.ds.StringMap(); - if( curplatform != null ) - types.set(curplatform,t); + if (curplatform != null) + types.set(curplatform, t); return { - file : if(x.has.file) x.att.file else null, - path : mkPath(x.att.path), - module : if( x.has.module ) mkPath(x.att.module) else null, - doc : doc, - isPrivate : x.x.exists("private"), - params : mkTypeParams(x.att.params), - type : t, - types : types, - platforms : defplat(), - meta : meta, + file: if (x.has.file) x.att.file else null, + path: mkPath(x.att.path), + module: if (x.has.module) mkPath(x.att.module) else null, + doc: doc, + isPrivate: x.x.exists("private"), + params: mkTypeParams(x.att.params), + type: t, + types: types, + platforms: defplat(), + meta: meta, }; } - function xtype( x : Fast ) : CType { - return switch( x.name ) { - case "unknown": - CUnknown; - case "e": - CEnum(mkPath(x.att.path),xtypeparams(x)); - case "c": - CClass(mkPath(x.att.path),xtypeparams(x)); - case "t": - CTypedef(mkPath(x.att.path),xtypeparams(x)); - case "x": - CAbstract(mkPath(x.att.path),xtypeparams(x)); - case "f": - var args = new Array(); - var aname = x.att.a.split(":"); - var eargs = aname.iterator(); - var evalues = x.has.v ? x.att.v.split(":").iterator() : null; - for( e in x.elements ) { - var opt = false; - var a = eargs.next(); - if( a == null ) - a = ""; - if( a.charAt(0) == "?" ) { - opt = true; - a = a.substr(1); + function xtype(x:Access):CType { + return switch (x.name) { + case "unknown": + CUnknown; + case "e": + CEnum(mkPath(x.att.path), xtypeparams(x)); + case "c": + CClass(mkPath(x.att.path), xtypeparams(x)); + case "t": + CTypedef(mkPath(x.att.path), xtypeparams(x)); + case "x": + CAbstract(mkPath(x.att.path), xtypeparams(x)); + case "f": + var args = new Array(); + var aname = x.att.a.split(":"); + var eargs = aname.iterator(); + var evalues = x.has.v ? x.att.v.split(":").iterator() : null; + for (e in x.elements) { + var opt = false; + var a = eargs.hasNext() ? eargs.next() : null; + if (a == null) + a = ""; + if (a.charAt(0) == "?") { + opt = true; + a = a.substr(1); + } + var v = evalues == null || !evalues.hasNext() ? null : evalues.next(); + args.push({ + name: a, + opt: opt, + t: xtype(e), + value: v == "" ? null : v + }); } - var v = evalues == null ? null : evalues.next(); - args.push({ - name : a, - opt : opt, - t : xtype(e), - value : v == "" ? null : v - }); - } - var ret = args[args.length - 1]; - args.remove(ret); - CFunction(args,ret.t); - case "a": - var fields = new Array(); - for( f in x.elements ) { - var f = xclassfield(f,true); - f.platforms = new Array(); // platforms selection are on the type itself, not on fields - fields.push(f); - } - CAnonymous(fields); - case "d": - var t = null; - var tx = x.x.firstElement(); - if( tx != null ) - t = xtype(new Fast(tx)); - CDynamic(t); - default: - xerror(x); + var ret = args[args.length - 1]; + args.remove(ret); + CFunction(args, ret.t); + case "a": + var fields = new Array(); + for (f in x.elements) { + var f = xclassfield(f, true); + f.platforms = new Array(); // platforms selection are on the type itself, not on fields + fields.push(f); + } + CAnonymous(fields); + case "d": + var t = null; + var tx = x.x.firstElement(); + if (tx != null) + t = xtype(new Access(tx)); + CDynamic(t); + default: + xerror(x); } } - function xtypeparams( x : Fast ) : Array { + function xtypeparams(x:Access):Array { var p = new Array(); - for( c in x.elements ) + for (c in x.elements) p.push(xtype(c)); return p; } function defplat() { var l = new Array(); - if( curplatform != null ) + if (curplatform != null) l.push(curplatform); return l; } - } diff --git a/std/haxe/xml/Access.hx b/std/haxe/xml/Access.hx new file mode 100644 index 00000000000..b97b7f639b8 --- /dev/null +++ b/std/haxe/xml/Access.hx @@ -0,0 +1,243 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.xml; + +private abstract NodeAccess(Xml) from Xml { + @:op(a.b) + public function resolve(name:String):Access { + var x = this.elementsNamed(name).next(); + if (x == null) { + var xname = if (this.nodeType == Xml.Document) "Document" else this.nodeName; + throw xname + " is missing element " + name; + } + return new Access(x); + } +} + +private abstract AttribAccess(Xml) from Xml { + @:op(a.b) + public function resolve(name:String):String { + if (this.nodeType == Xml.Document) + throw "Cannot access document attribute " + name; + var v = this.get(name); + if (v == null) + throw this.nodeName + " is missing attribute " + name; + return v; + } + + @:op(a.b) + function _hx_set(name:String, value:String):String { + if (this.nodeType == Xml.Document) + throw "Cannot access document attribute " + name; + this.set(name, value); + return value; + } +} + +private abstract HasAttribAccess(Xml) from Xml { + @:op(a.b) + public function resolve(name:String):Bool { + if (this.nodeType == Xml.Document) + throw "Cannot access document attribute " + name; + return this.exists(name); + } +} + +private abstract HasNodeAccess(Xml) from Xml { + @:op(a.b) + public function resolve(name:String):Bool { + return this.elementsNamed(name).hasNext(); + } +} + +private abstract NodeListAccess(Xml) from Xml { + @:op(a.b) + public function resolve(name:String):Array { + var l = []; + for (x in this.elementsNamed(name)) + l.push(new Access(x)); + return l; + } +} + +/** + The `haxe.xml.Access` API helps providing a fast dot-syntax access to the + most common `Xml` methods. +**/ +abstract Access(Xml) { + public var x(get, never):Xml; + + public inline function get_x() + return this; + + /** + The name of the current element. This is the same as `Xml.nodeName`. + **/ + public var name(get, never):String; + + inline function get_name() { + return if (this.nodeType == Xml.Document) "Document" else this.nodeName; + } + + /** + The inner PCDATA or CDATA of the node. + + An exception is thrown if there is no data or if there not only data + but also other nodes. + **/ + public var innerData(get, never):String; + + /** + The XML string built with all the sub nodes, excluding the current one. + **/ + public var innerHTML(get, never):String; + + /** + Access to the first sub element with the given name. + + An exception is thrown if the element doesn't exists. + Use `hasNode` to check the existence of a node. + + ```haxe + var access = new haxe.xml.Access(Xml.parse("John")); + var user = access.node.user; + var name = user.node.name; + trace(name.innerData); // John + + // Uncaught Error: Document is missing element password + var password = user.node.password; + ``` + **/ + public var node(get, never):NodeAccess; + + inline function get_node():NodeAccess + return x; + + /** + Access to the List of elements with the given name. + ```haxe + var fast = new haxe.xml.Access(Xml.parse(" + + + + + " + )); + + var users = fast.node.users; + for (user in users.nodes.user) { + trace(user.att.name); + } + ``` + **/ + public var nodes(get, never):NodeListAccess; + + inline function get_nodes():NodeListAccess + return this; + + /** + Access to a given attribute. + + An exception is thrown if the attribute doesn't exists. + Use `has` to check the existence of an attribute. + + ```haxe + var f = new haxe.xml.Access(Xml.parse("")); + var user = f.node.user; + if (user.has.name) { + trace(user.att.name); // Mark + } + ``` + **/ + public var att(get, never):AttribAccess; + + inline function get_att():AttribAccess + return this; + + /** + Check the existence of an attribute with the given name. + **/ + public var has(get, never):HasAttribAccess; + + inline function get_has():HasAttribAccess + return this; + + /** + Check the existence of a sub node with the given name. + + ```haxe + var f = new haxe.xml.Access(Xml.parse("31")); + var user = f.node.user; + if (user.hasNode.age) { + trace(user.node.age.innerData); // 31 + } + ``` + **/ + public var hasNode(get, never):HasNodeAccess; + + inline function get_hasNode():HasNodeAccess + return x; + + /** + The list of all sub-elements which are the nodes with type `Xml.Element`. + **/ + public var elements(get, never):Iterator; + + inline function get_elements():Iterator + return cast this.elements(); + + public inline function new(x:Xml) { + if (x.nodeType != Xml.Document && x.nodeType != Xml.Element) + throw "Invalid nodeType " + x.nodeType; + this = x; + } + + function get_innerData() { + var it = this.iterator(); + if (!it.hasNext()) + throw name + " does not have data"; + var v = it.next(); + if (it.hasNext()) { + var n = it.next(); + // handle CDATA + if (v.nodeType == Xml.PCData && n.nodeType == Xml.CData && StringTools.trim(v.nodeValue) == "") { + if (!it.hasNext()) + return n.nodeValue; + var n2 = it.next(); + if (n2.nodeType == Xml.PCData && StringTools.trim(n2.nodeValue) == "" && !it.hasNext()) + return n.nodeValue; + } + throw name + " does not only have data"; + } + if (v.nodeType != Xml.PCData && v.nodeType != Xml.CData) + throw name + " does not have data"; + return v.nodeValue; + } + + function get_innerHTML() { + var s = new StringBuf(); + for (x in this) + s.add(x.toString()); + return s.toString(); + } +} diff --git a/std/haxe/xml/Check.hx b/std/haxe/xml/Check.hx index d16b5184394..94c5e75b956 100644 --- a/std/haxe/xml/Check.hx +++ b/std/haxe/xml/Check.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,303 +19,311 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.xml; enum Filter { FInt; FBool; - FEnum( values : Array ); - FReg( matcher : EReg ); + FEnum(values:Array); + FReg(matcher:EReg); } enum Attrib { - Att( name : String, ?filter : Filter, ?defvalue : String ); + Att(name:String, ?filter:Filter, ?defvalue:String); } enum Rule { - RNode( name : String, ?attribs : Array, ?childs : Rule ); - RData( ?filter : Filter ); - RMulti( rule : Rule, ?atLeastOne : Bool ); - RList( rules : Array, ?ordered : Bool ); - RChoice( choices : Array ); - ROptional( rule : Rule ); + RNode(name:String, ?attribs:Array, ?childs:Rule); + RData(?filter:Filter); + RMulti(rule:Rule, ?atLeastOne:Bool); + RList(rules:Array, ?ordered:Bool); + RChoice(choices:Array); + ROptional(rule:Rule); } private enum CheckResult { CMatch; - CMissing( r : Rule ); - CExtra( x : Xml ); - CElementExpected( name : String, x : Xml ); - CDataExpected( x : Xml ); - CExtraAttrib( att : String, x : Xml ); - CMissingAttrib( att : String, x : Xml ); - CInvalidAttrib( att : String, x : Xml, f : Filter ); - CInvalidData( x : Xml, f : Filter ); - CInElement( x : Xml, r : CheckResult ); + CMissing(r:Rule); + CExtra(x:Xml); + CElementExpected(name:String, x:Xml); + CDataExpected(x:Xml); + CExtraAttrib(att:String, x:Xml); + CMissingAttrib(att:String, x:Xml); + CInvalidAttrib(att:String, x:Xml, f:Filter); + CInvalidData(x:Xml, f:Filter); + CInElement(x:Xml, r:CheckResult); } class Check { - static var blanks = ~/^[ \r\n\t]*$/; - static function isBlank( x : Xml ) { - return( x.nodeType == Xml.PCData && blanks.match(x.nodeValue) ) || x.nodeType == Xml.Comment; + static function isBlank(x:Xml) { + return (x.nodeType == Xml.PCData && blanks.match(x.nodeValue)) || x.nodeType == Xml.Comment; } - static function filterMatch( s : String, f : Filter ) { - switch( f ) { - case FInt: return filterMatch(s,FReg(~/[0-9]+/)); - case FBool: return filterMatch(s,FEnum(["true","false","0","1"])); - case FEnum(values): - for( v in values ) - if( s == v ) - return true; - return false; - case FReg(r): - return r.match(s); + static function filterMatch(s:String, f:Filter) { + switch (f) { + case FInt: + return filterMatch(s, FReg(~/[0-9]+/)); + case FBool: + return filterMatch(s, FEnum(["true", "false", "0", "1"])); + case FEnum(values): + for (v in values) + if (s == v) + return true; + return false; + case FReg(r): + return r.match(s); } } - static function isNullable( r : Rule ) { - switch( r ) { - case RMulti(r,one): - return( one != true || isNullable(r) ); - case RList(rl,_): - for( r in rl ) - if( !isNullable(r) ) - return false; - return true; - case RChoice(rl): - for( r in rl ) - if( isNullable(r) ) - return true; - return false; - case RData(_): - return false; - case RNode(_,_,_): - return false; - case ROptional(_): - return true; + static function isNullable(r:Rule) { + switch (r) { + case RMulti(r, one): + return (one != true || isNullable(r)); + case RList(rl, _): + for (r in rl) + if (!isNullable(r)) + return false; + return true; + case RChoice(rl): + for (r in rl) + if (isNullable(r)) + return true; + return false; + case RData(_): + return false; + case RNode(_, _, _): + return false; + case ROptional(_): + return true; } } - static function check( x : Xml, r : Rule ) { - switch( r ) { - // check the node validity - case RNode(name,attribs,childs): - if( x.nodeType != Xml.Element || x.nodeName != name ) - return CElementExpected(name,x); - var attribs = if( attribs == null ) new Array() else attribs.copy(); - // check defined attributes - for( xatt in x.attributes() ) { - var found = false; - for( att in attribs ) - switch( att ) { - case Att(name,filter,_): - if( xatt != name ) - continue; - if( filter != null && !filterMatch(x.get(xatt),filter) ) - return CInvalidAttrib(name,x,filter); - attribs.remove(att); - found = true; - } - if( !found ) - return CExtraAttrib(xatt,x); - } - // check remaining unchecked attributes - for( att in attribs ) - switch( att ) { - case Att(name,_,defvalue): - if( defvalue == null ) - return CMissingAttrib(name,x); - } - // check childs - if( childs == null ) - childs = RList([]); - var m = checkList(x.iterator(),childs); - if( m != CMatch ) - return CInElement(x,m); - // set default attribs values - for( att in attribs ) - switch( att ) { - case Att(name,_,defvalue): - x.set(name,defvalue); + static function check(x:Xml, r:Rule) { + switch (r) { + // check the node validity + case RNode(name, attribs, childs): + if (x.nodeType != Xml.Element || x.nodeName != name) + return CElementExpected(name, x); + var attribs = if (attribs == null) new Array() else attribs.copy(); + // check defined attributes + for (xatt in x.attributes()) { + var found = false; + for (att in attribs) + switch (att) { + case Att(name, filter, _): + if (xatt != name) + continue; + if (filter != null && !filterMatch(x.get(xatt), filter)) + return CInvalidAttrib(name, x, filter); + attribs.remove(att); + found = true; + } + if (!found) + return CExtraAttrib(xatt, x); } - return CMatch; - // check the data validity - case RData(filter): - if( x.nodeType != Xml.PCData && x.nodeType != Xml.CData ) - return CDataExpected(x); - if( filter != null && !filterMatch(x.nodeValue,filter) ) - return CInvalidData(x,filter); - return CMatch; - // several choices - case RChoice(choices): - if( choices.length == 0 ) - throw "No choice possible"; - for( c in choices ) - if( check(x,c) == CMatch ) - return CMatch; - return check(x,choices[0]); - case ROptional(r): - return check(x,r); - default: - throw "Unexpected "+Std.string(r); + // check remaining unchecked attributes + for (att in attribs) + switch (att) { + case Att(name, _, defvalue): + if (defvalue == null) + return CMissingAttrib(name, x); + } + // check childs + if (childs == null) + childs = RList([]); + var m = checkList(x.iterator(), childs); + if (m != CMatch) + return CInElement(x, m); + // set default attribs values + for (att in attribs) + switch (att) { + case Att(name, _, defvalue): + x.set(name, defvalue); + } + return CMatch; + // check the data validity + case RData(filter): + if (x.nodeType != Xml.PCData && x.nodeType != Xml.CData) + return CDataExpected(x); + if (filter != null && !filterMatch(x.nodeValue, filter)) + return CInvalidData(x, filter); + return CMatch; + // several choices + case RChoice(choices): + if (choices.length == 0) + throw "No choice possible"; + for (c in choices) + if (check(x, c) == CMatch) + return CMatch; + return check(x, choices[0]); + case ROptional(r): + return check(x, r); + default: + throw "Unexpected " + Std.string(r); } } - static function checkList( it : Iterator, r : Rule ) { - switch( r ) { - case RList(rules,ordered): - var rules = rules.copy(); - for( x in it ) { - if( isBlank(x) ) - continue; - var found = false; - for( r in rules ) { - var m = checkList([x].iterator(),r); - if( m == CMatch ) { - found = true; - switch(r) { - case RMulti(rsub,one): - if( one ) { - var i; - for( i in 0...rules.length ) - if( rules[i] == r ) - rules[i] = RMulti(rsub); + static function checkList(it:Iterator, r:Rule) { + switch (r) { + case RList(rules, ordered): + var rules = rules.copy(); + for (x in it) { + if (isBlank(x)) + continue; + var found = false; + for (r in rules) { + var m = checkList([x].iterator(), r); + if (m == CMatch) { + found = true; + switch (r) { + case RMulti(rsub, one): + if (one) { + var i; + for (i in 0...rules.length) + if (rules[i] == r) + rules[i] = RMulti(rsub); + } + default: + rules.remove(r); } - default: - rules.remove(r); - } - break; - } else if( ordered && !isNullable(r) ) + break; + } else if (ordered && !isNullable(r)) + return m; + } + if (!found) + return CExtra(x); + } + for (r in rules) + if (!isNullable(r)) + return CMissing(r); + return CMatch; + case RMulti(r, one): + var found = false; + for (x in it) { + if (isBlank(x)) + continue; + var m = checkList([x].iterator(), r); + if (m != CMatch) return m; + found = true; } - if( !found ) - return CExtra(x); - } - for( r in rules ) - if( !isNullable(r) ) + if (one && !found) return CMissing(r); - return CMatch; - case RMulti(r,one): - var found = false; - for( x in it ) { - if( isBlank(x) ) - continue; - var m = checkList([x].iterator(),r); - if( m != CMatch ) - return m; - found = true; - } - if( one && !found ) - return CMissing(r); - return CMatch; - default: - var found = false; - for( x in it ) { - if( isBlank(x) ) - continue; - var m = check(x,r); - if( m != CMatch ) - return m; - found = true; - break; - } - if( !found ) { - switch(r) { - case ROptional(_): - default: return CMissing(r); + return CMatch; + default: + var found = false; + for (x in it) { + if (isBlank(x)) + continue; + var m = check(x, r); + if (m != CMatch) + return m; + found = true; + break; } - } - for( x in it ) { - if( isBlank(x) ) - continue; - return CExtra(x); - } - return CMatch; + if (!found) { + switch (r) { + case ROptional(_): + default: return CMissing(r); + } + } + for (x in it) { + if (isBlank(x)) + continue; + return CExtra(x); + } + return CMatch; } } - static function makeWhere( path : Array ) { - if( path.length == 0 ) + static function makeWhere(path:Array) { + if (path.length == 0) return ""; var s = "In "; var first = true; - for( x in path ) { - if( first ) + for (x in path) { + if (first) first = false; else s += "."; s += x.nodeName; } - return s+": "; + return s + ": "; } - static function makeString( x : Xml ) { - if( x.nodeType == Xml.Element ) - return "element "+x.nodeName; + static function makeString(x:Xml) { + if (x.nodeType == Xml.Element) + return "element " + x.nodeName; var s = x.nodeValue.split("\r").join("\\r").split("\n").join("\\n").split("\t").join("\\t"); - if( s.length > 20 ) - return s.substr(0,17)+"..."; + if (s.length > 20) + return s.substr(0, 17) + "..."; return s; } - static function makeRule( r : Rule ) { - switch( r ) { - case RNode(name,_,_): return "element "+name; - case RData(_): return "data"; - case RMulti(r,_): return makeRule(r); - case RList(rules,_): return makeRule(rules[0]); - case RChoice(choices): return makeRule(choices[0]); - case ROptional(r): return makeRule(r); + static function makeRule(r:Rule) { + switch (r) { + case RNode(name, _, _): + return "element " + name; + case RData(_): + return "data"; + case RMulti(r, _): + return makeRule(r); + case RList(rules, _): + return makeRule(rules[0]); + case RChoice(choices): + return makeRule(choices[0]); + case ROptional(r): + return makeRule(r); } } - static function makeError(m,?path) { - if( path == null ) + static function makeError(m, ?path) { + if (path == null) path = new Array(); - switch( m ) { - case CMatch: throw "assert"; - case CMissing(r): - return makeWhere(path)+"Missing "+makeRule(r); - case CExtra(x): - return makeWhere(path)+"Unexpected "+makeString(x); - case CElementExpected(name,x): - return makeWhere(path)+makeString(x)+" while expected element "+name; - case CDataExpected(x): - return makeWhere(path)+makeString(x)+" while data expected"; - case CExtraAttrib(att,x): - path.push(x); - return makeWhere(path)+"unexpected attribute "+att; - case CMissingAttrib(att,x): - path.push(x); - return makeWhere(path)+"missing required attribute "+att; - case CInvalidAttrib(att,x,_): - path.push(x); - return makeWhere(path)+"invalid attribute value for "+att; - case CInvalidData(x,_): - return makeWhere(path)+"invalid data format for "+makeString(x); - case CInElement(x,m): - path.push(x); - return makeError(m,path); + switch (m) { + case CMatch: + throw "assert"; + case CMissing(r): + return makeWhere(path) + "Missing " + makeRule(r); + case CExtra(x): + return makeWhere(path) + "Unexpected " + makeString(x); + case CElementExpected(name, x): + return makeWhere(path) + makeString(x) + " while expected element " + name; + case CDataExpected(x): + return makeWhere(path) + makeString(x) + " while data expected"; + case CExtraAttrib(att, x): + path.push(x); + return makeWhere(path) + "unexpected attribute " + att; + case CMissingAttrib(att, x): + path.push(x); + return makeWhere(path) + "missing required attribute " + att; + case CInvalidAttrib(att, x, _): + path.push(x); + return makeWhere(path) + "invalid attribute value for " + att; + case CInvalidData(x, _): + return makeWhere(path) + "invalid data format for " + makeString(x); + case CInElement(x, m): + path.push(x); + return makeError(m, path); } } - public static function checkNode( x : Xml, r : Rule ) { - var m = checkList([x].iterator(),r); - if( m == CMatch ) + public static function checkNode(x:Xml, r:Rule) { + var m = checkList([x].iterator(), r); + if (m == CMatch) return; throw makeError(m); } - public static function checkDocument( x : Xml, r : Rule ) { - if( x.nodeType != Xml.Document ) + public static function checkDocument(x:Xml, r:Rule) { + if (x.nodeType != Xml.Document) throw "Document expected"; - var m = checkList(x.iterator(),r); - if( m == CMatch ) + var m = checkList(x.iterator(), r); + if (m == CMatch) return; throw makeError(m); } - } diff --git a/std/haxe/xml/Fast.hx b/std/haxe/xml/Fast.hx index 0281af20671..97a70065e7a 100644 --- a/std/haxe/xml/Fast.hx +++ b/std/haxe/xml/Fast.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,209 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe.xml; - -private abstract NodeAccess(Xml) from Xml { - - @:op(a.b) - public function resolve( name : String ) : Fast { - var x = this.elementsNamed(name).next(); - if( x == null ) { - var xname = if( this.nodeType == Xml.Document ) "Document" else this.nodeName; - throw xname+" is missing element "+name; - } - return new Fast(x); - } - -} - -private abstract AttribAccess(Xml) from Xml { - - @:op(a.b) - public function resolve( name : String ) : String { - if( this.nodeType == Xml.Document ) - throw "Cannot access document attribute "+name; - var v = this.get(name); - if( v == null ) - throw this.nodeName+" is missing attribute "+name; - return v; - } - -} - -private abstract HasAttribAccess(Xml) from Xml { - - @:op(a.b) - public function resolve( name : String ) : Bool { - if( this.nodeType == Xml.Document ) - throw "Cannot access document attribute "+name; - return this.exists(name); - } - -} - -private abstract HasNodeAccess(Xml) from Xml { - - @:op(a.b) - public function resolve( name : String ) : Bool { - return this.elementsNamed(name).hasNext(); - } - -} - -private abstract NodeListAccess(Xml) from Xml { - - @:op(a.b) - public function resolve( name : String ) : Array { - var l = []; - for( x in this.elementsNamed(name) ) - l.push(new Fast(x)); - return l; - } - -} - -/** - The `haxe.xml.Fast` API helps providing a fast dot-syntax access to the - most common `Xml` methods. -**/ -abstract Fast(Xml) { - public var x(get,never) : Xml; - public inline function get_x() return this; - - /** - The name of the current element. This is the same as `Xml.nodeName`. - **/ - public var name(get,never) : String; - inline function get_name() { - return if( this.nodeType == Xml.Document ) "Document" else this.nodeName; - } - /** - The inner PCDATA or CDATA of the node. - - An exception is thrown if there is no data or if there not only data - but also other nodes. - **/ - public var innerData(get,never) : String; - - /** - The XML string built with all the sub nodes, excluding the current one. - **/ - public var innerHTML(get,never) : String; - - /** - Access to the first sub element with the given name. - - An exception is thrown if the element doesn't exists. - Use `hasNode` to check the existence of a node. - - ```haxe - var fast = new haxe.xml.Fast(Xml.parse("John")); - var user = fast.node.user; - var name = user.node.name; - trace(name.innerData); // John - - // Uncaught Error: Document is missing element password - var password = user.node.password; - ``` - **/ - public var node(get,never) : NodeAccess; - inline function get_node() : NodeAccess return x; - - /** - Access to the List of elements with the given name. - ```haxe - var fast = new haxe.xml.Fast(Xml.parse(" - - - - ")); - - var users = fast.node.users; - for(user in users.nodes.user) { - trace(user.att.name); - } - ``` - **/ - public var nodes(get,never) : NodeListAccess; - inline function get_nodes() : NodeListAccess return this; - - /** - Access to a given attribute. - - An exception is thrown if the attribute doesn't exists. - Use `has` to check the existence of an attribute. - - ```haxe - var f = new haxe.xml.Fast(Xml.parse("")); - var user = f.node.user; - if (user.has.name) { - trace(user.att.name); // Mark - } - ``` - **/ - public var att(get,never) : AttribAccess; - inline function get_att() : AttribAccess return this; - - /** - Check the existence of an attribute with the given name. - **/ - public var has(get,never) : HasAttribAccess; - inline function get_has() : HasAttribAccess return this; - - /** - Check the existence of a sub node with the given name. - - ```haxe - var f = new haxe.xml.Fast(Xml.parse("31")); - var user = f.node.user; - if (user.hasNode.age) { - trace(user.node.age.innerData); // 31 - } - ``` - **/ - public var hasNode(get,never) : HasNodeAccess; - inline function get_hasNode() : HasNodeAccess return x; - - /** - The list of all sub-elements which are the nodes with type `Xml.Element`. - **/ - public var elements(get,never) : Iterator; - inline function get_elements() : Iterator return cast this.elements(); - - public inline function new( x : Xml ) { - if( x.nodeType != Xml.Document && x.nodeType != Xml.Element ) - throw "Invalid nodeType "+x.nodeType; - this = x; - } - - function get_innerData() { - var it = this.iterator(); - if( !it.hasNext() ) - throw name+" does not have data"; - var v = it.next(); - if( it.hasNext() ) { - var n = it.next(); - // handle CDATA - if( v.nodeType == Xml.PCData && n.nodeType == Xml.CData && StringTools.trim(v.nodeValue) == "" ) { - if( !it.hasNext() ) - return n.nodeValue; - var n2 = it.next(); - if( n2.nodeType == Xml.PCData && StringTools.trim(n2.nodeValue) == "" && !it.hasNext() ) - return n.nodeValue; - } - throw name+" does not only have data"; - } - if( v.nodeType != Xml.PCData && v.nodeType != Xml.CData ) - throw name+" does not have data"; - return v.nodeValue; - } +package haxe.xml; - function get_innerHTML() { - var s = new StringBuf(); - for( x in this ) - s.add(this.toString()); - return s.toString(); - } -} +@:deprecated typedef Fast = haxe.xml.Access; diff --git a/std/haxe/xml/Parser.hx b/std/haxe/xml/Parser.hx index c0ab845ef49..f02765cc485 100644 --- a/std/haxe/xml/Parser.hx +++ b/std/haxe/xml/Parser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,88 +19,84 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.xml; using StringTools; -/* poor'man enum : reduce code size + a bit faster since inlined */ -extern private class S { - public static inline var IGNORE_SPACES = 0; - public static inline var BEGIN = 1; - public static inline var BEGIN_NODE = 2; - public static inline var TAG_NAME = 3; - public static inline var BODY = 4; - public static inline var ATTRIB_NAME = 5; - public static inline var EQUALS = 6; - public static inline var ATTVAL_BEGIN = 7; - public static inline var ATTRIB_VAL = 8; - public static inline var CHILDS = 9; - public static inline var CLOSE = 10; - public static inline var WAIT_END = 11; - public static inline var WAIT_END_RET = 12; - public static inline var PCDATA = 13; - public static inline var HEADER = 14; - public static inline var COMMENT = 15; - public static inline var DOCTYPE = 16; - public static inline var CDATA = 17; - public static inline var ESCAPE = 18; +private enum abstract S(Int) { + var IGNORE_SPACES; + var BEGIN; + var BEGIN_NODE; + var TAG_NAME; + var BODY; + var ATTRIB_NAME; + var EQUALS; + var ATTVAL_BEGIN; + var ATTRIB_VAL; + var CHILDS; + var CLOSE; + var WAIT_END; + var WAIT_END_RET; + var PCDATA; + var HEADER; + var COMMENT; + var DOCTYPE; + var CDATA; + var ESCAPE; } -class XmlParserException -{ +class XmlParserException { /** - * the XML parsing error message - */ + the XML parsing error message + **/ public var message:String; /** - * the line number at which the XML parsing error occurred - */ + the line number at which the XML parsing error occurred + **/ public var lineNumber:Int; /** - * the character position in the reported line at which the parsing error occurred - */ + the character position in the reported line at which the parsing error occurred + **/ public var positionAtLine:Int; /** - * the character position in the XML string at which the parsing error occurred - */ + the character position in the XML string at which the parsing error occurred + **/ public var position:Int; /** - * the invalid XML string - */ + the invalid XML string + **/ public var xml:String; - public function new(message:String, xml:String, position:Int) - { + public function new(message:String, xml:String, position:Int) { this.xml = xml; this.message = message; this.position = position; lineNumber = 1; positionAtLine = 0; - for( i in 0...position) - { + for (i in 0...position) { var c = xml.fastCodeAt(i); if (c == '\n'.code) { lineNumber++; positionAtLine = 0; } else { - if (c != '\r'.code) positionAtLine++; + if (c != '\r'.code) + positionAtLine++; } } } - public function toString():String - { + public function toString():String { return Type.getClassName(Type.getClass(this)) + ": " + message + " at line " + lineNumber + " char " + positionAtLine; } } -class Parser -{ +class Parser { static var escapes = { var h = new haxe.ds.StringMap(); h.set("lt", "<"); @@ -112,19 +108,17 @@ class Parser } /** - * Parses the String into an XML Document. Set strict parsing to true in order to enable a strict check of XML attributes and entities. - * - * @throws haxe.xml.XmlParserException - */ - static public function parse(str:String, strict = false) - { + Parses the String into an XML Document. Set strict parsing to true in order to enable a strict check of XML attributes and entities. + + @throws haxe.xml.XmlParserException + **/ + static public function parse(str:String, strict = false) { var doc = Xml.createDocument(); doParse(str, strict, 0, doc); return doc; } - static function doParse(str:String, strict:Bool, p:Int = 0, ?parent:Xml):Int - { + static function doParse(str:String, strict:Bool, p:Int = 0, ?parent:Xml):Int { var xml:Xml = null; var state = S.BEGIN; var next = S.BEGIN; @@ -141,25 +135,17 @@ class Parser parent.addChild(xml); nsubs++; } - while (!StringTools.isEof(c)) - { - switch(state) - { + while (!StringTools.isEof(c)) { + switch (state) { case S.IGNORE_SPACES: - switch(c) - { - case - '\n'.code, - '\r'.code, - '\t'.code, - ' '.code: + switch (c) { + case '\n'.code, '\r'.code, '\t'.code, ' '.code: default: state = next; continue; } case S.BEGIN: - switch(c) - { + switch (c) { case '<'.code: state = S.IGNORE_SPACES; next = S.BEGIN_NODE; @@ -169,8 +155,7 @@ class Parser continue; } case S.PCDATA: - if (c == '<'.code) - { + if (c == '<'.code) { buf.addSub(str, start, p - start); var child = Xml.createPCData(buf.toString()); buf = new StringBuf(); @@ -184,38 +169,31 @@ class Parser start = p + 1; } case S.CDATA: - if (c == ']'.code && str.fastCodeAt(p + 1) == ']'.code && str.fastCodeAt(p + 2) == '>'.code) - { + if (c == ']'.code && str.fastCodeAt(p + 1) == ']'.code && str.fastCodeAt(p + 2) == '>'.code) { var child = Xml.createCData(str.substr(start, p - start)); addChild(child); p += 2; state = S.BEGIN; } case S.BEGIN_NODE: - switch(c) - { + switch (c) { case '!'.code: - if (str.fastCodeAt(p + 1) == '['.code) - { + if (str.fastCodeAt(p + 1) == '['.code) { p += 2; if (str.substr(p, 6).toUpperCase() != "CDATA[") throw new XmlParserException("Expected '.code: @@ -258,22 +234,20 @@ class Parser continue; } case S.ATTRIB_NAME: - if (!isValidChar(c)) - { + if (!isValidChar(c)) { var tmp; - if( start == p ) + if (start == p) throw new XmlParserException("Expected attribute name", str, p); - tmp = str.substr(start,p-start); + tmp = str.substr(start, p - start); aname = tmp; - if( xml.exists(aname) ) + if (xml.exists(aname)) throw new XmlParserException("Duplicate attribute [" + aname + "]", str, p); state = S.IGNORE_SPACES; next = S.EQUALS; continue; } case S.EQUALS: - switch(c) - { + switch (c) { case '='.code: state = S.IGNORE_SPACES; next = S.ATTVAL_BEGIN; @@ -281,8 +255,7 @@ class Parser throw new XmlParserException("Expected =", str, p); } case S.ATTVAL_BEGIN: - switch(c) - { + switch (c) { case '"'.code | '\''.code: buf = new StringBuf(); state = S.ATTRIB_VAL; @@ -298,7 +271,7 @@ class Parser state = S.ESCAPE; escapeNext = S.ATTRIB_VAL; start = p + 1; - case '>'.code | '<'.code if( strict ): + case '>'.code | '<'.code if (strict): // HTML allows these in attributes values throw new XmlParserException("Invalid unescaped " + String.fromCharCode(c) + " in attribute value", str, p); case _ if (c == attrValQuote): @@ -314,81 +287,75 @@ class Parser start = p; state = S.BEGIN; case S.WAIT_END: - switch(c) - { + switch (c) { case '>'.code: state = S.BEGIN; - default : + default: throw new XmlParserException("Expected >", str, p); } case S.WAIT_END_RET: - switch(c) - { + switch (c) { case '>'.code: - if( nsubs == 0 ) + if (nsubs == 0) parent.addChild(Xml.createPCData("")); return p; - default : + default: throw new XmlParserException("Expected >", str, p); } case S.CLOSE: - if (!isValidChar(c)) - { - if( start == p ) + if (!isValidChar(c)) { + if (start == p) throw new XmlParserException("Expected node name", str, p); - var v = str.substr(start,p - start); + var v = str.substr(start, p - start); + if (parent == null || parent.nodeType != Element) { + throw new XmlParserException('Unexpected , tag is not open', str, p); + } if (v != parent.nodeName) - throw new XmlParserException("Expected ", str, p); + throw new XmlParserException("Expected ", str, p); state = S.IGNORE_SPACES; next = S.WAIT_END_RET; continue; } case S.COMMENT: - if (c == '-'.code && str.fastCodeAt(p +1) == '-'.code && str.fastCodeAt(p + 2) == '>'.code) - { + if (c == '-'.code && str.fastCodeAt(p + 1) == '-'.code && str.fastCodeAt(p + 2) == '>'.code) { addChild(Xml.createComment(str.substr(start, p - start))); p += 2; state = S.BEGIN; } case S.DOCTYPE: - if(c == '['.code) + if (c == '['.code) nbrackets++; - else if(c == ']'.code) + else if (c == ']'.code) nbrackets--; - else if (c == '>'.code && nbrackets == 0) - { + else if (c == '>'.code && nbrackets == 0) { addChild(Xml.createDocType(str.substr(start, p - start))); state = S.BEGIN; } case S.HEADER: - if (c == '?'.code && str.fastCodeAt(p + 1) == '>'.code) - { + if (c == '?'.code && str.fastCodeAt(p + 1) == '>'.code) { p++; var str = str.substr(start + 1, p - start - 2); addChild(Xml.createProcessingInstruction(str)); state = S.BEGIN; } case S.ESCAPE: - if (c == ';'.code) - { + if (c == ';'.code) { var s = str.substr(start, p - start); if (s.fastCodeAt(0) == '#'.code) { - var c = s.fastCodeAt(1) == 'x'.code - ? Std.parseInt("0" +s.substr(1, s.length - 1)) - : Std.parseInt(s.substr(1, s.length - 1)); - #if (neko || cpp || php || lua || eval) - if( c >= 128 ) { + var c = s.fastCodeAt(1) == 'x'.code ? Std.parseInt("0" + s.substr(1, s.length - 1)) : Std.parseInt(s.substr(1, s.length - 1)); + #if !(target.unicode) + if (c >= 128) { // UTF8-encode it - if( c <= 0x7FF ) { + if (c <= 0x7FF) { buf.addChar(0xC0 | (c >> 6)); buf.addChar(0x80 | (c & 63)); - } else if( c <= 0xFFFF ) { + } else if (c <= 0xFFFF) { buf.addChar(0xE0 | (c >> 12)); buf.addChar(0x80 | ((c >> 6) & 63)); buf.addChar(0x80 | (c & 63)); - } else if( c <= 0x10FFFF ) { + } else if (c <= 0x10FFFF) { buf.addChar(0xF0 | (c >> 18)); buf.addChar(0x80 | ((c >> 12) & 63)); buf.addChar(0x80 | ((c >> 6) & 63)); @@ -399,7 +366,7 @@ class Parser #end buf.addChar(c); } else if (!escapes.exists(s)) { - if( strict ) + if (strict) throw new XmlParserException("Undefined entity: " + s, str, p); buf.add('&$s;'); } else { @@ -408,7 +375,7 @@ class Parser start = p + 1; state = escapeNext; } else if (!isValidChar(c) && c != "#".code) { - if( strict ) + if (strict) throw new XmlParserException("Invalid character in entity: " + String.fromCharCode(c), str, p); buf.addChar("&".code); buf.addSub(str, start, p - start); @@ -420,22 +387,23 @@ class Parser c = str.fastCodeAt(++p); } - if (state == S.BEGIN) - { + if (state == S.BEGIN) { start = p; state = S.PCDATA; } - if (state == S.PCDATA) - { + if (state == S.PCDATA) { + if (parent.nodeType == Element) { + throw new XmlParserException("Unclosed node <" + parent.nodeName + ">", str, p); + } if (p != start || nsubs == 0) { - buf.addSub(str, start, p-start); + buf.addSub(str, start, p - start); addChild(Xml.createPCData(buf.toString())); } return p; } - if( !strict && state == S.ESCAPE && escapeNext == S.PCDATA ) { + if (!strict && state == S.ESCAPE && escapeNext == S.PCDATA) { buf.addChar("&".code); buf.addSub(str, start, p - start); addChild(Xml.createPCData(buf.toString())); @@ -446,6 +414,7 @@ class Parser } static inline function isValidChar(c) { - return (c >= 'a'.code && c <= 'z'.code) || (c >= 'A'.code && c <= 'Z'.code) || (c >= '0'.code && c <= '9'.code) || c == ':'.code || c == '.'.code || c == '_'.code || c == '-'.code; + return (c >= 'a'.code && c <= 'z'.code) || (c >= 'A'.code && c <= 'Z'.code) || (c >= '0'.code && c <= '9'.code) || c == ':'.code || c == '.'.code + || c == '_'.code || c == '-'.code; } } diff --git a/std/haxe/xml/Printer.hx b/std/haxe/xml/Printer.hx index aa47d1e2ace..d64661888a6 100644 --- a/std/haxe/xml/Printer.hx +++ b/std/haxe/xml/Printer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,13 +23,13 @@ package haxe.xml; /** - This class provides utility methods to convert Xml instances to + This class provides utility methods to convert Xml instances to String representation. **/ class Printer { /** Convert `Xml` to string representation. - + Set `pretty` to `true` to prettify the result. **/ static public function print(xml:Xml, ?pretty = false) { @@ -50,7 +50,7 @@ class Printer { switch (value.nodeType) { case CData: write(tabs + ""); newline(); case Comment: diff --git a/std/haxe/xml/Proxy.hx b/std/haxe/xml/Proxy.hx index b607e6128a2..f897a15b09a 100644 --- a/std/haxe/xml/Proxy.hx +++ b/std/haxe/xml/Proxy.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.xml; /** @@ -29,7 +30,7 @@ package haxe.xml; ```haxe class MyXml extends haxe.xml.Proxy<"my.xml", MyStructure> { } - + var h = new haxe.ds.StringMap(); // ... fill h with "my.xml" content var m = new MyXml(h.get); @@ -38,9 +39,8 @@ package haxe.xml; // in your XML, and completion works as well. ``` **/ -class Proxy { - - var __f : String -> T; +class Proxy { + var __f:String->T; public function new(f) { this.__f = f; @@ -49,5 +49,4 @@ class Proxy { public function resolve(k) { return __f(k); } - } diff --git a/std/haxe/zip/Compress.hx b/std/haxe/zip/Compress.hx index d87535b5302..b6bb2b44b03 100644 --- a/std/haxe/zip/Compress.hx +++ b/std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,27 +19,24 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; class Compress { - - public function new( level : Int ) { + public function new(level:Int) { throw "Not implemented for this platform"; } - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { return null; } - public function setFlushMode( f : FlushMode ) { - } + public function setFlushMode(f:FlushMode) {} - public function close() { - } + public function close() {} - public static function run( s : haxe.io.Bytes, level : Int ) : haxe.io.Bytes { + public static function run(s:haxe.io.Bytes, level:Int):haxe.io.Bytes { throw "Not implemented for this platform"; return null; } - } diff --git a/std/haxe/zip/Entry.hx b/std/haxe/zip/Entry.hx index ddd7b031f91..cb8c2d55020 100644 --- a/std/haxe/zip/Entry.hx +++ b/std/haxe/zip/Entry.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,24 +19,24 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; import haxe.ds.List; enum ExtraField { - FUnknown( tag : Int, bytes : haxe.io.Bytes ); - FInfoZipUnicodePath( name : String, crc : Int ); + FUnknown(tag:Int, bytes:haxe.io.Bytes); + FInfoZipUnicodePath(name:String, crc:Int); FUtf8; } -typedef Entry = { - var fileName : String; - var fileSize : Int; - var fileTime : Date; - var compressed : Bool; - var dataSize : Int; - var data : Null; - var crc32 : Null; - @:optional var extraFields : Null>; +typedef Entry = { + var fileName:String; + var fileSize:Int; + var fileTime:Date; + var compressed:Bool; + var dataSize:Int; + var data:Null; + var crc32:Null; + var ?extraFields:Null>; } - diff --git a/std/haxe/zip/FlushMode.hx b/std/haxe/zip/FlushMode.hx index 9a529f7b4cc..8e47a69a105 100644 --- a/std/haxe/zip/FlushMode.hx +++ b/std/haxe/zip/FlushMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; enum FlushMode { diff --git a/std/haxe/zip/Huffman.hx b/std/haxe/zip/Huffman.hx index b1e87443c2b..fb3368b9dc6 100644 --- a/std/haxe/zip/Huffman.hx +++ b/std/haxe/zip/Huffman.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,97 +19,99 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; enum Huffman { - Found( i : Int ); - NeedBit( left : Huffman, right : Huffman ); - NeedBits( n : Int, table : Array ); + Found(i:Int); + NeedBit(left:Huffman, right:Huffman); + NeedBits(n:Int, table:Array); } class HuffTools { - - public function new() { - } + public function new() {} function treeDepth(t) { - return switch(t) { - case Found(_): 0; - case NeedBits(_,_): throw "assert"; - case NeedBit(a,b): - var da = treeDepth(a); - var db = treeDepth(b); - 1 + ((da < db) ? da : db); + return switch (t) { + case Found(_): 0; + case NeedBits(_, _): throw "assert"; + case NeedBit(a, b): + var da = treeDepth(a); + var db = treeDepth(b); + 1 + ((da < db) ? da : db); } } function treeCompress(t) { var d = treeDepth(t); - if( d == 0 ) + if (d == 0) return t; - if( d == 1 ) - return switch( t ) { - case NeedBit(a,b): NeedBit(treeCompress(a),treeCompress(b)); - default: throw "assert"; + if (d == 1) + return switch (t) { + case NeedBit(a, b): NeedBit(treeCompress(a), treeCompress(b)); + default: throw "assert"; } var size = 1 << d; var table = new Array(); - for( i in 0...size ) + for (i in 0...size) table.push(Found(-1)); - treeWalk(table,0,0,d,t); - return NeedBits(d,table); + treeWalk(table, 0, 0, d, t); + return NeedBits(d, table); } - function treeWalk(table,p,cd,d,t) { - switch( t ) { - case NeedBit(a,b): - if( d > 0 ) { - treeWalk(table,p,cd+1,d-1,a); - treeWalk(table,p|(1< 0) { + treeWalk(table, p, cd + 1, d - 1, a); + treeWalk(table, p | (1 << cd), cd + 1, d - 1, b); + } else + table[p] = treeCompress(t); + default: table[p] = treeCompress(t); - default: - table[p] = treeCompress(t); } } - function treeMake( bits : haxe.ds.IntMap, maxbits : Int, v : Int, len : Int ) { - if( len > maxbits ) throw "Invalid huffman"; + function treeMake(bits:haxe.ds.IntMap, maxbits:Int, v:Int, len:Int) { + if (len > maxbits) + throw "Invalid huffman"; var idx = (v << 5) | len; - if( bits.exists(idx) ) + if (bits.exists(idx)) return Found(bits.get(idx)); v <<= 1; len += 1; - return NeedBit(treeMake(bits,maxbits,v,len),treeMake(bits,maxbits,v|1,len)); + return NeedBit(treeMake(bits, maxbits, v, len), treeMake(bits, maxbits, v | 1, len)); } - public function make(lengths,pos,nlengths,maxbits) { + public function make(lengths, pos, nlengths, maxbits) { var counts = new Array(); var tmp = new Array(); - if( maxbits > 32 ) throw "Invalid huffman"; - for( i in 0...maxbits ) { + if (maxbits > 32) + throw "Invalid huffman"; + for (i in 0...maxbits) { counts.push(0); tmp.push(0); } - for( i in 0...nlengths ) { - var p = lengths[i+pos]; - if( p >= maxbits ) throw "Invalid huffman"; + for (i in 0...nlengths) { + var p = lengths[i + pos]; + if (p >= maxbits) + throw "Invalid huffman"; counts[p]++; } var code = 0; - for( i in 1...maxbits-1 ) { + for (i in 1...maxbits - 1) { code = (code + counts[i]) << 1; tmp[i] = code; } var bits = new haxe.ds.IntMap(); - for( i in 0...nlengths ) { + for (i in 0...nlengths) { var l = lengths[i + pos]; - if( l != 0 ) { - var n = tmp[l-1]; - tmp[l-1] = n + 1; - bits.set((n << 5) | l,i); + if (l != 0) { + var n = tmp[l - 1]; + tmp[l - 1] = n + 1; + bits.set((n << 5) | l, i); } } - return treeCompress(NeedBit(treeMake(bits,maxbits,0,1),treeMake(bits,maxbits,1,1))); + return treeCompress(NeedBit(treeMake(bits, maxbits, 0, 1), treeMake(bits, maxbits, 1, 1))); } } diff --git a/std/haxe/zip/InflateImpl.hx b/std/haxe/zip/InflateImpl.hx index 04b593e89cd..8cf99921c22 100644 --- a/std/haxe/zip/InflateImpl.hx +++ b/std/haxe/zip/InflateImpl.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,42 +19,48 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; + import haxe.zip.Huffman; import haxe.crypto.Adler32; private class Window { - public static inline var SIZE = 1 << 15; public static inline var BUFSIZE = 1 << 16; - public var buffer : haxe.io.Bytes; - public var pos : Int; - var crc : Adler32; + public var buffer:haxe.io.Bytes; + public var pos:Int; + + var crc:Adler32; public function new(hasCrc) { buffer = haxe.io.Bytes.alloc(BUFSIZE); pos = 0; - if( hasCrc ) crc = new Adler32(); + if (hasCrc) + crc = new Adler32(); } public function slide() { - if( crc != null ) crc.update(buffer,0,SIZE); + if (crc != null) + crc.update(buffer, 0, SIZE); var b = haxe.io.Bytes.alloc(BUFSIZE); pos -= SIZE; - b.blit(0,buffer,SIZE,pos); + b.blit(0, buffer, SIZE, pos); buffer = b; } - public function addBytes(b,p,len) { - if( pos + len > BUFSIZE ) slide(); - buffer.blit(pos,b,p,len); + public function addBytes(b, p, len) { + if (pos + len > BUFSIZE) + slide(); + buffer.blit(pos, b, p, len); pos += len; } public function addByte(c) { - if( pos == BUFSIZE ) slide(); - buffer.set(pos,c); + if (pos == BUFSIZE) + slide(); + buffer.set(pos, c); pos++; } @@ -67,10 +73,10 @@ private class Window { } public function checksum() { - if( crc != null ) crc.update(buffer,0,pos); + if (crc != null) + crc.update(buffer, 0, pos); return crc; } - } private enum State { @@ -88,32 +94,39 @@ private enum State { A pure Haxe implementation of the ZLIB Inflate algorithm which allows reading compressed data without any platform-specific support. **/ class InflateImpl { - - static var LEN_EXTRA_BITS_TBL = [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,-1,-1]; - static var LEN_BASE_VAL_TBL = [3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258]; - static var DIST_EXTRA_BITS_TBL = [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,-1,-1]; - static var DIST_BASE_VAL_TBL = [1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577]; - static var CODE_LENGTHS_POS = [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; - - var nbits : Int; - var bits : Int; - var state : State; - var isFinal : Bool; - var huffman : Huffman; - var huffdist : Null; - var htools : HuffTools; - var len : Int; - var dist : Int; - var needed : Int; - var output : haxe.io.Bytes; - var outpos : Int; - var input : haxe.io.Input; - var lengths : Array; - var window : Window; + static var LEN_EXTRA_BITS_TBL = [ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, -1, -1 + ]; + static var LEN_BASE_VAL_TBL = [ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 + ]; + static var DIST_EXTRA_BITS_TBL = [ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, -1, -1 + ]; + static var DIST_BASE_VAL_TBL = [ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 + ]; + static var CODE_LENGTHS_POS = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + + var nbits:Int; + var bits:Int; + var state:State; + var isFinal:Bool; + var huffman:Huffman; + var huffdist:Null; + var htools:HuffTools; + var len:Int; + var dist:Int; + var needed:Int; + var output:haxe.io.Bytes; + var outpos:Int; + var input:haxe.io.Input; + var lengths:Array; + var window:Window; static var FIXED_HUFFMAN = null; - public function new( i, ?header = true, ?crc = true ) { + public function new(i, ?header = true, ?crc = true) { isFinal = false; htools = new HuffTools(); huffman = buildFixedHuffman(); @@ -128,33 +141,32 @@ class InflateImpl { output = null; outpos = 0; lengths = new Array(); - for( i in 0...19 ) + for (i in 0...19) lengths.push(-1); window = new Window(crc); } function buildFixedHuffman() { - if( FIXED_HUFFMAN != null ) + if (FIXED_HUFFMAN != null) return FIXED_HUFFMAN; var a = new Array(); - for( n in 0...288 ) - a.push(if( n <= 143 ) 8 else if( n <= 255 ) 9 else if( n <= 279 ) 7 else 8); - FIXED_HUFFMAN = htools.make(a,0,288,10); + for (n in 0...288) + a.push(if (n <= 143) 8 else if (n <= 255) 9 else if (n <= 279) 7 else 8); + FIXED_HUFFMAN = htools.make(a, 0, 288, 10); return FIXED_HUFFMAN; } - public function readBytes(b,pos,len) { + public function readBytes(b, pos, len) { needed = len; outpos = pos; output = b; - if( len > 0 ) - while( inflateLoop() ) { - } + if (len > 0) + while (inflateLoop()) {} return len - needed; } function getBits(n) { - while( nbits < n ) { + while (nbits < n) { bits |= input.readByte() << nbits; nbits += 8; } @@ -165,7 +177,7 @@ class InflateImpl { } function getBit() { - if( nbits == 0 ) { + if (nbits == 0) { nbits = 8; bits = input.readByte(); } @@ -176,12 +188,12 @@ class InflateImpl { } function getRevBits(n) { - return if( n == 0 ) + return if (n == 0) 0 - else if( getBit() ) - (1 << (n - 1)) | getRevBits(n-1) + else if (getBit()) + (1 << (n - 1)) | getRevBits(n - 1) else - getRevBits(n-1); + getRevBits(n - 1); } function resetBits() { @@ -189,188 +201,200 @@ class InflateImpl { nbits = 0; } - function addBytes(b,p,len) { - window.addBytes(b,p,len); - output.blit(outpos,b,p,len); + function addBytes(b, p, len) { + window.addBytes(b, p, len); + output.blit(outpos, b, p, len); needed -= len; outpos += len; } function addByte(b) { window.addByte(b); - output.set(outpos,b); + output.set(outpos, b); needed--; outpos++; } function addDistOne(n) { var c = window.getLastChar(); - for( i in 0...n ) + for (i in 0...n) addByte(c); } - function addDist(d,len) { - addBytes(window.buffer,window.pos - d,len); + function addDist(d, len) { + addBytes(window.buffer, window.pos - d, len); } function applyHuffman(h) { - return switch(h) { - case Found(n): n; - case NeedBit(a,b): applyHuffman(getBit()?b:a); - case NeedBits(n,tbl): applyHuffman(tbl[getBits(n)]); + return switch (h) { + case Found(n): n; + case NeedBit(a, b): applyHuffman(getBit() ? b : a); + case NeedBits(n, tbl): applyHuffman(tbl[getBits(n)]); } } - function inflateLengths(a,max) { + function inflateLengths(a, max) { var i = 0; var prev = 0; - while( i < max ) { + while (i < max) { var n = applyHuffman(huffman); - switch( n ) { - case 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15: - prev = n; - a[i] = n; - i++; - case 16: - var end = i + 3 + getBits(2); - if( end > max ) throw "Invalid data"; - while( i < end ) { - a[i] = prev; + switch (n) { + case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15: + prev = n; + a[i] = n; i++; - } - case 17: - i += 3 + getBits(3); - if( i > max ) throw "Invalid data"; - case 18: - i += 11 + getBits(7); - if( i > max ) throw "Invalid data"; - default: - throw "Invalid data"; + case 16: + var end = i + 3 + getBits(2); + if (end > max) + throw "Invalid data"; + while (i < end) { + a[i] = prev; + i++; + } + case 17: + i += 3 + getBits(3); + if (i > max) + throw "Invalid data"; + case 18: + i += 11 + getBits(7); + if (i > max) + throw "Invalid data"; + default: + throw "Invalid data"; } } } function inflateLoop() { - switch( state ) { - case Head: - var cmf = input.readByte(); - var cm = cmf & 15; - var cinfo = cmf >> 4; - if( cm != 8 ) throw "Invalid data"; - var flg = input.readByte(); - //var fcheck = flg & 31; - var fdict = flg & 32 != 0; - //var flevel = flg >> 6; - if( ((cmf << 8) + flg) % 31 != 0 ) throw "Invalid data"; - if( fdict ) throw "Unsupported dictionary"; - state = Block; - return true; - case Crc: - var calc = window.checksum(); - if( calc == null ) { - state = Done; + switch (state) { + case Head: + var cmf = input.readByte(); + var cm = cmf & 15; + var cinfo = cmf >> 4; + if (cm != 8) + throw "Invalid data"; + var flg = input.readByte(); + // var fcheck = flg & 31; + var fdict = flg & 32 != 0; + // var flevel = flg >> 6; + if (((cmf << 8) + flg) % 31 != 0) + throw "Invalid data"; + if (fdict) + throw "Unsupported dictionary"; + state = Block; return true; - } - var crc = Adler32.read(input); - if( !calc.equals(crc) ) throw "Invalid CRC"; - state = Done; - return true; - case Done: - // nothing - return false; - case Block: - isFinal = getBit(); - switch( getBits(2) ) { - case 0: // no compression - len = input.readUInt16(); - var nlen = input.readUInt16(); - if( nlen != 0xFFFF - len ) throw "Invalid data"; - state = Flat; - var r = inflateLoop(); - resetBits(); - return r; - case 1: // fixed Huffman - huffman = buildFixedHuffman(); - huffdist = null; - state = CData; - return true; - case 2: // dynamic Huffman - var hlit = getBits(5) + 257; - var hdist = getBits(5) + 1; - var hclen = getBits(4) + 4; - for( i in 0...hclen ) - lengths[CODE_LENGTHS_POS[i]] = getBits(3); - for( i in hclen...19 ) - lengths[CODE_LENGTHS_POS[i]] = 0; - huffman = htools.make(lengths,0,19,8); - var lengths = new Array(); - for( i in 0...hlit + hdist ) - lengths.push(0); - inflateLengths(lengths,hlit + hdist); - huffdist = htools.make(lengths,hlit,hdist,16); - huffman = htools.make(lengths,0,hlit,16); - state = CData; + case Crc: + var calc = window.checksum(); + if (calc == null) { + state = Done; + return true; + } + var crc = Adler32.read(input); + if (!calc.equals(crc)) + throw "Invalid CRC"; + state = Done; return true; - default: - throw "Invalid data"; - } - case Flat: - var rlen = (len < needed) ? len : needed; - var bytes = input.read(rlen); - len -= rlen; - addBytes(bytes,0,rlen); - if( len == 0 ) state = isFinal ? Crc : Block; - return needed > 0; - case DistOne: - var rlen = (len < needed) ? len : needed; - addDistOne(rlen); - len -= rlen; - if( len == 0 ) state = CData; - return needed > 0; - case Dist: - while( len > 0 && needed > 0 ) { - var rdist = (len < dist) ? len : dist; - var rlen = (needed < rdist) ? needed : rdist; - addDist(dist,rlen); + case Done: + // nothing + return false; + case Block: + isFinal = getBit(); + switch (getBits(2)) { + case 0: // no compression + len = input.readUInt16(); + var nlen = input.readUInt16(); + if (nlen != 0xFFFF - len) throw "Invalid data"; + state = Flat; + var r = inflateLoop(); + resetBits(); + return r; + case 1: // fixed Huffman + huffman = buildFixedHuffman(); + huffdist = null; + state = CData; + return true; + case 2: // dynamic Huffman + var hlit = getBits(5) + 257; + var hdist = getBits(5) + 1; + var hclen = getBits(4) + 4; + for (i in 0...hclen) + lengths[CODE_LENGTHS_POS[i]] = getBits(3); + for (i in hclen...19) + lengths[CODE_LENGTHS_POS[i]] = 0; + huffman = htools.make(lengths, 0, 19, 8); + var lengths = new Array(); + for (i in 0...hlit + hdist) + lengths.push(0); + inflateLengths(lengths, hlit + hdist); + huffdist = htools.make(lengths, hlit, hdist, 16); + huffman = htools.make(lengths, 0, hlit, 16); + state = CData; + return true; + default: + throw "Invalid data"; + } + case Flat: + var rlen = (len < needed) ? len : needed; + var bytes = input.read(rlen); len -= rlen; - } - if( len == 0 ) state = CData; - return needed > 0; - case CData: - var n = applyHuffman(huffman); - if( n < 256 ) { - addByte(n); + addBytes(bytes, 0, rlen); + if (len == 0) + state = isFinal ? Crc : Block; return needed > 0; - } else if( n == 256 ) { - state = isFinal ? Crc : Block; - return true; - } else { - n -= 257; - var extra_bits = LEN_EXTRA_BITS_TBL[n]; - if( extra_bits == -1 ) throw "Invalid data"; - len = LEN_BASE_VAL_TBL[n] + getBits(extra_bits); - var dist_code = if( huffdist == null ) getRevBits(5) else applyHuffman(huffdist); - extra_bits = DIST_EXTRA_BITS_TBL[dist_code]; - if( extra_bits == -1 ) throw "Invalid data"; - dist = DIST_BASE_VAL_TBL[dist_code] + getBits(extra_bits); - if( dist > window.available() ) throw "Invalid data"; - state = (dist == 1) ? DistOne : Dist; - return true; - } + case DistOne: + var rlen = (len < needed) ? len : needed; + addDistOne(rlen); + len -= rlen; + if (len == 0) + state = CData; + return needed > 0; + case Dist: + while (len > 0 && needed > 0) { + var rdist = (len < dist) ? len : dist; + var rlen = (needed < rdist) ? needed : rdist; + addDist(dist, rlen); + len -= rlen; + } + if (len == 0) + state = CData; + return needed > 0; + case CData: + var n = applyHuffman(huffman); + if (n < 256) { + addByte(n); + return needed > 0; + } else if (n == 256) { + state = isFinal ? Crc : Block; + return true; + } else { + n -= 257; + var extra_bits = LEN_EXTRA_BITS_TBL[n]; + if (extra_bits == -1) + throw "Invalid data"; + len = LEN_BASE_VAL_TBL[n] + getBits(extra_bits); + var dist_code = if (huffdist == null) getRevBits(5) else applyHuffman(huffdist); + extra_bits = DIST_EXTRA_BITS_TBL[dist_code]; + if (extra_bits == -1) + throw "Invalid data"; + dist = DIST_BASE_VAL_TBL[dist_code] + getBits(extra_bits); + if (dist > window.available()) + throw "Invalid data"; + state = (dist == 1) ? DistOne : Dist; + return true; + } } } - public static function run( i : haxe.io.Input, ?bufsize = 65536 ) { + public static function run(i:haxe.io.Input, ?bufsize = 65536) { var buf = haxe.io.Bytes.alloc(bufsize); var output = new haxe.io.BytesBuffer(); var inflate = new InflateImpl(i); - while( true ) { - var len = inflate.readBytes(buf,0,bufsize); - output.addBytes(buf,0,len); - if( len < bufsize ) + while (true) { + var len = inflate.readBytes(buf, 0, bufsize); + output.addBytes(buf, 0, len); + if (len < bufsize) break; } return output.getBytes(); } - } diff --git a/std/haxe/zip/Reader.hx b/std/haxe/zip/Reader.hx index 6ccaf1e3552..cdb6115a432 100644 --- a/std/haxe/zip/Reader.hx +++ b/std/haxe/zip/Reader.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,15 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; + import haxe.zip.Entry; import haxe.ds.List; // see http://www.pkware.com/documents/casestudies/APPNOTE.TXT - class Reader { - - var i : haxe.io.Input; + var i:haxe.io.Input; public function new(i) { this.i = i; @@ -42,98 +42,100 @@ class Reader { var year = d >> 9; var month = (d >> 5) & 15; var day = d & 31; - return new Date(year + 1980, month-1, day, hour, min, sec << 1); + return new Date(year + 1980, month - 1, day, hour, min, sec << 1); } function readExtraFields(length) { var fields = new List(); - while( length > 0 ) { - if( length < 4 ) throw "Invalid extra fields data"; + while (length > 0) { + if (length < 4) + throw "Invalid extra fields data"; var tag = i.readUInt16(); var len = i.readUInt16(); - if( length < len ) throw "Invalid extra fields data"; - switch( tag ) { - case 0x7075: - var version = i.readByte(); - if( version != 1 ) { - var data = new haxe.io.BytesBuffer(); - data.addByte(version); - data.add(i.read(len-1)); - fields.add(FUnknown(tag,data.getBytes())); - } else { - var crc = i.readInt32(); - var name = i.read(len - 5).toString(); - fields.add(FInfoZipUnicodePath(name,crc)); - } - default: - fields.add(FUnknown(tag,i.read(len))); + if (length < len) + throw "Invalid extra fields data"; + switch (tag) { + case 0x7075: + var version = i.readByte(); + if (version != 1) { + var data = new haxe.io.BytesBuffer(); + data.addByte(version); + data.add(i.read(len - 1)); + fields.add(FUnknown(tag, data.getBytes())); + } else { + var crc = i.readInt32(); + var name = i.read(len - 5).toString(); + fields.add(FInfoZipUnicodePath(name, crc)); + } + default: + fields.add(FUnknown(tag, i.read(len))); } length -= 4 + len; } return fields; } - public function readEntryHeader() : Entry { + public function readEntryHeader():Entry { var i = this.i; var h = i.readInt32(); - if( h == 0x02014B50 || h == 0x06054B50 ) + if (h == 0x02014B50 || h == 0x06054B50) return null; - if( h != 0x04034B50 ) + if (h != 0x04034B50) throw "Invalid Zip Data"; var version = i.readUInt16(); var flags = i.readUInt16(); var utf8 = flags & 0x800 != 0; - if( (flags & 0xF7F1) != 0 ) - throw "Unsupported flags "+flags; + if ((flags & 0xF7F1) != 0) + throw "Unsupported flags " + flags; var compression = i.readUInt16(); var compressed = (compression != 0); - if( compressed && compression != 8 ) - throw "Unsupported compression "+compression; + if (compressed && compression != 8) + throw "Unsupported compression " + compression; var mtime = readZipDate(); - var crc32 : Null = i.readInt32(); + var crc32:Null = i.readInt32(); var csize = i.readInt32(); var usize = i.readInt32(); var fnamelen = i.readInt16(); var elen = i.readInt16(); var fname = i.readString(fnamelen); var fields = readExtraFields(elen); - if( utf8 ) + if (utf8) fields.push(FUtf8); var data = null; // we have a data descriptor that store the real crc/sizes // after the compressed data, let's wait for it - if( (flags & 8) != 0 ) + if ((flags & 8) != 0) crc32 = null; return { - fileName : fname, - fileSize : usize, - fileTime : mtime, - compressed : compressed, - dataSize : csize, - data : data, - crc32 : crc32, - extraFields : fields, + fileName: fname, + fileSize: usize, + fileTime: mtime, + compressed: compressed, + dataSize: csize, + data: data, + crc32: crc32, + extraFields: fields, }; } - public function read() : List { + public function read():List { var l = new List(); var buf = null; var tmp = null; - while( true ) { + while (true) { var e = readEntryHeader(); - if( e == null ) + if (e == null) break; // do we have a data descriptor? (see readEntryHeader) - if( e.crc32 == null ) { - if( e.compressed ) { + if (e.crc32 == null) { + if (e.compressed) { #if neko // enter progressive mode : we use a different input which has // a temporary buffer, this is necessary since we have to uncompress // progressively, and after that we might have pending read data // that needs to be processed var bufSize = 65536; - if( buf == null ) { + if (buf == null) { buf = new haxe.io.BufferInput(i, haxe.io.Bytes.alloc(bufSize)); tmp = haxe.io.Bytes.alloc(bufSize); i = buf; @@ -141,11 +143,11 @@ class Reader { var out = new haxe.io.BytesBuffer(); var z = new neko.zip.Uncompress(-15); z.setFlushMode(neko.zip.Flush.SYNC); - while( true ) { - if( buf.available == 0 ) + while (true) { + if (buf.available == 0) buf.refill(); var p = bufSize - buf.available; - if( p != buf.pos ) { + if (p != buf.pos) { // because of lack of "srcLen" in zip api, we need to always be stuck to the buffer end buf.buf.blit(p, buf.buf, buf.pos, buf.available); buf.pos = p; @@ -154,19 +156,20 @@ class Reader { out.addBytes(tmp, 0, r.write); buf.pos += r.read; buf.available -= r.read; - if( r.done ) break; + if (r.done) + break; } e.data = out.getBytes(); #else var bufSize = 65536; - if( tmp == null ) + if (tmp == null) tmp = haxe.io.Bytes.alloc(bufSize); var out = new haxe.io.BytesBuffer(); var z = new InflateImpl(i, false, false); - while( true ) { + while (true) { var n = z.readBytes(tmp, 0, bufSize); out.addBytes(tmp, 0, n); - if( n < bufSize ) + if (n < bufSize) break; } e.data = out.getBytes(); @@ -174,7 +177,7 @@ class Reader { } else e.data = i.read(e.dataSize); e.crc32 = i.readInt32(); - if( e.crc32 == 0x08074b50 ) + if (e.crc32 == 0x08074b50) e.crc32 = i.readInt32(); e.dataSize = i.readInt32(); e.fileSize = i.readInt32(); @@ -188,24 +191,23 @@ class Reader { return l; } - public static function readZip( i : haxe.io.Input ) { + public static function readZip(i:haxe.io.Input) { var r = new Reader(i); return r.read(); } - public static function unzip( f : Entry ) { - if( !f.compressed ) + public static function unzip(f:Entry) { + if (!f.compressed) return f.data; var c = new haxe.zip.Uncompress(-15); var s = haxe.io.Bytes.alloc(f.fileSize); - var r = c.execute(f.data,0,s,0); + var r = c.execute(f.data, 0, s, 0); c.close(); - if( !r.done || r.read != f.data.length || r.write != f.fileSize ) - throw "Invalid compressed data for "+f.fileName; + if (!r.done || r.read != f.data.length || r.write != f.fileSize) + throw "Invalid compressed data for " + f.fileName; f.compressed = false; f.dataSize = f.fileSize; f.data = s; return f.data; } - } diff --git a/std/haxe/zip/Tools.hx b/std/haxe/zip/Tools.hx index c180332af87..373f3ade8b6 100644 --- a/std/haxe/zip/Tools.hx +++ b/std/haxe/zip/Tools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,20 +19,19 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; class Tools { - - public static function compress( f : Entry, level : Int ) { - if( f.compressed ) + public static function compress(f:Entry, level:Int) { + if (f.compressed) return; // this should be optimized with a temp buffer // that would discard the first two bytes // (in order to prevent 2x mem usage for large files) - var data = haxe.zip.Compress.run( f.data, level ); + var data = haxe.zip.Compress.run(f.data, level); f.compressed = true; - f.data = data.sub(2,data.length-6); + f.data = data.sub(2, data.length - 6); f.dataSize = f.data.length; } - } diff --git a/std/haxe/zip/Uncompress.hx b/std/haxe/zip/Uncompress.hx index 3e792b06f56..55c27d8c06d 100644 --- a/std/haxe/zip/Uncompress.hx +++ b/std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,26 +19,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; class Uncompress { - - public function new( ?windowBits : Int ) { + public function new(?windowBits:Int) { throw "Not implemented for this platform"; } - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { return null; } - public function setFlushMode( f : FlushMode ) { - } + public function setFlushMode(f:FlushMode) {} - public function close() { - } + public function close() {} - public static function run( src : haxe.io.Bytes, ?bufsize : Int ) : haxe.io.Bytes { - return InflateImpl.run(new haxe.io.BytesInput(src),bufsize); + public static function run(src:haxe.io.Bytes, ?bufsize:Int):haxe.io.Bytes { + return InflateImpl.run(new haxe.io.BytesInput(src), bufsize); } - } diff --git a/std/haxe/zip/Writer.hx b/std/haxe/zip/Writer.hx index 09dd5bf4675..c340a45758d 100644 --- a/std/haxe/zip/Writer.hx +++ b/std/haxe/zip/Writer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,76 +19,86 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; import haxe.ds.List; class Writer { - - /* - * The next constant is required for computing the Central - * Directory Record(CDR) size. CDR consists of some fields - * of constant size and a filename. Constant represents - * total length of all fields with constant size for each - * file in archive - */ + /** + The next constant is required for computing the Central + Directory Record(CDR) size. CDR consists of some fields + of constant size and a filename. Constant represents + total length of all fields with constant size for each + file in archive + **/ inline static var CENTRAL_DIRECTORY_RECORD_FIELDS_SIZE = 46; - /* - * The following constant is the total size of all fields - * of Local File Header. It's required for calculating - * offset of start of central directory record - */ + /** + The following constant is the total size of all fields + of Local File Header. It's required for calculating + offset of start of central directory record + **/ inline static var LOCAL_FILE_HEADER_FIELDS_SIZE = 30; - var o : haxe.io.Output; - var files : List<{ name : String, compressed : Bool, clen : Int, size : Int, crc : Int, date : Date, fields : haxe.io.Bytes }>; + var o:haxe.io.Output; + var files:List<{ + name:String, + compressed:Bool, + clen:Int, + size:Int, + crc:Int, + date:Date, + fields:haxe.io.Bytes + }>; - public function new( o : haxe.io.Output ) { + public function new(o:haxe.io.Output) { this.o = o; files = new List(); } - function writeZipDate( date : Date ) { + function writeZipDate(date:Date) { var hour = date.getHours(); var min = date.getMinutes(); var sec = date.getSeconds() >> 1; - o.writeUInt16( (hour << 11) | (min << 5) | sec ); + o.writeUInt16((hour << 11) | (min << 5) | sec); var year = date.getFullYear() - 1980; var month = date.getMonth() + 1; var day = date.getDate(); - o.writeUInt16( (year << 9) | (month << 5) | day ); + o.writeUInt16((year << 9) | (month << 5) | day); } - public function writeEntryHeader( f : Entry ) { + public function writeEntryHeader(f:Entry) { var o = this.o; var flags = 0; if (f.extraFields != null) { - for( e in f.extraFields ) - switch( e ) { - case FUtf8: flags |= 0x800; - default: + for (e in f.extraFields) + switch (e) { + case FUtf8: + flags |= 0x800; + default: } } o.writeInt32(0x04034B50); o.writeUInt16(0x0014); // version o.writeUInt16(flags); // flags - if( f.data == null ) { + if (f.data == null) { f.fileSize = 0; f.dataSize = 0; f.crc32 = 0; f.compressed = false; f.data = haxe.io.Bytes.alloc(0); } else { - if( f.crc32 == null ) { - if( f.compressed ) throw "CRC32 must be processed before compression"; + if (f.crc32 == null) { + if (f.compressed) + throw "CRC32 must be processed before compression"; f.crc32 = haxe.crypto.Crc32.make(f.data); } - if( !f.compressed ) + if (!f.compressed) f.fileSize = f.data.length; f.dataSize = f.data.length; } - o.writeUInt16(f.compressed?8:0); + o.writeUInt16(f.compressed ? 8 : 0); writeZipDate(f.fileTime); o.writeInt32(f.crc32); o.writeInt32(f.dataSize); @@ -96,34 +106,42 @@ class Writer { o.writeUInt16(f.fileName.length); var e = new haxe.io.BytesOutput(); if (f.extraFields != null) { - for( f in f.extraFields ) - switch( f ) { - case FInfoZipUnicodePath(name,crc): - var namebytes = haxe.io.Bytes.ofString(name); - e.writeUInt16(0x7075); - e.writeUInt16(namebytes.length + 5); - e.writeByte(1); // version - e.writeInt32(crc); - e.write(namebytes); - case FUnknown(tag,bytes): - e.writeUInt16(tag); - e.writeUInt16(bytes.length); - e.write(bytes); - case FUtf8: - // nothing + for (f in f.extraFields) + switch (f) { + case FInfoZipUnicodePath(name, crc): + var namebytes = haxe.io.Bytes.ofString(name); + e.writeUInt16(0x7075); + e.writeUInt16(namebytes.length + 5); + e.writeByte(1); // version + e.writeInt32(crc); + e.write(namebytes); + case FUnknown(tag, bytes): + e.writeUInt16(tag); + e.writeUInt16(bytes.length); + e.write(bytes); + case FUtf8: + // nothing } } var ebytes = e.getBytes(); o.writeUInt16(ebytes.length); o.writeString(f.fileName); o.write(ebytes); - files.add({ name : f.fileName, compressed : f.compressed, clen : f.data.length, size : f.fileSize, crc : f.crc32, date : f.fileTime, fields : ebytes }); + files.add({ + name: f.fileName, + compressed: f.compressed, + clen: f.data.length, + size: f.fileSize, + crc: f.crc32, + date: f.fileTime, + fields: ebytes + }); } - public function write( files : List ) { - for( f in files ) { + public function write(files:List) { + for (f in files) { writeEntryHeader(f); - o.writeFullBytes(f.data,0,f.data.length); + o.writeFullBytes(f.data, 0, f.data.length); } writeCDR(); } @@ -131,46 +149,45 @@ class Writer { public function writeCDR() { var cdr_size = 0; var cdr_offset = 0; - for ( f in files ) { + for (f in files) { var namelen = f.name.length; var extraFieldsLength = f.fields.length; o.writeInt32(0x02014B50); // header o.writeUInt16(0x0014); // version made-by o.writeUInt16(0x0014); // version o.writeUInt16(0); // flags - o.writeUInt16(f.compressed?8:0); + o.writeUInt16(f.compressed ? 8 : 0); writeZipDate(f.date); o.writeInt32(f.crc); o.writeInt32(f.clen); o.writeInt32(f.size); o.writeUInt16(namelen); o.writeUInt16(extraFieldsLength); - o.writeUInt16(0); //comment length always 0 - o.writeUInt16(0); //disk number start - o.writeUInt16(0); //internal file attributes - o.writeInt32(0); //external file attributes - o.writeInt32(cdr_offset); //relative offset of local header + o.writeUInt16(0); // comment length always 0 + o.writeUInt16(0); // disk number start + o.writeUInt16(0); // internal file attributes + o.writeInt32(0); // external file attributes + o.writeInt32(cdr_offset); // relative offset of local header o.writeString(f.name); o.write(f.fields); cdr_size += CENTRAL_DIRECTORY_RECORD_FIELDS_SIZE + namelen + extraFieldsLength; cdr_offset += LOCAL_FILE_HEADER_FIELDS_SIZE + namelen + extraFieldsLength + f.clen; } - //end of central dir signature + // end of central dir signature o.writeInt32(0x06054B50); - //number of this disk + // number of this disk o.writeUInt16(0); - //number of the disk with the start of the central directory + // number of the disk with the start of the central directory o.writeUInt16(0); - //total number of entries in the central directory on this disk + // total number of entries in the central directory on this disk o.writeUInt16(files.length); - //total number of entries in the central directory + // total number of entries in the central directory o.writeUInt16(files.length); - //size of the central directory record + // size of the central directory record o.writeInt32(cdr_size); - //offset of start of central directory with respect to the starting disk number + // offset of start of central directory with respect to the starting disk number o.writeInt32(cdr_offset); // .ZIP file comment length o.writeUInt16(0); } - } diff --git a/std/hl/Abstract.hx b/std/hl/Abstract.hx index b3b99d7ad64..c02f0c5b4b2 100644 --- a/std/hl/Abstract.hx +++ b/std/hl/Abstract.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; -extern class Abstract { -} \ No newline at end of file +extern class Abstract {} diff --git a/std/hl/Api.hx b/std/hl/Api.hx index f79f6d77a1c..9949ec656aa 100644 --- a/std/hl/Api.hx +++ b/std/hl/Api.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,23 +19,26 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; extern class Api { - - static inline function rethrow( v : Dynamic ) : Void { untyped $rethrow(v); } - @:hlNative("std","obj_get_field") static function getField( obj : Dynamic, hash : Int ) : Dynamic; - @:hlNative("std","obj_set_field") static function setField( obj : Dynamic, hash : Int, value : Dynamic ) : Void; - @:hlNative("std","obj_has_field") static function hasField( obj : Dynamic, hash : Int ) : Bool; - @:hlNative("std","obj_delete_field") static function deleteField( obj : Dynamic, hash : Int ) : Bool; - @:hlNative("std","call_method") static function callMethod( f : haxe.Constraints.Function, args : NativeArray ) : Dynamic; - @:hlNative("std","get_closure_value") static function getClosureValue( f : haxe.Constraints.Function ) : Dynamic; - @:hlNative("std","no_closure") static function noClosure( f : haxe.Constraints.Function ) : haxe.Constraints.Function; - @:hlNative("std", "value_cast") static function safeCast( v : Dynamic, t : Type ) : Dynamic; - @:hlNative("std", "make_var_args") static function makeVarArgs( v : NativeArray -> Dynamic ) : haxe.Constraints.Function; - @:hlNative("std", "get_virtual_value") static function getVirtualValue( v : Dynamic ) : Dynamic; - @:hlNative("std", "set_error_handler") static function setErrorHandler( v : Dynamic -> Void ) : Void; - @:hlNative("std", "breakpoint") static function breakPoint() : Void; - @:hlNative("std", "sys_is64") static function is64() : Bool; - + static inline function rethrow(v:Dynamic):Void { + untyped $rethrow(v); + } + @:hlNative("std", "obj_get_field") static function getField(obj:Dynamic, hash:Int):Dynamic; + @:hlNative("std", "obj_set_field") static function setField(obj:Dynamic, hash:Int, value:Dynamic):Void; + @:hlNative("std", "obj_has_field") static function hasField(obj:Dynamic, hash:Int):Bool; + @:hlNative("std", "obj_delete_field") static function deleteField(obj:Dynamic, hash:Int):Bool; + @:hlNative("std", "call_method") static function callMethod(f:haxe.Constraints.Function, args:NativeArray):Dynamic; + @:hlNative("std", "get_closure_value") static function getClosureValue(f:haxe.Constraints.Function):Dynamic; + @:hlNative("std", "make_closure") static function makeClosure(f:haxe.Constraints.Function, v:Dynamic):Dynamic; + @:hlNative("std", "no_closure") static function noClosure(f:haxe.Constraints.Function):haxe.Constraints.Function; + @:hlNative("std", "value_cast") static function safeCast(v:Dynamic, t:Type):Dynamic; + @:hlNative("std", "make_var_args") static function makeVarArgs(v:NativeArray->Dynamic):haxe.Constraints.Function; + @:hlNative("std", "get_virtual_value") static function getVirtualValue(v:Dynamic):Dynamic; + @:hlNative("std", "set_error_handler") static function setErrorHandler(v:Dynamic->Void):Void; + @:hlNative("std", "breakpoint") static function breakPoint():Void; + @:hlNative("std", "sys_is64") static function is64():Bool; + @:hlNative("std", "ptr_compare") static function comparePointer(a:Dynamic, b:Dynamic):Int; } diff --git a/std/hl/BaseType.hx b/std/hl/BaseType.hx index 76eee600bd9..80ead1c8a04 100644 --- a/std/hl/BaseType.hx +++ b/std/hl/BaseType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,26 +19,29 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; @:keep class BaseType { - public var __type__ : Type; - public var __meta__ : Dynamic; - public var __implementedBy__ : NativeArray; - public function check( v : Dynamic ) { + public var __type__:Type; + public var __meta__:Dynamic; + public var __implementedBy__:NativeArray; + + public function check(v:Dynamic) { var t = Type.getDynamic(v); - if( t.kind == HVirtual ) { + if (t.kind == HVirtual) { var v2 = hl.Api.getVirtualValue(v); - if( v2 != null ) t = Type.getDynamic(v2); + if (v2 != null) + t = Type.getDynamic(v2); } - if( __implementedBy__ == null ) { - if( t.safeCast(__type__) ) + if (__implementedBy__ == null) { + if (t.safeCast(__type__)) return true; return false; } - for( i in __implementedBy__ ) - if( t.safeCast(i) ) + for (i in __implementedBy__) + if (t.safeCast(i)) return true; return false; } @@ -46,22 +49,20 @@ class BaseType { @:keep class Class extends BaseType { - public var __name__ : String; - public var __constructor__ : Dynamic; + public var __name__:String; + public var __constructor__:Dynamic; } @:keep class Enum extends BaseType { - public var __ename__ : String; - public var __emap__ : hl.types.BytesMap; - public var __constructs__ : Array; - public var __evalues__ : NativeArray; + public var __ename__:String; + public var __emap__:hl.types.BytesMap; + public var __constructs__:Array; + public var __evalues__:NativeArray; } @:keep -class CoreType extends Class { -} +class CoreType extends Class {} @:keep -class CoreEnum extends Enum { -} +class CoreEnum extends Enum {} diff --git a/std/hl/Boot.hx b/std/hl/Boot.hx index 680e2239cdd..ca16c51ce5e 100644 --- a/std/hl/Boot.hx +++ b/std/hl/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,11 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; import hl.types.ArrayDyn; import hl.BaseType; @:dox(hide) -extern class Boot { -} +extern class Boot {} diff --git a/std/hl/Bytes.hx b/std/hl/Bytes.hx index 6403948c0ee..9e038baabd4 100644 --- a/std/hl/Bytes.hx +++ b/std/hl/Bytes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,203 +19,204 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; @:coreType abstract Bytes { - - @:extern public inline function new( v : Int ) { + extern public inline function new(v:Int) { this = alloc(v); } - @:hlNative("std","bytes_blit") public function blit( pos : Int, src : Bytes, srcPos : Int, len : Int ) : Void { - } + @:hlNative("std", "bytes_blit") public function blit(pos:Int, src:Bytes, srcPos:Int, len:Int):Void {} - @:extern @:arrayAccess public inline function getUI8( pos : Int ) : Int { - return untyped $bgetui8(this,pos); + @:arrayAccess extern public inline function getUI8(pos:Int):Int { + return untyped $bgetui8(this, pos); } - @:extern @:arrayAccess public inline function setUI8( pos : Int, value : Int ) : Int { - untyped $bsetui8(this,pos,value); + @:arrayAccess extern public inline function setUI8(pos:Int, value:Int):Int { + untyped $bsetui8(this, pos, value); return value; } - @:extern public inline function getI32( pos : Int ) : Int { - return untyped $bgeti32(this,pos); + extern public inline function getI32(pos:Int):Int { + return untyped $bgeti32(this, pos); } - public inline function getUI16( pos : Int ) : Int { + public inline function getUI16(pos:Int):Int { return untyped $bgetui16(this, pos); } - public inline function setUI16( pos : Int, v : Int ) { - untyped $bsetui16(this,pos,v); + public inline function setUI16(pos:Int, v:Int) { + untyped $bsetui16(this, pos, v); } - @:extern public inline function getF32( pos : Int ) : F32 { - return untyped $bgetf32(this,pos); + extern public inline function getF32(pos:Int):F32 { + return untyped $bgetf32(this, pos); } - @:extern public inline function getF64( pos : Int ) : Float { - return untyped $bgetf64(this,pos); + extern public inline function getF64(pos:Int):Float { + return untyped $bgetf64(this, pos); } - @:extern public inline function setI32( pos : Int, value : Int ) : Void { + extern public inline function setI32(pos:Int, value:Int):Void { untyped $bseti32(this, pos, value); } - @:extern public inline function setF32( pos : Int, value : F32 ) : Void { + extern public inline function setF32(pos:Int, value:F32):Void { untyped $bsetf32(this, pos, value); } - @:extern public inline function setF64( pos : Int, value : Float ) : Void { + extern public inline function setF64(pos:Int, value:Float):Void { untyped $bsetf64(this, pos, value); } - @:hlNative("std","alloc_bytes") - static function alloc( size : Int ) : Bytes { + @:hlNative("std", "alloc_bytes") + static function alloc(size:Int):Bytes { return null; } - @:hlNative("std","parse_int") - public function parseInt( pos : Int, size : Int ) : Null { + @:hlNative("std", "parse_int") + public function parseInt(pos:Int, size:Int):Null { return null; } - @:hlNative("std","parse_float") - public function parseFloat( pos : Int, size : Int ) : Float { + @:hlNative("std", "parse_float") + public function parseFloat(pos:Int, size:Int):Float { return 0.; } - @:hlNative("std","bytes_compare") - public function compare( pos : Int, bytes : Bytes, bytesPos : Int, size : Int ) : Int { + @:hlNative("std", "bytes_compare") + public function compare(pos:Int, bytes:Bytes, bytesPos:Int, size:Int):Int { return 0; } - @:hlNative("std","bytes_find") - public function find( pos : Int, size : Int, bytes : Bytes, bytesPos : Int, bytesSize : Int ) : Int { + #if (hl_ver >= version("1.10.0")) + @:hlNative("std", "bytes_compare16") + public function compare16(bytes:Bytes, size:Int):Int { return 0; } + #end - @:hlNative("std","bytes_fill") - public function fill( pos : Int, size : Int, v : Int ) : Void { + @:hlNative("std", "bytes_find") + public function find(pos:Int, size:Int, bytes:Bytes, bytesPos:Int, bytesSize:Int):Int { + return 0; } - @:hlNative("std","bsort_i32") - public function sortI32( pos : Int, length : Int, f : Int->Int->Int ) : Void { - } + @:hlNative("std", "bytes_fill") + public function fill(pos:Int, size:Int, v:Int):Void {} - @:hlNative("std","bsort_f64") - public function sortF64( pos : Int, length : Int, f : Float->Float->Int ) : Void { - } + @:hlNative("std", "bsort_i32") + public function sortI32(pos:Int, length:Int, f:Int->Int->Int):Void {} + @:hlNative("std", "bsort_f64") + public function sortF64(pos:Int, length:Int, f:Float->Float->Int):Void {} /** Please note that you need to retain the original unoffset'ed Bytes so it does not get garbage collected, unless the pointer was not GC allocated. **/ - @:hlNative("std","bytes_offset") - public function offset( delta : Int ) : Bytes { + @:hlNative("std", "bytes_offset") + public function offset(delta:Int):Bytes { return null; } /** Returns an offset between the two pointers. This might overflow in 64 bits if the addresses of the two pointers differs by more than 4GB **/ - @:hlNative("std","bytes_subtract") - public function subtract( other : Bytes ) : Int { + @:hlNative("std", "bytes_subtract") + public function subtract(other:Bytes):Int { return 0; } @:hlNative("std", "bytes_address") - static function get_address( b : Bytes, high : Ref ) : Int { + static function get_address(b:Bytes, high:Ref):Int { return 0; } @:hlNative("std", "bytes_from_address") - static function from_address( low : Int, high : Int ) : Bytes { + static function from_address(low:Int, high:Int):Bytes { return null; } /** Creates an pointer at a given memory address (highly unsafe) **/ - public static inline function fromAddress( h : haxe.Int64 ) : Bytes { + public static inline function fromAddress(h:haxe.Int64):Bytes { return from_address(h.low, h.high); } /** Returns the address value of the bytes. On 32 bit system the upper 32 bits will always be 0 **/ - public function address() : haxe.Int64 { + public function address():haxe.Int64 { var high = 0; var low = get_address(this, high); - return haxe.Int64.make(high,low); + return haxe.Int64.make(high, low); } - public function sub( pos : Int, size : Int ) { + public function sub(pos:Int, size:Int) { var b = new Bytes(size); b.blit(0, this, pos, size); return b; } @:hlNative("std", "ucs2length") - public function ucs2Length( bytePos : Int ) : Int { + public function ucs2Length(bytePos:Int):Int { return 0; } - @:hlNative("std","hash") - function hash() : Int { + @:hlNative("std", "hash") + function hash():Int { return 0; } - @:hlNative("std","utf8_to_utf16") - public function utf8ToUtf16( bytePos : Int, outSize : Ref ) : Bytes { + @:hlNative("std", "utf8_to_utf16") + public function utf8ToUtf16(bytePos:Int, outSize:Ref):Bytes { return null; } - @:hlNative("std","utf16_to_utf8") - public function utf16ToUtf8( bytePos : Int, outSize : Ref ) : Bytes { + @:hlNative("std", "utf16_to_utf8") + public function utf16ToUtf8(bytePos:Int, outSize:Ref):Bytes { return null; } @:hlNative("std", "ucs2_upper") - function ucs2Upper( bytePos : Int, size : Int ) : Bytes { + function ucs2Upper(bytePos:Int, size:Int):Bytes { return null; } @:hlNative("std", "ucs2_lower") - function ucs2Lower( bytePos : Int, size : Int ) : Bytes { + function ucs2Lower(bytePos:Int, size:Int):Bytes { return null; } @:hlNative("std", "url_encode") - function urlEncode( outSize : Ref ) : Bytes { + function urlEncode(outSize:Ref):Bytes { return null; } @:hlNative("std", "url_decode") - function urlDecode( outSize : Ref ) : Bytes { + function urlDecode(outSize:Ref):Bytes { return null; } - @:hlNative("std","value_to_string") - public static function fromValue( v : Dynamic, length : Ref ) : Bytes { + @:hlNative("std", "value_to_string") + public static function fromValue(v:Dynamic, length:Ref):Bytes { return null; } /** Get the bytes reference from an array of basic types (no copy occurs) **/ - @:extern public static inline function getArray( a : Array ) : Bytes { + extern public static inline function getArray(a:Array):Bytes { return untyped $abytes(a); } @:from - public static inline function fromBytes( bytes : haxe.io.Bytes ) { + public static inline function fromBytes(bytes:haxe.io.Bytes) { return @:privateAccess bytes.b; } - public inline function toBytes( len : Int ) { + public inline function toBytes(len:Int) { return @:privateAccess new haxe.io.Bytes(this, len); } - -} \ No newline at end of file +} diff --git a/std/hl/BytesAccess.hx b/std/hl/BytesAccess.hx index b0c8e326607..980d8b179e1 100644 --- a/std/hl/BytesAccess.hx +++ b/std/hl/BytesAccess.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,33 +19,31 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; @:coreType abstract BytesAccess from Bytes to Bytes { + public var sizeBits(get, never):Int; + public var nullValue(get, never):T; - public var sizeBits(get, never) : Int; - public var nullValue(get, never) : T; - - - @:extern inline function get_sizeBits() { + extern inline function get_sizeBits():Int { return untyped $bytes_sizebits(this); } - @:extern inline function get_nullValue() { + extern inline function get_nullValue():T { return untyped $bytes_nullvalue(this); } - @:extern public inline function blit( pos : Int, src : BytesAccess, srcPos : Int, len : Int ) : Void { - (this:Bytes).blit(pos << sizeBits, src, srcPos << sizeBits, len << sizeBits); + extern public inline function blit(pos:Int, src:BytesAccess, srcPos:Int, len:Int):Void { + (this : Bytes).blit(pos << sizeBits, src, srcPos << sizeBits, len << sizeBits); } - @:extern @:arrayAccess public inline function get( pos : Int ) : T { - return untyped $bget(this,pos); + @:arrayAccess extern public inline function get(pos:Int):T { + return untyped $bget(this, pos); } - @:extern @:arrayAccess public inline function set( pos : Int, value : T ) : T { - untyped $bset(this,pos,value); + @:arrayAccess extern public inline function set(pos:Int, value:T):T { + untyped $bset(this, pos, value); return value; } - -} \ No newline at end of file +} diff --git a/std/hl/F32.hx b/std/hl/F32.hx index 8cca901c59d..78cb04dad2c 100644 --- a/std/hl/F32.hx +++ b/std/hl/F32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; -typedef F32 = Single; \ No newline at end of file +typedef F32 = Single; diff --git a/std/hl/F64.hx b/std/hl/F64.hx index 02b74c385fa..ea633bcf2d0 100644 --- a/std/hl/F64.hx +++ b/std/hl/F64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; typedef F64 = Float; diff --git a/std/hl/Format.hx b/std/hl/Format.hx index c57d2278256..6090898077e 100644 --- a/std/hl/Format.hx +++ b/std/hl/Format.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,50 +19,91 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; -@:enum abstract PixelFormat(Int) { - var RGB = 0; - var BGR = 1; - var RGBX = 2; - var BGRX = 3; - var XBGR = 4; - var XRGB = 5; - var GRAY = 6; - var RGBA = 7; - var BGRA = 8; - var ABGR = 9; - var ARGB = 10; - var CMYK = 11; +enum abstract PixelFormat(Int) { + var RGB = 0; + var BGR = 1; + var RGBX = 2; + var BGRX = 3; + var XBGR = 4; + var XRGB = 5; + var GRAY = 6; + var RGBA = 7; + var BGRA = 8; + var ABGR = 9; + var ARGB = 10; + var CMYK = 11; } /** These are the bindings for the HL `fmt.hdll` library, which contains various low level formats handling. **/ class Format { - /** Decode JPG data into the target buffer. **/ - @:hlNative("fmt","jpg_decode") - public static function decodeJPG( src : hl.Bytes, srcLen : Int, dst : hl.Bytes, width : Int, height : Int, stride : Int, format : PixelFormat, flags : Int ) : Bool { + @:hlNative("fmt", "jpg_decode") + public static function decodeJPG(src:hl.Bytes, srcLen:Int, dst:hl.Bytes, width:Int, height:Int, stride:Int, format:PixelFormat, flags:Int):Bool { return false; } /** Decode PNG data into the target buffer. **/ - @:hlNative("fmt","png_decode") - public static function decodePNG( src : hl.Bytes, srcLen : Int, dst : hl.Bytes, width : Int, height : Int, stride : Int, format : PixelFormat, flags : Int ) : Bool { + @:hlNative("fmt", "png_decode") + public static function decodePNG(src:hl.Bytes, srcLen:Int, dst:hl.Bytes, width:Int, height:Int, stride:Int, format:PixelFormat, flags:Int):Bool { return false; } + /** + Decode any image data into ARGB pixels + **/ + #if (hl_ver >= version("1.10.0")) + @:hlNative("fmt", "dxt_decode") + public static function decodeDXT(src:hl.Bytes, dst:hl.Bytes, width:Int, height:Int, dxtFormat:Int):Bool { + return false; + } + #end + /** Upscale/downscale an image. Currently supported flag bits: 1 = bilinear filtering **/ - @:hlNative("fmt","img_scale") - public static function scaleImage( out : hl.Bytes, outPos : Int, outStride : Int, outWidth : Int, outHeight : Int, _in : hl.Bytes, inPos : Int, inStride : Int, inWidth : Int, inHeight : Int, flags : Int ) { + @:hlNative("fmt", "img_scale") + public static function scaleImage(out:hl.Bytes, outPos:Int, outStride:Int, outWidth:Int, outHeight:Int, _in:hl.Bytes, inPos:Int, inStride:Int, + inWidth:Int, inHeight:Int, flags:Int) {} + + /** + Performs a cryptographic digest of some bytes. + 0 = Md5 , 1 = Sha1 , 2 = Crc32, 3 = Adler32 + Set 256 flag to tell the src are String bytes. + **/ + @:hlNative("fmt", "digest") + public static function digest(out:hl.Bytes, src:hl.Bytes, srcLen:Int, algorithm:Int) {} +} + +class Mikktspace { + public var buffer:hl.BytesAccess; + public var stride:Int; + public var xPos:Int; + public var normalPos:Int; + public var uvPos:Int; + public var tangents:hl.BytesAccess; + public var tangentStride:Int; + public var tangentPos:Int; + public var indexes:hl.BytesAccess; + public var indices:Int; + + public function new() {} + + public function compute(threshold = 180.) { + if (!_compute(this, threshold)) + throw "assert"; } -} \ No newline at end of file + @:hlNative("fmt", "compute_mikkt_tangents") static function _compute(m:Dynamic, threshold:Float):Bool { + return false; + } +} diff --git a/std/hl/Gc.hx b/std/hl/Gc.hx index f1abf5aea56..03df18e2f08 100644 --- a/std/hl/Gc.hx +++ b/std/hl/Gc.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; enum GcFlag { @@ -26,49 +27,66 @@ enum GcFlag { Activate profiling: regularly print on stdout gc allocation stats **/ Profile; + /** Allows one to dump a hlmemory.dump file when HL runs out of memory to be examined with hl memory inspector tool. **/ DumpMem; + /** - Enable allocation tracking + Disable GC locking for multithreads **/ - Track; + NoThreads; + + /** + Force major GC on each allocation + **/ + ForceMajor; } class Gc { - - public static var flags(get,set) : haxe.EnumFlags; + public static var flags(get, set):haxe.EnumFlags; public static function stats() { var tot = 0., count = 0., mem = 0.; _stats(tot, count, mem); - return { totalAllocated : tot, allocationCount : count, currentMemory : mem }; + return {totalAllocated: tot, allocationCount: count, currentMemory: mem}; } /** Dump whole memory into target filename for analysis. **/ - public static function dumpMemory( ?fileName : String = "hlmemory.dump" ) { + public static function dumpMemory(?fileName:String = "hlmemory.dump") { _dump(@:privateAccess fileName.toUtf8()); } - static function get_flags() : haxe.EnumFlags { + static function get_flags():haxe.EnumFlags { return haxe.EnumFlags.ofInt(_get_flags()); } - static function set_flags(v : haxe.EnumFlags) { + static function set_flags(v:haxe.EnumFlags) { _set_flags(v.toInt()); return v; } - @:hlNative("std", "gc_dump_memory") static function _dump( b : hl.Bytes ) : Void {} + /** + Enter/leave a blocking section: when in a blocking section the thread cannot + allocate any memory but other threads will not wait for it for collecting memory. + **/ + @:hlNative("std", "blocking") + public static function blocking(b:Bool) {} + + @:hlNative("std", "gc_dump_memory") static function _dump(b:hl.Bytes):Void {} - @:hlNative("std", "gc_enable") public static function enable( b : Bool ) : Void {} - @:hlNative("std", "gc_major") public static function major() : Void {} - @:hlNative("std", "gc_stats") static function _stats( totalAllocated : hl.Ref, allocationCount : hl.Ref, currentMemory : hl.Ref ) : Void {} + @:hlNative("std", "gc_enable") public static function enable(b:Bool):Void {} - @:hlNative("std", "gc_get_flags") static function _get_flags() : Int { return 0; } - @:hlNative("std", "gc_set_flags") static function _set_flags( v : Int ) {} + @:hlNative("std", "gc_major") public static function major():Void {} + + @:hlNative("std", "gc_stats") static function _stats(totalAllocated:hl.Ref, allocationCount:hl.Ref, currentMemory:hl.Ref):Void {} + + @:hlNative("std", "gc_get_flags") static function _get_flags():Int { + return 0; + } + @:hlNative("std", "gc_set_flags") static function _set_flags(v:Int) {} } diff --git a/std/hl/I64.hx b/std/hl/I64.hx index b00d40c9496..c447d04af45 100644 --- a/std/hl/I64.hx +++ b/std/hl/I64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; @:coreType @:notNull @:runtimeValue abstract I64 to Int from Int {} diff --git a/std/hl/NativeArray.hx b/std/hl/NativeArray.hx index 48284bc612e..18d3173f552 100644 --- a/std/hl/NativeArray.hx +++ b/std/hl/NativeArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,12 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; @:generic class NativeArrayIterator { - var arr : NativeArray; - var pos : Int; - var length : Int; + var arr:NativeArray; + var pos:Int; + var length:Int; public inline function new(arr:NativeArray) { this.arr = arr; @@ -42,41 +43,38 @@ package hl; } @:coreType abstract NativeArray { + public var length(get, never):Int; - public var length(get,never):Int; - - @:extern public inline function new( length : Int ) { + extern public inline function new(length:Int) { this = untyped $aalloc(length); } - @:extern inline function get_length() : Int { + extern inline function get_length():Int { return untyped $asize(this); } - @:extern @:arrayAccess inline function get( pos : Int ) : T { - return untyped ($aget(this,pos):T); + @:arrayAccess extern inline function get(pos:Int):T { + return untyped ($aget(this, pos) : T); } - @:extern @:arrayAccess inline function set( pos : Int, value : T ) : T { - untyped $aset(this,pos,value); + @:arrayAccess extern inline function set(pos:Int, value:T):T { + untyped $aset(this, pos, value); return value; } - @:extern public inline function sub( pos : Int, len : Int ) { + extern public inline function sub(pos:Int, len:Int) { var n = new NativeArray(len); n.blit(0, this, pos, len); return n; } - @:to @:extern public inline function getRef() : Ref { + @:to extern public inline function getRef():Ref { return untyped $refdata(this); } - @:hlNative("std","array_type") public function getType() : Type { + @:hlNative("std", "array_type") public function getType():Type { return null; } - @:hlNative("std","array_blit") public function blit( pos : Int, src : NativeArray, srcPos : Int, srcLen : Int ) : Void { - } - -} \ No newline at end of file + @:hlNative("std", "array_blit") public function blit(pos:Int, src:NativeArray, srcPos:Int, srcLen:Int):Void {} +} diff --git a/std/hl/Profile.hx b/std/hl/Profile.hx index 4c36476dd72..6d4039a9dc4 100644 --- a/std/hl/Profile.hx +++ b/std/hl/Profile.hx @@ -1,17 +1,49 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package hl; typedef Symbol = hl.Abstract<"hl_symbol">; -class Allocation { - public var t : hl.Type; - public var count : Int; - public var size : Int; - public var stack : Array; - public function new(t, count, size) { +enum TrackKind { + Alloc; + Cast; + DynField; + DynCall; +} + +class Result { + public var t:hl.Type; + public var kind:TrackKind; + public var count:Int; + public var info:Int; + public var stack:Array; + + public function new(t, count, info) { this.t = t; this.count = count; - this.size = size; + this.info = info; } + @:keep public function toString() { return t + "(" + count + ")"; } @@ -19,71 +51,171 @@ class Allocation { @:hlNative("std") class Profile { + public static var threadBits(get, set):haxe.EnumFlags; + public static var globalBits(get, set):haxe.EnumFlags; - public static var enable(get, set) : Bool; + static var KINDS = null; - public static function getData() { - var old = enable; - enable = false; + public static function getData(sortBySize = false, reset = true) { + var old = globalBits; + globalBits = new haxe.EnumFlags(); + if (buf == null) + buf = new hl.Bytes(BUFSIZE * 2); + track_lock(true); var maxDepth = 0; var count = track_count(maxDepth); var arr = new hl.NativeArray(maxDepth); var out = []; - for( i in 0...count ) { - var t : hl.Type = null, count = 0, size = 0; - track_entry(i, t, count, size, arr); - if( count == 0 ) continue; - var a = new Allocation(t, count, size); - a.stack = [for( a in arr ) resolveSymbol(a)]; + if (KINDS == null) + KINDS = TrackKind.createAll(); + for (i in 0...count) { + var t:hl.Type = null, count = 0, info = 0; + var k = track_entry(i, t, count, info, arr); + if (count == 0) + continue; + var a = new Result(t, count, info); + a.kind = KINDS[k]; + a.stack = [for (a in arr) resolveSymbol(a)]; out.push(a); } - out.sort(function(a1, a2) return a2.count - a1.count); - enable = old; + out.sort(function(a1, a2) { + if (a1.kind != a2.kind) + return a1.kind.getIndex() - a2.kind.getIndex(); + if (sortBySize && a1.kind == Alloc) + return a2.info - a1.info; + return a2.count - a1.count; + }); + track_lock(false); + if (reset) + Profile.reset(); + globalBits = old; return out; } - public static function dump( fileName = "alloc.dump" ) { - var d = getData(); - var old = enable; - enable = false; + public static function dump(fileName = "track.dump", sortBySize = false, reset = true) { + var old = globalBits; + globalBits = new haxe.EnumFlags(); var f = sys.io.File.write(fileName); - var data = getData(); - var count = 0, size = 0; - for( o in data ) { - count += o.count; - size += o.size; + var data = getData(sortBySize, reset); + var allocCount = 0, allocSize = 0, castCount = 0, dynCount = 0; + for (o in data) { + switch (o.kind) { + case Alloc: + allocCount += o.count; + allocSize += o.info; + case Cast: + castCount += o.count; + case DynCall, DynField: + dynCount += o.count; + } } - f.writeString(count +" total allocs (" + size+" bytes)\n"); - for( o in data ) { - f.writeString(o.count+" "+o.t + " (" + o.size + " bytes)\n"); - for( s in o.stack ) - f.writeString("\t" + s + "\n"); + if (data.length == 0) + f.writeString("Nothing\n"); + if (allocCount > 0) + f.writeString(allocCount + " total allocs (" + allocSize + " bytes)\n"); + if (castCount > 0) + f.writeString(castCount + " total casts\n"); + if (dynCount > 0) + f.writeString(dynCount + " total dynamic accesses/calls\n"); + for (o in data) { + var pcount = StringTools.lpad("" + o.count, " ", 5); + switch (o.kind) { + case Alloc: + f.writeString("alloc " + pcount + " " + o.t + " (" + o.info + " bytes)\n"); + case Cast: + f.writeString("cast " + pcount + " " + o.t + "\n"); + case DynCall: + f.writeString("dyncall " + pcount + " " + o.t + "." + getFieldName(o.info) + "()\n"); + case DynField: + f.writeString("dynfield " + pcount + " " + o.t + "." + getFieldName(o.info) + "\n"); + } + for (s in o.stack) + f.writeString("\t\t\t\t" + s + "\n"); } f.close(); - enable = old; + globalBits = old; + } + + /** + Reset accumulated tracked data. + **/ + @:hlNative("std", "track_reset") public static function reset() {} + + /** + Restart tracking after being stopped. + **/ + @:hlNative("std", "track_init") public static function restart() {} + + /** + Stop tracking for all threads. + **/ + public static function stop() { + globalBits = new haxe.EnumFlags(); + } + + /** + Set maximum stack depth for reports (default = 10) + **/ + @:hlNative("std", "track_set_depth") public static function setMaxDepth(v:Int) {} + + static function get_threadBits() + return new haxe.EnumFlags(track_get_bits(true)); + + static function set_threadBits(v:haxe.EnumFlags) { + track_set_bits(v.toInt(), true); + return v; + } + + static function get_globalBits() + return new haxe.EnumFlags(track_get_bits(false)); + + static function set_globalBits(v:haxe.EnumFlags) { + track_set_bits(v.toInt(), false); + return v; } static var BUFSIZE = 512; - static var buf = new hl.Bytes(BUFSIZE*2); - static function resolveSymbol( s : Symbol ) { + static var buf:hl.Bytes; + + static function resolveSymbol(s:Symbol) { var size = BUFSIZE; + if (buf == null) + buf = new hl.Bytes(BUFSIZE * 2); var bytes = resolve_symbol(s, buf, size); - if( bytes == null ) return ""; - return @:privateAccess String.fromUCS2(bytes.sub(0,(size+1)*2)); + if (bytes == null) + return ""; + return @:privateAccess String.fromUCS2(bytes.sub(0, (size + 1) * 2)); } - static function get_enable() return Gc.flags.has(Track); - static function set_enable(v) { - var flags = Gc.flags; - if( v ) flags.set(Track) else flags.unset(Track); - Gc.flags = flags; - return v; + static function resolve_symbol(s:Symbol, buf:hl.Bytes, bufSize:hl.Ref):hl.Bytes { + return null; + } + + static function track_count(maxDepth:hl.Ref):Int { + return 0; + } + + static function track_entry(id:Int, type:hl.Ref, count:hl.Ref, info:hl.Ref, stack:NativeArray):Int { + return 0; } - static function resolve_symbol( s : Symbol, buf : hl.Bytes, bufSize : hl.Ref ) : hl.Bytes { return null; } - static function track_count( maxDepth : hl.Ref ) : Int { return 0; } - static function track_entry( id : Int, type : hl.Ref, count : hl.Ref, size : hl.Ref, stack : NativeArray ) : Void {} - static function track_init() : Void {} - static function __init__() track_init(); + static function track_init():Void {} + static function track_lock(b:Bool):Void {} + + static function track_get_bits(thread:Bool):Int { + return 0; + } + + static function track_set_bits(bits:Int, thread:Bool):Void {} + + static function __init__() + track_init(); + + // todo : move later to hl.Bytes + + @:hlNative("std", "field_name") + public static function getFieldName(hash:Int):Bytes { + return null; + } } diff --git a/std/hl/Ref.hx b/std/hl/Ref.hx index 009e8213202..1d08f23eab1 100644 --- a/std/hl/Ref.hx +++ b/std/hl/Ref.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,24 +19,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; +@:semantics(reference) @:coreType abstract Ref { - - @:extern @:from public static inline function make( v : T ) { + @:from extern public static inline function make(v:T) { return new Ref(v); } - @:extern public inline function new( v : T ) { + extern public inline function new(v:T) { this = untyped $ref(v); } - @:extern public inline function get() : T { + + extern public inline function get():T { return untyped $unref(this); } - @:extern public inline function set( v : T ) : Void { - return untyped $setref(this,v); + + extern public inline function set(v:T):Void { + return untyped $setref(this, v); } - @:extern public inline function offset( v : Int ) : Ref { + + extern public inline function offset(v:Int):Ref { return untyped $refoffset(this, v); } -} \ No newline at end of file +} diff --git a/std/hl/Type.hx b/std/hl/Type.hx index 386fe8b1a8c..97472175f33 100644 --- a/std/hl/Type.hx +++ b/std/hl/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,10 +19,10 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; -@:enum -abstract TypeKind(Int) { +enum abstract TypeKind(Int) { public var HVoid = 0; public var HUI8 = 1; public var HUI16 = 2; @@ -46,68 +46,68 @@ abstract TypeKind(Int) { } @:coreType abstract Type { + public var kind(get, never):TypeKind; - public var kind(get,never) : TypeKind; - - @:extern inline function get_kind() : TypeKind { + extern inline function get_kind():TypeKind { return untyped $tkind(this); } - @:hlNative("std","type_name") function getNameBytes() : Bytes { + @:hlNative("std", "type_name") function getNameBytes():Bytes { return null; } - @:extern public static inline function getDynamic( v : Dynamic ) : Type { + extern public static inline function getDynamic(v:Dynamic):Type { return untyped $tdyntype(v); } - @:extern public static inline function get( v : T ) : Type { + extern public static inline function get(v:T):Type { return untyped $ttype(v); } - @:extern public inline function getName() : String { + extern public inline function getTypeName():String { var s = getNameBytes(); + if (s == null) + return null; return @:privateAccess String.fromUCS2(s); } - @:hlNative("std", "type_safe_cast") public function safeCast( t : Type ) : Bool { + @:hlNative("std", "type_safe_cast") public function safeCast(t:Type):Bool { return false; } - @:hlNative("std","type_instance_fields") public function getInstanceFields() : NativeArray { + @:hlNative("std", "type_instance_fields") public function getInstanceFields():NativeArray { return null; } - @:hlNative("std","type_get_global") public function getGlobal() : Dynamic { + @:hlNative("std", "type_get_global") public function getGlobal():Dynamic { return null; } - @:hlNative("std","type_set_global") public function setGlobal( v : Dynamic ) : Bool { + @:hlNative("std", "type_set_global") public function setGlobal(v:Dynamic):Bool { return false; } - @:hlNative("std","type_args_count") public function getArgsCount() : Int { + @:hlNative("std", "type_args_count") public function getArgsCount():Int { return 0; } - @:hlNative("std","type_super") public function getSuper() : Type { + @:hlNative("std", "type_super") public function getSuper():Type { return null; } - @:hlNative("std","type_enum_fields") public function getEnumFields() : NativeArray { + @:hlNative("std", "type_enum_fields") public function getEnumFields():NativeArray { return null; } - @:hlNative("std","type_enum_values") public function getEnumValues() : NativeArray { + @:hlNative("std", "type_enum_values") public function getEnumValues():NativeArray { return null; } - @:hlNative("std","alloc_obj") public function allocObject() : Dynamic { + @:hlNative("std", "alloc_obj") public function allocObject():Dynamic { return null; } - @:hlNative("std", "alloc_enum_dyn") public function allocEnum( index : Int, args : NativeArray, nargs : Int ) : Dynamic { + @:hlNative("std", "alloc_enum_dyn") public function allocEnum(index:Int, args:NativeArray, nargs:Int):Dynamic { return null; } - -} \ No newline at end of file +} diff --git a/std/hl/UI.hx b/std/hl/UI.hx index b03082142ab..82735e75ff9 100644 --- a/std/hl/UI.hx +++ b/std/hl/UI.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,23 +19,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; typedef SentinelHandle = hl.Abstract<"ui_sentinel">; abstract Sentinel(SentinelHandle) { + public var pause(get, set):Bool; - public var pause(get,set) : Bool; - - public function new( timeout, callback ) { - this = create_sentinel(timeout,callback); + public function new(timeout, callback) { + this = create_sentinel(timeout, callback); } function get_pause() { return is_paused(this); } - function set_pause( p : Bool ) { + function set_pause(p:Bool) { _pause(this, p); return p; } @@ -44,27 +44,29 @@ abstract Sentinel(SentinelHandle) { _tick(this); } - @:hlNative("ui", "ui_start_sentinel") static function create_sentinel( timeout : Float, callb : Void -> Void ) : SentinelHandle { + @:hlNative("ui", "ui_start_sentinel") static function create_sentinel(timeout:Float, callb:Void->Void):SentinelHandle { return null; } - @:hlNative("ui","ui_sentinel_tick") static function _tick( h : SentinelHandle ) : Void {} - @:hlNative("ui","ui_sentinel_pause") static function _pause( h : SentinelHandle, b : Bool ) : Void {} - @:hlNative("ui","ui_sentinel_is_paused") static function is_paused( h : SentinelHandle ) : Bool { return false; } + @:hlNative("ui", "ui_sentinel_tick") static function _tick(h:SentinelHandle):Void {} + @:hlNative("ui", "ui_sentinel_pause") static function _pause(h:SentinelHandle, b:Bool):Void {} + + @:hlNative("ui", "ui_sentinel_is_paused") static function is_paused(h:SentinelHandle):Bool { + return false; + } } typedef WinHandle = hl.Abstract<"ui_window">; class Window { + var h:WinHandle; - var h : WinHandle; - - public function setText( text : String ) { + public function setText(text:String) { win_set_text(h, @:privateAccess text.bytes); } - public function setEnable( b : Bool ) { + public function setEnable(b:Bool) { win_set_enable(h, b); } @@ -72,58 +74,45 @@ class Window { win_destroy(h); } + @:hlNative("ui", "ui_win_destroy") + static function win_destroy(win:WinHandle):Void {} - @:hlNative("ui","ui_win_destroy") - static function win_destroy( win : WinHandle ) : Void { - } - - @:hlNative("ui","ui_win_set_text") - static function win_set_text( win : WinHandle, text : hl.Bytes ) : Void { - } - - @:hlNative("ui","ui_win_set_enable") - static function win_set_enable( win : WinHandle, enable : Bool ) : Void { - } - + @:hlNative("ui", "ui_win_set_text") + static function win_set_text(win:WinHandle, text:hl.Bytes):Void {} + @:hlNative("ui", "ui_win_set_enable") + static function win_set_enable(win:WinHandle, enable:Bool):Void {} } class Button extends Window { - - public function new( parent : Window, text : String ) { + public function new(parent:Window, text:String) { h = button_new(parent.h, @:privateAccess text.bytes, function() this.onClick()); } - public dynamic function onClick() { - } + public dynamic function onClick() {} @:hlNative("ui", "ui_button_new") - static function button_new( parent : WinHandle, text : hl.Bytes, onClick : Void -> Void ) : WinHandle { + static function button_new(parent:WinHandle, text:hl.Bytes, onClick:Void->Void):WinHandle { return null; } - } class WinLog extends Window { - - public function new( title : String, width, height ) { - h = winlog_new(@:privateAccess title.bytes,width, height); + public function new(title:String, width, height) { + h = winlog_new(@:privateAccess title.bytes, width, height); } - public function setTextContent( text : String, autoScroll = false ) { - winlog_set_text(h, @:privateAccess text.bytes,autoScroll); + public function setTextContent(text:String, autoScroll = false) { + winlog_set_text(h, @:privateAccess text.bytes, autoScroll); } - - @:hlNative("ui","ui_winlog_new") - static function winlog_new( text : hl.Bytes, width : Int, height : Int ) : WinHandle { + @:hlNative("ui", "ui_winlog_new") + static function winlog_new(text:hl.Bytes, width:Int, height:Int):WinHandle { return null; } - @:hlNative("ui","ui_winlog_set_text") - static function winlog_set_text( win : WinHandle, text : hl.Bytes, autoScroll : Bool ) : Void { - } - + @:hlNative("ui", "ui_winlog_set_text") + static function winlog_set_text(win:WinHandle, text:hl.Bytes, autoScroll:Bool):Void {} } enum DialogFlags { @@ -131,43 +120,98 @@ enum DialogFlags { IsError; } -@:enum abstract LoopResult(Int) { +enum abstract LoopResult(Int) { var NoMessage = 0; var HandledMessage = 1; var Quit = 2; } +typedef FileOptions = { + var ?window:Window; + var ?filters:Array<{name:String, exts:Array}>; + var ?filterIndex:Int; + var ?fileName:String; + var ?title:String; +} + /** These are the bindings for the HL `ui.hdll` library, which contains some low level system access. **/ class UI { - - @:hlNative("ui","ui_init") static function init() {} + @:hlNative("ui", "ui_init") static function init() {} static function __init__() { init(); } - @:hlNative("ui","ui_dialog") - static function _dialog( title : hl.Bytes, text : hl.Bytes, flags : Int ) : Int { + @:hlNative("ui", "ui_dialog") + static function _dialog(title:hl.Bytes, text:hl.Bytes, flags:Int):Int { return 0; } - public static function dialog( title : String, text : String, flags : haxe.EnumFlags ) { - @:privateAccess _dialog(title.bytes,text.bytes,flags.toInt()); + public static function dialog(title:String, text:String, flags:haxe.EnumFlags) { + @:privateAccess _dialog(title.bytes, text.bytes, flags.toInt()); } - @:hlNative("ui","ui_loop") - public static function loop( blocking : Bool ) : LoopResult { + @:hlNative("ui", "ui_loop") + public static function loop(blocking:Bool):LoopResult { return Quit; } - @:hlNative("ui","ui_stop_loop") - public static function stopLoop() : Void { - } - - @:hlNative("ui","ui_close_console") - public static function closeConsole() : Void { + @:hlNative("ui", "ui_stop_loop") + public static function stopLoop():Void {} + + @:hlNative("ui", "ui_close_console") + public static function closeConsole():Void {} + + public static function loadFile(opts:FileOptions) { + return chooseFile(false, opts); + } + + public static function saveFile(opts:FileOptions) { + return chooseFile(true, opts); + } + + static function chooseFile(save:Bool, opts:FileOptions) @:privateAccess { + var out:Dynamic = {}; + if (opts.fileName != null) { + var file = sys.FileSystem.absolutePath(opts.fileName); + if (Sys.systemName() == "Windows") + file = file.split("/").join("\\"); + var dir = null; + if (sys.FileSystem.isDirectory(file)) { + dir = file; + file = null; + } else { + var path = new haxe.io.Path(file); + dir = path.dir; + file = path.file + (path.ext == null ? "" : "." + path.ext); + } + if (file != null) + out.fileName = file.bytes; + if (dir != null) + out.directory = dir.bytes; + } + if (opts.title != null) + out.title = opts.title.bytes; + if (opts.filters != null) { + var filters = new hl.NativeArray(opts.filters.length * 2); + var i = 0; + for (f in opts.filters) { + filters[i++] = f.name.bytes; + filters[i++] = [for (e in f.exts) "*." + e].join(";").bytes; + } + out.filters = filters; + out.filterIndex = opts.filterIndex; + } + if (opts.window != null) + out.window = opts.window.h; + var str = _chooseFile(save, out); + return str == null ? null : String.fromUCS2(str); + } + + @:hlNative("ui", "ui_choose_file") + static function _chooseFile(forSave:Bool, obj:Dynamic):hl.Bytes { + return null; } - -} \ No newline at end of file +} diff --git a/std/hl/UI16.hx b/std/hl/UI16.hx index 0b77920e136..23f4e97e42c 100644 --- a/std/hl/UI16.hx +++ b/std/hl/UI16.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; @:coreType @:notNull @:runtimeValue abstract UI16 to Int from Int {} diff --git a/std/hl/UI8.hx b/std/hl/UI8.hx index e3acda17267..d53c915eb43 100644 --- a/std/hl/UI8.hx +++ b/std/hl/UI8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl; @:coreType @:notNull @:runtimeValue abstract UI8 to Int from Int {} diff --git a/std/hl/_std/Date.hx b/std/hl/_std/Date.hx index acb923457ea..bb811459c06 100644 --- a/std/hl/_std/Date.hx +++ b/std/hl/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,126 +19,178 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -import hl.Ref; -@:coreApi @:final class Date { +import hl.Ref; - private var t : Int; +@:coreApi final class Date { + private var t:Int; - public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void { + public function new(year:Int, month:Int, day:Int, hour:Int, min:Int, sec:Int):Void { t = date_new(year, month, day, hour, min, sec); } - public function getTime() : Float { + public function getTime():Float { return date_get_time(t); } - public function getFullYear() : Int { + public function getFullYear():Int { var v = 0; date_get_inf(t, v, null, null, null, null, null, null); return v; } - public function getMonth() : Int { + public function getMonth():Int { var v = 0; date_get_inf(t, null, v, null, null, null, null, null); return v; } - public function getDate() : Int { + public function getDate():Int { var v = 0; date_get_inf(t, null, null, v, null, null, null, null); return v; } - public function getHours() : Int { + public function getHours():Int { var v = 0; date_get_inf(t, null, null, null, v, null, null, null); return v; } - public function getMinutes() : Int { + public function getMinutes():Int { var v = 0; date_get_inf(t, null, null, null, null, v, null, null); return v; } - public function getSeconds() : Int { + public function getSeconds():Int { var v = 0; date_get_inf(t, null, null, null, null, null, v, null); return v; } - public function getDay() : Int { + public function getDay():Int { var v = 0; date_get_inf(t, null, null, null, null, null, null, v); return v; } + public function getUTCFullYear():Int { + var v = 0; + date_get_utc_inf(t, v, null, null, null, null, null, null); + return v; + } + + public function getUTCMonth():Int { + var v = 0; + date_get_utc_inf(t, null, v, null, null, null, null, null); + return v; + } + + public function getUTCDate():Int { + var v = 0; + date_get_utc_inf(t, null, null, v, null, null, null, null); + return v; + } + + public function getUTCHours():Int { + var v = 0; + date_get_utc_inf(t, null, null, null, v, null, null, null); + return v; + } + + public function getUTCMinutes():Int { + var v = 0; + date_get_utc_inf(t, null, null, null, null, v, null, null); + return v; + } + + public function getUTCSeconds():Int { + var v = 0; + date_get_utc_inf(t, null, null, null, null, null, v, null); + return v; + } + + public function getUTCDay():Int { + var v = 0; + date_get_utc_inf(t, null, null, null, null, null, null, v); + return v; + } + + public function getTimezoneOffset():Int { + var y = 0; + var mo = 0; + var d = 0; + var h = 0; + var m = 0; + var s = 0; + date_get_utc_inf(t, y, mo, d, h, m, s, null); + return Std.int((date_new(y, mo, d, h, m, s) - t) / 60); + } + @:keep public function toString():String { var outLen = 0; var bytes = date_to_string(t, outLen); - return @:privateAccess String.__alloc__(bytes,outLen); + return @:privateAccess String.__alloc__(bytes, outLen); } - public static function now() : Date { - var d : Date = untyped $new(Date); + public static function now():Date { + var d:Date = untyped $new(Date); d.t = date_now(); return d; } - static function fromInt( t : Int ) : Date { - var d : Date = untyped $new(Date); + static function fromInt(t:Int):Date { + var d:Date = untyped $new(Date); d.t = t; return d; } - public static function fromTime( t : Float ) : Date { - var d : Date = untyped $new(Date); + public static function fromTime(t:Float):Date { + var d:Date = untyped $new(Date); d.t = date_from_time(t); return d; } - public static function fromString( s : String ) : Date { - var d : Date = untyped $new(Date); - d.t = date_from_string(@:privateAccess s.bytes, s.length<<1); + public static function fromString(s:String):Date { + var d:Date = untyped $new(Date); + d.t = date_from_string(@:privateAccess s.bytes, s.length << 1); return d; } @:hlNative - static function date_new( year : Int, month : Int, day : Int, hours : Int, minutes : Int, seconds : Int ) : Int { + static function date_new(year:Int, month:Int, day:Int, hours:Int, minutes:Int, seconds:Int):Int { return 0; } @:hlNative - static function date_now() : Int { + static function date_now():Int { return 0; } @:hlNative - static function date_from_time( t : Float ) : Int { + static function date_from_time(t:Float):Int { return 0; } @:hlNative - static function date_from_string( b : hl.Bytes, len : Int ) : Int { + static function date_from_string(b:hl.Bytes, len:Int):Int { return 0; } @:hlNative - static function date_get_time( t : Int ) : Float { + static function date_get_time(t:Int):Float { return 0.; } + @:hlNative(1.11) + static function date_get_inf(t:Int, year:Ref, month:Ref, day:Ref, hours:Ref, minutes:Ref, seconds:Ref, wday:Ref):Void {} + @:hlNative - static function date_get_inf( t : Int, year : Ref, month : Ref, day : Ref, hours : Ref, minutes : Ref, seconds : Ref, wday : Ref ) : Void { - } + static function date_get_utc_inf(t:Int, year:Ref, month:Ref, day:Ref, hours:Ref, minutes:Ref, seconds:Ref, wday:Ref):Void {} @:hlNative - static function date_to_string( t : Int, outLen : Ref ) : hl.Bytes { + static function date_to_string(t:Int, outLen:Ref):hl.Bytes { return null; } - } - - diff --git a/std/hl/_std/EReg.hx b/std/hl/_std/EReg.hx index db97f2e3ffb..c066161ba8a 100644 --- a/std/hl/_std/EReg.hx +++ b/std/hl/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,145 +19,145 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - private typedef ERegValue = hl.Abstract<"ereg">; @:access(String) -@:coreApi @:final class EReg { - - var r : ERegValue; - var last : String; - var global : Bool; +@:coreApi final class EReg { + var r:ERegValue; + var last:String; + var global:Bool; - public function new( r : String, opt : String ) : Void { + public function new(r:String, opt:String):Void { var a = opt.split("g"); global = a.length > 1; - if( global ) + if (global) opt = a.join(""); this.r = regexp_new_options(r.bytes, opt.bytes); } - public function match( s : String ) : Bool { - var p = regexp_match(r,s.bytes,0,s.length); - if( p ) + public function match(s:String):Bool { + var p = regexp_match(r, s.bytes, 0, s.length); + if (p) last = s; else last = null; return p; } - public function matched( n : Int ) : String { + public function matched(n:Int):String { var len = 0; - var m = regexp_matched_pos(r,n,len); + var m = regexp_matched_pos(r, n, len); return m < 0 ? null : last.substr(m, len); } - public function matchedLeft() : String { - var p = regexp_matched_pos(r,0,null); - return last.substr(0,p); + public function matchedLeft():String { + var p = regexp_matched_pos(r, 0, null); + return last.substr(0, p); } - public function matchedRight() : String { + public function matchedRight():String { var len = 0; - var p = regexp_matched_pos(r,0,len); + var p = regexp_matched_pos(r, 0, len); return last.substr(p + len); } - public function matchedPos() : { pos : Int, len : Int } { + public function matchedPos():{pos:Int, len:Int} { var len = 0; var p = regexp_matched_pos(r, 0, len); - if( p < 0 ) return null; - return { pos : p, len : len }; + if (p < 0) + return null; + return {pos: p, len: len}; } - public function matchSub( s : String, pos : Int, len : Int = -1):Bool { + public function matchSub(s:String, pos:Int, len:Int = -1):Bool { var p = regexp_match(r, s.bytes, pos, len < 0 ? s.length - pos : len); - if( p ) + if (p) last = s; else last = null; return p; } - public function split( s : String ) : Array { + public function split(s:String):Array { var pos = 0; var len = s.length; var a = new Array(); var first = true; do { - if( !regexp_match(r,s.bytes,pos,len) ) + if (!regexp_match(r, s.bytes, pos, len)) break; var plen = 0; - var p = regexp_matched_pos(r,0,plen); - if( plen == 0 && !first ) { - if( p == s.length ) + var p = regexp_matched_pos(r, 0, plen); + if (plen == 0 && !first) { + if (p == s.length) break; p++; } - a.push(s.substr(pos,p - pos)); + a.push(s.substr(pos, p - pos)); var tot = p + plen - pos; pos += tot; len -= tot; first = false; - } while( global ); - a.push(s.substr(pos,len)); + } while (global); + a.push(s.substr(pos, len)); return a; } - public function replace( s : String, by : String ) : String { + public function replace(s:String, by:String):String { var b = new StringBuf(); var pos = 0; var len = s.length; var a = by.split("$"); var first = true; do { - if( !regexp_match(r,s.bytes,pos,len) ) + if (!regexp_match(r, s.bytes, pos, len)) break; var plen = 0; - var p = regexp_matched_pos(r,0, plen); - if( plen == 0 && !first ) { - if( p == s.length ) + var p = regexp_matched_pos(r, 0, plen); + if (plen == 0 && !first) { + if (p == s.length) break; p++; } - b.addSub(s,pos,p-pos); - if( a.length > 0 ) + b.addSub(s, pos, p - pos); + if (a.length > 0) b.add(a[0]); var i = 1; - while( i < a.length ) { + while (i < a.length) { var k = a[i]; var c = StringTools.fastCodeAt(k, 0); // 1...9 - if( c >= 49 && c <= 57 ) { + if (c >= 49 && c <= 57) { var plen = 0; - var p = try regexp_matched_pos(r,Std.int(c)-48,plen) catch( e : String ) -1; - if( p < 0 ){ + var p = try regexp_matched_pos(r, Std.int(c) - 48, plen) catch (e:String) -1; + if (p < 0) { b.add("$"); b.add(k); } else { - if( p >= 0 ) b.addSub(s,p,plen); - b.addSub(k,1,k.length - 1); + if (p >= 0) + b.addSub(s, p, plen); + b.addSub(k, 1, k.length - 1); } - } else if( c == 0 ) { + } else if (c == 0) { b.add("$"); i++; var k2 = a[i]; - if( k2 != null && k2.length > 0 ) + if (k2 != null && k2.length > 0) b.add(k2); } else - b.add("$"+k); + b.add("$" + k); i++; } var tot = p + plen - pos; pos += tot; len -= tot; first = false; - } while( global ); - b.addSub(s,pos,len); + } while (global); + b.addSub(s, pos, len); return b.toString(); } - public function map( s : String, f : EReg -> String ) : String { + public function map(s:String, f:EReg->String):String { var offset = 0; var buf = new StringBuf(); do { @@ -168,14 +168,13 @@ private typedef ERegValue = hl.Abstract<"ereg">; break; } var plen = 0; - var p = regexp_matched_pos(r,0,plen); + var p = regexp_matched_pos(r, 0, plen); buf.add(s.substr(offset, p - offset)); buf.add(f(this)); if (plen == 0) { buf.add(s.substr(p, 1)); offset = p + 1; - } - else + } else offset = p + plen; } while (global); if (!global && offset > 0 && offset < s.length) @@ -183,22 +182,21 @@ private typedef ERegValue = hl.Abstract<"ereg">; return buf.toString(); } - public static function escape( s : String ) : String { + public static function escape(s:String):String { return escapeRegExpRe.map(s, function(r) return "\\" + r.matched(0)); } + static var escapeRegExpRe = ~/[\[\]{}()*+?.\\\^$|]/g; - @:hlNative("std", "regexp_new_options") static function regexp_new_options( bytes : hl.Bytes, options : hl.Bytes ) : ERegValue { + @:hlNative("std", "regexp_new_options") static function regexp_new_options(bytes:hl.Bytes, options:hl.Bytes):ERegValue { return null; } - @:hlNative("std", "regexp_match") static function regexp_match( r : ERegValue, str : hl.Bytes, pos : Int, size : Int ) : Bool { + @:hlNative("std", "regexp_match") static function regexp_match(r:ERegValue, str:hl.Bytes, pos:Int, size:Int):Bool { return false; } - @:hlNative("std", "regexp_matched_pos") static function regexp_matched_pos( r : ERegValue, n : Int, size : hl.Ref ) : Int { + @:hlNative("std", "regexp_matched_pos") static function regexp_matched_pos(r:ERegValue, n:Int, size:hl.Ref):Int { return 0; } - - } diff --git a/std/hl/_std/Math.hx b/std/hl/_std/Math.hx index 031a8672aa6..2c76ba8335d 100644 --- a/std/hl/_std/Math.hx +++ b/std/hl/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,45 +21,84 @@ */ @:coreApi class Math { + @:hlNative("std", "math_sqrt") public static function sqrt(v:Float):Float + return 0.; - @:hlNative("std","math_sqrt") public static function sqrt( v : Float ) : Float return 0.; - @:hlNative("std","math_abs") public static function abs( v : Float ) : Float return 0.; - @:hlNative("std","math_floor") public static function floor( v : Float ) : Int return 0; - @:hlNative("std","math_round") public static function round( v : Float ) : Int return 0; - @:hlNative("std","math_ceil") public static function ceil( v : Float ) : Int return 0; - @:hlNative("std","math_isfinite") public static function isFinite( f : Float ) : Bool return true; - @:hlNative("std","math_isnan") public static function isNaN( f : Float ) : Bool return false; - - @:hlNative("std","math_ffloor") public static function ffloor( v : Float ) : Float return 0.; - @:hlNative("std","math_fround") public static function fround( v : Float ) : Float return 0.; - @:hlNative("std","math_fceil") public static function fceil( v : Float ) : Float return 0.; - - @:hlNative("std","math_cos") public static function cos( v : Float ) : Float return 0.; - @:hlNative("std","math_sin") public static function sin( v : Float ) : Float return 0.; - @:hlNative("std","math_exp") public static function exp( v : Float ) : Float return 0.; - @:hlNative("std","math_log") public static function log( v : Float ) : Float return 0.; - @:hlNative("std","math_tan") public static function tan( v : Float ) : Float return 0.; - @:hlNative("std","math_atan") public static function atan( v : Float ) : Float return 0.; - @:hlNative("std","math_acos") public static function acos( v : Float ) : Float return 0.; - @:hlNative("std","math_asin") public static function asin( v : Float ) : Float return 0.; - @:hlNative("std","math_pow") public static function pow( v : Float, exp : Float ) : Float return 0.; - @:hlNative("std","math_atan2") public static function atan2( y : Float, x : Float ) : Float return 0.; - - public static function random() : Float return @:privateAccess Std.rnd_float(Std.rnd); - - public static function min( a : Float, b : Float ) : Float return a < b || isNaN(a) ? a : b; - public static function max( a : Float, b : Float ) : Float return a < b || isNaN(b) ? b : a; - - public static var PI(default,null) : Float; - public static var NaN(default,null) : Float; - public static var POSITIVE_INFINITY(default,null) : Float; - public static var NEGATIVE_INFINITY(default,null) : Float; - - static function __init__() : Void { + @:hlNative("std", "math_abs") public static function abs(v:Float):Float + return 0.; + + @:hlNative("std", "math_floor") public static function floor(v:Float):Int + return 0; + + @:hlNative("std", "math_round") public static function round(v:Float):Int + return 0; + + @:hlNative("std", "math_ceil") public static function ceil(v:Float):Int + return 0; + + @:hlNative("std", "math_isfinite") public static function isFinite(f:Float):Bool + return true; + + @:hlNative("std", "math_isnan") public static function isNaN(f:Float):Bool + return false; + + @:hlNative("std", "math_ffloor") public static function ffloor(v:Float):Float + return 0.; + + @:hlNative("std", "math_fround") public static function fround(v:Float):Float + return 0.; + + @:hlNative("std", "math_fceil") public static function fceil(v:Float):Float + return 0.; + + @:hlNative("std", "math_cos") public static function cos(v:Float):Float + return 0.; + + @:hlNative("std", "math_sin") public static function sin(v:Float):Float + return 0.; + + @:hlNative("std", "math_exp") public static function exp(v:Float):Float + return 0.; + + @:hlNative("std", "math_log") public static function log(v:Float):Float + return 0.; + + @:hlNative("std", "math_tan") public static function tan(v:Float):Float + return 0.; + + @:hlNative("std", "math_atan") public static function atan(v:Float):Float + return 0.; + + @:hlNative("std", "math_acos") public static function acos(v:Float):Float + return 0.; + + @:hlNative("std", "math_asin") public static function asin(v:Float):Float + return 0.; + + @:hlNative("std", "math_pow") public static function pow(v:Float, exp:Float):Float + return 0.; + + @:hlNative("std", "math_atan2") public static function atan2(y:Float, x:Float):Float + return 0.; + + public static function random():Float + return @:privateAccess Std.rnd_float(Std.rnd); + + public static function min(a:Float, b:Float):Float + return a < b || isNaN(a) ? a : b; + + public static function max(a:Float, b:Float):Float + return a < b || isNaN(b) ? b : a; + + public static var PI(default, null):Float; + public static var NaN(default, null):Float; + public static var POSITIVE_INFINITY(default, null):Float; + public static var NEGATIVE_INFINITY(default, null):Float; + + static function __init__():Void { PI = 3.1415926535897932384626433832795; NaN = 0. / 0.; POSITIVE_INFINITY = 1. / 0.; NEGATIVE_INFINITY = -1. / 0.; } - -} \ No newline at end of file +} diff --git a/std/hl/_std/Reflect.hx b/std/hl/_std/Reflect.hx index 14e199429b8..7768660fa91 100644 --- a/std/hl/_std/Reflect.hx +++ b/std/hl/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,125 +19,126 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - @:coreApi class Reflect { - - public static function hasField( o : Dynamic, field : String ) : Bool { - if( field == null ) return false; + public static function hasField(o:Dynamic, field:String):Bool { + if (field == null) + return false; var hash = @:privateAccess field.bytes.hash(); - return hl.Api.hasField(o,hash); + return hl.Api.hasField(o, hash); } - public static function field( o : Dynamic, field : String ) : Dynamic { - if( field == null ) return null; + public static function field(o:Dynamic, field:String):Dynamic { + if (field == null) + return null; var hash = @:privateAccess field.bytes.hash(); - return hl.Api.getField(o,hash); + return hl.Api.getField(o, hash); } - public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void { + public static function setField(o:Dynamic, field:String, value:Dynamic):Void { var hash = @:privateAccess field.bytes.hash(); - hl.Api.setField(o,hash,value); + hl.Api.setField(o, hash, value); } - public static function getProperty( o : Dynamic, field : String ) : Dynamic { - var f : Dynamic = Reflect.field(o, "get_" + field); - if( f != null ) + public static function getProperty(o:Dynamic, field:String):Dynamic { + var f:Dynamic = Reflect.field(o, "get_" + field); + if (f != null) return f(); - return Reflect.field(o,field); + return Reflect.field(o, field); } - public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void { - var f : Dynamic = Reflect.field(o, "set_" + field); - if( f != null ) + public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void { + var f:Dynamic = Reflect.field(o, "set_" + field); + if (f != null) f(value); else setField(o, field, value); } - public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic { - var args : hl.types.ArrayDyn = cast args; - var count = args.length; + public static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array):Dynamic { + var args:hl.types.ArrayDyn = cast args; var ft = hl.Type.getDynamic(func); - if( ft.kind != HFun ) + if (ft.kind != HFun) throw "Invalid function " + func; + + var count = args.length; var need = ft.getArgsCount(); - var cval = hl.Api.getClosureValue(func); - var isClosure = cval != null && need >= 0; - if( o == null ) - o = cval; - else if( !isClosure && count == need ) - o = null; - var nargs = o == null ? count : count + 1; - if( isClosure ) need++; - if( nargs < need ) nargs = need; + var nargs = count < need ? need : count; + var cval:Dynamic = hl.Api.getClosureValue(func); + if (cval != null) { + func = hl.Api.noClosure(func); + nargs++; + } + var a = new hl.NativeArray(nargs); - if( o == null || need < 0 ) { - for( i in 0...count ) + if (cval == null) { + for (i in 0...count) a[i] = args.getDyn(i); } else { - func = hl.Api.noClosure(func); - a[0] = o; - for( i in 0...count ) - a[i+1] = args.getDyn(i); + a[0] = cval; + for (i in 0...count) + a[i + 1] = args.getDyn(i); } - return hl.Api.callMethod(func,a); + return hl.Api.callMethod(func, a); } - @:hlNative("std","obj_fields") static function getObjectFields( v : Dynamic ) : hl.NativeArray { + @:hlNative("std", "obj_fields") static function getObjectFields(v:Dynamic):hl.NativeArray { return null; } - public static function fields( o : Dynamic ) : Array { + public static function fields(o:Dynamic):Array { var fields = getObjectFields(o); - if( fields == null ) return []; - return [for( f in fields ) @:privateAccess String.fromUCS2(f)]; + if (fields == null) + return []; + return [for (f in fields) @:privateAccess String.fromUCS2(f)]; } - public static inline function isFunction( f : Dynamic ) : Bool { + public static inline function isFunction(f:Dynamic):Bool { return hl.Type.getDynamic(f).kind == HFun; } - @:hlNative("std","dyn_compare") - public static function compare( a : T, b : T ) : Int { + @:hlNative("std", "dyn_compare") + public static function compare(a:T, b:T):Int { return 0; } - @:hlNative("std","fun_compare") - public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool { + @:hlNative("std", "fun_compare") + public static function compareMethods(f1:Dynamic, f2:Dynamic):Bool { return false; } - public static function isObject( v : Dynamic ) : Bool { + public static function isObject(v:Dynamic):Bool { var t = hl.Type.getDynamic(v); - return switch( t.kind ) { case HObj, HDynObj, HVirtual: true; default: false; } + return switch (t.kind) { + case HObj, HDynObj, HVirtual: true; + default: false; + } } - public static function isEnumValue( v : Dynamic ) : Bool { + public static function isEnumValue(v:Dynamic):Bool { var t = hl.Type.getDynamic(v); return t.kind == HEnum; } - public static function deleteField( o : Dynamic, field : String ) : Bool { - return hl.Api.deleteField(o,@:privateAccess field.bytes.hash()); + public static function deleteField(o:Dynamic, field:String):Bool { + return hl.Api.deleteField(o, @:privateAccess field.bytes.hash()); } - @:hlNative("std","obj_copy") - public static function copy( o : T ) : T { + @:hlNative("std", "obj_copy") + public static function copy(o:Null):Null { return null; } - @:overload(function( f : Array -> Void ) : Dynamic {}) - @:extern public inline static function makeVarArgs( f : Array -> Dynamic ) : Dynamic { + @:overload(function(f:Array->Void):Dynamic {}) + extern public inline static function makeVarArgs(f:Array->Dynamic):Dynamic { return _makeVarArgs(f); } - static function _makeVarArgs( f : Array -> Dynamic ) : Dynamic { + static function _makeVarArgs(f:Array->Dynamic):Dynamic { return hl.Api.makeVarArgs(function(args:hl.NativeArray) { var arr = hl.types.ArrayDyn.alloc(hl.types.ArrayObj.alloc(args), true); return f(cast arr); }); } - } diff --git a/std/hl/_std/Std.hx b/std/hl/_std/Std.hx index e4d417d0a26..ff9a7027237 100644 --- a/std/hl/_std/Std.hx +++ b/std/hl/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,102 +19,123 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import hl.Boot; private typedef Rand = hl.Abstract<"hl_random">; @:coreApi class Std { + static var rnd:Rand; + static var toStringDepth:Int = 0; - static var rnd : Rand; - - static function __init__() : Void { + static function __init__():Void { rnd = rnd_sys(); } - @:hlNative("std","rnd_init_system") static function rnd_sys() : Rand { return null; } - @:hlNative("std","rnd_int") static function rnd_int( r : Rand ) : Int { return 0; } - @:hlNative("std","rnd_float") static function rnd_float( r : Rand ) : Float { return 0.; } + @:hlNative("std", "rnd_init_system") static function rnd_sys():Rand { + return null; + } + + @:hlNative("std", "rnd_int") static function rnd_int(r:Rand):Int { + return 0; + } + + @:hlNative("std", "rnd_float") static function rnd_float(r:Rand):Float { + return 0.; + } - public static function random( x : Int ) : Int { + public static function random(x:Int):Int { return x <= 0 ? 0 : (rnd_int(rnd) & 0x3FFFFFFF) % x; } - public static function is( v : Dynamic, t : Dynamic ) : Bool { - var t : hl.BaseType = t; - if( t == null ) return false; - switch( t.__type__.kind ) { - case HDyn: - return true; - case HF64: - switch( hl.Type.getDynamic(v).kind ) { - case HUI8, HUI16, HI32: - return true; - default: - } - case HI32: - switch( hl.Type.getDynamic(v).kind ) { - case HF32, HF64: - var v : Float = v; - return Std.int(v) == v; + public static function is(v:Dynamic, t:Dynamic):Bool { + var t:hl.BaseType = t; + if (t == null) + return false; + switch (t.__type__.kind) { + case HDyn: + return v != null; + case HF64: + switch (hl.Type.getDynamic(v).kind) { + case HUI8, HUI16, HI32: + return true; + default: + } + case HI32: + switch (hl.Type.getDynamic(v).kind) { + case HF32, HF64: + var v:Float = v; + return Std.int(v) == v; + default: + } default: - } - default: } return t.check(v); } - @:extern public inline static function instance( value : T, c : Class ) : S { - var t : hl.BaseType = cast c; - return t.check(value) ? cast value : null; + extern public static function downcast(value:T, c:Class):S; + + @:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.') + public static inline function instance(value:T, c:Class):S { + return downcast(value, c); } - @:extern public static inline function int( x : Float ) : Int { + extern public static inline function int(x:Float):Int { return untyped $int(x); } - @:keep public static function string( s : Dynamic ) : String { + @:keep public static function string(s:Dynamic):String { var len = 0; - var bytes = hl.Bytes.fromValue(s,new hl.Ref(len)); - return @:privateAccess String.__alloc__(bytes,len); + var bytes = hl.Bytes.fromValue(s, new hl.Ref(len)); + return @:privateAccess String.__alloc__(bytes, len); } - public static function parseInt( x : String ) : Null { - if( x == null ) return null; - return @:privateAccess x.bytes.parseInt(0, x.length<<1); + public static function parseInt(x:String):Null { + if (x == null) + return null; + return @:privateAccess x.bytes.parseInt(0, x.length << 1); } - public static function parseFloat( x : String ) : Float { - if( x == null ) return Math.NaN; - return @:privateAccess x.bytes.parseFloat(0, x.length<<1); + public static function parseFloat(x:String):Float { + if (x == null) + return Math.NaN; + return @:privateAccess x.bytes.parseFloat(0, x.length << 1); } - @:keep static function __add__( a : Dynamic, b : Dynamic ) : Dynamic { + @:keep static function __add__(a:Dynamic, b:Dynamic):Dynamic { var ta = hl.Type.getDynamic(a); var tb = hl.Type.getDynamic(b); - if( ta == hl.Type.get("") ) + if (ta == hl.Type.get("")) return (a : String) + b; - if( tb == hl.Type.get("") ) + if (tb == hl.Type.get("")) return a + (b : String); - switch(ta.kind) { - case HUI8, HUI16, HI32: - var a : Int = a; - switch( tb.kind ) { - case HUI8, HUI16, HI32: return a + (b:Int); - case HF32, HF64: return a + (b:Float); - default: - } - case HF32, HF64: - var a : Float = a; - switch( tb.kind ) { - case HUI8, HUI16, HI32: return a + (b:Int); - case HF32, HF64: return a + (b:Float); + switch (ta.kind) { + case HUI8, HUI16, HI32: + var a:Int = a; + switch (tb.kind) { + case HUI8, HUI16, HI32: return a + (b : Int); + case HF32, HF64: return a + (b : Float); + case HVoid: return a; + default: + } + case HF32, HF64: + var a:Float = a; + switch (tb.kind) { + case HUI8, HUI16, HI32: return a + (b : Int); + case HF32, HF64: return a + (b : Float); + case HVoid: return a; + default: + } + case HVoid: + switch (tb.kind) { + case HUI8, HUI16, HI32, HF32, HF64: return b; + case HVoid: return 0.; + default: + } default: - } - default: } - throw "Can't add "+a+"("+ta+") and "+b+"("+tb+")"; + throw "Can't add " + a + "(" + ta + ") and " + b + "(" + tb + ")"; return null; } - } diff --git a/std/hl/_std/String.hx b/std/hl/_std/String.hx index 880722deb8b..20a33423251 100644 --- a/std/hl/_std/String.hx +++ b/std/hl/_std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,82 +21,99 @@ */ @:coreApi class String { + var bytes:hl.Bytes; - var bytes : hl.Bytes; - public var length(default,null) : Int; + public var length(default, null):Int; - public function new(string:String) : Void { + public function new(string:String):Void { bytes = string.bytes; length = string.length; } - public function toUpperCase() : String { - return __alloc__(@:privateAccess bytes.ucs2Upper(0,length), length); + public function toUpperCase():String { + return __alloc__(@:privateAccess bytes.ucs2Upper(0, length), length); } - public function toLowerCase() : String { - return __alloc__(@:privateAccess bytes.ucs2Lower(0,length), length); + public function toLowerCase():String { + return __alloc__(@:privateAccess bytes.ucs2Lower(0, length), length); } - public function charAt(index : Int) : String { - if( (index:UInt) >= (length:UInt) ) return ""; + public function charAt(index:Int):String { + if ((index : UInt) >= (length : UInt)) + return ""; var b = new hl.Bytes(4); - b.setUI16(0, bytes.getUI16(index<<1)); - b.setUI16(2,0); - return __alloc__(b,1); + b.setUI16(0, bytes.getUI16(index << 1)); + b.setUI16(2, 0); + return __alloc__(b, 1); } - public function charCodeAt( index : Int) : Null { - var idx : UInt = index; - if( idx >= (length:UInt) ) + public function charCodeAt(index:Int):Null { + var idx:UInt = index; + if (idx >= (length : UInt)) return null; return bytes.getUI16(index << 1); } - public function indexOf( str : String, ?startIndex : Int ) : Int { + inline function findChar(start:Int, len:Int, src:hl.Bytes, srcLen:Int):Int { + var p = 0; + while (true) { + p = bytes.find(start, len - start, src, 0, srcLen); + if (p < 0 || p & 1 == 0) + break; + start = p + 1; + } + return p; + } + + public function indexOf(str:String, ?startIndex:Int):Int { var startByte = 0; - if( startIndex != null && startIndex > 0 ) { - if( startIndex >= length ) + if (startIndex != null && startIndex > 0) { + if (startIndex >= length) return -1; startByte = startIndex << 1; } - var p = bytes.find(startByte, (length << 1) - startByte, str.bytes, 0, str.length << 1); - if( p > 0 ) p >>= 1; + var p = findChar(startByte, length << 1, str.bytes, str.length << 1); + if (p > 0) + p >>= 1; return p; } - public function lastIndexOf( str : String, ?startIndex : Int ) : Int { - var last = 0; - var start = this.length; - if( startIndex != null ) - start = startIndex; - start <<= 1; - while( true ) { - var p = bytes.find(last, (length << 1) - last, str.bytes, 0, str.length << 1); - if( p < 0 || p > start ) - return (last >> 1) - 1; - last = p + 2; + public function lastIndexOf(str:String, ?startIndex:Int):Int { + var max = this.length; + if (startIndex != null) { + max = startIndex + str.length; + if (max < 0) + max = 0; + if (max > this.length) + max = this.length; + } + var pos = max - str.length; + var slen = str.length << 1; + while (pos >= 0) { + if (bytes.compare(pos << 1, str.bytes, 0, slen) == 0) + return pos; + pos--; } return -1; } - public function split( delimiter : String ) : Array { + public function split(delimiter:String):Array { var out = []; - if( length == 0 ) { + if (length == 0) { out.push(""); return out; } - if( delimiter.length == 0 ) { - for( i in 0...length ) - out.push(substr(i,1)); + if (delimiter.length == 0) { + for (i in 0...length) + out.push(substr(i, 1)); return out; } var pos = 0; var dlen = delimiter.length; - while( true ) { - var p = bytes.find(pos << 1, (length - pos) << 1, delimiter.bytes, 0, dlen << 1); - if( p < 0 ) { - out.push(substr(pos, length-pos)); + while (true) { + var p = findChar(pos << 1, length << 1, delimiter.bytes, dlen << 1); + if (p < 0) { + out.push(substr(pos, length - pos)); break; } p >>= 1; @@ -106,64 +123,69 @@ class String { return out; } - public function substr( pos : Int, ?len : Int ) : String @:privateAccess { + public function substr(pos:Int, ?len:Int):String@:privateAccess { var sl = length; - var len : Int = if( len == null ) sl else len; - if( len == 0 ) return ""; - if( pos != 0 && len < 0 ) + var len:Int = if (len == null) sl else len; + if (len == 0) return ""; - if( pos < 0 ) { + if (pos != 0 && len < 0) + return ""; + if (pos < 0) { pos = sl + pos; - if( pos < 0 ) pos = 0; - } else if( len < 0 ) { + if (pos < 0) + pos = 0; + } else if (len < 0) { len = sl + len - pos; - if( len < 0 ) return ""; + if (len < 0) + return ""; } - if( ((pos + len) : UInt) > (sl:UInt) ) + if (((pos + len) : UInt) > (sl : UInt)) len = sl - pos; - if( pos < 0 || len <= 0 ) return ""; + if (pos < 0 || len <= 0) + return ""; var b = new hl.Bytes((len + 1) << 1); - b.blit(0, bytes, pos<<1, len << 1); - b.setUI16(len<<1,0); + b.blit(0, bytes, pos << 1, len << 1); + b.setUI16(len << 1, 0); return __alloc__(b, len); } - public function substring( startIndex : Int, ?endIndex : Int ) : String { - var end : Int; - if( endIndex == null ) + public function substring(startIndex:Int, ?endIndex:Int):String { + var end:Int; + if (endIndex == null) end = length; else { end = endIndex; - if( end < 0 ) + if (end < 0) end = 0; - else if ( end > length ) + else if (end > length) end = length; } - if( startIndex < 0 ) + if (startIndex < 0) startIndex = 0; - else if ( startIndex > length ) + else if (startIndex > length) startIndex = length; - if( startIndex > end ) { + if (startIndex > end) { var tmp = startIndex; startIndex = end; end = tmp; } - return substr( startIndex, end - startIndex ); + return substr(startIndex, end - startIndex); } - public function toString() : String { + public function toString():String { return this; } - public static function fromCharCode( code : Int ) : String { - if( code >= 0 && code < 0x10000 ) { - if( code >= 0xD800 && code <= 0xDFFF ) throw "Invalid unicode char " + code; + public static function fromCharCode(code:Int):String { + if (code >= 0 && code < 0x10000) { + if (code >= 0xD800 && code <= 0xDFFF) + throw "Invalid unicode char " + code; var b = new hl.Bytes(4); b.setUI16(0, code); b.setUI16(2, 0); return __alloc__(b, 1); - } else if( code < 0x110000 ) { + } else if (code < 0x110000) { var b = new hl.Bytes(6); code -= 0x10000; b.setUI16(0, (code >> 10) + 0xD800); @@ -174,52 +196,61 @@ class String { throw "Invalid unicode char " + code; } - function toUtf8() : hl.Bytes { + function toUtf8():hl.Bytes { return bytes.utf16ToUtf8(0, null); } - @:keep function __string() : hl.Bytes { + @:keep function __string():hl.Bytes { return bytes; } - @:keep function __compare( s : String ) : Int { + @:keep function __compare(v:Dynamic):Int { + var s = Std.downcast(v, String); + if (s == null) + return hl.Api.comparePointer(this, v); + #if (hl_ver >= version("1.10.0")) + var v = bytes.compare16(s.bytes, length < s.length ? length : s.length); + #else var v = bytes.compare(0, s.bytes, 0, (length < s.length ? length : s.length) << 1); + #end return v == 0 ? length - s.length : v; } - @:keep static inline function __alloc__( b : hl.Bytes, length : Int ) : String { - var s : String = untyped $new(String); + @:keep static inline function __alloc__(b:hl.Bytes, length:Int):String { + var s:String = untyped $new(String); s.bytes = b; s.length = length; return s; } - @:keep static function call_toString( v : Dynamic ) : hl.Bytes { - var s : String = v.toString(); + @:keep static function call_toString(v:Dynamic):hl.Bytes { + var s:String = v.toString(); return s.bytes; } - inline static function fromUCS2( b : hl.Bytes ) : String { - var s : String = untyped $new(String); + inline static function fromUCS2(b:hl.Bytes):String { + var s:String = untyped $new(String); s.bytes = b; s.length = @:privateAccess b.ucs2Length(0); return s; } - @:keep static function fromUTF8( b : hl.Bytes ) : String { + @:keep static function fromUTF8(b:hl.Bytes):String { var outLen = 0; var b2 = @:privateAccess b.utf8ToUtf16(0, outLen); - return __alloc__(b2, outLen>>1); + return __alloc__(b2, outLen >> 1); } - @:keep static function __add__( a : String, b : String ) : String { - if( a == null ) a = "null"; - if( b == null ) b = "null"; + @:keep static function __add__(a:String, b:String):String { + if (a == null) + a = "null"; + if (b == null) + b = "null"; var asize = a.length << 1, bsize = b.length << 1, tot = asize + bsize; - var bytes = new hl.Bytes(tot+2); + var bytes = new hl.Bytes(tot + 2); bytes.blit(0, a.bytes, 0, asize); - bytes.blit(asize,b.bytes,0,bsize); + bytes.blit(asize, b.bytes, 0, bsize); bytes.setUI16(tot, 0); - return __alloc__(bytes, tot>>1); + return __alloc__(bytes, tot >> 1); } } diff --git a/std/hl/_std/StringBuf.hx b/std/hl/_std/StringBuf.hx index 52a5cb71596..794237cd945 100644 --- a/std/hl/_std/StringBuf.hx +++ b/std/hl/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,63 +20,74 @@ * DEALINGS IN THE SOFTWARE. */ @:coreApi class StringBuf { + var b:hl.Bytes; + var size:Int; + var pos:Int; - var b : hl.Bytes; - var size : Int; - var pos : Int; - public var length(get,never) : Int; + public var length(get, never):Int; - public function new() : Void { + public function new():Void { pos = 0; size = 8; // ensure 4 bytes expand for addChar() b = new hl.Bytes(size); } - inline function get_length() : Int { + inline function get_length():Int { return pos >> 1; } - inline function __expand( need : Int ) : Void { + inline function __expand(need:Int):Void { var nsize = (size * 3) >> 1; - if( need > nsize ) nsize = need; + if (need > nsize) + nsize = need; var b2 = new hl.Bytes(nsize); b2.blit(0, b, 0, pos); b = b2; size = nsize; } - inline function __add( bytes : hl.Bytes, spos : Int, ssize : Int ) : Void { - if( pos + ssize > size ) __expand(pos + ssize); + inline function __add(bytes:hl.Bytes, spos:Int, ssize:Int):Void { + if (pos + ssize > size) + __expand(pos + ssize); b.blit(pos, bytes, spos, ssize); pos += ssize; } - public function add( x : T ) : Void { + public function add(x:T):Void { var slen = 0; var sbytes = hl.Bytes.fromValue(x, new hl.Ref(slen)); - __add(sbytes, 0, slen<<1); + __add(sbytes, 0, slen << 1); } - public function addSub( s : String, pos : Int, ?len : Int ) : Void @:privateAccess { - if( pos < 0 ) pos = 0; - if( pos >= s.length ) return; - var slen : Int; - if( len == null ) slen = s.length - pos else { + public function addSub(s:String, pos:Int, ?len:Int):Void@:privateAccess { + if (pos < 0) + pos = 0; + if (pos >= s.length) + return; + var slen:Int; + if (len == null) + slen = s.length - pos + else { slen = len; - if( pos + slen > s.length ) slen = s.length - pos; - if( slen <= 0 ) return; + if (pos + slen > s.length) + slen = s.length - pos; + if (slen <= 0) + return; } __add(s.bytes, pos << 1, slen << 1); } - public function addChar( c : Int ) : Void { - if( c >= 0 && c < 0x10000 ) { - if( c >= 0xD800 && c <= 0xDFFF ) throw "Invalid unicode char " + c; - if( pos + 2 > size ) __expand(0); + public function addChar(c:Int):Void { + if (c >= 0 && c < 0x10000) { + if (c >= 0xD800 && c <= 0xDFFF) + throw "Invalid unicode char " + c; + if (pos + 2 > size) + __expand(0); b.setUI16(pos, c); pos += 2; - } else if( c < 0x110000 ) { - if( pos + 4 > size ) __expand(0); + } else if (c < 0x110000) { + if (pos + 4 > size) + __expand(0); c -= 0x10000; b.setUI16(pos, (c >> 10) + 0xD800); b.setUI16(pos + 2, (c & 1023) + 0xDC00); @@ -85,10 +96,10 @@ throw "Invalid unicode char " + c; } - public function toString() : String { - if( pos+2 > size ) __expand(0); - b.setUI16(pos,0); - return @:privateAccess String.__alloc__(b, pos>>1); + public function toString():String { + if (pos + 2 > size) + __expand(0); + b.setUI16(pos, 0); + return @:privateAccess String.__alloc__(b, pos >> 1); } - } diff --git a/std/hl/_std/Sys.hx b/std/hl/_std/Sys.hx index b98f1779567..feae9d03e7c 100644 --- a/std/hl/_std/Sys.hx +++ b/std/hl/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + +import haxe.SysTools; + class SysError { - public var msg : String; + public var msg:String; + public function new(msg) { this.msg = msg; } + @:keep public function toString() { - return "SysError("+msg+")"; + return "SysError(" + msg + ")"; } } @@ -33,86 +38,90 @@ class SysError { @:keepInit @:access(String) class Sys { + static var utf8Path:Bool; - static var utf8Path : Bool; - static function __init__() : Void { + static function __init__():Void { utf8Path = sys_utf8_path(); } - static function getPath( s : String ) : hl.Bytes { + + static function getPath(s:String):hl.Bytes { return utf8Path ? s.bytes.utf16ToUtf8(0, null) : s.bytes; } - static function makePath( b : hl.Bytes ) : String { - if( b == null ) return null; + + static function makePath(b:hl.Bytes):String { + if (b == null) + return null; return utf8Path ? String.fromUTF8(b) : String.fromUCS2(b); } - public static function print( v : Dynamic ) : Void { + public static function print(v:Dynamic):Void { sys_print(Std.string(v).bytes); } - public static function println( v : Dynamic ) : Void { + public static function println(v:Dynamic):Void { sys_print(Std.string(v).bytes); sys_print("\n".bytes); } - public static function args() : Array { - return [for( a in sys_args() ) makePath(a)]; + public static function args():Array { + return [for (a in sys_args()) makePath(a)]; } - public static function stdin() : haxe.io.Input { + public static function stdin():haxe.io.Input { return @:privateAccess new sys.io.FileInput(file_stdin()); } - public static function stdout() : haxe.io.Output { + public static function stdout():haxe.io.Output { return @:privateAccess new sys.io.FileOutput(file_stdout()); } - public static function stderr() : haxe.io.Output { + public static function stderr():haxe.io.Output { return @:privateAccess new sys.io.FileOutput(file_stderr()); } - public static function getEnv( s : String ) : String { + public static function getEnv(s:String):String { var v = get_env(getPath(s)); - if( v == null ) + if (v == null) return null; return makePath(v); } - public static function putEnv( s : String, v : String ) : Void { - if( !put_env(getPath(s), if( v == null ) null else getPath(v)) ) throw "putEnv() failure"; + public static function putEnv(s:String, v:String):Void { + if (!put_env(getPath(s), if (v == null) null else getPath(v))) + throw "putEnv() failure"; } - public static function environment() : Map { + public static function environment():Map { var env = sys_env(); var h = new haxe.ds.StringMap(); - for( i in 0...env.length >> 1 ) { + for (i in 0...env.length >> 1) { var p = i << 1; h.set(makePath(env[p]), makePath(env[p + 1])); } return h; } - @:hlNative("std","sys_sleep") - public static function sleep( seconds : Float ) : Void { - } + @:hlNative("std", "sys_sleep") + public static function sleep(seconds:Float):Void {} - public static function setTimeLocale( loc : String ) : Bool { - return set_time_locale(loc.bytes.utf16ToUtf8(0,null)); + public static function setTimeLocale(loc:String):Bool { + return set_time_locale(loc.bytes.utf16ToUtf8(0, null)); } - public static function getCwd() : String { + public static function getCwd():String { return makePath(get_cwd()); } - public static function setCwd( s : String ) : Void { - if( !set_cwd(getPath(s)) ) throw new SysError("Failed to set path to " + s); + public static function setCwd(s:String):Void { + if (!set_cwd(getPath(s))) + throw new SysError("Failed to set path to " + s); } - public static function systemName() : String { + public static function systemName():String { return String.fromUCS2(sys_string()); } - public static function command( cmd : String, ?args : Array ) : Int { + public static function command(cmd:String, ?args:Array):Int { var code = 0; if (args == null) { code = sys_command(getPath(cmd)); @@ -121,53 +130,106 @@ class Sys { case "Windows": cmd = [ for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) - StringTools.quoteWinArg(a, true) + SysTools.quoteWinArg(a, true) ].join(" "); code = sys_command(getPath(cmd)); case _: - cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + cmd = [cmd].concat(args).map(SysTools.quoteUnixArg).join(" "); code = sys_command(getPath(cmd)); } } return code; } - @:deprecated("Use programPath instead") public static function executablePath() : String { + @:deprecated("Use programPath instead") public static function executablePath():String { return makePath(sys_exe_path()); } - public static function programPath() : String { + public static function programPath():String { return sys_program_path; } + private static var sys_program_path = { var hlFile = sys_hl_file(); - if( hlFile == null ) - makePath( sys_exe_path() ); + if (hlFile == null) + makePath(sys_exe_path()); else - sys.FileSystem.fullPath( makePath(hlFile) ); - } - - @:hlNative("std", "sys_utf8_path") static function sys_utf8_path() : Bool { return false; } - - @:hlNative("std","sys_time") public static function time() : Float { return 0.; }; - @:hlNative("std","sys_exit") public static function exit( code : Int ) : Void {}; - @:hlNative("std", "sys_cpu_time") public static function cpuTime() : Float { return 0.; }; - @:hlNative("std", "sys_get_char") public static function getChar( echo : Bool ) : Int { return 0; } - - @:hlNative("std","sys_print") static function sys_print( v : hl.Bytes ) : Void {}; - @:hlNative("std", "file_stdin") static function file_stdin() : sys.io.File.FileHandle { return null; } - @:hlNative("std", "file_stdout") static function file_stdout() : sys.io.File.FileHandle { return null; } - @:hlNative("std", "file_stderr") static function file_stderr() : sys.io.File.FileHandle { return null; } - @:hlNative("std", "sys_args") static function sys_args() : hl.NativeArray { return null; } - @:hlNative("std", "sys_get_env") static function get_env( key : hl.Bytes ) : hl.Bytes { return null; } - @:hlNative("std", "sys_put_env") static function put_env( key : hl.Bytes, val : hl.Bytes ) : Bool { return false; } - @:hlNative("std", "sys_env") static function sys_env() : hl.NativeArray { return null; } - @:hlNative("std", "sys_set_time_locale") static function set_time_locale( loc : hl.Bytes ) : Bool { return true; } - @:hlNative("std", "sys_get_cwd") static function get_cwd() : hl.Bytes { return null; } - @:hlNative("std", "sys_set_cwd") static function set_cwd( path : hl.Bytes ) : Bool { return true; } - @:hlNative("std", "sys_command") static function sys_command( cmd : hl.Bytes ) : Int { return 0; } - @:hlNative("std", "sys_exe_path") static function sys_exe_path() : hl.Bytes { return null; } - @:hlNative("std", "sys_hl_file") static function sys_hl_file() : hl.Bytes { return null; } - @:hlNative("std", "sys_string") static function sys_string() : hl.Bytes { return null; } - -} \ No newline at end of file + sys.FileSystem.fullPath(makePath(hlFile)); + } + + @:hlNative("std", "sys_utf8_path") static function sys_utf8_path():Bool { + return false; + } + + @:hlNative("std", "sys_time") public static function time():Float { + return 0.; + }; + + @:hlNative("std", "sys_exit") public static function exit(code:Int):Void {}; + + @:hlNative("std", "sys_cpu_time") public static function cpuTime():Float { + return 0.; + }; + + @:hlNative("std", "sys_get_char") public static function getChar(echo:Bool):Int { + return 0; + } + + @:hlNative("std", "sys_print") static function sys_print(v:hl.Bytes):Void {}; + + @:hlNative("std", "file_stdin") static function file_stdin():sys.io.File.FileHandle { + return null; + } + + @:hlNative("std", "file_stdout") static function file_stdout():sys.io.File.FileHandle { + return null; + } + + @:hlNative("std", "file_stderr") static function file_stderr():sys.io.File.FileHandle { + return null; + } + + @:hlNative("std", "sys_args") static function sys_args():hl.NativeArray { + return null; + } + + @:hlNative("std", "sys_get_env") static function get_env(key:hl.Bytes):hl.Bytes { + return null; + } + + @:hlNative("std", "sys_put_env") static function put_env(key:hl.Bytes, val:hl.Bytes):Bool { + return false; + } + + @:hlNative("std", "sys_env") static function sys_env():hl.NativeArray { + return null; + } + + @:hlNative("std", "sys_set_time_locale") static function set_time_locale(loc:hl.Bytes):Bool { + return true; + } + + @:hlNative("std", "sys_get_cwd") static function get_cwd():hl.Bytes { + return null; + } + + @:hlNative("std", "sys_set_cwd") static function set_cwd(path:hl.Bytes):Bool { + return true; + } + + @:hlNative("std", "sys_command") static function sys_command(cmd:hl.Bytes):Int { + return 0; + } + + @:hlNative("std", "sys_exe_path") static function sys_exe_path():hl.Bytes { + return null; + } + + @:hlNative("std", "sys_hl_file") static function sys_hl_file():hl.Bytes { + return null; + } + + @:hlNative("std", "sys_string") static function sys_string():hl.Bytes { + return null; + } +} diff --git a/std/hl/_std/Type.hx b/std/hl/_std/Type.hx index 6aeb8a5b73d..a80bd68267a 100644 --- a/std/hl/_std/Type.hx +++ b/std/hl/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,6 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - enum ValueType { TNull; TInt; @@ -27,23 +26,24 @@ enum ValueType { TBool; TObject; TFunction; - TClass( c : Class ); - TEnum( e : Enum ); + TClass(c:Class); + TEnum(e:Enum); TUnknown; } @:coreApi class Type { + static var allTypes(get, never):hl.types.BytesMap; - static var allTypes(get,never) : hl.types.BytesMap; - static inline function get_allTypes() : hl.types.BytesMap return untyped $allTypes(); + static inline function get_allTypes():hl.types.BytesMap + return untyped $allTypes(); - @:keep static function init() : Void { + @:keep static function init():Void { untyped $allTypes(new hl.types.BytesMap()); } - @:keep static function initClass( ct : hl.Type, t : hl.Type, name : hl.Bytes ) : hl.BaseType.Class @:privateAccess { - var c : hl.BaseType.Class = ct.allocObject(); + @:keep static function initClass(ct:hl.Type, t:hl.Type, name:hl.Bytes):hl.BaseType.Class@:privateAccess { + var c:hl.BaseType.Class = ct.allocObject(); t.setGlobal(c); c.__type__ = t; c.__name__ = String.fromUCS2(name); @@ -51,131 +51,140 @@ class Type { return c; } - @:keep static function initEnum( et : hl.Type, t : hl.Type ) : hl.BaseType.Enum @:privateAccess { - var e : hl.BaseType.Enum = et.allocObject(); + @:keep static function initEnum(et:hl.Type, t:hl.Type):hl.BaseType.Enum@:privateAccess { + var e:hl.BaseType.Enum = et.allocObject(); e.__type__ = t; e.__evalues__ = t.getEnumValues(); - e.__ename__ = t.getName(); + e.__ename__ = t.getTypeName(); e.__emap__ = new hl.types.BytesMap(); e.__constructs__ = new Array(); var cl = t.getEnumFields(); - for( i in 0...cl.length ) { + for (i in 0...cl.length) { var name = cl[i]; e.__emap__.set(name, i); e.__constructs__.push(String.fromUCS2(name)); } - register(e.__ename__.bytes,e); + register(e.__ename__.bytes, e); t.setGlobal(e); return e; } - @:keep static function register( b : hl.Bytes, t : hl.BaseType ) : Void { + @:keep static function register(b:hl.Bytes, t:hl.BaseType):Void { allTypes.set(b, t); } - public static function getClass( o : T ) : Class { + public static function getClass(o:T):Class { var t = hl.Type.getDynamic(o); - if( t.kind == HVirtual ) { + if (t.kind == HVirtual) { o = hl.Api.getVirtualValue(o); t = hl.Type.getDynamic(o); } - if( t.kind == HObj ) + if (t.kind == HObj) return t.getGlobal(); return null; } - public static function getEnum( o : EnumValue ) : Enum { + public static function getEnum(o:EnumValue):Enum { var t = hl.Type.getDynamic(o); - if( t.kind == HEnum ) + if (t.kind == HEnum) return t.getGlobal(); return null; } - public static function getSuperClass( c : Class ) : Class @:privateAccess { - var c : hl.BaseType.Class = cast c; + public static function getSuperClass(c:Class):Class@:privateAccess { + var c:hl.BaseType.Class = cast c; var t = c.__type__.getSuper(); return t == hl.Type.get((null : Void)) ? null : t.getGlobal(); } - public static function getClassName( c : Class ) : String { - var c : hl.BaseType.Class = cast c; + public static function getClassName(c:Class):String { + var c:hl.BaseType.Class = cast c; return c.__name__; } - public static function getEnumName( e : Enum ) : String { - var e : hl.BaseType.Enum = cast e; + public static function getEnumName(e:Enum):String { + var e:hl.BaseType.Enum = cast e; return e.__ename__; } - public static function resolveClass( name : String ) : Class { - var t : hl.BaseType = allTypes.get(@:privateAccess name.bytes); - if( t == null || !Std.is(t, hl.BaseType.Class) ) + public static function resolveClass(name:String):Class { + var t:hl.BaseType = allTypes.get(@:privateAccess name.bytes); + if (t == null || !Std.is(t, hl.BaseType.Class)) return null; return cast t; } - public static function resolveEnum( name : String ) : Enum { - var t : hl.BaseType = allTypes.get(@:privateAccess name.bytes); - if( t == null || !Std.is(t, hl.BaseType.Enum) ) + public static function resolveEnum(name:String):Enum { + var t:hl.BaseType = allTypes.get(@:privateAccess name.bytes); + if (t == null || !Std.is(t, hl.BaseType.Enum)) return null; return cast t; } - public static function createInstance( cl : Class, args : Array ) : T { - var c : hl.BaseType.Class = cast cl; + public static function createInstance(cl:Class, args:Array):T { + var c:hl.BaseType.Class = cast cl; var t = c.__type__; - if( t == hl.Type.get((null : hl.types.ArrayBase.ArrayAccess)) ) + if (t == hl.Type.get((null : hl.types.ArrayBase.ArrayAccess))) return cast new Array(); var o = t.allocObject(); - if( c.__constructor__ != null ) Reflect.callMethod(o, c.__constructor__, args); + if (c.__constructor__ != null) { + var v:Dynamic = hl.Api.noClosure(c.__constructor__); + var args = args.copy(); + args.unshift(o); + Reflect.callMethod(null, v, args); + } return o; } - public static function createEmptyInstance( cl : Class ) : T { - var c : hl.BaseType.Class = cast cl; + public static function createEmptyInstance(cl:Class):T { + var c:hl.BaseType.Class = cast cl; return c.__type__.allocObject(); } - public static function createEnum( e : Enum, constr : String, ?params : Array ) : T { - var en : hl.BaseType.Enum = cast e; - var idx : Null = en.__emap__.get(@:privateAccess constr.bytes); - if( idx == null ) throw "Unknown enum constructor " + en.__ename__ +"." + constr; - return createEnumIndex(e,idx,params); + public static function createEnum(e:Enum, constr:String, ?params:Array):T { + var en:hl.BaseType.Enum = cast e; + var idx:Null = en.__emap__.get(@:privateAccess constr.bytes); + if (idx == null) + throw "Unknown enum constructor " + en.__ename__ + "." + constr; + return createEnumIndex(e, idx, params); } - public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T { - var e : hl.BaseType.Enum = cast e; - if( index < 0 || index >= e.__constructs__.length ) throw "Invalid enum index " + e.__ename__ +"." + index; - if( params == null || params.length == 0 ) { + public static function createEnumIndex(e:Enum, index:Int, ?params:Array):T { + var e:hl.BaseType.Enum = cast e; + if (index < 0 || index >= e.__constructs__.length) + throw "Invalid enum index " + e.__ename__ + "." + index; + if (params == null || params.length == 0) { var v = index >= e.__evalues__.length ? null : e.__evalues__[index]; - if( v == null ) throw "Constructor " + e.__ename__ +"." + e.__constructs__[index] + " takes parameters"; + if (v == null) + throw "Constructor " + e.__ename__ + "." + e.__constructs__[index] + " takes parameters"; return v; } - var a : hl.types.ArrayDyn = cast params; + var a:hl.types.ArrayDyn = cast params; var narr; - if( @:privateAccess !a.array.isArrayObj() ) { + if (@:privateAccess !a.array.isArrayObj()) { narr = new hl.NativeArray(a.length); - for( i in 0...a.length ) + for (i in 0...a.length) narr[i] = @:privateAccess a.array.getDyn(i); } else { - var aobj : hl.types.ArrayObj = cast @:privateAccess a.array; + var aobj:hl.types.ArrayObj = cast @:privateAccess a.array; narr = @:privateAccess aobj.array; } var v = @:privateAccess e.__type__.allocEnum(index, narr, a.length); - if( v == null ) throw "Constructor " + e.__ename__ +"." + e.__constructs__[index] + " does not takes " + narr.length + " parameters"; + if (v == null) + throw "Constructor " + e.__ename__ + "." + e.__constructs__[index] + " does not takes " + narr.length + " parameters"; return v; } - public static function getInstanceFields( c : Class ) : Array @:privateAccess { - var c : hl.BaseType.Class = cast c; + public static function getInstanceFields(c:Class):Array@:privateAccess { + var c:hl.BaseType.Class = cast c; var fields = c.__type__.getInstanceFields(); - return [for( f in fields ) String.fromUCS2(f)]; + return [for (f in fields) String.fromUCS2(f)]; } - public static function getClassFields( c : Class ) : Array { - var c : hl.BaseType.Class = cast c; + public static function getClassFields(c:Class):Array { + var c:hl.BaseType.Class = cast c; var fields = @:privateAccess Reflect.getObjectFields(c); - var fields = [for( f in fields ) @:privateAccess String.fromUCS2(f)]; + var fields = [for (f in fields) @:privateAccess String.fromUCS2(f)]; fields.remove("__constructor__"); fields.remove("__meta__"); fields.remove("__name__"); @@ -184,75 +193,75 @@ class Type { return fields; } - public static function getEnumConstructs( e : Enum ) : Array { - var e : hl.BaseType.Enum = cast e; + public static function getEnumConstructs(e:Enum):Array { + var e:hl.BaseType.Enum = cast e; return e.__constructs__.copy(); } - public static function typeof( v : Dynamic ) : ValueType { + public static function typeof(v:Dynamic):ValueType { var t = hl.Type.getDynamic(v); - switch( t.kind ) { - case HVoid: - return TNull; - case HUI8, HUI16, HI32: - return TInt; - case HF32, HF64: - return TFloat; - case HBool: - return TBool; - case HDynObj: - return TObject; - case HObj: - var c : Dynamic = Type.getClass(v); - if( c == Class || c == null ) - return TObject; - return TClass(c); - case HEnum: - return TEnum(Type.getEnum(v)); - case HFun: - return TFunction; - case HVirtual: - var v = hl.Api.getVirtualValue(v); - if( v == null ) + switch (t.kind) { + case HVoid: + return TNull; + case HUI8, HUI16, HI32: + return TInt; + case HF32, HF64: + return (v : Int) == (v:Float) ? TInt : TFloat; + case HBool: + return TBool; + case HDynObj: return TObject; - return typeof(v); - default: - return TUnknown; + case HObj: + var c:Dynamic = Type.getClass(v); + if (c == Class || c == null) + return TObject; + return TClass(c); + case HEnum: + return TEnum(Type.getEnum(v)); + case HFun: + return TFunction; + case HVirtual: + var v = hl.Api.getVirtualValue(v); + if (v == null) + return TObject; + return typeof(v); + default: + return TUnknown; } } - @:hlNative("std","type_enum_eq") - public static function enumEq( a : T, b : T ) : Bool { + @:hlNative("std", "type_enum_eq") + public static function enumEq(a:T, b:T):Bool { return false; } - public static function enumConstructor( e : EnumValue ) : String { - var en : hl.BaseType.Enum = cast getEnum(e); + public static function enumConstructor(e:EnumValue):String { + var en:hl.BaseType.Enum = cast getEnum(e); return en.__constructs__[Type.enumIndex(e)]; } - @:hlNative("std","enum_parameters") - static function _enumParameters( e : EnumValue ) : hl.NativeArray { + @:hlNative("std", "enum_parameters") + static function _enumParameters(e:EnumValue):hl.NativeArray { return null; } - public static function enumParameters( e : EnumValue ) : Array { + public static function enumParameters(e:EnumValue):Array { var arr = _enumParameters(e); return cast hl.types.ArrayObj.alloc(arr); } - public static function enumIndex( e : EnumValue ) : Int { + public static function enumIndex(e:EnumValue):Int { return untyped $enumIndex(e); } - public static function allEnums( e : Enum ) : Array { - var en : hl.BaseType.Enum = cast e; + public static function allEnums(e:Enum):Array { + var en:hl.BaseType.Enum = cast e; var out = []; - for( i in 0...en.__evalues__.length ) { + for (i in 0...en.__evalues__.length) { var v = en.__evalues__[i]; - if( v != null ) out.push(v); + if (v != null) + out.push(v); } return out; } - -} \ No newline at end of file +} diff --git a/std/hl/_std/UInt.hx b/std/hl/_std/UInt.hx index c6a12a448a0..8a404e7104b 100644 --- a/std/hl/_std/UInt.hx +++ b/std/hl/_std/UInt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,10 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - @:coreApi abstract UInt(Int) from Int to Int { - @:op(A + B) private static inline function add(a:UInt, b:UInt):UInt { return a.toInt() + b.toInt(); } @@ -101,27 +99,18 @@ abstract UInt(Int) from Int to Int { return a.toFloat() > b; } - @:commutative @:op(A == B) private static inline function equalsInt(a:UInt, b:T):Bool { - return a.toInt() == b; - } + @:commutative @:op(A == B) private static function equalsInt(a:UInt, b:T):Bool; - @:commutative @:op(A != B) private static inline function notEqualsInt(a:UInt, b:T):Bool { - return a.toInt() != b; - } + @:commutative @:op(A != B) private static function notEqualsInt(a:UInt, b:T):Bool; - @:commutative @:op(A == B) private static inline function equalsFloat(a:UInt, b:T):Bool { - return a.toFloat() == b; - } + @:commutative @:op(A == B) private static function equalsFloat(a:UInt, b:T):Bool; - @:commutative @:op(A != B) private static inline function notEqualsFloat(a:UInt, b:T):Bool { - return a.toFloat() != b; - } + @:commutative @:op(A != B) private static function notEqualsFloat(a:UInt, b:T):Bool; @:op(A >= B) private static inline function gteFloat(a:UInt, b:Float):Bool { return a.toFloat() >= b; } - @:op(A > B) private static inline function floatGt(a:Float, b:UInt):Bool { return a > b.toFloat(); } @@ -184,7 +173,6 @@ abstract UInt(Int) from Int to Int { } @:to private inline function toFloat():Float { - return cast (this:UInt); + return cast(this : UInt); } } - diff --git a/std/hl/_std/haxe/Resource.hx b/std/hl/_std/haxe/Resource.hx index cc22a5173bd..1601578905c 100644 --- a/std/hl/_std/haxe/Resource.hx +++ b/std/hl/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,39 +19,38 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; private class ResourceContent { - public var name : hl.Bytes; - public var data : hl.Bytes; - public var dataLen : Int; + public var name:hl.Bytes; + public var data:hl.Bytes; + public var dataLen:Int; } @:coreApi class Resource { + static var content:hl.NativeArray; - static var content : hl.NativeArray; - - public static function listNames() : Array { + public static function listNames():Array { return [for (x in content) @:privateAccess String.fromUCS2(x.name)]; } - public static function getString( name : String ) : String { - for( x in content ) - if( x.name.compare(0,@:privateAccess name.bytes,0,(name.length+1)<<1) == 0 ) + public static function getString(name:String):String { + for (x in content) + if (x.name.compare(0, @:privateAccess name.bytes, 0, (name.length + 1) << 1) == 0) return @:privateAccess String.fromUTF8(x.data); return null; } - public static function getBytes( name : String ) : haxe.io.Bytes { - for( x in content ) - if( x.name.compare(0,@:privateAccess name.bytes,0,(name.length+1)<<1) == 0 ) + public static function getBytes(name:String):haxe.io.Bytes { + for (x in content) + if (x.name.compare(0, @:privateAccess name.bytes, 0, (name.length + 1) << 1) == 0) return @:privateAccess new haxe.io.Bytes(x.data, x.dataLen); return null; } - static function __init__() : Void { + static function __init__():Void { content = untyped $resources(); } - } diff --git a/std/cs/_std/haxe/Log.hx b/std/hl/_std/haxe/crypto/Md5.hx similarity index 71% rename from std/cs/_std/haxe/Log.hx rename to std/hl/_std/haxe/crypto/Md5.hx index 2bce0e53cd6..b30278bba06 100644 --- a/std/cs/_std/haxe/Log.hx +++ b/std/hl/_std/haxe/crypto/Md5.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,20 +19,19 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe; -@:coreApi class Log { - public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { - var str:String = null; - if (infos != null) { - str = infos.fileName + ":" + infos.lineNumber + ": " + v; - if (infos.customParams != null) - { - str += "," + infos.customParams.join(","); - } - } else { - str = v; - } - cs.system.Console.WriteLine(str); +package haxe.crypto; + +class Md5 { + public static function encode(s:String):String { + var out = haxe.io.Bytes.alloc(16); + @:privateAccess hl.Format.digest(out.b, s.bytes, s.length, 256); + return out.toHex(); + } + + public static function make(b:haxe.io.Bytes):haxe.io.Bytes { + var out = haxe.io.Bytes.alloc(16); + @:privateAccess hl.Format.digest(out.b, b.b, b.length, 0); + return out; } } diff --git a/std/hl/_std/haxe/crypto/Sha1.hx b/std/hl/_std/haxe/crypto/Sha1.hx new file mode 100644 index 00000000000..d614993ad73 --- /dev/null +++ b/std/hl/_std/haxe/crypto/Sha1.hx @@ -0,0 +1,37 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.crypto; + +class Sha1 { + public static function encode(s:String):String { + var out = haxe.io.Bytes.alloc(20); + @:privateAccess hl.Format.digest(out.b, s.bytes, s.length, 256 | 1); + return out.toHex(); + } + + public static function make(b:haxe.io.Bytes):haxe.io.Bytes { + var out = haxe.io.Bytes.alloc(20); + @:privateAccess hl.Format.digest(out.b, b.b, b.length, 1); + return out; + } +} diff --git a/std/hl/_std/haxe/ds/IntMap.hx b/std/hl/_std/haxe/ds/IntMap.hx index c117551efb8..663682b2922 100644 --- a/std/hl/_std/haxe/ds/IntMap.hx +++ b/std/hl/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,51 +23,55 @@ package haxe.ds; @:coreApi -class IntMap implements haxe.Constraints.IMap { +class IntMap implements haxe.Constraints.IMap { + var h:hl.types.IntMap; - var h : hl.types.IntMap; - - public function new() : Void { + public function new():Void { h = new hl.types.IntMap(); } - public function set( key : Int, value : T ) : Void { - @:privateAccess h.set(key,value); + public function set(key:Int, value:T):Void { + @:privateAccess h.set(key, value); } - public function get( key : Int ) : Null { + public function get(key:Int):Null { return @:privateAccess h.get(key); } - public function exists( key : Int ) : Bool { + public function exists(key:Int):Bool { return @:privateAccess h.exists(key); } - public function remove( key : Int ) : Bool { + public function remove(key:Int):Bool { return @:privateAccess h.remove(key); } - public function keys() : Iterator { + public function keys():Iterator { return new hl.NativeArray.NativeArrayIterator(h.keysArray()); } - public function iterator() : Iterator { + public function iterator():Iterator { return h.iterator(); } - - public function copy() : IntMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():IntMap { var copied = new IntMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = new StringBuf(); var keys = h.keysArray(); var values = h.valuesArray(); s.addChar('{'.code); - for( i in 0...keys.length ) { - if( i > 0 ) + for (i in 0...keys.length) { + if (i > 0) s.add(", "); s.add(keys[i]); s.add(" => "); @@ -76,5 +80,4 @@ class IntMap implements haxe.Constraints.IMap { s.addChar('}'.code); return s.toString(); } - } diff --git a/std/hl/_std/haxe/ds/ObjectMap.hx b/std/hl/_std/haxe/ds/ObjectMap.hx index 9e12982c787..4f507c7f09a 100644 --- a/std/hl/_std/haxe/ds/ObjectMap.hx +++ b/std/hl/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,51 +23,55 @@ package haxe.ds; @:coreApi -class ObjectMap implements haxe.Constraints.IMap { +class ObjectMap implements haxe.Constraints.IMap { + var h:hl.types.ObjectMap; - var h : hl.types.ObjectMap; - - public function new() : Void { + public function new():Void { h = new hl.types.ObjectMap(); } - public function set( key : K, value : T ) : Void { - @:privateAccess h.set(key,value); + public function set(key:K, value:T):Void { + @:privateAccess h.set(key, value); } - public function get( key : K ) : Null { + public function get(key:K):Null { return @:privateAccess h.get(key); } - public function exists( key : K ) : Bool { + public function exists(key:K):Bool { return @:privateAccess h.exists(key); } - public function remove( key : K ) : Bool { + public function remove(key:K):Bool { return @:privateAccess h.remove(key); } - public function keys() : Iterator { + public function keys():Iterator { return new hl.NativeArray.NativeArrayIterator(cast h.keysArray()); } - public function iterator() : Iterator { + public function iterator():Iterator { return h.iterator(); } - - public function copy() : ObjectMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():ObjectMap { var copied = new ObjectMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = new StringBuf(); var keys = h.keysArray(); var values = h.valuesArray(); s.addChar('{'.code); - for( i in 0...keys.length ) { - if( i > 0 ) + for (i in 0...keys.length) { + if (i > 0) s.add(", "); s.add(keys[i]); s.add(" => "); @@ -76,5 +80,4 @@ class ObjectMap implements haxe.Constraints.IMap { s.addChar('}'.code); return s.toString(); } - } diff --git a/std/hl/_std/haxe/ds/StringMap.hx b/std/hl/_std/haxe/ds/StringMap.hx index 1180df5a670..c885e2edc01 100644 --- a/std/hl/_std/haxe/ds/StringMap.hx +++ b/std/hl/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,9 +23,9 @@ package haxe.ds; private class StringMapKeysIterator { - var arr : hl.NativeArray; - var pos : Int; - var length : Int; + var arr:hl.NativeArray; + var pos:Int; + var length:Int; public inline function new(h:hl.types.BytesMap) { this.arr = h.keysArray(); @@ -41,66 +41,71 @@ private class StringMapKeysIterator { var b = arr[pos++]; return String.fromUCS2(b); } - } @:coreApi -class StringMap implements haxe.Constraints.IMap { - - var h : hl.types.BytesMap; +class StringMap implements haxe.Constraints.IMap { + var h:hl.types.BytesMap; - public function new() : Void { + public function new():Void { h = new hl.types.BytesMap(); } - public function set( key : String, value : T ) : Void { - @:privateAccess h.set(key.bytes,value); + public function set(key:String, value:T):Void { + @:privateAccess h.set(key.bytes, value); } - public function get( key : String ) : Null { - if( key == null ) return null; + public function get(key:String):Null { + if (key == null) + return null; return @:privateAccess h.get(key.bytes); } - public function exists( key : String ) : Bool { - if( key == null ) return false; + public function exists(key:String):Bool { + if (key == null) + return false; return @:privateAccess h.exists(key.bytes); } - public function remove( key : String ) : Bool { - if( key == null ) return false; + public function remove(key:String):Bool { + if (key == null) + return false; return @:privateAccess h.remove(key.bytes); } - public function keys() : Iterator { + public function keys():Iterator { return new StringMapKeysIterator(h); } - public function iterator() : Iterator { + public function iterator():Iterator { return h.iterator(); } - - public function copy() : StringMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():StringMap { var copied = new StringMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = new StringBuf(); var keys = h.keysArray(); var values = h.valuesArray(); s.addChar('{'.code); - for( i in 0...keys.length ) { - if( i > 0 ) + for (i in 0...keys.length) { + if (i > 0) s.add(", "); var k = keys[i]; - @:privateAccess s.__add(k,0,(@:privateAccess k.ucs2Length(0)) << 1); + @:privateAccess s.__add(k, 0, (@:privateAccess k.ucs2Length(0)) << 1); s.add(" => "); s.add(values[i]); } s.addChar('}'.code); return s.toString(); } - } diff --git a/std/hl/_std/haxe/ds/Vector.hx b/std/hl/_std/haxe/ds/Vector.hx index 44815ff33b1..d56f1e5a3e3 100644 --- a/std/hl/_std/haxe/ds/Vector.hx +++ b/std/hl/_std/haxe/ds/Vector.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,16 +19,17 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; private typedef VectorData = Array @:coreApi abstract Vector(VectorData) { - public inline function new(length:Int) { this = []; - if( length > 0 ) this[length-1] = cast null; + if (length > 0) + this[length - 1] = cast null; } @:op([]) public inline function get(index:Int):T { @@ -46,7 +47,7 @@ abstract Vector(VectorData) { } public static inline function blit(src:Vector, srcPos:Int, dest:Vector, destPos:Int, len:Int):Void { - (cast dest : hl.types.ArrayBase.ArrayAccess).blit(destPos,(cast src : hl.types.ArrayBase.ArrayAccess),srcPos,len); + (cast dest : hl.types.ArrayBase.ArrayAccess).blit(destPos, (cast src : hl.types.ArrayBase.ArrayAccess), srcPos, len); } public inline function toArray():Array { @@ -80,7 +81,7 @@ abstract Vector(VectorData) { var r = new Vector(length); var i = 0; var len = length; - for(i in 0...len) { + for (i in 0...len) { var v = f(get(i)); r.set(i, v); } diff --git a/std/hl/_std/haxe/io/Bytes.hx b/std/hl/_std/haxe/io/Bytes.hx index e93ab5f168c..156e521829b 100644 --- a/std/hl/_std/haxe/io/Bytes.hx +++ b/std/hl/_std/haxe/io/Bytes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,113 +19,164 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; @:coreApi class Bytes { + public var length(default, null):Int; - public var length(default,null) : Int; - var b : hl.Bytes; + var b:hl.Bytes; - function new(b:hl.Bytes,length:Int) : Void { + function new(b:hl.Bytes, length:Int):Void { this.b = b; this.length = length; } - inline function out(pos:Int) : Bool { - return (pos:UInt) >= (length : UInt); + inline function out(pos:Int):Bool { + return (pos : UInt) >= (length : UInt); } - inline function outRange(pos:Int,len:Int) : Bool { - return pos < 0 || len < 0 || ((pos+len):UInt) > (length : UInt); + inline function outRange(pos:Int, len:Int):Bool { + return pos < 0 || len < 0 || ((pos + len) : UInt) > (length : UInt); } - public function get( pos : Int ) : Int { - return if( out(pos) ) 0 else b[pos]; + public function get(pos:Int):Int { + return if (out(pos)) 0 else b[pos]; } - public function set( pos : Int, v : Int ) : Void { - if( out(pos) ) throw Error.OutsideBounds; + public function set(pos:Int, v:Int):Void { + if (out(pos)) + throw Error.OutsideBounds; b[pos] = v; } - public function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void { - if( outRange(pos, len) || src.outRange(srcpos,len) ) throw Error.OutsideBounds; + public function blit(pos:Int, src:Bytes, srcpos:Int, len:Int):Void { + if (outRange(pos, len) || src.outRange(srcpos, len)) + throw Error.OutsideBounds; b.blit(pos, src.b, srcpos, len); } - public function fill( pos : Int, len : Int, value : Int ) : Void { - if( outRange(pos,len) ) throw Error.OutsideBounds; + public function fill(pos:Int, len:Int, value:Int):Void { + if (outRange(pos, len)) + throw Error.OutsideBounds; b.fill(pos, len, value); } - public function sub( pos : Int, len : Int ) : Bytes { - if( outRange(pos,len) ) throw Error.OutsideBounds; + public function sub(pos:Int, len:Int):Bytes { + if (outRange(pos, len)) + throw Error.OutsideBounds; return new Bytes(b.sub(pos, len), len); } - public function compare( other : Bytes ) : Int { + public function compare(other:Bytes):Int { var len = length < other.length ? length : other.length; var r = b.compare(0, other.b, 0, len); - if( r == 0 ) + if (r == 0) r = length - other.length; return r; } - public function getDouble( pos : Int ) : Float { - return if( out(pos + 7) ) 0. else b.getF64(pos); - } - - public function getFloat( pos : Int ) : Float { - return if( out(pos + 3) ) 0. else b.getF32(pos); - } + #if hl_check_align + static var alignBuffer:hl.Bytes = new hl.Bytes(8); + #end - public function setDouble( pos : Int, v : Float ) : Void { - if( out(pos + 7) ) throw Error.OutsideBounds; + public function getDouble(pos:Int):Float { + if (out(pos + 7)) + return 0.; + #if hl_check_align + return if (pos & 3 == 0) b.getF64(pos) else { + alignBuffer.blit(0, b, pos, 8); + alignBuffer.getF64(0); + } + #else + return b.getF64(pos); + #end + } + + public function getFloat(pos:Int):Float { + if (out(pos + 3)) + return 0.; + #if hl_check_align + return if (pos & 3 == 0) b.getF32(pos) else { + alignBuffer.blit(0, b, pos, 4); + alignBuffer.getF32(0); + } + #else + return b.getF32(pos); + #end + } + + public function setDouble(pos:Int, v:Float):Void { + if (out(pos + 7)) + throw Error.OutsideBounds; + #if hl_check_align + if (pos & 7 == 0) + b.setF64(pos, v); + else { + alignBuffer.setF64(0, v); + b.blit(pos, alignBuffer, 0, 8); + } + #else b.setF64(pos, v); - } - - public function setFloat( pos : Int, v : Float ) : Void { - if( out(pos + 3) ) throw Error.OutsideBounds; + #end + } + + public function setFloat(pos:Int, v:Float):Void { + if (out(pos + 3)) + throw Error.OutsideBounds; + #if hl_check_align + if (pos & 3 == 0) + b.setF32(pos, v); + else { + alignBuffer.setF32(0, v); + b.blit(pos, alignBuffer, 0, 4); + } + #else b.setF32(pos, v); + #end } - public inline function getUInt16( pos : Int ) : Int { - return if( out(pos + 1) ) 0 else b.getUI16(pos); + public inline function getUInt16(pos:Int):Int { + return if (out(pos + 1)) 0 else b.getUI16(pos); } - public inline function setUInt16( pos : Int, v : Int ) : Void { - if( out(pos + 1) ) throw Error.OutsideBounds; + public inline function setUInt16(pos:Int, v:Int):Void { + if (out(pos + 1)) + throw Error.OutsideBounds; b.setUI16(pos, v); } - public function getInt32( pos : Int ) : Int { - return if( out(pos + 3) ) 0 else b.getI32(pos); + public function getInt32(pos:Int):Int { + return if (out(pos + 3)) 0 else b.getI32(pos); } - public function getInt64( pos : Int ) : haxe.Int64 { - if( out(pos + 7) ) + public function getInt64(pos:Int):haxe.Int64 { + if (out(pos + 7)) return haxe.Int64.ofInt(0); - return haxe.Int64.make(b.getI32(pos+4), b.getI32(pos)); + return haxe.Int64.make(b.getI32(pos + 4), b.getI32(pos)); } - public function setInt32( pos : Int, v : Int ) : Void { - if( out(pos + 3) ) throw Error.OutsideBounds; + public function setInt32(pos:Int, v:Int):Void { + if (out(pos + 3)) + throw Error.OutsideBounds; b.setI32(pos, v); } - public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { + public inline function setInt64(pos:Int, v:haxe.Int64):Void { setInt32(pos + 4, v.high); setInt32(pos, v.low); } - public function getString( pos : Int, len : Int ) : String { - if( outRange(pos,len) ) throw Error.OutsideBounds; + public function getString(pos:Int, len:Int, ?encoding:Encoding):String { + if (outRange(pos, len)) + throw Error.OutsideBounds; - var b = new hl.Bytes(len + 1); + var b = new hl.Bytes(len + 2); b.blit(0, this.b, pos, len); b[len] = 0; - return @:privateAccess String.fromUTF8(b); + b[len + 1] = 0; + return @:privateAccess (encoding == RawNative ? String.fromUCS2(b) : String.fromUTF8(b)); } @:deprecated("readString is deprecated, use getString instead") @@ -134,17 +185,17 @@ class Bytes { return getString(pos, len); } - public function toString() : String { - return getString(0,length); + public function toString():String { + return getString(0, length); } - public function toHex() : String { + public function toHex():String { var s = new StringBuf(); var chars = []; var str = "0123456789abcdef"; - for( i in 0...str.length ) + for (i in 0...str.length) chars.push(str.charCodeAt(i)); - for( i in 0...length ) { + for (i in 0...length) { var c = get(i); s.addChar(chars[c >> 4]); s.addChar(chars[c & 15]); @@ -152,28 +203,51 @@ class Bytes { return s.toString(); } - public inline function getData() : BytesData { - return new haxe.io.BytesData(b,length); + public inline function getData():BytesData { + return new haxe.io.BytesData(b, length); } - public static function alloc( length : Int ) : Bytes { + public static function alloc(length:Int):Bytes { var b = new hl.Bytes(length); b.fill(0, length, 0); - return new Bytes(b,length); + return new Bytes(b, length); + } + + public static function ofString(s:String, ?encoding:Encoding):Bytes@:privateAccess { + if (encoding == null) + encoding = UTF8; + return switch (encoding) { + case RawNative: + return new Bytes(s.bytes.sub(0, s.length << 1), s.length << 1); + case UTF8: + var size = 0; + var b = s.bytes.utf16ToUtf8(0, size); + return new Bytes(b, size); + } } - public static function ofString( s : String ) : Bytes @:privateAccess { - var size = 0; - var b = s.bytes.utf16ToUtf8(0, size); - return new Bytes(b,size); + public static function ofData(b:BytesData):Bytes { + return new Bytes(b.bytes, b.length); } - public static function ofData( b : BytesData ) : Bytes { - return new Bytes(b.bytes,b.length); + public static function ofHex(s:String):Bytes { + var len = s.length; + if ((len & 1) != 0) + throw "Not a hex string (odd number of digits)"; + var l = len >> 1; + var b = new hl.Bytes(l); + for (i in 0...l) { + var high = s.charCodeAt(i * 2); + var low = s.charCodeAt(i * 2 + 1); + high = (high & 0xf) + ((high & 0x40) >> 6) * 9; + low = (low & 0xf) + ((low & 0x40) >> 6) * 9; + b.setUI8(i, ((high << 4) | low) & 0xff); + } + + return new Bytes(b, l); } - public inline static function fastGet( b : BytesData, pos : Int ) : Int { + public inline static function fastGet(b:BytesData, pos:Int):Int { return b[pos]; } - } diff --git a/std/hl/_std/haxe/io/BytesBuffer.hx b/std/hl/_std/haxe/io/BytesBuffer.hx index c0bd1744b20..12893eed0b2 100644 --- a/std/hl/_std/haxe/io/BytesBuffer.hx +++ b/std/hl/_std/haxe/io/BytesBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,16 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; @:coreApi class BytesBuffer { + var b:hl.Bytes; + var pos:Int; + var size:Int; - var b : hl.Bytes; - var pos : Int; - var size : Int; - - public var length(get,never) : Int; + public var length(get, never):Int; public function new() { pos = 0; @@ -36,71 +36,96 @@ class BytesBuffer { b = new hl.Bytes(size); } - inline function get_length() : Int { + inline function get_length():Int { return pos; } - public inline function addByte( byte : Int ) : Void { - if( pos == size ) __expand(0); + public inline function addByte(byte:Int):Void { + if (pos == size) + __expand(0); b[pos++] = byte; } - function __expand( req : Int ) : Void { + function __expand(req:Int):Void { var nsize = (size * 3) >> 1; - if( nsize < req ) nsize = req; + if (nsize < req) + nsize = req; var b2 = new hl.Bytes(nsize); b2.blit(0, b, 0, pos); b = b2; size = nsize; } - function __add( b : hl.Bytes, bpos : Int, blen : Int ) : Void { - if( pos + blen > size ) __expand(pos+blen); + function __add(b:hl.Bytes, bpos:Int, blen:Int):Void { + if (pos + blen > size) + __expand(pos + blen); this.b.blit(pos, b, bpos, blen); pos += blen; } - public inline function add( src : Bytes ) : Void { + public inline function add(src:Bytes):Void { __add(@:privateAccess src.b, 0, src.length); } - public inline function addString( v : String ) : Void { + public inline function addString(v:String, ?encoding:Encoding):Void { var len = 0; - @:privateAccess __add(v.bytes.utf16ToUtf8(0, len), 0, len); + @:privateAccess (encoding == RawNative ? __add(v.bytes, 0, v.length << 1) : __add(v.bytes.utf16ToUtf8(0, len), 0, len)); } - public inline function addInt32( v : Int ) : Void { - if( pos + 4 > size ) __expand(0); + public inline function addInt32(v:Int):Void { + if (pos + 4 > size) + __expand(0); b.setI32(pos, v); pos += 4; } - public inline function addInt64( v : haxe.Int64 ) : Void { - if( pos + 8 > size ) __expand(0); + public inline function addInt64(v:haxe.Int64):Void { + if (pos + 8 > size) + __expand(0); b.setI32(pos, v.low); b.setI32(pos + 4, v.high); pos += 8; } - public inline function addFloat( v : Float ) : Void { - if( pos + 4 > size ) __expand(0); + public inline function addFloat(v:Float):Void { + if (pos + 4 > size) + __expand(0); + #if hl_check_align + if (pos & 3 == 0) + b.setF32(pos, v); + else @:privateAccess { + haxe.io.Bytes.alignBuffer.setF32(0, v); + b.blit(pos, haxe.io.Bytes.alignBuffer, 0, 4); + } + #else b.setF32(pos, v); + #end pos += 4; } - public inline function addDouble( v : Float ) : Void { - if( pos + 8 > size ) __expand(0); + public inline function addDouble(v:Float):Void { + if (pos + 8 > size) + __expand(0); + #if hl_check_align + if (pos & 7 == 0) + b.setF64(pos, v); + else @:privateAccess { + haxe.io.Bytes.alignBuffer.setF64(0, v); + b.blit(pos, haxe.io.Bytes.alignBuffer, 0, 8); + } + #else b.setF64(pos, v); + #end pos += 8; } - public inline function addBytes( src : Bytes, pos : Int, len : Int ) : Void { - if( pos < 0 || len < 0 || pos + len > src.length ) throw Error.OutsideBounds; + public inline function addBytes(src:Bytes, pos:Int, len:Int):Void { + if (pos < 0 || len < 0 || pos + len > src.length) + throw Error.OutsideBounds; __add(@:privateAccess src.b, pos, len); } - public function getBytes() : Bytes { + public function getBytes():Bytes { return @:privateAccess new haxe.io.Bytes(b, pos); } - } diff --git a/std/hl/_std/haxe/io/FPHelper.hx b/std/hl/_std/haxe/io/FPHelper.hx index f9494247afd..2d5389c28b2 100644 --- a/std/hl/_std/haxe/io/FPHelper.hx +++ b/std/hl/_std/haxe/io/FPHelper.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,32 +19,32 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; class FPHelper { - // note : this is not thread safe, use TLS when available static var i64tmp = Int64.ofInt(0); static var helper = new hl.Bytes(8); - public static function i32ToFloat( i : Int ) : Single { - helper.setI32(0,i); + public static function i32ToFloat(i:Int):Single { + helper.setI32(0, i); return helper.getF32(0); } - public static function floatToI32( f : Single ) : Int { - helper.setF32(0,f); + public static function floatToI32(f:Single):Int { + helper.setF32(0, f); return helper.getI32(0); } - public static function i64ToDouble( low : Int, high : Int ) : Float { - helper.setI32(0,low); - helper.setI32(4,high); + public static function i64ToDouble(low:Int, high:Int):Float { + helper.setI32(0, low); + helper.setI32(4, high); return helper.getF64(0); } - public static function doubleToI64( v : Float ) : Int64 { - helper.setF64(0,v); + public static function doubleToI64(v:Float):Int64 { + helper.setF64(0, v); var i64 = i64tmp; @:privateAccess { i64.set_low(helper.getI32(0)); @@ -52,5 +52,4 @@ class FPHelper { } return i64; } - } diff --git a/std/hl/_std/haxe/zip/Compress.hx b/std/hl/_std/haxe/zip/Compress.hx index e4dbebf5ca9..416b0ab433f 100644 --- a/std/hl/_std/haxe/zip/Compress.hx +++ b/std/hl/_std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,51 +19,57 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; private typedef Deflater = hl.Abstract<"fmt_zip">; @:coreApi @:hlNative("fmt") class Compress { + var s:Deflater; - var s : Deflater; - - public function new( level : Int ) : Void { + public function new(level:Int):Void { s = deflate_init(level); } - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { var read = 0, write = 0; - var done = deflate_buffer(s,src.getData(),srcPos,src.length,dst.getData(),dstPos,dst.length,read,write); - return { done : done, read : read, write : write }; + var done = deflate_buffer(s, src.getData(), srcPos, src.length, dst.getData(), dstPos, dst.length, read, write); + return {done: done, read: read, write: write}; } - public function setFlushMode( f : FlushMode ) : Void { - @:privateAccess Uncompress.zip_flush_mode(cast s,f.getIndex()); + public function setFlushMode(f:FlushMode):Void { + @:privateAccess Uncompress.zip_flush_mode(cast s, f.getIndex()); } - public function close() : Void { + public function close():Void { @:privateAccess Uncompress.zip_end(cast s); } - public static function run( s : haxe.io.Bytes, level : Int ) : haxe.io.Bytes { + public static function run(s:haxe.io.Bytes, level:Int):haxe.io.Bytes { var c = new Compress(level); c.setFlushMode(FlushMode.FINISH); - var out = haxe.io.Bytes.alloc(deflate_bound(c.s,s.length)); - var r = c.execute(s,0,out,0); + var out = haxe.io.Bytes.alloc(deflate_bound(c.s, s.length)); + var r = c.execute(s, 0, out, 0); c.close(); - if( !r.done || r.read != s.length ) + if (!r.done || r.read != s.length) throw "Compression failed"; - if( r.write < out.length*0.66 ) + if (r.write < out.length * 0.66) return out.sub(0, r.write); @:privateAccess out.length = r.write; return out; } - static function deflate_init( level : Int ) : Deflater { return null; } - static function deflate_buffer( i : Deflater, bytes : hl.Bytes, bytesPos : Int, bytesLen : Int, dst : hl.Bytes, dstPos : Int, dstLen : Int, read : hl.Ref, write : hl.Ref) : Bool { + static function deflate_init(level:Int):Deflater { + return null; + } + + static function deflate_buffer(i:Deflater, bytes:hl.Bytes, bytesPos:Int, bytesLen:Int, dst:hl.Bytes, dstPos:Int, dstLen:Int, read:hl.Ref, + write:hl.Ref):Bool { return false; } - static function deflate_bound( i : Deflater, length : Int ) : Int { return 0; } + static function deflate_bound(i:Deflater, length:Int):Int { + return 0; + } } diff --git a/std/hl/_std/haxe/zip/Uncompress.hx b/std/hl/_std/haxe/zip/Uncompress.hx index 94f19dc8270..1d13565914b 100644 --- a/std/hl/_std/haxe/zip/Uncompress.hx +++ b/std/hl/_std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,56 +19,62 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; private typedef Inflater = hl.Abstract<"fmt_zip">; @:coreApi @:hlNative("fmt") class Uncompress { + var s:Inflater; - var s : Inflater; - - public function new( ?windowBits : Int ) : Void { + public function new(?windowBits:Int):Void { s = inflate_init(windowBits); } - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { var read = 0, write = 0; - var done = inflate_buffer(s,src.getData(),srcPos,src.length,dst.getData(),dstPos,dst.length,read,write); - return { done : done, read : read, write : write }; + var done = inflate_buffer(s, src.getData(), srcPos, src.length, dst.getData(), dstPos, dst.length, read, write); + return {done: done, read: read, write: write}; } - public function setFlushMode( f : FlushMode ) : Void { - zip_flush_mode(s,f.getIndex()); + public function setFlushMode(f:FlushMode):Void { + zip_flush_mode(s, f.getIndex()); } - public function close() : Void { + public function close():Void { zip_end(s); } - public static function run( src : haxe.io.Bytes, ?bufsize : Int ) : haxe.io.Bytes { + public static function run(src:haxe.io.Bytes, ?bufsize:Int):haxe.io.Bytes { var u = new Uncompress(null); - if( bufsize == null ) bufsize = 1 << 16; // 64K + if (bufsize == null) + bufsize = 1 << 16; // 64K var tmp = haxe.io.Bytes.alloc(bufsize); var b = new haxe.io.BytesBuffer(); var pos = 0; u.setFlushMode(FlushMode.SYNC); - while( true ) { - var r = u.execute(src,pos,tmp,0); - b.addBytes(tmp,0,r.write); + while (true) { + var r = u.execute(src, pos, tmp, 0); + b.addBytes(tmp, 0, r.write); pos += r.read; - if( r.done ) + if (r.done) break; } u.close(); return b.getBytes(); } - static function inflate_init( bits : Int ) : Inflater { return null; } - static function inflate_buffer( i : Inflater, bytes : hl.Bytes, bytesPos : Int, bytesLen : Int, dst : hl.Bytes, dstPos : Int, dstLen : Int, read : hl.Ref, write : hl.Ref) : Bool { + static function inflate_init(bits:Int):Inflater { + return null; + } + + static function inflate_buffer(i:Inflater, bytes:hl.Bytes, bytesPos:Int, bytesLen:Int, dst:hl.Bytes, dstPos:Int, dstLen:Int, read:hl.Ref, + write:hl.Ref):Bool { return false; } - static function zip_end( i : Inflater ) : Void { } - static function zip_flush_mode( i : Inflater, flush : Int ) : Void {} + static function zip_end(i:Inflater):Void {} + + static function zip_flush_mode(i:Inflater, flush:Int):Void {} } diff --git a/std/hl/_std/sys/FileSystem.hx b/std/hl/_std/sys/FileSystem.hx index 20fdf585e4d..f325e303d88 100644 --- a/std/hl/_std/sys/FileSystem.hx +++ b/std/hl/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,52 +19,55 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys; @:coreApi @:access(Sys) class FileSystem { - - public static function exists( path : String ) : Bool { - return sys_exists( Sys.getPath(makeCompatiblePath(path)) ); + public static function exists(path:String):Bool { + return sys_exists(Sys.getPath(makeCompatiblePath(path))); } - public static function rename( path : String, newPath : String ) : Void { - if( !sys_rename( Sys.getPath(path), Sys.getPath(newPath) ) ) throw new Sys.SysError("Failed to rename " + path + " to " + newPath); + public static function rename(path:String, newPath:String):Void { + if (!sys_rename(Sys.getPath(path), Sys.getPath(newPath))) + throw new Sys.SysError("Failed to rename " + path + " to " + newPath); } - public static function stat( path : String ) : FileStat { - var values = sys_stat( Sys.getPath(makeCompatiblePath(path)) ); - if( values == null ) throw new Sys.SysError("Failed to stat " + path); + public static function stat(path:String):FileStat { + var values = sys_stat(Sys.getPath(makeCompatiblePath(path))); + if (values == null) + throw new Sys.SysError("Failed to stat " + path); return { - gid : values[0], - uid : values[1], - atime : @:privateAccess Date.fromInt(values[2]), - mtime : @:privateAccess Date.fromInt(values[3]), - ctime : @:privateAccess Date.fromInt(values[4]), - size : values[5], - dev : values[6], - ino : values[7], - nlink : values[8], - rdev : values[9], - mode : values[10], + gid: values[0], + uid: values[1], + atime: @:privateAccess Date.fromInt(values[2]), + mtime: @:privateAccess Date.fromInt(values[3]), + ctime: @:privateAccess Date.fromInt(values[4]), + size: values[5], + dev: values[6], + ino: values[7], + nlink: values[8], + rdev: values[9], + mode: values[10], }; } - public static function fullPath( relPath : String ) : String { - return Sys.makePath( sys_full_path(Sys.getPath(relPath)) ); + public static function fullPath(relPath:String):String { + return Sys.makePath(sys_full_path(Sys.getPath(relPath))); } - public static function absolutePath ( relPath : String ) : String { - if (haxe.io.Path.isAbsolute(relPath)) return relPath; + public static function absolutePath(relPath:String):String { + if (haxe.io.Path.isAbsolute(relPath)) + return relPath; return haxe.io.Path.join([Sys.getCwd(), relPath]); } - public static function isDirectory( path : String ) : Bool { + public static function isDirectory(path:String):Bool { return sys_is_dir(Sys.getPath(makeCompatiblePath(path))); } - public static function createDirectory( path : String ) : Void { + public static function createDirectory(path:String):Void { var path = haxe.io.Path.addTrailingSlash(path); var _p = null; var parts = []; @@ -74,42 +77,71 @@ class FileSystem { } for (part in parts) { if (part.charCodeAt(part.length - 1) != ":".code && !exists(part)) - if( !sys_create_dir(Sys.getPath(part), 493) ) + if (!sys_create_dir(Sys.getPath(part), 493)) throw new Sys.SysError("Failed to create directory " + part); } } - public static function deleteFile( path : String ) : Void { - if( !sys_delete(Sys.getPath(path)) ) throw new Sys.SysError("Can't delete file " + path); + public static function deleteFile(path:String):Void { + if (!sys_delete(Sys.getPath(path))) + throw new Sys.SysError("Can't delete file " + path); } - public static function deleteDirectory( path : String ) : Void { - if( !sys_remove_dir(Sys.getPath(path)) ) throw new Sys.SysError("Can't delete directory " + path); + public static function deleteDirectory(path:String):Void { + if (!sys_remove_dir(Sys.getPath(path))) + throw new Sys.SysError("Can't delete directory " + path); } - public static function readDirectory( path : String ) : Array { + public static function readDirectory(path:String):Array { var content = sys_read_dir(Sys.getPath(path)); - if( content == null ) + if (content == null) throw new Sys.SysError("Failed to read directory " + path); - return [for( c in content ) Sys.makePath(c)]; + return [for (c in content) Sys.makePath(c)]; } private static inline function makeCompatiblePath(path:String):String { return if (path.charCodeAt(1) == ":".code && path.length <= 3) { haxe.io.Path.addTrailingSlash(path); + } else if (path == "/") { + "/"; } else { haxe.io.Path.removeTrailingSlashes(path); } } - @:hlNative("std", "sys_read_dir") static function sys_read_dir( path : hl.Bytes ) : hl.NativeArray { return null; } - @:hlNative("std", "sys_create_dir") static function sys_create_dir( path : hl.Bytes, rights : Int ) : Bool { return false; } - @:hlNative("std", "sys_is_dir") static function sys_is_dir( path : hl.Bytes ) : Bool { return false; } - @:hlNative("std", "sys_stat") static function sys_stat( path : hl.Bytes ) : hl.NativeArray { return null; } - @:hlNative("std", "sys_rename") static function sys_rename( path : hl.Bytes, to : hl.Bytes ) : Bool { return true; } - @:hlNative("std", "sys_delete") static function sys_delete( path : hl.Bytes ) : Bool { return true; }; - @:hlNative("std", "sys_full_path") static function sys_full_path( path : hl.Bytes ) : hl.Bytes { return null; } - @:hlNative("std", "sys_remove_dir") static function sys_remove_dir( path : hl.Bytes ) : Bool { return true; } - @:hlNative("std", "sys_exists") static function sys_exists( path : hl.Bytes ) : Bool { return true; } + @:hlNative("std", "sys_read_dir") static function sys_read_dir(path:hl.Bytes):hl.NativeArray { + return null; + } + + @:hlNative("std", "sys_create_dir") static function sys_create_dir(path:hl.Bytes, rights:Int):Bool { + return false; + } + + @:hlNative("std", "sys_is_dir") static function sys_is_dir(path:hl.Bytes):Bool { + return false; + } + + @:hlNative("std", "sys_stat") static function sys_stat(path:hl.Bytes):hl.NativeArray { + return null; + } + @:hlNative("std", "sys_rename") static function sys_rename(path:hl.Bytes, to:hl.Bytes):Bool { + return true; + } + + @:hlNative("std", "sys_delete") static function sys_delete(path:hl.Bytes):Bool { + return true; + }; + + @:hlNative("std", "sys_full_path") static function sys_full_path(path:hl.Bytes):hl.Bytes { + return null; + } + + @:hlNative("std", "sys_remove_dir") static function sys_remove_dir(path:hl.Bytes):Bool { + return true; + } + + @:hlNative("std", "sys_exists") static function sys_exists(path:hl.Bytes):Bool { + return true; + } } diff --git a/std/hl/_std/sys/db/Connection.hx b/std/hl/_std/sys/db/Connection.hx new file mode 100644 index 00000000000..d7331f5d5a4 --- /dev/null +++ b/std/hl/_std/sys/db/Connection.hx @@ -0,0 +1,36 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.db; + +interface Connection { + function request(s:String):ResultSet; + function close():Void; + function escape(s:String):String; + function quote(s:String):String; + function addValue(s:StringBuf, v:Dynamic):Void; + function lastInsertId():Int; + function dbName():String; + function startTransaction():Void; + function commit():Void; + function rollback():Void; +} diff --git a/std/hl/_std/sys/db/Mysql.hx b/std/hl/_std/sys/db/Mysql.hx new file mode 100644 index 00000000000..b3d9fd4962d --- /dev/null +++ b/std/hl/_std/sys/db/Mysql.hx @@ -0,0 +1,250 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.db; + +private class MysqlParams { + public var host:hl.Bytes; + public var user:hl.Bytes; + public var pass:hl.Bytes; + public var socket:hl.Bytes; + public var port:Int; + + public function new() {} +} + +private typedef ConnectionHandler = hl.Abstract<"mysql_cnx">; +private typedef ResultHandler = hl.Abstract<"mysql_result">; + +@:hlNative("mysql") +private class MysqlResultSet implements sys.db.ResultSet { + public var length(get, null):Int; + public var nfields(get, null):Int; + + private var r:ResultHandler; + private var cache:Dynamic; + + function new(r) { + this.r = r; + } + + private function get_length() { + return result_get_length(r); + } + + private function get_nfields() { + return result_get_nfields(r); + } + + public function hasNext() { + if (cache == null) + cache = next(); + return (cache != null); + } + + public function next():Dynamic { + var c = cache; + if (c != null) { + cache = null; + return c; + } + c = result_next(r); + return c; + } + + public function results():List { + var l = new List(); + while (hasNext()) + l.add(next()); + return l; + } + + public function getResult(n:Int) { + var v = result_get(r, n); + if (v == null) + return null; + return @:privateAccess String.fromUTF8(v); + } + + public function getIntResult(n:Int):Int { + return result_get_int(r, n); + } + + public function getFloatResult(n:Int):Float { + return result_get_float(r, n); + } + + public function getFieldsNames():Array { + var a = result_get_fields_names(r); + return [for (v in a) @:privateAccess String.fromUTF8(v)]; + } + + static function result_get_length(r:ResultHandler):Int { + return 0; + } + + static function result_get_nfields(r:ResultHandler):Int { + return 0; + } + + static function result_next(r:ResultHandler):Dynamic { + return null; + } + + static function result_get(r:ResultHandler, n:Int):hl.Bytes { + return null; + } + + static function result_get_int(r:ResultHandler, n:Int):Int { + return 0; + } + + static function result_get_float(r:ResultHandler, n:Int):Float { + return 0.; + } + + static function result_get_fields_names(r:ResultHandler):hl.NativeArray { + return null; + } +} + +@:hlNative("mysql") +private class MysqlConnection implements Connection { + var h:ConnectionHandler; + + function new(h) { + this.h = h; + } + + public function close() { + if (h != null) + close_wrap(h); + h = null; + } + + public function request(s:String) @:privateAccess { + var len = 0; + var b = s.bytes.utf16ToUtf8(0, len); + return new MysqlResultSet(request_wrap(h, b, len)); + } + + public function escape(s:String) @:privateAccess { + var len = 0; + var utf = s.bytes.utf16ToUtf8(0, len); + return String.fromUTF8(escape_wrap(h, utf, len)); + } + + public function quote(s:String) { + return "'" + escape(s) + "'"; + } + + public function addValue(s:StringBuf, v:Dynamic) { + if (v == null) { + s.add(null); + return; + } + var t = hl.Type.getDynamic(v).kind; + if (t == HI32 || t == HF64) + s.add(v); + else if (t == HBool) + s.addChar(if (v) "1".code else "0".code); + else { + s.addChar("'".code); + s.add(escape(Std.string(v))); + s.addChar("'".code); + } + } + + public function lastInsertId() { + return request("SELECT LAST_INSERT_ID()").getIntResult(0); + } + + public function dbName() { + return "MySQL"; + } + + public function startTransaction() { + request("START TRANSACTION"); + } + + public function commit() { + request("COMMIT"); + } + + public function rollback() { + request("ROLLBACK"); + } + + static function close_wrap(h:ConnectionHandler) {} + + static function connect_wrap(p:MysqlParams):ConnectionHandler { + return null; + } + + static function select_db_wrap(h:ConnectionHandler, db:hl.Bytes):Bool { + return false; + } + + @:hlNative("mysql", "request") + static function request_wrap(h:ConnectionHandler, rq:hl.Bytes, rqLen:Int):ResultHandler { + return null; + } + + @:hlNative("mysql", "escape") + static function escape_wrap(h:ConnectionHandler, str:hl.Bytes, len:Int):hl.Bytes { + return null; + } + + static function setConvFuns(fstring:Dynamic, fbytes:Dynamic, fdate:Dynamic, fjson:Dynamic) {}; +} + +class Mysql { + static var INIT_DONE = false; + + public static function connect(params:{ + host:String, + ?port:Int, + user:String, + pass:String, + ?socket:String, + ?database:String + }):sys.db.Connection@:privateAccess { + if (!INIT_DONE) { + INIT_DONE = true; + MysqlConnection.setConvFuns(function(v:hl.Bytes) return @:privateAccess String.fromUTF8(v), + function(v:hl.Bytes, len:Int) return new haxe.io.Bytes(v, len), function(t) return Date.fromTime(1000. * t), + function(v:hl.Bytes) return haxe.Json.parse(@:privateAccess String.fromUTF8(v))); + } + var p = new MysqlParams(); + p.host = params.host == null ? null : params.host.toUtf8(); + p.user = params.user.toUtf8(); + p.pass = params.pass.toUtf8(); + p.socket = params.socket == null ? null : params.socket.toUtf8(); + p.port = params.port == null ? 3306 : params.port; + var cnx = new MysqlConnection(MysqlConnection.connect_wrap(p)); + if (params.database != null && !MysqlConnection.select_db_wrap(cnx.h, params.database.toUtf8())) { + cnx.close(); + throw "Failed to select database " + params.database; + } + return cnx; + } +} diff --git a/std/hl/_std/sys/db/ResultSet.hx b/std/hl/_std/sys/db/ResultSet.hx new file mode 100644 index 00000000000..49f689994e8 --- /dev/null +++ b/std/hl/_std/sys/db/ResultSet.hx @@ -0,0 +1,36 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.db; + +interface ResultSet { + var length(get, null):Int; + var nfields(get, null):Int; + + function hasNext():Bool; + function next():Dynamic; + function results():List; + function getResult(n:Int):String; + function getIntResult(n:Int):Int; + function getFloatResult(n:Int):Float; + function getFieldsNames():Null>; +} diff --git a/std/hl/_std/sys/db/Sqlite.hx b/std/hl/_std/sys/db/Sqlite.hx index d4bd0c706e8..63d50f0d120 100644 --- a/std/hl/_std/sys/db/Sqlite.hx +++ b/std/hl/_std/sys/db/Sqlite.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,194 +19,196 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.db; + import haxe.crypto.BaseCode; private typedef SqliteConnectionHandle = hl.Abstract<"sqlite_database">; private typedef SqliteResultHandle = hl.Abstract<"sqlite_result">; @:hlNative("sqlite") -private class SqliteLib -{ - public static function connect( path : hl.Bytes ) : SqliteConnectionHandle { return null; } - public static function close( c : SqliteConnectionHandle ) : Void { } - public static function request( c : SqliteConnectionHandle, sql : hl.Bytes ) : SqliteResultHandle { return null; } - public static function last_id( c : SqliteConnectionHandle ) : Int { return 0; } - - public static function result_next( c : SqliteResultHandle ) : hl.NativeArray { return null; } - - public static function result_get( c : SqliteResultHandle, n : Int ) : Null { return null; } - public static function result_get_int( c : SqliteResultHandle, n : Int ) : Null { return 0; } - public static function result_get_float( c : SqliteResultHandle, n : Int ) : Null { return .0; } - public static function result_get_length( c : SqliteResultHandle ) : Null { return 0; } - public static function result_get_nfields( c : SqliteResultHandle ) : Int { return 0; } - public static function result_get_fields( c : SqliteResultHandle ) : hl.NativeArray { return null; } -} +private class SqliteLib { + public static function connect(path:hl.Bytes):SqliteConnectionHandle { + return null; + } + + public static function close(c:SqliteConnectionHandle):Void {} + + public static function request(c:SqliteConnectionHandle, sql:hl.Bytes):SqliteResultHandle { + return null; + } + public static function last_id(c:SqliteConnectionHandle):Int { + return 0; + } + + public static function result_next(c:SqliteResultHandle):hl.NativeArray { + return null; + } + + public static function result_get(c:SqliteResultHandle, n:Int):Null { + return null; + } + + public static function result_get_int(c:SqliteResultHandle, n:Int):Null { + return 0; + } + + public static function result_get_float(c:SqliteResultHandle, n:Int):Null { + return .0; + } + + public static function result_get_length(c:SqliteResultHandle):Null { + return 0; + } + + public static function result_get_nfields(c:SqliteResultHandle):Int { + return 0; + } + + public static function result_get_fields(c:SqliteResultHandle):hl.NativeArray { + return null; + } +} @:access(Sys) @:access(String) -private class SqliteConnection implements Connection -{ - - var c : SqliteConnectionHandle; +private class SqliteConnection implements Connection { + var c:SqliteConnectionHandle; - public function new( file : String ) - { + public function new(file:String) { c = SqliteLib.connect(Sys.getPath(file)); } - - public function close( ) : Void - { + + public function close():Void { SqliteLib.close(c); } - - public function request( s : String ) : ResultSet - { - try - { - var r : SqliteResultHandle = SqliteLib.request(c, s.bytes); - + + public function request(s:String):ResultSet { + try { + var r:SqliteResultHandle = SqliteLib.request(c, s.bytes); + return new SqliteResultSet(r); - } - catch ( e : String ) - { + } catch (e:String) { throw 'Error while executing $s ($e)'; } - + return null; } - - public function escape( s : String ) : String - { + + public function escape(s:String):String { return s.split("'").join("''"); } - - public function quote( s : String ) : String - { - if( s.indexOf("\000") >= 0 ) + + public function quote(s:String):String { + if (s.indexOf("\000") >= 0) return "x'" + BaseCode.encode(s, "0123456789ABCDEF") + "'"; - + return "'" + s.split("'").join("''") + "'"; } - - public function addValue( s : StringBuf, v : Dynamic ) : Void - { - switch( Type.typeof(v) ) - { - case TNull, TInt: s.add(v); - case TBool: s.add( v ? 1 : 0); - case _: s.add(quote(Std.string(v))); + + public function addValue(s:StringBuf, v:Dynamic):Void { + switch (Type.typeof(v)) { + case TNull, TInt: + s.add(v); + case TBool: + s.add(v ? 1 : 0); + case _: + s.add(quote(Std.string(v))); } } - - public function lastInsertId( ) : Int - { + + public function lastInsertId():Int { return SqliteLib.last_id(c); } - - public function dbName( ) : String - { + + public function dbName():String { return "SQLite"; } - - public function startTransaction( ) : Void - { + + public function startTransaction():Void { request("BEGIN TRANSACTION"); } - - public function commit( ) : Void - { + + public function commit():Void { request("COMMIT"); startTransaction(); // match mysql usage } - - public function rollback( ) : Void - { + + public function rollback():Void { request("ROLLBACK"); startTransaction(); // match mysql usage } } +@:access(String) +private class SqliteResultSet implements ResultSet { + public var length(get, null):Int; + public var nfields(get, null):Int; + var names:Array; + var cache:List; -@:access(String) -private class SqliteResultSet implements ResultSet -{ - public var length(get,null) : Int; - public var nfields(get,null) : Int; - - var names : Array; - var cache : List; - - var r : SqliteResultHandle; - - public function new( r : SqliteResultHandle ) - { + var r:SqliteResultHandle; + + public function new(r:SqliteResultHandle) { cache = new List(); this.r = r; hasNext(); // execute the request } - - function get_length( ) : Int - { - if ( nfields != 0 ) - { - while ( true ) - { + + function get_length():Int { + if (nfields != 0) { + while (true) { var c = doNext(); - if( c == null ) + if (c == null) break; - + cache.add(c); } - + return cache.length; } - + return SqliteLib.result_get_length(r); } - - function get_nfields( ) : Int - { + + function get_nfields():Int { return SqliteLib.result_get_nfields(r); } - - public function hasNext( ) : Bool - { + + public function hasNext():Bool { var c = next(); - if( c == null ) + if (c == null) return false; - + cache.push(c); - + return true; } - - public function next( ) : Dynamic - { + + public function next():Dynamic { var c = cache.pop(); - if( c != null ) + if (c != null) return c; - + return doNext(); } - - private function doNext( ) : Dynamic - { - var o : Dynamic = {}; + + private function doNext():Dynamic { + var o:Dynamic = {}; var a = SqliteLib.result_next(r); - if( a == null ) + if (a == null) return null; - + var names = getFieldsNames(); - var i = 0 ; + var i = 0; var l = names.length; - while ( i < l ) - { - var n : String = names[i]; - var v : Dynamic = a[i]; - if ( hl.Type.getDynamic(v).kind == hl.Type.TypeKind.HBytes ) + while (i < l) { + var n:String = names[i]; + var v:Dynamic = a[i]; + if (hl.Type.getDynamic(v).kind == hl.Type.TypeKind.HBytes) Reflect.setField(o, n, String.fromUCS2(v)); else Reflect.setField(o, n, v); @@ -214,65 +216,56 @@ private class SqliteResultSet implements ResultSet } return o; } - - public function results( ) : List - { + + public function results():List { var l = new List(); - while ( true ) - { + while (true) { var c = next(); - if( c == null ) + if (c == null) break; - + l.add(c); } - + return l; } - - public function getResult( n : Int ) : String - { + + public function getResult(n:Int):String { var bytes = SqliteLib.result_get(r, n); - if ( bytes == null ) + if (bytes == null) return null; - + return String.fromUCS2(bytes); } - - public function getIntResult( n : Int ) : Int - { - return SqliteLib.result_get_int(r,n); + + public function getIntResult(n:Int):Int { + return SqliteLib.result_get_int(r, n); } - - public function getFloatResult( n : Int ) : Float - { - return SqliteLib.result_get_float(r,n); + + public function getFloatResult(n:Int):Float { + return SqliteLib.result_get_float(r, n); } - - public function getFieldsNames( ) : Array - { - if ( this.names != null ) + + public function getFieldsNames():Array { + if (this.names != null) return this.names; - + this.names = []; var names = SqliteLib.result_get_fields(r); var i = 0; var l = names.length; - while ( i < l ) - { + while (i < l) { var name = String.fromUCS2(names[i]); this.names.push(name); i++; } - + return this.names; } } -@:coreApi class Sqlite -{ - public static function open( file : String ) : Connection - { +@:coreApi class Sqlite { + public static function open(file:String):Connection { return new SqliteConnection(file); } -} \ No newline at end of file +} diff --git a/std/hl/_std/sys/io/File.hx b/std/hl/_std/sys/io/File.hx index 74168e03253..1a5c7a167bf 100644 --- a/std/hl/_std/sys/io/File.hx +++ b/std/hl/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,69 +19,88 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; #if doc_gen -enum FileHandle { } +enum FileHandle {} #else typedef FileHandle = hl.Abstract<"hl_fdesc">; #end @:access(Sys) @:coreApi class File { - - public static function getContent( path : String ) : String { + public static function getContent(path:String):String { var bytes = file_contents(Sys.getPath(path), null); - if( bytes == null ) throw new Sys.SysError("Can't read "+path); + if (bytes == null) + throw new Sys.SysError("Can't read " + path); return @:privateAccess String.fromUTF8(bytes); } - public static function getBytes( path : String ) : haxe.io.Bytes { + public static function getBytes(path:String):haxe.io.Bytes { var size = 0; var bytes = file_contents(Sys.getPath(path), size); - if( bytes == null ) throw new Sys.SysError("Can't read "+path); + if (bytes == null) + throw new Sys.SysError("Can't read " + path); return @:privateAccess new haxe.io.Bytes(bytes, size); } - public static function saveContent( path : String, content : String ) : Void { + public static function saveContent(path:String, content:String):Void { var f = write(path); f.writeString(content); f.close(); } - public static function saveBytes( path : String, bytes : haxe.io.Bytes ) : Void { + public static function saveBytes(path:String, bytes:haxe.io.Bytes):Void { var f = write(path); f.write(bytes); f.close(); } - public static function read( path : String, binary : Bool = true ) : FileInput { - var f = file_open(Sys.getPath(path),0,binary); - if( f == null ) throw new Sys.SysError("Can't open "+path); + public static function read(path:String, binary:Bool = true):FileInput { + var f = file_open(Sys.getPath(path), 0, binary); + if (f == null) + throw new Sys.SysError("Can't open " + path); return @:privateAccess new FileInput(f); } - public static function write( path : String, binary : Bool = true ) : FileOutput { - var f = file_open(Sys.getPath(path),1,binary); - if( f == null ) throw new Sys.SysError("Can't open "+path+" for writing"); + public static function write(path:String, binary:Bool = true):FileOutput { + var f = file_open(Sys.getPath(path), 1, binary); + if (f == null) + throw new Sys.SysError("Can't open " + path + " for writing"); return @:privateAccess new FileOutput(f); } - public static function append( path : String, binary : Bool = true ) : FileOutput { - var f = file_open(Sys.getPath(path),2,binary); - if( f == null ) throw new Sys.SysError("Can't open "+path+" for append"); + public static function append(path:String, binary:Bool = true):FileOutput { + var f = file_open(Sys.getPath(path), 2, binary); + if (f == null) + throw new Sys.SysError("Can't open " + path + " for append"); return @:privateAccess new FileOutput(f); } - public static function copy( srcPath : String, dstPath : String ) : Void { - var s = read(srcPath,true); - var d = write(dstPath,true); + public static function update(path:String, binary:Bool = true):FileOutput { + if (!FileSystem.exists(path)) { + write(path).close(); + } + var f = file_open(Sys.getPath(path), 3, binary); + if (f == null) + throw new Sys.SysError("Can't open " + path + " for update"); + return @:privateAccess new FileOutput(f); + } + + public static function copy(srcPath:String, dstPath:String):Void { + var s = read(srcPath, true); + var d = write(dstPath, true); d.writeInput(s); s.close(); d.close(); } - @:hlNative("std", "file_open") static function file_open( path : hl.Bytes, mode : Int, binary : Bool ) : FileHandle { return null; } - @:hlNative("std", "file_contents") static function file_contents( path : hl.Bytes, size : hl.Ref ) : hl.Bytes { return null; } + @:hlNative("std", "file_open") static function file_open(path:hl.Bytes, mode:Int, binary:Bool):FileHandle { + return null; + } + @:hlNative("std", "file_contents") static function file_contents(path:hl.Bytes, size:hl.Ref):hl.Bytes { + return null; + } } diff --git a/std/hl/_std/sys/io/FileInput.hx b/std/hl/_std/sys/io/FileInput.hx index f9db2a21135..a766697be0b 100644 --- a/std/hl/_std/sys/io/FileInput.hx +++ b/std/hl/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,56 +19,79 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; + import sys.io.File; @:coreApi class FileInput extends haxe.io.Input { + private var __f:FileHandle; - private var __f : FileHandle; - - function new(f:FileHandle) : Void { + function new(f:FileHandle):Void { __f = f; } - public override function readByte() : Int { + public override function readByte():Int { var c = file_read_char(__f); - if( c < 0 ) throw new haxe.io.Eof(); + if (c < 0) + throw new haxe.io.Eof(); return c; } - public override function readBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int { - if( p < 0 || l < 0 || p + l > s.length ) throw haxe.io.Error.OutsideBounds; + public override function readBytes(s:haxe.io.Bytes, p:Int, l:Int):Int { + if (p < 0 || l < 0 || p + l > s.length) + throw haxe.io.Error.OutsideBounds; var v = file_read(__f, s.getData(), p, l); - if( v <= 0 ) throw new haxe.io.Eof(); + if (v <= 0) + throw new haxe.io.Eof(); return v; } - public override function close() : Void { + public override function close():Void { super.close(); file_close(__f); __f = null; } - public function seek( p : Int, pos : FileSeek ) : Void { - if( !file_seek(__f,p,switch( pos ) { case SeekBegin: 0; case SeekCur: 1; case SeekEnd: 2; }) ) + public function seek(p:Int, pos:FileSeek):Void { + if (!file_seek(__f, p, switch (pos) { + case SeekBegin: 0; + case SeekCur: 1; + case SeekEnd: 2; + })) throw haxe.io.Error.Custom("seek() failure"); } - public function tell() : Int { + public function tell():Int { var p = file_tell(__f); - if( p < 0 ) throw haxe.io.Error.Custom("tell() failure"); + if (p < 0) + throw haxe.io.Error.Custom("tell() failure"); return p; } - public function eof() : Bool { + public function eof():Bool { return file_eof(__f); } - @:hlNative("std", "file_eof") static function file_eof( f : FileHandle ) : Bool { return false; } - @:hlNative("std", "file_read") static function file_read( f : FileHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } - @:hlNative("std", "file_read_char") static function file_read_char( f : FileHandle ) : Int { return 0; } - @:hlNative("std", "file_close") static function file_close( f : FileHandle ) : Void { } - @:hlNative("std", "file_seek") static function file_seek( f : FileHandle, pos : Int, from : Int ) : Bool { return true; } - @:hlNative("std", "file_tell") static function file_tell( f : FileHandle ) : Int { return 0; } + @:hlNative("std", "file_eof") static function file_eof(f:FileHandle):Bool { + return false; + } + + @:hlNative("std", "file_read") static function file_read(f:FileHandle, bytes:hl.Bytes, pos:Int, len:Int):Int { + return 0; + } + + @:hlNative("std", "file_read_char") static function file_read_char(f:FileHandle):Int { + return 0; + } + + @:hlNative("std", "file_close") static function file_close(f:FileHandle):Void {} + @:hlNative("std", "file_seek") static function file_seek(f:FileHandle, pos:Int, from:Int):Bool { + return true; + } + + @:hlNative("std", "file_tell") static function file_tell(f:FileHandle):Int { + return 0; + } } diff --git a/std/hl/_std/sys/io/FileOutput.hx b/std/hl/_std/sys/io/FileOutput.hx index 87f9085f72d..34a8ff5c428 100644 --- a/std/hl/_std/sys/io/FileOutput.hx +++ b/std/hl/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,51 +19,68 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; + import sys.io.File; @:coreApi class FileOutput extends haxe.io.Output { + private var __f:FileHandle; - private var __f : FileHandle; - - function new(f:FileHandle) : Void { + function new(f:FileHandle):Void { __f = f; } - public override function writeByte( c : Int ) : Void { - if( !file_write_char(__f, c) ) throw new haxe.io.Eof(); + public override function writeByte(c:Int):Void { + if (!file_write_char(__f, c)) + throw new haxe.io.Eof(); } - public override function writeBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int { - if( p < 0 || l < 0 || p + l > s.length ) throw haxe.io.Error.OutsideBounds; + public override function writeBytes(s:haxe.io.Bytes, p:Int, l:Int):Int { + if (p < 0 || l < 0 || p + l > s.length) + throw haxe.io.Error.OutsideBounds; var v = file_write(__f, s.getData(), p, l); - if( v <= 0 ) throw new haxe.io.Eof(); + if (v <= 0) + throw new haxe.io.Eof(); return v; } - public override function flush() : Void { - if( !file_flush(__f) ) throw haxe.io.Error.Custom("flush() failure"); + public override function flush():Void { + if (!file_flush(__f)) + throw haxe.io.Error.Custom("flush() failure"); } - public override function close() : Void { + public override function close():Void { super.close(); @:privateAccess FileInput.file_close(__f); __f = null; } - public function seek( p : Int, pos : FileSeek ) : Void { - if( @:privateAccess !FileInput.file_seek(__f,p,switch( pos ) { case SeekBegin: 0; case SeekCur: 1; case SeekEnd: 2; }) ) + public function seek(p:Int, pos:FileSeek):Void { + if (@:privateAccess !FileInput.file_seek(__f, p, switch (pos) { + case SeekBegin: 0; + case SeekCur: 1; + case SeekEnd: 2; + })) throw haxe.io.Error.Custom("seek() failure"); } - public function tell() : Int { + public function tell():Int { var p = @:privateAccess FileInput.file_tell(__f); - if( p < 0 ) throw haxe.io.Error.Custom("tell() failure"); + if (p < 0) + throw haxe.io.Error.Custom("tell() failure"); return p; } - @:hlNative("std","file_flush") static function file_flush( f : FileHandle ) : Bool { return true; } - @:hlNative("std", "file_write") static function file_write( f : FileHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } - @:hlNative("std", "file_write_char") static function file_write_char( f : FileHandle, v : Int ) : Bool { return true; } + @:hlNative("std", "file_flush") static function file_flush(f:FileHandle):Bool { + return true; + } + @:hlNative("std", "file_write") static function file_write(f:FileHandle, bytes:hl.Bytes, pos:Int, len:Int):Int { + return 0; + } + + @:hlNative("std", "file_write_char") static function file_write_char(f:FileHandle, v:Int):Bool { + return true; + } } diff --git a/std/hl/_std/sys/io/Process.hx b/std/hl/_std/sys/io/Process.hx index fa455b877b4..0cbbc4dcef6 100644 --- a/std/hl/_std/sys/io/Process.hx +++ b/std/hl/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; private typedef ProcessHandle = hl.Abstract<"hl_process">; private class Stdin extends haxe.io.Output { - - var p : Dynamic; - var buf : haxe.io.Bytes; + var p:Dynamic; + var buf:haxe.io.Bytes; public function new(p) { this.p = p; @@ -39,67 +39,77 @@ private class Stdin extends haxe.io.Output { } public override function writeByte(c) { - buf.set(0,c); - writeBytes(buf,0,1); + buf.set(0, c); + writeBytes(buf, 0, 1); } - public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { + public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { var v = _stdin_write(p, buf.getData().bytes, pos, len); - if( v < 0 ) throw new haxe.io.Eof(); + if (v < 0) + throw new haxe.io.Eof(); return v; } - @:hlNative("std","process_stdin_write") static function _stdin_write( p : ProcessHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } - @:hlNative("std", "process_stdin_close") static function _stdin_close( p : ProcessHandle ) : Bool { return false; } + @:hlNative("std", "process_stdin_write") static function _stdin_write(p:ProcessHandle, bytes:hl.Bytes, pos:Int, len:Int):Int { + return 0; + } + @:hlNative("std", "process_stdin_close") static function _stdin_close(p:ProcessHandle):Bool { + return false; + } } private class Stdout extends haxe.io.Input { + var p:ProcessHandle; + var out:Bool; + var buf:haxe.io.Bytes; - var p : ProcessHandle; - var out : Bool; - var buf : haxe.io.Bytes; - - public function new(p,out) { + public function new(p, out) { this.p = p; this.out = out; buf = haxe.io.Bytes.alloc(1); } public override function readByte() { - if( readBytes(buf,0,1) == 0 ) + if (readBytes(buf, 0, 1) == 0) throw haxe.io.Error.Blocked; return buf.get(0); } - public override function readBytes( str : haxe.io.Bytes, pos : Int, len : Int ) : Int { - var v = out ? _stdout_read(p,str.getData().bytes,pos,len) : _stderr_read(p,str.getData().bytes,pos,len); - if( v < 0 ) throw new haxe.io.Eof(); + public override function readBytes(str:haxe.io.Bytes, pos:Int, len:Int):Int { + var v = out ? _stdout_read(p, str.getData().bytes, pos, len) : _stderr_read(p, str.getData().bytes, pos, len); + if (v < 0) + throw new haxe.io.Eof(); return v; } - @:hlNative("std","process_stdout_read") static function _stdout_read( p : ProcessHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } - @:hlNative("std","process_stderr_read") static function _stderr_read( p : ProcessHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } + @:hlNative("std", "process_stdout_read") static function _stdout_read(p:ProcessHandle, bytes:hl.Bytes, pos:Int, len:Int):Int { + return 0; + } + @:hlNative("std", "process_stderr_read") static function _stderr_read(p:ProcessHandle, bytes:hl.Bytes, pos:Int, len:Int):Int { + return 0; + } } @:access(Sys) @:coreApi class Process { + var p:ProcessHandle; - var p : ProcessHandle; - public var stdout(default,null) : haxe.io.Input; - public var stderr(default,null) : haxe.io.Input; - public var stdin(default, null) : haxe.io.Output; + public var stdout(default, null):haxe.io.Input; + public var stderr(default, null):haxe.io.Input; + public var stdin(default, null):haxe.io.Output; static var isWin = Sys.systemName() == "Windows"; - public function new( cmd : String, ?args : Array, ?detached : Bool ) : Void { + public function new(cmd:String, ?args:Array, ?detached:Bool):Void { var runCmd = cmd; - if( isWin ) { + if (isWin) { var b = new StringBuf(); - if( args == null ) { + if (args == null) { var exe = Sys.getEnv("COMSPEC"); - if( exe == null ) exe = "cmd.exe"; + if (exe == null) + exe = "cmd.exe"; b.add("\""); b.add(exe); b.add("\" /C \""); @@ -109,27 +119,27 @@ private class Stdout extends haxe.io.Input { b.addChar('"'.code); b.add(cmd); b.addChar('"'.code); - for( a in args ) { + for (a in args) { b.add(" \""); var bsCount = 0; - for( i in 0...a.length ) { - switch( StringTools.fastCodeAt(a, i) ) { - case '"'.code: - for( i in 0...bsCount * 2 ) - b.addChar('\\'.code); - bsCount = 0; - b.add("\\\""); - case '\\'.code: - bsCount++; - case c: - for( i in 0...bsCount ) - b.addChar('\\'.code); - bsCount = 0; - b.addChar(c); + for (i in 0...a.length) { + switch (StringTools.fastCodeAt(a, i)) { + case '"'.code: + for (i in 0...bsCount * 2) + b.addChar('\\'.code); + bsCount = 0; + b.add("\\\""); + case '\\'.code: + bsCount++; + case c: + for (i in 0...bsCount) + b.addChar('\\'.code); + bsCount = 0; + b.addChar(c); } } // Add remaining backslashes, if any. - for( i in 0...bsCount * 2 ) + for (i in 0...bsCount * 2) b.addChar('\\'.code); b.addChar('"'.code); } @@ -139,44 +149,53 @@ private class Stdout extends haxe.io.Input { } @:privateAccess { var aargs = null; - if( args != null ) { + if (args != null) { aargs = new hl.NativeArray(args.length); - for( i in 0...args.length ) + for (i in 0...args.length) aargs[i] = Sys.getPath(args[i]); } p = _run(Sys.getPath(runCmd), aargs, detached); } - if( p == null ) - throw new Sys.SysError("Process creation failure : "+cmd); + if (p == null) + throw new Sys.SysError("Process creation failure : " + cmd); stdin = new Stdin(p); - stdout = new Stdout(p,true); - stderr = new Stdout(p,false); + stdout = new Stdout(p, true); + stderr = new Stdout(p, false); } - public function getPid() : Int { + public function getPid():Int { return _pid(p); } - public function exitCode( block : Bool = true ) : Null { + public function exitCode(block:Bool = true):Null { var running = false; var code = _exit(p, block == false ? new hl.Ref(running) : null); - if( block == false ) + if (block == false) return running ? null : code; return code; } - public function close() : Void { + public function close():Void { _close(p); } - public function kill() : Void { + public function kill():Void { _kill(p); } - @:hlNative("std","process_run") static function _run( cmd : hl.Bytes, args : hl.NativeArray, detached : Bool ) : ProcessHandle { return null; } - @:hlNative("std", "process_exit") static function _exit( p : ProcessHandle, running : hl.Ref ) : Int { return 0; } - @:hlNative("std", "process_pid") static function _pid( p : ProcessHandle ) : Int { return 0; } - @:hlNative("std","process_close") static function _close( p : ProcessHandle ) : Void { } - @:hlNative("std","process_kill") static function _kill( p : ProcessHandle ) : Void { } + @:hlNative("std", "process_run") static function _run(cmd:hl.Bytes, args:hl.NativeArray, detached:Bool):ProcessHandle { + return null; + } + + @:hlNative("std", "process_exit") static function _exit(p:ProcessHandle, running:hl.Ref):Int { + return 0; + } -} \ No newline at end of file + @:hlNative("std", "process_pid") static function _pid(p:ProcessHandle):Int { + return 0; + } + + @:hlNative("std", "process_close") static function _close(p:ProcessHandle):Void {} + + @:hlNative("std", "process_kill") static function _kill(p:ProcessHandle):Void {} +} diff --git a/std/hl/_std/sys/net/Host.hx b/std/hl/_std/sys/net/Host.hx index 6f953f5cc9c..ed737c045de 100644 --- a/std/hl/_std/sys/net/Host.hx +++ b/std/hl/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,36 +19,47 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.net; @:coreApi class Host { + public var host(default, null):String; - public var host(default,null) : String; - - public var ip(default,null) : Int; + public var ip(default, null):Int; - public function new( name : String ) : Void { + public function new(name:String):Void { host = name; - ip = host_resolve(@:privateAccess name.bytes.utf16ToUtf8(0,null)); - if( ip == -1 ) throw new Sys.SysError("Unresolved host " + name); + ip = host_resolve(@:privateAccess name.bytes.utf16ToUtf8(0, null)); + if (ip == -1) + throw new Sys.SysError("Unresolved host " + name); } - public function toString() : String { + public function toString():String { return @:privateAccess String.fromUTF8(host_to_string(ip)); } - public function reverse() : String { + public function reverse():String { return @:privateAccess String.fromUTF8(host_reverse(ip)); } - public static function localhost() : String { + public static function localhost():String { return @:privateAccess String.fromUTF8(host_local()); } - @:hlNative("std","host_resolve") static function host_resolve( name : hl.Bytes ) : Int { return 0; } - @:hlNative("std","host_reverse") static function host_reverse( host : Int ) : hl.Bytes { return null; } - @:hlNative("std","host_to_string") static function host_to_string( host : Int ) : hl.Bytes { return null; } - @:hlNative("std","host_local") static function host_local() : hl.Bytes { return null; } + @:hlNative("std", "host_resolve") static function host_resolve(name:hl.Bytes):Int { + return 0; + } + + @:hlNative("std", "host_reverse") static function host_reverse(host:Int):hl.Bytes { + return null; + } + + @:hlNative("std", "host_to_string") static function host_to_string(host:Int):hl.Bytes { + return null; + } + @:hlNative("std", "host_local") static function host_local():hl.Bytes { + return null; + } } diff --git a/std/hl/_std/sys/net/Socket.hx b/std/hl/_std/sys/net/Socket.hx index 41579ed094a..0cd7113089c 100644 --- a/std/hl/_std/sys/net/Socket.hx +++ b/std/hl/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,36 +19,40 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.net; + import haxe.io.Error; #if doc_gen -@:noDoc enum SocketHandle { } +@:noDoc enum SocketHandle {} #else @:noDoc typedef SocketHandle = hl.Abstract<"hl_socket">; #end private class SocketOutput extends haxe.io.Output { - - var sock : Socket; + var sock:Socket; public function new(s) { this.sock = s; } - public override function writeByte( c : Int ) { + public override function writeByte(c:Int) { var k = socket_send_char(@:privateAccess sock.__s, c); - if( k < 0 ) { - if( k == -1 ) throw Blocked; + if (k < 0) { + if (k == -1) + throw Blocked; throw new haxe.io.Eof(); } } - public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { - if( pos < 0 || len < 0 || pos + len > buf.length ) throw haxe.io.Error.OutsideBounds; + public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { + if (pos < 0 || len < 0 || pos + len > buf.length) + throw haxe.io.Error.OutsideBounds; var n = socket_send(@:privateAccess sock.__s, buf.getData().bytes, pos, len); - if( n < 0 ) { - if( n == -1 ) throw Blocked; + if (n < 0) { + if (n == -1) + throw Blocked; throw new haxe.io.Eof(); } return n; @@ -58,34 +62,39 @@ private class SocketOutput extends haxe.io.Output { sock.close(); } + @:hlNative("std", "socket_send_char") static function socket_send_char(s:SocketHandle, c:Int):Int { + return 0; + } - @:hlNative("std","socket_send_char") static function socket_send_char( s : SocketHandle, c : Int ) : Int { return 0; } - @:hlNative("std","socket_send") static function socket_send( s : SocketHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } - + @:hlNative("std", "socket_send") static function socket_send(s:SocketHandle, bytes:hl.Bytes, pos:Int, len:Int):Int { + return 0; + } } private class SocketInput extends haxe.io.Input { - - var sock : Socket; + var sock:Socket; public function new(s) { sock = s; } - public override function readByte() : Int { + public override function readByte():Int { var c = socket_recv_char(@:privateAccess sock.__s); - if( c < 0 ) { - if( c == -1 ) throw Blocked; + if (c < 0) { + if (c == -1) + throw Blocked; throw new haxe.io.Eof(); } return c; } - public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { - if( pos < 0 || len < 0 || pos + len > buf.length ) throw haxe.io.Error.OutsideBounds; - var r = socket_recv(@:privateAccess sock.__s,buf.getData().bytes,pos,len); - if( r < 0 ) { - if( r == -1 ) throw Blocked; + public override function readBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { + if (pos < 0 || len < 0 || pos + len > buf.length) + throw haxe.io.Error.OutsideBounds; + var r = socket_recv(@:privateAccess sock.__s, buf.getData().bytes, pos, len); + if (r <= 0) { + if (r == -1) + throw Blocked; throw new haxe.io.Eof(); } return r; @@ -95,176 +104,231 @@ private class SocketInput extends haxe.io.Input { sock.close(); } - @:hlNative("std","socket_recv") static function socket_recv( s : SocketHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } - @:hlNative("std","socket_recv_char") static function socket_recv_char( s : SocketHandle ) : Int { return 0; } + @:hlNative("std", "socket_recv") static function socket_recv(s:SocketHandle, bytes:hl.Bytes, pos:Int, len:Int):Int { + return 0; + } + @:hlNative("std", "socket_recv_char") static function socket_recv_char(s:SocketHandle):Int { + return 0; + } } @:coreApi @:keepInit class Socket { + private var __s:SocketHandle; - private var __s : SocketHandle; - public var input(default,null) : haxe.io.Input; - public var output(default,null) : haxe.io.Output; - public var custom : Dynamic; + public var input(default, null):haxe.io.Input; + public var output(default, null):haxe.io.Output; + public var custom:Dynamic; - static function __init__() : Void { + static function __init__():Void { socket_init(); } - public function new() : Void { + public function new():Void { init(); } - function init() : Void { - __s = socket_new(false); + function init():Void { + if (__s == null) + __s = socket_new(false); input = new SocketInput(this); output = new SocketOutput(this); } - public function close() : Void { - if( __s != null ) { + public function close():Void { + if (__s != null) { socket_close(__s); __s = null; } } - public function read() : String { + public function read():String { return input.readAll().toString(); } - public function write( content : String ) : Void { + public function write(content:String):Void { output.writeString(content); } - public function connect(host : Host, port : Int) : Void { - if( !socket_connect(__s, host.ip, port) ) - throw new Sys.SysError("Failed to connect on "+host.toString()+":"+port); + public function connect(host:Host, port:Int):Void { + if (!socket_connect(__s, host.ip, port)) + throw new Sys.SysError("Failed to connect on " + host.toString() + ":" + port); } - public function listen( connections : Int ) : Void { - if( !socket_listen(__s, connections) ) + public function listen(connections:Int):Void { + if (!socket_listen(__s, connections)) throw new Sys.SysError("listen() failure"); } - public function shutdown( read : Bool, write : Bool ) : Void { - if( !socket_shutdown(__s, read, write) ) + public function shutdown(read:Bool, write:Bool):Void { + if (!socket_shutdown(__s, read, write)) throw new Sys.SysError("shutdown() failure"); } - public function bind(host : Host, port : Int) : Void { - if( !socket_bind(__s, host.ip, port) ) + public function bind(host:Host, port:Int):Void { + if (!socket_bind(__s, host.ip, port)) throw new Sys.SysError("Cannot bind socket on " + host + ":" + port); } - public function accept() : Socket { + public function accept():Socket { var c = socket_accept(__s); - if( c == null ) + if (c == null) return null; - var s : Socket = untyped $new(Socket); + var s:Socket = untyped $new(Socket); s.__s = c; s.input = new SocketInput(s); s.output = new SocketOutput(s); return s; } - public function peer() : { host : Host, port : Int } { + public function peer():{host:Host, port:Int} { var ip = 0, port = 0; - if( !socket_peer(__s, ip, port) ) + if (!socket_peer(__s, ip, port)) return null; - var h : Host = untyped $new(Host); + var h:Host = untyped $new(Host); @:privateAccess h.ip = ip; - return { host : h, port : port }; + return {host: h, port: port}; } - public function host() : { host : Host, port : Int } { + public function host():{host:Host, port:Int} { var ip = 0, port = 0; - if( !socket_host(__s, ip, port) ) + if (!socket_host(__s, ip, port)) return null; - var h : Host = untyped $new(Host); + var h:Host = untyped $new(Host); @:privateAccess h.ip = ip; - return { host : h, port : port }; + return {host: h, port: port}; } - public function setTimeout( timeout : Float ) : Void { - if( !socket_set_timeout(__s, timeout) ) throw new Sys.SysError("setTimeout() failure"); + public function setTimeout(timeout:Float):Void { + if (!socket_set_timeout(__s, timeout)) + throw new Sys.SysError("setTimeout() failure"); } - public function waitForRead() : Void { - select([this],null,null,null); + public function waitForRead():Void { + select([this], null, null, null); } - public function setBlocking( b : Bool ) : Void { - if( !socket_set_blocking(__s, b) ) throw new Sys.SysError("setBlocking() failure"); + public function setBlocking(b:Bool):Void { + if (!socket_set_blocking(__s, b)) + throw new Sys.SysError("setBlocking() failure"); } - public function setFastSend( b : Bool ) : Void { - if( !socket_set_fast_send(__s,b) ) throw new Sys.SysError("setFastSend() failure"); + public function setFastSend(b:Bool):Void { + if (!socket_set_fast_send(__s, b)) + throw new Sys.SysError("setFastSend() failure"); } // TODO : use TLS when multithread added - static var tmp : hl.Bytes = null; + static var tmp:hl.Bytes = null; static var curTmpSize = 0; - static function makeArray( a : Array ) : hl.NativeArray { - if( a == null ) return null; + static function makeArray(a:Array):hl.NativeArray { + if (a == null) + return null; var arr = new hl.NativeArray(a.length); - for( i in 0...a.length ) + for (i in 0...a.length) arr[i] = a[i].__s; return arr; } - static function outArray( a : hl.NativeArray, original : Array ) : Array { + static function outArray(a:hl.NativeArray, original:Array):Array { var out = []; - if( a == null ) return out; + if (a == null) + return out; var i = 0, p = 0; var max = original.length; - while( i < max ) { + while (i < max) { var sh = a[i++]; - if( sh == null ) break; - while( original[p].__s != sh ) p++; + if (sh == null) + break; + while (original[p].__s != sh) + p++; out.push(original[p++]); } return out; } - public static function select(read : Array, write : Array, others : Array, ?timeout : Float) : {read: Array, write: Array, others: Array} { + public static function select(read:Array, write:Array, others:Array, + ?timeout:Float):{read:Array, write:Array, others:Array} { var sread = makeArray(read); var swrite = makeArray(write); var sothers = makeArray(others); var tmpSize = 0; - if( sread != null ) tmpSize += socket_fd_size(sread.length); - if( swrite != null ) tmpSize += socket_fd_size(swrite.length); - if( sothers != null ) tmpSize += socket_fd_size(sothers.length); - if( tmpSize > curTmpSize ) { + if (sread != null) + tmpSize += socket_fd_size(sread.length); + if (swrite != null) + tmpSize += socket_fd_size(swrite.length); + if (sothers != null) + tmpSize += socket_fd_size(sothers.length); + if (tmpSize > curTmpSize) { tmp = new hl.Bytes(tmpSize); curTmpSize = tmpSize; } - if( !socket_select(sread, swrite, sothers, tmp, curTmpSize, timeout == null ? -1 : timeout) ) + if (!socket_select(sread, swrite, sothers, tmp, curTmpSize, timeout == null ? -1 : timeout)) throw "Error while waiting on socket"; return { - read : outArray(sread,read), - write : outArray(swrite,write), - others : outArray(sothers,others), + read: outArray(sread, read), + write: outArray(swrite, write), + others: outArray(sothers, others), }; } - @:hlNative("std", "socket_init") static function socket_init() : Void {} - @:hlNative("std", "socket_new") static function socket_new( udp : Bool ) : SocketHandle { return null; } - @:hlNative("std", "socket_close") static function socket_close( s : SocketHandle ) : Void { } - @:hlNative("std", "socket_connect") static function socket_connect( s : SocketHandle, host : Int, port : Int ) : Bool { return true; } - @:hlNative("std", "socket_listen") static function socket_listen( s : SocketHandle, count : Int ) : Bool { return true; } - @:hlNative("std", "socket_bind") static function socket_bind( s : SocketHandle, host : Int, port : Int ) : Bool { return true; } - @:hlNative("std", "socket_accept") static function socket_accept( s : SocketHandle ) : SocketHandle { return null; } - @:hlNative("std", "socket_peer") static function socket_peer( s : SocketHandle, host : hl.Ref, port : hl.Ref ) : Bool { return true; } - @:hlNative("std", "socket_host") static function socket_host( s : SocketHandle, host : hl.Ref, port : hl.Ref ) : Bool { return true; } - @:hlNative("std", "socket_set_timeout") static function socket_set_timeout( s : SocketHandle, timeout : Float ) : Bool { return true; } - @:hlNative("std", "socket_shutdown") static function socket_shutdown( s : SocketHandle, read : Bool, write : Bool ) : Bool { return true; } - @:hlNative("std", "socket_set_blocking") static function socket_set_blocking( s : SocketHandle, b : Bool ) : Bool { return true; } - @:hlNative("std", "socket_set_fast_send") static function socket_set_fast_send( s : SocketHandle, b : Bool ) : Bool { return true; } + @:hlNative("std", "socket_init") static function socket_init():Void {} + + @:hlNative("std", "socket_new") static function socket_new(udp:Bool):SocketHandle { + return null; + } - @:hlNative("std", "socket_fd_size") static function socket_fd_size( count : Int) : Int { return 0; } - @:hlNative("std", "socket_select") static function socket_select( read : hl.NativeArray, write : hl.NativeArray, other : hl.NativeArray, tmpData : hl.Bytes, tmpSize : Int, timeout : Float ) : Bool { return false; } + @:hlNative("std", "socket_close") static function socket_close(s:SocketHandle):Void {} + + @:hlNative("std", "socket_connect") static function socket_connect(s:SocketHandle, host:Int, port:Int):Bool { + return true; + } + + @:hlNative("std", "socket_listen") static function socket_listen(s:SocketHandle, count:Int):Bool { + return true; + } + + @:hlNative("std", "socket_bind") static function socket_bind(s:SocketHandle, host:Int, port:Int):Bool { + return true; + } + @:hlNative("std", "socket_accept") static function socket_accept(s:SocketHandle):SocketHandle { + return null; + } + + @:hlNative("std", "socket_peer") static function socket_peer(s:SocketHandle, host:hl.Ref, port:hl.Ref):Bool { + return true; + } + + @:hlNative("std", "socket_host") static function socket_host(s:SocketHandle, host:hl.Ref, port:hl.Ref):Bool { + return true; + } + + @:hlNative("std", "socket_set_timeout") static function socket_set_timeout(s:SocketHandle, timeout:Float):Bool { + return true; + } + + @:hlNative("std", "socket_shutdown") static function socket_shutdown(s:SocketHandle, read:Bool, write:Bool):Bool { + return true; + } + + @:hlNative("std", "socket_set_blocking") static function socket_set_blocking(s:SocketHandle, b:Bool):Bool { + return true; + } + + @:hlNative("std", "socket_set_fast_send") static function socket_set_fast_send(s:SocketHandle, b:Bool):Bool { + return true; + } + + @:hlNative("std", "socket_fd_size") static function socket_fd_size(count:Int):Int { + return 0; + } + + @:hlNative("std", "socket_select") static function socket_select(read:hl.NativeArray, write:hl.NativeArray, + other:hl.NativeArray, tmpData:hl.Bytes, tmpSize:Int, timeout:Float):Bool { + return false; + } } diff --git a/std/hl/_std/sys/net/UdpSocket.hx b/std/hl/_std/sys/net/UdpSocket.hx new file mode 100644 index 00000000000..d29f326f2bf --- /dev/null +++ b/std/hl/_std/sys/net/UdpSocket.hx @@ -0,0 +1,81 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.net; + +import sys.net.Socket; +import haxe.io.Error; + +class UdpSocket extends Socket { + public function new() { + super(); + } + + override function init():Void { + __s = Socket.socket_new(true); + super.init(); + } + + public function sendTo(buf:haxe.io.Bytes, pos:Int, len:Int, addr:Address):Int { + if (pos < 0 || len < 0 || pos + len > buf.length) + throw OutsideBounds; + var ret = socket_send_to(__s, (buf : hl.Bytes).offset(pos), len, addr.host, addr.port); + if (ret < 0) { + if (ret == -1) + throw Blocked; + throw new haxe.io.Eof(); + } + return ret; + } + + public function readFrom(buf:haxe.io.Bytes, pos:Int, len:Int, addr:Address):Int { + var host = 0, port = 0; + if (pos < 0 || len < 0 || pos + len > buf.length) + throw OutsideBounds; + var ret = socket_recv_from(__s, (buf : hl.Bytes).offset(pos), len, host, port); + if (ret <= 0) { + if (ret == -1) + throw Blocked; + throw new haxe.io.Eof(); + } + addr.host = host; + addr.port = port; + return ret; + } + + public function setBroadcast(b:Bool):Void { + if (!socket_set_broadcast(__s, b)) + throw new Sys.SysError("setBroadcast() failure"); + } + + @:hlNative("std", "socket_send_to") static function socket_send_to(s:SocketHandle, bytes:hl.Bytes, len:Int, host:Int, port:Int):Int { + return 0; + } + + @:hlNative("std", "socket_set_broadcast") static function socket_set_broadcast(s:SocketHandle, b:Bool):Bool { + return true; + } + + @:hlNative("std", "socket_recv_from") static function socket_recv_from(s:SocketHandle, bytes:hl.Bytes, len:Int, host:hl.Ref, port:hl.Ref):Int { + return 0; + } +} diff --git a/std/hl/_std/sys/ssl/Certificate.hx b/std/hl/_std/sys/ssl/Certificate.hx index b2db5575967..b15e3ec6396 100644 --- a/std/hl/_std/sys/ssl/Certificate.hx +++ b/std/hl/_std/sys/ssl/Certificate.hx @@ -1,4 +1,27 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package sys.ssl; + import sys.ssl.Lib; @:noDoc @@ -6,58 +29,57 @@ typedef CertificatePtr = hl.Abstract<"hl_ssl_cert">; @:coreApi class Certificate { - - var __h : Null; - var __x : CertificatePtr; + var __h:Null; + var __x:CertificatePtr; @:allow(sys.ssl.Socket) - function new( x : CertificatePtr, ?h: Null ){ + function new(x:CertificatePtr, ?h:Null) { __x = x; __h = h; } - public static function loadFile( file : String ) : Certificate { - return new Certificate( cert_load_file( @:privateAccess file.toUtf8() ) ); + public static function loadFile(file:String):Certificate { + return new Certificate(cert_load_file(@:privateAccess file.toUtf8())); } - - public static function loadPath( path : String ) : Certificate { - return new Certificate( cert_load_path( @:privateAccess path.toUtf8() ) ); + + public static function loadPath(path:String):Certificate { + return new Certificate(cert_load_path(@:privateAccess path.toUtf8())); } - public static function fromString( str : String ) : Certificate { - return new Certificate( cert_add_pem(null, @:privateAccess str.toUtf8() ) ); + public static function fromString(str:String):Certificate { + return new Certificate(cert_add_pem(null, @:privateAccess str.toUtf8())); } - - public static function loadDefaults() : Certificate { + + public static function loadDefaults():Certificate { var x = cert_load_defaults(); - if ( x != null ) - return new Certificate( x ); - + if (x != null) + return new Certificate(x); + var defPaths = null; - switch( Sys.systemName() ){ + switch (Sys.systemName()) { case "Linux": defPaths = [ "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. - "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL - "/etc/ssl/ca-bundle.pem", // OpenSUSE - "/etc/pki/tls/cacert.pem", // OpenELEC - "/etc/ssl/certs", // SLES10/SLES11 - "/system/etc/security/cacerts" // Android + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/ssl/certs", // SLES10/SLES11 + "/system/etc/security/cacerts" // Android ]; case "BSD": defPaths = [ "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly - "/etc/ssl/cert.pem", // OpenBSD - "/etc/openssl/certs/ca-certificates.crt", // NetBSD + "/etc/ssl/cert.pem", // OpenBSD + "/etc/openssl/certs/ca-certificates.crt", // NetBSD ]; case "Android": defPaths = ["/system/etc/security/cacerts"]; default: } - if( defPaths != null ){ - for( path in defPaths ){ - if( sys.FileSystem.exists(path) ){ - if( sys.FileSystem.isDirectory(path) ) + if (defPaths != null) { + for (path in defPaths) { + if (sys.FileSystem.exists(path)) { + if (sys.FileSystem.isDirectory(path)) return loadPath(path); else return loadFile(path); @@ -67,64 +89,94 @@ class Certificate { return null; } - public var commonName(get,null) : Null; - public var altNames(get, null) : Array; - public var notBefore(get,null) : Date; - public var notAfter(get,null) : Date; + public var commonName(get, null):Null; + public var altNames(get, null):Array; + public var notBefore(get, null):Date; + public var notAfter(get, null):Date; - function get_commonName() : Null { + function get_commonName():Null { return subject("CN"); } - function get_altNames() : Array { + function get_altNames():Array { var a = cert_get_altnames(__x); - return [for( e in a ) @:privateAccess String.fromUTF8(e)]; + return [for (e in a) @:privateAccess String.fromUCS2(e)]; } - - public function subject( field : String ) : Null { - var s = cert_get_subject(__x, @:privateAccess field.toUtf8() ); - return s==null ? null : new String( cast s ); + + public function subject(field:String):Null { + var s = cert_get_subject(__x, @:privateAccess field.toUtf8()); + return s == null ? null : @:privateAccess String.fromUCS2(cast s); } - - public function issuer( field : String ) : Null { + + public function issuer(field:String):Null { var s = cert_get_issuer(__x, @:privateAccess field.toUtf8()); - return s==null ? null : new String( cast s ); + return s == null ? null : @:privateAccess String.fromUCS2(cast s); } - function get_notBefore() : Date { - var a = cert_get_notbefore( __x ); - return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + function get_notBefore():Date { + var a = cert_get_notbefore(__x); + return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]); } - function get_notAfter() : Date { - var a = cert_get_notafter( __x ); - return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + function get_notAfter():Date { + var a = cert_get_notafter(__x); + return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]); } - - public function next() : Null { + + public function next():Null { var n = cert_get_next(__x); - return n == null ? null : new Certificate( n, __h==null ? this : __h ); + return n == null ? null : new Certificate(n, __h == null ? this : __h); } - public function add( pem : String ) : Void { + public function add(pem:String):Void { cert_add_pem(__x, @:privateAccess pem.toUtf8()); } - public function addDER( der : haxe.io.Bytes ) : Void { + public function addDER(der:haxe.io.Bytes):Void { cert_add_der(__x, @:privateAccess der.b, @:privateAccess der.length); } - @:hlNative("ssl","cert_load_defaults") static function cert_load_defaults() : CertificatePtr { return null; } - @:hlNative("ssl","cert_load_file") static function cert_load_file( file : hl.Bytes ) : CertificatePtr { return null; } - @:hlNative("ssl","cert_load_path") static function cert_load_path( path : hl.Bytes ) : CertificatePtr { return null; } - @:hlNative("ssl","cert_get_subject") static function cert_get_subject( cert : CertificatePtr, obj : hl.Bytes ) : hl.Bytes { return null; } - @:hlNative("ssl","cert_get_issuer") static function cert_get_issuer( cert : CertificatePtr, obj : hl.Bytes ) : hl.Bytes { return null; } - @:hlNative("ssl","cert_get_altnames") static function cert_get_altnames( cert : CertificatePtr ) : hl.NativeArray { return null; } - @:hlNative("ssl","cert_get_notbefore") static function cert_get_notbefore( cert : CertificatePtr ) : hl.NativeArray { return null; } - @:hlNative("ssl","cert_get_notafter") static function cert_get_notafter( cert : CertificatePtr ) : hl.NativeArray { return null; } - @:hlNative("ssl","cert_get_next") static function cert_get_next( cert : CertificatePtr ) : Null { return null; } - @:hlNative("ssl","cert_add_pem") static function cert_add_pem( cert : Null, data : hl.Bytes ) : CertificatePtr { return null; } - @:hlNative("ssl","cert_add_der") static function cert_add_der( cert : Null, data : hl.Bytes, len : Int ) : CertificatePtr { return null; } - + @:hlNative("ssl", "cert_load_defaults") static function cert_load_defaults():CertificatePtr { + return null; + } + + @:hlNative("ssl", "cert_load_file") static function cert_load_file(file:hl.Bytes):CertificatePtr { + return null; + } + + @:hlNative("ssl", "cert_load_path") static function cert_load_path(path:hl.Bytes):CertificatePtr { + return null; + } + + @:hlNative("ssl", "cert_get_subject") static function cert_get_subject(cert:CertificatePtr, obj:hl.Bytes):hl.Bytes { + return null; + } + @:hlNative("ssl", "cert_get_issuer") static function cert_get_issuer(cert:CertificatePtr, obj:hl.Bytes):hl.Bytes { + return null; + } + + @:hlNative("ssl", "cert_get_altnames") static function cert_get_altnames(cert:CertificatePtr):hl.NativeArray { + return null; + } + + @:hlNative("ssl", "cert_get_notbefore") static function cert_get_notbefore(cert:CertificatePtr):hl.NativeArray { + return null; + } + + @:hlNative("ssl", "cert_get_notafter") static function cert_get_notafter(cert:CertificatePtr):hl.NativeArray { + return null; + } + + @:hlNative("ssl", "cert_get_next") static function cert_get_next(cert:CertificatePtr):Null { + return null; + } + + @:hlNative("ssl", "cert_add_pem") static function cert_add_pem(cert:Null, data:hl.Bytes):CertificatePtr { + return null; + } + + @:hlNative("ssl", "cert_add_der") static function cert_add_der(cert:Null, data:hl.Bytes, len:Int):CertificatePtr { + return null; + } } diff --git a/std/hl/_std/sys/ssl/Context.hx b/std/hl/_std/sys/ssl/Context.hx new file mode 100644 index 00000000000..0109e715af2 --- /dev/null +++ b/std/hl/_std/sys/ssl/Context.hx @@ -0,0 +1,98 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.ssl; + +private typedef ConfigPtr = hl.Abstract<"mbedtls_ssl_config">; +private typedef ContextPtr = hl.Abstract<"mbedtls_ssl_context">; + +@:keep class SNICbResult { + public var cert:Certificate.CertificatePtr; + public var key:Key.KeyPtr; + + public function new(cert:Certificate, key:Key) { + this.cert = @:privateAccess cert.__x; + this.key = @:privateAccess key.__k; + } +} + +@:hlNative("ssl", "ssl_") +abstract Context(ContextPtr) { + public function new(config) { + this = ssl_new(config); + } + + public function close():Void {} + + public function handshake():Int { + return 0; + } + + public function recvChar():Int { + return 0; + } + + public function sendChar(c:Int):Int { + return 0; + } + + public function getPeerCertificate():Certificate.CertificatePtr { + return null; + } + + public function recv(bytes:hl.Bytes, pos:Int, len:Int):Int { + return 0; + } + + public function send(bytes:hl.Bytes, pos:Int, len:Int):Int { + return 0; + } + + public function setSocket(socket:sys.net.Socket.SocketHandle):Void {} + + public function setHostname(name:hl.Bytes):Void {} + + @:hlNative("ssl", "ssl_new") static function ssl_new(conf:Config):ContextPtr { + return null; + } +} + +@:hlNative("ssl", "conf_") +abstract Config(ConfigPtr) { + public function new(server:Bool) { + this = conf_new(server); + } + + public function setCert(cert:Certificate.CertificatePtr, pkey:Key.KeyPtr):Void {} + + public function setCa(ca:Certificate.CertificatePtr):Void {} + + public function close():Void {} + + public function setVerify(mode:Int):Void {} + + public function setServernameCallback(cb:hl.Bytes->SNICbResult):Void {} + + @:hlNative("ssl", "conf_new") static function conf_new(server:Bool):ConfigPtr { + return null; + } +} diff --git a/std/hl/_std/sys/ssl/Digest.hx b/std/hl/_std/sys/ssl/Digest.hx index 2b121e68b51..4578cae46ff 100644 --- a/std/hl/_std/sys/ssl/Digest.hx +++ b/std/hl/_std/sys/ssl/Digest.hx @@ -1,27 +1,56 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package sys.ssl; + import sys.ssl.Lib; @:coreApi class Digest { - - public static function make( data : haxe.io.Bytes, alg : DigestAlgorithm ) : haxe.io.Bytes { + public static function make(data:haxe.io.Bytes, alg:DigestAlgorithm):haxe.io.Bytes { var size = 0; - var b = @:privateAccess dgst_make( data.b, data.length, (alg:String).toUtf8(), size ); - return @:privateAccess new haxe.io.Bytes(b,size); + var b = @:privateAccess dgst_make(data.b, data.length, (alg : String).toUtf8(), size); + return @:privateAccess new haxe.io.Bytes(b, size); } - - public static function sign( data : haxe.io.Bytes, privKey : Key, alg : DigestAlgorithm ) : haxe.io.Bytes { + + public static function sign(data:haxe.io.Bytes, privKey:Key, alg:DigestAlgorithm):haxe.io.Bytes { var size = 0; - var b = @:privateAccess dgst_sign( data.b, data.length, privKey.__k, (alg:String).toUtf8(), size ); - return @:privateAccess new haxe.io.Bytes(b,size); + var b = @:privateAccess dgst_sign(data.b, data.length, privKey.__k, (alg : String).toUtf8(), size); + return @:privateAccess new haxe.io.Bytes(b, size); } - - public static function verify( data : haxe.io.Bytes, signature : haxe.io.Bytes, pubKey : Key, alg : DigestAlgorithm ) : Bool{ - return @:privateAccess dgst_verify( data.b, data.length, signature.b, signature.length, pubKey.__k, (alg:String).toUtf8() ); + + public static function verify(data:haxe.io.Bytes, signature:haxe.io.Bytes, pubKey:Key, alg:DigestAlgorithm):Bool { + return @:privateAccess dgst_verify(data.b, data.length, signature.b, signature.length, pubKey.__k, (alg : String).toUtf8()); } - @:hlNative("ssl","dgst_make") static function dgst_make( data : hl.Bytes, len : Int, alg : hl.Bytes, size : hl.Ref ) : hl.Bytes { return null; } - @:hlNative("ssl","dgst_sign") static function dgst_sign( data : hl.Bytes, len : Int, key : sys.ssl.Key.KeyPtr, alg : hl.Bytes, size : hl.Ref ) : hl.Bytes { return null; } - @:hlNative("ssl","dgst_verify") static function dgst_verify( data : hl.Bytes, dlen : Int, sign : hl.Bytes, slen : Int, key : sys.ssl.Key.KeyPtr, alg : hl.Bytes ) : Bool { return false; } - + @:hlNative("ssl", "dgst_make") static function dgst_make(data:hl.Bytes, len:Int, alg:hl.Bytes, size:hl.Ref):hl.Bytes { + return null; + } + + @:hlNative("ssl", "dgst_sign") static function dgst_sign(data:hl.Bytes, len:Int, key:sys.ssl.Key.KeyPtr, alg:hl.Bytes, size:hl.Ref):hl.Bytes { + return null; + } + + @:hlNative("ssl", "dgst_verify") static function dgst_verify(data:hl.Bytes, dlen:Int, sign:hl.Bytes, slen:Int, key:sys.ssl.Key.KeyPtr, alg:hl.Bytes):Bool { + return false; + } } diff --git a/std/hl/_std/sys/ssl/Key.hx b/std/hl/_std/sys/ssl/Key.hx index 1d62628fbe7..240d82d44fd 100644 --- a/std/hl/_std/sys/ssl/Key.hx +++ b/std/hl/_std/sys/ssl/Key.hx @@ -1,4 +1,27 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package sys.ssl; + import sys.ssl.Lib; @:noDoc @@ -6,31 +29,34 @@ typedef KeyPtr = hl.Abstract<"hl_ssl_pkey">; @:coreApi class Key { - - private var __k : KeyPtr; + private var __k:KeyPtr; - private function new( k : KeyPtr ){ + private function new(k:KeyPtr) { __k = k; } - - public static function loadFile( file : String, ?isPublic : Bool, ?pass : String ) : Key { - var data = sys.io.File.getBytes( file ); - var start = data.getString(0,11); - if( start == "-----BEGIN " ) - return readPEM( data.toString(), isPublic==true, pass ); + + public static function loadFile(file:String, ?isPublic:Bool, ?pass:String):Key { + var data = sys.io.File.getBytes(file); + var start = data.getString(0, 11); + if (start == "-----BEGIN ") + return readPEM(data.toString(), isPublic == true, pass); else - return readDER( data, isPublic==true ); + return readDER(data, isPublic == true); } - - public static function readPEM( data : String, isPublic : Bool, ?pass : String ) : Key { - return new Key( key_from_pem( @:privateAccess data.toUtf8(), isPublic, pass == null ? null : @:privateAccess pass.toUtf8() ) ); + + public static function readPEM(data:String, isPublic:Bool, ?pass:String):Key { + return new Key(key_from_pem(@:privateAccess data.toUtf8(), isPublic, pass == null ? null : @:privateAccess pass.toUtf8())); } - public static function readDER( data : haxe.io.Bytes, isPublic : Bool ) : Key { - return new Key( key_from_der( @:privateAccess data.b, @:privateAccess data.length, isPublic ) ); + public static function readDER(data:haxe.io.Bytes, isPublic:Bool):Key { + return new Key(key_from_der(@:privateAccess data.b, @:privateAccess data.length, isPublic)); } - @:hlNative("ssl","key_from_pem") static function key_from_pem( data : hl.Bytes, pub : Bool, pass : Null ) : KeyPtr { return null; } - @:hlNative("ssl","key_from_der") static function key_from_der( data : hl.Bytes, len : Int, pub : Bool ) : KeyPtr { return null; } + @:hlNative("ssl", "key_from_pem") static function key_from_pem(data:hl.Bytes, pub:Bool, pass:Null):KeyPtr { + return null; + } + @:hlNative("ssl", "key_from_der") static function key_from_der(data:hl.Bytes, len:Int, pub:Bool):KeyPtr { + return null; + } } diff --git a/std/hl/_std/sys/ssl/Lib.hx b/std/hl/_std/sys/ssl/Lib.hx index c501b64736f..5e6fc054360 100644 --- a/std/hl/_std/sys/ssl/Lib.hx +++ b/std/hl/_std/sys/ssl/Lib.hx @@ -1,10 +1,32 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package sys.ssl; @:noDoc @:keep class Lib { - static function __init__() : Void{ + static function __init__():Void { ssl_init(); } - - @:hlNative("ssl","ssl_init") static function ssl_init(){}; + + @:hlNative("ssl", "ssl_init") static function ssl_init() {}; } diff --git a/std/hl/_std/sys/ssl/Socket.hx b/std/hl/_std/sys/ssl/Socket.hx index 149308f3b33..c232fc23392 100644 --- a/std/hl/_std/sys/ssl/Socket.hx +++ b/std/hl/_std/sys/ssl/Socket.hx @@ -1,204 +1,215 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package sys.ssl; + import sys.ssl.Lib; import sys.ssl.Key.KeyPtr; import sys.ssl.Certificate.CertificatePtr; import sys.net.Socket.SocketHandle; -private typedef ConfigPtr = hl.Abstract<"mbedtls_ssl_config">; -private typedef ContextPtr = hl.Abstract<"mbedtls_ssl_context">; - -@:keep -private class SNICbResult { - public var cert : CertificatePtr; - public var key : KeyPtr; - public function new( cert : Certificate, key : Key ){ - this.cert = @:privateAccess cert.__x; - this.key = @:privateAccess key.__k; - } -} - private class SocketInput extends haxe.io.Input { - @:allow(sys.ssl.Socket) private var __s : Socket; + @:allow(sys.ssl.Socket) private var __s:Socket; - public function new( s : Socket ) { + public function new(s:Socket) { this.__s = s; } public override function readByte() { __s.handshake(); - var r = ssl_recv_char( @:privateAccess __s.ssl ); - if( r == -1 ) + var r = @:privateAccess __s.ssl.recvChar(); + if (r == -1) throw haxe.io.Error.Blocked; - else if( r < 0 ) + else if (r < 0) throw new haxe.io.Eof(); return r; } - public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { + public override function readBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { + if (pos < 0 || len < 0 || ((pos + len) : UInt) > (buf.length : UInt)) + throw haxe.io.Error.OutsideBounds; __s.handshake(); - var r = ssl_recv( @:privateAccess __s.ssl, @:privateAccess buf.b, pos, len ); - if( r == -1 ) + var r = @:privateAccess __s.ssl.recv(buf, pos, len); + if (r == -1) throw haxe.io.Error.Blocked; - else if( r < 0 ) + else if (r <= 0) throw new haxe.io.Eof(); return r; } public override function close() { super.close(); - if( __s != null ) __s.close(); + if (__s != null) + __s.close(); } - - @:hlNative("ssl","ssl_recv") static function ssl_recv( ssl : ContextPtr, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return -1; } - @:hlNative("ssl","ssl_recv_char") static function ssl_recv_char( ssl : ContextPtr ) : Int { return -1; } } private class SocketOutput extends haxe.io.Output { - @:allow(sys.ssl.Socket) private var __s : Socket; + @:allow(sys.ssl.Socket) private var __s:Socket; - public function new( s : Socket ) { + public function new(s:Socket) { this.__s = s; } - public override function writeByte( c : Int ) { + public override function writeByte(c:Int) { __s.handshake(); - var r = ssl_send_char( @:privateAccess __s.ssl, c); - if( r == -1 ) + var r = @:privateAccess __s.ssl.sendChar(c); + if (r == -1) throw haxe.io.Error.Blocked; - else if( r < 0 ) + else if (r < 0) throw new haxe.io.Eof(); } - public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { + public override function writeBytes(buf:haxe.io.Bytes, pos:Int, len:Int):Int { + if (pos < 0 || len < 0 || ((pos + len) : UInt) > (buf.length : UInt)) + throw haxe.io.Error.OutsideBounds; __s.handshake(); - var r = ssl_send( @:privateAccess __s.ssl, @:privateAccess buf.b, pos, len); - if( r == -1 ) + var r = @:privateAccess __s.ssl.send(buf, pos, len); + if (r == -1) throw haxe.io.Error.Blocked; - else if( r < 0 ) + else if (r < 0) throw new haxe.io.Eof(); return r; } public override function close() { super.close(); - if( __s != null ) __s.close(); + if (__s != null) + __s.close(); } - - @:hlNative("ssl","ssl_send") static function ssl_send( ssl : ContextPtr, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return -1; } - @:hlNative("ssl","ssl_send_char") static function ssl_send_char( ssl : ContextPtr, c : Int ) : Int { return -1; } - } @:coreApi @:access(sys.net.Socket) class Socket extends sys.net.Socket { - - public static var DEFAULT_VERIFY_CERT : Null = true; - - public static var DEFAULT_CA : Null; - - private var conf : ConfigPtr; - private var ssl : ContextPtr; - - public var verifyCert : Null; - private var caCert : Null; - private var hostname : String; - - private var ownCert : Null; - private var ownKey : Null; - private var altSNIContexts : NullBool, key: Key, cert: Certificate}>>; - private var sniCallback : hl.Bytes -> SNICbResult; - private var handshakeDone : Bool; - private var isBlocking : Bool = true; - - private override function init() : Void { - __s = sys.net.Socket.socket_new( false ); - input = new SocketInput( this ); - output = new SocketOutput( this ); - if( DEFAULT_VERIFY_CERT && DEFAULT_CA == null ){ + public static var DEFAULT_VERIFY_CERT:Null = true; + + public static var DEFAULT_CA:Null; + + private var conf:Context.Config; + private var ssl:Context; + + public var verifyCert:Null; + + private var caCert:Null; + private var hostname:String; + + private var ownCert:Null; + private var ownKey:Null; + private var altSNIContexts:NullBool, key:Key, cert:Certificate}>>; + private var sniCallback:hl.Bytes->Context.SNICbResult; + private var handshakeDone:Bool; + private var isBlocking:Bool = true; + + private override function init():Void { + __s = sys.net.Socket.socket_new(false); + input = new SocketInput(this); + output = new SocketOutput(this); + if (DEFAULT_VERIFY_CERT && DEFAULT_CA == null) { try { DEFAULT_CA = Certificate.loadDefaults(); - }catch( e : Dynamic ){} + } catch (e:Dynamic) {} } verifyCert = DEFAULT_VERIFY_CERT; caCert = DEFAULT_CA; } - public override function connect(host : sys.net.Host, port : Int) : Void { - conf = buildConfig( false ); - ssl = ssl_new( conf ); - ssl_set_socket( ssl, __s ); + public override function connect(host:sys.net.Host, port:Int):Void { + conf = buildConfig(false); + ssl = new Context(conf); + ssl.setSocket(__s); handshakeDone = false; - if( hostname == null ) + if (hostname == null) hostname = host.host; - if( hostname != null ) - ssl_set_hostname( ssl, @:privateAccess hostname.toUtf8() ); - if( !sys.net.Socket.socket_connect( __s, host.ip, port ) ) - throw new Sys.SysError("Failed to connect on "+host.toString()+":"+port); - if( isBlocking ) + if (hostname != null) + ssl.setHostname(@:privateAccess hostname.toUtf8()); + if (!sys.net.Socket.socket_connect(__s, host.ip, port)) + throw new Sys.SysError("Failed to connect on " + host.toString() + ":" + port); + if (isBlocking) handshake(); } - public function handshake() : Void { - if( !handshakeDone ){ - var r = ssl_handshake( ssl ); - if( r == 0 ) + public function handshake():Void { + if (!handshakeDone) { + var r = ssl.handshake(); + if (r == 0) handshakeDone = true; - else if( r == -1 ) + else if (r == -1) throw haxe.io.Error.Blocked; else throw new haxe.io.Eof(); } } - override function setBlocking( b : Bool ) : Void { + override function setBlocking(b:Bool):Void { super.setBlocking(b); isBlocking = b; } - public function setCA( cert : Certificate ) : Void { + public function setCA(cert:Certificate):Void { caCert = cert; } - public function setHostname( name : String ) : Void { + public function setHostname(name:String):Void { hostname = name; } - public function setCertificate( cert : Certificate, key : Key ) : Void { + public function setCertificate(cert:Certificate, key:Key):Void { ownCert = cert; ownKey = key; } - public override function close() : Void { - if( ssl != null ) ssl_close( ssl ); - if( conf != null ) conf_close( conf ); - if( altSNIContexts != null ) + public override function close():Void { + if (ssl != null) + ssl.close(); + if (conf != null) + conf.close(); + if (altSNIContexts != null) sniCallback = null; - sys.net.Socket.socket_close( __s ); - var input : SocketInput = cast input; - var output : SocketOutput = cast output; + sys.net.Socket.socket_close(__s); + var input:SocketInput = cast input; + var output:SocketOutput = cast output; @:privateAccess input.__s = output.__s = null; input.close(); output.close(); } - public function addSNICertificate( cbServernameMatch : String->Bool, cert : Certificate, key : Key ) : Void { - if( altSNIContexts == null ) + public function addSNICertificate(cbServernameMatch:String->Bool, cert:Certificate, key:Key):Void { + if (altSNIContexts == null) altSNIContexts = []; - altSNIContexts.push( {match: cbServernameMatch, cert: cert, key: key} ); + altSNIContexts.push({match: cbServernameMatch, cert: cert, key: key}); } - public override function bind( host : sys.net.Host, port : Int ) : Void { - conf = buildConfig( true ); + public override function bind(host:sys.net.Host, port:Int):Void { + conf = buildConfig(true); - sys.net.Socket.socket_bind( __s, host.ip, port ); + sys.net.Socket.socket_bind(__s, host.ip, port); } - public override function accept() : Socket { - var c = sys.net.Socket.socket_accept( __s ); - var cssl = ssl_new( conf ); - ssl_set_socket( cssl, c ); + public override function accept():Socket { + var c = sys.net.Socket.socket_accept(__s); + var cssl = new Context(conf); + cssl.setSocket(c); - var s = Type.createEmptyInstance( sys.ssl.Socket ); + var s = Type.createEmptyInstance(sys.ssl.Socket); s.__s = c; s.ssl = cssl; s.input = new SocketInput(s); @@ -208,51 +219,35 @@ class Socket extends sys.net.Socket { return s; } - public function peerCertificate() : sys.ssl.Certificate { - var x = ssl_get_peer_certificate( ssl ); - return x==null ? null : new sys.ssl.Certificate( x ); + public function peerCertificate():sys.ssl.Certificate { + var x = ssl.getPeerCertificate(); + return x == null ? null : new sys.ssl.Certificate(x); } - private function buildConfig( server : Bool ) : ConfigPtr { - var conf = conf_new( server ); + private function buildConfig(server:Bool):Context.Config { + var conf = new Context.Config(server); - if( ownCert != null && ownKey != null ) - conf_set_cert( conf, @:privateAccess ownCert.__x, @:privateAccess ownKey.__k ); + if (ownCert != null && ownKey != null) + conf.setCert(@:privateAccess ownCert.__x, @:privateAccess ownKey.__k); - if ( altSNIContexts != null ) { - sniCallback = function(servername:hl.Bytes) : SNICbResult { + if (altSNIContexts != null) { + sniCallback = function(servername:hl.Bytes):Context.SNICbResult { var servername = @:privateAccess String.fromUTF8(servername); - for( c in altSNIContexts ){ - if( c.match(servername) ) - return new SNICbResult(c.cert, c.key); + for (c in altSNIContexts) { + if (c.match(servername)) + return new Context.SNICbResult(c.cert, c.key); } - if( ownKey != null && ownCert != null ) - return new SNICbResult(ownCert, ownKey); + if (ownKey != null && ownCert != null) + return new Context.SNICbResult(ownCert, ownKey); return null; } - conf_set_servername_callback( conf, sniCallback ); + conf.setServernameCallback(sniCallback); } - if ( caCert != null ) - conf_set_ca( conf, caCert == null ? null : @:privateAccess caCert.__x ); - conf_set_verify( conf, if( verifyCert ) 1 else if( verifyCert==null ) 2 else 0 ); - + if (caCert != null) + conf.setCa(caCert == null ? null : @:privateAccess caCert.__x); + conf.setVerify(if (verifyCert) 1 else if (verifyCert == null) 2 else 0); + return conf; } - - - @:hlNative("ssl","ssl_new") static function ssl_new( conf : ConfigPtr ) : ContextPtr { return null; } - @:hlNative("ssl","ssl_close") static function ssl_close( ssl : ContextPtr ) : Void {} - @:hlNative("ssl","ssl_handshake") static function ssl_handshake( ssl : ContextPtr ) : Int { return -1; } - @:hlNative("ssl","ssl_set_socket") static function ssl_set_socket( ssl : ContextPtr, socket : SocketHandle ) : Void { } - @:hlNative("ssl","ssl_set_hostname") static function ssl_set_hostname( ssl : ContextPtr, name : hl.Bytes ) : Void { } - @:hlNative("ssl","ssl_get_peer_certificate") static function ssl_get_peer_certificate( ssl : ContextPtr ) : CertificatePtr { return null; } - - @:hlNative("ssl","conf_new") static function conf_new( server : Bool ) : ConfigPtr { return null; } - @:hlNative("ssl","conf_close") static function conf_close( conf : ConfigPtr ) : Void { } - @:hlNative("ssl","conf_set_ca") static function conf_set_ca( conf : ConfigPtr, ca : CertificatePtr ) : Void { } - @:hlNative("ssl","conf_set_verify") static function conf_set_verify( conf : ConfigPtr, mode : Int ) : Void { } - @:hlNative("ssl","conf_set_cert") static function conf_set_cert( conf : ConfigPtr, cert : CertificatePtr, pkey : KeyPtr ) : Void { } - @:hlNative("ssl","conf_set_servername_callback") static function conf_set_servername_callback( conf : ConfigPtr, cb : hl.Bytes -> SNICbResult ) : Void { } - } diff --git a/std/hl/_std/sys/thread/Deque.hx b/std/hl/_std/sys/thread/Deque.hx new file mode 100644 index 00000000000..eb71312e91d --- /dev/null +++ b/std/hl/_std/sys/thread/Deque.hx @@ -0,0 +1,52 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +#if doc_gen +@:coreApi extern class Deque { + public function new():Void; + public function add(i:T):Void; + public function push(i:T):Void; + public function pop(block:Bool):Null; +} +#else + +@:hlNative("std", "deque_") +abstract Deque(hl.Abstract<"hl_deque">) { + public function new() { + this = alloc(); + } + + public function add(i:T) {} + + public function push(i:T) {} + + public function pop(block:Bool):Null { + return null; + } + + static function alloc() { + return null; + } +} +#end diff --git a/std/lua/_std/haxe/Log.hx b/std/hl/_std/sys/thread/Lock.hx similarity index 67% rename from std/lua/_std/haxe/Log.hx rename to std/hl/_std/sys/thread/Lock.hx index 9711fcdfcac..372719ab057 100644 --- a/std/lua/_std/haxe/Log.hx +++ b/std/hl/_std/sys/thread/Lock.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,32 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe; -@:coreApi class Log { - public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { - var str:String = null; - if (infos != null) { - str = infos.fileName + ":" + infos.lineNumber + ": " + v; - if (infos.customParams != null) - { - str += "," + infos.customParams.join(","); - } - } else { - str = v; +package sys.thread; + +@:coreApi +class Lock { + var deque:sys.thread.Deque; + + public function new():Void { + deque = new Deque>(); + } + + public function wait(?timeout:Float):Bool { + if (timeout == null) { + deque.pop(true); + return true; } - if (str == null) str = "null"; - untyped __define_feature__("use._hx_print",_hx_print(str)); + var targetTime = haxe.Timer.stamp() + timeout; + do { + if (deque.pop(false) != null) { + return true; + } + } while (haxe.Timer.stamp() < targetTime); + return false; + } + + public function release():Void { + deque.push(true); } } diff --git a/std/hl/_std/sys/thread/Mutex.hx b/std/hl/_std/sys/thread/Mutex.hx new file mode 100644 index 00000000000..cc37e1aca71 --- /dev/null +++ b/std/hl/_std/sys/thread/Mutex.hx @@ -0,0 +1,52 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +#if doc_gen +@:coreApi +extern class Mutex { + public function new():Void; + public function acquire():Void; + public function tryAcquire():Bool; + public function release():Void; +} +#else + +abstract Mutex(hl.Abstract<"hl_mutex">) { + public function new() { + this = alloc(true); + } + + @:hlNative("std", "mutex_acquire") public function acquire() {} + + @:hlNative("std", "mutex_try_acquire") public function tryAcquire():Bool { + return false; + } + + @:hlNative("std", "mutex_release") public function release() {} + + @:hlNative("std", "mutex_alloc") public static function alloc(b:Bool) { + return null; + } +} +#end diff --git a/std/js/XMLSocket.hx b/std/hl/_std/sys/thread/Thread.hx similarity index 52% rename from std/js/XMLSocket.hx rename to std/hl/_std/sys/thread/Thread.hx index db8675307d6..4e34dc82534 100644 --- a/std/js/XMLSocket.hx +++ b/std/hl/_std/sys/thread/Thread.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,46 +19,50 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package js; -/** - By compiling the `haxe.remoting.SocketWrapper` into a SWF, you can create - and use XMLSockets directly from Javascript. -**/ -class XMLSocket { +package sys.thread; - var cnx : haxe.remoting.ExternalConnection; +typedef ThreadHandle = hl.Abstract<"hl_thread">; - public function new( flashObject : String ) { - var ctx = new haxe.remoting.Context(); - var cnx = haxe.remoting.ExternalConnection.flashConnect("SocketWrapper",flashObject,ctx); - var sockId = cnx.api.create.call([flashObject]); - cnx.close(); - ctx.addObject("api",this,false); - this.cnx = haxe.remoting.ExternalConnection.flashConnect(sockId,flashObject,ctx); +abstract Thread(ThreadHandle) { + public function sendMessage(msg:Dynamic) { + getQueue(this).add(msg); } - public function connect( host : String, port : Int ) { - cnx.sock.connect.call([host,port]); + public static function readMessage(block = true):Dynamic { + return getQueue(cast current()).pop(block); } - public function send( data : String ) { - cnx.sock.send.call([data]); - } - - public function close() { - cnx.sock.close.call([]); - cnx.api.destroy.call([]); - cnx.close(); - } + static var queue_mutex:Mutex = null; + static var threads_queues:Array<{t:ThreadHandle, q:Deque}> = null; - public dynamic function onData( data : String ) { + static function getQueue(t:ThreadHandle) { + if (queue_mutex == null) { + queue_mutex = new Mutex(); + threads_queues = []; + } + queue_mutex.acquire(); + var q = null; + for (tq in threads_queues) + if (tq.t == t) { + q = tq.q; + break; + } + if (q == null) { + q = new Deque(); + threads_queues.push({t: t, q: q}); + } + queue_mutex.release(); + return q; } - public dynamic function onClose() { + @:hlNative("std", "thread_create") + public static function create(callb:Void->Void):Thread { + return null; } - public dynamic function onConnect( b : Bool ) { + @:hlNative("std", "thread_current") + public static function current():Thread { + return null; } - } diff --git a/std/hl/_std/sys/thread/Tls.hx b/std/hl/_std/sys/thread/Tls.hx new file mode 100644 index 00000000000..bfc894ce2cd --- /dev/null +++ b/std/hl/_std/sys/thread/Tls.hx @@ -0,0 +1,58 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +#if doc_gen +@:coreApi +extern class Tls { + public var value(get, set):T; + public function new():Void; +} +#else + +@:hlNative("std") +abstract Tls(hl.Abstract<"hl_tls">) { + public var value(get, set):T; + + public function new() { + this = tls_alloc(true); + } + + function get_value():T { + return tls_get(this); + } + + function set_value(v:T) { + tls_set(this, v); + return v; + } + + static function tls_alloc(gcValue:Bool) + return null; + + static function tls_get(t):Dynamic + return null; + + static function tls_set(t, v:Dynamic) {} +} +#end diff --git a/std/hl/hl_version b/std/hl/hl_version new file mode 100644 index 00000000000..ed21137ee19 --- /dev/null +++ b/std/hl/hl_version @@ -0,0 +1 @@ +1.10.0 \ No newline at end of file diff --git a/std/hl/types/ArrayBase.hx b/std/hl/types/ArrayBase.hx index 1683850fe5f..5b89e2954a7 100644 --- a/std/hl/types/ArrayBase.hx +++ b/std/hl/types/ArrayBase.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,75 +19,72 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl.types; @:keep class ArrayAccess { - - public function getDyn( pos : Int ) : Dynamic { + public function getDyn(pos:Int):Dynamic { throw "Not implemented"; return 0; } - public function setDyn( pos : Int, v : Dynamic ) { + public function setDyn(pos:Int, v:Dynamic) { throw "Not implemented"; } - public function blit( pos : Int, src : ArrayAccess, srcpos : Int, len : Int ) : Void { + public function blit(pos:Int, src:ArrayAccess, srcpos:Int, len:Int):Void { throw "Not implemented"; } - } @:keep class ArrayBase extends ArrayAccess { + public var length(default, null):Int; - public var length(default,null) : Int; - - - public function pushDyn( v : Dynamic ) : Int { + public function pushDyn(v:Dynamic):Int { throw "Not implemented"; return 0; } - public function popDyn() : Null { + public function popDyn():Null { throw "Not implemented"; return null; } - public function shiftDyn() : Null { + public function shiftDyn():Null { throw "Not implemented"; return null; } - public function unshiftDyn( v : Dynamic ) : Void { + public function unshiftDyn(v:Dynamic):Void { throw "Not implemented"; } - public function insertDyn( pos : Int, v : Dynamic ) : Void { + public function insertDyn(pos:Int, v:Dynamic):Void { throw "Not implemented"; } - public function removeDyn( v : Dynamic ) : Bool { + public function removeDyn(v:Dynamic):Bool { throw "Not implemented"; return false; } - public function sortDyn( f : Dynamic -> Dynamic -> Int ) : Void { + public function sortDyn(f:Dynamic->Dynamic->Int):Void { throw "Not implemented"; } - public function slice( pos : Int, ?end : Int ) : ArrayBase{ + public function slice(pos:Int, ?end:Int):ArrayBase { throw "Not implemented"; return null; } - public function splice( pos : Int, len : Int ) : ArrayBase{ + public function splice(pos:Int, len:Int):ArrayBase { throw "Not implemented"; return null; } - public function join( sep : String ) : String { + public function join(sep:String):String { throw "Not implemented"; return null; } @@ -96,13 +93,17 @@ class ArrayBase extends ArrayAccess { throw "Not implemented"; } - public function toString() : String { + public function resize(len:Int) { + throw "Not implemented"; + } + + public function toString():String { throw "Not implemented"; return null; } - function __cast( t : Type ) : Dynamic { - if( t == Type.get(new ArrayDyn()) ) + function __cast(t:Type):Dynamic { + if (t == Type.get((null : ArrayDyn))) return ArrayDyn.alloc(this, false); return null; } @@ -111,36 +112,35 @@ class ArrayBase extends ArrayAccess { return false; } - public static function allocI32( bytes : BytesAccess, length : Int ) @:privateAccess { - var a : ArrayBytes.ArrayI32 = untyped $new(ArrayBytes.ArrayI32); + public static function allocI32(bytes:BytesAccess, length:Int) @:privateAccess { + var a:ArrayBytes.ArrayI32 = untyped $new(ArrayBytes.ArrayI32); a.length = length; a.bytes = bytes; a.size = length; return a; } - public static function allocUI16( bytes : BytesAccess, length : Int ) @:privateAccess { - var a : ArrayBytes.ArrayUI16 = untyped $new(ArrayBytes.ArrayUI16); + public static function allocUI16(bytes:BytesAccess, length:Int) @:privateAccess { + var a:ArrayBytes.ArrayUI16 = untyped $new(ArrayBytes.ArrayUI16); a.length = length; a.bytes = bytes; a.size = length; return a; } - public static function allocF32( bytes : BytesAccess, length : Int ) @:privateAccess { - var a : ArrayBytes.ArrayF32 = untyped $new(ArrayBytes.ArrayF32); + public static function allocF32(bytes:BytesAccess, length:Int) @:privateAccess { + var a:ArrayBytes.ArrayF32 = untyped $new(ArrayBytes.ArrayF32); a.length = length; a.bytes = bytes; a.size = length; return a; } - public static function allocF64( bytes : BytesAccess, length : Int ) @:privateAccess { - var a : ArrayBytes.ArrayF64 = untyped $new(ArrayBytes.ArrayF64); + public static function allocF64(bytes:BytesAccess, length:Int) @:privateAccess { + var a:ArrayBytes.ArrayF64 = untyped $new(ArrayBytes.ArrayF64); a.length = length; a.bytes = bytes; a.size = length; return a; } - } diff --git a/std/hl/types/ArrayBytes.hx b/std/hl/types/ArrayBytes.hx index 197434fd0c0..20cf96c0068 100644 --- a/std/hl/types/ArrayBytes.hx +++ b/std/hl/types/ArrayBytes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,64 +19,68 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl.types; @:keep @:generic class BytesIterator { - var pos : Int; - var a : ArrayBytes; + var pos:Int; + var a:ArrayBytes; + public function new(a) { this.a = a; } + public function hasNext() { return pos < a.length; } - public function next() : T { + + public function next():T { return @:privateAccess a.bytes.get(pos++); } } @:keep @:generic class ArrayBytes extends ArrayBase { - - var bytes : hl.BytesAccess; - var size : Int; + var bytes:hl.BytesAccess; + var size:Int; public function new() { size = length = 0; bytes = null; } - public function concat( a : ArrayBytes ) : ArrayBytes { + public function concat(a:ArrayBytes):ArrayBytes { var ac = new ArrayBytes(); ac.length = ac.size = length + a.length; ac.bytes = new Bytes(ac.length << bytes.sizeBits); var offset = length << bytes.sizeBits; - (ac.bytes:Bytes).blit(0, this.bytes, 0, offset); - (ac.bytes:Bytes).blit(offset, a.bytes, 0, a.length << bytes.sizeBits); + (ac.bytes : Bytes).blit(0, this.bytes, 0, offset); + (ac.bytes : Bytes).blit(offset, a.bytes, 0, a.length << bytes.sizeBits); return ac; } - override function join( sep : String ) : String { + override function join(sep:String):String { var s = new StringBuf(); - for( i in 0...length ) { - if( i > 0 ) s.add(sep); + for (i in 0...length) { + if (i > 0) + s.add(sep); s.add(bytes[i]); } return s.toString(); } - public function pop() : Null { - if( length == 0 ) + public function pop():Null { + if (length == 0) return null; length--; return bytes[length]; } - public function push(x : T) : Int { + public function push(x:T):Int { var len = length; - if( size == len ) + if (size == len) __expand(len); else length++; @@ -84,8 +88,8 @@ class BytesIterator { return length; } - override function reverse() : Void { - for( i in 0...length >> 1 ) { + override function reverse():Void { + for (i in 0...length >> 1) { var k = length - 1 - i; var tmp = bytes[i]; bytes[i] = bytes[k]; @@ -93,199 +97,238 @@ class BytesIterator { } } - public function shift() : Null { - if( length == 0 ) + public function shift():Null { + if (length == 0) return null; var v = bytes[0]; length--; - (bytes:Bytes).blit(0, bytes, 1 << bytes.sizeBits, length << bytes.sizeBits); + (bytes : Bytes).blit(0, bytes, 1 << bytes.sizeBits, length << bytes.sizeBits); return v; } - override function blit( pos : Int, src : ArrayBase.ArrayAccess, srcpos : Int, len : Int ) : Void { + override function blit(pos:Int, src:ArrayBase.ArrayAccess, srcpos:Int, len:Int):Void { var src = (cast src : ArrayBytes); - if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) throw haxe.io.Error.OutsideBounds; - (bytes:Bytes).blit(pos << bytes.sizeBits,src.bytes,srcpos< length || srcpos + len > src.length) + throw haxe.io.Error.OutsideBounds; + (bytes : Bytes).blit(pos << bytes.sizeBits, src.bytes, srcpos << bytes.sizeBits, len << bytes.sizeBits); } - override function slice( pos : Int, ?end : Int ) : ArrayBytes { - if( pos < 0 ) { + override function slice(pos:Int, ?end:Int):ArrayBytes { + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) + if (pos < 0) pos = 0; } - var pend : Int; - if( end == null ) + var pend:Int; + if (end == null) pend = this.length; else { pend = end; - if( pend < 0 ) + if (pend < 0) pend += this.length; - if( pend > this.length ) + if (pend > this.length) pend = this.length; } var len = pend - pos; - if( len < 0 ) + if (len < 0) return new ArrayBytes(); var a = new ArrayBytes(); a.length = a.size = len; - a.bytes = (bytes:Bytes).sub(pos << bytes.sizeBits, len << bytes.sizeBits); + a.bytes = (bytes : Bytes).sub(pos << bytes.sizeBits, len << bytes.sizeBits); return a; } - public function sort( f : T -> T -> Int ) : Void { - if( Type.get((cast null : T)) == Type.get(0) ) - (bytes:Bytes).sortI32(0, length, cast f); + public function sort(f:T->T->Int):Void { + if (Type.get((cast null : T)) == Type.get(0)) + (bytes : Bytes).sortI32(0, length, cast f); else - (bytes:Bytes).sortF64(0, length, cast f); + (bytes : Bytes).sortF64(0, length, cast f); } - override function splice( pos : Int, len : Int ) : ArrayBytes { - if( len < 0 ) + override function splice(pos:Int, len:Int):ArrayBytes { + if (len < 0) return new ArrayBytes(); - if( pos < 0 ){ + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) pos = 0; + if (pos < 0) + pos = 0; } - if( pos > this.length ) { + if (pos > this.length) { pos = 0; len = 0; - } else if( pos + len > this.length ) { + } else if (pos + len > this.length) { len = this.length - pos; - if( len < 0 ) len = 0; + if (len < 0) + len = 0; } - if( len == 0 ) + if (len == 0) return new ArrayBytes(); var ret = new ArrayBytes(); - ret.bytes = (bytes:Bytes).sub(pos << bytes.sizeBits, len << bytes.sizeBits); + ret.bytes = (bytes : Bytes).sub(pos << bytes.sizeBits, len << bytes.sizeBits); ret.size = ret.length = len; var end = pos + len; - (bytes:Bytes).blit(pos << bytes.sizeBits, bytes, end << bytes.sizeBits, (length - end) << bytes.sizeBits); + (bytes : Bytes).blit(pos << bytes.sizeBits, bytes, end << bytes.sizeBits, (length - end) << bytes.sizeBits); length -= len; return ret; } - override function toString() : String { + override function toString():String { var b = new StringBuf(); b.addChar("[".code); - for( i in 0...length ) { - if( i > 0 ) b.addChar(",".code); + for (i in 0...length) { + if (i > 0) + b.addChar(",".code); b.add(bytes[i]); } b.addChar("]".code); return b.toString(); } - public function unshift( x : T ) : Void { - if( length == size ) __expand(length) else length++; - (bytes:Bytes).blit(1< length ) pos = length; - if( length == size ) __expand(length) else length++; - (bytes:Bytes).blit((pos + 1)< length) + pos = length; + if (length == size) + __expand(length) + else + length++; + (bytes : Bytes).blit((pos + 1) << bytes.sizeBits, bytes, pos << bytes.sizeBits, (length - pos - 1) << bytes.sizeBits); bytes[pos] = x; } - public function remove( x : T ) : Bool { + public function remove(x:T):Bool { var idx = indexOf(x); - if( idx < 0 ) + if (idx < 0) return false; length--; - (bytes : hl.Bytes).blit(idx<= len ) + if (i >= len) i = len - 1; - else if( i < 0 ) + else if (i < 0) i += len; - while( i >= 0 ) { - if( bytes[i] == x ) + while (i >= 0) { + if (bytes[i] == x) return i; i--; } return -1; } - public function copy() : ArrayBytes { + public function copy():ArrayBytes { var a = new ArrayBytes(); a.length = a.size = length; a.bytes = new Bytes(length << bytes.sizeBits); - (a.bytes:Bytes).blit(0, bytes, 0, length << bytes.sizeBits); + (a.bytes : Bytes).blit(0, bytes, 0, length << bytes.sizeBits); return a; } - public function iterator() : Iterator { + public function iterator():Iterator { return new BytesIterator(this); } - public function map( f : T -> S ) : ArrayDyn @:privateAccess { + public function map(f:T->S):ArrayDyn@:privateAccess { var a = new ArrayObj(); - if( length > 0 ) a.__expand(length - 1); - for( i in 0...length ) + if (length > 0) + a.__expand(length - 1); + for (i in 0...length) a.array[i] = f(bytes[i]); - return ArrayDyn.alloc(a,true); + return ArrayDyn.alloc(a, true); } - public function filter( f : T -> Bool ) : ArrayBytes { + public function filter(f:T->Bool):ArrayBytes { var a = new ArrayBytes(); - for( i in 0...length ) { + for (i in 0...length) { var v = bytes[i]; - if( f(v) ) a.push(v); + if (f(v)) + a.push(v); } return a; } - override function getDyn( pos : Int ) : Dynamic { - var pos : UInt = pos; - if( pos >= length ) + override public function resize(len:Int):Void { + if (length < len) { + __expand(len - 1); + } else if (length > len) { + (bytes : Bytes).fill(len << bytes.sizeBits, (length - len) << bytes.sizeBits, 0); + this.length = len; + } + } + + override function getDyn(pos:Int):Dynamic { + var pos:UInt = pos; + if (pos >= length) return bytes.nullValue; return bytes[pos]; } - override function setDyn( pos : Int, v : Dynamic ) { - var pos : UInt = pos; - if( pos >= length ) + override function setDyn(pos:Int, v:Dynamic) { + var pos:UInt = pos; + if (pos >= length) __expand(pos); bytes[pos] = v; } - override function pushDyn( v : Dynamic ) return push(v); - override function popDyn() : Null return pop(); - override function shiftDyn() : Null return shift(); - override function unshiftDyn( v : Dynamic ) unshift(v); - override function insertDyn( pos : Int, v : Dynamic ) insert(pos, v); - override function removeDyn( v : Dynamic ) return remove(v); - override function sortDyn( f : Dynamic -> Dynamic -> Int ) sort(f); + override function pushDyn(v:Dynamic) + return push(v); + + override function popDyn():Null + return pop(); + + override function shiftDyn():Null + return shift(); + + override function unshiftDyn(v:Dynamic) + unshift(v); + + override function insertDyn(pos:Int, v:Dynamic) + insert(pos, v); + + override function removeDyn(v:Dynamic) + return remove(v); + + override function sortDyn(f:Dynamic->Dynamic->Int) + sort(f); // called by compiler when accessing the array outside of its bounds, might trigger resize - function __expand( index : Int ) { - if( index < 0 ) throw "Invalid array index "+index; + function __expand(index:Int) { + if (index < 0) + throw "Invalid array index " + index; var newlen = index + 1; - if( newlen > size ) { + if (newlen > size) { var next = (size * 3) >> 1; - if( next < newlen ) next = newlen; + if (next < newlen) + next = newlen; var bytes2 = new hl.Bytes(next << bytes.sizeBits); var bsize = length << bytes.sizeBits; bytes2.blit(0, bytes, 0, bsize); @@ -295,7 +338,6 @@ class BytesIterator { } length = newlen; } - } typedef ArrayI32 = ArrayBytes; diff --git a/std/hl/types/ArrayDyn.hx b/std/hl/types/ArrayDyn.hx index f0b20306e4b..0244574b12c 100644 --- a/std/hl/types/ArrayDyn.hx +++ b/std/hl/types/ArrayDyn.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,26 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl.types; + import hl.types.ArrayBase; class ArrayDynIterator { - var a : ArrayBase; - var len : Int; - var pos : Int; + var a:ArrayBase; + var len:Int; + var pos:Int; + public function new(a) { this.a = a; this.len = a.length; this.pos = 0; } + public function hasNext() { return pos < len; } + public function next() { return a.getDyn(pos++); } @@ -41,17 +46,18 @@ class ArrayDynIterator { @:keep class ArrayDyn extends ArrayAccess { + public var length(get, never):Int; - public var length(get,never) : Int; - var array : ArrayBase; - var allowReinterpret : Bool; + var array:ArrayBase; + var allowReinterpret:Bool; public function new() { array = new ArrayObj(); allowReinterpret = true; } - inline function get_length() return array.length; + inline function get_length() + return array.length; override function getDyn(i) { return array.getDyn(i); @@ -61,149 +67,154 @@ class ArrayDyn extends ArrayAccess { array.setDyn(pos, value); } - override function blit( pos : Int, src : ArrayAccess, srcpos : Int, len : Int ) : Void { + override function blit(pos:Int, src:ArrayAccess, srcpos:Int, len:Int):Void { array.blit(pos, src, srcpos, len); } - public function concat( a : ArrayDyn ) : ArrayDyn { + public function concat(a:ArrayDyn):ArrayDyn { var a1 = array; var a2 = a.array; var alen = a1.length; var anew = new NativeArray(alen + a2.length); - for( i in 0...alen ) + for (i in 0...alen) anew[i] = a1.getDyn(i); - for( i in 0...a2.length ) - anew[i+alen] = a2.getDyn(i); - return alloc(ArrayObj.alloc(anew),true); + for (i in 0...a2.length) + anew[i + alen] = a2.getDyn(i); + return alloc(ArrayObj.alloc(anew), true); } - public function join( sep : String ) : String { + public function join(sep:String):String { return array.join(sep); } - public function pop() : Null { + public function pop():Null { return array.popDyn(); } - public function push(x : Dynamic) : Int { + public function push(x:Dynamic):Int { return array.pushDyn(x); } - public function reverse() : Void { + public function reverse():Void { array.reverse(); } - public function shift() : Null { + public function resize(len:Int) { + array.resize(len); + } + + public function shift():Null { return array.shiftDyn(); } - public function slice( pos : Int, ?end : Int ) : ArrayDyn { - return alloc(array.slice(pos,end),true); + public function slice(pos:Int, ?end:Int):ArrayDyn { + return alloc(array.slice(pos, end), true); } - public function sort( f : Dynamic -> Dynamic -> Int ) : Void { + public function sort(f:Dynamic->Dynamic->Int):Void { array.sortDyn(f); } - public function splice( pos : Int, len : Int ) : ArrayDyn { - return alloc(array.splice(pos,len),true); + public function splice(pos:Int, len:Int):ArrayDyn { + return alloc(array.splice(pos, len), true); } - public function toString() : String { + public function toString():String { return array.toString(); } - public function unshift( x : Dynamic ) : Void { + public function unshift(x:Dynamic):Void { array.unshiftDyn(x); } - public function insert( pos : Int, x : Dynamic ) : Void { - array.insertDyn(pos,x); + public function insert(pos:Int, x:Dynamic):Void { + array.insertDyn(pos, x); } - public function remove( x : Dynamic ) : Bool { + public function remove(x:Dynamic):Bool { return array.removeDyn(x); } - public function indexOf( x : Dynamic, ?fromIndex:Int ) : Int { - var i : Int = fromIndex; + public function indexOf(x:Dynamic, ?fromIndex:Int):Int { + var i:Int = fromIndex; var length = length; var array = array; - while( i < length ) { - if( array.getDyn(i) == x ) + while (i < length) { + if (array.getDyn(i) == x) return i; i++; } return -1; } - public function lastIndexOf( x : Dynamic, ?fromIndex:Int ) : Int { + public function lastIndexOf(x:Dynamic, ?fromIndex:Int):Int { var len = length; var i:Int = fromIndex != null ? fromIndex : len - 1; - if( i >= len ) + if (i >= len) i = len - 1; - else if( i < 0 ) + else if (i < 0) i += len; - while( i >= 0 ) { - if( array.getDyn(i) == x ) + while (i >= 0) { + if (array.getDyn(i) == x) return i; i--; } return -1; } - public function copy() : ArrayDyn { + public function copy():ArrayDyn { var a = new NativeArray(length); - for( i in 0...length ) + for (i in 0...length) a[i] = array.getDyn(i); - return alloc(ArrayObj.alloc(a),true); + return alloc(ArrayObj.alloc(a), true); } - public function iterator() : Iterator { + public function iterator():Iterator { return new ArrayDynIterator(array); } - public function map( f : Dynamic -> Dynamic ) : ArrayDyn { + public function map(f:Dynamic->Dynamic):ArrayDyn { var a = new NativeArray(length); - for( i in 0...length ) + for (i in 0...length) a[i] = f(array.getDyn(i)); - return alloc(ArrayObj.alloc(a),true); + return alloc(ArrayObj.alloc(a), true); } - public function filter( f : Dynamic -> Bool ) : ArrayDyn { + public function filter(f:Dynamic->Bool):ArrayDyn { var a = new ArrayObj(); - for( i in 0...length ) { + for (i in 0...length) { var v = array.getDyn(i); - if( f(v) ) a.push(v); + if (f(v)) + a.push(v); } - return alloc(a,true); + return alloc(a, true); } - function __get_field( fid : Int ) : Dynamic { - if( fid == untyped $hash("length") ) + function __get_field(fid:Int):Dynamic { + if (fid == untyped $hash("length")) return length; return null; } - function __cast( t : Type ) : Dynamic { - if( t == Type.getDynamic(array) ) + function __cast(t:Type):Dynamic { + if (t == Type.getDynamic(array)) return array; - if( !allowReinterpret ) + if (!allowReinterpret) return null; - if( t == Type.get(new ArrayBytes.ArrayI32()) ) { - var a : BytesAccess = null; + if (t == Type.get((null : ArrayBytes.ArrayI32))) { + var a:BytesAccess = null; a = new Bytes(array.length << a.sizeBits); - for( i in 0...array.length ) + for (i in 0...array.length) a[i] = array.getDyn(i); var arr = ArrayBase.allocI32(a, array.length); array = arr; allowReinterpret = false; return arr; } - if( t == Type.get(new ArrayBytes.ArrayF64()) ) { - var a : BytesAccess = null; + if (t == Type.get((null : ArrayBytes.ArrayF64))) { + var a:BytesAccess = null; a = new Bytes(array.length << a.sizeBits); - for( i in 0...array.length ) + for (i in 0...array.length) a[i] = array.getDyn(i); var arr = ArrayBase.allocF64(a, array.length); array = arr; @@ -213,11 +224,14 @@ class ArrayDyn extends ArrayAccess { return null; } - public static function alloc( a : ArrayBase, allowReinterpret = false ) : ArrayDyn { - var arr : ArrayDyn = untyped $new(ArrayDyn); + @:keep function __compare(a:Dynamic):Int { + return a == array ? 0 : hl.Api.comparePointer(this, a); + } + + public static function alloc(a:ArrayBase, allowReinterpret = false):ArrayDyn { + var arr:ArrayDyn = untyped $new(ArrayDyn); arr.array = a; arr.allowReinterpret = allowReinterpret; return arr; } - } diff --git a/std/hl/types/ArrayObj.hx b/std/hl/types/ArrayObj.hx index de36c3ebdc6..ce36921741d 100644 --- a/std/hl/types/ArrayObj.hx +++ b/std/hl/types/ArrayObj.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,29 +19,30 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl.types; @:keep class ArrayObj extends ArrayBase { - - var array : hl.NativeArray; + var array:hl.NativeArray; public function new() { length = 0; array = new NativeArray(0); } - public function concat( a : ArrayObj ) : ArrayObj { + public function concat(a:ArrayObj):ArrayObj { var arr = new hl.NativeArray(length + a.length); arr.blit(0, array, 0, length); arr.blit(length, a.array, 0, a.length); return alloc(cast arr); } - override function join( sep : String ) : String { + override function join(sep:String):String { var b = new StringBuf(); - for( i in 0...length ) { - if( i > 0 ) b.add(sep); + for (i in 0...length) { + if (i > 0) + b.add(sep); b.add(array[i]); } return b.toString(); @@ -51,8 +52,8 @@ class ArrayObj extends ArrayBase { return true; } - public function pop() : Null { - if( length == 0 ) + public function pop():Null { + if (length == 0) return null; length--; var v = array[length]; @@ -60,9 +61,9 @@ class ArrayObj extends ArrayBase { return v; } - public function push(x : T) : Int { + public function push(x:T):Int { var len = length; - if( array.length == len ) + if (array.length == len) __expand(len); else length++; @@ -70,8 +71,8 @@ class ArrayObj extends ArrayBase { return length; } - override function reverse() : Void { - for( i in 0...length >> 1 ) { + override function reverse():Void { + for (i in 0...length >> 1) { var k = length - 1 - i; var tmp = array[i]; array[i] = array[k]; @@ -79,8 +80,8 @@ class ArrayObj extends ArrayBase { } } - public function shift() : Null { - if( length == 0 ) + public function shift():Null { + if (length == 0) return null; length--; var v = array[0]; @@ -89,200 +90,252 @@ class ArrayObj extends ArrayBase { return v; } - override function slice( pos : Int, ?end : Int ) : ArrayObj { - if( pos < 0 ) { + override function slice(pos:Int, ?end:Int):ArrayObj { + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) + if (pos < 0) pos = 0; } - var pend : Int; - if( end == null ) + var pend:Int; + if (end == null) pend = this.length; else { pend = end; - if( pend < 0 ) + if (pend < 0) pend += this.length; - if( pend > this.length ) + if (pend > this.length) pend = this.length; } var len = pend - pos; - if( len < 0 ) + if (len < 0) return new ArrayObj(); - return alloc(array.sub(pos,len)); + return alloc(array.sub(pos, len)); } - public function sort( f : T -> T -> Int ) : Void { + public function sort(f:T->T->Int):Void { // TODO : use native call ? haxe.ds.ArraySort.sort(cast this, f); } - override function splice( pos : Int, len : Int ) : ArrayObj { - if( len < 0 ) return new ArrayObj(); - if( pos < 0 ){ + override function splice(pos:Int, len:Int):ArrayObj { + if (len < 0) + return new ArrayObj(); + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) pos = 0; + if (pos < 0) + pos = 0; } - if( pos > this.length ) { + if (pos > this.length) { pos = 0; len = 0; - } else if( pos + len > this.length ) { + } else if (pos + len > this.length) { len = this.length - pos; - if( len < 0 ) len = 0; + if (len < 0) + len = 0; } var a = this.array; - var ret : ArrayObj = alloc(cast a.sub(pos,len)); + var ret:ArrayObj = alloc(cast a.sub(pos, len)); var end = pos + len; - a.blit(pos,a,end,this.length-end); + a.blit(pos, a, end, this.length - end); this.length -= len; - while( --len >= 0 ) + while (--len >= 0) a[this.length + len] = null; return ret; } - override function toString() : String { + @:access(Std.toStringDepth) + override function toString():String { + if (Std.toStringDepth >= 5) + return "..."; + Std.toStringDepth++; var b = new StringBuf(); b.addChar("[".code); - for( i in 0...length ) { - if( i > 0 ) b.addChar(",".code); - b.add(array[i]); + try { + for (i in 0...length) { + if (i > 0) + b.addChar(",".code); + b.add(array[i]); + } + } catch (e:Dynamic) { + Std.toStringDepth--; + hl.Api.rethrow(e); } b.addChar("]".code); + Std.toStringDepth--; return b.toString(); } - public function unshift( x : T ) : Void { - if( length == array.length ) __expand(length) else length++; + public function unshift(x:T):Void { + if (length == array.length) + __expand(length) + else + length++; array.blit(1, array, 0, length - 1); array[0] = x; } - public function insert( pos : Int, x : T ) : Void { - if( pos < 0 ) { + public function insert(pos:Int, x:T):Void { + if (pos < 0) { pos = length + pos; - if( pos < 0 ) pos = 0; - } else if( pos > length ) pos = length; - if( length == array.length ) __expand(length) else length++; + if (pos < 0) + pos = 0; + } else if (pos > length) + pos = length; + if (length == array.length) + __expand(length) + else + length++; array.blit(pos + 1, array, pos, length - pos - 1); array[pos] = x; } - public function remove( x : T ) : Bool { + public function remove(x:T):Bool { var i = indexOf(x); - if( i < 0 ) return false; + if (i < 0) + return false; length--; - array.blit(i,array,i+1,length - i); + array.blit(i, array, i + 1, length - i); array[length] = null; return true; } - public function indexOf( x : T, ?fromIndex:Int ) : Int { - var i : Int = fromIndex; - if( i < 0 ) { + public function indexOf(x:T, ?fromIndex:Int):Int { + var i:Int = fromIndex; + if (i < 0) { i += length; - if( i < 0 ) i = 0; + if (i < 0) + i = 0; } var length = length; var array = array; - while( i < length ) { - if( array[i] == x ) + while (i < length) { + if (array[i] == x) return i; i++; } return -1; } - override function blit( pos : Int, src : ArrayBase.ArrayAccess, srcpos : Int, len : Int ) : Void { + override function blit(pos:Int, src:ArrayBase.ArrayAccess, srcpos:Int, len:Int):Void { var src = (cast src : ArrayObj); - if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) throw haxe.io.Error.OutsideBounds; + if (pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length) + throw haxe.io.Error.OutsideBounds; array.blit(pos, src.array, srcpos, len); } - public function lastIndexOf( x : T, ?fromIndex:Int ) : Int { + public function lastIndexOf(x:T, ?fromIndex:Int):Int { var len = length; var i:Int = fromIndex != null ? fromIndex : len - 1; - if( i >= len ) + if (i >= len) i = len - 1; - else if( i < 0 ) + else if (i < 0) i += len; - while( i >= 0 ) { - if( array[i] == x ) + while (i >= 0) { + if (array[i] == x) return i; i--; } return -1; } - public function copy() : ArrayObj { + public function copy():ArrayObj { var n = new NativeArray(length); n.blit(0, array, 0, length); return alloc(n); } - public function iterator() : Iterator { + public function iterator():Iterator { var n = new NativeArray.NativeArrayIterator(cast array); @:privateAccess n.length = length; return n; } - public function map( f : T -> S ) : ArrayDyn { + public function map(f:T->S):ArrayDyn { var a = new ArrayObj(); - if( length > 0 ) a.__expand(length - 1); - for( i in 0...length ) + if (length > 0) + a.__expand(length - 1); + for (i in 0...length) a.array[i] = f(array[i]); - return ArrayDyn.alloc(a,true); + return ArrayDyn.alloc(a, true); } - public function filter( f : T -> Bool ) : ArrayObj { + public function filter(f:T->Bool):ArrayObj { var a = new ArrayObj(); - for( i in 0...length ) { + for (i in 0...length) { var v = array[i]; - if( f(v) ) a.push(v); + if (f(v)) + a.push(v); } return a; } + override public function resize(len:Int):Void { + if (length < len) { + __expand(len - 1); + } else if (length > len) { + for (i in length...len) { + array[i] = null; + } + this.length = len; + } + } + // called by compiler when accessing the array outside of its bounds, might trigger resize - function __expand( index : Int ) { - if( index < 0 ) throw "Invalid array index " + index; + function __expand(index:Int) { + if (index < 0) + throw "Invalid array index " + index; var newlen = index + 1; - var size : Int = array.length; - if( newlen > size ) { + var size:Int = array.length; + if (newlen > size) { var next = (size * 3) >> 1; - if( next < newlen ) next = newlen; + if (next < newlen) + next = newlen; var arr2 = new hl.NativeArray(next); - arr2.blit(0,array,0,length); + arr2.blit(0, array, 0, length); array = arr2; } length = newlen; } - override function getDyn( pos : Int ) : Dynamic { - var pos : UInt = pos; - if( pos >= length ) + override function getDyn(pos:Int):Dynamic { + var pos:UInt = pos; + if (pos >= length) return null; return array[pos]; } - override function setDyn( pos : Int, v : Dynamic ) { - var pos : UInt = pos; - if( pos >= length ) + override function setDyn(pos:Int, v:Dynamic) { + var pos:UInt = pos; + if (pos >= length) __expand(pos); - array[pos] = Api.safeCast(v,array.getType()); + array[pos] = Api.safeCast(v, array.getType()); } - override function pushDyn( v : Dynamic ) return push(v); - override function popDyn() : Null return pop(); - override function shiftDyn() : Null return shift(); - override function unshiftDyn( v : Dynamic ) unshift(v); - override function insertDyn( pos : Int, v : Dynamic ) insert(pos, v); - override function removeDyn( v : Dynamic ) return remove(v); - override function sortDyn( f : Dynamic -> Dynamic -> Int ) sort(f); + override function pushDyn(v:Dynamic) + return push(v); + + override function popDyn():Null + return pop(); + + override function shiftDyn():Null + return shift(); - public static function alloc( a : hl.NativeArray ) : ArrayObj { - var arr : ArrayObj = untyped $new(ArrayObj); + override function unshiftDyn(v:Dynamic) + unshift(v); + + override function insertDyn(pos:Int, v:Dynamic) + insert(pos, v); + + override function removeDyn(v:Dynamic) + return remove(v); + + override function sortDyn(f:Dynamic->Dynamic->Int) + sort(f); + + public static function alloc(a:hl.NativeArray):ArrayObj { + var arr:ArrayObj = untyped $new(ArrayObj); arr.array = a; arr.length = a.length; return arr; } - } diff --git a/std/hl/types/BytesMap.hx b/std/hl/types/BytesMap.hx index ea947d91d89..5c739b8d952 100644 --- a/std/hl/types/BytesMap.hx +++ b/std/hl/types/BytesMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,51 +19,49 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl.types; typedef BytesMapData = Abstract<"hl_bytes_map">; abstract BytesMap(BytesMapData) { - - @:extern public inline function new() { + extern public inline function new() { this = alloc(); } - @:hlNative("std","hballoc") static function alloc() : BytesMapData { + @:hlNative("std", "hballoc") static function alloc():BytesMapData { return null; } - @:hlNative("std","hbset") - public function set( key : Bytes, value : Dynamic ) { - } + @:hlNative("std", "hbset") + public function set(key:Bytes, value:Dynamic) {} - @:hlNative("std","hbexists") - public function exists( key : Bytes ) : Bool { + @:hlNative("std", "hbexists") + public function exists(key:Bytes):Bool { return false; } - @:hlNative("std","hbget") - public function get( key : Bytes ) : Dynamic { + @:hlNative("std", "hbget") + public function get(key:Bytes):Dynamic { return null; } - @:hlNative("std","hbremove") - public function remove( key : Bytes ) : Bool { + @:hlNative("std", "hbremove") + public function remove(key:Bytes):Bool { return false; } - @:hlNative("std","hbkeys") - public function keysArray() : NativeArray { + @:hlNative("std", "hbkeys") + public function keysArray():NativeArray { return null; } - @:hlNative("std","hbvalues") - public function valuesArray() : NativeArray { + @:hlNative("std", "hbvalues") + public function valuesArray():NativeArray { return null; } - @:extern public inline function iterator() { + extern public inline function iterator() { return new NativeArray.NativeArrayIterator(valuesArray()); } - -} \ No newline at end of file +} diff --git a/std/hl/types/IntMap.hx b/std/hl/types/IntMap.hx index f07674a428c..1db60ca1d88 100644 --- a/std/hl/types/IntMap.hx +++ b/std/hl/types/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,51 +19,49 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl.types; typedef IntMapData = Abstract<"hl_int_map">; abstract IntMap(IntMapData) { - - @:extern public inline function new() { + extern public inline function new() { this = alloc(); } - @:hlNative("std","hialloc") static function alloc() : IntMapData { + @:hlNative("std", "hialloc") static function alloc():IntMapData { return null; } - @:hlNative("std","hiset") - public function set( key : Int, value : Dynamic ) { - } + @:hlNative("std", "hiset") + public function set(key:Int, value:Dynamic) {} - @:hlNative("std","hiexists") - public function exists( key : Int ) : Bool { + @:hlNative("std", "hiexists") + public function exists(key:Int):Bool { return false; } - @:hlNative("std","higet") - public function get( key : Int ) : Dynamic { + @:hlNative("std", "higet") + public function get(key:Int):Dynamic { return null; } - @:hlNative("std","hiremove") - public function remove( key : Int ) : Bool { + @:hlNative("std", "hiremove") + public function remove(key:Int):Bool { return false; } - @:hlNative("std","hikeys") - public function keysArray() : NativeArray { + @:hlNative("std", "hikeys") + public function keysArray():NativeArray { return null; } - @:hlNative("std","hivalues") - public function valuesArray() : NativeArray { + @:hlNative("std", "hivalues") + public function valuesArray():NativeArray { return null; } - @:extern public inline function iterator() { + extern public inline function iterator() { return new NativeArray.NativeArrayIterator(valuesArray()); } - -} \ No newline at end of file +} diff --git a/std/hl/types/ObjectMap.hx b/std/hl/types/ObjectMap.hx index 5a342fba14d..dbf311e63ee 100644 --- a/std/hl/types/ObjectMap.hx +++ b/std/hl/types/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,51 +19,49 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package hl.types; typedef ObjectMapData = Abstract<"hl_obj_map">; abstract ObjectMap(ObjectMapData) { - - @:extern public inline function new() { + extern public inline function new() { this = alloc(); } - @:hlNative("std","hoalloc") static function alloc() : ObjectMapData { + @:hlNative("std", "hoalloc") static function alloc():ObjectMapData { return null; } - @:hlNative("std","hoset") - public function set( key : Dynamic, value : Dynamic ) { - } + @:hlNative("std", "hoset") + public function set(key:Dynamic, value:Dynamic) {} - @:hlNative("std","hoexists") - public function exists( key : Dynamic ) : Bool { + @:hlNative("std", "hoexists") + public function exists(key:Dynamic):Bool { return false; } - @:hlNative("std","hoget") - public function get( key : Dynamic ) : Dynamic { + @:hlNative("std", "hoget") + public function get(key:Dynamic):Dynamic { return null; } - @:hlNative("std","horemove") - public function remove( key : Dynamic ) : Bool { + @:hlNative("std", "horemove") + public function remove(key:Dynamic):Bool { return false; } - @:hlNative("std","hokeys") - public function keysArray() : NativeArray { + @:hlNative("std", "hokeys") + public function keysArray():NativeArray { return null; } - @:hlNative("std","hovalues") - public function valuesArray() : NativeArray { + @:hlNative("std", "hovalues") + public function valuesArray():NativeArray { return null; } - @:extern public inline function iterator() { + extern public inline function iterator() { return new NativeArray.NativeArrayIterator(valuesArray()); } - -} \ No newline at end of file +} diff --git a/std/hl/uv/Handle.hx b/std/hl/uv/Handle.hx index a0adb599423..0d1d3078583 100644 --- a/std/hl/uv/Handle.hx +++ b/std/hl/uv/Handle.hx @@ -1,19 +1,40 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package hl.uv; @:hlNative("uv") class Handle { - public var handle : HandleData; + public var handle:HandleData; function new(h) { handle = h; } - public function close( ?callb ) { - if( handle != null ) close_handle(handle, callb); + public function close(?callb) { + if (handle != null) + close_handle(handle, callb); handle = null; } - static function close_handle( h : HandleData, callb : Void->Void ) : Void { - } - + static function close_handle(h:HandleData, callb:Void->Void):Void {} } diff --git a/std/hl/uv/HandleData.hx b/std/hl/uv/HandleData.hx index 9bf3a035cc9..020970f3675 100644 --- a/std/hl/uv/HandleData.hx +++ b/std/hl/uv/HandleData.hx @@ -1,3 +1,25 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package hl.uv; typedef HandleData = hl.Abstract<"uv_handle">; diff --git a/std/hl/uv/Loop.hx b/std/hl/uv/Loop.hx index fdb288daaff..4276c33b1d8 100644 --- a/std/hl/uv/Loop.hx +++ b/std/hl/uv/Loop.hx @@ -1,43 +1,64 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package hl.uv; -@:enum abstract LoopRunMode(Int) { +enum abstract LoopRunMode(Int) { var Default = 0; var Once = 1; var NoWait = 2; } abstract Loop(hl.Abstract<"uv_loop">) { - - @:hlNative("uv","loop_close") public function close() : Int { + @:hlNative("uv", "loop_close") public function close():Int { return 0; } - @:hlNative("uv","run") public function run( mode : LoopRunMode ) : Int { + @:hlNative("uv", "run") public function run(mode:LoopRunMode):Int { return 0; } - @:hlNative("uv","loop_alive") public function alive() : Int { + @:hlNative("uv", "loop_alive") public function alive():Int { return 0; } - @:hlNative("uv","stop") public function stop() : Void { - } + @:hlNative("uv", "stop") public function stop():Void {} - @:hlNative("uv","default_loop") - public static function getDefault() : Loop { - return null; + public static function getDefault():Loop { + var def = default_loop(); + if (loopEvent == null) + loopEvent = haxe.MainLoop.add(function() { + // if no more things to process, stop + if (def.run(NoWait) == 0) { + loopEvent.stop(); + loopEvent = null; + } + }); + return def; } - /** - Register the default loop into the main haxe loop. - Should be called at least once unless you want to integrate the loop update yourself. - **/ - public static function register() { - if( initDone ) return; - initDone = true; - var def = getDefault(); - haxe.MainLoop.add(function() def.run(NoWait)); + @:hlNative("uv", "default_loop") static function default_loop():Loop { + return null; } - static var initDone = false; + static var loopEvent:haxe.MainLoop.MainEvent; } diff --git a/std/hl/uv/Stream.hx b/std/hl/uv/Stream.hx index 84772904799..5a96fd0bdcf 100644 --- a/std/hl/uv/Stream.hx +++ b/std/hl/uv/Stream.hx @@ -1,45 +1,70 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package hl.uv; @:hlNative("uv") class Stream extends Handle { - - public function write( bytes : haxe.io.Bytes, ?onWrite : Bool -> Void, pos = 0, len = -1 ) { - if( len < 0 ) len = bytes.length - pos; - if( pos < 0 || len < 0 || pos+len > bytes.length ) throw haxe.io.Error.OutsideBounds; - if( handle == null || !stream_write(handle, (bytes : hl.Bytes).offset(pos), len, onWrite) ) throw new haxe.io.Eof(); + public function write(bytes:haxe.io.Bytes, ?onWrite:Bool->Void, pos = 0, len = -1) { + if (len < 0) + len = bytes.length - pos; + if (pos < 0 || len < 0 || pos + len > bytes.length) + throw haxe.io.Error.OutsideBounds; + if (handle == null || !stream_write(handle, (bytes : hl.Bytes).offset(pos), len, onWrite)) + throw new haxe.io.Eof(); } - public function readStartRaw( onData : hl.Bytes -> Int -> Void ) { - if( handle == null || !stream_read_start(handle, onData) ) throw new haxe.io.Eof(); + public function readStartRaw(onData:hl.Bytes->Int->Void) { + if (handle == null || !stream_read_start(handle, onData)) + throw new haxe.io.Eof(); } - public function readStart( onData : haxe.io.Bytes -> Void ) { - readStartRaw(function(b, len) onData(if( len < 0 ) null else b.toBytes(len))); + public function readStart(onData:haxe.io.Bytes->Void) { + readStartRaw(function(b, len) onData(if (len < 0) null else b.toBytes(len))); } public function readStop() { - if( handle != null ) stream_read_stop(handle); + if (handle != null) + stream_read_stop(handle); } - public function listen( n : Int, onConnect : Void -> Void ) { - if( handle == null || !stream_listen(handle, n, onConnect) ) throw new haxe.io.Eof(); + public function listen(n:Int, onConnect:Void->Void) { + if (handle == null || !stream_listen(handle, n, onConnect)) + throw new haxe.io.Eof(); } // -- - static function stream_write( handle : HandleData, bytes: hl.Bytes, len : Int, callb : Bool -> Void ) : Bool { + static function stream_write(handle:HandleData, bytes:hl.Bytes, len:Int, callb:Bool->Void):Bool { return false; } - static function stream_read_start( handle : HandleData, callb : hl.Bytes -> Int -> Void ) { + static function stream_read_start(handle:HandleData, callb:hl.Bytes->Int->Void) { return false; } - static function stream_read_stop( handle : HandleData ) { - } + static function stream_read_stop(handle:HandleData) {} - static function stream_listen( handle : HandleData, n : Int, callb : Void -> Void ) { + static function stream_listen(handle:HandleData, n:Int, callb:Void->Void) { return false; } - -} \ No newline at end of file +} diff --git a/std/hl/uv/Tcp.hx b/std/hl/uv/Tcp.hx index 30e42486288..34ba038c38c 100644 --- a/std/hl/uv/Tcp.hx +++ b/std/hl/uv/Tcp.hx @@ -1,43 +1,72 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + package hl.uv; @:hlNative("uv") class Tcp extends Stream { - - public function new( ?loop : Loop ) { - if( loop == null ) loop = Loop.getDefault(); + public function new(?loop:Loop) { + if (loop == null) + loop = Loop.getDefault(); super(tcp_init_wrap(loop)); } - public function connect( host : sys.net.Host, port : Int, onConnected : Bool -> Void ) { + public function connect(host:sys.net.Host, port:Int, onConnected:Bool->Void) { var h = tcp_connect_wrap(handle, host.ip, port, onConnected); - if( h == null ) throw haxe.io.Error.Custom("Failed to connect to "+host+":"+port); + if (h == null) + throw haxe.io.Error.Custom("Failed to connect to " + host + ":" + port); } - public function bind( host : sys.net.Host, port : Int ) { - if( !tcp_bind_wrap(handle, host.ip, port) ) - throw haxe.io.Error.Custom("Failed to bind socket to "+host+":"+port); + public function bind(host:sys.net.Host, port:Int) { + if (!tcp_bind_wrap(handle, host.ip, port)) + throw haxe.io.Error.Custom("Failed to bind socket to " + host + ":" + port); } public function accept() { var client = handle == null ? null : tcp_accept_wrap(handle); - if( client == null ) throw new haxe.io.Eof(); + if (client == null) + throw new haxe.io.Eof(); return new Stream(client); } - static function tcp_init_wrap( loop : Loop ) : HandleData { + public function noDelay(b:Bool) { + tcp_nodelay_wrap(handle, b); + } + + static function tcp_init_wrap(loop:Loop):HandleData { return null; } - static function tcp_connect_wrap( h : HandleData, host : Int, port : Int, onConnected : Bool -> Void ) : HandleData { + static function tcp_connect_wrap(h:HandleData, host:Int, port:Int, onConnected:Bool->Void):HandleData { return null; } - static function tcp_bind_wrap( h : HandleData, host : Int, port : Int ) : Bool { + static function tcp_bind_wrap(h:HandleData, host:Int, port:Int):Bool { return false; } - static function tcp_accept_wrap( h : HandleData ) : HandleData { + static function tcp_accept_wrap(h:HandleData):HandleData { return null; } -} \ No newline at end of file + static function tcp_nodelay_wrap(h:HandleData, b:Bool):Void {} +} diff --git a/std/java/Boot.hx b/std/java/Boot.hx index e2fb385575a..6e641eb5212 100644 --- a/std/java/Boot.hx +++ b/std/java/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java; + import java.internal.Exceptions; import java.internal.Function; import java.internal.HxObject; import java.internal.Runtime; import java.Lib; -//import java.internal.StringExt; +import java.Init; +// import java.internal.StringExt; import java.StdTypes; import Reflect; import Map; @@ -45,9 +48,4 @@ import java.internal.StringExt; import java.internal.FieldLookup; @:dox(hide) -extern class Boot -{ - - - -} +extern class Boot {} diff --git a/std/java/Init.hx b/std/java/Init.hx new file mode 100644 index 00000000000..5483b16cdbe --- /dev/null +++ b/std/java/Init.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +package java; + +@:native("haxe.java.Init") @:keep class Init { + public static function init():Void { + try { + java.lang.System.setOut(new java.io.PrintStream(java.lang.System.out, true, "utf-8")); + java.lang.System.setErr(new java.io.PrintStream(java.lang.System.err, true, "utf-8")); + } catch (e:java.io.UnsupportedEncodingException) {} + } +} diff --git a/std/java/Lib.hx b/std/java/Lib.hx index 384bf646532..88e7e2b3d21 100644 --- a/std/java/Lib.hx +++ b/std/java/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,27 +19,26 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java; /** Platform-specific Java Library. Provides some platform-specific functions for the Java target, such as conversion from Haxe types to native types and vice-versa. **/ -//we cannot use the java package for custom classes, so we're redefining it as "haxe.java.Lib" -@:native('haxe.java.Lib') class Lib -{ - +// we cannot use the java package for custom classes, so we're redefining it as "haxe.java.Lib" +@:native('haxe.java.Lib') class Lib { /** Print the specified value on the default output. **/ - inline public static function print( v : Dynamic ) : Void { + inline public static function print(v:Dynamic):Void { Sys.print(v); } /** Print the specified value on the default output followed by a newline character. **/ - inline public static function println( v : Dynamic ) : Void { + inline public static function println(v:Dynamic):Void { Sys.println(v); } @@ -49,11 +48,9 @@ package java; If `equalLengthRequired` is true, the result might be a copy of an array with the correct size. **/ - inline public static function nativeArray(arr:Array, equalLengthRequired:Bool):NativeArray - { + inline public static function nativeArray(arr:Array, equalLengthRequired:Bool):NativeArray { var ret = new NativeArray(arr.length); - for (i in 0...arr.length) - { + for (i in 0...arr.length) { ret[i] = arr[i]; } return ret; @@ -64,40 +61,35 @@ package java; [deprecated] - use `getNativeType` instead **/ @:deprecated('The function `nativeType` is deprecated and will be removed in later versions. Please use `getNativeType` instead') - inline public static function nativeType(obj:T):java.lang.Class - { + inline public static function nativeType(obj:T):java.lang.Class { return untyped obj.getClass(); } /** Gets the native `java.lang.Class` from the supplied object. Will throw an exception in case of null being passed. **/ - inline public static function getNativeType(obj:T):java.lang.Class - { + inline public static function getNativeType(obj:T):java.lang.Class { return untyped obj.getClass(); } /** Returns a Class<> equivalent to the native java.lang.Class type. **/ - public static inline function fromNativeType(t:java.lang.Class):Class - { + public static inline function fromNativeType(t:java.lang.Class):Class { return untyped t; } /** Returns a java.lang.Class equivalent to the Haxe Class<> type. **/ - public static inline function toNativeType(cl:Class):java.lang.Class - { + public static inline function toNativeType(cl:Class):java.lang.Class { return untyped cl; } /** Returns a java.lang.Class equivalent to the Haxe Enum<> type. **/ - public static inline function toNativeEnum(cl:Enum):java.lang.Class - { + public static inline function toNativeEnum(cl:Enum):java.lang.Class { return untyped cl; } @@ -106,66 +98,54 @@ package java; Unless `copy` is true, it won't copy the contents of the native array, so unless any operation triggers an array resize, all changes made to the Haxe array will affect the native array argument. **/ - @:generic public static function array(native:java.NativeArray):Array - { + @:generic public static function array(native:java.NativeArray):Array { return untyped Array.ofNative(native); } - @:extern inline private static function doArray(native:java.NativeArray):Array - { + extern inline private static function doArray(native:java.NativeArray):Array { var ret:NativeArray = new NativeArray(native.length); - for (i in 0...native.length) - { + for (i in 0...native.length) { ret[i] = native[i]; } return untyped Array.ofNative(ret); } - public static function array_Int(native:java.NativeArray):Array - { + public static function array_Int(native:java.NativeArray):Array { return doArray(native); } - public static function array_Float(native:java.NativeArray):Array - { + public static function array_Float(native:java.NativeArray):Array { return doArray(native); } - public static function array_Bool(native:java.NativeArray):Array - { + public static function array_Bool(native:java.NativeArray):Array { return doArray(native); } - public static function array_java_Int8(native:java.NativeArray):Array - { + public static function array_java_Int8(native:java.NativeArray):Array { return doArray(native); } - public static function array_java_Int16(native:java.NativeArray):Array - { + public static function array_java_Int16(native:java.NativeArray):Array { return doArray(native); } - public static function array_java_Char16(native:java.NativeArray):Array - { + public static function array_java_Char16(native:java.NativeArray):Array { return doArray(native); } - public static function array_Single(native:java.NativeArray):Array - { + public static function array_Single(native:java.NativeArray):Array { return doArray(native); } - public static function array_haxe_Int64(native:java.NativeArray):Array - { + public static function array_haxe_Int64(native:java.NativeArray):Array { return doArray(native); } /** Allocates a new Haxe Array with a predetermined size **/ - public static function arrayAlloc(size:Int):Array - { + public static function arrayAlloc(size:Int):Array { return untyped Array.alloc(size); } @@ -177,8 +157,7 @@ package java; This method only exists at compile-time, so it can't be called via reflection. **/ - @:extern public static inline function lock(obj:Dynamic, block:T):Void - { + extern public static inline function lock(obj:Dynamic, block:T):Void { untyped __lock__(obj, block); } } diff --git a/std/java/NativeArray.hx b/std/java/NativeArray.hx index c427450ba43..6c9054db5f9 100644 --- a/std/java/NativeArray.hx +++ b/std/java/NativeArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java; import haxe.extern.Rest; @@ -26,8 +27,7 @@ import haxe.extern.Rest; /** Represents a java fixed-size Array (`T[]`) **/ -@:nativeGen extern class NativeArray implements ArrayAccess -{ +@:nativeGen extern class NativeArray implements ArrayAccess { /** Creates a new array with the specified elements. @@ -35,16 +35,16 @@ import haxe.extern.Rest; ```haxe var elements = NativeArray.make(1,2,3,4,5,6); ``` - **/ + **/ public static function make(elements:Rest):NativeArray; /** The length of the array - **/ + **/ public var length(default, null):Int; /** Allocates a new array with size `len` - **/ + **/ public function new(len:Int):Void; } diff --git a/std/java/NativeString.hx b/std/java/NativeString.hx new file mode 100644 index 00000000000..3cf50a5e6ce --- /dev/null +++ b/std/java/NativeString.hx @@ -0,0 +1,99 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package java; + +import haxe.Int64; +import haxe.extern.Rest; +import java.StdTypes.Int8; +import java.StdTypes.Char16; +import java.lang.CharSequence; +import java.util.Locale; + +@:native("java.lang.String") +extern class NativeString { + function charAt(index:Int):Char16; + function codePointAt(index:Int):Int; + function codePointBefore(index:Int):Int; + function codePointCount(beginIndex:Int, endIndex:Int):Int; + function compareTo(anotherString:String):Int; + function compareToIgnoreCase(str:String):Int; + function concat(str:String):String; + function contains(s:CharSequence):Bool; + @:overload function contentEquals(cs:CharSequence):Bool; + @:overload function contentEquals(sb:java.lang.StringBuffer):Bool; + @:overload static function copyValueOf(data:NativeArray):String; + @:overload static function copyValueOf(data:NativeArray, offset:Int, count:Int):String; + function endsWith(suffix:String):Bool; + function equals(anObject:Dynamic):Bool; + function equalsIgnoreCase(anotherString:String):Bool; + @:overload static function format(l:Locale, format:String, args:Rest):String; + @:overload static function format(format:String, args:Rest):String; + @:overload function getBytes():NativeArray; + @:overload function getBytes(charset:java.nio.charset.Charset):NativeArray; + @:deprecated @:overload function getBytes(srcBegin:Int, srcEnd:Int, dst:NativeArray, dstBegin:Int):Void; + @:overload function getBytes(charsetName:String):NativeArray; + function getChars(srcBegin:Int, srcEnd:Int, dst:NativeArray, dstBegin:Int):Void; + function hashCode():Int; + @:overload function indexOf(ch:Int):Int; + @:overload function indexOf(ch:Int, fromIndex:Int):Int; + @:overload function indexOf(str:String):Int; + @:overload function indexOf(str:String, fromIndex:Int):Int; + function intern():String; + function isEmpty():Bool; + @:overload function lastIndexOf(ch:Int):Int; + @:overload function lastIndexOf(ch:Int, fromIndex:Int):Int; + @:overload function lastIndexOf(str:String):Int; + @:overload function lastIndexOf(str:String, fromIndex:Int):Int; + function length():Int; + function matches(regex:String):Bool; + function offsetByCodePoints(index:Int, codePointOffset:Int):Int; + @:overload function regionMatches(ignoreCase:Bool, toffset:Int, other:String, ooffset:Int, len:Int):Bool; + @:overload function regionMatches(toffset:Int, other:String, ooffset:Int, len:Int):Bool; + @:overload function replace(oldChar:Char16, newChar:Char16):String; + @:overload function replace(target:CharSequence, replacement:CharSequence):String; + function replaceAll(regex:String, replacement:String):String; + function replaceFirst(regex:String, replacement:String):String; + @:overload function split(regex:String):NativeArray; + @:overload function split(regex:String, limit:Int):NativeArray; + @:overload function startsWith(prefix:String):Bool; + @:overload function startsWith(prefix:String, toffset:Int):Bool; + function subSequence(beginIndex:Int, endIndex:Int):CharSequence; + @:overload function substring(beginIndex:Int):String; + @:overload function substring(beginIndex:Int, endIndex:Int):String; + function toCharArray():NativeArray; + @:overload function toLowerCase():String; + @:overload function toLowerCase(locale:Locale):String; + function toString():String; + @:overload function toUpperCase():String; + @:overload function toUpperCase(locale:Locale):String; + function trim():String; + @:overload static function valueOf(b:Bool):String; + @:overload static function valueOf(c:Char16):String; + @:overload static function valueOf(data:NativeArray):String; + @:overload static function valueOf(data:NativeArray, offset:Int, count:Int):String; + @:overload static function valueOf(d:Float):String; + @:overload static function valueOf(f:String):String; + @:overload static function valueOf(i:Int):String; + @:overload static function valueOf(l:haxe.Int64):String; + @:overload static function valueOf(obj:java.lang.Object):String; +} diff --git a/std/java/StdTypes.hx b/std/java/StdTypes.hx index 8d39212e9c9..060571b9de0 100644 --- a/std/java/StdTypes.hx +++ b/std/java/StdTypes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,46 +19,75 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java; @:notNull @:runtimeValue @:coreType extern abstract Int8 from Int {} @:notNull @:runtimeValue @:coreType extern abstract Int16 from Int {} @:notNull @:runtimeValue @:coreType extern abstract Char16 from Int {} -@:notNull @:runtimeValue @:coreType extern abstract Int64 from Int from Float -{ - @:op(A+B) public static function addI(lhs:Int64, rhs:Int):Int64; - @:op(A+B) public static function add(lhs:Int64, rhs:Int64):Int64; - @:op(A*B) public static function mulI(lhs:Int64, rhs:Int):Int64; - @:op(A*B) public static function mul(lhs:Int64, rhs:Int64):Int64; - @:op(A%B) public static function modI(lhs:Int64, rhs:Int):Int64; - @:op(A%B) public static function mod(lhs:Int64, rhs:Int64):Int64; - @:op(A-B) public static function subI(lhs:Int64, rhs:Int):Int64; - @:op(A-B) public static function sub(lhs:Int64, rhs:Int64):Int64; - @:op(A/B) public static function divI(lhs:Int64, rhs:Int):Int64; - @:op(A/B) public static function div(lhs:Int64, rhs:Int64):Int64; - @:op(A|B) public static function orI(lhs:Int64, rhs:Int):Int64; - @:op(A|B) public static function or(lhs:Int64, rhs:Int64):Int64; - @:op(A^B) public static function xorI(lhs:Int64, rhs:Int):Int64; - @:op(A^B) public static function xor(lhs:Int64, rhs:Int64):Int64; - @:op(A&B) public static function andI(lhs:Int64, rhs:Int):Int64; - @:op(A&B) public static function and(lhs:Int64, rhs:Int64):Int64; - @:op(A<>B) public static function shrI(lhs:Int64, rhs:Int):Int64; - @:op(A>>B) public static function shr(lhs:Int64, rhs:Int64):Int64; - @:op(A>>>B) public static function ushrI(lhs:Int64, rhs:Int):Int64; - @:op(A>>>B) public static function ushr(lhs:Int64, rhs:Int64):Int64; - - @:op(A>B) public static function gt(lhs:Int64, rhs:Int64):Bool; - @:op(A>=B) public static function gte(lhs:Int64, rhs:Int64):Bool; - @:op(A> B) public static function shrI(lhs:Int64, rhs:Int):Int64; + + @:op(A >> B) public static function shr(lhs:Int64, rhs:Int64):Int64; + + @:op(A >>> B) public static function ushrI(lhs:Int64, rhs:Int):Int64; + + @:op(A >>> B) public static function ushr(lhs:Int64, rhs:Int64):Int64; + + @:op(A > B) public static function gt(lhs:Int64, rhs:Int64):Bool; + + @:op(A >= B) public static function gte(lhs:Int64, rhs:Int64):Bool; + + @:op(A < B) public static function lt(lhs:Int64, rhs:Int64):Bool; + + @:op(A <= B) public static function lte(lhs:Int64, rhs:Int64):Bool; @:op(~A) public static function bneg(t:Int64):Int64; + @:op(-A) public static function neg(t:Int64):Int64; @:op(++A) public static function preIncrement(t:Int64):Int64; + @:op(A++) public static function postIncrement(t:Int64):Int64; + @:op(--A) public static function preDecrement(t:Int64):Int64; + @:op(A--) public static function postDecrement(t:Int64):Int64; } diff --git a/std/java/_std/Array.hx b/std/java/_std/Array.hx index 2ae10a28225..12ed28a18b6 100644 --- a/std/java/_std/Array.hx +++ b/std/java/_std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import java.lang.System; import java.NativeArray; @@ -29,36 +30,48 @@ import java.NativeArray; this.length = _native.length; } ') -@:final @:coreApi class Array implements ArrayAccess { - - public var length(default,null) : Int; +@:coreApi final class Array implements ArrayAccess { + public var length(default, null):Int; private var __a:NativeArray; + @:skipReflection static var __hx_toString_depth = 0; + @:skipReflection static inline final __hx_defaultCapacity = 4; + @:functionCode(' return new Array(_native); ') - private static function ofNative(native:NativeArray):Array - { - return null; + private static function ofNative(native:NativeArray):Array { + var a = new Array(); + a.length = native.length; + a.__a = native; + return a; } @:functionCode(' return new Array((Y[]) ((java.lang.Object)new java.lang.Object[size])); ') - private static function alloc(size:Int):Array - { - return null; + private static function alloc(size:Int):Array { + var a = new Array(); + a.length = size; + a.__a = new java.NativeArray(size); + return a; } - public function new() : Void - { + #if jvm + function getNative():NativeArray { + var a = new NativeArray(length); + System.arraycopy(__a, 0, a, 0, length); + return a; + } + #end + + public function new():Void { this.length = 0; this.__a = new NativeArray(0); } - public function concat( a : Array ) : Array - { + public function concat(a:Array):Array { var length = length; var len = length + a.length; var retarr = new NativeArray(len); @@ -68,13 +81,11 @@ import java.NativeArray; return ofNative(retarr); } - private function concatNative( a : NativeArray ) : Void - { + private function concatNative(a:NativeArray):Void { var __a = __a; var length = length; var len = length + a.length; - if (__a.length >= len) - { + if (__a.length >= len) { System.arraycopy(a, 0, __a, length, length); } else { var newarr = new NativeArray(len); @@ -87,15 +98,13 @@ import java.NativeArray; this.length = len; } - public function join( sep : String ) : String - { + public function join(sep:String):String { var buf = new StringBuf(); var i = -1; var first = true; var length = length; - while (++i < length) - { + while (++i < length) { if (first) first = false; else @@ -106,12 +115,10 @@ import java.NativeArray; return buf.toString(); } - public function pop() : Null - { + public function pop():Null { var __a = __a; var length = length; - if (length > 0) - { + if (length > 0) { var val = __a[--length]; __a[length] = null; this.length = length; @@ -122,12 +129,10 @@ import java.NativeArray; } } - public function push(x : T) : Int - { + public function push(x:T):Int { var length = length; - if (length >= __a.length) - { - var newLen = (length << 1) + 1; + if (length >= __a.length) { + var newLen = length == 0 ? __hx_defaultCapacity : (length << 1); var newarr = new NativeArray(newLen); System.arraycopy(__a, 0, newarr, 0, __a.length); @@ -138,53 +143,50 @@ import java.NativeArray; return ++this.length; } - public function reverse() : Void - { + public function reverse():Void { var i = 0; var l = this.length; var a = this.__a; var half = l >> 1; l -= 1; - while ( i < half ) - { + while (i < half) { var tmp = a[i]; - a[i] = a[l-i]; - a[l-i] = tmp; + a[i] = a[l - i]; + a[l - i] = tmp; i += 1; } } - public function shift() : Null - { + public function shift():Null { var l = this.length; - if( l == 0 ) + if (l == 0) return null; var a = this.__a; var x = a[0]; l -= 1; - System.arraycopy(a, 1, a, 0, length-1); + System.arraycopy(a, 1, a, 0, length - 1); a[l] = null; this.length = l; return x; } - public function slice( pos : Int, ?end : Int ) : Array - { - if( pos < 0 ){ + public function slice(pos:Int, ?end:Int):Array { + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) + if (pos < 0) pos = 0; } - if( end == null ) + if (end == null) end = this.length; - else if( end < 0 ) + else if (end < 0) end = this.length + end; - if( end > this.length ) + if (end > this.length) end = this.length; var len = end - pos; - if ( len < 0 ) return new Array(); + if (len < 0) + return new Array(); var newarr = new NativeArray(len); System.arraycopy(__a, pos, newarr, 0, len); @@ -192,47 +194,49 @@ import java.NativeArray; return ofNative(newarr); } - public function sort( f : T -> T -> Int ) : Void - { + public function sort(f:T->T->Int):Void { if (length == 0) return; quicksort(0, length - 1, f); } - private function quicksort( lo : Int, hi : Int, f : T -> T -> Int ) : Void - { + private function quicksort(lo:Int, hi:Int, f:T->T->Int):Void { var buf = __a; var i = lo, j = hi; var p = buf[(i + j) >> 1]; - while ( i <= j ) - { - while ( i < hi && f(buf[i], p) < 0 ) i++; - while ( j > lo && f(buf[j], p) > 0 ) j--; - if ( i <= j ) - { + while (i <= j) { + while (i < hi && f(buf[i], p) < 0) + i++; + while (j > lo && f(buf[j], p) > 0) + j--; + if (i <= j) { var t = buf[i]; buf[i++] = buf[j]; buf[j--] = t; } } - if( lo < j ) quicksort( lo, j, f ); - if( i < hi ) quicksort( i, hi, f ); + if (lo < j) + quicksort(lo, j, f); + if (i < hi) + quicksort(i, hi, f); } - public function splice( pos : Int, len : Int ) : Array - { - if( len < 0 ) return new Array(); - if( pos < 0 ) { + public function splice(pos:Int, len:Int):Array { + if (len < 0) + return new Array(); + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) pos = 0; + if (pos < 0) + pos = 0; } - if( pos > this.length ) { + if (pos > this.length) { pos = 0; len = 0; - } else if( pos + len > this.length ) { + } else if (pos + len > this.length) { len = this.length - pos; - if( len < 0 ) len = 0; + if (len < 0) + len = 0; } var a = this.__a; @@ -243,42 +247,57 @@ import java.NativeArray; var end = pos + len; System.arraycopy(a, end, a, pos, this.length - end); this.length -= len; - while( --len >= 0 ) + while (--len >= 0) a[this.length + len] = null; return ret; } - private function spliceVoid( pos : Int, len : Int ) : Void - { - if( len < 0 ) return; - if( pos < 0 ) { + private function spliceVoid(pos:Int, len:Int):Void { + if (len < 0) + return; + if (pos < 0) { pos = this.length + pos; - if( pos < 0 ) pos = 0; + if (pos < 0) + pos = 0; } - if( pos > this.length ) { + if (pos > this.length) { pos = 0; len = 0; - } else if( pos + len > this.length ) { + } else if (pos + len > this.length) { len = this.length - pos; - if( len < 0 ) len = 0; + if (len < 0) + len = 0; } var a = this.__a; var end = pos + len; System.arraycopy(a, end, a, pos, this.length - end); this.length -= len; - while( --len >= 0 ) + while (--len >= 0) a[this.length + len] = null; } - public function toString() : String - { + public function toString():String { + if (__hx_toString_depth >= 5) { + return "..."; + } + ++__hx_toString_depth; + try { + var s = __hx_toString(); + --__hx_toString_depth; + return s; + } catch (e:Dynamic) { + --__hx_toString_depth; + throw(e); + } + } + + function __hx_toString():String { var ret = new StringBuf(); var a = __a; ret.add("["); var first = true; - for (i in 0...length) - { + for (i in 0...length) { if (first) first = false; else @@ -290,12 +309,10 @@ import java.NativeArray; return ret.toString(); } - public function unshift( x : T ) : Void - { + public function unshift(x:T):Void { var __a = __a; var length = length; - if (length >= __a.length) - { + if (length >= __a.length) { var newLen = (length << 1) + 1; var newarr = new NativeArray(newLen); System.arraycopy(__a, 0, newarr, 1, length); @@ -309,14 +326,14 @@ import java.NativeArray; ++this.length; } - public function insert( pos : Int, x : T ) : Void - { + public function insert(pos:Int, x:T):Void { var l = this.length; - if( pos < 0 ) { + if (pos < 0) { pos = l + pos; - if( pos < 0 ) pos = 0; + if (pos < 0) + pos = 0; } - if ( pos >= l ) { + if (pos >= l) { this.push(x); return; } else if (pos == 0) { @@ -324,8 +341,7 @@ import java.NativeArray; return; } - if (l >= __a.length) - { + if (l >= __a.length) { var newLen = (length << 1) + 1; var newarr = new NativeArray(newLen); System.arraycopy(__a, 0, newarr, 0, pos); @@ -343,15 +359,12 @@ import java.NativeArray; } } - public function remove( x : T ) : Bool - { + public function remove(x:T):Bool { var __a = __a; var i = -1; var length = length; - while (++i < length) - { - if (__a[i] == x) - { + while (++i < length) { + if (__a[i] == x) { System.arraycopy(__a, i + 1, __a, i, length - i - 1); __a[--this.length] = null; @@ -362,15 +375,14 @@ import java.NativeArray; return false; } - public function indexOf(x : T, ?fromIndex:Int) : Int { + public function indexOf(x:T, ?fromIndex:Int):Int { var len = length, a = __a, i:Int = (fromIndex == null) ? 0 : fromIndex; - if (i < 0) - { + if (i < 0) { i += len; - if (i < 0) i = 0; + if (i < 0) + i = 0; } - while (i < len) - { + while (i < len) { if (a[i] == x) return i; i++; @@ -378,14 +390,15 @@ import java.NativeArray; return -1; } - public function lastIndexOf(x : T, ?fromIndex:Int) : Int { - var len = length, a = __a, i:Int = (fromIndex == null) ? len - 1 : fromIndex; + public function lastIndexOf(x:T, ?fromIndex:Int):Int { + var len = length, + a = __a, + i:Int = (fromIndex == null) ? len - 1 : fromIndex; if (i >= len) i = len - 1; else if (i < 0) i += len; - while (i >= 0) - { + while (i >= 0) { if (a[i] == x) return i; i--; @@ -393,8 +406,7 @@ import java.NativeArray; return -1; } - public function copy() : Array - { + public function copy():Array { var len = length; var __a = __a; var newarr = new NativeArray(len); @@ -402,19 +414,32 @@ import java.NativeArray; return ofNative(newarr); } - public inline function iterator() : Iterator - { + public inline function iterator():Iterator { return new ArrayIterator(this); } - public inline function map( f : T -> S ) : Array { + public function resize(len:Int):Void { + if (length < len) { + if (__a.length < len) { + var newArr = new NativeArray(len); + if (length > 0) + System.arraycopy(__a, 0, newArr, 0, length); + this.__a = __a = newArr; + } + this.length = len; + } else if (length > len) { + spliceVoid(len, length - len); + } + } + + public inline function map(f:T->S):Array { var ret = alloc(length); for (i in 0...length) ret.__set(i, f(__get(i))); return ret; } - public inline function filter( f : T -> Bool ) : Array { + public inline function filter(f:T->Bool):Array { var ret = []; for (i in 0...length) { var elt = __get(i); @@ -424,8 +449,7 @@ import java.NativeArray; return ret; } - private function __get(idx:Int):T - { + private function __get(idx:Int):T { var __a = __a; if (idx >= __a.length || idx < 0) return null; @@ -433,11 +457,10 @@ import java.NativeArray; return __a[idx]; } - private function __set(idx:Int, v:T):T + private function __set(idx:Int, v:T):#if jvm Void #else T #end { var __a = __a; - if (idx >= __a.length) - { + if (idx >= __a.length) { var newl = idx + 1; if (idx == __a.length) newl = (idx << 1) + 1; @@ -450,34 +473,32 @@ import java.NativeArray; if (idx >= length) this.length = idx + 1; - return __a[idx] = v; + #if !jvm return #end __a[idx] = v; } - private inline function __unsafe_get(idx:Int):T - { + private inline function __unsafe_get(idx:Int):T { return __a[idx]; } - private inline function __unsafe_set(idx:Int, val:T):T - { + private inline function __unsafe_set(idx:Int, val:T):T { return __a[idx] = val; } } -@:final -private class ArrayIterator -{ +private final class ArrayIterator { var arr:Array; var len:Int; var i:Int; - public inline function new(a:Array) - { + public inline function new(a:Array) { arr = a; len = a.length; i = 0; } - public inline function hasNext():Bool return i < len; - public inline function next():T return arr[i++]; + public inline function hasNext():Bool + return i < len; + + public inline function next():T + return arr[i++]; } diff --git a/std/java/_std/Date.hx b/std/java/_std/Date.hx index 03609efc872..a1a42cc2bcc 100644 --- a/std/java/_std/Date.hx +++ b/std/java/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,106 +19,127 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package; + import haxe.Int64; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +@:coreApi class Date { + private var date:Calendar; + private var dateUTC:Calendar; + + public function new(year:Int, month:Int, day:Int, hour:Int, min:Int, sec:Int):Void { + date = new GregorianCalendar(year, month, day, hour, min, sec); + dateUTC = new GregorianCalendar(TimeZone.getTimeZone("UTC")); + dateUTC.setTimeInMillis(date.getTimeInMillis()); + } + + public inline function getTime():Float { + return cast date.getTimeInMillis(); + } + + public inline function getHours():Int { + return date.get(Calendar.HOUR_OF_DAY); + } -@:SuppressWarnings("deprecation") -@:coreApi class Date -{ - private var date:java.util.Date; + public inline function getMinutes():Int { + return date.get(Calendar.MINUTE); + } + + public inline function getSeconds():Int { + return date.get(Calendar.SECOND); + } + + public inline function getFullYear():Int { + return date.get(Calendar.YEAR); + } + + public inline function getMonth():Int { + return date.get(Calendar.MONTH); + } + + public inline function getDate():Int { + return date.get(Calendar.DAY_OF_MONTH); + } - public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void - { - //issue #1769 - year = year != 0 ? year - 1900 : 0; - date = new java.util.Date(year, month, day, hour, min, sec); + public inline function getDay():Int { + // SUNDAY in Java == 1, MONDAY == 2, ... + return cast date.get(Calendar.DAY_OF_WEEK) - 1; } - public inline function getTime() : Float - { - return cast date.getTime(); + public inline function getUTCHours():Int { + return dateUTC.get(Calendar.HOUR_OF_DAY); } - public inline function getHours() : Int - { - return date.getHours(); + public inline function getUTCMinutes():Int { + return dateUTC.get(Calendar.MINUTE); } - public inline function getMinutes() : Int - { - return date.getMinutes(); + public inline function getUTCSeconds():Int { + return dateUTC.get(Calendar.SECOND); } - public inline function getSeconds() : Int - { - return date.getSeconds(); + public inline function getUTCFullYear():Int { + return dateUTC.get(Calendar.YEAR); } - public inline function getFullYear() : Int - { - return date.getYear() + 1900; + public inline function getUTCMonth():Int { + return dateUTC.get(Calendar.MONTH); } - public inline function getMonth() : Int - { - return date.getMonth(); + public inline function getUTCDate():Int { + return dateUTC.get(Calendar.DAY_OF_MONTH); } - public inline function getDate() : Int - { - return date.getDate(); + public inline function getUTCDay():Int { + // SUNDAY in Java == 1, MONDAY == 2, ... + return cast dateUTC.get(Calendar.DAY_OF_WEEK) - 1; } - public inline function getDay() : Int - { - return date.getDay(); + public inline function getTimezoneOffset():Int { + return -Std.int(date.get(Calendar.ZONE_OFFSET) / 60000); } - public function toString():String - { - var m = date.getMonth() + 1; - var d = date.getDate(); - var h = date.getHours(); - var mi = date.getMinutes(); - var s = date.getSeconds(); - return (date.getYear() + 1900) - +"-"+(if( m < 10 ) "0"+m else ""+m) - +"-"+(if( d < 10 ) "0"+d else ""+d) - +" "+(if( h < 10 ) "0"+h else ""+h) - +":"+(if( mi < 10 ) "0"+mi else ""+mi) - +":"+(if( s < 10 ) "0"+s else ""+s); + public function toString():String { + var m = getMonth() + 1; + var d = getDate(); + var h = getHours(); + var mi = getMinutes(); + var s = getSeconds(); + return getFullYear() + "-" + (if (m < 10) "0" + m else "" + m) + "-" + (if (d < 10) "0" + d else "" + d) + " " + + (if (h < 10) "0" + h else "" + h) + ":" + (if (mi < 10) "0" + mi else "" + mi) + ":" + (if (s < 10) "0" + s else "" + s); } - static public function now() : Date - { + static public function now():Date { var d = new Date(0, 0, 0, 0, 0, 0); - d.date = new java.util.Date(); + d.date = Calendar.getInstance(); + d.dateUTC.setTimeInMillis(d.date.getTimeInMillis()); return d; } - static public function fromTime( t : Float ) : Date - { + static public function fromTime(t:Float):Date { var d = new Date(0, 0, 0, 0, 0, 0); - d.date = new java.util.Date(cast(t, Int64)); + d.date.setTimeInMillis(cast t); + d.dateUTC.setTimeInMillis(cast t); return d; } - static public function fromString( s : String ) : Date - { - switch( s.length ) - { + static public function fromString(s:String):Date { + switch (s.length) { case 8: // hh:mm:ss var k = s.split(":"); - var d : Date = new Date(0, 0, 0, Std.parseInt(k[0]), Std.parseInt(k[1]), Std.parseInt(k[2])); - return d; + return Date.fromTime(Std.parseInt(k[0]) * 3600000. + Std.parseInt(k[1]) * 60000. + Std.parseInt(k[2]) * 1000.); case 10: // YYYY-MM-DD var k = s.split("-"); - return new Date(Std.parseInt(k[0]),Std.parseInt(k[1]) - 1,Std.parseInt(k[2]),0,0,0); + return new Date(Std.parseInt(k[0]), Std.parseInt(k[1]) - 1, Std.parseInt(k[2]), 0, 0, 0); case 19: // YYYY-MM-DD hh:mm:ss var k = s.split(" "); var y = k[0].split("-"); var t = k[1].split(":"); - return new Date(Std.parseInt(y[0]),Std.parseInt(y[1]) - 1,Std.parseInt(y[2]),Std.parseInt(t[0]),Std.parseInt(t[1]),Std.parseInt(t[2])); + return new Date(Std.parseInt(y[0]), Std.parseInt(y[1]) - 1, Std.parseInt(y[2]), Std.parseInt(t[0]), Std.parseInt(t[1]), Std.parseInt(t[2])); default: throw "Invalid date format : " + s; } diff --git a/std/java/_std/EReg.hx b/std/java/_std/EReg.hx index 0639a7029bf..425e1b56f76 100644 --- a/std/java/_std/EReg.hx +++ b/std/java/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,19 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import java.util.regex.*; @:coreApi class EReg { - private var pattern:String; private var matcher:Matcher; private var cur:String; private var isGlobal:Bool; - public function new( r : String, opt : String ) { + public function new(r:String, opt:String) { var flags = 0; - for (i in 0...opt.length) - { - switch(StringTools.fastCodeAt(opt, i)) - { + for (i in 0...opt.length) { + switch (StringTools.fastCodeAt(opt, i)) { case 'i'.code: flags |= Pattern.CASE_INSENSITIVE; case 'm'.code: @@ -45,80 +43,78 @@ import java.util.regex.*; } } + flags |= Pattern.UNICODE_CASE; + #if !android // see https://github.com/HaxeFoundation/haxe/issues/7632 + flags |= Pattern.UNICODE_CHARACTER_CLASS; + #end matcher = Pattern.compile(convert(r), flags).matcher(""); pattern = r; } - private static function convert(r:String):String - { - //some references of the implementation: - //http://stackoverflow.com/questions/809647/java-vs-javascript-regex-problem - //http://stackoverflow.com/questions/4788413/how-to-convert-javascript-regex-to-safe-java-regex - //Some necessary changes: + private static function convert(r:String):String { + // some references of the implementation: + // http://stackoverflow.com/questions/809647/java-vs-javascript-regex-problem + // http://stackoverflow.com/questions/4788413/how-to-convert-javascript-regex-to-safe-java-regex + // Some necessary changes: // // \0 -> \x00 // \v -> \x0b // [^] -> [\s\S] // unescaped ', " -> \', \" /* FIXME - var pat = new StringBuf(); - var len = r.length; - var i = 0; - while (i < len) - { - var c = StringTools.fastCodeAt(r, i++); - switch(c) + var pat = new StringBuf(); + var len = r.length; + var i = 0; + while (i < len) { - case '\\'.code: //escape-sequence + var c = StringTools.fastCodeAt(r, i++); + switch(c) + { + case '\\'.code: //escape-sequence + } } - } - */ + */ + return r; } - public function match( s : String ) : Bool { + public function match(s:String):Bool { cur = s; matcher = matcher.reset(s); return matcher.find(); } - public function matched( n : Int ) : String - { + public function matched(n:Int):String { if (n == 0) return matcher.group(); else return matcher.group(n); } - public function matchedLeft() : String - { + public function matchedLeft():String { return untyped cur.substring(0, matcher.start()); } - public function matchedRight() : String - { + public function matchedRight():String { return untyped cur.substring(matcher.end(), cur.length); } - public function matchedPos() : { pos : Int, len : Int } { + public function matchedPos():{pos:Int, len:Int} { var start = matcher.start(); - return { pos : start, len : matcher.end() - start }; + return {pos: start, len: matcher.end() - start}; } - public function matchSub( s : String, pos : Int, len : Int = -1):Bool { - matcher = matcher.reset(len < 0 ? s : s.substr(0,pos + len)); + public function matchSub(s:String, pos:Int, len:Int = -1):Bool { + matcher = matcher.reset(len < 0 ? s : s.substr(0, pos + len)); cur = s; return matcher.find(pos); } - public function split( s : String ) : Array - { - if (isGlobal) - { + public function split(s:String):Array { + if (isGlobal) { var ret = []; - while(this.match(s)) - { + while (this.match(s)) { ret.push(matchedLeft()); s = matchedRight(); } @@ -127,8 +123,7 @@ import java.util.regex.*; } else { var m = matcher; m.reset(s); - if (m.find()) - { + if (m.find()) { return untyped [s.substring(0, m.start()), s.substring(m.end(), s.length)]; } else { return [s]; @@ -136,24 +131,21 @@ import java.util.regex.*; } } - inline function start(group:Int) : Int - { + inline function start(group:Int):Int { return matcher.start(group); } - inline function len(group:Int) : Int - { + inline function len(group:Int):Int { return matcher.end(group) - matcher.start(group); } - public function replace( s : String, by : String ) : String - { - matcher.reset(s); - by = by.split("$$").join("\\$"); - return isGlobal ? matcher.replaceAll(by) : matcher.replaceFirst(by); + public function replace(s:String, by:String):String { + matcher.reset(s); + by = by.split("$$").join("\\$"); + return isGlobal ? matcher.replaceAll(by) : matcher.replaceFirst(by); } - public function map( s : String, f : EReg -> String ) : String { + public function map(s:String, f:EReg->String):String { var offset = 0; var buf = new StringBuf(); do { @@ -169,8 +161,7 @@ import java.util.regex.*; if (p.len == 0) { buf.add(s.substr(p.pos, 1)); offset = p.pos + 1; - } - else + } else offset = p.pos + p.len; } while (isGlobal); if (!isGlobal && offset > 0 && offset < s.length) @@ -178,7 +169,7 @@ import java.util.regex.*; return buf.toString(); } - public static inline function escape( s : String ) : String { + public static inline function escape(s:String):String { return Pattern.quote(s); } } diff --git a/std/java/_std/Math.hx b/std/java/_std/Math.hx index 13f4487150a..4e6662704cb 100644 --- a/std/java/_std/Math.hx +++ b/std/java/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,21 +19,19 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - @:coreApi -@:native("java.lang.Math") extern class Math -{ - static var PI(default,null) : Float; - static var NaN(default,null) : Float; - static var NEGATIVE_INFINITY(default,null) : Float; - static var POSITIVE_INFINITY(default,null) : Float; +@:native("java.lang.Math") extern class Math { + static var PI(default, null):Float; + static var NaN(default, null):Float; + static var NEGATIVE_INFINITY(default, null):Float; + static var POSITIVE_INFINITY(default, null):Float; static function abs(v:Float):Float; - static function min(a:Float,b:Float):Float; - static function max(a:Float,b:Float):Float; + static function min(a:Float, b:Float):Float; + static function max(a:Float, b:Float):Float; static function sin(v:Float):Float; static function cos(v:Float):Float; - static function atan2(y:Float,x:Float):Float; + static function atan2(y:Float, x:Float):Float; static function tan(v:Float):Float; static function exp(v:Float):Float; static function log(v:Float):Float; @@ -49,11 +47,9 @@ static function fceil(v:Float):Float; static function asin(v:Float):Float; static function acos(v:Float):Float; - static function pow(v:Float,exp:Float):Float; - static function random() : Float; + static function pow(v:Float, exp:Float):Float; + static function random():Float; - static function isFinite( f : Float ) : Bool; - static function isNaN( f : Float ) : Bool; + static function isFinite(f:Float):Bool; + static function isNaN(f:Float):Bool; } - - diff --git a/std/java/_std/Reflect.hx b/std/java/_std/Reflect.hx index 2fdc8041433..6389300387f 100644 --- a/std/java/_std/Reflect.hx +++ b/std/java/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,9 +26,7 @@ import java.internal.Runtime; import java.Boot; @:coreApi class Reflect { - - public static function hasField( o : Dynamic, field : String ) : Bool - { + public static function hasField(o:Dynamic, field:String):Bool { if (Std.is(o, IHxObject)) { return untyped (o : IHxObject).__hx_getField(field, false, true, false) != Runtime.undefined; } @@ -36,8 +34,7 @@ import java.Boot; } @:keep - public static function field( o : Dynamic, field : String ) : Dynamic - { + public static function field(o:Dynamic, field:String):Dynamic { if (Std.is(o, IHxObject)) { return untyped (o : IHxObject).__hx_getField(field, false, false, false); } @@ -45,8 +42,7 @@ import java.Boot; } @:keep - public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void - { + public static function setField(o:Dynamic, field:String, value:Dynamic):Void { if (Std.is(o, IHxObject)) { untyped (o : IHxObject).__hx_setField(field, value, false); } else { @@ -54,8 +50,10 @@ import java.Boot; } } - public static function getProperty( o : Dynamic, field : String ) : Dynamic - { + public static function getProperty(o:Dynamic, field:String):Dynamic { + if (o == null || field == null) { + return null; + } if (Std.is(o, IHxObject)) { return untyped (o : IHxObject).__hx_getField(field, false, false, true); } @@ -65,8 +63,7 @@ import java.Boot; return Runtime.slowGetField(o, field, false); } - public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void - { + public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void { if (Std.is(o, IHxObject)) { untyped (o : IHxObject).__hx_setField(field, value, true); } else if (Runtime.slowHasField(o, "set_" + field)) { @@ -76,15 +73,13 @@ import java.Boot; } } - public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic - { + public static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array):Dynamic { var args = java.Lib.nativeArray(args, true); return untyped (func : Function).__hx_invokeDynamic(args); } @:keep - public static function fields( o : Dynamic ) : Array - { + public static function fields(o:Dynamic):Array { if (Std.is(o, IHxObject)) { var ret:Array = []; untyped (o : IHxObject).__hx_getFields(ret); @@ -96,19 +91,16 @@ import java.Boot; } } - public static function isFunction( f : Dynamic ) : Bool - { + public static function isFunction(f:Dynamic):Bool { return Std.is(f, Function); } - public static function compare( a : T, b : T ) : Int - { + public static function compare(a:T, b:T):Int { return Runtime.compare(a, b); } @:access(java.internal.Closure) - public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool - { + public static function compareMethods(f1:Dynamic, f2:Dynamic):Bool { if (f1 == f2) { return true; } @@ -120,33 +112,34 @@ import java.Boot; return false; } - public static function isObject( v : Dynamic ) : Bool - { - return v != null && !(Std.is(v, HxEnum) || Std.is(v, Function) || Std.is(v, java.lang.Enum) || Std.is(v, java.lang.Number) || Std.is(v, java.lang.Boolean.BooleanClass)); + public static function isObject(v:Dynamic):Bool { + return v != null + && !(Std.is(v, HxEnum) + || Std.is(v, Function) + || Std.is(v, java.lang.Enum) + || Std.is(v, java.lang.Number) + || Std.is(v, java.lang.Boolean.BooleanClass)); } - public static function isEnumValue( v : Dynamic ) : Bool { + public static function isEnumValue(v:Dynamic):Bool { return v != null && (Std.is(v, HxEnum) || Std.is(v, java.lang.Enum)); } - public static function deleteField( o : Dynamic, field : String ) : Bool - { + public static function deleteField(o:Dynamic, field:String):Bool { return (Std.is(o, DynamicObject) && (o : DynamicObject).__hx_deleteField(field)); } - public static function copy( o : T ) : T - { - var o2 : Dynamic = {}; - for( f in Reflect.fields(o) ) - Reflect.setField(o2,f,Reflect.field(o,f)); + public static function copy(o:Null):Null { + if (o == null) + return null; + var o2:Dynamic = {}; + for (f in Reflect.fields(o)) + Reflect.setField(o2, f, Reflect.field(o, f)); return cast o2; } - @:overload(function( f : Array -> Void ) : Dynamic {}) - public static function makeVarArgs( f : Array -> Dynamic ) : Dynamic - { + @:overload(function(f:Array->Void):Dynamic {}) + public static function makeVarArgs(f:Array->Dynamic):Dynamic { return new VarArgsFunction(f); } - - } diff --git a/std/java/_std/Std.hx b/std/java/_std/Std.hx index 4556baf285a..d4f93330480 100644 --- a/std/java/_std/Std.hx +++ b/std/java/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,10 +25,9 @@ import java.Lib; import java.internal.Exceptions; @:coreApi @:nativeGen class Std { - public static function is( v : Dynamic, t : Dynamic ) : Bool - { + public static function is(v:Dynamic, t:Dynamic):Bool { if (v == null) - return t == Dynamic; + return false; if (t == null) return false; var clt:java.lang.Class = cast t; @@ -36,8 +35,7 @@ import java.internal.Exceptions; return false; var name:String = clt.getName(); - switch(name) - { + switch (name) { case "double", "java.lang.Double": return untyped __java__('haxe.lang.Runtime.isDouble(v)'); case "int", "java.lang.Integer": @@ -53,11 +51,11 @@ import java.internal.Exceptions; return clt.isAssignableFrom(clv); } - public static function string( s : Dynamic ) : String { + public static function string(s:Dynamic):String { return cast(s, String) + ""; } - public static function int( x : Float ) : Int { + public static function int(x:Float):Int { return cast x; } @@ -131,65 +129,69 @@ import java.internal.Exceptions; else return null; ') - public static function parseInt( x : String ) : Null { + public static function parseInt(x:String):Null { return null; } - public static function parseFloat( x : String ) : Float { - if (x == null) return Math.NaN; + public static function parseFloat(x:String):Float { + if (x == null) + return Math.NaN; x = StringTools.ltrim(x); - var found = false, hasDot = false, hasSign = false, - hasE = false, hasESign = false, hasEData = false; + var found = false, + hasDot = false, + hasSign = false, + hasE = false, + hasESign = false, + hasEData = false; var i = -1; - inline function getch(i:Int):Int return cast (untyped x._charAt(i) : java.StdTypes.Char16); + inline function getch(i:Int):Int + return cast(untyped x._charAt(i) : java.StdTypes.Char16); - while (++i < x.length) - { + while (++i < x.length) { var chr = getch(i); - if (chr >= '0'.code && chr <= '9'.code) - { - if (hasE) - { + if (chr >= '0'.code && chr <= '9'.code) { + if (hasE) { hasEData = true; } found = true; - } else switch (chr) { - case 'e'.code | 'E'.code if(!hasE): - hasE = true; - case '.'.code if (!hasDot): - hasDot = true; - case '-'.code, '+'.code if (!found && !hasSign): - hasSign = true; - case '-'.code | '+'.code if (found && !hasESign && hasE && !hasEData): - hasESign = true; - case _: - break; - } + } else + switch (chr) { + case 'e'.code | 'E'.code if (!hasE): + hasE = true; + case '.'.code if (!hasDot): + hasDot = true; + case '-'.code, '+'.code if (!found && !hasSign): + hasSign = true; + case '-'.code | '+'.code if (found && !hasESign && hasE && !hasEData): + hasESign = true; + case _: + break; + } } - if (hasE && !hasEData) - { + if (hasE && !hasEData) { i--; if (hasESign) i--; } - if (i != x.length) - { - x = x.substr(0,i); + if (i != x.length) { + x = x.substr(0, i); } - return try - java.lang.Double.DoubleClass.parseDouble(x) - catch(e:Dynamic) - Math.NaN; + return try java.lang.Double.DoubleClass.parseDouble(x) catch (e:Dynamic) Math.NaN; } - inline public static function instance( value : T, c : Class ) : S { + inline public static function downcast(value:T, c:Class):S { return Std.is(value, c) ? cast value : null; } - public static function random( x : Int ) : Int { - if (x <= 0) return 0; - return Std.int(Math.random() * x); + @:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.') + inline public static function instance(value:T, c:Class):S { + return downcast(value, c); } + public static function random(x:Int):Int { + if (x <= 0) + return 0; + return Std.int(Math.random() * x); + } } diff --git a/std/java/_std/String.hx b/std/java/_std/String.hx index c51ee32ac17..1cf2eb0b6f6 100644 --- a/std/java/_std/String.hx +++ b/std/java/_std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,42 +19,40 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - @:coreApi extern class String implements java.lang.CharSequence { + var length(default, null):Int; - var length(default,null) : Int; - - @:overload(function(b:haxe.io.BytesData, offset:Int, length:Int, charsetName:String):Void { }) - @:overload(function(b:haxe.io.BytesData, offset:Int, length:Int):Void { }) - function new(string:String) : Void; - - function toUpperCase() : String; + @:overload(function(b:haxe.io.BytesData, offset:Int, length:Int, charsetName:String):Void {}) + @:overload(function(b:haxe.io.BytesData, offset:Int, length:Int):Void {}) + @:overload(function(b:java.NativeArray):Void {}) + function new(string:String):Void; - function toLowerCase() : String; + function toUpperCase():String; - function charAt( index : Int) : String; + function toLowerCase():String; - function charCodeAt( index : Int) : Null; + function charAt(index:Int):String; - function indexOf( str : String, ?startIndex : Int ) : Int; + function charCodeAt(index:Int):Null; - function lastIndexOf( str : String, ?startIndex : Int ) : Int; + function indexOf(str:String, ?startIndex:Int):Int; - function split( delimiter : String ) : Array; + function lastIndexOf(str:String, ?startIndex:Int):Int; - function substr( pos : Int, ?len : Int ) : String; + function split(delimiter:String):Array; - function substring( startIndex : Int, ?endIndex : Int ) : String; + function substr(pos:Int, ?len:Int):String; - function toString() : String; + function substring(startIndex:Int, ?endIndex:Int):String; - private function compareTo( anotherString : String ) : Int; + function toString():String; - private function codePointAt( idx : Int ) : Int; + private function compareTo(anotherString:String):Int; - @:overload(function() : haxe.io.BytesData { }) - private function getBytes(encoding:String) : haxe.io.BytesData; + private function codePointAt(idx:Int):Int; - static function fromCharCode( code : Int ) : String; + @:overload(function():haxe.io.BytesData {}) + private function getBytes(encoding:String):haxe.io.BytesData; + static function fromCharCode(code:Int):String; } diff --git a/std/java/_std/StringBuf.hx b/std/java/_std/StringBuf.hx index bb03d30ae13..d695dfe996e 100644 --- a/std/java/_std/StringBuf.hx +++ b/std/java/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,25 +19,31 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - @:coreApi class StringBuf { + private var b:java.lang.StringBuilder; - private var b : java.lang.StringBuilder; - - public var length(get,never) : Int; + public var length(get, never):Int; - public function new() : Void { + public function new():Void { b = new java.lang.StringBuilder(); } - inline function get_length() : Int { + inline function get_length():Int { return b.length(); } - public function add( x : T ) : Void { - if (Std.is(x, Int)) - { + #if jvm + public function add(x:T):Void { + if (jvm.Jvm.instanceof(x, java.lang.Double.DoubleClass)) { + b.append(jvm.Jvm.toString(cast x)); + } else { + b.append(x); + } + } + #else + public function add(x:T):Void { + if (Std.is(x, Int)) { var x:Int = cast x; var xd:Dynamic = x; b.append(xd); @@ -45,18 +51,19 @@ class StringBuf { b.append(x); } } + #end - public function addSub( s : String, pos : Int, ?len : Int ) : Void { + public function addSub(s:String, pos:Int, ?len:Int):Void { var l:Int = (len == null) ? s.length - pos : len; b.append(s, pos, pos + l); } - public function addChar( c : Int ) : Void untyped { - b.append(cast(c, java.StdTypes.Char16)); - } + public function addChar(c:Int):Void + untyped { + b.appendCodePoint(c); + } - public function toString() : String { + public function toString():String { return b.toString(); } - } diff --git a/std/java/_std/Sys.hx b/std/java/_std/Sys.hx index dde0f25119e..da79ffba600 100644 --- a/std/java/_std/Sys.hx +++ b/std/java/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,6 +22,7 @@ import java.lang.System; import sys.io.Process; + using haxe.Int64; @:coreApi class Sys { @@ -29,74 +30,63 @@ using haxe.Int64; private static var _env:haxe.ds.StringMap; private static var _sysName:String; - public static inline function print( v : Dynamic ) : Void - { + public static inline function print(v:Dynamic):Void { java.lang.System.out.print(v); } - public static inline function println( v : Dynamic ) : Void - { + public static inline function println(v:Dynamic):Void { java.lang.System.out.println(v); } - public static function args() : Array - { + public static function args():Array { if (_args == null) return []; return java.Lib.array(_args); } - public static function getEnv( s : String ) : String - { + public static function getEnv(s:String):String { return java.lang.System.getenv(s); } - public static function putEnv( s : String, v : String ) : Void - { - //java offers no support for it (!) + public static function putEnv(s:String, v:String):Void { + // java offers no support for it (!) throw "Not implemented in this platform"; } - public static function environment() : Map - { + public static function environment():Map { if (_env != null) return _env; var _env = _env = new haxe.ds.StringMap(); - for (mv in java.lang.System.getenv().entrySet()) - { + for (mv in java.lang.System.getenv().entrySet()) { _env.set(mv.getKey(), mv.getValue()); } return _env; } - public static function sleep( seconds : Float ) : Void - { + public static function sleep(seconds:Float):Void { try java.lang.Thread.sleep(cast seconds * 1000) catch (e:Dynamic) throw e; } - public static function setTimeLocale( loc : String ) : Bool - { + public static function setTimeLocale(loc:String):Bool { return false; } - public static function getCwd() : String - { - return new java.io.File(".").getAbsolutePath().substr(0,-1); + public static function getCwd():String { + return new java.io.File(".").getAbsolutePath().substr(0, -1); } - public static function setCwd( s : String ) : Void - { - //java offers no support for it (!) + public static function setCwd(s:String):Void { + // java offers no support for it (!) throw "not implemented"; } - public static function systemName() : String - { - if (_sysName != null) return _sysName; + public static function systemName():String { + if (_sysName != null) + return _sysName; var sname = System.getProperty("os.name").toLowerCase(); if (sname.indexOf("win") >= 0) return _sysName = "Windows"; @@ -110,79 +100,65 @@ using haxe.Int64; return _sysName = System.getProperty("os.name"); } - public static function command( cmd : String, ?args : Array ) : Int - { + public static function command(cmd:String, ?args:Array):Int { var pb = Process.createProcessBuilder(cmd, args); -#if java6 + #if java6 pb.redirectErrorStream(true); -#else + #else pb.redirectOutput(java.lang.ProcessBuilder.ProcessBuilder_Redirect.INHERIT); pb.redirectError(java.lang.ProcessBuilder.ProcessBuilder_Redirect.INHERIT); -#end + #end var proc = pb.start(); -#if java6 + #if java6 var reader = new java.io.NativeInput(proc.getInputStream()); - try - { - while(true) { + try { + while (true) { var ln = reader.readLine(); Sys.println(ln); } - } - catch(e:haxe.io.Eof) {} -#end + } catch (e:haxe.io.Eof) {} + #end proc.waitFor(); var exitCode = proc.exitValue(); proc.destroy(); return exitCode; } - public static function exit( code : Int ) : Void - { + public static function exit(code:Int):Void { System.exit(code); } - public static function time() : Float - { + public static function time():Float { return cast(System.currentTimeMillis(), Float) / 1000; } - public static function cpuTime() : Float - { + public static function cpuTime():Float { return cast(System.nanoTime(), Float) / 1000000000; } - @:deprecated("Use programPath instead") public static function executablePath() : String - { + @:deprecated("Use programPath instead") public static function executablePath():String { return getCwd(); } - public static function programPath() : String { - return java.Lib.toNativeType(Sys) - .getProtectionDomain() - .getCodeSource() - .getLocation().toURI().getPath(); + public static function programPath():String { + return java.Lib.toNativeType(Sys).getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); } - public static function getChar( echo : Bool ) : Int - { - //TODO + public static function getChar(echo:Bool):Int { + // TODO return throw "Not implemented"; } - public static function stdin() : haxe.io.Input - { + public static function stdin():haxe.io.Input { var _in:java.io.InputStream = Reflect.field(System, "in"); return new java.io.NativeInput(_in); } - public static function stdout() : haxe.io.Output - { + public static function stdout():haxe.io.Output { return new java.io.NativeOutput(System.out); } - public static function stderr() : haxe.io.Output - { + public static function stderr():haxe.io.Output { return new java.io.NativeOutput(System.err); } } diff --git a/std/java/_std/Type.hx b/std/java/_std/Type.hx index 4cd0ca2e3f6..2205edb43f3 100644 --- a/std/java/_std/Type.hx +++ b/std/java/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,31 +31,27 @@ enum ValueType { TBool; TObject; TFunction; - TClass( c : Class ); - TEnum( e : Enum ); + TClass(c:Class); + TEnum(e:Enum); TUnknown; } @:coreApi class Type { - - public static function getClass( o : T ) : Class - { + public static function getClass(o:T):Class { if (o == null || Std.is(o, DynamicObject) || Std.is(o, java.lang.Class)) { return null; } return cast java.Lib.getNativeType(o); } - public static function getEnum( o : EnumValue ) : Enum - { + public static function getEnum(o:EnumValue):Enum { if (Std.is(o, java.lang.Enum) || Std.is(o, HxEnum)) { return untyped o.getClass(); } return null; } - public static function getSuperClass( c : Class ) : Class - { + public static function getSuperClass(c:Class):Class { var c = java.Lib.toNativeType(c); var cl:java.lang.Class = c == null ? null : untyped c.getSuperclass(); if (cl != null && cl.getName() != "haxe.lang.HxObject" && cl.getName() != "java.lang.Object") { @@ -64,16 +60,15 @@ enum ValueType { return null; } - public static function getClassName( c : Class ) : String { - var c : java.lang.Class = cast c; + public static function getClassName(c:Class):String { + var c:java.lang.Class = cast c; var name:String = c.getName(); if (name.startsWith("haxe.root.")) return name.substr(10); if (name.startsWith("java.lang")) name = name.substr(10); - return switch(name) - { + return switch (name) { case "int", "Integer": "Int"; case "double", "Double": "Float"; case "Object": "Dynamic"; @@ -81,8 +76,8 @@ enum ValueType { } } - public static function getEnumName( e : Enum ) : String { - var c : java.lang.Class = cast e; + public static function getEnumName(e:Enum):String { + var c:java.lang.Class = cast e; var ret:String = c.getName(); if (ret.startsWith("haxe.root.")) return ret.substr(10); @@ -90,11 +85,10 @@ enum ValueType { return ret; } - public static function resolveClass( name : String ) : Class - { + public static function resolveClass(name:String):Class { try { if (name.indexOf(".") == -1) { - name = "haxe.root." +name; + name = "haxe.root." + name; } return cast java.lang.Class.forName(name); } catch (e:java.lang.ClassNotFoundException) { @@ -110,7 +104,6 @@ enum ValueType { } } - @:functionCode(' if ("Bool".equals(name)) return boolean.class; Class r = resolveClass(name); @@ -118,20 +111,20 @@ enum ValueType { return r; return null; ') - public static function resolveEnum( name : String ) : Enum untyped - { - if (name == "Bool") return Bool; - return resolveClass(name); - } + public static function resolveEnum(name:String):Enum + untyped { + if (name == "Bool") + return Bool; + return resolveClass(name); + } - public static function createInstance( cl : Class, args : Array ) : T - { + public static function createInstance(cl:Class, args:Array):T { var nargs = args.length, - callArguments = new java.NativeArray(nargs); + callArguments = new java.NativeArray(nargs); var ctors = java.Lib.toNativeType(cl).getConstructors(), - totalCtors = ctors.length, - validCtors = 0; + totalCtors = ctors.length, + validCtors = 0; for (i in 0...totalCtors) { var ctor = ctors[i]; @@ -140,16 +133,18 @@ enum ValueType { continue; } - var argNum = -1, - valid = true; + var argNum = -1, valid = true; for (arg in args) { argNum++; var expectedType = argNum < ptypes.length ? ptypes[argNum] : ptypes[ptypes.length - 1]; // varags - if (arg == null || expectedType.isAssignableFrom(java.Lib.toNativeType(Type.getClass(arg)))) { + var isDynamic = Std.is(arg, DynamicObject) && expectedType.isAssignableFrom(java.Lib.getNativeType(arg)); + var argType = Type.getClass(arg); + + if (arg == null || isDynamic || (argType != null && expectedType.isAssignableFrom(java.Lib.toNativeType(argType)))) { callArguments[argNum] = arg; } else if (Std.is(arg, java.lang.Number)) { var name = expectedType.getName(); - switch(name) { + switch (name) { case 'double' | 'java.lang.Double': callArguments[argNum] = (cast arg : java.lang.Number).doubleValue(); case 'int' | 'java.lang.Integer': @@ -161,7 +156,8 @@ enum ValueType { case 'short' | 'java.lang.Short': callArguments[argNum] = (cast arg : java.lang.Number).shortValue(); case _: - throw 'Unknown expected number subclass of type $name'; + valid = false; + break; } } else { valid = false; @@ -184,7 +180,7 @@ enum ValueType { @:protected @:readOnly static var __createEmptyInstance_EMPTY_TYPES = java.NativeArray.make(java.Lib.toNativeEnum(java.internal.Runtime.EmptyObject)); @:protected @:readOnly static var __createEmptyInstance_EMPTY_ARGS = java.NativeArray.make(java.internal.Runtime.EmptyObject.EMPTY); - public static function createEmptyInstance( cl : Class ) : T { + public static function createEmptyInstance(cl:Class):T { var t = java.Lib.toNativeType(cl); try { var ctor = t.getConstructor(__createEmptyInstance_EMPTY_TYPES); @@ -194,7 +190,7 @@ enum ValueType { } } - public static function createEnum( e : Enum, constr : String, ?params : Array ) : T { + public static function createEnum(e:Enum, constr:String, ?params:Array):T { if (params == null || params.length == 0) { var ret:Dynamic = java.internal.Runtime.slowGetField(e, constr, true); if (Std.is(ret, java.internal.Function)) { @@ -207,7 +203,7 @@ enum ValueType { } } - public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T { + public static function createEnumIndex(e:Enum, index:Int, ?params:Array):T { var constr = getEnumConstructs(e); return createEnum(e, constr[index], params); } @@ -237,7 +233,7 @@ enum ValueType { return ret; ') - public static function getInstanceFields( c : Class ) : Array { + public static function getInstanceFields(c:Class):Array { return null; } @@ -267,17 +263,17 @@ enum ValueType { return ret; ') - public static function getClassFields( c : Class ) : Array { + public static function getClassFields(c:Class):Array { return null; } - public static function getEnumConstructs( e : Enum ) : Array { - if (Reflect.hasField(e, "__hx_constructs")) - { + public static function getEnumConstructs(e:Enum):Array { + if (Reflect.hasField(e, "__hx_constructs")) { var ret:Array = java.Lib.array(untyped e.__hx_constructs); return ret.copy(); } - var vals:java.NativeArray> = untyped e.values(), ret = []; + var vals:java.NativeArray> = untyped e.values(), + ret = []; for (i in 0...vals.length) ret[i] = vals[i].name(); return ret; @@ -311,10 +307,10 @@ enum ValueType { return ValueType.TClass(v.getClass()); } ') - public static function typeof( v : Dynamic ) : ValueType untyped - { - return null; - } + public static function typeof(v:Dynamic):ValueType + untyped { + return null; + } @:functionCode(' if (a instanceof haxe.lang.Enum) @@ -322,10 +318,10 @@ enum ValueType { else return haxe.lang.Runtime.eq(a, b); ') - public static function enumEq( a : T, b : T ) : Bool untyped - { - return a == b; - } + public static function enumEq(a:T, b:T):Bool + untyped { + return a == b; + } @:functionCode(' if (e instanceof java.lang.Enum) @@ -333,18 +329,18 @@ enum ValueType { else return ((haxe.lang.Enum) e).getTag(); ') - public static function enumConstructor( e : EnumValue ) : String untyped - { - return null; - } + public static function enumConstructor(e:EnumValue):String + untyped { + return null; + } @:functionCode(' return ( e instanceof java.lang.Enum ) ? new haxe.root.Array() : ((haxe.lang.Enum) e).getParams(); ') - public static function enumParameters( e : EnumValue ) : Array untyped - { - return null; - } + public static function enumParameters(e:EnumValue):Array + untyped { + return null; + } @:ifFeature("has_enum") @:functionCode(' @@ -353,17 +349,15 @@ enum ValueType { else return ((haxe.lang.Enum) e).index; ') - public static function enumIndex( e : EnumValue ) : Int untyped - { - return e.index; - } + public static function enumIndex(e:EnumValue):Int + untyped { + return e.index; + } - public static function allEnums( e : Enum ) : Array - { + public static function allEnums(e:Enum):Array { var ctors = getEnumConstructs(e); var ret = []; - for (ctor in ctors) - { + for (ctor in ctors) { var v = Reflect.field(e, ctor); if (Std.is(v, e)) ret.push(v); @@ -371,5 +365,4 @@ enum ValueType { return ret; } - } diff --git a/std/java/_std/haxe/Int64.hx b/std/java/_std/haxe/Int64.hx index 5d2d2a54812..5f6ac934f65 100644 --- a/std/java/_std/haxe/Int64.hx +++ b/std/java/_std/haxe/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; + using haxe.Int64; import haxe.Int64Helper; @@ -27,203 +29,214 @@ import haxe.Int64Helper; private typedef __Int64 = java.StdTypes.Int64; @:coreApi -abstract Int64(__Int64) from __Int64 to __Int64 -{ +abstract Int64(__Int64) from __Int64 to __Int64 { + #if jvm + extern public static function make(high:Int32, low:Int32):Int64; + #else + public static inline function make(high:Int32, low:Int32):Int64 + return new Int64(((cast high : __Int64) << 32) | ((cast low : __Int64) & (untyped __java__('0xffffffffL') : Int64))); + #end + + private inline function new(x:__Int64) + this = x; - public static inline function make( high : Int32, low : Int32 ) : Int64 - return new Int64( (cast(high, __Int64) << 32) | (cast(low, __Int64)& (untyped __java__('0xffffffffL') : Int64)) ); + private var val(get, set):__Int64; - private inline function new(x : __Int64) - this = x; + inline function get_val():__Int64 + return this; + + inline function set_val(x:__Int64):__Int64 + return this = x; + + public var high(get, never):Int32; - private var val( get, set ) : __Int64; - inline function get_val() : __Int64 return this; - inline function set_val( x : __Int64 ) : __Int64 return this = x; + public inline function get_high():Int32 + return cast(this >> 32); - public var high( get, never ):Int32; - public inline function get_high():Int32 return cast(this >> 32); + public var low(get, never):Int32; - public var low( get, never ):Int32; - public inline function get_low():Int32 return cast this; + public inline function get_low():Int32 + return cast this; public inline function copy():Int64 - return new Int64( this ); + return new Int64(this); - @:from public static inline function ofInt( x : Int ) : Int64 + @:from public static inline function ofInt(x:Int):Int64 return cast x; - inline public static function is( val : Dynamic ) : Bool - return Std.is(val,java.lang.Long.LongClass); + inline public static function is(val:Dynamic):Bool + return Std.is(val, java.lang.Long.LongClass); - public static inline function toInt( x : Int64 ) : Int { - if( x.val < 0x80000000 || x.val > 0x7FFFFFFF ) + public static inline function toInt(x:Int64):Int { + if (x.val < 0x80000000 || x.val > 0x7FFFFFFF) throw "Overflow"; return cast x.val; } - public static inline function getHigh( x : Int64 ) : Int32 - return cast( x.val >> 32 ); + public static inline function getHigh(x:Int64):Int32 + return cast(x.val >> 32); - public static inline function getLow( x : Int64 ) : Int32 - return cast( x.val ); + public static inline function getLow(x:Int64):Int32 + return cast(x.val); - public static inline function isNeg( x : Int64 ) : Bool + public static inline function isNeg(x:Int64):Bool return x.val < 0; - public static inline function isZero( x : Int64 ) : Bool + public static inline function isZero(x:Int64):Bool return x.val == 0; - public static inline function compare( a : Int64, b : Int64 ) : Int - { - if( a.val < b.val ) return -1; - if( a.val > b.val ) return 1; + public static inline function compare(a:Int64, b:Int64):Int { + if (a.val < b.val) + return -1; + if (a.val > b.val) + return 1; return 0; } - public static inline function ucompare( a : Int64, b : Int64 ) : Int { - if( a.val < 0 ) - return ( b.val < 0 ) ? compare( a, b ) : 1; - return ( b.val < 0 ) ? -1 : compare( a, b ); + public static inline function ucompare(a:Int64, b:Int64):Int { + if (a.val < 0) + return (b.val < 0) ? compare(a, b) : 1; + return (b.val < 0) ? -1 : compare(a, b); } - public static inline function toStr( x : Int64 ) : String + public static inline function toStr(x:Int64):String return '${x.val}'; - public static inline function divMod( dividend : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 } - return { quotient: dividend / divisor, modulus: dividend % divisor }; + public static inline function divMod(dividend:Int64, divisor:Int64):{quotient:Int64, modulus:Int64} + return {quotient: dividend / divisor, modulus: dividend % divisor}; - private inline function toString() : String + private inline function toString():String return '$this'; - public static function parseString( sParam : String ) : Int64 { + public static function parseString(sParam:String):Int64 { // can this be done?: return new Int64( java.lang.Long.LongClass.parseLong( sParam ) ); - return Int64Helper.parseString( sParam ); + return Int64Helper.parseString(sParam); } - public static function fromFloat( f : Float ) : Int64 { - return Int64Helper.fromFloat( f ); + public static function fromFloat(f:Float):Int64 { + return Int64Helper.fromFloat(f); } - @:op(-A) public static function neg( x : Int64 ) : Int64 + @:op(-A) public static function neg(x:Int64):Int64 return -x.val; - @:op(++A) private inline function preIncrement() : Int64 + @:op(++A) private inline function preIncrement():Int64 return ++this; - @:op(A++) private inline function postIncrement() : Int64 + @:op(A++) private inline function postIncrement():Int64 return this++; - @:op(--A) private inline function preDecrement() : Int64 + @:op(--A) private inline function preDecrement():Int64 return --this; - @:op(A--) private inline function postDecrement() : Int64 + @:op(A--) private inline function postDecrement():Int64 return this--; - @:op(A + B) public static inline function add( a : Int64, b : Int64 ) : Int64 + @:op(A + B) public static inline function add(a:Int64, b:Int64):Int64 return a.val + b.val; - @:op(A + B) @:commutative private static inline function addInt( a : Int64, b : Int ) : Int64 + @:op(A + B) @:commutative private static inline function addInt(a:Int64, b:Int):Int64 return a.val + b; - @:op(A - B) public static inline function sub( a : Int64, b : Int64 ) : Int64 + @:op(A - B) public static inline function sub(a:Int64, b:Int64):Int64 return a.val - b.val; - @:op(A - B) private static inline function subInt( a : Int64, b : Int ) : Int64 + @:op(A - B) private static inline function subInt(a:Int64, b:Int):Int64 return a.val - b; - @:op(A - B) private static inline function intSub( a : Int, b : Int64 ) : Int64 + @:op(A - B) private static inline function intSub(a:Int, b:Int64):Int64 return a - b.val; - @:op(A * B) public static inline function mul( a : Int64, b : Int64 ) : Int64 + @:op(A * B) public static inline function mul(a:Int64, b:Int64):Int64 return a.val * b.val; - @:op(A * B) @:commutative private static inline function mulInt( a : Int64, b : Int ) : Int64 + @:op(A * B) @:commutative private static inline function mulInt(a:Int64, b:Int):Int64 return a.val * b; - @:op(A / B) public static inline function div( a : Int64, b : Int64 ) : Int64 + @:op(A / B) public static inline function div(a:Int64, b:Int64):Int64 return a.val / b.val; - @:op(A / B) private static inline function divInt( a : Int64, b : Int ) : Int64 + @:op(A / B) private static inline function divInt(a:Int64, b:Int):Int64 return a.val / b; - @:op(A / B) private static inline function intDiv( a : Int, b : Int64 ) : Int64 + @:op(A / B) private static inline function intDiv(a:Int, b:Int64):Int64 return a / b.val; - @:op(A % B) public static inline function mod( a : Int64, b : Int64 ) : Int64 + @:op(A % B) public static inline function mod(a:Int64, b:Int64):Int64 return a.val % b.val; - @:op(A % B) private static inline function modInt( a : Int64, b : Int ) : Int64 + @:op(A % B) private static inline function modInt(a:Int64, b:Int):Int64 return a.val % b; - @:op(A % B) private static inline function intMod( a : Int, b : Int64 ) : Int64 + @:op(A % B) private static inline function intMod(a:Int, b:Int64):Int64 return a % b.val; - @:op(A == B) public static inline function eq( a : Int64, b : Int64 ) : Bool + @:op(A == B) public static inline function eq(a:Int64, b:Int64):Bool return a.val == b.val; - @:op(A == B) @:commutative private static inline function eqInt( a : Int64, b : Int ) : Bool + @:op(A == B) @:commutative private static inline function eqInt(a:Int64, b:Int):Bool return a.val == b; - @:op(A != B) public static inline function neq( a : Int64, b : Int64 ) : Bool + @:op(A != B) public static inline function neq(a:Int64, b:Int64):Bool return a.val != b.val; - @:op(A != B) @:commutative private static inline function neqInt( a : Int64, b : Int ) : Bool + @:op(A != B) @:commutative private static inline function neqInt(a:Int64, b:Int):Bool return a.val != b; - @:op(A < B) private static inline function lt( a : Int64, b : Int64 ) : Bool + @:op(A < B) private static inline function lt(a:Int64, b:Int64):Bool return a.val < b.val; - @:op(A < B) private static inline function ltInt( a : Int64, b : Int ) : Bool + @:op(A < B) private static inline function ltInt(a:Int64, b:Int):Bool return a.val < b; - @:op(A < B) private static inline function intLt( a : Int, b : Int64 ) : Bool + @:op(A < B) private static inline function intLt(a:Int, b:Int64):Bool return a < b.val; - @:op(A <= B) private static inline function lte( a : Int64, b : Int64 ) : Bool + @:op(A <= B) private static inline function lte(a:Int64, b:Int64):Bool return a.val <= b.val; - @:op(A <= B) private static inline function lteInt( a : Int64, b : Int ) : Bool + @:op(A <= B) private static inline function lteInt(a:Int64, b:Int):Bool return a.val <= b; - @:op(A <= B) private static inline function intLte( a : Int, b : Int64 ) : Bool + @:op(A <= B) private static inline function intLte(a:Int, b:Int64):Bool return a <= b.val; - @:op(A > B) private static inline function gt( a : Int64, b : Int64 ) : Bool + @:op(A > B) private static inline function gt(a:Int64, b:Int64):Bool return a.val > b.val; - @:op(A > B) private static inline function gtInt( a : Int64, b : Int ) : Bool + @:op(A > B) private static inline function gtInt(a:Int64, b:Int):Bool return a.val > b; - @:op(A > B) private static inline function intGt( a : Int, b : Int64 ) : Bool + @:op(A > B) private static inline function intGt(a:Int, b:Int64):Bool return a > b.val; - @:op(A >= B) private static inline function gte( a : Int64, b : Int64 ) : Bool + @:op(A >= B) private static inline function gte(a:Int64, b:Int64):Bool return a.val >= b.val; - @:op(A >= B) private static inline function gteInt( a : Int64, b : Int ) : Bool + @:op(A >= B) private static inline function gteInt(a:Int64, b:Int):Bool return a.val >= b; - @:op(A >= B) private static inline function intGte( a : Int, b : Int64 ) : Bool + @:op(A >= B) private static inline function intGte(a:Int, b:Int64):Bool return a >= b.val; - @:op(~A) private static inline function complement( x : Int64 ) : Int64 + @:op(~A) private static inline function complement(x:Int64):Int64 return ~x.val; - @:op(A & B) public static inline function and( a : Int64, b : Int64 ) : Int64 + @:op(A & B) public static inline function and(a:Int64, b:Int64):Int64 return a.val & b.val; - @:op(A | B) public static inline function or( a : Int64, b : Int64 ) : Int64 + @:op(A | B) public static inline function or(a:Int64, b:Int64):Int64 return a.val | b.val; - @:op(A ^ B) public static inline function xor( a : Int64, b : Int64 ) : Int64 + @:op(A ^ B) public static inline function xor(a:Int64, b:Int64):Int64 return a.val ^ b.val; - @:op(A << B) public static inline function shl( a : Int64, b : Int ) : Int64 + @:op(A << B) public static inline function shl(a:Int64, b:Int):Int64 return a.val << b; - @:op(A >> B) public static inline function shr( a : Int64, b : Int ) : Int64 + @:op(A >> B) public static inline function shr(a:Int64, b:Int):Int64 return a.val >> b; - @:op(A >>> B) public static inline function ushr( a : Int64, b : Int ) : Int64 + @:op(A >>> B) public static inline function ushr(a:Int64, b:Int):Int64 return a.val >>> b; } diff --git a/std/java/_std/haxe/Resource.hx b/std/java/_std/haxe/Resource.hx index 38a243220f9..525e84aaea9 100644 --- a/std/java/_std/haxe/Resource.hx +++ b/std/java/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,18 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; @:coreApi class Resource { + @:keep static var content:Array; - @:keep static var content : Array; - - public static inline function listNames() : Array { + public static inline function listNames():Array { return content.copy(); } @:access(haxe.io.Path.escape) - public static function getString( name : String ) : String { + public static function getString(name:String):String { name = haxe.io.Path.escape(name, true); var stream = cast(Resource, java.lang.Class).getResourceAsStream("/" + name); if (stream == null) @@ -40,7 +40,7 @@ package haxe; } @:access(haxe.io.Path.escape) - public static function getBytes( name : String ) : haxe.io.Bytes { + public static function getBytes(name:String):haxe.io.Bytes { name = haxe.io.Path.escape(name, true); var stream = cast(Resource, java.lang.Class).getResourceAsStream("/" + name); if (stream == null) diff --git a/std/java/_std/haxe/ds/IntMap.hx b/std/java/_std/haxe/ds/IntMap.hx index a865125efbc..16266c3c62d 100644 --- a/std/java/_std/haxe/ds/IntMap.hx +++ b/std/java/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; import java.NativeArray; @@ -30,9 +31,7 @@ import java.NativeArray; * Thanks also to Jonas Malaco Filho for his Haxe-written IntMap code inspired by Python tables. * (https://jonasmalaco.com/fossil/test/jonas-haxe/artifact/887b53126e237d6c68951111d594033403889304) */ - -@:coreApi class IntMap implements haxe.Constraints.IMap -{ +@:coreApi class IntMap implements haxe.Constraints.IMap { private static inline var HASH_UPPER = 0.7; private var flags:NativeArray; @@ -44,26 +43,22 @@ import java.NativeArray; private var nOccupied:Int; private var upperBound:Int; -#if !no_map_cache + #if !no_map_cache private var cachedKey:Int; private var cachedIndex:Int; -#end + #end - public function new() : Void - { -#if !no_map_cache + public function new():Void { + #if !no_map_cache cachedIndex = -1; -#end + #end } - public function set( key : Int, value : T ) : Void - { + public function set(key:Int, value:T):Void { var targetIndex:Int; - if (nOccupied >= upperBound) - { - if (nBuckets > (size << 1)) - { - resize(nBuckets - 1); //clear "deleted" elements + if (nOccupied >= upperBound) { + if (nBuckets > (size << 1)) { + resize(nBuckets - 1); // clear "deleted" elements } else { resize(nBuckets + 1); } @@ -72,27 +67,23 @@ import java.NativeArray; var flags = flags, _keys = _keys; { var mask = nBuckets - 1, - hashedKey = hash(key), - curIndex = hashedKey & mask; + hashedKey = hash(key), + curIndex = hashedKey & mask; - var delKey = -1, - curFlag = 0; + var delKey = -1, curFlag = 0; // to speed things up, don't loop if the first bucket is already free if (isEmpty(getFlag(flags, curIndex))) { targetIndex = curIndex; } else { - var inc = getInc(hashedKey, mask), - last = curIndex; - while (! (_keys[curIndex] == key || isEmpty(curFlag = getFlag(flags, curIndex))) ) - { - if (delKey == -1 && isDel(curFlag)) - { + var inc = getInc(hashedKey, mask), last = curIndex; + while (!(_keys[curIndex] == key || isEmpty(curFlag = getFlag(flags, curIndex)))) { + if (delKey == -1 && isDel(curFlag)) { delKey = curIndex; } curIndex = (curIndex + inc) & mask; -#if debug + #if debug assert(curIndex != last); -#end + #end } if (delKey != -1 && isEmpty(getFlag(flags, curIndex))) { @@ -104,8 +95,7 @@ import java.NativeArray; } var flag = getFlag(flags, targetIndex); - if (isEmpty(flag)) - { + if (isEmpty(flag)) { _keys[targetIndex] = key; vals[targetIndex] = value; setIsBothFalse(flags, targetIndex); @@ -117,30 +107,26 @@ import java.NativeArray; setIsBothFalse(flags, targetIndex); size++; } else { -#if debug + #if debug assert(_keys[targetIndex] == key); -#end + #end vals[targetIndex] = value; } } - @:final private function lookup( key : Int ) : Int - { - if (nBuckets != 0) - { + private final function lookup(key:Int):Int { + if (nBuckets != 0) { var flags = flags, _keys = _keys; var mask = nBuckets - 1, - k = hash(key), - index = k & mask, - curFlag = -1, - inc = getInc(k, mask), /* inc == 1 for linear probing */ - last = index; - do - { + k = hash(key), + index = k & mask, + curFlag = -1, + inc = getInc(k, mask), /* inc == 1 for linear probing */ + last = index; + do { if (_keys[index] == key) { - if (isEmpty(curFlag = getFlag(flags, index))) - { + if (isEmpty(curFlag = getFlag(flags, index))) { index = (index + inc) & mask; continue; } else if (isDel(curFlag)) { @@ -157,69 +143,60 @@ import java.NativeArray; return -1; } - public function get( key : Int ) : Null - { + public function get(key:Int):Null { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } return null; } - private function getDefault( key : Int, def : T ) : T - { + private function getDefault(key:Int, def:T):T { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } return def; } - public function exists( key : Int ) : Bool - { + public function exists(key:Int):Bool { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return true; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return true; } @@ -227,28 +204,24 @@ import java.NativeArray; return false; } - public function remove( key : Int ) : Bool - { + public function remove(key:Int):Bool { var idx = -1; -#if !no_map_cache - if (! (cachedKey == key && ( (idx = cachedIndex) != -1 ))) -#end + #if !no_map_cache + if (!(cachedKey == key && ((idx = cachedIndex) != -1))) + #end { idx = lookup(key); } - if (idx == -1) - { + if (idx == -1) { return false; } else { -#if !no_map_cache - if (cachedKey == key) - { + #if !no_map_cache + if (cachedKey == key) { cachedIndex = -1; } -#end - if (!isEither(getFlag(flags, idx))) - { + #end + if (!isEither(getFlag(flags, idx))) { setIsDelTrue(flags, idx); --size; @@ -264,59 +237,53 @@ import java.NativeArray; } } - @:final private function resize(newNBuckets:Int) : Void - { - //This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. + private final function resize(newNBuckets:Int):Void { + // This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. var newFlags = null; var j = 1; { newNBuckets = roundUp(newNBuckets); - if (newNBuckets < 4) newNBuckets = 4; - if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */ - { + if (newNBuckets < 4) + newNBuckets = 4; + if (size >= (newNBuckets * HASH_UPPER + 0.5)) + /* requested size is too small */ { j = 0; } else { /* hash table size to be changed (shrink or expand); rehash */ var nfSize = flagsSize(newNBuckets); - newFlags = new NativeArray( nfSize ); - for (i in 0...nfSize) - { + newFlags = new NativeArray(nfSize); + for (i in 0...nfSize) { newFlags[i] = 0xaaaaaaaa; // isEmpty = true; isDel = false } - if (nBuckets < newNBuckets) //expand + if (nBuckets < newNBuckets) // expand { var k = new NativeArray(newNBuckets); - if (_keys != null) - { + if (_keys != null) { arrayCopy(_keys, 0, k, 0, nBuckets); } _keys = k; var v = new NativeArray(newNBuckets); - if (vals != null) - { + if (vals != null) { arrayCopy(vals, 0, v, 0, nBuckets); } vals = v; - } //otherwise shrink + } // otherwise shrink } } - if (j != 0) - { //rehashing is required -#if !no_map_cache - //resetting cache + if (j != 0) { // rehashing is required + #if !no_map_cache + // resetting cache cachedKey = 0; cachedIndex = -1; -#end + #end j = -1; var nBuckets = nBuckets, _keys = _keys, vals = vals, flags = flags; var newMask = newNBuckets - 1; - while (++j < nBuckets) - { - if (!isEither(getFlag(flags, j))) - { + while (++j < nBuckets) { + if (!isEither(getFlag(flags, j))) { var key = _keys[j]; var val = vals[j]; @@ -324,25 +291,23 @@ import java.NativeArray; // _keys[j] = 0; vals[j] = cast null; setIsDelTrue(flags, j); - while (true) /* kick-out process; sort of like in Cuckoo hashing */ - { + while (true) + /* kick-out process; sort of like in Cuckoo hashing */ { var k = hash(key); var inc = getInc(k, newMask); var i = k & newMask; - while (!isEmpty(getFlag(newFlags, i))) - { + while (!isEmpty(getFlag(newFlags, i))) { i = (i + inc) & newMask; } setIsEmptyFalse(newFlags, i); - if (i < nBuckets && !isEither(getFlag(flags, i))) /* kick out the existing element */ - { + if (i < nBuckets && !isEither(getFlag(flags, i))) + /* kick out the existing element */ { { var tmp = _keys[i]; _keys[i] = key; key = tmp; - } - { + } { var tmp = vals[i]; vals[i] = val; val = tmp; @@ -358,14 +323,13 @@ import java.NativeArray; } } - if (nBuckets > newNBuckets) /* shrink the hash table */ - { + if (nBuckets > newNBuckets) + /* shrink the hash table */ { { var k = new NativeArray(newNBuckets); arrayCopy(_keys, 0, k, 0, newNBuckets); this._keys = k; - } - { + } { var v = new NativeArray(newNBuckets); arrayCopy(vals, 0, v, 0, newNBuckets); this.vals = v; @@ -379,57 +343,49 @@ import java.NativeArray; } } - /** - Returns an iterator of all keys in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function keys() : Iterator - { + public inline function keys():Iterator { return new IntMapKeyIterator(this); } - /** - Returns an iterator of all values in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function iterator() : Iterator - { + public inline function iterator():Iterator { return new IntMapValueIterator(this); } - public function copy() : IntMap { + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():IntMap { var copied = new IntMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - /** - Returns an displayable representation of the hashtable content. - **/ - - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(i); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - private static inline function assert(x:Bool):Void - { + private static inline function assert(x:Bool):Void { #if debug - if (!x) throw "assert failed"; + if (!x) + throw "assert failed"; #end } - private static inline function defaultK():Int return 0; + private static inline function defaultK():Int + return 0; private static inline function arrayCopy(sourceArray:Dynamic, sourceIndex:Int, destinationArray:Dynamic, destinationIndex:Int, length:Int):Void java.lang.System.arraycopy(sourceArray, sourceIndex, destinationArray, destinationIndex, length); @@ -446,18 +402,15 @@ import java.NativeArray; // * gets the integer with (flags / 16) // * shifts those bits to the right ((flags % 16) * 2) places // * masks it with 0b11 - private static inline function getFlag(flags:NativeArray, i:Int):Int - { - return ( (flags[i >> 4] >>> ((i & 0xf) << 1)) & 3 ); + private static inline function getFlag(flags:NativeArray, i:Int):Int { + return ((flags[i >> 4] >>> ((i & 0xf) << 1)) & 3); } - private static inline function isDel(flag:Int):Bool - { + private static inline function isDel(flag:Int):Bool { return (flag & 1) != 0; } - private static inline function isEmpty(flag:Int):Bool - { + private static inline function isEmpty(flag:Int):Bool { return (flag & 2) != 0; } @@ -465,28 +418,23 @@ import java.NativeArray; return flag != 0; } - private static inline function setIsDelFalse(flags:NativeArray, i:Int):Void - { + private static inline function setIsDelFalse(flags:NativeArray, i:Int):Void { flags[i >> 4] &= ~(1 << ((i & 0xf) << 1)); } - private static inline function setIsEmptyFalse(flags:NativeArray, i:Int):Void - { + private static inline function setIsEmptyFalse(flags:NativeArray, i:Int):Void { flags[i >> 4] &= ~(2 << ((i & 0xf) << 1)); } - private static inline function setIsBothFalse(flags:NativeArray, i:Int):Void - { + private static inline function setIsBothFalse(flags:NativeArray, i:Int):Void { flags[i >> 4] &= ~(3 << ((i & 0xf) << 1)); } - private static inline function setIsDelTrue(flags:NativeArray, i:Int):Void - { + private static inline function setIsDelTrue(flags:NativeArray, i:Int):Void { flags[i >> 4] |= 1 << ((i & 0xf) << 1); } - private static inline function roundUp(x:Int):Int - { + private static inline function roundUp(x:Int):Int { --x; x |= (x) >>> 1; x |= (x) >>> 2; @@ -497,30 +445,24 @@ import java.NativeArray; } private static inline function flagsSize(m:Int):Int - return ((m) < 16? 1 : (m) >> 4); + return ((m) < 16 ? 1 : (m) >> 4); } @:access(haxe.ds.IntMap) -@:final -private class IntMapKeyIterator -{ +private final class IntMapKeyIterator { var m:IntMap; var i:Int; var len:Int; - public function new(m:IntMap) - { + public function new(m:IntMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } - public function hasNext():Bool - { - for (j in i...len) - { - if (!IntMap.isEither(IntMap.getFlag(m.flags, j))) - { + public function hasNext():Bool { + for (j in i...len) { + if (!IntMap.isEither(IntMap.getFlag(m.flags, j))) { i = j; return true; } @@ -528,38 +470,32 @@ private class IntMapKeyIterator return false; } - public function next():Int - { + public function next():Int { var ret = m._keys[i]; -#if !no_map_cache + #if !no_map_cache m.cachedIndex = i; m.cachedKey = ret; -#end + #end i++; return ret; } } @:access(haxe.ds.IntMap) -@:final -private class IntMapValueIterator -{ +private final class IntMapValueIterator { var m:IntMap; var i:Int; var len:Int; - public function new(m:IntMap) - { + public function new(m:IntMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } public function hasNext():Bool { - for (j in i...len) - { - if (!IntMap.isEither(IntMap.getFlag(m.flags, j))) - { + for (j in i...len) { + if (!IntMap.isEither(IntMap.getFlag(m.flags, j))) { i = j; return true; } @@ -567,8 +503,7 @@ private class IntMapValueIterator return false; } - public inline function next():T - { + public inline function next():T { return m.vals[i++]; } } diff --git a/std/java/_std/haxe/ds/ObjectMap.hx b/std/java/_std/haxe/ds/ObjectMap.hx index 151ecfc954f..0895bacbf2e 100644 --- a/std/java/_std/haxe/ds/ObjectMap.hx +++ b/std/java/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,15 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; import java.NativeArray; -@:coreApi class ObjectMap implements haxe.Constraints.IMap -{ - @:extern private static inline var HASH_UPPER = 0.77; - @:extern private static inline var FLAG_EMPTY = 0; - @:extern private static inline var FLAG_DEL = 1; +@:coreApi class ObjectMap implements haxe.Constraints.IMap { + extern private static inline var HASH_UPPER = 0.77; + extern private static inline var FLAG_EMPTY = 0; + extern private static inline var FLAG_DEL = 1; /** * This is the most important structure here and the reason why it's so fast. @@ -38,6 +38,7 @@ import java.NativeArray; * The insertion algorithm will do the same but will also break when FLAG_DEL is found; */ private var hashes:NativeArray; + private var _keys:NativeArray; private var vals:NativeArray; @@ -46,32 +47,29 @@ import java.NativeArray; private var nOccupied:Int; private var upperBound:Int; -#if !no_map_cache + #if !no_map_cache private var cachedKey:K; private var cachedIndex:Int; -#end + #end -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL private var totalProbes:Int; private var probeTimes:Int; private var sameHash:Int; private var maxProbe:Int; -#end + #end - public function new() : Void - { -#if !no_map_cache + public function new():Void { + #if !no_map_cache cachedIndex = -1; -#end + #end } - public function set( key : K, value : V ) : Void - { + public function set(key:K, value:V):Void { var x:Int, k:Int; - if (nOccupied >= upperBound) - { + if (nOccupied >= upperBound) { if (nBuckets > (size << 1)) - resize(nBuckets - 1); //clear "deleted" elements + resize(nBuckets - 1); // clear "deleted" elements else resize(nBuckets + 2); } @@ -84,22 +82,21 @@ import java.NativeArray; var i = k & mask, nProbes = 0; var delKey = -1; - //for speed up + // for speed up if (isEmpty(hashes[i])) { x = i; } else { - //var inc = getInc(k, mask); + // var inc = getInc(k, mask); var last = i, flag; - while(! (isEmpty(flag = hashes[i]) || (flag == k && untyped keys[i].equals(key))) ) - { + while (!(isEmpty(flag = hashes[i]) || (flag == k && (cast keys[i] : java.lang.Object).equals(key)))) { if (isDel(flag) && delKey == -1) delKey = i; i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } if (isEmpty(flag) && delKey != -1) @@ -108,16 +105,15 @@ import java.NativeArray; x = i; } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end } var flag = hashes[x]; - if (isEmpty(flag)) - { + if (isEmpty(flag)) { keys[x] = key; vals[x] = value; hashes[x] = k; @@ -133,58 +129,55 @@ import java.NativeArray; vals[x] = value; } -#if !no_map_cache + #if !no_map_cache cachedIndex = x; cachedKey = key; -#end + #end } - @:final private function lookup( key : K ) : Int - { - if (nBuckets != 0) - { + private final function lookup(key:K):Int { + if (nBuckets != 0) { var hashes = hashes, keys = _keys; var mask = nBuckets - 1, hash = hash(key), k = hash, nProbes = 0; var i = k & mask; var last = i, flag; - //var inc = getInc(k, mask); - while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || !(untyped keys[i].equals(key)))) - { + // var inc = getInc(k, mask); + while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || !((cast keys[i] : java.lang.Object).equals(key)))) { i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end return isEither(flag) ? -1 : i; } return -1; } - @:final @:private function resize(newNBuckets:Int) : Void - { - //This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. + @:private final function resize(newNBuckets:Int):Void { + // This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. var newHash = null; var j = 1; { newNBuckets = roundUp(newNBuckets); - if (newNBuckets < 4) newNBuckets = 4; - if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */ - { + if (newNBuckets < 4) + newNBuckets = 4; + if (size >= (newNBuckets * HASH_UPPER + 0.5)) + /* requested size is too small */ { j = 0; } else { /* hash table size to be changed (shrink or expand); rehash */ var nfSize = newNBuckets; - newHash = new NativeArray( nfSize ); - if (nBuckets < newNBuckets) //expand + newHash = new NativeArray(nfSize); + if (nBuckets < newNBuckets) // expand { var k = new NativeArray(newNBuckets); if (_keys != null) @@ -195,37 +188,37 @@ import java.NativeArray; if (vals != null) arrayCopy(vals, 0, v, 0, nBuckets); vals = v; - } //otherwise shrink + } // otherwise shrink } } - if (j != 0) - { //rehashing is required - //resetting cache -#if !no_map_cache + if (j != 0) { // rehashing is required + // resetting cache + #if !no_map_cache cachedKey = null; cachedIndex = -1; -#end + #end j = -1; - var nBuckets = nBuckets, _keys = _keys, vals = vals, hashes = hashes; + var nBuckets = nBuckets, + _keys = _keys, + vals = vals, + hashes = hashes; var newMask = newNBuckets - 1; - while (++j < nBuckets) - { + while (++j < nBuckets) { var k; - if (!isEither(k = hashes[j])) - { + if (!isEither(k = hashes[j])) { var key = _keys[j]; var val = vals[j]; _keys[j] = null; vals[j] = cast null; hashes[j] = FLAG_DEL; - while (true) /* kick-out process; sort of like in Cuckoo hashing */ - { + while (true) + /* kick-out process; sort of like in Cuckoo hashing */ { var nProbes = 0; - //var inc = getInc(k, newMask); + // var inc = getInc(k, newMask); var i = k & newMask; while (!isEmpty(newHash[i])) @@ -233,14 +226,13 @@ import java.NativeArray; newHash[i] = k; - if (i < nBuckets && !isEither(k = hashes[i])) /* kick out the existing element */ - { + if (i < nBuckets && !isEither(k = hashes[i])) + /* kick out the existing element */ { { var tmp = _keys[i]; _keys[i] = key; key = tmp; - } - { + } { var tmp = vals[i]; vals[i] = val; val = tmp; @@ -256,14 +248,13 @@ import java.NativeArray; } } - if (nBuckets > newNBuckets) /* shrink the hash table */ - { + if (nBuckets > newNBuckets) + /* shrink the hash table */ { { var k = new NativeArray(newNBuckets); arrayCopy(_keys, 0, k, 0, newNBuckets); this._keys = k; - } - { + } { var v = new NativeArray(newNBuckets); arrayCopy(vals, 0, v, 0, newNBuckets); this.vals = v; @@ -277,23 +268,20 @@ import java.NativeArray; } } - public function get( key : K ) : Null - { + public function get(key:K):Null { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } @@ -301,23 +289,20 @@ import java.NativeArray; return null; } - private function getDefault( key : K, def : V ) : V - { + private function getDefault(key:K, def:V):V { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } @@ -325,23 +310,20 @@ import java.NativeArray; return def; } - public function exists( key : K ) : Bool - { + public function exists(key:K):Bool { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return true; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return true; } @@ -349,24 +331,22 @@ import java.NativeArray; return false; } - public function remove( key : K ) : Bool - { + public function remove(key:K):Bool { var idx = -1; -#if !no_map_cache - if (! (cachedKey == key && ( (idx = cachedIndex) != -1 ))) -#end + #if !no_map_cache + if (!(cachedKey == key && ((idx = cachedIndex) != -1))) + #end { idx = lookup(key); } - if (idx == -1) - { + if (idx == -1) { return false; } else { -#if !no_map_cache + #if !no_map_cache if (cachedKey == key) cachedIndex = -1; -#end + #end hashes[idx] = FLAG_DEL; _keys[idx] = null; @@ -377,52 +357,41 @@ import java.NativeArray; } } - /** - Returns an iterator of all keys in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public function keys() : Iterator - { + public function keys():Iterator { return new ObjectMapKeyIterator(this); } - /** - Returns an iterator of all values in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public function iterator() : Iterator - { + public function iterator():Iterator { return new ObjectMapValueIterator(this); } + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } - public function copy() : ObjectMap { + public function copy():ObjectMap { var copied = new ObjectMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - /** - Returns an displayable representation of the hashtable content. - **/ - - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(Std.string(i)); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - @:extern private static inline function roundUp(x:Int):Int - { + extern private static inline function roundUp(x:Int):Int { --x; x |= (x) >>> 1; x |= (x) >>> 2; @@ -432,38 +401,36 @@ import java.NativeArray; return ++x; } - @:extern private static inline function getInc(k:Int, mask:Int):Int //return 1 for linear probing + extern private static inline function getInc(k:Int, mask:Int):Int // return 1 for linear probing return (((k) >> 3 ^ (k) << 3) | 1) & (mask); - @:extern private static inline function isEither(v:HashType):Bool + extern private static inline function isEither(v:HashType):Bool return (v & 0xFFFFFFFE) == 0; - @:extern private static inline function isEmpty(v:HashType):Bool + extern private static inline function isEmpty(v:HashType):Bool return v == FLAG_EMPTY; - @:extern private static inline function isDel(v:HashType):Bool + extern private static inline function isDel(v:HashType):Bool return v == FLAG_DEL; - //guarantee: Whatever this function is, it will never return 0 nor 1 - @:extern private static inline function hash(s:Dynamic):HashType - { - var k:Int = untyped s.hashCode(); - //k *= 357913941; - //k ^= k << 24; - //k += ~357913941; - //k ^= k >> 31; - //k ^= k << 31; - - k = (k+0x7ed55d16) + (k<<12); - k = (k^0xc761c23c) ^ (k>>19); - k = (k+0x165667b1) + (k<<5); - k = (k+0xd3a2646c) ^ (k<<9); - k = (k+0xfd7046c5) + (k<<3); - k = (k^0xb55a4f09) ^ (k>>16); + // guarantee: Whatever this function is, it will never return 0 nor 1 + extern private static inline function hash(s:Dynamic):HashType { + var k:Int = (cast s : java.lang.Object).hashCode(); + // k *= 357913941; + // k ^= k << 24; + // k += ~357913941; + // k ^= k >> 31; + // k ^= k << 31; + + k = (k + 0x7ed55d16) + (k << 12); + k = (k ^ 0xc761c23c) ^ (k >> 19); + k = (k + 0x165667b1) + (k << 5); + k = (k + 0xd3a2646c) ^ (k << 9); + k = (k + 0xfd7046c5) + (k << 3); + k = (k ^ 0xb55a4f09) ^ (k >> 16); var ret = k; - if (isEither(ret)) - { + if (isEither(ret)) { if (ret == 0) ret = 2; else @@ -473,35 +440,32 @@ import java.NativeArray; return ret; } - @:extern private static inline function arrayCopy(sourceArray:Dynamic, sourceIndex:Int, destinationArray:Dynamic, destinationIndex:Int, length:Int):Void + extern private static inline function arrayCopy(sourceArray:Dynamic, sourceIndex:Int, destinationArray:Dynamic, destinationIndex:Int, length:Int):Void java.lang.System.arraycopy(sourceArray, sourceIndex, destinationArray, destinationIndex, length); - @:extern private static inline function assert(x:Bool):Void - { -#if DEBUG_HASHTBL - if (!x) throw "assert failed"; -#end + extern private static inline function assert(x:Bool):Void { + #if DEBUG_HASHTBL + if (!x) + throw "assert failed"; + #end } } @:access(haxe.ds.ObjectMap) -@:final -private class ObjectMapKeyIterator { - var m:ObjectMap; +private final class ObjectMapKeyIterator { + var m:ObjectMap; var i:Int; var len:Int; - public function new(m:ObjectMap) { + public function new(m:ObjectMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } public function hasNext():Bool { - for (j in i...len) - { - if (!ObjectMap.isEither(m.hashes[j])) - { + for (j in i...len) { + if (!ObjectMap.isEither(m.hashes[j])) { i = j; return true; } @@ -509,13 +473,13 @@ private class ObjectMapKeyIterator { return false; } - public function next() : T { + public function next():T { var ret = m._keys[i]; -#if !no_map_cache + #if !no_map_cache m.cachedIndex = i; m.cachedKey = ret; -#end + #end i = i + 1; return ret; @@ -523,24 +487,20 @@ private class ObjectMapKeyIterator { } @:access(haxe.ds.ObjectMap) -@:final -private class ObjectMapValueIterator { - var m:ObjectMap; +private final class ObjectMapValueIterator { + var m:ObjectMap; var i:Int; var len:Int; - public function new(m:ObjectMap) - { + public function new(m:ObjectMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } - public function hasNext() : Bool { - for (j in i...len) - { - if (!ObjectMap.isEither(m.hashes[j])) - { + public function hasNext():Bool { + for (j in i...len) { + if (!ObjectMap.isEither(m.hashes[j])) { i = j; return true; } diff --git a/std/java/_std/haxe/ds/StringMap.hx b/std/java/_std/haxe/ds/StringMap.hx index 7458a7e1380..6cb5d8531b1 100644 --- a/std/java/_std/haxe/ds/StringMap.hx +++ b/std/java/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,15 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; import java.NativeArray; -@:coreApi class StringMap implements haxe.Constraints.IMap -{ - @:extern private static inline var HASH_UPPER = 0.77; - @:extern private static inline var FLAG_EMPTY = 0; - @:extern private static inline var FLAG_DEL = 1; +@:coreApi class StringMap implements haxe.Constraints.IMap { + extern private static inline var HASH_UPPER = 0.77; + extern private static inline var FLAG_EMPTY = 0; + extern private static inline var FLAG_DEL = 1; /** * This is the most important structure here and the reason why it's so fast. @@ -38,6 +38,7 @@ import java.NativeArray; * The insertion algorithm will do the same but will also break when FLAG_DEL is found; */ private var hashes:NativeArray; + private var _keys:NativeArray; private var vals:NativeArray; @@ -46,33 +47,29 @@ import java.NativeArray; private var nOccupied:Int; private var upperBound:Int; -#if !no_map_cache + #if !no_map_cache private var cachedKey:String; private var cachedIndex:Int; -#end + #end -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL private var totalProbes:Int; private var probeTimes:Int; private var sameHash:Int; private var maxProbe:Int; -#end + #end - public function new() : Void - { -#if !no_map_cache + public function new():Void { + #if !no_map_cache cachedIndex = -1; -#end + #end } - public function set( key : String, value : T ) : Void - { + public function set(key:String, value:T):Void { var x:Int, k:Int; - if (nOccupied >= upperBound) - { - if (nBuckets > (size << 1)) - { - resize(nBuckets - 1); //clear "deleted" elements + if (nOccupied >= upperBound) { + if (nBuckets > (size << 1)) { + resize(nBuckets - 1); // clear "deleted" elements } else { resize(nBuckets + 2); } @@ -91,38 +88,34 @@ import java.NativeArray; x = i; } else { var last = i, flag; - while(! (isEmpty(flag = hashes[i]) || (flag == k && _keys[i] == key)) ) - { - if (isDel(flag) && delKey == -1) - { + while (!(isEmpty(flag = hashes[i]) || (flag == k && _keys[i] == key))) { + if (isDel(flag) && delKey == -1) { delKey = i; } i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } - if (isEmpty(flag) && delKey != -1) - { + if (isEmpty(flag) && delKey != -1) { x = delKey; } else { x = i; } } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end } var flag = hashes[x]; - if (isEmpty(flag)) - { + if (isEmpty(flag)) { keys[x] = key; vals[x] = value; hashes[x] = k; @@ -138,58 +131,55 @@ import java.NativeArray; vals[x] = value; } -#if !no_map_cache + #if !no_map_cache cachedIndex = x; cachedKey = key; -#end + #end } - @:final private function lookup( key : String ) : Int - { - if (nBuckets != 0) - { + private final function lookup(key:String):Int { + if (nBuckets != 0) { var hashes = hashes, keys = _keys; var mask = nBuckets - 1, hash = hash(key), k = hash, nProbes = 0; var i = k & mask; var last = i, flag; // if we hit an empty bucket, it means we're done - while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || keys[i] != key)) - { + while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || keys[i] != key)) { i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end return isEither(flag) ? -1 : i; } return -1; } - @:final @:private function resize(newNBuckets:Int) : Void - { - //This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. + @:private final function resize(newNBuckets:Int):Void { + // This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. var newHash = null; var j = 1; { newNBuckets = roundUp(newNBuckets); - if (newNBuckets < 4) newNBuckets = 4; - if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */ - { + if (newNBuckets < 4) + newNBuckets = 4; + if (size >= (newNBuckets * HASH_UPPER + 0.5)) + /* requested size is too small */ { j = 0; } else { /* hash table size to be changed (shrink or expand); rehash */ var nfSize = newNBuckets; - newHash = new NativeArray( nfSize ); - if (nBuckets < newNBuckets) //expand + newHash = new NativeArray(nfSize); + if (nBuckets < newNBuckets) // expand { var k = new NativeArray(newNBuckets); if (_keys != null) @@ -200,53 +190,51 @@ import java.NativeArray; if (vals != null) arrayCopy(vals, 0, v, 0, nBuckets); vals = v; - } //otherwise shrink + } // otherwise shrink } } - if (j != 0) - { //rehashing is required - //resetting cache -#if !no_map_cache + if (j != 0) { // rehashing is required + // resetting cache + #if !no_map_cache cachedKey = null; cachedIndex = -1; -#end + #end j = -1; - var nBuckets = nBuckets, _keys = _keys, vals = vals, hashes = hashes; + var nBuckets = nBuckets, + _keys = _keys, + vals = vals, + hashes = hashes; var newMask = newNBuckets - 1; - while (++j < nBuckets) - { + while (++j < nBuckets) { var k; - if (!isEither(k = hashes[j])) - { + if (!isEither(k = hashes[j])) { var key = _keys[j]; var val = vals[j]; _keys[j] = null; vals[j] = cast null; hashes[j] = FLAG_DEL; - while (true) /* kick-out process; sort of like in Cuckoo hashing */ - { + while (true) + /* kick-out process; sort of like in Cuckoo hashing */ { var nProbes = 0; var i = k & newMask; - while (!isEmpty(newHash[i])) - { + while (!isEmpty(newHash[i])) { i = (i + ++nProbes) & newMask; } newHash[i] = k; - if (i < nBuckets && !isEither(k = hashes[i])) /* kick out the existing element */ - { + if (i < nBuckets && !isEither(k = hashes[i])) + /* kick out the existing element */ { { var tmp = _keys[i]; _keys[i] = key; key = tmp; - } - { + } { var tmp = vals[i]; vals[i] = val; val = tmp; @@ -262,14 +250,13 @@ import java.NativeArray; } } - if (nBuckets > newNBuckets) /* shrink the hash table */ - { + if (nBuckets > newNBuckets) + /* shrink the hash table */ { { var k = new NativeArray(newNBuckets); arrayCopy(_keys, 0, k, 0, newNBuckets); this._keys = k; - } - { + } { var v = new NativeArray(newNBuckets); arrayCopy(vals, 0, v, 0, newNBuckets); this.vals = v; @@ -283,45 +270,39 @@ import java.NativeArray; } } - public function get( key : String ) : Null - { + public function get(key:String):Null { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } return null; } - private function getDefault( key : String, def : T ) : T - { + private function getDefault(key:String, def:T):T { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return vals[idx]; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return vals[idx]; } @@ -329,49 +310,43 @@ import java.NativeArray; return def; } - public function exists( key : String ) : Bool - { + public function exists(key:String):Bool { var idx = -1; -#if !no_map_cache - if (cachedKey == key && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedKey == key && ((idx = cachedIndex) != -1)) { return true; } -#end + #end idx = lookup(key); - if (idx != -1) - { -#if !no_map_cache + if (idx != -1) { + #if !no_map_cache cachedKey = key; cachedIndex = idx; -#end + #end return true; } return false; } - public function remove( key : String ) : Bool - { + public function remove(key:String):Bool { var idx = -1; -#if !no_map_cache - if (! (cachedKey == key && ( (idx = cachedIndex) != -1 ))) -#end + #if !no_map_cache + if (!(cachedKey == key && ((idx = cachedIndex) != -1))) + #end { idx = lookup(key); } - if (idx == -1) - { + if (idx == -1) { return false; } else { -#if !no_map_cache - if (cachedKey == key) - { + #if !no_map_cache + if (cachedKey == key) { cachedIndex = -1; } -#end + #end hashes[idx] = FLAG_DEL; _keys[idx] = null; vals[idx] = null; @@ -381,51 +356,41 @@ import java.NativeArray; } } - /** - Returns an iterator of all keys in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function keys() : Iterator - { + public inline function keys():Iterator { return new StringMapKeyIterator(this); } - /** - Returns an iterator of all values in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function iterator() : Iterator - { + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public inline function iterator():Iterator { return new StringMapValueIterator(this); } - public function copy() : StringMap { + public function copy():StringMap { var copied = new StringMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - /** - Returns an displayable representation of the hashtable content. - **/ - - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(i); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - @:extern private static inline function roundUp(x:Int):Int - { + extern private static inline function roundUp(x:Int):Int { --x; x |= (x) >>> 1; x |= (x) >>> 2; @@ -435,38 +400,36 @@ import java.NativeArray; return ++x; } - @:extern private static inline function getInc(k:Int, mask:Int):Int //return 1 for linear probing + extern private static inline function getInc(k:Int, mask:Int):Int // return 1 for linear probing return (((k) >> 3 ^ (k) << 3) | 1) & (mask); - @:extern private static inline function isEither(v:HashType):Bool + extern private static inline function isEither(v:HashType):Bool return (v & 0xFFFFFFFE) == 0; - @:extern private static inline function isEmpty(v:HashType):Bool + extern private static inline function isEmpty(v:HashType):Bool return v == FLAG_EMPTY; - @:extern private static inline function isDel(v:HashType):Bool + extern private static inline function isDel(v:HashType):Bool return v == FLAG_DEL; - //guarantee: Whatever this function is, it will never return 0 nor 1 - @:extern private static inline function hash(s:String):HashType - { - var k:Int = untyped s.hashCode(); - //k *= 357913941; - //k ^= k << 24; - //k += ~357913941; - //k ^= k >> 31; - //k ^= k << 31; - - k = (k+0x7ed55d16) + (k<<12); - k = (k^0xc761c23c) ^ (k>>19); - k = (k+0x165667b1) + (k<<5); - k = (k+0xd3a2646c) ^ (k<<9); - k = (k+0xfd7046c5) + (k<<3); - k = (k^0xb55a4f09) ^ (k>>16); + // guarantee: Whatever this function is, it will never return 0 nor 1 + extern private static inline function hash(s:String):HashType { + var k:Int = (cast s : java.NativeString).hashCode(); + // k *= 357913941; + // k ^= k << 24; + // k += ~357913941; + // k ^= k >> 31; + // k ^= k << 31; + + k = (k + 0x7ed55d16) + (k << 12); + k = (k ^ 0xc761c23c) ^ (k >> 19); + k = (k + 0x165667b1) + (k << 5); + k = (k + 0xd3a2646c) ^ (k << 9); + k = (k + 0xfd7046c5) + (k << 3); + k = (k ^ 0xb55a4f09) ^ (k >> 16); var ret = k; - if (isEither(ret)) - { + if (isEither(ret)) { if (ret == 0) ret = 2; else @@ -476,40 +439,34 @@ import java.NativeArray; return ret; } - @:extern private static inline function arrayCopy(sourceArray:Dynamic, sourceIndex:Int, destinationArray:Dynamic, destinationIndex:Int, length:Int):Void + extern private static inline function arrayCopy(sourceArray:Dynamic, sourceIndex:Int, destinationArray:Dynamic, destinationIndex:Int, length:Int):Void java.lang.System.arraycopy(sourceArray, sourceIndex, destinationArray, destinationIndex, length); - @:extern private static inline function assert(x:Bool):Void - { -#if DEBUG_HASHTBL - if (!x) throw "assert failed"; -#end + extern private static inline function assert(x:Bool):Void { + #if DEBUG_HASHTBL + if (!x) + throw "assert failed"; + #end } } private typedef HashType = Int; -@:final @:access(haxe.ds.StringMap) -private class StringMapKeyIterator -{ +private final class StringMapKeyIterator { var m:StringMap; var i:Int; var len:Int; - public function new(m:StringMap) - { + public function new(m:StringMap) { this.m = m; this.i = 0; this.len = m.nBuckets; } - public function hasNext():Bool - { - for (j in i...len) - { - if (!StringMap.isEither(m.hashes[j])) - { + public function hasNext():Bool { + for (j in i...len) { + if (!StringMap.isEither(m.hashes[j])) { i = j; return true; } @@ -517,39 +474,32 @@ private class StringMapKeyIterator return false; } - public function next():String - { + public function next():String { var ret = m._keys[i]; -#if !no_map_cache + #if !no_map_cache m.cachedIndex = i; m.cachedKey = ret; -#end + #end i++; return ret; } } -@:final @:access(haxe.ds.StringMap) -private class StringMapValueIterator -{ +private final class StringMapValueIterator { var m:StringMap; var i:Int; var len:Int; - public function new(m:StringMap) - { + public function new(m:StringMap) { this.m = m; this.i = 0; this.len = m.nBuckets; } - public function hasNext():Bool - { - for (j in i...len) - { - if (!StringMap.isEither(m.hashes[j])) - { + public function hasNext():Bool { + for (j in i...len) { + if (!StringMap.isEither(m.hashes[j])) { i = j; return true; } @@ -557,8 +507,7 @@ private class StringMapValueIterator return false; } - public inline function next():T - { + public inline function next():T { return m.vals[i++]; } } diff --git a/std/java/_std/haxe/ds/WeakMap.hx b/std/java/_std/haxe/ds/WeakMap.hx index c627bf6c79a..21a96a971ca 100644 --- a/std/java/_std/haxe/ds/WeakMap.hx +++ b/std/java/_std/haxe/ds/WeakMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,17 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; import java.NativeArray; import java.lang.ref.WeakReference; import java.lang.ref.ReferenceQueue; -@:coreApi class WeakMap implements haxe.Constraints.IMap -{ - @:extern private static inline var HASH_UPPER = 0.77; - @:extern private static inline var FLAG_EMPTY = 0; - @:extern private static inline var FLAG_DEL = 1; +@:coreApi class WeakMap implements haxe.Constraints.IMap { + extern private static inline var HASH_UPPER = 0.77; + extern private static inline var FLAG_EMPTY = 0; + extern private static inline var FLAG_DEL = 1; /** * This is the most important structure here and the reason why it's so fast. @@ -40,9 +40,10 @@ import java.lang.ref.ReferenceQueue; * The insertion algorithm will do the same but will also break when FLAG_DEL is found; */ private var hashes:NativeArray; - private var entries:NativeArray>; - //weak map specific + private var entries:NativeArray>; + + // weak map specific private var queue:ReferenceQueue; private var nBuckets:Int; @@ -50,56 +51,49 @@ import java.lang.ref.ReferenceQueue; private var nOccupied:Int; private var upperBound:Int; -#if !no_map_cache - private var cachedEntry:Entry; + #if !no_map_cache + private var cachedEntry:Entry; private var cachedIndex:Int; -#end + #end -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL private var totalProbes:Int; private var probeTimes:Int; private var sameHash:Int; private var maxProbe:Int; -#end + #end - public function new() : Void - { -#if !no_map_cache + public function new():Void { + #if !no_map_cache cachedIndex = -1; -#end + #end queue = new ReferenceQueue(); } @:analyzer(ignore) - private function cleanupRefs():Void - { + private function cleanupRefs():Void { var x:Dynamic = null, nOccupied = nOccupied; - while (( x = queue.poll()) != null) - { - //even if not found on hashtable (already removed), release value - var x:Entry = cast x; + while ((x = queue.poll()) != null) { + // even if not found on hashtable (already removed), release value + var x:Entry = cast x; x.value = null; - //lookup index - if (nOccupied != 0) - { + // lookup index + if (nOccupied != 0) { var mask = nBuckets - 1, hash = x.hash, nProbes = 0; var i = hash & mask; var last = i, flag; - while(!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != hash || entries[i] != x)) - { + while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != hash || entries[i] != x)) { i = (i + ++nProbes) & mask; } - if (entries[i] == x) - { -#if !no_map_cache - if (cachedIndex == i) - { + if (entries[i] == x) { + #if !no_map_cache + if (cachedIndex == i) { cachedIndex = -1; cachedEntry = null; } -#end + #end entries[i] = null; hashes[i] = FLAG_DEL; --size; @@ -108,14 +102,12 @@ import java.lang.ref.ReferenceQueue; } } - public function set( key : K, value : V ) : Void - { + public function set(key:K, value:V):Void { cleanupRefs(); var x:Int, k:Int; - if (nOccupied >= upperBound) - { + if (nOccupied >= upperBound) { if (nBuckets > (size << 1)) - resize(nBuckets - 1); //clear "deleted" elements + resize(nBuckets - 1); // clear "deleted" elements else resize(nBuckets + 2); } @@ -128,22 +120,21 @@ import java.lang.ref.ReferenceQueue; var i = k & mask, nProbes = 0; var delKey = -1; - //for speed up + // for speed up if (isEmpty(hashes[i])) { x = i; } else { - //var inc = getInc(k, mask); + // var inc = getInc(k, mask); var last = i, flag; - while(! (isEmpty(flag = hashes[i]) || (flag == k && entries[i].keyEquals(key) )) ) - { + while (!(isEmpty(flag = hashes[i]) || (flag == k && entries[i].keyEquals(key)))) { if (delKey == -1 && isDel(flag)) delKey = i; i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } if (isEmpty(flag) && delKey != -1) @@ -152,16 +143,15 @@ import java.lang.ref.ReferenceQueue; x = i; } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end } - var flag = hashes[x], entry = new Entry(key,value,k,queue); - if (isEmpty(flag)) - { + var flag = hashes[x], entry = new Entry(key, value, k, queue); + if (isEmpty(flag)) { entries[x] = entry; hashes[x] = k; size++; @@ -175,90 +165,84 @@ import java.lang.ref.ReferenceQueue; entries[x] = entry; } -#if !no_map_cache + #if !no_map_cache cachedIndex = x; cachedEntry = entry; -#end + #end } - @:final private function lookup( key : K ) : Int - { - if (nBuckets != 0) - { + private final function lookup(key:K):Int { + if (nBuckets != 0) { var hashes = hashes, entries = entries; var mask = nBuckets - 1, hash = hash(key), k = hash, nProbes = 0; var i = k & mask; var last = i, flag; - //var inc = getInc(k, mask); - while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || !entries[i].keyEquals(key))) - { + // var inc = getInc(k, mask); + while (!isEmpty(flag = hashes[i]) && (isDel(flag) || flag != k || !entries[i].keyEquals(key))) { i = (i + ++nProbes) & mask; -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL probeTimes++; if (i == last) throw "assert"; -#end + #end } -#if DEBUG_HASHTBL + #if DEBUG_HASHTBL if (nProbes > maxProbe) maxProbe = nProbes; totalProbes++; -#end + #end return isEither(flag) ? -1 : i; } return -1; } - @:final @:private function resize(newNBuckets:Int) : Void - { - //This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. + @:private final function resize(newNBuckets:Int):Void { + // This function uses 0.25*n_bucktes bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. var newHash = null; var j = 1; { newNBuckets = roundUp(newNBuckets); - if (newNBuckets < 4) newNBuckets = 4; - if (size >= (newNBuckets * HASH_UPPER + 0.5)) /* requested size is too small */ - { + if (newNBuckets < 4) + newNBuckets = 4; + if (size >= (newNBuckets * HASH_UPPER + 0.5)) + /* requested size is too small */ { j = 0; } else { /* hash table size to be changed (shrink or expand); rehash */ var nfSize = newNBuckets; - newHash = new NativeArray( nfSize ); - if (nBuckets < newNBuckets) //expand + newHash = new NativeArray(nfSize); + if (nBuckets < newNBuckets) // expand { var e = new NativeArray(newNBuckets); if (entries != null) arrayCopy(entries, 0, e, 0, nBuckets); entries = e; - } //otherwise shrink + } // otherwise shrink } } - if (j != 0) - { //rehashing is required - //resetting cache -#if !no_map_cache + if (j != 0) { // rehashing is required + // resetting cache + #if !no_map_cache cachedEntry = null; cachedIndex = -1; -#end + #end j = -1; var nBuckets = nBuckets, entries = entries, hashes = hashes; var newMask = newNBuckets - 1; - while (++j < nBuckets) - { + while (++j < nBuckets) { var k; - if (!isEither(k = hashes[j])) - { + if (!isEither(k = hashes[j])) { var entry = entries[j]; entries[j] = null; hashes[j] = FLAG_DEL; - while (true) /* kick-out process; sort of like in Cuckoo hashing */ - { + while (true) + /* kick-out process; sort of like in Cuckoo hashing */ { var nProbes = 0; var i = k & newMask; @@ -267,8 +251,8 @@ import java.lang.ref.ReferenceQueue; newHash[i] = k; - if (i < nBuckets && !isEither(k = hashes[i])) /* kick out the existing element */ - { + if (i < nBuckets && !isEither(k = hashes[i])) + /* kick out the existing element */ { { var tmp = entries[i]; entries[i] = entry; @@ -284,8 +268,8 @@ import java.lang.ref.ReferenceQueue; } } - if (nBuckets > newNBuckets) /* shrink the hash table */ - { + if (nBuckets > newNBuckets) + /* shrink the hash table */ { { var e = new NativeArray(newNBuckets); arrayCopy(entries, 0, e, 0, newNBuckets); @@ -300,25 +284,22 @@ import java.lang.ref.ReferenceQueue; } } - public function get( key : K ) : Null - { + public function get(key:K):Null { cleanupRefs(); var idx = -1; -#if !no_map_cache - if (cachedEntry != null && cachedEntry.keyEquals(key) && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedEntry != null && cachedEntry.keyEquals(key) && ((idx = cachedIndex) != -1)) { return cachedEntry.value; } -#end + #end idx = lookup(key); - if (idx != -1) - { + if (idx != -1) { var entry = entries[idx]; -#if !no_map_cache + #if !no_map_cache cachedEntry = entry; cachedIndex = idx; -#end + #end return entry.value; } @@ -326,25 +307,22 @@ import java.lang.ref.ReferenceQueue; return null; } - private function getDefault( key : K, def : V ) : V - { + private function getDefault(key:K, def:V):V { cleanupRefs(); var idx = -1; -#if !no_map_cache - if (cachedEntry != null && cachedEntry.keyEquals(key) && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedEntry != null && cachedEntry.keyEquals(key) && ((idx = cachedIndex) != -1)) { return cachedEntry.value; } -#end + #end idx = lookup(key); - if (idx != -1) - { + if (idx != -1) { var entry = entries[idx]; -#if !no_map_cache + #if !no_map_cache cachedEntry = entry; cachedIndex = idx; -#end + #end return entry.value; } @@ -352,25 +330,22 @@ import java.lang.ref.ReferenceQueue; return def; } - public function exists( key : K ) : Bool - { + public function exists(key:K):Bool { cleanupRefs(); var idx = -1; -#if !no_map_cache - if (cachedEntry != null && cachedEntry.keyEquals(key) && ( (idx = cachedIndex) != -1 )) - { + #if !no_map_cache + if (cachedEntry != null && cachedEntry.keyEquals(key) && ((idx = cachedIndex) != -1)) { return true; } -#end + #end idx = lookup(key); - if (idx != -1) - { + if (idx != -1) { var entry = entries[idx]; -#if !no_map_cache + #if !no_map_cache cachedEntry = entry; cachedIndex = idx; -#end + #end return true; } @@ -378,28 +353,25 @@ import java.lang.ref.ReferenceQueue; return false; } - public function remove( key : K ) : Bool - { + public function remove(key:K):Bool { cleanupRefs(); var idx = -1; -#if !no_map_cache - if ( !(cachedEntry != null && cachedEntry.keyEquals(key) && ( (idx = cachedIndex) != -1 )) ) -#end + #if !no_map_cache + if (!(cachedEntry != null && cachedEntry.keyEquals(key) && ((idx = cachedIndex) != -1))) + #end { idx = lookup(key); } - if (idx == -1) - { + if (idx == -1) { return false; } else { -#if !no_map_cache - if (cachedEntry != null && cachedEntry.keyEquals(key)) - { + #if !no_map_cache + if (cachedEntry != null && cachedEntry.keyEquals(key)) { cachedIndex = -1; cachedEntry = null; } -#end + #end hashes[idx] = FLAG_DEL; entries[idx] = null; @@ -409,54 +381,43 @@ import java.lang.ref.ReferenceQueue; } } - /** - Returns an iterator of all keys in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function keys() : Iterator - { + public inline function keys():Iterator { cleanupRefs(); return new WeakMapKeyIterator(this); } - /** - Returns an iterator of all values in the hashtable. - Implementation detail: Do not set() any new value while iterating, as it may cause a resize, which will break iteration - **/ - public inline function iterator() : Iterator - { + public inline function iterator():Iterator { cleanupRefs(); return new WeakMapValueIterator(this); } + public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } - public function copy() : WeakMap { + public function copy():WeakMap { var copied = new WeakMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - /** - Returns an displayable representation of the hashtable content. - **/ - - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(Std.string(i)); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - @:extern private static inline function roundUp(x:Int):Int - { + extern private static inline function roundUp(x:Int):Int { --x; x |= (x) >>> 1; x |= (x) >>> 2; @@ -466,38 +427,36 @@ import java.lang.ref.ReferenceQueue; return ++x; } - @:extern private static inline function getInc(k:Int, mask:Int):Int //return 1 for linear probing + extern private static inline function getInc(k:Int, mask:Int):Int // return 1 for linear probing return (((k) >> 3 ^ (k) << 3) | 1) & (mask); - @:extern private static inline function isEither(v:HashType):Bool + extern private static inline function isEither(v:HashType):Bool return (v & 0xFFFFFFFE) == 0; - @:extern private static inline function isEmpty(v:HashType):Bool + extern private static inline function isEmpty(v:HashType):Bool return v == FLAG_EMPTY; - @:extern private static inline function isDel(v:HashType):Bool + extern private static inline function isDel(v:HashType):Bool return v == FLAG_DEL; - //guarantee: Whatever this function is, it will never return 0 nor 1 - @:extern private static inline function hash(s:Dynamic):HashType - { + // guarantee: Whatever this function is, it will never return 0 nor 1 + extern private static inline function hash(s:Dynamic):HashType { var k:Int = untyped s.hashCode(); - //k *= 357913941; - //k ^= k << 24; - //k += ~357913941; - //k ^= k >> 31; - //k ^= k << 31; - - k = (k+0x7ed55d16) + (k<<12); - k = (k^0xc761c23c) ^ (k>>19); - k = (k+0x165667b1) + (k<<5); - k = (k+0xd3a2646c) ^ (k<<9); - k = (k+0xfd7046c5) + (k<<3); - k = (k^0xb55a4f09) ^ (k>>16); + // k *= 357913941; + // k ^= k << 24; + // k += ~357913941; + // k ^= k >> 31; + // k ^= k << 31; + + k = (k + 0x7ed55d16) + (k << 12); + k = (k ^ 0xc761c23c) ^ (k >> 19); + k = (k + 0x165667b1) + (k << 5); + k = (k + 0xd3a2646c) ^ (k << 9); + k = (k + 0xfd7046c5) + (k << 3); + k = (k ^ 0xb55a4f09) ^ (k >> 16); var ret = k; - if (isEither(ret)) - { + if (isEither(ret)) { if (ret == 0) ret = 2; else @@ -507,61 +466,54 @@ import java.lang.ref.ReferenceQueue; return ret; } - @:extern private static inline function arrayCopy(sourceArray:Dynamic, sourceIndex:Int, destinationArray:Dynamic, destinationIndex:Int, length:Int):Void + extern private static inline function arrayCopy(sourceArray:Dynamic, sourceIndex:Int, destinationArray:Dynamic, destinationIndex:Int, length:Int):Void java.lang.System.arraycopy(sourceArray, sourceIndex, destinationArray, destinationIndex, length); - @:extern private static inline function assert(x:Bool):Void - { -#if DEBUG_HASHTBL - if (!x) throw "assert failed"; -#end + extern private static inline function assert(x:Bool):Void { + #if DEBUG_HASHTBL + if (!x) + throw "assert failed"; + #end } } -private class Entry extends WeakReference -{ +private class Entry extends WeakReference { public var value:V; public var hash(default, null):Int; - public function new(key:K, value:V, hash:Int, queue:ReferenceQueue) - { + + public function new(key:K, value:V, hash:Int, queue:ReferenceQueue) { super(key, queue); this.value = value; this.hash = hash; } - @:final inline public function keyEquals(k:K):Bool - { + final inline public function keyEquals(k:K):Bool { return k != null && untyped k.equals(get()); } } @:access(haxe.ds.WeakMap) -@:final -private class WeakMapKeyIterator { - var m:WeakMap; +private final class WeakMapKeyIterator { + var m:WeakMap; var i:Int; var len:Int; var lastKey:T; - public function new(m:WeakMap) { + public function new(m:WeakMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } public function hasNext():Bool { - for (j in i...len) - { - if (!WeakMap.isEither(m.hashes[j])) - { - var entry = m.entries[j], - last = entry.get(); - if (last != null) - { -#if !no_map_cache + for (j in i...len) { + if (!WeakMap.isEither(m.hashes[j])) { + var entry = m.entries[j], last = entry.get(); + if (last != null) { + #if !no_map_cache m.cachedIndex = i; m.cachedEntry = entry; -#end + #end lastKey = last; // keep a strong reference to the key while iterating, so it doesn't get collected i = j; return true; @@ -572,31 +524,27 @@ private class WeakMapKeyIterator { return false; } - public function next() : T { + public function next():T { i = i + 1; return lastKey; } } @:access(haxe.ds.WeakMap) -@:final -private class WeakMapValueIterator { - var m:WeakMap; +private final class WeakMapValueIterator { + var m:WeakMap; var i:Int; var len:Int; - public function new(m:WeakMap) - { + public function new(m:WeakMap) { this.i = 0; this.m = m; this.len = m.nBuckets; } - public function hasNext() : Bool { - for (j in i...len) - { - if (!WeakMap.isEither(m.hashes[j]) && m.entries[j].get() != null) - { + public function hasNext():Bool { + for (j in i...len) { + if (!WeakMap.isEither(m.hashes[j]) && m.entries[j].get() != null) { i = j; return true; } diff --git a/std/java/_std/haxe/zip/Compress.hx b/std/java/_std/haxe/zip/Compress.hx index 41050626d74..b77a513abe9 100644 --- a/std/java/_std/haxe/zip/Compress.hx +++ b/std/java/_std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,24 +19,23 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; + import java.util.zip.Deflater; -class Compress -{ +class Compress { var deflater:Deflater; var mode:Int; var finish:Bool = false; - public function new( level : Int ) - { - throw "Not implemented for this platform"; //FIXME: Add unit tests for Compress/Uncompress and check current implementation + public function new(level:Int) { + throw "Not implemented for this platform"; // FIXME: Add unit tests for Compress/Uncompress and check current implementation this.deflater = new Deflater(level); this.mode = Deflater.NO_FLUSH; } - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } - { + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { deflater.setInput(src.getData(), srcPos, src.length - srcPos); if (finish) deflater.finish(); @@ -44,11 +43,10 @@ class Compress var written = deflater.deflate(dst.getData(), dstPos, dst.length - dstPos); var read = deflater.getTotalIn(); - return { done: deflater.finished(), read: read, write: written }; + return {done: deflater.finished(), read: read, write: written}; } - public function setFlushMode( f : FlushMode ) - { + public function setFlushMode(f:FlushMode) { this.mode = switch (f) { case NO: Deflater.NO_FLUSH; @@ -64,13 +62,11 @@ class Compress } } - public function close() - { + public function close() { deflater.end(); } - public static function run( s : haxe.io.Bytes, level : Int ) : haxe.io.Bytes - { + public static function run(s:haxe.io.Bytes, level:Int):haxe.io.Bytes { var deflater = new java.util.zip.Deflater(level); deflater.setInput(s.getData()); var outputStream = new java.io.ByteArrayOutputStream(s.length); diff --git a/std/java/_std/haxe/zip/Uncompress.hx b/std/java/_std/haxe/zip/Uncompress.hx index e6c1f1f59b7..b7012002692 100644 --- a/std/java/_std/haxe/zip/Uncompress.hx +++ b/std/java/_std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,40 +19,46 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.zip; -class Uncompress -{ - public function new( ?windowBits : Int ) { - throw "Not implemented for this platform"; - } +import java.util.zip.Inflater; + +class Uncompress { + final inflater:Inflater; - public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { - return null; + public function new(?windowBits:Int) { + inflater = new Inflater(windowBits != null && windowBits < 0); } - public function setFlushMode( f : FlushMode ) { + public function execute(src:haxe.io.Bytes, srcPos:Int, dst:haxe.io.Bytes, dstPos:Int):{done:Bool, read:Int, write:Int} { + inflater.setInput(src.getData(), srcPos, src.length - srcPos); + inflater.inflate(dst.getData(), dstPos, dst.length - dstPos); + return { + done: inflater.finished(), + read: Int64.toInt(inflater.getBytesRead()), + write: Int64.toInt(inflater.getBytesWritten()) + }; } + public function setFlushMode(f:FlushMode) {} + public function close() { + inflater.end(); } - public static function run( src : haxe.io.Bytes, ?bufsize : Int ) : haxe.io.Bytes - { + public static function run(src:haxe.io.Bytes, ?bufsize:Int):haxe.io.Bytes { var decompresser = new java.util.zip.Inflater(); var buf = haxe.io.Bytes.alloc(bufsize == null ? src.length : bufsize).getData(); var out = new java.io.ByteArrayOutputStream(src.length); decompresser.setInput(src.getData(), 0, src.length); - while (!decompresser.finished()) - { + while (!decompresser.finished()) { var count = decompresser.inflate(buf); out.write(buf, 0, count); } out.close(); return haxe.io.Bytes.ofData(out.toByteArray()); } - } - diff --git a/std/java/_std/sys/FileSystem.hx b/std/java/_std/sys/FileSystem.hx index afedca55fc4..1c45f687fc9 100644 --- a/std/java/_std/sys/FileSystem.hx +++ b/std/java/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,92 +19,84 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys; + import java.io.File; import java.Lib; @:coreApi class FileSystem { - - public static function exists( path : String ) : Bool - { + public static function exists(path:String):Bool { return new File(path).exists(); } - public static function rename( path : String, newPath : String ) : Void - { - if (!new File(path).renameTo(new File(newPath))) - { + public static function rename(path:String, newPath:String):Void { + if (!new File(path).renameTo(new File(newPath))) { throw "Cannot rename " + path + " to " + newPath; } } - public static function stat( path : String ) : FileStat - { + public static function stat(path:String):FileStat { var f = new File(path); if (!f.exists()) throw "Path " + path + " doesn't exist"; return { - gid: 0, //java doesn't let you get this info - uid: 0, //same - atime: Date.now(), //same + gid: 0, // java doesn't let you get this info + uid: 0, // same + atime: Date.now(), // same mtime: Date.fromTime(cast(f.lastModified(), Float)), - ctime: Date.fromTime(cast(f.lastModified(), Float)), //same - size: cast(f.length(), Int), //TODO: maybe change to Int64 for Haxe 3? - dev: 0, //FIXME: not sure what that is - ino: 0, //FIXME: not sure what that is - nlink: 0, //FIXME: not sure what that is - rdev: 0, //FIXME: not sure what that is - mode: 0 //FIXME: not sure what that is + ctime: Date.fromTime(cast(f.lastModified(), Float)), // same + size: cast(f.length(), Int), // TODO: maybe change to Int64 for Haxe 3? + dev: 0, // FIXME: not sure what that is + ino: 0, // FIXME: not sure what that is + nlink: 0, // FIXME: not sure what that is + rdev: 0, // FIXME: not sure what that is + mode: 0 // FIXME: not sure what that is }; } - public static function fullPath( relPath : String ) : String - { + public static function fullPath(relPath:String):String { try { return new File(relPath).getCanonicalPath(); - } catch (e: java.io.IOException) { + } catch (e:java.io.IOException) { throw new java.lang.RuntimeException(e); } } - public static function absolutePath ( relPath : String ) : String { - if (haxe.io.Path.isAbsolute(relPath)) return relPath; + public static function absolutePath(relPath:String):String { + if (haxe.io.Path.isAbsolute(relPath)) + return relPath; return haxe.io.Path.join([Sys.getCwd(), relPath]); } - public static function isDirectory( path : String ) : Bool - { + public static function isDirectory(path:String):Bool { var f = new File(path); if (!f.exists()) throw "Path " + path + " doesn't exist"; return f.isDirectory(); } - public static function createDirectory( path : String ) : Void - { + public static function createDirectory(path:String):Void { var f = new File(path); if (!f.isDirectory() && !f.mkdirs()) throw "Cannot create dir " + path; } - public static function deleteFile( path : String ) : Void - { + public static function deleteFile(path:String):Void { if (!new File(path).delete()) throw "Cannot delete file " + path; } - public static function deleteDirectory( path : String ) : Void - { + public static function deleteDirectory(path:String):Void { if (!new File(path).delete()) throw "Cannot delete directory " + path; } - public static function readDirectory( path : String ) : Array - { + public static function readDirectory(path:String):Array { var f = new File(path); if (!f.exists()) throw "Path " + path + " doesn't exist"; - return Lib.array( f.list() ); + return Lib.array(f.list()); } } diff --git a/std/java/_std/sys/db/Mysql.hx b/std/java/_std/sys/db/Mysql.hx index 033d3294305..6dfabe52e54 100644 --- a/std/java/_std/sys/db/Mysql.hx +++ b/std/java/_std/sys/db/Mysql.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,29 +19,27 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.db; class Mysql { - static var init = false; - public static function connect( params : { - host : String, - ?port : Int, - user : String, - pass : String, - ?socket : String, - ?database : String - } ) : sys.db.Connection { - if (!init) - { + public static function connect(params:{ + host:String, + ?port:Int, + user:String, + pass:String, + ?socket:String, + ?database:String + }):sys.db.Connection { + if (!init) { java.lang.Class.forName("com.mysql.jdbc.Driver"); init = true; } var url = new StringBuf(); url.add('jdbc:mysql:'); - if (params.socket != null) - { + if (params.socket != null) { url.add(params.socket); } else { url.add('//'); @@ -55,5 +53,4 @@ class Mysql { var cnx = java.sql.DriverManager.getConnection(url.toString(), params.user, params.pass); return java.db.Jdbc.create(cnx); } - } diff --git a/std/java/_std/sys/db/Sqlite.hx b/std/java/_std/sys/db/Sqlite.hx index 21e6b903804..378f8190eb7 100644 --- a/std/java/_std/sys/db/Sqlite.hx +++ b/std/java/_std/sys/db/Sqlite.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,26 +19,24 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package sys.db; -class Sqlite -{ +package sys.db; + +class Sqlite { static var init = false; - /** - Opens a new SQLite connection on the specified path. - Note that you will need a SQLite JDBC driver (like https://bitbucket.org/xerial/sqlite-jdbc). - **/ - public static function open(file:String):sys.db.Connection - { - if (!init) - { - try java.lang.Class.forName("org.sqlite.JDBC") catch(e:Dynamic) throw e; + + public static function open(file:String):sys.db.Connection { + if (!init) { + try + java.lang.Class.forName("org.sqlite.JDBC") + catch (e:Dynamic) + throw e; init = true; } - try - { + try { var cnx = java.sql.DriverManager.getConnection("jdbc:sqlite:" + file); return java.db.Jdbc.create(cnx); - } catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } } diff --git a/std/java/_std/sys/io/File.hx b/std/java/_std/sys/io/File.hx index 179f99cb694..3ce9a33cd71 100644 --- a/std/java/_std/sys/io/File.hx +++ b/std/java/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,108 +19,102 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; @:coreApi class File { - - public static function getContent( path : String ) : String - { + public static function getContent(path:String):String { var f = read(path, false); var ret = f.readAll().toString(); f.close(); return ret; } - public static function saveContent( path : String, content : String ) : Void - { + public static function saveContent(path:String, content:String):Void { var f = write(path, false); f.writeString(content); f.close(); } - public static function getBytes( path : String ) : haxe.io.Bytes - { + public static function getBytes(path:String):haxe.io.Bytes { var f = read(path, true); var ret = f.readAll(); f.close(); return ret; } - public static function saveBytes( path : String, bytes : haxe.io.Bytes ) : Void - { + public static function saveBytes(path:String, bytes:haxe.io.Bytes):Void { var f = write(path, true); f.writeBytes(bytes, 0, bytes.length); f.close(); } - public static function read( path : String, binary : Bool = true ) : FileInput - { - try - { - return new FileInput( new java.io.RandomAccessFile(new java.io.File(path), "r") ); - } - catch (e:Dynamic) //swallow checked exceptions + public static function read(path:String, binary:Bool = true):FileInput { + try { + return new FileInput(new java.io.RandomAccessFile(new java.io.File(path), "r")); + } catch (e:Dynamic) // swallow checked exceptions { throw e; } } - public static function write( path : String, binary : Bool = true ) : FileOutput - { + public static function write(path:String, binary:Bool = true):FileOutput { var f = new java.io.File(path); - if (f.exists()) - { + if (f.exists()) { f.delete(); } - try - { - return new FileOutput( new java.io.RandomAccessFile(f, "rw") ); - } - catch (e:Dynamic) //swallow checked exceptions + try { + return new FileOutput(new java.io.RandomAccessFile(f, "rw")); + } catch (e:Dynamic) // swallow checked exceptions { throw e; } } - public static function append( path : String, binary : Bool = true ) : FileOutput - { + public static function append(path:String, binary:Bool = true):FileOutput { var f = new java.io.File(path); - try - { + try { var ra = new java.io.RandomAccessFile(f, "rw"); - if (f.exists()) - { + if (f.exists()) { ra.seek(f.length()); } - return new FileOutput( ra ); + return new FileOutput(ra); + } catch (e:Dynamic) // swallow checked exceptions + { + throw e; } - catch (e:Dynamic) //swallow checked exceptions + } + + public static function update(path:String, binary:Bool = true):FileOutput { + var f = new java.io.File(path); + + try { + var ra = new java.io.RandomAccessFile(f, "rw"); + return new FileOutput(ra); + } catch (e:Dynamic) // swallow checked exceptions { throw e; } } - public static function copy( srcPath : String, dstPath : String ) : Void - { + public static function copy(srcPath:String, dstPath:String):Void { var r:FileInput = null; var w:FileOutput = null; - try - { + try { r = read(srcPath); w = write(dstPath); w.writeInput(r); r.close(); w.close(); - } - - catch (e:Dynamic) - { - if (r != null) r.close(); - if (w != null) w.close(); + } catch (e:Dynamic) { + if (r != null) + r.close(); + if (w != null) + w.close(); throw e; } } -} \ No newline at end of file +} diff --git a/std/java/_std/sys/io/FileInput.hx b/std/java/_std/sys/io/FileInput.hx index 9cb37473d90..3905cad459b 100644 --- a/std/java/_std/sys/io/FileInput.hx +++ b/std/java/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; + import haxe.Int64; import haxe.io.Bytes; import haxe.io.Eof; @@ -30,48 +32,40 @@ import java.io.IOException; class FileInput extends Input { var f:java.io.RandomAccessFile; var _eof:Bool; - public function new(f) - { + + public function new(f) { this.f = f; this._eof = false; } - override public function close() - { - try f.close() catch(e:Dynamic) throw e; + override public function close() { + try + f.close() + catch (e:Dynamic) + throw e; } - override public function readByte():Int - { - try - { + override public function readByte():Int { + try { return f.readUnsignedByte(); - } + } catch (e:EOFException) { - catch (e:EOFException) { _eof = true; throw new Eof(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } - override public function readBytes(s:Bytes, pos:Int, len:Int):Int - { + override public function readBytes(s:Bytes, pos:Int, len:Int):Int { var ret = 0; - try - { + try { ret = f.read(s.getData(), pos, len); - } + } catch (e:EOFException) { - catch (e:EOFException) { _eof = true; throw new Eof(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } @@ -83,43 +77,35 @@ class FileInput extends Input { return ret; } - public function seek( p : Int, pos : FileSeek ) : Void - { + public function seek(p:Int, pos:FileSeek):Void { _eof = false; - try - { - switch(pos) - { - case SeekBegin: f.seek(cast p); - case SeekCur: f.seek(haxe.Int64.add(f.getFilePointer(), cast(p, Int64))); - case SeekEnd: f.seek(haxe.Int64.add(f.length(), cast p)); + try { + switch (pos) { + case SeekBegin: + f.seek(cast p); + case SeekCur: + f.seek(haxe.Int64.add(f.getFilePointer(), cast(p, Int64))); + case SeekEnd: + f.seek(haxe.Int64.add(f.length(), cast p)); } - } + } catch (e:EOFException) { - catch (e:EOFException) { _eof = true; throw new Eof(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } - public function tell() : Int - { - try - { + public function tell():Int { + try { return cast f.getFilePointer(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } - public inline function eof() : Bool - { + public inline function eof():Bool { return _eof; } } diff --git a/std/java/_std/sys/io/FileOutput.hx b/std/java/_std/sys/io/FileOutput.hx index d42818646e7..ae75449117f 100644 --- a/std/java/_std/sys/io/FileOutput.hx +++ b/std/java/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; + import haxe.io.Bytes; import haxe.io.Eof; import haxe.io.Output; @@ -28,81 +30,64 @@ import java.io.IOException; class FileOutput extends Output { var f:java.io.RandomAccessFile; - public function new(f) - { + + public function new(f) { this.f = f; } - override public function close() - { - try f.close() catch(e:Dynamic) throw e; + override public function close() { + try + f.close() + catch (e:Dynamic) + throw e; } - override public function writeByte(c:Int):Void - { - try - { + override public function writeByte(c:Int):Void { + try { this.f.write(c); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } - override public function write(s:Bytes):Void - { - try - { + override public function write(s:Bytes):Void { + try { this.f.write(s.getData()); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } - override public function writeBytes(s:Bytes, pos:Int, len:Int):Int - { - try - { + override public function writeBytes(s:Bytes, pos:Int, len:Int):Int { + try { this.f.write(s.getData(), pos, len); return len; - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } - public function seek( p : Int, pos : FileSeek ) : Void - { - try - { - switch(pos) - { - case SeekBegin: f.seek(cast p); - case SeekCur: f.seek(haxe.Int64.add(f.getFilePointer(), cast(p, haxe.Int64))); - case SeekEnd: f.seek(haxe.Int64.add(f.length(), cast p)); + public function seek(p:Int, pos:FileSeek):Void { + try { + switch (pos) { + case SeekBegin: + f.seek(cast p); + case SeekCur: + f.seek(haxe.Int64.add(f.getFilePointer(), cast(p, haxe.Int64))); + case SeekEnd: + f.seek(haxe.Int64.add(f.length(), cast p)); } - } - catch (e:EOFException) { + } catch (e:EOFException) { throw new Eof(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } - public function tell() : Int - { - try - { + public function tell():Int { + try { return cast f.getFilePointer(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } diff --git a/std/java/_std/sys/io/Process.hx b/std/java/_std/sys/io/Process.hx index dba301dd8a4..73a8f740d49 100644 --- a/std/java/_std/sys/io/Process.hx +++ b/std/java/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,10 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.io; + +import haxe.SysTools; import haxe.io.Bytes; import haxe.io.BytesInput; import haxe.io.Eof; @@ -29,12 +32,12 @@ import java.NativeArray; @:coreApi class Process { - - public var stdout(default,null) : haxe.io.Input; - public var stderr(default,null) : haxe.io.Input; - public var stdin(default, null) : haxe.io.Output; + public var stdout(default, null):haxe.io.Input; + public var stderr(default, null):haxe.io.Input; + public var stdin(default, null):haxe.io.Output; private var proc:java.lang.Process; + @:allow(Sys) private static function createProcessBuilder(cmd:String, ?args:Array):java.lang.ProcessBuilder { var sysName = Sys.systemName(); @@ -60,15 +63,13 @@ class Process { pargs = new NativeArray(args.length + 1); switch (sysName) { case "Windows": - pargs[0] = StringTools.quoteWinArg(cmd, false); - for (i in 0...args.length) - { - pargs[i + 1] = StringTools.quoteWinArg(args[i], false); + pargs[0] = SysTools.quoteWinArg(cmd, false); + for (i in 0...args.length) { + pargs[i + 1] = SysTools.quoteWinArg(args[i], false); } case _: pargs[0] = cmd; - for (i in 0...args.length) - { + for (i in 0...args.length) { pargs[i + 1] = args[i]; } } @@ -77,99 +78,84 @@ class Process { return new java.lang.ProcessBuilder(pargs); } - public function new( cmd : String, ?args : Array, ?detached : Bool ) : Void - { - if( detached ) throw "Detached process is not supported on this platform"; + public function new(cmd:String, ?args:Array, ?detached:Bool):Void { + if (detached) + throw "Detached process is not supported on this platform"; var p = proc = createProcessBuilder(cmd, args).start(); stderr = new ProcessInput(p.getErrorStream()); stdout = new ProcessInput(p.getInputStream()); stdin = new java.io.NativeOutput(p.getOutputStream()); } - public function getPid() : Int - { + public function getPid():Int { if (Reflect.hasField(proc, "pid")) return Reflect.field(proc, "pid"); return -1; } - public function exitCode( block : Bool = true ) : Null - { - if( block == false ) { + public function exitCode(block:Bool = true):Null { + if (block == false) { try { return proc.exitValue(); - } catch( e : Dynamic ) { + } catch (e:Dynamic) { return null; } } cast(stdout, ProcessInput).bufferContents(); cast(stderr, ProcessInput).bufferContents(); - try - { + try { proc.waitFor(); + } catch (e:Dynamic) { + throw e; } - catch (e:Dynamic) { throw e; } return proc.exitValue(); } - public function close() : Void - { + public function close():Void { proc.destroy(); } - public function kill() : Void - { + public function kill():Void { proc.destroy(); } - } - -private class ProcessInput extends java.io.NativeInput -{ +private class ProcessInput extends java.io.NativeInput { private var chained:BytesInput; - public function bufferContents():Void - { - if (chained != null) return; + public function bufferContents():Void { + if (chained != null) + return; var b = this.readAll(); chained = new BytesInput(b); } - override public function readByte():Int - { + override public function readByte():Int { if (chained != null) return chained.readByte(); var ret = 0; - try - { + try { ret = stream.read(); - } - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } - if ( ret == -1 ) + if (ret == -1) throw new Eof(); return ret; } - override public function readBytes(s:Bytes, pos:Int, len:Int):Int - { + override public function readBytes(s:Bytes, pos:Int, len:Int):Int { if (chained != null) return chained.readBytes(s, pos, len); var ret = -1; - try - { + try { ret = stream.read(s.getData(), pos, len); - } + } catch (e:EOFException) { - catch (e:EOFException) { throw new Eof(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } @@ -178,16 +164,12 @@ private class ProcessInput extends java.io.NativeInput return ret; } - override public function close():Void - { + override public function close():Void { if (chained != null) chained.close(); - try - { + try { stream.close(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } diff --git a/std/java/_std/sys/net/Host.hx b/std/java/_std/sys/net/Host.hx index 665776bc268..320b69e317a 100644 --- a/std/java/_std/sys/net/Host.hx +++ b/std/java/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,43 +19,40 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.net; + import java.net.InetAddress; class Host { - public var host(default,null) : String; - public var ip(default,null) : Int; + public var host(default, null):String; + public var ip(default, null):Int; @:allow(sys.net) private var wrapped:InetAddress; - public function new( name : String ) : Void - { + public function new(name:String):Void { host = name; try this.wrapped = InetAddress.getByName(name) - catch(e:Dynamic) throw e; + catch (e:Dynamic) + throw e; var rawIp = wrapped.getAddress(); - //network byte order assumed + // network byte order assumed this.ip = cast(rawIp[3], Int) | (cast(rawIp[2], Int) << 8) | (cast(rawIp[1], Int) << 16) | (cast(rawIp[0], Int) << 24); } - public function toString() : String - { + public function toString():String { return wrapped.getHostAddress(); } - public function reverse() : String - { + public function reverse():String { return wrapped.getHostName(); } - public static function localhost() : String - { - try - { + public static function localhost():String { + try { return InetAddress.getLocalHost().getHostName(); - } - catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } - } diff --git a/std/java/_std/sys/net/Socket.hx b/std/java/_std/sys/net/Socket.hx index a1462e56a36..ae288c438b4 100644 --- a/std/java/_std/sys/net/Socket.hx +++ b/std/java/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,100 +19,90 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package sys.net; + import java.net.InetSocketAddress; @:coreApi class Socket { + public var input(default, null):haxe.io.Input; + public var output(default, null):haxe.io.Output; - public var input(default,null) : haxe.io.Input; - public var output(default,null) : haxe.io.Output; - - public var custom : Dynamic; + public var custom:Dynamic; private var sock:java.net.Socket; private var server:java.net.ServerSocket; private var boundAddr:java.net.SocketAddress; - public function new() : Void - { + public function new():Void { create(); } - private function create():Void - { + private function create():Void { this.sock = new java.net.Socket(); - try - { + try { this.server = new java.net.ServerSocket(); - } catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } - public function close() : Void - { - try - { + public function close():Void { + try { if (sock != null) this.sock.close(); if (server != null) this.server.close(); - } - catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } - public function read() : String - { + public function read():String { return input.readAll().toString(); } - public function write( content : String ) : Void - { + public function write(content:String):Void { output.writeString(content); } - public function connect( host : Host, port : Int ) : Void - { - try - { - sock.connect(new InetSocketAddress( host.wrapped, port)); + public function connect(host:Host, port:Int):Void { + try { + sock.connect(new InetSocketAddress(host.wrapped, port)); this.output = new java.io.NativeOutput(sock.getOutputStream()); this.input = new java.io.NativeInput(sock.getInputStream()); - } - catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } - public function listen( connections : Int ) : Void - { - if (boundAddr == null) throw "You must bind the Socket to an address!"; + public function listen(connections:Int):Void { + if (boundAddr == null) + throw "You must bind the Socket to an address!"; try - server.bind(boundAddr,connections) - catch(e:Dynamic) throw e; + server.bind(boundAddr, connections) + catch (e:Dynamic) + throw e; } - public function shutdown( read : Bool, write : Bool ) : Void - { - try - { + public function shutdown(read:Bool, write:Bool):Void { + try { if (read) sock.shutdownInput(); if (write) sock.shutdownOutput(); - } - catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } - public function bind( host : Host, port : Int ) : Void - { - if (boundAddr != null) - { - if (server.isBound()) throw "Already bound"; + public function bind(host:Host, port:Int):Void { + if (boundAddr != null) { + if (server.isBound()) + throw "Already bound"; } this.boundAddr = new java.net.InetSocketAddress(host.wrapped, port); } - public function accept() : Socket - { - var ret = try server.accept() catch(e:Dynamic) throw e; + public function accept():Socket { + var ret = try server.accept() catch (e:Dynamic) throw e; var s = new Socket(); s.sock = ret; @@ -122,56 +112,52 @@ class Socket { return s; } - public function peer() : { host : Host, port : Int } - { + public function peer():{host:Host, port:Int} { var rem = sock.getInetAddress(); - if (rem == null) return null; + if (rem == null) + return null; var host = new Host(null); host.wrapped = rem; - return { host: host, port: sock.getPort() }; + return {host: host, port: sock.getPort()}; } - public function host() : { host : Host, port : Int } - { + public function host():{host:Host, port:Int} { var local = sock.getLocalAddress(); var host = new Host(null); host.wrapped = local; - - if (boundAddr != null) - { - return { host: host, port: server.getLocalPort() }; + + if (boundAddr != null) { + return {host: host, port: server.getLocalPort()}; } - return { host: host, port: sock.getLocalPort() }; + return {host: host, port: sock.getLocalPort()}; } - public function setTimeout( timeout : Float ) : Void - { + public function setTimeout(timeout:Float):Void { try - sock.setSoTimeout( Std.int(timeout * 1000) ) - catch(e:Dynamic) throw e; + sock.setSoTimeout(Std.int(timeout * 1000)) + catch (e:Dynamic) + throw e; } - public function waitForRead() : Void - { + public function waitForRead():Void { throw "Not implemented"; } - public function setBlocking( b : Bool ) : Void - { + public function setBlocking(b:Bool):Void { throw "Not implemented"; } - public function setFastSend( b : Bool ) : Void - { + public function setFastSend(b:Bool):Void { try sock.setTcpNoDelay(b) - catch(e:Dynamic) throw e; + catch (e:Dynamic) + throw e; } - public static function select(read : Array, write : Array, others : Array, ?timeout : Float) : { read: Array,write: Array,others: Array } - { + public static function select(read:Array, write:Array, others:Array, + ?timeout:Float):{read:Array, write:Array, others:Array} { throw "Not implemented"; return null; } diff --git a/std/python/_std/haxe/Log.hx b/std/java/_std/sys/thread/Deque.hx similarity index 68% rename from std/python/_std/haxe/Log.hx rename to std/java/_std/sys/thread/Deque.hx index 5daca6f8c06..dc7b0fdbefe 100644 --- a/std/python/_std/haxe/Log.hx +++ b/std/java/_std/sys/thread/Deque.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,19 +19,33 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe; -@:coreApi class Log { - public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { - var str:String = null; - if (infos != null) { - str = infos.fileName + ":" + Std.string(infos.lineNumber) + ": " + v; - if (infos.customParams != null) { - str += "," + infos.customParams.join(","); - } +package sys.thread; + +import java.Lib; + +@:coreApi +@:native('haxe.java.vm.Deque') +@:nativeGen class Deque { + var lbd:java.util.concurrent.LinkedBlockingDeque; + + public function new() { + lbd = new java.util.concurrent.LinkedBlockingDeque(); + } + + public function add(i:T):Void { + lbd.add(i); + } + + public function push(i:T):Void { + lbd.push(i); + } + + public inline function pop(block:Bool):Null { + return if (block) { + lbd.take(); } else { - str = v; + lbd.poll(); } - python.Lib.println(str); } } diff --git a/std/java/_std/sys/thread/Lock.hx b/std/java/_std/sys/thread/Lock.hx new file mode 100644 index 00000000000..fdba7e75853 --- /dev/null +++ b/std/java/_std/sys/thread/Lock.hx @@ -0,0 +1,78 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +import java.Lib; +import java.lang.System; + +using haxe.Int64; + +@:coreApi +@:native('haxe.java.vm.Lock') class Lock { + @:private @:volatile var releasedCount = 0; + + public function new() {} + + public function wait(?timeout:Float):Bool { + var ret = false; + java.Lib.lock(this, { + if (--releasedCount < 0) { + if (timeout == null) { + // since .notify() is asynchronous, this `while` is needed + // because there is a very remote possibility of release() awaking a thread, + // but before it releases, another thread calls wait - and since the release count + // is still positive, it will get the lock. + while (releasedCount < 0) { + try { + (cast this : java.lang.Object).wait(); + } catch (e:java.lang.InterruptedException) {} + } + } else { + var timeout:haxe.Int64 = cast timeout * 1000; + var cur = System.currentTimeMillis(), + max = cur.add(timeout); + // see above comment about this while loop + while (releasedCount < 0 && cur.compare(max) < 0) { + try { + var t = max.sub(cur); + (cast this : java.lang.Object).wait(t); + cur = System.currentTimeMillis(); + } catch (e:java.lang.InterruptedException) {} + } + } + } + ret = this.releasedCount >= 0; + if (!ret) + this.releasedCount++; // timed out + }); + return ret; + } + + public function release():Void { + untyped __lock__(this, { + if (++releasedCount >= 0) { + untyped this.notify(); + } + }); + } +} diff --git a/std/java/_std/sys/thread/Mutex.hx b/std/java/_std/sys/thread/Mutex.hx new file mode 100644 index 00000000000..8f0a81308c4 --- /dev/null +++ b/std/java/_std/sys/thread/Mutex.hx @@ -0,0 +1,46 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +import java.util.concurrent.locks.ReentrantLock; + +@:coreApi +@:native('haxe.java.vm.Mutex') class Mutex { + @:private var lock:ReentrantLock; + + public function new() { + this.lock = new ReentrantLock(); + } + + public function tryAcquire():Bool { + return this.lock.tryLock(); + } + + public function acquire():Void { + this.lock.lock(); + } + + public function release():Void { + this.lock.unlock(); + } +} diff --git a/std/java/_std/sys/thread/Thread.hx b/std/java/_std/sys/thread/Thread.hx new file mode 100644 index 00000000000..47c0641ef77 --- /dev/null +++ b/std/java/_std/sys/thread/Thread.hx @@ -0,0 +1,111 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package sys.thread; + +import java.Lib; + +abstract Thread(NativeThread) { + inline function new(t:NativeThread) { + this = t; + } + + public static function create(callb:Void->Void):Thread { + var ret = new NativeThread(); + var t = new HaxeThread(ret, callb); + t.start(); + return new Thread(ret); + } + + public static function current():Thread { + return new Thread(NativeThread.getThread(java.lang.Thread.currentThread())); + } + + public static function readMessage(block:Bool):Dynamic { + return current().getHandle().messages.pop(block); + } + + public inline function sendMessage(msg:Dynamic):Void { + this.sendMessage(msg); + } + + private inline function getHandle():NativeThread { + return this; + } +} + +@:native('haxe.java.vm.Thread') private class NativeThread { + @:private static var javaThreadToHaxe = new haxe.ds.WeakMap(); + @:private static var mainJavaThread = java.lang.Thread.currentThread(); + @:private static var mainHaxeThread = { + var ret = new NativeThread(); + javaThreadToHaxe.set(mainJavaThread, ret); + ret; + }; + + public static function getThread(jt:java.lang.Thread):NativeThread { + if (Std.is(jt, HaxeThread)) { + var t:HaxeThread = cast jt; + return t.threadObject; + } else if (jt == mainJavaThread) { + return mainHaxeThread; + } else { + var ret = null; + untyped __lock__(javaThreadToHaxe, { + ret = javaThreadToHaxe.get(jt); + if (ret == null) { + ret = new NativeThread(); + javaThreadToHaxe.set(jt, ret); + } + }); + return ret; + } + } + + public var messages:Deque; + + public function new() { + this.messages = new Deque(); + } + + public function sendMessage(msg:Dynamic):Void { + messages.add(msg); + } +} + +@:native('haxe.java.vm.HaxeThread') +private class HaxeThread extends java.lang.Thread { + public var threadObject(default, null):NativeThread; + + private var runFunction:Void->Void; + + @:overload override public function run():Void { + runFunction(); + } + + public function new(hxThread:NativeThread, run:Void->Void) { + super(); + threadObject = hxThread; + runFunction = run; + setDaemon(true); + } +} diff --git a/std/hl/_std/haxe/Log.hx b/std/java/_std/sys/thread/Tls.hx similarity index 72% rename from std/hl/_std/haxe/Log.hx rename to std/java/_std/sys/thread/Tls.hx index 5702f22f91f..54ec7d1b383 100644 --- a/std/hl/_std/haxe/Log.hx +++ b/std/java/_std/sys/thread/Tls.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,25 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe; -@:coreApi class Log { - public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { - var pstr = infos == null ? "(null)" : infos.fileName + ":" + infos.lineNumber; - var str = Std.string(v); - if( infos != null && infos.customParams != null ) for( v in infos.customParams ) str += "," + Std.string(v); - Sys.println(pstr+": "+str); +package sys.thread; + +// @:coreApi // causes some overload error... +@:native('haxe.java.vm.Tls') class Tls { + var t:java.lang.ThreadLocal; + + public var value(get, set):T; + + public function new() { + this.t = new java.lang.ThreadLocal(); + } + + inline private function get_value():T { + return t.get(); + } + + inline private function set_value(v:T):T { + t.set(v); + return v; } } diff --git a/std/java/db/Jdbc.hx b/std/java/db/Jdbc.hx index 0f3aae53e3d..1c9811e1cc6 100644 --- a/std/java/db/Jdbc.hx +++ b/std/java/db/Jdbc.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,63 +19,56 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.db; + +package java.db; + import java.util.concurrent.atomic.AtomicInteger; import haxe.io.Bytes; import java.sql.Types; @:native('haxe.java.db.Jdbc') -class Jdbc -{ - - public static function create(cnx:java.sql.Connection):sys.db.Connection - { +class Jdbc { + public static function create(cnx:java.sql.Connection):sys.db.Connection { return new JdbcConnection(cnx); } - } @:native('haxe.java.db.JdbcConnection') -private class JdbcConnection implements sys.db.Connection -{ +private class JdbcConnection implements sys.db.Connection { private static var ids = new AtomicInteger(0); + private var id:Int; private var cnx:java.sql.Connection; private var _lastInsertId:Int; - //escape handling + // escape handling private var escapeRegex:EReg; private var escapes:Array; - public function new(cnx) - { + public function new(cnx) { this.id = ids.getAndIncrement(); this.cnx = cnx; this.escapes = []; this.escapeRegex = ~/@@HX_ESCAPE(\d+)_(\d+)@@/; } - public function close() - { + public function close() { try this.cnx.close() - catch(e:Dynamic) throw e; + catch (e:Dynamic) + throw e; } - public function escape(s:String):String - { - return "@@HX_ESCAPE" + id + "_" +escapes.push(s) + "@@"; + public function escape(s:String):String { + return "@@HX_ESCAPE" + id + "_" + escapes.push(s) + "@@"; } - public function quote(s:String):String - { - return "@@HX_ESCAPE" + id + "_" +escapes.push(s) + "@@"; + public function quote(s:String):String { + return "@@HX_ESCAPE" + id + "_" + escapes.push(s) + "@@"; } - public function addValue(s:StringBuf, v:Dynamic) - { - if (Std.is(v, Date)) - { + public function addValue(s:StringBuf, v:Dynamic) { + if (Std.is(v, Date)) { v = Std.string(v); } else if (Std.is(v, Bytes)) { var bt:Bytes = v; @@ -88,13 +81,11 @@ private class JdbcConnection implements sys.db.Connection s.add("@@"); } - public function lastInsertId():Int - { + public function lastInsertId():Int { return _lastInsertId; } - public function dbName():String - { + public function dbName():String { try { var ret = cnx.getMetaData().getDriverName(); var retc = ret.toLowerCase(); @@ -103,51 +94,45 @@ private class JdbcConnection implements sys.db.Connection else if (retc.indexOf("sqlite") != -1) return "SQLite"; return ret; - } catch(e:Dynamic) { throw e; } + } catch (e:Dynamic) { + throw e; + } } - public function startTransaction() - { - try - { + public function startTransaction() { + try { cnx.setAutoCommit(false); - } - catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } - public function commit() - { - try - { + public function commit() { + try { cnx.commit(); - } - catch(e:Dynamic) - { + } catch (e:Dynamic) { throw e; } } - public function rollback() - { + public function rollback() { try cnx.rollback() - catch(e:Dynamic) throw e; + catch (e:Dynamic) + throw e; } - public function request(s:String):sys.db.ResultSet - { + public function request(s:String):sys.db.ResultSet { var newst = new StringBuf(); var sentArray = []; - //cycle through the request string, adding any @@HX_ESCAPE@@ reference to the sentArray + // cycle through the request string, adding any @@HX_ESCAPE@@ reference to the sentArray var r = escapeRegex; var myid = id + "", escapes = escapes, elen = escapes.length; - try - { - while (r.match(s)) - { + try { + while (r.match(s)) { var id = r.matched(1); - if (id != myid) throw "Request quotes are only valid for one single request; They can't be cached."; + if (id != myid) + throw "Request quotes are only valid for one single request; They can't be cached."; newst.add(r.matchedLeft()); var eid = Std.parseInt(r.matched(2)); @@ -159,52 +144,44 @@ private class JdbcConnection implements sys.db.Connection } newst.add(s); var stmt = cnx.prepareStatement(newst.toString(), java.sql.Statement.Statement_Statics.RETURN_GENERATED_KEYS); - for (i in 0...sentArray.length) - { + for (i in 0...sentArray.length) { stmt.setObject(i + 1, sentArray[i]); } var ret = null, dbName = dbName(); - if (stmt.execute()) - { - //is a result set + if (stmt.execute()) { + // is a result set var rs = stmt.getResultSet(); ret = new JdbcResultSet(rs, dbName, stmt.getMetaData()); } else { - //is an update + // is an update var affected = stmt.getUpdateCount(); - if (affected == 1) - { + if (affected == 1) { var autogen = stmt.getGeneratedKeys(); - if (autogen.next()) - { + if (autogen.next()) { this._lastInsertId = autogen.getInt(1); } } - ret = new JdbcResultSet(null, dbName,null); + ret = new JdbcResultSet(null, dbName, null); } if (escapes.length != 0) escapes = []; this.id = ids.getAndIncrement(); return ret; - } - catch(e:Dynamic) - { + } catch (e:Dynamic) { if (escapes.length != 0) escapes = []; this.id = ids.getAndIncrement(); throw e; } } - } @:native('haxe.java.db.JdbcResultSet') -private class JdbcResultSet implements sys.db.ResultSet -{ - @:isVar public var length(get,null) : Int; - public var nfields(get,null) : Int; +private class JdbcResultSet implements sys.db.ResultSet { + @:isVar public var length(get, null):Int; + public var nfields(get, null):Int; private var rs:java.sql.ResultSet; private var names:Array; @@ -212,143 +189,129 @@ private class JdbcResultSet implements sys.db.ResultSet private var dbName:String; private var didNext:Bool; - public function new(rs, dbName, meta:java.sql.ResultSetMetaData) - { + public function new(rs, dbName, meta:java.sql.ResultSetMetaData) { this.dbName = dbName; this.rs = rs; - if (meta != null) - { + if (meta != null) { try { var count = meta.getColumnCount(); var names = [], types = new NativeArray(count); - for (i in 0...count) - { - names.push(meta.getColumnName(i+1)); - types[i] = meta.getColumnType(i+1); + for (i in 0...count) { + names.push(meta.getColumnName(i + 1)); + types[i] = meta.getColumnType(i + 1); } this.types = types; this.names = names; - } catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } } - private function get_length():Int - { - if (length == 0) - { - try - { - var cur = rs.getRow(); - rs.last(); - this.length = rs.getRow(); - rs.absolute(cur); - } catch(e:Dynamic) throw e; + private function get_length():Int { + if (length == 0) { + try { + var cur = rs.getRow(); + rs.last(); + this.length = rs.getRow(); + rs.absolute(cur); + } catch (e:Dynamic) + throw e; } return length; } - private function get_nfields():Int - { + private function get_nfields():Int { return names == null ? 0 : names.length; } - public function hasNext() : Bool - { - try - { + public function hasNext():Bool { + try { didNext = true; return rs != null && rs.next(); + } catch (e:Dynamic) { + return throw e; } - catch(e:Dynamic) { return throw e; } } - public function next() : Dynamic - { + public function next():Dynamic { try { - if (rs == null) return null; - if (didNext) - { + if (rs == null) + return null; + if (didNext) { didNext = false; } else { - if (!rs.next()) - { + if (!rs.next()) { return null; } } var ret = {}, names = names, types = types; - for (i in 0...names.length) - { + for (i in 0...names.length) { var name = names[i], t = types[i], val:Dynamic = null; - if (t == Types.FLOAT) - { - val = rs.getDouble(i+1); + if (t == Types.FLOAT) { + val = rs.getDouble(i + 1); } else if (t == Types.DATE || t == Types.TIME) { - if (dbName == "SQLite") - { - var str = rs.getString(i+1); - if (str != null) - { + if (dbName == "SQLite") { + var str = rs.getString(i + 1); + if (str != null) { var d:Date = Date.fromString(str); val = d; } } else { - var d:java.sql.Date = rs.getDate(i+1); + var d:java.sql.Date = rs.getDate(i + 1); if (d != null) val = Date.fromTime(cast d.getTime()); } } else if (t == Types.LONGVARBINARY || t == Types.VARBINARY || t == Types.BINARY || t == Types.BLOB) { - var b = rs.getBytes(i+1); + var b = rs.getBytes(i + 1); if (b != null) val = Bytes.ofData(b); } else { - untyped __java__("val = rs.getObject(i + 1)"); //type parameter constraint + overloads + untyped __java__("val = rs.getObject(i + 1)"); // type parameter constraint + overloads } Reflect.setField(ret, name, val); } return ret; - } catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } - public function results() : List - { + public function results():List { var l = new List(); - if (rs == null) return l; + if (rs == null) + return l; - try - { - while(hasNext()) + try { + while (hasNext()) l.add(next()); - } catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; return l; } - public function getResult( n : Int ) : String - { - try - { - return rs.getString(n); - } catch(e:Dynamic) throw e; + public function getResult(n:Int):String { + try { + return rs.getString(n); + } catch (e:Dynamic) + throw e; } - public function getIntResult( n : Int ) : Int - { - try - { + public function getIntResult(n:Int):Int { + try { return rs.getInt(n); - } - catch(e:Dynamic) { return throw e; }; + } catch (e:Dynamic) { + return throw e; + }; } - public function getFloatResult( n : Int ) : Float - { - try - { - return rs.getFloat(n); - } catch(e:Dynamic) { return throw e; }; + public function getFloatResult(n:Int):Float { + try { + return rs.getFloat(n); + } catch (e:Dynamic) { + return throw e; + }; } - public function getFieldsNames() : Null> - { + public function getFieldsNames():Null> { return this.names; } } diff --git a/std/java/internal/Exceptions.hx b/std/java/internal/Exceptions.hx index d58c2f8d2eb..7e54fbcdef3 100644 --- a/std/java/internal/Exceptions.hx +++ b/std/java/internal/Exceptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.internal; + import java.lang.Throwable; import java.lang.RuntimeException; import java.lang.Exception; @@ -28,28 +30,23 @@ import java.lang.Exception; class Exceptions { private static var exception = new java.lang.ThreadLocal(); - @:keep private static function setException(exc:Throwable) - { + @:keep private static function setException(exc:Throwable) { exception.set(exc); } - public static function currentException() - { + public static function currentException() { return exception.get(); } } @:classCode("public static final long serialVersionUID = 5956463319488556322L;") -@:nativeGen @:keep @:native("haxe.lang.HaxeException") private class HaxeException extends RuntimeException -{ +@:nativeGen @:keep @:native("haxe.lang.HaxeException") private class HaxeException extends RuntimeException { private var obj:Dynamic; - public function new(obj:Dynamic, msg:String, cause:Throwable) - { + public function new(obj:Dynamic, msg:String, cause:Throwable) { super(msg, cause); - if (Std.is(obj, HaxeException)) - { + if (Std.is(obj, HaxeException)) { var _obj:HaxeException = cast obj; obj = _obj.getObject(); } @@ -57,40 +54,34 @@ class Exceptions { this.obj = obj; } - public function getObject():Dynamic - { + public function getObject():Dynamic { return obj; } -#if !debug - @:overload override public function fillInStackTrace():Throwable - { + #if !debug + @:overload override public function fillInStackTrace():Throwable { return this; } -#end + #end - @:overload override public function toString():String - { + @:overload override public function toString():String { return "Haxe Exception: " + obj; } - @:overload override public function getMessage():String - { - return switch (super.getMessage()) - { + @:overload override public function getMessage():String { + return switch (super.getMessage()) { case null: Std.string(obj); case var message: message; } } - public static function wrap(obj:Dynamic):RuntimeException - { + public static function wrap(obj:Dynamic):RuntimeException { var ret:RuntimeException = null; - if (Std.is(obj, RuntimeException)) + if (Std.is(obj, RuntimeException)) ret = obj; else if (Std.is(obj, String)) ret = new HaxeException(obj, obj, null); - else if (Std.is(obj, Throwable)) + else if (Std.is(obj, Throwable)) ret = new HaxeException(obj, Std.string(obj), obj); else ret = new HaxeException(obj, Std.string(obj), null); diff --git a/std/java/internal/FieldLookup.hx b/std/java/internal/FieldLookup.hx index 9018cce83f9..04a4d8a3b24 100644 --- a/std/java/internal/FieldLookup.hx +++ b/std/java/internal/FieldLookup.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,34 +19,29 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.internal; import java.lang.System; @:native('haxe.lang.FieldLookup') @:keep -@:static private class FieldLookup -{ - +@:static class FieldLookup { @:functionCode(' return s.hashCode(); ') - public static function hash(s:String):Int - { + public static function hash(s:String):Int { return 0; } - public static function findHash(hash:String, hashs:java.NativeArray, length:Int):Int - { + public static function findHash(hash:String, hashs:java.NativeArray, length:Int):Int { var min = 0; var max = length; - while (min < max) - { - var mid = Std.int((max + min) / 2); //overflow safe + while (min < max) { + var mid = Std.int((max + min) / 2); // overflow safe var classify = untyped hash.compareTo(hashs[mid]); - if (classify < 0) - { + if (classify < 0) { max = mid; } else if (classify > 0) { min = mid + 1; @@ -54,62 +49,48 @@ import java.lang.System; return mid; } } - //if not found, return a negative value of where it should be inserted + // if not found, return a negative value of where it should be inserted return ~min; } - static function removeString(a:java.NativeArray, length:Int, pos:Int) { + public static function removeString(a:java.NativeArray, length:Int, pos:Int) { System.arraycopy(a, pos + 1, a, pos, length - pos - 1); a[length - 1] = null; } - static function removeFloat(a:java.NativeArray, length:Int, pos:Int) { + public static function removeFloat(a:java.NativeArray, length:Int, pos:Int) { System.arraycopy(a, pos + 1, a, pos, length - pos - 1); a[length - 1] = 0; } - static function removeDynamic(a:java.NativeArray, length:Int, pos:Int) { + public static function removeDynamic(a:java.NativeArray, length:Int, pos:Int) { System.arraycopy(a, pos + 1, a, pos, length - pos - 1); a[length - 1] = null; } - @:extern - static inline function __insert(a:java.NativeArray, length:Int, pos:Int, x:T):java.NativeArray - { + extern static inline function __insert(a:java.NativeArray, length:Int, pos:Int, x:T):java.NativeArray { var capacity = a.length; - if (pos == length) - { - if (capacity == length) - { + if (pos == length) { + if (capacity == length) { var newarr = new NativeArray((length << 1) + 1); System.arraycopy(a, 0, newarr, 0, a.length); a = newarr; } - } - else if (pos == 0) - { - if (capacity == length) - { + } else if (pos == 0) { + if (capacity == length) { var newarr = new NativeArray((length << 1) + 1); System.arraycopy(a, 0, newarr, 1, length); a = newarr; - } - else - { + } else { System.arraycopy(a, 0, a, 1, length); } - } - else - { - if (capacity == length) - { + } else { + if (capacity == length) { var newarr = new NativeArray((length << 1) + 1); System.arraycopy(a, 0, newarr, 0, pos); System.arraycopy(a, pos, newarr, pos + 1, length - pos); a = newarr; - } - else - { + } else { System.arraycopy(a, pos, a, pos + 1, length - pos); System.arraycopy(a, 0, a, 0, pos); } @@ -118,7 +99,12 @@ import java.lang.System; return a; } - static function insertString(a:java.NativeArray, length:Int, pos:Int, x:String):java.NativeArray return __insert(a, length, pos, x); - static function insertFloat(a:java.NativeArray, length:Int, pos:Int, x:Float):java.NativeArray return __insert(a, length, pos, x); - static function insertDynamic(a:java.NativeArray, length:Int, pos:Int, x:Dynamic):java.NativeArray return __insert(a, length, pos, x); + public static function insertString(a:java.NativeArray, length:Int, pos:Int, x:String):java.NativeArray + return __insert(a, length, pos, x); + + public static function insertFloat(a:java.NativeArray, length:Int, pos:Int, x:Float):java.NativeArray + return __insert(a, length, pos, x); + + public static function insertDynamic(a:java.NativeArray, length:Int, pos:Int, x:Dynamic):java.NativeArray + return __insert(a, length, pos, x); } diff --git a/std/java/internal/Function.hx b/std/java/internal/Function.hx index e83ad8973c6..0cce7a10c4d 100644 --- a/std/java/internal/Function.hx +++ b/std/java/internal/Function.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.internal; + import java.internal.Runtime; /** @@ -29,57 +31,44 @@ import java.internal.Runtime; * * @author waneck */ -@:abstract @:nativeGen @:native("haxe.lang.Function") @:keep class Function -{ - function new(arity:Int, type:Int) - { - - } +@:abstract @:nativeGen @:native("haxe.lang.Function") @:keep class Function { + function new(arity:Int, type:Int) {} } -@:nativeGen @:native("haxe.lang.VarArgsBase") @:keep private class VarArgsBase extends Function -{ - public function __hx_invokeDynamic(dynArgs:java.NativeArray):Dynamic - { +@:nativeGen @:native("haxe.lang.VarArgsBase") @:keep private class VarArgsBase extends Function { + public function __hx_invokeDynamic(dynArgs:java.NativeArray):Dynamic { throw "Abstract implementation"; } } -@:nativeGen @:native('haxe.lang.VarArgsFunction') @:keep class VarArgsFunction extends VarArgsBase -{ +@:nativeGen @:native('haxe.lang.VarArgsFunction') @:keep class VarArgsFunction extends VarArgsBase { private var fun:Array->Dynamic; - public function new(fun) - { + public function new(fun) { super(-1, -1); this.fun = fun; } - override public function __hx_invokeDynamic(dynArgs:java.NativeArray):Dynamic - { + override public function __hx_invokeDynamic(dynArgs:java.NativeArray):Dynamic { return fun(@:privateAccess Array.ofNative(dynArgs)); } } -@:nativeGen @:native('haxe.lang.Closure') @:keep class Closure extends VarArgsBase -{ +@:nativeGen @:native('haxe.lang.Closure') @:keep class Closure extends VarArgsBase { private var obj:Dynamic; private var field:String; - public function new(obj:Dynamic, field) - { + public function new(obj:Dynamic, field) { super(-1, -1); this.obj = obj; this.field = field; } - override public function __hx_invokeDynamic(dynArgs:java.NativeArray):Dynamic - { + override public function __hx_invokeDynamic(dynArgs:java.NativeArray):Dynamic { return Runtime.callField(obj, field, dynArgs); } - public function equals(obj:Dynamic):Bool - { + public function equals(obj:Dynamic):Bool { if (obj == null) return false; @@ -87,8 +76,7 @@ import java.internal.Runtime; return (c.obj == this.obj && c.field == this.field); } - public function hashCode():Int - { + public function hashCode():Int { return obj.hashCode() ^ untyped field.hashCode(); } } diff --git a/std/java/internal/HxObject.hx b/std/java/internal/HxObject.hx index c6bcf82a162..d8f4d795c4c 100644 --- a/std/java/internal/HxObject.hx +++ b/std/java/internal/HxObject.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.internal; + import java.internal.IEquatable; import haxe.ds.Vector; @@ -27,94 +29,231 @@ private typedef StdType = Type; @:native('haxe.lang.HxObject') @:keep -private class HxObject implements IHxObject -{ -} +private class HxObject implements IHxObject {} @:native('haxe.lang.IHxObject') @:keep -interface IHxObject -{ -} +interface IHxObject {} @:native('haxe.lang.DynamicObject') @:keep -class DynamicObject extends HxObject implements Dynamic -{ - @:skipReflection public function toString():String - { - var ts = Reflect.field(this, "toString"); +class DynamicObject extends HxObject { + @:skipReflection var __hx_fields:java.NativeArray; + @:skipReflection var __hx_dynamics:java.NativeArray; + + @:skipReflection var __hx_fields_f:java.NativeArray; + @:skipReflection var __hx_dynamics_f:java.NativeArray; + + @:skipReflection var __hx_length:Int; + @:skipReflection var __hx_length_f:Int; + + @:skipReflection static var __hx_toString_depth = 0; + + @:overload public function new() { + this.__hx_fields = new java.NativeArray(0); + this.__hx_dynamics = new java.NativeArray(0); + this.__hx_fields_f = new java.NativeArray(0); + this.__hx_dynamics_f = new java.NativeArray(0); + } + + @:overload public function new(fields:NativeArray, dynamics:NativeArray, fields_f:NativeArray, dynamics_f:NativeArray) { + this.__hx_fields = fields; + this.__hx_dynamics = dynamics; + this.__hx_fields_f = fields_f; + this.__hx_dynamics_f = dynamics_f; + this.__hx_length = fields.length; + this.__hx_length_f = fields_f.length; + } + + public function __hx_deleteField(field:String):Bool { + var res = FieldLookup.findHash(field, this.__hx_fields, this.__hx_length); + if (res >= 0) { + FieldLookup.removeString(this.__hx_fields, this.__hx_length, res); + FieldLookup.removeDynamic(this.__hx_dynamics, this.__hx_length, res); + this.__hx_length--; + return true; + } + var res = FieldLookup.findHash(field, this.__hx_fields_f, this.__hx_length_f); + if (res >= 0) { + FieldLookup.removeString(this.__hx_fields_f, this.__hx_length_f, res); + FieldLookup.removeFloat(this.__hx_dynamics_f, this.__hx_length_f, res); + this.__hx_length_f--; + return true; + } + return false; + } + + public function __hx_getField(field:String, throwErrors:Bool, isCheck:Bool, handleProperties:Bool):Dynamic { + var res = FieldLookup.findHash(field, this.__hx_fields, this.__hx_length); + if (res >= 0) { + return this.__hx_dynamics[res]; + } + res = FieldLookup.findHash(field, this.__hx_fields_f, this.__hx_length_f); + if (res >= 0) { + return this.__hx_dynamics_f[res]; + } + + return isCheck ? Runtime.undefined : null; + } + + public function __hx_setField(field:String, value:Dynamic, handleProperties:Bool):Dynamic { + var res = FieldLookup.findHash(field, this.__hx_fields, this.__hx_length); + if (res >= 0) { + return this.__hx_dynamics[res] = value; + } else { + var res = FieldLookup.findHash(field, this.__hx_fields_f, this.__hx_length_f); + if (res >= 0) { + if (Std.is(value, Float)) { + return this.__hx_dynamics_f[res] = value; + } + + FieldLookup.removeString(this.__hx_fields_f, this.__hx_length_f, res); + FieldLookup.removeFloat(this.__hx_dynamics_f, this.__hx_length_f, res); + this.__hx_length_f--; + } + } + + this.__hx_fields = FieldLookup.insertString(this.__hx_fields, this.__hx_length, ~(res), field); + this.__hx_dynamics = FieldLookup.insertDynamic(this.__hx_dynamics, this.__hx_length, ~(res), value); + this.__hx_length++; + return value; + } + + public function __hx_getField_f(field:String, throwErrors:Bool, handleProperties:Bool):Float { + var res = FieldLookup.findHash(field, this.__hx_fields_f, this.__hx_length_f); + if (res >= 0) { + return this.__hx_dynamics_f[res]; + } + res = FieldLookup.findHash(field, this.__hx_fields, this.__hx_length); + if (res >= 0) { + return this.__hx_dynamics[res]; + } + + return 0.0; + } + + public function __hx_setField_f(field:String, value:Float, handleProperties:Bool):Float { + var res = FieldLookup.findHash(field, this.__hx_fields_f, this.__hx_length_f); + if (res >= 0) { + return this.__hx_dynamics_f[res] = value; + } else { + var res = FieldLookup.findHash(field, this.__hx_fields, this.__hx_length); + if (res >= 0) { + // return this.__hx_dynamics[res] = value; + FieldLookup.removeString(this.__hx_fields, this.__hx_length, res); + FieldLookup.removeDynamic(this.__hx_dynamics, this.__hx_length, res); + this.__hx_length--; + } + } + + this.__hx_fields_f = FieldLookup.insertString(this.__hx_fields_f, this.__hx_length_f, ~(res), field); + this.__hx_dynamics_f = FieldLookup.insertFloat(this.__hx_dynamics_f, this.__hx_length_f, ~(res), value); + this.__hx_length_f++; + return value; + } + + public function __hx_getFields(baseArr:Array):Void { + for (i in 0...this.__hx_length) { + baseArr.push(this.__hx_fields[i]); + } + for (i in 0...this.__hx_length_f) { + baseArr.push(this.__hx_fields_f[i]); + } + } + + public function __hx_invokeField(field:String, dynargs:NativeArray):Dynamic { + if (field == "toString") { + return this.toString(); + } + var fn:Function = this.__hx_getField(field, false, false, false); + if (fn == null) { + throw 'Cannot invoke field $field: It does not exist'; + } + + return untyped fn.__hx_invokeDynamic(dynargs); + } + + public function toString():String { + if (__hx_toString_depth >= 5) { + return "..."; + } + ++__hx_toString_depth; + try { + var s = __hx_toString(); + --__hx_toString_depth; + return s; + } catch (e:Dynamic) { + --__hx_toString_depth; + throw(e); + } + } + + function __hx_toString() { + var ts = this.__hx_getField("toString", false, false, false); if (ts != null) return ts(); var ret = new StringBuf(); ret.add("{"); var first = true; - for (f in Reflect.fields(this)) - { - if( first ) + for (f in Reflect.fields(this)) { + if (first) first = false; else ret.add(","); - ret.add(" "); ret.add(f); + ret.add(" "); + ret.add(f); ret.add(" : "); ret.add(Reflect.field(this, f)); } - if (!first) ret.add(" "); + if (!first) + ret.add(" "); ret.add("}"); return ret.toString(); } } @:keep @:native('haxe.lang.Enum') @:nativeGen -class HxEnum -{ - @:readOnly private var index(default,never):Int; +class HxEnum { + @:readOnly private var index(default, never):Int; - public function new(index:Int) - { + public function new(index:Int) { untyped this.index = index; } - public function getTag():String - { + public function getTag():String { return throw 'Not Implemented'; } - public function getParams():Array<{}> - { + public function getParams():Array<{}> { return []; } - public function toString():String - { + public function toString():String { return getTag(); } } @:keep @:native('haxe.lang.ParamEnum') @:nativeGen -private class ParamEnum extends HxEnum -{ - @:readOnly private var params(default,never):Vector; +private class ParamEnum extends HxEnum { + @:readOnly private var params(default, never):Vector; - public function new(index:Int, params:Vector) - { + public function new(index:Int, params:Vector) { super(index); untyped this.params = params; } - override public function getParams():Array<{}> - { + override public function getParams():Array<{}> { return params == null ? [] : cast params.toArray(); } - override public function toString():String - { - if (params == null || params.length == 0) return getTag(); + override public function toString():String { + if (params == null || params.length == 0) + return getTag(); var ret = new StringBuf(); - ret.add(getTag()); ret.add("("); + ret.add(getTag()); + ret.add("("); var first = true; - for (p in params) - { + for (p in params) { if (first) first = false; else @@ -125,11 +264,10 @@ private class ParamEnum extends HxEnum return ret.toString(); } - public function equals(obj:Dynamic) - { - if (obj == this) //we cannot use == as .Equals ! + public function equals(obj:Dynamic) { + if (obj == this) // we cannot use == as .Equals ! return true; - var obj:ParamEnum = Std.is(obj,ParamEnum) ? cast obj : null; + var obj:ParamEnum = Std.is(obj, ParamEnum) ? cast obj : null; var ret = obj != null && Std.is(obj, StdType.getEnum(cast this)) && obj.index == this.index; if (!ret) return false; @@ -138,23 +276,21 @@ private class ParamEnum extends HxEnum var len = 0; if (obj.params == null || this.params == null || (len = this.params.length) != obj.params.length) return false; - for (i in 0...len) - { + for (i in 0...len) { if (!StdType.enumEq(obj.params[i], this.params[i])) return false; } return true; } - public function hashCode():Int - { + public function hashCode():Int { var h = 19; - if (params != null) for (p in params) - { - h = h * 31; - if (p != null) - untyped h += p.hashCode(); - } + if (params != null) + for (p in params) { + h = h * 31; + if (p != null) + untyped h += p.hashCode(); + } h += index; return h; } diff --git a/std/java/internal/IEquatable.hx b/std/java/internal/IEquatable.hx index 699ddd4e21e..f557a19a76d 100644 --- a/std/java/internal/IEquatable.hx +++ b/std/java/internal/IEquatable.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,14 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.internal; @:native('haxe.lang.IEquatable') @:keep @:nativeGen -interface IEquatable -{ - +interface IEquatable { public function equals(to:Dynamic):Bool; - } diff --git a/std/java/internal/Runtime.hx b/std/java/internal/Runtime.hx index 34bad2887b1..104ef34923c 100644 --- a/std/java/internal/Runtime.hx +++ b/std/java/internal/Runtime.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.internal; /** - This class is meant for internal compiler use only. It provides the Haxe runtime - compatibility to the host language. Do not access it directly. + This class is meant for internal compiler use only. It provides the Haxe runtime + compatibility to the host language. Do not access it directly. **/ - @:native('haxe.lang.Runtime') @:nativeGen @:classCode(' @@ -56,15 +56,13 @@ package java.internal; return obj.__hx_invokeField(field, args); } ') -@:keep class Runtime -{ - public static var undefined:Dynamic = { }; +@:keep class Runtime { + public static var undefined:Dynamic = {}; @:functionCode(' return new haxe.lang.Closure(obj, field); ') - public static function closure(obj:Dynamic, field:String):Dynamic - { + public static function closure(obj:Dynamic, field:String):Dynamic { return null; } @@ -90,8 +88,7 @@ package java.internal; return false; ') - public static function eq(v1:Dynamic, v2:Dynamic):Bool - { + public static function eq(v1:Dynamic, v2:Dynamic):Bool { return false; } @@ -106,42 +103,36 @@ package java.internal; return v1 == v2; } ') - public static function refEq(v1: { }, v2: { } ):Bool - { + public static function refEq(v1:{}, v2:{}):Bool { return false; } @:functionCode(' return v1 == v2 || (v1 != null && v1.equals(v2)); ') - public static function valEq(v1: { }, v2: { } ):Bool - { + public static function valEq(v1:{}, v2:{}):Bool { return false; } @:functionCode(' return (obj == null) ? 0.0 : ((java.lang.Number) obj).doubleValue(); ') - public static function toDouble(obj:Dynamic):Float - { + public static function toDouble(obj:Dynamic):Float { return 0.0; } - public static function toBool(obj:java.lang.Boolean):Bool - { + public static function toBool(obj:java.lang.Boolean):Bool { return obj == null ? false : obj.booleanValue(); } @:functionCode(' return (obj == null) ? 0 : ((java.lang.Number) obj).intValue(); ') - public static function toInt(obj:Dynamic):Int - { + public static function toInt(obj:Dynamic):Int { return 0; } - public static function toLong(obj:Dynamic):haxe.Int64 - { + public static function toLong(obj:Dynamic):haxe.Int64 { return obj == null ? 0 : (obj : java.lang.Number).longValue(); } @@ -153,13 +144,11 @@ package java.internal; return false; } ') - public static function isDouble(obj:Dynamic):Bool - { + public static function isDouble(obj:Dynamic):Bool { return false; } - @:overload public static function isInt(obj:Dynamic):Bool - { + @:overload public static function isInt(obj:Dynamic):Bool { if (Std.is(obj, java.lang.Number)) { var n:java.lang.Number = obj; return n.doubleValue() == n.intValue(); @@ -205,8 +194,7 @@ package java.internal; return false; ') - public static function slowHasField(o:Dynamic, field:String):Bool - { + public static function slowHasField(o:Dynamic, field:String):Bool { return false; } @@ -236,8 +224,7 @@ package java.internal; //if it\'s not a number it must be a String return ((java.lang.String) v1).compareTo((java.lang.String) v2); ') - public static function compare(v1:Dynamic, v2:Dynamic):Int - { + public static function compare(v1:Dynamic, v2:Dynamic):Int { return 0; } @@ -258,8 +245,7 @@ package java.internal; throw new java.lang.IllegalArgumentException("Cannot dynamically add " + v1 + " and " + v2); ') - public static function plus(v1:Dynamic, v2:Dynamic):Dynamic - { + public static function plus(v1:Dynamic, v2:Dynamic):Dynamic { return null; } @@ -314,8 +300,7 @@ package java.internal; } ') - public static function slowGetField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic - { + public static function slowGetField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic { return null; } @@ -349,8 +334,7 @@ package java.internal; throw HaxeException.wrap(t); } ') - public static function slowSetField(obj:Dynamic, field:String, value:Dynamic):Dynamic - { + public static function slowSetField(obj:Dynamic, field:String, value:Dynamic):Dynamic { return null; } @@ -495,8 +479,7 @@ package java.internal; throw haxe.lang.HaxeException.wrap(t); } ') - public static function slowCallField(obj:Dynamic, field:String, args:java.NativeArray):Dynamic - { + public static function slowCallField(obj:Dynamic, field:String, args:java.NativeArray):Dynamic { return null; } @@ -508,8 +491,7 @@ package java.internal; return slowCallField(obj, field, args); ') - public static function callField(obj:Dynamic, field:String, args:java.NativeArray):Dynamic - { + public static function callField(obj:Dynamic, field:String, args:java.NativeArray):Dynamic { return null; } @@ -521,8 +503,7 @@ package java.internal; return slowGetField(obj, field, throwErrors); ') - public static function getField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic - { + public static function getField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic { return null; } @@ -534,8 +515,7 @@ package java.internal; return toDouble(slowGetField(obj, field, throwErrors)); ') - public static function getField_f(obj:Dynamic, field:String, throwErrors:Bool):Float - { + public static function getField_f(obj:Dynamic, field:String, throwErrors:Bool):Float { return 0.0; } @@ -547,8 +527,7 @@ package java.internal; return slowSetField(obj, field, value); ') - public static function setField(obj:Dynamic, field:String, value:Dynamic):Dynamic - { + public static function setField(obj:Dynamic, field:String, value:Dynamic):Dynamic { return null; } @@ -560,23 +539,20 @@ package java.internal; return toDouble(slowSetField(obj, field, value)); ') - public static function setField_f(obj:Dynamic, field:String, value:Float):Float - { + public static function setField_f(obj:Dynamic, field:String, value:Float):Float { return 0.0; } - public static function toString(obj:Dynamic):String - { + public static function toString(obj:Dynamic):String { if (obj == null) return null; - if (Std.is(obj, java.lang.Number) && !Std.is(obj, java.lang.Integer.IntegerClass) && isInt( (obj : java.lang.Number) )) + if (Std.is(obj, java.lang.Number) && !Std.is(obj, java.lang.Integer.IntegerClass) && isInt((obj : java.lang.Number))) return java.lang.Integer._toString(toInt(obj)); return untyped obj.toString(); } - public static function isFinite(v:Float):Bool - { + public static function isFinite(v:Float):Bool { return (v == v) && !java.lang.Double.DoubleClass._isInfinite(v); } @@ -617,7 +593,6 @@ package java.internal; } } -@:keep @:native("haxe.lang.EmptyObject") enum EmptyObject -{ +@:keep @:native("haxe.lang.EmptyObject") enum EmptyObject { EMPTY; } diff --git a/std/java/internal/StringExt.hx b/std/java/internal/StringExt.hx index abdf1733236..95cc03a5f16 100644 --- a/std/java/internal/StringExt.hx +++ b/std/java/internal/StringExt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,22 +19,21 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.internal; + import java.internal.Function; private typedef NativeString = String; -@:keep @:nativeGen @:native("haxe.lang.StringExt") private class StringExt -{ - +@:keep @:nativeGen @:native("haxe.lang.StringExt") private class StringExt { @:functionCode(' if ( index >= me.length() || index < 0 ) return ""; else return java.lang.Character.toString(me.charAt(index)); ') - public static function charAt(me:NativeString, index:Int):NativeString - { + public static function charAt(me:NativeString, index:Int):NativeString { return null; } @@ -44,8 +43,7 @@ private typedef NativeString = String; else return (int) me.charAt(index); ') - public static function charCodeAt(me:NativeString, index:Int):Null - { + public static function charCodeAt(me:NativeString, index:Int):Null { return null; } @@ -55,8 +53,7 @@ private typedef NativeString = String; return -1; return me.indexOf(str, sIndex); ') - public static function indexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int - { + public static function indexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int { return -1; } @@ -68,8 +65,7 @@ private typedef NativeString = String; return -1; return me.lastIndexOf(str, sIndex); ') - public static function lastIndexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int - { + public static function lastIndexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int { return -1; } @@ -100,8 +96,7 @@ private typedef NativeString = String; } return ret; ') - public static function split(me:NativeString, delimiter:NativeString):Array - { + public static function split(me:NativeString, delimiter:NativeString):Array { return null; } @@ -133,8 +128,7 @@ private typedef NativeString = String; return me.substring(pos, pos + targetLen); ') - public static function substr(me:NativeString, pos:Int, ?len:Int):NativeString - { + public static function substr(me:NativeString, pos:Int, ?len:Int):NativeString { return null; } @@ -164,55 +158,46 @@ private typedef NativeString = String; return me.substring(startIndex, endIdx); ') - public static function substring(me:NativeString, startIndex:Int, ?endIndex:Int):NativeString - { + public static function substring(me:NativeString, startIndex:Int, ?endIndex:Int):NativeString { return null; } - public static function toString(me:NativeString):NativeString - { + public static function toString(me:NativeString):NativeString { return me; } @:functionCode(' return me.toLowerCase(); ') - public static function toLowerCase(me:NativeString):NativeString - { + public static function toLowerCase(me:NativeString):NativeString { return null; } @:functionCode(' return me.toUpperCase(); ') - public static function toUpperCase(me:NativeString):NativeString - { + public static function toUpperCase(me:NativeString):NativeString { return null; } - public static function toNativeString(me:NativeString):NativeString - { + public static function toNativeString(me:NativeString):NativeString { return me; } - @:functionCode(' - return java.lang.Character.toString( (char) code ); - ') - public static function fromCharCode(code:Int):NativeString - { - return null; + public static function fromCharCode(code:Int):String { + return new String(java.lang.Character.toChars(code)); } } -@:keep @:nativeGen @:native('haxe.lang.StringRefl') private class StringRefl -{ - public static var fields = ["length", "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring"]; +@:keep @:nativeGen @:native('haxe.lang.StringRefl') private class StringRefl { + public static var fields = [ + "length", "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring" + ]; - public static function handleGetField(str:NativeString, f:NativeString, throwErrors:Bool):Dynamic - { - switch(f) - { - case "length": return str.length; + public static function handleGetField(str:NativeString, f:NativeString, throwErrors:Bool):Dynamic { + switch (f) { + case "length": + return str.length; case "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring": return new Closure(str, f); default: @@ -223,8 +208,7 @@ private typedef NativeString = String; } } - public static function handleCallField(str:NativeString, f:NativeString, args:java.NativeArray):Dynamic - { + public static function handleCallField(str:NativeString, f:NativeString, args:java.NativeArray):Dynamic { var _args:java.NativeArray; if (args == null) { _args = java.NativeArray.make(str); @@ -238,9 +222,8 @@ private typedef NativeString = String; } } -@:keep @:native('haxe.lang.NativeString') private extern class JavaString -{ - //name collides with Haxe's +@:keep @:native('haxe.lang.NativeString') private extern class JavaString { + // name collides with Haxe's function _charAt(idx:Int):java.StdTypes.Char16; function codePointAt(idx:Int):Int; function codePointBefore(idx:Int):Int; @@ -248,7 +231,6 @@ private typedef NativeString = String; function offsetByCodePoints(index:Int, codePointOffset:Int):Int; function getChars(srcBegin:Int, srcEnd:Int, dst:java.NativeArray, dstBegin:Int):Void; - function startsWith(prefix:String):Bool; function endsWith(suffix:String):Bool; function _indexOf(str:String, fromIndex:Int):Int; diff --git a/std/java/io/NativeInput.hx b/std/java/io/NativeInput.hx index 4343bb338c2..d6f34c3ecfa 100644 --- a/std/java/io/NativeInput.hx +++ b/std/java/io/NativeInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.io; + import haxe.Int64; import haxe.io.Bytes; import haxe.io.Eof; @@ -27,42 +29,33 @@ import haxe.io.Input; import java.io.IOException; import java.io.EOFException; -@:native('haxe.java.io.NativeInput') class NativeInput extends Input -{ +@:native('haxe.java.io.NativeInput') class NativeInput extends Input { var stream:java.io.InputStream; - public function new(stream) - { + + public function new(stream) { this.stream = stream; } - override public function readByte():Int - { + override public function readByte():Int { var ret = 0; - try - { + try { ret = stream.read(); - } - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } - if ( ret == -1 ) + if (ret == -1) throw new Eof(); return ret; } - override public function readBytes(s:Bytes, pos:Int, len:Int):Int - { + override public function readBytes(s:Bytes, pos:Int, len:Int):Int { var ret = 0; - try - { + try { ret = stream.read(s.getData(), pos, len); - } + } catch (e:EOFException) { - catch (e:EOFException) { throw new Eof(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } @@ -71,14 +64,10 @@ import java.io.EOFException; return ret; } - override public function close():Void - { - try - { + override public function close():Void { + try { stream.close(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } diff --git a/std/java/io/NativeOutput.hx b/std/java/io/NativeOutput.hx index daa9f72e4a4..cdf693c8e3f 100644 --- a/std/java/io/NativeOutput.hx +++ b/std/java/io/NativeOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.io; + import haxe.Int64; import haxe.io.Bytes; import haxe.io.Eof; @@ -27,50 +29,36 @@ import haxe.io.Output; import java.io.IOException; import java.io.EOFException; -@:native('haxe.java.io.NativeOutput') class NativeOutput extends Output -{ +@:native('haxe.java.io.NativeOutput') class NativeOutput extends Output { var stream:java.io.OutputStream; - public function new(stream) - { + + public function new(stream) { this.stream = stream; } - override public function writeByte(c:Int):Void - { - try - { + override public function writeByte(c:Int):Void { + try { stream.write(c); - } + } catch (e:EOFException) { - catch (e:EOFException) { throw new Eof(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } - override public function close():Void - { - try - { + override public function close():Void { + try { stream.close(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } - override public function flush():Void - { - try - { + override public function flush():Void { + try { stream.flush(); - } - - catch (e:IOException) { + } catch (e:IOException) { throw haxe.io.Error.Custom(e); } } diff --git a/std/java/lang/Boolean.hx b/std/java/lang/Boolean.hx index 01f631a13fb..150afde2aa6 100644 --- a/std/java/lang/Boolean.hx +++ b/std/java/lang/Boolean.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,35 +19,35 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.lang; + +package java.lang; @:native("") // make sure the generator won't see this @:forward -@:forwardStatics abstract Boolean(BooleanClass) from BooleanClass to BooleanClass -{ - @:to @:extern inline public function toBool():Bool +@:forwardStatics abstract Boolean(BooleanClass) from BooleanClass to BooleanClass { + @:to extern inline public function toBool():Bool return this.booleanValue(); - @:from @:extern inline public static function fromBool(b:Bool):Boolean + + @:from extern inline public static function fromBool(b:Bool):Boolean return BooleanClass.valueOf(b); } -@:native("java.lang.Boolean") extern class BooleanClass extends Number implements Comparable -{ - @:overload public function new(bool:Bool):Void; - @:overload public function new(string:String):Void; - @:overload public function booleanValue() : Bool; - @:overload public function compareTo(param1 : Boolean) : Int; - @:overload public function compareTo(param1 : Dynamic) : Int; - @:overload public function equals(param1 : Dynamic) : Bool; - @:overload public function hashCode() : Int; - @:overload public function toString() : String; - @:final public static var FALSE : Boolean; - @:final public static var TRUE : Boolean; - @:final public static var TYPE : Class; - @:overload public static function compare(param1 : Bool, param2 : Bool) : Int; - @:overload public static function getBoolean(param1 : String) : Bool; - @:overload public static function parseBoolean(param1 : String) : Bool; - @:native("toString") @:overload public static function _toString(param1 : Bool) : String; - @:overload public static function valueOf(param1 : Bool) : Boolean; - @:overload public static function valueOf(param1 : String) : Boolean; +@:native("java.lang.Boolean") extern class BooleanClass extends Number implements Comparable { + @:overload function new(bool:Bool):Void; + @:overload function new(string:String):Void; + @:overload function booleanValue():Bool; + @:overload function compareTo(param1:Boolean):Int; + @:overload function compareTo(param1:Dynamic):Int; + @:overload function equals(param1:Dynamic):Bool; + @:overload function hashCode():Int; + @:overload function toString():String; + static final FALSE:Boolean; + static final TRUE:Boolean; + static final TYPE:Class; + @:overload static function compare(param1:Bool, param2:Bool):Int; + @:overload static function getBoolean(param1:String):Bool; + @:overload static function parseBoolean(param1:String):Bool; + @:native("toString") @:overload static function _toString(param1:Bool):String; + @:overload static function valueOf(param1:Bool):Boolean; + @:overload static function valueOf(param1:String):Boolean; } diff --git a/std/java/lang/Byte.hx b/std/java/lang/Byte.hx index 54a943a2b26..84cf4651f8e 100644 --- a/std/java/lang/Byte.hx +++ b/std/java/lang/Byte.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,40 +19,40 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.lang; + +package java.lang; @:native("") // make sure the generator won't see this @:forwardStatics -@:forward abstract Byte(ByteClass) from ByteClass to ByteClass -{ - @:to @:extern inline public function toByte():java.types.Int8 +@:forward abstract Byte(ByteClass) from ByteClass to ByteClass { + @:to extern inline public function toByte():java.types.Int8 return this.byteValue(); - @:from @:extern inline public static function fromByte(b:java.types.Int8):Byte + + @:from extern inline public static function fromByte(b:java.types.Int8):Byte return ByteClass.valueOf(b); } -@:native("java.lang.Byte") extern class ByteClass extends Number implements Comparable -{ - @:overload function new(param1 : java.types.Int8) : Void; - @:overload @:throws("java.lang.NumberFormatException") function new(param1 : String) : Void; - @:overload function compareTo(param1 : Byte) : Int; - @:overload function compareTo(param1 : Dynamic) : Int; - @:overload function equals(param1 : Dynamic) : Bool; - @:overload function hashCode() : Int; - @:overload function toString() : String; - @:final static var MAX_VALUE(default,null) : java.types.Int8; - @:final static var MIN_VALUE(default,null) : java.types.Int8; - @:final static var SIZE(default,null) : Int; - @:final static var TYPE : Class; - @:overload static function compare(param1 : java.types.Int8, param2 : java.types.Int8) : Int; - @:overload @:throws("java.lang.NumberFormatException") static function decode(param1 : String) : Byte; - @:overload @:throws("java.lang.NumberFormatException") static function parseByte(param1 : String, param2 : Int) : java.types.Int8; - @:overload @:throws("java.lang.NumberFormatException") static function parseByte(param1 : String) : java.types.Int8; - @:native("toString") @:overload static function _toString(param1 : java.types.Int8) : String; - @:overload static function valueOf(param1 : java.types.Int8) : Byte; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String) : Byte; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String, param2 : Int) : Byte; +@:native("java.lang.Byte") extern class ByteClass extends Number implements Comparable { + @:overload function new(param1:java.types.Int8):Void; + @:overload @:throws("java.lang.NumberFormatException") function new(param1:String):Void; + @:overload function compareTo(param1:Byte):Int; + @:overload function compareTo(param1:Dynamic):Int; + @:overload function equals(param1:Dynamic):Bool; + @:overload function hashCode():Int; + @:overload function toString():String; + static final MAX_VALUE:java.types.Int8; + static final MIN_VALUE:java.types.Int8; + static final SIZE:Int; + static final TYPE:Class; + @:overload static function compare(param1:java.types.Int8, param2:java.types.Int8):Int; + @:overload @:throws("java.lang.NumberFormatException") static function decode(param1:String):Byte; + @:overload @:throws("java.lang.NumberFormatException") static function parseByte(param1:String, param2:Int):java.types.Int8; + @:overload @:throws("java.lang.NumberFormatException") static function parseByte(param1:String):java.types.Int8; + @:native("toString") @:overload static function _toString(param1:java.types.Int8):String; + @:overload static function valueOf(param1:java.types.Int8):Byte; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String):Byte; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String, param2:Int):Byte; } -@:realPath("java.lang.Byte_ByteCache") @:javaNative @:native("java.lang.Byte$ByteCache") @:javaCanonical("java.lang","Byte.ByteCache") extern class Byte_ByteCache { -} +@:realPath("java.lang.Byte_ByteCache") @:javaNative @:native("java.lang.Byte$ByteCache") @:javaCanonical("java.lang", + "Byte.ByteCache") extern class Byte_ByteCache {} diff --git a/std/java/lang/Character.hx b/std/java/lang/Character.hx index 0856a4dc20b..678ea2a5a75 100644 --- a/std/java/lang/Character.hx +++ b/std/java/lang/Character.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,400 +19,403 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.lang; + +package java.lang; @:native("") // make sure the generator won't see this @:forwardStatics -@:forward abstract Character(CharacterClass) from CharacterClass to CharacterClass -{ - @:to @:extern inline public function toCharacter():java.types.Char16 +@:forward abstract Character(CharacterClass) from CharacterClass to CharacterClass { + @:to extern inline public function toCharacter():java.types.Char16 return this.charValue(); - @:from @:extern inline public static function fromCharacter(b:java.types.Char16):Character + + @:from extern inline public static function fromCharacter(b:java.types.Char16):Character return CharacterClass.valueOf(b); } -@:native("java.lang.Character") extern class CharacterClass implements Comparable -{ - @:overload function new(param1 : java.types.Char16) : Void; - @:overload function charValue() : java.types.Char16; - @:overload function compareTo(param1 : Character) : Int; - @:overload function compareTo(param1 : Dynamic) : Int; - @:overload function equals(param1 : Dynamic) : Bool; - @:overload function hashCode() : Int; - @:overload function toString() : String; - @:final static var COMBINING_SPACING_MARK(default,null) : java.types.Char16; - @:final static var CONNECTOR_PUNCTUATION(default,null) : java.types.Char16; - @:final static var CONTROL(default,null) : java.types.Char16; - @:final static var CURRENCY_SYMBOL(default,null) : java.types.Char16; - @:final static var DASH_PUNCTUATION(default,null) : java.types.Char16; - @:final static var DECIMAL_DIGIT_NUMBER(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_ARABIC_NUMBER(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_BOUNDARY_NEUTRAL(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_COMMON_NUMBER_SEPARATOR(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_EUROPEAN_NUMBER(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_LEFT_TO_RIGHT(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_NONSPACING_MARK(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_OTHER_NEUTRALS(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_PARAGRAPH_SEPARATOR(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_POP_DIRECTIONAL_FORMAT(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_RIGHT_TO_LEFT(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_SEGMENT_SEPARATOR(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_UNDEFINED(default,null) : java.types.Char16; - @:final static var DIRECTIONALITY_WHITESPACE(default,null) : java.types.Char16; - @:final static var ENCLOSING_MARK(default,null) : java.types.Char16; - @:final static var END_PUNCTUATION(default,null) : java.types.Char16; - @:final static var FINAL_QUOTE_PUNCTUATION(default,null) : java.types.Char16; - @:final static var FORMAT(default,null) : java.types.Char16; - @:final static var INITIAL_QUOTE_PUNCTUATION(default,null) : java.types.Char16; - @:final static var LETTER_NUMBER(default,null) : java.types.Char16; - @:final static var LINE_SEPARATOR(default,null) : java.types.Char16; - @:final static var LOWERCASE_LETTER(default,null) : java.types.Char16; - @:final static var MATH_SYMBOL(default,null) : java.types.Char16; - @:final static var MAX_CODE_POINT(default,null) : Int; - @:final static var MAX_HIGH_SURROGATE(default,null) : java.types.Char16; - @:final static var MAX_LOW_SURROGATE(default,null) : java.types.Char16; - @:final static var MAX_RADIX(default,null) : Int; - @:final static var MAX_SURROGATE(default,null) : java.types.Char16; - @:final static var MAX_VALUE(default,null) : java.types.Char16; - @:final static var MIN_CODE_POINT(default,null) : Int; - @:final static var MIN_HIGH_SURROGATE(default,null) : java.types.Char16; - @:final static var MIN_LOW_SURROGATE(default,null) : java.types.Char16; - @:final static var MIN_RADIX(default,null) : Int; - @:final static var MIN_SUPPLEMENTARY_CODE_POINT(default,null) : Int; - @:final static var MIN_SURROGATE(default,null) : java.types.Char16; - @:final static var MIN_VALUE(default,null) : java.types.Char16; - @:final static var MODIFIER_LETTER(default,null) : java.types.Char16; - @:final static var MODIFIER_SYMBOL(default,null) : java.types.Char16; - @:final static var NON_SPACING_MARK(default,null) : java.types.Char16; - @:final static var OTHER_LETTER(default,null) : java.types.Char16; - @:final static var OTHER_NUMBER(default,null) : java.types.Char16; - @:final static var OTHER_PUNCTUATION(default,null) : java.types.Char16; - @:final static var OTHER_SYMBOL(default,null) : java.types.Char16; - @:final static var PARAGRAPH_SEPARATOR(default,null) : java.types.Char16; - @:final static var PRIVATE_USE(default,null) : java.types.Char16; - @:final static var SIZE(default,null) : Int; - @:final static var SPACE_SEPARATOR(default,null) : java.types.Char16; - @:final static var START_PUNCTUATION(default,null) : java.types.Char16; - @:final static var SURROGATE(default,null) : java.types.Char16; - @:final static var TITLECASE_LETTER(default,null) : java.types.Char16; - @:final static var TYPE : Class; - @:final static var UNASSIGNED(default,null) : java.types.Char16; - @:final static var UPPERCASE_LETTER(default,null) : java.types.Char16; - @:overload static function charCount(param1 : Int) : Int; - @:overload static function codePointAt(param1 : CharSequence, param2 : Int) : Int; - @:overload static function codePointAt(param1 : java.NativeArray, param2 : Int, param3 : Int) : Int; - @:overload static function codePointAt(param1 : java.NativeArray, param2 : Int) : Int; - @:overload static function codePointBefore(param1 : CharSequence, param2 : Int) : Int; - @:overload static function codePointBefore(param1 : java.NativeArray, param2 : Int, param3 : Int) : Int; - @:overload static function codePointBefore(param1 : java.NativeArray, param2 : Int) : Int; - @:overload static function codePointCount(param1 : CharSequence, param2 : Int, param3 : Int) : Int; - @:overload static function codePointCount(param1 : java.NativeArray, param2 : Int, param3 : Int) : Int; - @:overload static function compare(param1 : java.types.Char16, param2 : java.types.Char16) : Int; - @:overload static function digit(param1 : java.types.Char16, param2 : Int) : Int; - @:overload static function digit(param1 : Int, param2 : Int) : Int; - @:overload static function forDigit(param1 : Int, param2 : Int) : java.types.Char16; - @:overload static function getDirectionality(param1 : java.types.Char16) : java.types.Char16; - @:overload static function getDirectionality(param1 : Int) : java.types.Char16; - @:overload static function getName(param1 : Int) : String; - @:overload static function getNumericValue(param1 : java.types.Char16) : Int; - @:overload static function getNumericValue(param1 : Int) : Int; - @:overload static function getType(param1 : java.types.Char16) : Int; - @:overload static function getType(param1 : Int) : Int; - @:overload static function highSurrogate(param1 : Int) : java.types.Char16; - @:overload static function isAlphabetic(param1 : Int) : Bool; - @:overload static function isBmpCodePoint(param1 : Int) : Bool; - @:overload static function isDefined(param1 : java.types.Char16) : Bool; - @:overload static function isDefined(param1 : Int) : Bool; - @:overload static function isDigit(param1 : java.types.Char16) : Bool; - @:overload static function isDigit(param1 : Int) : Bool; - @:overload static function isHighSurrogate(param1 : java.types.Char16) : Bool; - @:overload static function isISOControl(param1 : java.types.Char16) : Bool; - @:overload static function isISOControl(param1 : Int) : Bool; - @:overload static function isIdentifierIgnorable(param1 : java.types.Char16) : Bool; - @:overload static function isIdentifierIgnorable(param1 : Int) : Bool; - @:overload static function isIdeographic(param1 : Int) : Bool; - @:overload static function isJavaIdentifierPart(param1 : java.types.Char16) : Bool; - @:overload static function isJavaIdentifierPart(param1 : Int) : Bool; - @:overload static function isJavaIdentifierStart(param1 : java.types.Char16) : Bool; - @:overload static function isJavaIdentifierStart(param1 : Int) : Bool; - @:overload @:deprecated static function isJavaLetter(param1 : java.types.Char16) : Bool; - @:overload @:deprecated static function isJavaLetterOrDigit(param1 : java.types.Char16) : Bool; - @:overload static function isLetter(param1 : java.types.Char16) : Bool; - @:overload static function isLetter(param1 : Int) : Bool; - @:overload static function isLetterOrDigit(param1 : java.types.Char16) : Bool; - @:overload static function isLetterOrDigit(param1 : Int) : Bool; - @:overload static function isLowSurrogate(param1 : java.types.Char16) : Bool; - @:overload static function isLowerCase(param1 : java.types.Char16) : Bool; - @:overload static function isLowerCase(param1 : Int) : Bool; - @:overload static function isMirrored(param1 : java.types.Char16) : Bool; - @:overload static function isMirrored(param1 : Int) : Bool; - @:overload @:deprecated static function isSpace(param1 : java.types.Char16) : Bool; - @:overload static function isSpaceChar(param1 : java.types.Char16) : Bool; - @:overload static function isSpaceChar(param1 : Int) : Bool; - @:overload static function isSupplementaryCodePoint(param1 : Int) : Bool; - @:overload static function isSurrogate(param1 : java.types.Char16) : Bool; - @:overload static function isSurrogatePair(param1 : java.types.Char16, param2 : java.types.Char16) : Bool; - @:overload static function isTitleCase(param1 : java.types.Char16) : Bool; - @:overload static function isTitleCase(param1 : Int) : Bool; - @:overload static function isUnicodeIdentifierPart(param1 : java.types.Char16) : Bool; - @:overload static function isUnicodeIdentifierPart(param1 : Int) : Bool; - @:overload static function isUnicodeIdentifierStart(param1 : java.types.Char16) : Bool; - @:overload static function isUnicodeIdentifierStart(param1 : Int) : Bool; - @:overload static function isUpperCase(param1 : java.types.Char16) : Bool; - @:overload static function isUpperCase(param1 : Int) : Bool; - @:overload static function isValidCodePoint(param1 : Int) : Bool; - @:overload static function isWhitespace(param1 : java.types.Char16) : Bool; - @:overload static function isWhitespace(param1 : Int) : Bool; - @:overload static function lowSurrogate(param1 : Int) : java.types.Char16; - @:overload static function offsetByCodePoints(param1 : CharSequence, param2 : Int, param3 : Int) : Int; - @:overload static function offsetByCodePoints(param1 : java.NativeArray, param2 : Int, param3 : Int, param4 : Int, param5 : Int) : Int; - @:overload static function reverseBytes(param1 : java.types.Char16) : java.types.Char16; - @:overload static function toChars(param1 : Int, param2 : java.NativeArray, param3 : Int) : Int; - @:overload static function toChars(param1 : Int) : java.NativeArray; - @:overload static function toCodePoint(param1 : java.types.Char16, param2 : java.types.Char16) : Int; - @:overload static function toLowerCase(param1 : java.types.Char16) : java.types.Char16; - @:overload static function toLowerCase(param1 : Int) : Int; - @:native("toString") @:overload static function _toString(param1 : java.types.Char16) : String; - @:overload static function toTitleCase(param1 : java.types.Char16) : java.types.Char16; - @:overload static function toTitleCase(param1 : Int) : Int; - @:overload static function toUpperCase(param1 : java.types.Char16) : java.types.Char16; - @:overload static function toUpperCase(param1 : Int) : Int; - @:overload static function valueOf(param1 : java.types.Char16) : Character; +@:native("java.lang.Character") extern class CharacterClass implements Comparable { + @:overload function new(param1:java.types.Char16):Void; + @:overload function charValue():java.types.Char16; + @:overload function compareTo(param1:Character):Int; + @:overload function compareTo(param1:Dynamic):Int; + @:overload function equals(param1:Dynamic):Bool; + @:overload function hashCode():Int; + @:overload function toString():String; + static final COMBINING_SPACING_MARK:java.types.Char16; + static final CONNECTOR_PUNCTUATION:java.types.Char16; + static final CONTROL:java.types.Char16; + static final CURRENCY_SYMBOL:java.types.Char16; + static final DASH_PUNCTUATION:java.types.Char16; + static final DECIMAL_DIGIT_NUMBER:java.types.Char16; + static final DIRECTIONALITY_ARABIC_NUMBER:java.types.Char16; + static final DIRECTIONALITY_BOUNDARY_NEUTRAL:java.types.Char16; + static final DIRECTIONALITY_COMMON_NUMBER_SEPARATOR:java.types.Char16; + static final DIRECTIONALITY_EUROPEAN_NUMBER:java.types.Char16; + static final DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR:java.types.Char16; + static final DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR:java.types.Char16; + static final DIRECTIONALITY_LEFT_TO_RIGHT:java.types.Char16; + static final DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:java.types.Char16; + static final DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE:java.types.Char16; + static final DIRECTIONALITY_NONSPACING_MARK:java.types.Char16; + static final DIRECTIONALITY_OTHER_NEUTRALS:java.types.Char16; + static final DIRECTIONALITY_PARAGRAPH_SEPARATOR:java.types.Char16; + static final DIRECTIONALITY_POP_DIRECTIONAL_FORMAT:java.types.Char16; + static final DIRECTIONALITY_RIGHT_TO_LEFT:java.types.Char16; + static final DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:java.types.Char16; + static final DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:java.types.Char16; + static final DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:java.types.Char16; + static final DIRECTIONALITY_SEGMENT_SEPARATOR:java.types.Char16; + static final DIRECTIONALITY_UNDEFINED:java.types.Char16; + static final DIRECTIONALITY_WHITESPACE:java.types.Char16; + static final ENCLOSING_MARK:java.types.Char16; + static final END_PUNCTUATION:java.types.Char16; + static final FINAL_QUOTE_PUNCTUATION:java.types.Char16; + static final FORMAT:java.types.Char16; + static final INITIAL_QUOTE_PUNCTUATION:java.types.Char16; + static final LETTER_NUMBER:java.types.Char16; + static final LINE_SEPARATOR:java.types.Char16; + static final LOWERCASE_LETTER:java.types.Char16; + static final MATH_SYMBOL:java.types.Char16; + static final MAX_CODE_POINT:Int; + static final MAX_HIGH_SURROGATE:java.types.Char16; + static final MAX_LOW_SURROGATE:java.types.Char16; + static final MAX_RADIX:Int; + static final MAX_SURROGATE:java.types.Char16; + static final MAX_VALUE:java.types.Char16; + static final MIN_CODE_POINT:Int; + static final MIN_HIGH_SURROGATE:java.types.Char16; + static final MIN_LOW_SURROGATE:java.types.Char16; + static final MIN_RADIX:Int; + static final MIN_SUPPLEMENTARY_CODE_POINT:Int; + static final MIN_SURROGATE:java.types.Char16; + static final MIN_VALUE:java.types.Char16; + static final MODIFIER_LETTER:java.types.Char16; + static final MODIFIER_SYMBOL:java.types.Char16; + static final NON_SPACING_MARK:java.types.Char16; + static final OTHER_LETTER:java.types.Char16; + static final OTHER_NUMBER:java.types.Char16; + static final OTHER_PUNCTUATION:java.types.Char16; + static final OTHER_SYMBOL:java.types.Char16; + static final PARAGRAPH_SEPARATOR:java.types.Char16; + static final PRIVATE_USE:java.types.Char16; + static final SIZE:Int; + static final SPACE_SEPARATOR:java.types.Char16; + static final START_PUNCTUATION:java.types.Char16; + static final SURROGATE:java.types.Char16; + static final TITLECASE_LETTER:java.types.Char16; + static final TYPE:Class; + static final UNASSIGNED:java.types.Char16; + static final UPPERCASE_LETTER:java.types.Char16; + @:overload static function charCount(param1:Int):Int; + @:overload static function codePointAt(param1:CharSequence, param2:Int):Int; + @:overload static function codePointAt(param1:java.NativeArray, param2:Int, param3:Int):Int; + @:overload static function codePointAt(param1:java.NativeArray, param2:Int):Int; + @:overload static function codePointBefore(param1:CharSequence, param2:Int):Int; + @:overload static function codePointBefore(param1:java.NativeArray, param2:Int, param3:Int):Int; + @:overload static function codePointBefore(param1:java.NativeArray, param2:Int):Int; + @:overload static function codePointCount(param1:CharSequence, param2:Int, param3:Int):Int; + @:overload static function codePointCount(param1:java.NativeArray, param2:Int, param3:Int):Int; + @:overload static function compare(param1:java.types.Char16, param2:java.types.Char16):Int; + @:overload static function digit(param1:java.types.Char16, param2:Int):Int; + @:overload static function digit(param1:Int, param2:Int):Int; + @:overload static function forDigit(param1:Int, param2:Int):java.types.Char16; + @:overload static function getDirectionality(param1:java.types.Char16):java.types.Char16; + @:overload static function getDirectionality(param1:Int):java.types.Char16; + @:overload static function getName(param1:Int):String; + @:overload static function getNumericValue(param1:java.types.Char16):Int; + @:overload static function getNumericValue(param1:Int):Int; + @:overload static function getType(param1:java.types.Char16):Int; + @:overload static function getType(param1:Int):Int; + @:overload static function highSurrogate(param1:Int):java.types.Char16; + @:overload static function isAlphabetic(param1:Int):Bool; + @:overload static function isBmpCodePoint(param1:Int):Bool; + @:overload static function isDefined(param1:java.types.Char16):Bool; + @:overload static function isDefined(param1:Int):Bool; + @:overload static function isDigit(param1:java.types.Char16):Bool; + @:overload static function isDigit(param1:Int):Bool; + @:overload static function isHighSurrogate(param1:java.types.Char16):Bool; + @:overload static function isISOControl(param1:java.types.Char16):Bool; + @:overload static function isISOControl(param1:Int):Bool; + @:overload static function isIdentifierIgnorable(param1:java.types.Char16):Bool; + @:overload static function isIdentifierIgnorable(param1:Int):Bool; + @:overload static function isIdeographic(param1:Int):Bool; + @:overload static function isJavaIdentifierPart(param1:java.types.Char16):Bool; + @:overload static function isJavaIdentifierPart(param1:Int):Bool; + @:overload static function isJavaIdentifierStart(param1:java.types.Char16):Bool; + @:overload static function isJavaIdentifierStart(param1:Int):Bool; + @:overload @:deprecated static function isJavaLetter(param1:java.types.Char16):Bool; + @:overload @:deprecated static function isJavaLetterOrDigit(param1:java.types.Char16):Bool; + @:overload static function isLetter(param1:java.types.Char16):Bool; + @:overload static function isLetter(param1:Int):Bool; + @:overload static function isLetterOrDigit(param1:java.types.Char16):Bool; + @:overload static function isLetterOrDigit(param1:Int):Bool; + @:overload static function isLowSurrogate(param1:java.types.Char16):Bool; + @:overload static function isLowerCase(param1:java.types.Char16):Bool; + @:overload static function isLowerCase(param1:Int):Bool; + @:overload static function isMirrored(param1:java.types.Char16):Bool; + @:overload static function isMirrored(param1:Int):Bool; + @:overload @:deprecated static function isSpace(param1:java.types.Char16):Bool; + @:overload static function isSpaceChar(param1:java.types.Char16):Bool; + @:overload static function isSpaceChar(param1:Int):Bool; + @:overload static function isSupplementaryCodePoint(param1:Int):Bool; + @:overload static function isSurrogate(param1:java.types.Char16):Bool; + @:overload static function isSurrogatePair(param1:java.types.Char16, param2:java.types.Char16):Bool; + @:overload static function isTitleCase(param1:java.types.Char16):Bool; + @:overload static function isTitleCase(param1:Int):Bool; + @:overload static function isUnicodeIdentifierPart(param1:java.types.Char16):Bool; + @:overload static function isUnicodeIdentifierPart(param1:Int):Bool; + @:overload static function isUnicodeIdentifierStart(param1:java.types.Char16):Bool; + @:overload static function isUnicodeIdentifierStart(param1:Int):Bool; + @:overload static function isUpperCase(param1:java.types.Char16):Bool; + @:overload static function isUpperCase(param1:Int):Bool; + @:overload static function isValidCodePoint(param1:Int):Bool; + @:overload static function isWhitespace(param1:java.types.Char16):Bool; + @:overload static function isWhitespace(param1:Int):Bool; + @:overload static function lowSurrogate(param1:Int):java.types.Char16; + @:overload static function offsetByCodePoints(param1:CharSequence, param2:Int, param3:Int):Int; + @:overload static function offsetByCodePoints(param1:java.NativeArray, param2:Int, param3:Int, param4:Int, param5:Int):Int; + @:overload static function reverseBytes(param1:java.types.Char16):java.types.Char16; + @:overload static function toChars(param1:Int, param2:java.NativeArray, param3:Int):Int; + @:overload static function toChars(param1:Int):java.NativeArray; + @:overload static function toCodePoint(param1:java.types.Char16, param2:java.types.Char16):Int; + @:overload static function toLowerCase(param1:java.types.Char16):java.types.Char16; + @:overload static function toLowerCase(param1:Int):Int; + @:native("toString") @:overload static function _toString(param1:java.types.Char16):String; + @:overload static function toTitleCase(param1:java.types.Char16):java.types.Char16; + @:overload static function toTitleCase(param1:Int):Int; + @:overload static function toUpperCase(param1:java.types.Char16):java.types.Char16; + @:overload static function toUpperCase(param1:Int):Int; + @:overload static function valueOf(param1:java.types.Char16):Character; } -@:realPath("java.lang.Character_CharacterCache") @:javaNative @:native("java.lang.Character$CharacterCache") @:javaCanonical("java.lang","Character.CharacterCache") extern class Character_CharacterCache { -} +@:realPath("java.lang.Character_CharacterCache") @:javaNative @:native("java.lang.Character$CharacterCache") @:javaCanonical("java.lang", + "Character.CharacterCache") extern class Character_CharacterCache {} -@:realPath("java.lang.Character_Subset") @:javaNative @:native("java.lang.Character$Subset") @:javaCanonical("java.lang","Character.Subset") extern class Character_Subset { - @:overload @:final function equals(param1 : Dynamic) : Bool; - @:overload @:final function hashCode() : Int; - @:overload @:final function toString() : String; +@:realPath("java.lang.Character_Subset") @:javaNative @:native("java.lang.Character$Subset") @:javaCanonical("java.lang", + "Character.Subset") extern class Character_Subset { + @:overload final function equals(param1:Dynamic):Bool; + @:overload final function hashCode():Int; + @:overload final function toString():String; } -@:realPath("java.lang.Character_UnicodeBlock") @:final @:javaNative @:native("java.lang.Character$UnicodeBlock") @:javaCanonical("java.lang","Character.UnicodeBlock") extern class Character_UnicodeBlock extends Character_Subset { - @:final static var AEGEAN_NUMBERS : Character_UnicodeBlock; - @:final static var ALCHEMICAL_SYMBOLS : Character_UnicodeBlock; - @:final static var ALPHABETIC_PRESENTATION_FORMS : Character_UnicodeBlock; - @:final static var ANCIENT_GREEK_MUSICAL_NOTATION : Character_UnicodeBlock; - @:final static var ANCIENT_GREEK_NUMBERS : Character_UnicodeBlock; - @:final static var ANCIENT_SYMBOLS : Character_UnicodeBlock; - @:final static var ARABIC : Character_UnicodeBlock; - @:final static var ARABIC_PRESENTATION_FORMS_A : Character_UnicodeBlock; - @:final static var ARABIC_PRESENTATION_FORMS_B : Character_UnicodeBlock; - @:final static var ARABIC_SUPPLEMENT : Character_UnicodeBlock; - @:final static var ARMENIAN : Character_UnicodeBlock; - @:final static var ARROWS : Character_UnicodeBlock; - @:final static var AVESTAN : Character_UnicodeBlock; - @:final static var BALINESE : Character_UnicodeBlock; - @:final static var BAMUM : Character_UnicodeBlock; - @:final static var BAMUM_SUPPLEMENT : Character_UnicodeBlock; - @:final static var BASIC_LATIN : Character_UnicodeBlock; - @:final static var BATAK : Character_UnicodeBlock; - @:final static var BENGALI : Character_UnicodeBlock; - @:final static var BLOCK_ELEMENTS : Character_UnicodeBlock; - @:final static var BOPOMOFO : Character_UnicodeBlock; - @:final static var BOPOMOFO_EXTENDED : Character_UnicodeBlock; - @:final static var BOX_DRAWING : Character_UnicodeBlock; - @:final static var BRAHMI : Character_UnicodeBlock; - @:final static var BRAILLE_PATTERNS : Character_UnicodeBlock; - @:final static var BUGINESE : Character_UnicodeBlock; - @:final static var BUHID : Character_UnicodeBlock; - @:final static var BYZANTINE_MUSICAL_SYMBOLS : Character_UnicodeBlock; - @:final static var CARIAN : Character_UnicodeBlock; - @:final static var CHAM : Character_UnicodeBlock; - @:final static var CHEROKEE : Character_UnicodeBlock; - @:final static var CJK_COMPATIBILITY : Character_UnicodeBlock; - @:final static var CJK_COMPATIBILITY_FORMS : Character_UnicodeBlock; - @:final static var CJK_COMPATIBILITY_IDEOGRAPHS : Character_UnicodeBlock; - @:final static var CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT : Character_UnicodeBlock; - @:final static var CJK_RADICALS_SUPPLEMENT : Character_UnicodeBlock; - @:final static var CJK_STROKES : Character_UnicodeBlock; - @:final static var CJK_SYMBOLS_AND_PUNCTUATION : Character_UnicodeBlock; - @:final static var CJK_UNIFIED_IDEOGRAPHS : Character_UnicodeBlock; - @:final static var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A : Character_UnicodeBlock; - @:final static var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B : Character_UnicodeBlock; - @:final static var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C : Character_UnicodeBlock; - @:final static var CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D : Character_UnicodeBlock; - @:final static var COMBINING_DIACRITICAL_MARKS : Character_UnicodeBlock; - @:final static var COMBINING_DIACRITICAL_MARKS_SUPPLEMENT : Character_UnicodeBlock; - @:final static var COMBINING_HALF_MARKS : Character_UnicodeBlock; - @:final static var COMBINING_MARKS_FOR_SYMBOLS : Character_UnicodeBlock; - @:final static var COMMON_INDIC_NUMBER_FORMS : Character_UnicodeBlock; - @:final static var CONTROL_PICTURES : Character_UnicodeBlock; - @:final static var COPTIC : Character_UnicodeBlock; - @:final static var COUNTING_ROD_NUMERALS : Character_UnicodeBlock; - @:final static var CUNEIFORM : Character_UnicodeBlock; - @:final static var CUNEIFORM_NUMBERS_AND_PUNCTUATION : Character_UnicodeBlock; - @:final static var CURRENCY_SYMBOLS : Character_UnicodeBlock; - @:final static var CYPRIOT_SYLLABARY : Character_UnicodeBlock; - @:final static var CYRILLIC : Character_UnicodeBlock; - @:final static var CYRILLIC_EXTENDED_A : Character_UnicodeBlock; - @:final static var CYRILLIC_EXTENDED_B : Character_UnicodeBlock; - @:final static var CYRILLIC_SUPPLEMENTARY : Character_UnicodeBlock; - @:final static var DESERET : Character_UnicodeBlock; - @:final static var DEVANAGARI : Character_UnicodeBlock; - @:final static var DEVANAGARI_EXTENDED : Character_UnicodeBlock; - @:final static var DINGBATS : Character_UnicodeBlock; - @:final static var DOMINO_TILES : Character_UnicodeBlock; - @:final static var EGYPTIAN_HIEROGLYPHS : Character_UnicodeBlock; - @:final static var EMOTICONS : Character_UnicodeBlock; - @:final static var ENCLOSED_ALPHANUMERICS : Character_UnicodeBlock; - @:final static var ENCLOSED_ALPHANUMERIC_SUPPLEMENT : Character_UnicodeBlock; - @:final static var ENCLOSED_CJK_LETTERS_AND_MONTHS : Character_UnicodeBlock; - @:final static var ENCLOSED_IDEOGRAPHIC_SUPPLEMENT : Character_UnicodeBlock; - @:final static var ETHIOPIC : Character_UnicodeBlock; - @:final static var ETHIOPIC_EXTENDED : Character_UnicodeBlock; - @:final static var ETHIOPIC_EXTENDED_A : Character_UnicodeBlock; - @:final static var ETHIOPIC_SUPPLEMENT : Character_UnicodeBlock; - @:final static var GENERAL_PUNCTUATION : Character_UnicodeBlock; - @:final static var GEOMETRIC_SHAPES : Character_UnicodeBlock; - @:final static var GEORGIAN : Character_UnicodeBlock; - @:final static var GEORGIAN_SUPPLEMENT : Character_UnicodeBlock; - @:final static var GLAGOLITIC : Character_UnicodeBlock; - @:final static var GOTHIC : Character_UnicodeBlock; - @:final static var GREEK : Character_UnicodeBlock; - @:final static var GREEK_EXTENDED : Character_UnicodeBlock; - @:final static var GUJARATI : Character_UnicodeBlock; - @:final static var GURMUKHI : Character_UnicodeBlock; - @:final static var HALFWIDTH_AND_FULLWIDTH_FORMS : Character_UnicodeBlock; - @:final static var HANGUL_COMPATIBILITY_JAMO : Character_UnicodeBlock; - @:final static var HANGUL_JAMO : Character_UnicodeBlock; - @:final static var HANGUL_JAMO_EXTENDED_A : Character_UnicodeBlock; - @:final static var HANGUL_JAMO_EXTENDED_B : Character_UnicodeBlock; - @:final static var HANGUL_SYLLABLES : Character_UnicodeBlock; - @:final static var HANUNOO : Character_UnicodeBlock; - @:final static var HEBREW : Character_UnicodeBlock; - @:final static var HIGH_PRIVATE_USE_SURROGATES : Character_UnicodeBlock; - @:final static var HIGH_SURROGATES : Character_UnicodeBlock; - @:final static var HIRAGANA : Character_UnicodeBlock; - @:final static var IDEOGRAPHIC_DESCRIPTION_CHARACTERS : Character_UnicodeBlock; - @:final static var IMPERIAL_ARAMAIC : Character_UnicodeBlock; - @:final static var INSCRIPTIONAL_PAHLAVI : Character_UnicodeBlock; - @:final static var INSCRIPTIONAL_PARTHIAN : Character_UnicodeBlock; - @:final static var IPA_EXTENSIONS : Character_UnicodeBlock; - @:final static var JAVANESE : Character_UnicodeBlock; - @:final static var KAITHI : Character_UnicodeBlock; - @:final static var KANA_SUPPLEMENT : Character_UnicodeBlock; - @:final static var KANBUN : Character_UnicodeBlock; - @:final static var KANGXI_RADICALS : Character_UnicodeBlock; - @:final static var KANNADA : Character_UnicodeBlock; - @:final static var KATAKANA : Character_UnicodeBlock; - @:final static var KATAKANA_PHONETIC_EXTENSIONS : Character_UnicodeBlock; - @:final static var KAYAH_LI : Character_UnicodeBlock; - @:final static var KHAROSHTHI : Character_UnicodeBlock; - @:final static var KHMER : Character_UnicodeBlock; - @:final static var KHMER_SYMBOLS : Character_UnicodeBlock; - @:final static var LAO : Character_UnicodeBlock; - @:final static var LATIN_1_SUPPLEMENT : Character_UnicodeBlock; - @:final static var LATIN_EXTENDED_A : Character_UnicodeBlock; - @:final static var LATIN_EXTENDED_ADDITIONAL : Character_UnicodeBlock; - @:final static var LATIN_EXTENDED_B : Character_UnicodeBlock; - @:final static var LATIN_EXTENDED_C : Character_UnicodeBlock; - @:final static var LATIN_EXTENDED_D : Character_UnicodeBlock; - @:final static var LEPCHA : Character_UnicodeBlock; - @:final static var LETTERLIKE_SYMBOLS : Character_UnicodeBlock; - @:final static var LIMBU : Character_UnicodeBlock; - @:final static var LINEAR_B_IDEOGRAMS : Character_UnicodeBlock; - @:final static var LINEAR_B_SYLLABARY : Character_UnicodeBlock; - @:final static var LISU : Character_UnicodeBlock; - @:final static var LOW_SURROGATES : Character_UnicodeBlock; - @:final static var LYCIAN : Character_UnicodeBlock; - @:final static var LYDIAN : Character_UnicodeBlock; - @:final static var MAHJONG_TILES : Character_UnicodeBlock; - @:final static var MALAYALAM : Character_UnicodeBlock; - @:final static var MANDAIC : Character_UnicodeBlock; - @:final static var MATHEMATICAL_ALPHANUMERIC_SYMBOLS : Character_UnicodeBlock; - @:final static var MATHEMATICAL_OPERATORS : Character_UnicodeBlock; - @:final static var MEETEI_MAYEK : Character_UnicodeBlock; - @:final static var MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A : Character_UnicodeBlock; - @:final static var MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B : Character_UnicodeBlock; - @:final static var MISCELLANEOUS_SYMBOLS : Character_UnicodeBlock; - @:final static var MISCELLANEOUS_SYMBOLS_AND_ARROWS : Character_UnicodeBlock; - @:final static var MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS : Character_UnicodeBlock; - @:final static var MISCELLANEOUS_TECHNICAL : Character_UnicodeBlock; - @:final static var MODIFIER_TONE_LETTERS : Character_UnicodeBlock; - @:final static var MONGOLIAN : Character_UnicodeBlock; - @:final static var MUSICAL_SYMBOLS : Character_UnicodeBlock; - @:final static var MYANMAR : Character_UnicodeBlock; - @:final static var MYANMAR_EXTENDED_A : Character_UnicodeBlock; - @:final static var NEW_TAI_LUE : Character_UnicodeBlock; - @:final static var NKO : Character_UnicodeBlock; - @:final static var NUMBER_FORMS : Character_UnicodeBlock; - @:final static var OGHAM : Character_UnicodeBlock; - @:final static var OLD_ITALIC : Character_UnicodeBlock; - @:final static var OLD_PERSIAN : Character_UnicodeBlock; - @:final static var OLD_SOUTH_ARABIAN : Character_UnicodeBlock; - @:final static var OLD_TURKIC : Character_UnicodeBlock; - @:final static var OL_CHIKI : Character_UnicodeBlock; - @:final static var OPTICAL_CHARACTER_RECOGNITION : Character_UnicodeBlock; - @:final static var ORIYA : Character_UnicodeBlock; - @:final static var OSMANYA : Character_UnicodeBlock; - @:final static var PHAGS_PA : Character_UnicodeBlock; - @:final static var PHAISTOS_DISC : Character_UnicodeBlock; - @:final static var PHOENICIAN : Character_UnicodeBlock; - @:final static var PHONETIC_EXTENSIONS : Character_UnicodeBlock; - @:final static var PHONETIC_EXTENSIONS_SUPPLEMENT : Character_UnicodeBlock; - @:final static var PLAYING_CARDS : Character_UnicodeBlock; - @:final static var PRIVATE_USE_AREA : Character_UnicodeBlock; - @:final static var REJANG : Character_UnicodeBlock; - @:final static var RUMI_NUMERAL_SYMBOLS : Character_UnicodeBlock; - @:final static var RUNIC : Character_UnicodeBlock; - @:final static var SAMARITAN : Character_UnicodeBlock; - @:final static var SAURASHTRA : Character_UnicodeBlock; - @:final static var SHAVIAN : Character_UnicodeBlock; - @:final static var SINHALA : Character_UnicodeBlock; - @:final static var SMALL_FORM_VARIANTS : Character_UnicodeBlock; - @:final static var SPACING_MODIFIER_LETTERS : Character_UnicodeBlock; - @:final static var SPECIALS : Character_UnicodeBlock; - @:final static var SUNDANESE : Character_UnicodeBlock; - @:final static var SUPERSCRIPTS_AND_SUBSCRIPTS : Character_UnicodeBlock; - @:final static var SUPPLEMENTAL_ARROWS_A : Character_UnicodeBlock; - @:final static var SUPPLEMENTAL_ARROWS_B : Character_UnicodeBlock; - @:final static var SUPPLEMENTAL_MATHEMATICAL_OPERATORS : Character_UnicodeBlock; - @:final static var SUPPLEMENTAL_PUNCTUATION : Character_UnicodeBlock; - @:final static var SUPPLEMENTARY_PRIVATE_USE_AREA_A : Character_UnicodeBlock; - @:final static var SUPPLEMENTARY_PRIVATE_USE_AREA_B : Character_UnicodeBlock; - @:deprecated @:final static var SURROGATES_AREA : Character_UnicodeBlock; - @:final static var SYLOTI_NAGRI : Character_UnicodeBlock; - @:final static var SYRIAC : Character_UnicodeBlock; - @:final static var TAGALOG : Character_UnicodeBlock; - @:final static var TAGBANWA : Character_UnicodeBlock; - @:final static var TAGS : Character_UnicodeBlock; - @:final static var TAI_LE : Character_UnicodeBlock; - @:final static var TAI_THAM : Character_UnicodeBlock; - @:final static var TAI_VIET : Character_UnicodeBlock; - @:final static var TAI_XUAN_JING_SYMBOLS : Character_UnicodeBlock; - @:final static var TAMIL : Character_UnicodeBlock; - @:final static var TELUGU : Character_UnicodeBlock; - @:final static var THAANA : Character_UnicodeBlock; - @:final static var THAI : Character_UnicodeBlock; - @:final static var TIBETAN : Character_UnicodeBlock; - @:final static var TIFINAGH : Character_UnicodeBlock; - @:final static var TRANSPORT_AND_MAP_SYMBOLS : Character_UnicodeBlock; - @:final static var UGARITIC : Character_UnicodeBlock; - @:final static var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS : Character_UnicodeBlock; - @:final static var UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED : Character_UnicodeBlock; - @:final static var VAI : Character_UnicodeBlock; - @:final static var VARIATION_SELECTORS : Character_UnicodeBlock; - @:final static var VARIATION_SELECTORS_SUPPLEMENT : Character_UnicodeBlock; - @:final static var VEDIC_EXTENSIONS : Character_UnicodeBlock; - @:final static var VERTICAL_FORMS : Character_UnicodeBlock; - @:final static var YIJING_HEXAGRAM_SYMBOLS : Character_UnicodeBlock; - @:final static var YI_RADICALS : Character_UnicodeBlock; - @:final static var YI_SYLLABLES : Character_UnicodeBlock; - @:overload @:final static function forName(param1 : String) : Character_UnicodeBlock; - @:overload static function of(param1 : java.types.Char16) : Character_UnicodeBlock; - @:overload static function of(param1 : Int) : Character_UnicodeBlock; +@:realPath("java.lang.Character_UnicodeBlock") @:javaNative @:native("java.lang.Character$UnicodeBlock") @:javaCanonical("java.lang", + "Character.UnicodeBlock") extern final class Character_UnicodeBlock extends Character_Subset { + static final AEGEAN_NUMBERS:Character_UnicodeBlock; + static final ALCHEMICAL_SYMBOLS:Character_UnicodeBlock; + static final ALPHABETIC_PRESENTATION_FORMS:Character_UnicodeBlock; + static final ANCIENT_GREEK_MUSICAL_NOTATION:Character_UnicodeBlock; + static final ANCIENT_GREEK_NUMBERS:Character_UnicodeBlock; + static final ANCIENT_SYMBOLS:Character_UnicodeBlock; + static final ARABIC:Character_UnicodeBlock; + static final ARABIC_PRESENTATION_FORMS_A:Character_UnicodeBlock; + static final ARABIC_PRESENTATION_FORMS_B:Character_UnicodeBlock; + static final ARABIC_SUPPLEMENT:Character_UnicodeBlock; + static final ARMENIAN:Character_UnicodeBlock; + static final ARROWS:Character_UnicodeBlock; + static final AVESTAN:Character_UnicodeBlock; + static final BALINESE:Character_UnicodeBlock; + static final BAMUM:Character_UnicodeBlock; + static final BAMUM_SUPPLEMENT:Character_UnicodeBlock; + static final BASIC_LATIN:Character_UnicodeBlock; + static final BATAK:Character_UnicodeBlock; + static final BENGALI:Character_UnicodeBlock; + static final BLOCK_ELEMENTS:Character_UnicodeBlock; + static final BOPOMOFO:Character_UnicodeBlock; + static final BOPOMOFO_EXTENDED:Character_UnicodeBlock; + static final BOX_DRAWING:Character_UnicodeBlock; + static final BRAHMI:Character_UnicodeBlock; + static final BRAILLE_PATTERNS:Character_UnicodeBlock; + static final BUGINESE:Character_UnicodeBlock; + static final BUHID:Character_UnicodeBlock; + static final BYZANTINE_MUSICAL_SYMBOLS:Character_UnicodeBlock; + static final CARIAN:Character_UnicodeBlock; + static final CHAM:Character_UnicodeBlock; + static final CHEROKEE:Character_UnicodeBlock; + static final CJK_COMPATIBILITY:Character_UnicodeBlock; + static final CJK_COMPATIBILITY_FORMS:Character_UnicodeBlock; + static final CJK_COMPATIBILITY_IDEOGRAPHS:Character_UnicodeBlock; + static final CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT:Character_UnicodeBlock; + static final CJK_RADICALS_SUPPLEMENT:Character_UnicodeBlock; + static final CJK_STROKES:Character_UnicodeBlock; + static final CJK_SYMBOLS_AND_PUNCTUATION:Character_UnicodeBlock; + static final CJK_UNIFIED_IDEOGRAPHS:Character_UnicodeBlock; + static final CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A:Character_UnicodeBlock; + static final CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B:Character_UnicodeBlock; + static final CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C:Character_UnicodeBlock; + static final CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D:Character_UnicodeBlock; + static final COMBINING_DIACRITICAL_MARKS:Character_UnicodeBlock; + static final COMBINING_DIACRITICAL_MARKS_SUPPLEMENT:Character_UnicodeBlock; + static final COMBINING_HALF_MARKS:Character_UnicodeBlock; + static final COMBINING_MARKS_FOR_SYMBOLS:Character_UnicodeBlock; + static final COMMON_INDIC_NUMBER_FORMS:Character_UnicodeBlock; + static final CONTROL_PICTURES:Character_UnicodeBlock; + static final COPTIC:Character_UnicodeBlock; + static final COUNTING_ROD_NUMERALS:Character_UnicodeBlock; + static final CUNEIFORM:Character_UnicodeBlock; + static final CUNEIFORM_NUMBERS_AND_PUNCTUATION:Character_UnicodeBlock; + static final CURRENCY_SYMBOLS:Character_UnicodeBlock; + static final CYPRIOT_SYLLABARY:Character_UnicodeBlock; + static final CYRILLIC:Character_UnicodeBlock; + static final CYRILLIC_EXTENDED_A:Character_UnicodeBlock; + static final CYRILLIC_EXTENDED_B:Character_UnicodeBlock; + static final CYRILLIC_SUPPLEMENTARY:Character_UnicodeBlock; + static final DESERET:Character_UnicodeBlock; + static final DEVANAGARI:Character_UnicodeBlock; + static final DEVANAGARI_EXTENDED:Character_UnicodeBlock; + static final DINGBATS:Character_UnicodeBlock; + static final DOMINO_TILES:Character_UnicodeBlock; + static final EGYPTIAN_HIEROGLYPHS:Character_UnicodeBlock; + static final EMOTICONS:Character_UnicodeBlock; + static final ENCLOSED_ALPHANUMERICS:Character_UnicodeBlock; + static final ENCLOSED_ALPHANUMERIC_SUPPLEMENT:Character_UnicodeBlock; + static final ENCLOSED_CJK_LETTERS_AND_MONTHS:Character_UnicodeBlock; + static final ENCLOSED_IDEOGRAPHIC_SUPPLEMENT:Character_UnicodeBlock; + static final ETHIOPIC:Character_UnicodeBlock; + static final ETHIOPIC_EXTENDED:Character_UnicodeBlock; + static final ETHIOPIC_EXTENDED_A:Character_UnicodeBlock; + static final ETHIOPIC_SUPPLEMENT:Character_UnicodeBlock; + static final GENERAL_PUNCTUATION:Character_UnicodeBlock; + static final GEOMETRIC_SHAPES:Character_UnicodeBlock; + static final GEORGIAN:Character_UnicodeBlock; + static final GEORGIAN_SUPPLEMENT:Character_UnicodeBlock; + static final GLAGOLITIC:Character_UnicodeBlock; + static final GOTHIC:Character_UnicodeBlock; + static final GREEK:Character_UnicodeBlock; + static final GREEK_EXTENDED:Character_UnicodeBlock; + static final GUJARATI:Character_UnicodeBlock; + static final GURMUKHI:Character_UnicodeBlock; + static final HALFWIDTH_AND_FULLWIDTH_FORMS:Character_UnicodeBlock; + static final HANGUL_COMPATIBILITY_JAMO:Character_UnicodeBlock; + static final HANGUL_JAMO:Character_UnicodeBlock; + static final HANGUL_JAMO_EXTENDED_A:Character_UnicodeBlock; + static final HANGUL_JAMO_EXTENDED_B:Character_UnicodeBlock; + static final HANGUL_SYLLABLES:Character_UnicodeBlock; + static final HANUNOO:Character_UnicodeBlock; + static final HEBREW:Character_UnicodeBlock; + static final HIGH_PRIVATE_USE_SURROGATES:Character_UnicodeBlock; + static final HIGH_SURROGATES:Character_UnicodeBlock; + static final HIRAGANA:Character_UnicodeBlock; + static final IDEOGRAPHIC_DESCRIPTION_CHARACTERS:Character_UnicodeBlock; + static final IMPERIAL_ARAMAIC:Character_UnicodeBlock; + static final INSCRIPTIONAL_PAHLAVI:Character_UnicodeBlock; + static final INSCRIPTIONAL_PARTHIAN:Character_UnicodeBlock; + static final IPA_EXTENSIONS:Character_UnicodeBlock; + static final JAVANESE:Character_UnicodeBlock; + static final KAITHI:Character_UnicodeBlock; + static final KANA_SUPPLEMENT:Character_UnicodeBlock; + static final KANBUN:Character_UnicodeBlock; + static final KANGXI_RADICALS:Character_UnicodeBlock; + static final KANNADA:Character_UnicodeBlock; + static final KATAKANA:Character_UnicodeBlock; + static final KATAKANA_PHONETIC_EXTENSIONS:Character_UnicodeBlock; + static final KAYAH_LI:Character_UnicodeBlock; + static final KHAROSHTHI:Character_UnicodeBlock; + static final KHMER:Character_UnicodeBlock; + static final KHMER_SYMBOLS:Character_UnicodeBlock; + static final LAO:Character_UnicodeBlock; + static final LATIN_1_SUPPLEMENT:Character_UnicodeBlock; + static final LATIN_EXTENDED_A:Character_UnicodeBlock; + static final LATIN_EXTENDED_ADDITIONAL:Character_UnicodeBlock; + static final LATIN_EXTENDED_B:Character_UnicodeBlock; + static final LATIN_EXTENDED_C:Character_UnicodeBlock; + static final LATIN_EXTENDED_D:Character_UnicodeBlock; + static final LEPCHA:Character_UnicodeBlock; + static final LETTERLIKE_SYMBOLS:Character_UnicodeBlock; + static final LIMBU:Character_UnicodeBlock; + static final LINEAR_B_IDEOGRAMS:Character_UnicodeBlock; + static final LINEAR_B_SYLLABARY:Character_UnicodeBlock; + static final LISU:Character_UnicodeBlock; + static final LOW_SURROGATES:Character_UnicodeBlock; + static final LYCIAN:Character_UnicodeBlock; + static final LYDIAN:Character_UnicodeBlock; + static final MAHJONG_TILES:Character_UnicodeBlock; + static final MALAYALAM:Character_UnicodeBlock; + static final MANDAIC:Character_UnicodeBlock; + static final MATHEMATICAL_ALPHANUMERIC_SYMBOLS:Character_UnicodeBlock; + static final MATHEMATICAL_OPERATORS:Character_UnicodeBlock; + static final MEETEI_MAYEK:Character_UnicodeBlock; + static final MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A:Character_UnicodeBlock; + static final MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B:Character_UnicodeBlock; + static final MISCELLANEOUS_SYMBOLS:Character_UnicodeBlock; + static final MISCELLANEOUS_SYMBOLS_AND_ARROWS:Character_UnicodeBlock; + static final MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS:Character_UnicodeBlock; + static final MISCELLANEOUS_TECHNICAL:Character_UnicodeBlock; + static final MODIFIER_TONE_LETTERS:Character_UnicodeBlock; + static final MONGOLIAN:Character_UnicodeBlock; + static final MUSICAL_SYMBOLS:Character_UnicodeBlock; + static final MYANMAR:Character_UnicodeBlock; + static final MYANMAR_EXTENDED_A:Character_UnicodeBlock; + static final NEW_TAI_LUE:Character_UnicodeBlock; + static final NKO:Character_UnicodeBlock; + static final NUMBER_FORMS:Character_UnicodeBlock; + static final OGHAM:Character_UnicodeBlock; + static final OLD_ITALIC:Character_UnicodeBlock; + static final OLD_PERSIAN:Character_UnicodeBlock; + static final OLD_SOUTH_ARABIAN:Character_UnicodeBlock; + static final OLD_TURKIC:Character_UnicodeBlock; + static final OL_CHIKI:Character_UnicodeBlock; + static final OPTICAL_CHARACTER_RECOGNITION:Character_UnicodeBlock; + static final ORIYA:Character_UnicodeBlock; + static final OSMANYA:Character_UnicodeBlock; + static final PHAGS_PA:Character_UnicodeBlock; + static final PHAISTOS_DISC:Character_UnicodeBlock; + static final PHOENICIAN:Character_UnicodeBlock; + static final PHONETIC_EXTENSIONS:Character_UnicodeBlock; + static final PHONETIC_EXTENSIONS_SUPPLEMENT:Character_UnicodeBlock; + static final PLAYING_CARDS:Character_UnicodeBlock; + static final PRIVATE_USE_AREA:Character_UnicodeBlock; + static final REJANG:Character_UnicodeBlock; + static final RUMI_NUMERAL_SYMBOLS:Character_UnicodeBlock; + static final RUNIC:Character_UnicodeBlock; + static final SAMARITAN:Character_UnicodeBlock; + static final SAURASHTRA:Character_UnicodeBlock; + static final SHAVIAN:Character_UnicodeBlock; + static final SINHALA:Character_UnicodeBlock; + static final SMALL_FORM_VARIANTS:Character_UnicodeBlock; + static final SPACING_MODIFIER_LETTERS:Character_UnicodeBlock; + static final SPECIALS:Character_UnicodeBlock; + static final SUNDANESE:Character_UnicodeBlock; + static final SUPERSCRIPTS_AND_SUBSCRIPTS:Character_UnicodeBlock; + static final SUPPLEMENTAL_ARROWS_A:Character_UnicodeBlock; + static final SUPPLEMENTAL_ARROWS_B:Character_UnicodeBlock; + static final SUPPLEMENTAL_MATHEMATICAL_OPERATORS:Character_UnicodeBlock; + static final SUPPLEMENTAL_PUNCTUATION:Character_UnicodeBlock; + static final SUPPLEMENTARY_PRIVATE_USE_AREA_A:Character_UnicodeBlock; + static final SUPPLEMENTARY_PRIVATE_USE_AREA_B:Character_UnicodeBlock; + @:deprecated static var SURROGATES_AREA:Character_UnicodeBlock; + static final SYLOTI_NAGRI:Character_UnicodeBlock; + static final SYRIAC:Character_UnicodeBlock; + static final TAGALOG:Character_UnicodeBlock; + static final TAGBANWA:Character_UnicodeBlock; + static final TAGS:Character_UnicodeBlock; + static final TAI_LE:Character_UnicodeBlock; + static final TAI_THAM:Character_UnicodeBlock; + static final TAI_VIET:Character_UnicodeBlock; + static final TAI_XUAN_JING_SYMBOLS:Character_UnicodeBlock; + static final TAMIL:Character_UnicodeBlock; + static final TELUGU:Character_UnicodeBlock; + static final THAANA:Character_UnicodeBlock; + static final THAI:Character_UnicodeBlock; + static final TIBETAN:Character_UnicodeBlock; + static final TIFINAGH:Character_UnicodeBlock; + static final TRANSPORT_AND_MAP_SYMBOLS:Character_UnicodeBlock; + static final UGARITIC:Character_UnicodeBlock; + static final UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS:Character_UnicodeBlock; + static final UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED:Character_UnicodeBlock; + static final VAI:Character_UnicodeBlock; + static final VARIATION_SELECTORS:Character_UnicodeBlock; + static final VARIATION_SELECTORS_SUPPLEMENT:Character_UnicodeBlock; + static final VEDIC_EXTENSIONS:Character_UnicodeBlock; + static final VERTICAL_FORMS:Character_UnicodeBlock; + static final YIJING_HEXAGRAM_SYMBOLS:Character_UnicodeBlock; + static final YI_RADICALS:Character_UnicodeBlock; + static final YI_SYLLABLES:Character_UnicodeBlock; + @:overload final static function forName(param1:String):Character_UnicodeBlock; + @:overload static function of(param1:java.types.Char16):Character_UnicodeBlock; + @:overload static function of(param1:Int):Character_UnicodeBlock; } -@:realPath("java.lang.Character_UnicodeScript") @:javaCanonical("java.lang","Character.UnicodeScript") @:native("java.lang.Character$UnicodeScript") extern enum Character_UnicodeScript { +@:realPath("java.lang.Character_UnicodeScript") @:javaCanonical("java.lang", + "Character.UnicodeScript") @:native("java.lang.Character$UnicodeScript") extern enum Character_UnicodeScript { COMMON; LATIN; GREEK; diff --git a/std/java/lang/Double.hx b/std/java/lang/Double.hx index b4fa23745b9..61d83ab6fec 100644 --- a/std/java/lang/Double.hx +++ b/std/java/lang/Double.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,48 +19,48 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.lang; + +package java.lang; @:native("") // make sure the generator won't see this @:forwardStatics -@:forward abstract Double(DoubleClass) from DoubleClass to DoubleClass -{ - @:to @:extern inline public function toFloat():Float +@:forward abstract Double(DoubleClass) from DoubleClass to DoubleClass { + @:to extern inline public function toFloat():Float return this.doubleValue(); - @:from @:extern inline public static function fromFloat(b:Float):Double + + @:from extern inline public static function fromFloat(b:Float):Double return DoubleClass.valueOf(b); } -@:native("java.lang.Double") extern class DoubleClass extends Number implements Comparable -{ - @:overload function new(param1 : Float) : Void; - @:overload @:throws("java.lang.NumberFormatException") function new(param1 : String) : Void; - @:overload function compareTo(param1 : Double) : Int; - @:overload function compareTo(param1 : Dynamic) : Int; - @:overload function equals(param1 : Dynamic) : Bool; - @:overload function hashCode() : Int; - @:overload function isInfinite() : Bool; - @:overload function isNaN() : Bool; - @:overload function toString() : String; - @:final static var MAX_EXPONENT(default,null) : Int; - @:final static var MAX_VALUE(default,null) : Float; - @:final static var MIN_EXPONENT(default,null) : Int; - @:final static var MIN_NORMAL(default,null) : Float; - @:final static var MIN_VALUE(default,null) : Float; - @:final static var NEGATIVE_INFINITY(default,null) : Float; - @:final static var NaN(default,null) : Float; - @:final static var POSITIVE_INFINITY(default,null) : Float; - @:final static var SIZE(default,null) : Int; - @:final static var TYPE : Class; - @:overload static function compare(param1 : Float, param2 : Float) : Int; - @:overload static function doubleToLongBits(param1 : Float) : haxe.Int64; - @:overload static function doubleToRawLongBits(param1 : Float) : haxe.Int64; - @:native("isInfinite") @:overload static function _isInfinite(param1 : Float) : Bool; - @:native("isNaN") @:overload static function _isNaN(param1 : Float) : Bool; - @:overload static function longBitsToDouble(param1 : haxe.Int64) : Float; - @:overload @:throws("java.lang.NumberFormatException") static function parseDouble(param1 : String) : Float; - @:overload static function toHexString(param1 : Float) : String; - @:native("toString") @:overload static function _toString(param1 : Float) : String; - @:overload static function valueOf(param1 : Float) : Double; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String) : Double; +@:native("java.lang.Double") extern class DoubleClass extends Number implements Comparable { + @:overload function new(param1:Float):Void; + @:overload @:throws("java.lang.NumberFormatException") function new(param1:String):Void; + @:overload function compareTo(param1:Double):Int; + @:overload function compareTo(param1:Dynamic):Int; + @:overload function equals(param1:Dynamic):Bool; + @:overload function hashCode():Int; + @:overload function isInfinite():Bool; + @:overload function isNaN():Bool; + @:overload function toString():String; + static final MAX_EXPONENT:Int; + static final MAX_VALUE:Float; + static final MIN_EXPONENT:Int; + static final MIN_NORMAL:Float; + static final MIN_VALUE:Float; + static final NEGATIVE_INFINITY:Float; + static final NaN:Float; + static final POSITIVE_INFINITY:Float; + static final SIZE:Int; + static final TYPE:Class; + @:overload static function compare(param1:Float, param2:Float):Int; + @:overload static function doubleToLongBits(param1:Float):haxe.Int64; + @:overload static function doubleToRawLongBits(param1:Float):haxe.Int64; + @:native("isInfinite") @:overload static function _isInfinite(param1:Float):Bool; + @:native("isNaN") @:overload static function _isNaN(param1:Float):Bool; + @:overload static function longBitsToDouble(param1:haxe.Int64):Float; + @:overload @:throws("java.lang.NumberFormatException") static function parseDouble(param1:String):Float; + @:overload static function toHexString(param1:Float):String; + @:native("toString") @:overload static function _toString(param1:Float):String; + @:overload static function valueOf(param1:Float):Double; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String):Double; } diff --git a/std/java/lang/Float.hx b/std/java/lang/Float.hx index 7ca327463df..8a7f4c206f4 100644 --- a/std/java/lang/Float.hx +++ b/std/java/lang/Float.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,51 +19,49 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.lang; + +package java.lang; @:native("") // make sure the generator won't see this @:forwardStatics -@:forward abstract Float(FloatClass) from FloatClass to FloatClass -{ - @:to @:extern inline public function toFloat():std.StdTypes.Float +@:forward abstract Float(FloatClass) from FloatClass to FloatClass { + @:to extern inline public function toFloat():std.StdTypes.Float return this.floatValue(); - @:from @:extern inline public static function fromFloat(b:std.StdTypes.Single):Float + + @:from extern inline public static function fromFloat(b:std.StdTypes.Single):Float return FloatClass.valueOf(b); } -@:native("java.lang.Float") extern class FloatClass extends Number implements Comparable -{ - @:overload function new(param1 : Single) : Void; - @:overload @:throws("java.lang.NumberFormatException") function new(param1 : String) : Void; - @:overload function new(param1 : std.StdTypes.Float) : Void; - @:overload function compareTo(param1 : Float) : Int; - @:overload function compareTo(param1 : Dynamic) : Int; - @:overload function equals(param1 : Dynamic) : Bool; - @:overload function hashCode() : Int; - @:overload function isInfinite() : Bool; - @:overload function isNaN() : Bool; - @:overload function toString() : String; - @:final static var MAX_EXPONENT(default,null) : Int; - @:final static var MAX_VALUE(default,null) : Single; - @:final static var MIN_EXPONENT(default,null) : Int; - @:final static var MIN_NORMAL(default,null) : Single; - @:final static var MIN_VALUE(default,null) : Single; - @:final static var NEGATIVE_INFINITY(default,null) : Single; - @:final static var NaN(default,null) : Single; - @:final static var POSITIVE_INFINITY(default,null) : Single; - @:final static var SIZE(default,null) : Int; - @:final static var TYPE : Class; - @:overload static function compare(param1 : Single, param2 : Single) : Int; - @:overload static function floatToIntBits(param1 : Single) : Int; - @:overload static function floatToRawIntBits(param1 : Single) : Int; - @:overload static function intBitsToFloat(param1 : Int) : Single; - @:native("isInfinite") @:overload static function _isInfinite(param1 : Single) : Bool; - @:native("isNaN") @:overload static function _isNaN(param1 : Single) : Bool; - @:overload @:throws("java.lang.NumberFormatException") static function parseFloat(param1 : String) : Single; - @:overload static function toHexString(param1 : Single) : String; - @:native("toString") @:overload static function _toString(param1 : Single) : String; - @:overload static function valueOf(param1 : Single) : Float; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String) : Float; - +@:native("java.lang.Float") extern class FloatClass extends Number implements Comparable { + @:overload function new(param1:Single):Void; + @:overload @:throws("java.lang.NumberFormatException") function new(param1:String):Void; + @:overload function new(param1:std.StdTypes.Float):Void; + @:overload function compareTo(param1:Float):Int; + @:overload function compareTo(param1:Dynamic):Int; + @:overload function equals(param1:Dynamic):Bool; + @:overload function hashCode():Int; + @:overload function isInfinite():Bool; + @:overload function isNaN():Bool; + @:overload function toString():String; + static final MAX_EXPONENT:Int; + static final MAX_VALUE:Single; + static final MIN_EXPONENT:Int; + static final MIN_NORMAL:Single; + static final MIN_VALUE:Single; + static final NEGATIVE_INFINITY:Single; + static final NaN:Single; + static final POSITIVE_INFINITY:Single; + static final SIZE:Int; + static final TYPE:Class; + @:overload static function compare(param1:Single, param2:Single):Int; + @:overload static function floatToIntBits(param1:Single):Int; + @:overload static function floatToRawIntBits(param1:Single):Int; + @:overload static function intBitsToFloat(param1:Int):Single; + @:native("isInfinite") @:overload static function _isInfinite(param1:Single):Bool; + @:native("isNaN") @:overload static function _isNaN(param1:Single):Bool; + @:overload @:throws("java.lang.NumberFormatException") static function parseFloat(param1:String):Single; + @:overload static function toHexString(param1:Single):String; + @:native("toString") @:overload static function _toString(param1:Single):String; + @:overload static function valueOf(param1:Single):Float; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String):Float; } - diff --git a/std/java/lang/Integer.hx b/std/java/lang/Integer.hx index 1d157f92722..402c0584f7b 100644 --- a/std/java/lang/Integer.hx +++ b/std/java/lang/Integer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,57 +19,57 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.lang; + +package java.lang; @:native("") // make sure the generator won't see this @:forwardStatics -@:forward abstract Integer(IntegerClass) from IntegerClass to IntegerClass -{ - @:to @:extern inline public function toInt():Int +@:forward abstract Integer(IntegerClass) from IntegerClass to IntegerClass { + @:to extern inline public function toInt():Int return this.intValue(); - @:from @:extern inline public static function fromInt(b:Int):Integer + + @:from extern inline public static function fromInt(b:Int):Integer return IntegerClass.valueOf(b); } -@:native("java.lang.Integer") extern class IntegerClass extends Number implements Comparable -{ - @:overload function new(param1 : Int) : Void; - @:overload @:throws("java.lang.NumberFormatException") function new(param1 : String) : Void; - @:overload function compareTo(param1 : Integer) : Int; - @:overload function compareTo(param1 : Dynamic) : Int; - @:overload function equals(param1 : Dynamic) : Bool; - @:overload function hashCode() : Int; - @:overload function toString() : String; - @:final static var MAX_VALUE(default,null) : Int; - @:final static var MIN_VALUE(default,null) : Int; - @:final static var SIZE(default,null) : Int; - @:final static var TYPE : Class; - @:overload static function bitCount(param1 : Int) : Int; - @:overload static function compare(param1 : Int, param2 : Int) : Int; - @:overload @:throws("java.lang.NumberFormatException") static function decode(param1 : String) : Integer; - @:overload static function getInteger(param1 : String) : Integer; - @:overload static function getInteger(param1 : String, param2 : Integer) : Integer; - @:overload static function getInteger(param1 : String, param2 : Int) : Integer; - @:overload static function highestOneBit(param1 : Int) : Int; - @:overload static function lowestOneBit(param1 : Int) : Int; - @:overload static function numberOfLeadingZeros(param1 : Int) : Int; - @:overload static function numberOfTrailingZeros(param1 : Int) : Int; - @:overload @:throws("java.lang.NumberFormatException") static function parseInt(param1 : String, param2 : Int) : Int; - @:overload @:throws("java.lang.NumberFormatException") static function parseInt(param1 : String) : Int; - @:overload static function reverse(param1 : Int) : Int; - @:overload static function reverseBytes(param1 : Int) : Int; - @:overload static function rotateLeft(param1 : Int, param2 : Int) : Int; - @:overload static function rotateRight(param1 : Int, param2 : Int) : Int; - @:overload static function signum(param1 : Int) : Int; - @:overload static function toBinaryString(param1 : Int) : String; - @:overload static function toHexString(param1 : Int) : String; - @:overload static function toOctalString(param1 : Int) : String; - @:native("toString") @:overload static function _toString(param1 : Int, param2 : Int) : String; - @:native("toString") @:overload static function _toString(param1 : Int) : String; - @:overload static function valueOf(param1 : Int) : Integer; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String, param2 : Int) : Integer; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String) : Integer; +@:native("java.lang.Integer") extern class IntegerClass extends Number implements Comparable { + @:overload function new(param1:Int):Void; + @:overload @:throws("java.lang.NumberFormatException") function new(param1:String):Void; + @:overload function compareTo(param1:Integer):Int; + @:overload function compareTo(param1:Dynamic):Int; + @:overload function equals(param1:Dynamic):Bool; + @:overload function hashCode():Int; + @:overload function toString():String; + static final MAX_VALUE:Int; + static final MIN_VALUE:Int; + static final SIZE:Int; + static final TYPE:Class; + @:overload static function bitCount(param1:Int):Int; + @:overload static function compare(param1:Int, param2:Int):Int; + @:overload @:throws("java.lang.NumberFormatException") static function decode(param1:String):Integer; + @:overload static function getInteger(param1:String):Integer; + @:overload static function getInteger(param1:String, param2:Integer):Integer; + @:overload static function getInteger(param1:String, param2:Int):Integer; + @:overload static function highestOneBit(param1:Int):Int; + @:overload static function lowestOneBit(param1:Int):Int; + @:overload static function numberOfLeadingZeros(param1:Int):Int; + @:overload static function numberOfTrailingZeros(param1:Int):Int; + @:overload @:throws("java.lang.NumberFormatException") static function parseInt(param1:String, param2:Int):Int; + @:overload @:throws("java.lang.NumberFormatException") static function parseInt(param1:String):Int; + @:overload static function reverse(param1:Int):Int; + @:overload static function reverseBytes(param1:Int):Int; + @:overload static function rotateLeft(param1:Int, param2:Int):Int; + @:overload static function rotateRight(param1:Int, param2:Int):Int; + @:overload static function signum(param1:Int):Int; + @:overload static function toBinaryString(param1:Int):String; + @:overload static function toHexString(param1:Int):String; + @:overload static function toOctalString(param1:Int):String; + @:native("toString") @:overload static function _toString(param1:Int, param2:Int):String; + @:native("toString") @:overload static function _toString(param1:Int):String; + @:overload static function valueOf(param1:Int):Integer; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String, param2:Int):Integer; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String):Integer; } -@:realPath("java.lang.Integer_IntegerCache") @:javaNative @:native("java.lang.Integer$IntegerCache") @:javaCanonical("java.lang","Integer.IntegerCache") extern class Integer_IntegerCache { -} +@:realPath("java.lang.Integer_IntegerCache") @:javaNative @:native("java.lang.Integer$IntegerCache") @:javaCanonical("java.lang", + "Integer.IntegerCache") extern class Integer_IntegerCache {} diff --git a/std/java/lang/Long.hx b/std/java/lang/Long.hx index 4ff65e13118..5f798224e93 100644 --- a/std/java/lang/Long.hx +++ b/std/java/lang/Long.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,57 +19,57 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.lang; + +package java.lang; @:native("") // make sure the generator won't see this @:forwardStatics -@:forward abstract Long(LongClass) from LongClass to LongClass -{ - @:to @:extern inline public function toLong():haxe.Int64 +@:forward abstract Long(LongClass) from LongClass to LongClass { + @:to extern inline public function toLong():haxe.Int64 return this.longValue(); - @:from @:extern inline public static function fromLong(b:haxe.Int64):Long + + @:from extern inline public static function fromLong(b:haxe.Int64):Long return LongClass.valueOf(b); } -@:native("java.lang.Long") extern class LongClass extends Number implements Comparable -{ - @:overload @:throws("java.lang.NumberFormatException") function new(param1 : String) : Void; - @:overload function new(param1 : haxe.Int64) : Void; - @:overload function compareTo(param1 : Dynamic) : Int; - @:overload function compareTo(param1 : Long) : Int; - @:overload function equals(param1 : Dynamic) : Bool; - @:overload function hashCode() : Int; - @:overload function toString() : String; - @:final static var MAX_VALUE(default,null) : haxe.Int64; - @:final static var MIN_VALUE(default,null) : haxe.Int64; - @:final static var SIZE(default,null) : Int; - @:final static var TYPE : Class; - @:overload static function bitCount(param1 : haxe.Int64) : Int; - @:overload static function compare(param1 : haxe.Int64, param2 : haxe.Int64) : Int; - @:overload @:throws("java.lang.NumberFormatException") static function decode(param1 : String) : Long; - @:overload static function getLong(param1 : String, param2 : Long) : Long; - @:overload static function getLong(param1 : String) : Long; - @:overload static function getLong(param1 : String, param2 : haxe.Int64) : Long; - @:overload static function highestOneBit(param1 : haxe.Int64) : haxe.Int64; - @:overload static function lowestOneBit(param1 : haxe.Int64) : haxe.Int64; - @:overload static function numberOfLeadingZeros(param1 : haxe.Int64) : Int; - @:overload static function numberOfTrailingZeros(param1 : haxe.Int64) : Int; - @:overload @:throws("java.lang.NumberFormatException") static function parseLong(param1 : String) : haxe.Int64; - @:overload @:throws("java.lang.NumberFormatException") static function parseLong(param1 : String, param2 : Int) : haxe.Int64; - @:overload static function reverse(param1 : haxe.Int64) : haxe.Int64; - @:overload static function reverseBytes(param1 : haxe.Int64) : haxe.Int64; - @:overload static function rotateLeft(param1 : haxe.Int64, param2 : Int) : haxe.Int64; - @:overload static function rotateRight(param1 : haxe.Int64, param2 : Int) : haxe.Int64; - @:overload static function signum(param1 : haxe.Int64) : Int; - @:overload static function toBinaryString(param1 : haxe.Int64) : String; - @:overload static function toHexString(param1 : haxe.Int64) : String; - @:overload static function toOctalString(param1 : haxe.Int64) : String; - @:native("toString") @:overload static function _toString(param1 : haxe.Int64) : String; - @:native("toString") @:overload static function _toString(param1 : haxe.Int64, param2 : Int) : String; - @:overload static function valueOf(param1 : haxe.Int64) : Long; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String, param2 : Int) : Long; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String) : Long; +@:native("java.lang.Long") extern class LongClass extends Number implements Comparable { + @:overload @:throws("java.lang.NumberFormatException") function new(param1:String):Void; + @:overload function new(param1:haxe.Int64):Void; + @:overload function compareTo(param1:Dynamic):Int; + @:overload function compareTo(param1:Long):Int; + @:overload function equals(param1:Dynamic):Bool; + @:overload function hashCode():Int; + @:overload function toString():String; + static final MAX_VALUE:haxe.Int64; + static final MIN_VALUE:haxe.Int64; + static final SIZE:Int; + static final TYPE:Class; + @:overload static function bitCount(param1:haxe.Int64):Int; + @:overload static function compare(param1:haxe.Int64, param2:haxe.Int64):Int; + @:overload @:throws("java.lang.NumberFormatException") static function decode(param1:String):Long; + @:overload static function getLong(param1:String, param2:Long):Long; + @:overload static function getLong(param1:String):Long; + @:overload static function getLong(param1:String, param2:haxe.Int64):Long; + @:overload static function highestOneBit(param1:haxe.Int64):haxe.Int64; + @:overload static function lowestOneBit(param1:haxe.Int64):haxe.Int64; + @:overload static function numberOfLeadingZeros(param1:haxe.Int64):Int; + @:overload static function numberOfTrailingZeros(param1:haxe.Int64):Int; + @:overload @:throws("java.lang.NumberFormatException") static function parseLong(param1:String):haxe.Int64; + @:overload @:throws("java.lang.NumberFormatException") static function parseLong(param1:String, param2:Int):haxe.Int64; + @:overload static function reverse(param1:haxe.Int64):haxe.Int64; + @:overload static function reverseBytes(param1:haxe.Int64):haxe.Int64; + @:overload static function rotateLeft(param1:haxe.Int64, param2:Int):haxe.Int64; + @:overload static function rotateRight(param1:haxe.Int64, param2:Int):haxe.Int64; + @:overload static function signum(param1:haxe.Int64):Int; + @:overload static function toBinaryString(param1:haxe.Int64):String; + @:overload static function toHexString(param1:haxe.Int64):String; + @:overload static function toOctalString(param1:haxe.Int64):String; + @:native("toString") @:overload static function _toString(param1:haxe.Int64):String; + @:native("toString") @:overload static function _toString(param1:haxe.Int64, param2:Int):String; + @:overload static function valueOf(param1:haxe.Int64):Long; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String, param2:Int):Long; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String):Long; } -@:realPath("java.lang.Long_LongCache") @:javaNative @:native("java.lang.Long$LongCache") @:javaCanonical("java.lang","Long.LongCache") extern class Long_LongCache { -} +@:realPath("java.lang.Long_LongCache") @:javaNative @:native("java.lang.Long$LongCache") @:javaCanonical("java.lang", + "Long.LongCache") extern class Long_LongCache {} diff --git a/std/java/lang/Short.hx b/std/java/lang/Short.hx index 26b8f862104..ff688a90778 100644 --- a/std/java/lang/Short.hx +++ b/std/java/lang/Short.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,41 +19,41 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.lang; + +package java.lang; @:native("") // make sure the generator won't see this @:forwardStatics -@:forward abstract Short(ShortClass) from ShortClass to ShortClass -{ - @:to @:extern inline public function toShort():java.types.Int16 +@:forward abstract Short(ShortClass) from ShortClass to ShortClass { + @:to extern inline public function toShort():java.types.Int16 return this.shortValue(); - @:from @:extern inline public static function fromShort(b:java.types.Int16):Short + + @:from extern inline public static function fromShort(b:java.types.Int16):Short return ShortClass.valueOf(b); } -@:native("java.lang.Short") extern class ShortClass extends Number implements Comparable -{ - @:overload function new(param1 : java.types.Int16) : Void; - @:overload @:throws("java.lang.NumberFormatException") function new(param1 : String) : Void; - @:overload function compareTo(param1 : Short) : Int; - @:overload function compareTo(param1 : Dynamic) : Int; - @:overload function equals(param1 : Dynamic) : Bool; - @:overload function hashCode() : Int; - @:overload function toString() : String; - @:final static var MAX_VALUE(default,null) : java.types.Int16; - @:final static var MIN_VALUE(default,null) : java.types.Int16; - @:final static var SIZE(default,null) : Int; - @:final static var TYPE : Class; - @:overload static function compare(param1 : java.types.Int16, param2 : java.types.Int16) : Int; - @:overload @:throws("java.lang.NumberFormatException") static function decode(param1 : String) : Short; - @:overload @:throws("java.lang.NumberFormatException") static function parseShort(param1 : String, param2 : Int) : java.types.Int16; - @:overload @:throws("java.lang.NumberFormatException") static function parseShort(param1 : String) : java.types.Int16; - @:overload static function reverseBytes(param1 : java.types.Int16) : java.types.Int16; - @:native("toString") @:overload static function _toString(param1 : java.types.Int16) : String; - @:overload static function valueOf(param1 : java.types.Int16) : Short; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String, param2 : Int) : Short; - @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1 : String) : Short; +@:native("java.lang.Short") extern class ShortClass extends Number implements Comparable { + @:overload function new(param1:java.types.Int16):Void; + @:overload @:throws("java.lang.NumberFormatException") function new(param1:String):Void; + @:overload function compareTo(param1:Short):Int; + @:overload function compareTo(param1:Dynamic):Int; + @:overload function equals(param1:Dynamic):Bool; + @:overload function hashCode():Int; + @:overload function toString():String; + static final MAX_VALUE:java.types.Int16; + static final MIN_VALUE:java.types.Int16; + static final SIZE:Int; + static final TYPE:Class; + @:overload static function compare(param1:java.types.Int16, param2:java.types.Int16):Int; + @:overload @:throws("java.lang.NumberFormatException") static function decode(param1:String):Short; + @:overload @:throws("java.lang.NumberFormatException") static function parseShort(param1:String, param2:Int):java.types.Int16; + @:overload @:throws("java.lang.NumberFormatException") static function parseShort(param1:String):java.types.Int16; + @:overload static function reverseBytes(param1:java.types.Int16):java.types.Int16; + @:native("toString") @:overload static function _toString(param1:java.types.Int16):String; + @:overload static function valueOf(param1:java.types.Int16):Short; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String, param2:Int):Short; + @:overload @:throws("java.lang.NumberFormatException") static function valueOf(param1:String):Short; } -@:realPath("java.lang.Short_ShortCache") @:javaNative @:native("java.lang.Short$ShortCache") @:javaCanonical("java.lang","Short.ShortCache") extern class Short_ShortCache { -} +@:realPath("java.lang.Short_ShortCache") @:javaNative @:native("java.lang.Short$ShortCache") @:javaCanonical("java.lang", + "Short.ShortCache") extern class Short_ShortCache {} diff --git a/std/java/net/SslSocket.hx b/std/java/net/SslSocket.hx index 60e543a8a6d..f2116afc2e7 100644 --- a/std/java/net/SslSocket.hx +++ b/std/java/net/SslSocket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,17 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package java.net; @:native('haxe.java.net.SslSocket') class SslSocket extends sys.net.Socket { - - override private function create() : Void - { - try - { + override private function create():Void { + try { this.sock = java.javax.net.ssl.SSLSocketFactory.getDefault().createSocket(); this.server = java.javax.net.ssl.SSLServerSocketFactory.getDefault().createServerSocket(); - } catch(e:Dynamic) throw e; + } catch (e:Dynamic) + throw e; } - } diff --git a/std/java/types/Char16.hx b/std/java/types/Char16.hx index 893366d5b27..3f0f9eb9ed0 100644 --- a/std/java/types/Char16.hx +++ b/std/java/types/Char16.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.types; + +package java.types; typedef Char16 = java.StdTypes.Char16; diff --git a/std/java/types/Int16.hx b/std/java/types/Int16.hx index a28857a77a6..1f264aa6d2d 100644 --- a/std/java/types/Int16.hx +++ b/std/java/types/Int16.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.types; + +package java.types; typedef Int16 = java.StdTypes.Int16; diff --git a/std/java/types/Int8.hx b/std/java/types/Int8.hx index e5b50b17bb8..baccb6c9629 100644 --- a/std/java/types/Int8.hx +++ b/std/java/types/Int8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.types; + +package java.types; typedef Int8 = java.StdTypes.Int8; diff --git a/std/java/vm/AtomicList.hx b/std/java/vm/AtomicList.hx index 29671dd7117..f61dc279338 100644 --- a/std/java/vm/AtomicList.hx +++ b/std/java/vm/AtomicList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.vm; + +package java.vm; import java.util.concurrent.atomic.AtomicReference; @@ -27,67 +28,56 @@ import java.util.concurrent.atomic.AtomicReference; A lock-free queue implementation **/ @:native('haxe.java.vm.AtomicList') -@:nativeGen class AtomicList -{ +@:nativeGen class AtomicList { @:volatile @:private var head:AtomicNode; @:volatile @:private var tail:AtomicReference>; - public function new() - { + public function new() { this.head = new AtomicNode(null); this.head.set(new AtomicNode(null)); this.tail = new AtomicReference(head); } - public function add(v:T) - { + public function add(v:T) { var n = new AtomicNode(v), tail = this.tail; var p = null; - while( !((p = tail.get()).compareAndSet(null, n)) ) - { + while (!((p = tail.get()).compareAndSet(null, n))) { tail.compareAndSet(p, p.get()); } tail.compareAndSet(p, n); } - public function pop():Null - { + public function pop():Null { var p = null, pget = null, head = head; - do - { + do { p = head.get(); - if ( (pget = p.get()) == null) - return null; //empty - } while(!head.compareAndSet(p, pget)); + if ((pget = p.get()) == null) + return null; // empty + } while (!head.compareAndSet(p, pget)); var ret = pget.value; pget.value = null; return ret; } - public function peek() - { + public function peek() { var ret = head.get(); - if (ret == null) return null; //empty + if (ret == null) + return null; // empty return ret.value; } - public function peekLast() - { + public function peekLast() { return tail.get().value; } - } @:native('haxe.java.vm.AtomicNode') -@:nativeGen class AtomicNode extends AtomicReference> -{ +@:nativeGen class AtomicNode extends AtomicReference> { public var value:T; - public function new(value) - { + public function new(value) { super(); this.value = value; } - } diff --git a/std/java/vm/Deque.hx b/std/java/vm/Deque.hx index b85cbfe5ac1..004c27e5b45 100644 --- a/std/java/vm/Deque.hx +++ b/std/java/vm/Deque.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,76 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.vm; -import java.Lib; -/** - A Lock-free Queue implementation -**/ -@:native('haxe.java.vm.Deque') -@:nativeGen class Deque -{ - @:private var head:Node; - @:private var tail:Node; +package java.vm; - public function new() - { - this.head = this.tail = new Node(null); - } - - public function add(i : T) - { - var n = new Node(i); - untyped __lock__(this, - { - tail.next = n; - tail = n; - try { untyped this.notify(); } catch(e:Dynamic) { throw e; } - }); - } - - public function push(i : T) - { - var n = new Node(i); - untyped __lock__(this, - { - n.next = head.next; - head.next = n; - try { untyped this.notify(); } catch(e:Dynamic) { throw e; } - }); - } - - public function pop(block : Bool) : Null - { - var ret = null; - untyped __lock__(this, { - var n = null; - do { - n = head.next; - if (n != null) - { - ret = n.value; - n.value = null; - head = n; - } else if (block) { - //block - try { untyped this.wait(); } catch(e:Dynamic) { throw e; } - } - } while( block && n == null ); - }); - return ret; - } -} - -@:native('haxe.java.vm.DequeNode') -@:nativeGen -class Node -{ - public var value:T; - public var next:Node; - - public function new(val) - { - this.value = val; - } -} +@:deprecated typedef Deque = sys.thread.Deque; diff --git a/std/java/vm/Gc.hx b/std/java/vm/Gc.hx index afa2f578884..11423660f8c 100644 --- a/std/java/vm/Gc.hx +++ b/std/java/vm/Gc.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,18 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.vm; -@:native('haxe.java.vm.Gc') class Gc -{ - public static function run( major : Bool ) - { +package java.vm; + +@:native('haxe.java.vm.Gc') class Gc { + public static function run(major:Bool) { java.lang.System.gc(); } - public static function stats() : { heap : Int, free : Int } - { + public static function stats():{heap:Int, free:Int} { var r = java.lang.Runtime.getRuntime(); - return { heap : cast r.totalMemory(), free : cast r.freeMemory() }; + return {heap: cast r.totalMemory(), free: cast r.freeMemory()}; } } diff --git a/std/java/vm/Lock.hx b/std/java/vm/Lock.hx index fc4128d7227..65286ff7a72 100644 --- a/std/java/vm/Lock.hx +++ b/std/java/vm/Lock.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,87 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.vm; -import java.Lib; -import java.lang.System; -using haxe.Int64; -@:native('haxe.java.vm.Lock') class Lock -{ - @:private @:volatile var releasedCount = 0; +package java.vm; - /** - Creates a new lock, which is initially locked - **/ - public function new() - { - } - - /** - Waits for a lock to be released and acquire it. - If `timeout` (in seconds) is not null and expires then the returned value is false - **/ - public function wait(?timeout : Float) : Bool - { - var ret = false; - java.Lib.lock(this, - { - if (--releasedCount < 0) - { - if (timeout == null) - { - // since .notify() is asynchronous, this `while` is needed - // because there is a very remote possibility of release() awaking a thread, - // but before it releases, another thread calls wait - and since the release count - // is still positive, it will get the lock. - while( releasedCount < 0 ) - { - try - { - untyped __java__("this.wait()"); - } - catch(e:java.lang.InterruptedException) - { - } - } - } else { - var timeout:haxe.Int64 = cast timeout * 1000; - var cur = System.currentTimeMillis(), - max = cur.add(timeout); - // see above comment about this while loop - while ( releasedCount < 0 && cur.compare(max) < 0 ) - { - try - { - var t = max.sub(cur); - untyped __java__("this.wait({0})",t); - cur = System.currentTimeMillis(); - } - catch(e:java.lang.InterruptedException) - { - } - } - } - } - ret = this.releasedCount >= 0; - if (!ret) - this.releasedCount++; //timed out - }); - return ret; - } - - /** - Release a lock. The thread does not need to own the lock to be able to release it. - If a lock is released several times, it can be acquired as many times - **/ - public function release() - { - untyped __lock__(this, - { - if (++releasedCount >= 0) - { - untyped this.notify(); - } - }); - } -} +@:deprecated typedef Lock = sys.thread.Lock; diff --git a/std/java/vm/Mutex.hx b/std/java/vm/Mutex.hx index 6077bda1671..ae0900cff3c 100644 --- a/std/java/vm/Mutex.hx +++ b/std/java/vm/Mutex.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,44 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.vm; -import java.util.concurrent.locks.ReentrantLock; -@:native('haxe.java.vm.Mutex') class Mutex -{ - @:private var lock:ReentrantLock; +package java.vm; - /** - Creates a mutex, which can be used to acquire a temporary lock to access some resource. - The main difference with a lock is that a mutex must always be released by the owner thread - **/ - public function new() - { - this.lock = new ReentrantLock(); - } - - /** - Try to acquire the mutex, returns true if acquire or false if it's already locked by another thread. - **/ - public function tryAcquire():Bool - { - return this.lock.tryLock(); - } - - /** - The current thread acquire the mutex or wait if not available. - The same thread can acquire several times the same mutex, but must release it as many times it has been acquired. - **/ - public function acquire():Void - { - this.lock.lock(); - } - - /** - Release a mutex that has been acquired by the current thread. If the current thread does not own the mutex, an exception will be thrown - **/ - public function release():Void - { - this.lock.unlock(); - } -} +@:deprecated typedef Mutex = sys.thread.Mutex; diff --git a/std/java/vm/Thread.hx b/std/java/vm/Thread.hx index 84bb1dae1d8..e1a1dcc9543 100644 --- a/std/java/vm/Thread.hx +++ b/std/java/vm/Thread.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,93 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.vm; -import java.Lib; -@:native('haxe.java.vm.Thread') class Thread -{ +package java.vm; - @:private static var javaThreadToHaxe = new haxe.ds.WeakMap(); - @:private static var mainJavaThread = java.lang.Thread.currentThread(); - @:private static var mainHaxeThread = { - var ret = new Thread(); - javaThreadToHaxe.set(mainJavaThread, ret); - ret; - }; - - - private static function getThread(jt:java.lang.Thread):Thread - { - if (Std.is(jt, HaxeThread)) - { - var t:HaxeThread = cast jt; - return t.threadObject; - } - else if (jt == mainJavaThread) - { - return mainHaxeThread; - } - else - { - var ret = null; - untyped __lock__(javaThreadToHaxe, { - ret = javaThreadToHaxe.get(jt); - if (ret == null) - { - ret = new Thread(); - javaThreadToHaxe.set(jt, ret); - } - - }); - return ret; - } - } - - private var messages:Deque; - - function new() - { - this.messages = new Deque(); - } - - public function sendMessage(obj:Dynamic) - { - messages.add(obj); - } - - public static function current():Thread - { - return getThread( java.lang.Thread.currentThread() ); - } - - public static function readMessage(block : Bool) : Dynamic - { - return current().messages.pop(block); - } - - public static function create(fn:Void->Void):Thread - { - var ret = new Thread(); - var t = new HaxeThread(ret, fn); - t.start(); - return ret; - } -} - -@:native('haxe.java.vm.HaxeThread') -private class HaxeThread extends java.lang.Thread -{ - public var threadObject(default, null):Thread; - private var runFunction:Void->Void; - @:overload override public function run():Void - { - runFunction(); - } - public function new(hxThread:Thread, run:Void->Void) - { - super(); - threadObject = hxThread; - runFunction = run; - setDaemon(true); - } -} +@:deprecated typedef Thread = sys.thread.Thread; diff --git a/std/java/vm/Tls.hx b/std/java/vm/Tls.hx index 375b4778227..2bb6f1bc004 100644 --- a/std/java/vm/Tls.hx +++ b/std/java/vm/Tls.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,30 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package java.vm; -/** - Thread-local Storage implementation -**/ -@:native('haxe.java.vm.Tls') class Tls -{ - var t : java.lang.ThreadLocal; - public var value(get,set):T; +package java.vm; - public function new() - { - this.t = new java.lang.ThreadLocal(); - } - - inline private function get_value():T - { - return t.get(); - } - - inline private function set_value(v:T):T - { - t.set(v); - return v; - } - -} +@:deprecated typedef Tls = sys.thread.Tls; diff --git a/std/js/Boot.hx b/std/js/Boot.hx index a964e19b453..e27b52f0752 100644 --- a/std/js/Boot.hx +++ b/std/js/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,39 +19,51 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package js; -private class HaxeError extends js.Error { +import js.Syntax; // import it here so it's always available in the compiler +private class HaxeError extends js.lib.Error { var val:Dynamic; - public function new(val:Dynamic) untyped { + @:pure + public function new(val:Dynamic) { super(); - this.val = __define_feature__("js.Boot.HaxeError", val); - this.message = String(val); - if (js.Error.captureStackTrace) js.Error.captureStackTrace(this, HaxeError); + this.val = val; + if ((cast js.lib.Error).captureStackTrace) + (cast js.lib.Error).captureStackTrace(this, HaxeError); + } + + public static function wrap(val:Dynamic):js.lib.Error { + return if (js.Syntax.instanceof(val, js.lib.Error)) val else new HaxeError(val); } - public static function wrap(val:Dynamic):Dynamic untyped { - return if (__instanceof__(val, js.Error)) val else new HaxeError(val); + static function __init__() { + js.lib.Object.defineProperty((cast HaxeError).prototype, "message", {get: () -> (cast String)(js.Lib.nativeThis.val)}); } } @:dox(hide) class Boot { - - static inline function isClass(o:Dynamic) : Bool { + static inline function isClass(o:Dynamic):Bool { return untyped __define_feature__("js.Boot.isClass", o.__name__); } - static inline function isEnum(e:Dynamic) : Bool { + static inline function isInterface(o:Class):Bool { + return untyped __define_feature__("js.Boot.isInterface", o.__isInterface__); + } + + static inline function isEnum(e:Dynamic):Bool { return untyped __define_feature__("js.Boot.isEnum", e.__ename__); } - static function getClass(o:Dynamic) : Dynamic { - if (Std.is(o, Array)) + @:pure static function getClass(o:Null):Null { + if (o == null) { + return null; + } else if (Std.is(o, Array)) { return Array; - else { + } else { var cl = untyped __define_feature__("js.Boot.getClass", o.__class__); if (cl != null) return cl; @@ -63,161 +75,175 @@ class Boot { } @:ifFeature("has_enum") - private static function __string_rec(o,s:String) { + private static function __string_rec(o, s:String) { untyped { - if( o == null ) - return "null"; - if( s.length >= 5 ) + if (o == null) + return "null"; + if (s.length >= 5) return "<...>"; // too much deep recursion - var t = js.Lib.typeof(o); - if( t == "function" && (isClass(o) || isEnum(o)) ) + var t = js.Syntax.typeof(o); + if (t == "function" && (isClass(o) || isEnum(o))) t = "object"; - switch( t ) { - case "object": - #if js_enums_as_objects - if (o.__enum__) { - var e = $hxEnums[o.__enum__]; - var n = e.__constructs__[o._hx_index]; - var con = e[n]; - if (con.__params__) { + switch (t) { + case "object": + #if !js_enums_as_arrays + __feature__("has_enum", if (o.__enum__) { + var e = $hxEnums[o.__enum__]; + var n = e.__constructs__[o._hx_index]; + var con = e[n]; + if (con.__params__) { + s += "\t"; + return n + "(" + [for (p in (con.__params__ : Array)) __string_rec(o[p], s)].join(",") + ")"; + } else { + return n; + } + }); + #end + if (js.Syntax.instanceof(o, Array)) { + #if js_enums_as_arrays + __feature__("has_enum", if (o.__enum__) { + if (o.length == 2) + return o[0]; + var str = o[0] + "("; + s += "\t"; + for (i in 2...o.length) { + if (i != 2) + str += "," + __string_rec(o[i], s); + else + str += __string_rec(o[i], s); + } + return str + ")"; + }); + #end + var str = "["; s += "\t"; - return n + "(" + - [for (p in (con.__params__:Array)) __string_rec(o[p],s)].join(",") + ")"; - } else { - return n; + for (i in 0...o.length) + str += (if (i > 0) "," else "") + __string_rec(o[i], s); + str += "]"; + return str; } - } - #end - if( __js__("o instanceof Array") ) { - #if !js_enums_as_objects - if( o.__enum__ ) { - if( o.length == 2 ) - return o[0]; - var str = o[0]+"("; - s += "\t"; - for( i in 2...o.length ) { - if( i != 2 ) - str += "," + __string_rec(o[i],s); - else - str += __string_rec(o[i],s); - } - return str + ")"; + var tostr; + try { + tostr = untyped o.toString; + } catch (e:Dynamic) { + // strange error on IE + return "???"; } - #end - var l = o.length; - var i; - var str = "["; + if (tostr != null && tostr != __js__("Object.toString") && js.Syntax.typeof(tostr) == "function") { + var s2 = o.toString(); + if (s2 != "[object Object]") + return s2; + } + var str = "{\n"; s += "\t"; - for( i in 0...l ) - str += (if (i > 0) "," else "")+__string_rec(o[i],s); - str += "]"; - return str; - } - var tostr; - try { - tostr = untyped o.toString; - } catch( e : Dynamic ) { - // strange error on IE - return "???"; - } - if( tostr != null && tostr != __js__("Object.toString") && js.Lib.typeof(tostr) == "function" ) { - var s2 = o.toString(); - if( s2 != "[object Object]") - return s2; - } - var k : String = null; - var str = "{\n"; - s += "\t"; - var hasp = (o.hasOwnProperty != null); - __js__("for( var k in o ) {"); - if( hasp && !o.hasOwnProperty(k) ) + var hasp = (o.hasOwnProperty != null); + var k:String = null; + __js__("for( {0} in {1} ) {", k, o); + if (hasp && !o.hasOwnProperty(k)) __js__("continue"); - if( k == "prototype" || k == "__class__" || k == "__super__" || k == "__interfaces__" || k == "__properties__" ) + if (k == "prototype" || k == "__class__" || k == "__super__" || k == "__interfaces__" || k == "__properties__") __js__("continue"); - if( str.length != 2 ) + if (str.length != 2) str += ", \n"; - str += s + k + " : "+__string_rec(o[k],s); - __js__("}"); - s = s.substring(1); - str += "\n" + s + "}"; - return str; - case "function": - return ""; - case "string": - return o; - default: - return String(o); + str += s + k + " : " + __string_rec(o[k], s); + __js__("}"); + s = s.substring(1); + str += "\n" + s + "}"; + return str; + case "function": + return ""; + case "string": + return o; + default: + return String(o); } } } - private static function __interfLoop(cc : Dynamic,cl : Dynamic) { - if( cc == null ) + @:pure private static function __interfLoop(cc:Dynamic, cl:Dynamic) { + if (cc == null) return false; - if( cc == cl ) + if (cc == cl) return true; - var intf : Dynamic = cc.__interfaces__; - if( intf != null ) - for( i in 0...intf.length ) { - var i : Dynamic = intf[i]; - if( i == cl || __interfLoop(i,cl) ) + if (js.lib.Object.prototype.hasOwnProperty.call(cc, "__interfaces__")) { + var intf:Dynamic = cc.__interfaces__; + for (i in 0...intf.length) { + var i:Dynamic = intf[i]; + if (i == cl || __interfLoop(i, cl)) return true; } - return __interfLoop(cc.__super__,cl); + } + return __interfLoop(cc.__super__, cl); } - @:ifFeature("typed_catch") private static function __instanceof(o : Dynamic,cl : Dynamic) { - if( cl == null ) + @:ifFeature("typed_catch") @:pure private static function __instanceof(o:Dynamic, cl:Dynamic) { + if (cl == null) return false; - switch( cl ) { - case Int: - return js.Lib.typeof(o) == "number" && untyped __js__("(o|0) === o"); - case Float: - return js.Lib.typeof(o) == "number"; - case Bool: - return js.Lib.typeof(o) == "boolean"; - case String: - return js.Lib.typeof(o) == "string"; - case Array: - return (untyped __js__("(o instanceof Array)")) && o.__enum__ == null; - case Dynamic: - return true; - default: - if( o != null ) { - // Check if o is an instance of a Haxe class or a native JS object - if( js.Lib.typeof(cl) == "function" ) { - if( untyped __js__("o instanceof cl") ) - return true; - if( __interfLoop(getClass(o),cl) ) - return true; - } - else if ( js.Lib.typeof(cl) == "object" && __isNativeObj(cl) ) { - if( untyped __js__("o instanceof cl") ) - return true; + switch (cl) { + case Int: + return js.Syntax.typeof(o) == "number" && js.Syntax.strictEq(o | 0, o); + case Float: + return js.Syntax.typeof(o) == "number"; + case Bool: + return js.Syntax.typeof(o) == "boolean"; + case String: + return js.Syntax.typeof(o) == "string"; + case Array: + return js.Syntax.instanceof(o, Array) #if js_enums_as_arrays && o.__enum__ == null #end; + case Dynamic: + return o != null; + default: + if (o != null) { + // Check if o is an instance of a Haxe class or a native JS object + if (js.Syntax.typeof(cl) == "function") { + if (__downcastCheck(o, cl)) + return true; + } else if (js.Syntax.typeof(cl) == "object" && __isNativeObj(cl)) { + if (js.Syntax.instanceof(o, cl)) + return true; + } + } else { + return false; } - } else { - return false; - } - // do not use isClass/isEnum here - untyped __feature__("Class.*",if( cl == Class && o.__name__ != null ) return true); - untyped __feature__("Enum.*",if( cl == Enum && o.__ename__ != null ) return true); - #if !js_enums_as_objects - return untyped o.__enum__ == cl; - #else - return (untyped $hxEnums[o.__enum__]) == cl; - #end + // do not use isClass/isEnum here + untyped __feature__("Class.*", if (cl == Class && o.__name__ != null) return true); + untyped __feature__("Enum.*", if (cl == Enum && o.__ename__ != null) return true); + #if js_enums_as_arrays + return o.__enum__ == cl; + #else + return untyped __feature__( + "has_enum", + if (o.__enum__ != null) ($hxEnums[o.__enum__]) == cl else false, + false + ); + #end } } - @:ifFeature("typed_cast") private static function __cast(o : Dynamic, t : Dynamic) { - if (__instanceof(o, t)) return o; - else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t); + static function __downcastCheck(o:Dynamic, cl:Class):Bool { + return js.Syntax.instanceof(o, cl) || (isInterface(cl) && inline __implements(o, cl)); + } + + static function __implements(o:Dynamic, iface:Class):Bool { + return __interfLoop(getClass(o), iface); + } + + @:ifFeature("typed_cast") private static function __cast(o:Dynamic, t:Dynamic) { + if (o == null || __instanceof(o, t)) + return o; + else + throw "Cannot cast " + Std.string(o) + " to " + Std.string(t); + } + + static var __toStr:js.lib.Function; + + static function __init__() { + Boot.__toStr = (cast {}).toString; } - static var __toStr = untyped ({}).toString; // get native JS [[Class]] static function __nativeClassName(o:Dynamic):String { - var name = untyped __toStr.call(o).slice(8, -1); + var name:String = __toStr.call(o).slice(8, -1); // exclude general Object and Function // also exclude Math and JSON, because instanceof cannot be called on them if (name == "Object" || name == "Function" || name == "Math" || name == "JSON") @@ -232,7 +258,6 @@ class Boot { // resolve native JS class in the global scope: static function __resolveNativeClass(name:String) { - return untyped js.Lib.global[name]; + return js.Lib.global[cast name]; } - } diff --git a/std/js/Browser.hx b/std/js/Browser.hx index 344de2453c8..0a1afcd1b84 100644 --- a/std/js/Browser.hx +++ b/std/js/Browser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package js; import js.html.Storage; @@ -27,23 +28,33 @@ import js.html.XMLHttpRequest; class Browser { /** The global window object. */ public static var window(get, never):js.html.Window; - inline static function get_window() return untyped __js__("window"); + + extern inline static function get_window() + return untyped __js__("window"); /** Shortcut to Window.document. */ public static var document(get, never):js.html.HTMLDocument; - inline static function get_document() return untyped __js__("window.document"); + + extern inline static function get_document() + return window.document; /** Shortcut to Window.location. */ public static var location(get, never):js.html.Location; - inline static function get_location() return untyped __js__("window.location"); + + extern inline static function get_location() + return window.location; /** Shortcut to Window.navigator. */ public static var navigator(get, never):js.html.Navigator; - inline static function get_navigator() return untyped __js__("window.navigator"); + + extern inline static function get_navigator() + return window.navigator; /** Shortcut to Window.console. */ - public static var console(get, never):js.html.Console; - inline static function get_console() return untyped __js__("window.console"); + public static var console(get, never):js.html.ConsoleInstance; + + extern inline static function get_console() + return window.console; /** * True if a window object exists, false otherwise. @@ -52,24 +63,25 @@ class Browser { * environment such as node.js. */ public static var supported(get, never):Bool; - inline static function get_supported() return untyped __typeof__(window) != "undefined"; + + extern inline static function get_supported() + return js.Syntax.typeof(window) != "undefined"; /** * Safely gets the browser's local storage, or returns null if localStorage is unsupported or * disabled. */ - public static function getLocalStorage() : Storage - { + public static function getLocalStorage():Storage { try { var s = window.localStorage; s.getItem(""); if (s.length == 0) { var key = "_hx_" + Math.random(); - s.setItem(key,key); + s.setItem(key, key); s.removeItem(key); } return s; - } catch( e : Dynamic ) { + } catch (e:Dynamic) { return null; } } @@ -78,18 +90,17 @@ class Browser { * Safely gets the browser's session storage, or returns null if sessionStorage is unsupported * or disabled. */ - public static function getSessionStorage() : Storage - { + public static function getSessionStorage():Storage { try { var s = window.sessionStorage; s.getItem(""); if (s.length == 0) { var key = "_hx_" + Math.random(); - s.setItem(key,key); + s.setItem(key, key); s.removeItem(key); } return s; - } catch( e : Dynamic ) { + } catch (e:Dynamic) { return null; } } @@ -98,13 +109,12 @@ class Browser { * Creates an XMLHttpRequest, with a fallback to ActiveXObject for ancient versions of Internet * Explorer. */ - public static function createXMLHttpRequest() : XMLHttpRequest - { - if( untyped __js__("typeof XMLHttpRequest") != "undefined" ) { + public static function createXMLHttpRequest():XMLHttpRequest { + if (untyped __js__("typeof XMLHttpRequest") != "undefined") { return new XMLHttpRequest(); } - if( untyped __js__("typeof ActiveXObject") != "undefined" ) { - return untyped __new__("ActiveXObject","Microsoft.XMLHTTP"); + if (untyped __js__("typeof ActiveXObject") != "undefined") { + return js.Syntax.construct("ActiveXObject", "Microsoft.XMLHTTP"); } throw "Unable to create XMLHttpRequest object."; } @@ -112,7 +122,7 @@ class Browser { /** Display an alert message box containing the given message. See also `Window.alert()`. **/ - public static function alert( v : Dynamic ) { - @:privateAccess window.alert(Boot.__string_rec(v,"")); + public static inline function alert(v:Dynamic) { + window.alert(Std.string(v)); } } diff --git a/std/js/Cookie.hx b/std/js/Cookie.hx index 0b0cc4f92e8..3520c2d8357 100644 --- a/std/js/Cookie.hx +++ b/std/js/Cookie.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,24 +19,27 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package js; +import Date; + class Cookie { /** Create or update a cookie. @param expireDelay In seconds. If null, the cookie expires at end of session. **/ - public static function set( name : String, value : String, ?expireDelay : Int, ?path : String, ?domain : String ){ - var s = name+"="+StringTools.urlEncode(value); - if( expireDelay != null ){ - var d = DateTools.delta(Date.now(),expireDelay*1000); + public static function set(name:String, value:String, ?expireDelay:Int, ?path:String, ?domain:String) { + var s = name + "=" + StringTools.urlEncode(value); + if (expireDelay != null) { + var d = DateTools.delta(Date.now(), expireDelay * 1000); s += ";expires=" + untyped d.toGMTString(); } - if( path != null ){ - s += ";path="+path; + if (path != null) { + s += ";path=" + path; } - if( domain != null ){ - s += ";domain="+domain; + if (domain != null) { + s += ";domain=" + domain; } Browser.document.cookie = s; } @@ -44,15 +47,15 @@ class Cookie { /** Returns all cookies. **/ - public static function all(){ + public static function all() { var h = new haxe.ds.StringMap(); var a = Browser.document.cookie.split(";"); - for( e in a ){ + for (e in a) { e = StringTools.ltrim(e); var t = e.split("="); - if( t.length < 2 ) + if (t.length < 2) continue; - h.set(t[0],StringTools.urlDecode(t[1])); + h.set(t[0], StringTools.urlDecode(t[1])); } return h; } @@ -60,21 +63,21 @@ class Cookie { /** Returns value of a cookie. **/ - public static function get( name : String ){ + public static function get(name:String) { return all().get(name); } /** Returns true if a cookie `name` exists. **/ - public static function exists( name : String ){ + public static function exists(name:String) { return all().exists(name); } /** Remove a cookie. **/ - public static function remove( name : String, ?path : String, ?domain : String ){ - set(name,"",-10,path,domain); + public static function remove(name:String, ?path:String, ?domain:String) { + set(name, "", -10, path, domain); } } diff --git a/std/js/Error.hx b/std/js/Error.hx index e960866cb8a..b0241a819a4 100644 --- a/std/js/Error.hx +++ b/std/js/Error.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,50 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package js; - -@:native("Error") -extern class Error -{ - var message : String; - var name : String; - var stack(default,null) : String; - - function new(?message : String) : Void; -} - -@:native("EvalError") -extern class EvalError extends Error -{ - function new(?message : String) : Void; -} -@:native("RangeError") -extern class RangeError extends Error -{ - function new(?message : String) : Void; -} - -@:native("ReferenceError") -extern class ReferenceError extends Error -{ - function new(?message : String) : Void; -} - -@:native("SyntaxError") -extern class SyntaxError extends Error -{ - function new(?message : String) : Void; -} - -@:native("TypeError") -extern class TypeError extends Error -{ - function new(?message : String) : Void; -} +package js; -@:native("URIError") -extern class URIError extends Error -{ - function new(?message : String) : Void; -} +@:deprecated typedef Error = js.lib.Error; +@:deprecated typedef EvalError = js.lib.Error.EvalError; +@:deprecated typedef RangeError = js.lib.Error.RangeError; +@:deprecated typedef ReferenceError = js.lib.Error.ReferenceError; +@:deprecated typedef SyntaxError = js.lib.Error.SyntaxError; +@:deprecated typedef TypeError = js.lib.Error.TypeError; +@:deprecated typedef URIError = js.lib.Error.URIError; diff --git a/std/js/Function.hx b/std/js/Function.hx index 77f46a53a89..ef9d035d611 100644 --- a/std/js/Function.hx +++ b/std/js/Function.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,33 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package js; - -import haxe.extern.Rest; - -@:native("Function") -extern class Function { - /** Specifies the number of arguments expected by the function. **/ - var length(default,never):Int; - - /** The name of the function. **/ - var name:String; - /** Creates a new Function object. **/ - function new(arg:String, rest:Rest); - - /** Calls a function and sets its this to the provided value, arguments can be passed as an Array object. **/ - function apply(thisArg:Dynamic, argsArray:Array):Dynamic; - - /** Calls (executes) a function and sets its this to the provided value, arguments can be passed as they are. **/ - function call(thisArg:Dynamic, args:Rest):Dynamic; - - /** - Creates a new function which, when called, has its this set to the provided value, - with a given sequence of arguments preceding any provided when the new function was called. - **/ - @:pure function bind(thisArg:Dynamic, args:Rest):Function; +package js; - /** Returns a string representing the source code of the function. **/ - @:pure function toString():String; -} +@:deprecated typedef Function = js.lib.Function; diff --git a/std/js/JsIterator.hx b/std/js/JsIterator.hx new file mode 100644 index 00000000000..c56a2410a6d --- /dev/null +++ b/std/js/JsIterator.hx @@ -0,0 +1,26 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package js; + +@:deprecated typedef JsIterator = js.lib.Iterator; +@:deprecated typedef JsIteratorStep = js.lib.Iterator.IteratorStep; diff --git a/std/js/Lib.hx b/std/js/Lib.hx index 354d3936f13..1def3cf7850 100644 --- a/std/js/Lib.hx +++ b/std/js/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package js; /** @@ -26,7 +27,6 @@ package js; for the JavaScript target. **/ class Lib { - /** Inserts a 'debugger' statement that will make a breakpoint if a debugger is available. **/ @@ -39,11 +39,11 @@ class Lib { @deprecated Use Browser.alert() instead. **/ @:deprecated("Lib.alert() is deprecated, use Browser.alert() instead") - public static function alert( v : Dynamic ) { - untyped __js__("alert")(js.Boot.__string_rec(v,"")); + public static function alert(v:Dynamic) { + untyped __js__("alert")(js.Boot.__string_rec(v, "")); } - public static inline function eval( code : String ) : Dynamic { + public static inline function eval(code:String):Dynamic { return untyped __js__("eval")(code); } @@ -54,7 +54,7 @@ class Lib { This is only supported in environments where `require` function is available, such as Node.js or RequireJS. **/ - @:extern public static inline function require( module:String ) : Dynamic { + extern public static inline function require(module:String):Dynamic { return untyped __js__("require")(module); } @@ -65,8 +65,9 @@ class Lib { In Haxe, `null` is used to represent the absence of a value. **/ - public static var undefined(get,never) : Dynamic; - static inline function get_undefined() : Dynamic { + public static var undefined(get, never):Dynamic; + + static inline function get_undefined():Dynamic { return untyped __js__("undefined"); } @@ -82,8 +83,9 @@ class Lib { Read more at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this **/ - public static var nativeThis(get,never) : Dynamic; - @:extern static inline function get_nativeThis() : Dynamic { + public static var nativeThis(get, never):Dynamic; + + extern static inline function get_nativeThis():Dynamic { return untyped __js__("this"); } @@ -93,8 +95,8 @@ class Lib { Read more at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof **/ - @:pure @:extern public static inline function typeof(o:Dynamic):String { - return untyped __typeof__(o); + extern public static inline function typeof(o:Dynamic):String { + return js.Syntax.typeof(o); } /** @@ -103,23 +105,37 @@ class Lib { Concretely, it is set as the first defined value in the list of `window`, `global`, `self`, and `this` in the top-level of the compiled output. **/ - #if (haxe_ver >= 3.3) - public - #else - // hide it since we should not add new feature in 3.2.1 - @:allow(js) private - #end - static var global(get,never) : Dynamic; - @:extern static inline function get_global() : Dynamic { + public static var global(get, never):Dynamic; + + extern static inline function get_global():Dynamic { return untyped __define_feature__("js.Lib.global", __js__("$global")); // $global is generated by the compiler } /** Re-throw last cathed exception, preserving original stack information. - Calling this only makes sense inside a catch statement. + Calling this is only possible inside a catch statement. + **/ + @:pure(false) public static function rethrow() { + // function is implemented in the compiler + } + + /** + Get original caught exception object, before unwrapping the `js.Boot.HaxeError`. + + Can be useful if we want to redirect the original error into some external API (e.g. Promise or node.js callbacks). + + Calling this is only possible inside a catch statement. + **/ + public static function getOriginalException():Dynamic { + return null; // function is implemented in the compiler + } + + /** + Generate next unique id **/ - @:extern public static inline function rethrow() { - untyped __define_feature__("js.Lib.rethrow", __rethrow__()); + @:allow(haxe.ds.ObjectMap.assignId) + static inline function getNextHaxeUID():{function nextId(counterName:String):Int;} { + return js.Syntax.code("{0}.$haxeUID++", untyped __define_feature__("$global.$haxeUID", global)); } } diff --git a/std/js/Object.hx b/std/js/Object.hx index 64b0de7d49e..7da188a7248 100644 --- a/std/js/Object.hx +++ b/std/js/Object.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,48 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package js; - -import haxe.extern.Rest; -import haxe.DynamicAccess; -@:native("Object") -extern class Object { - static function assign(target:T, sources:Rest<{}>):T; - @:pure static function create(proto:{}, ?propertiesObject:DynamicAccess):T; - static function defineProperties(obj:T, props:DynamicAccess):T; - static function defineProperty(obj:T, prop:String, descriptor:ObjectPropertyDescriptor):T; - static function freeze(obj:T):T; - @:pure static function getOwnPropertyDescriptor(obj:{}, prop:String):Null; - @:pure static function getOwnPropertyNames(obj:{}):Array; - @:pure static function getOwnPropertySymbols(obj:{}):Array; - @:pure static function getPrototypeOf(obj:{}):Null; - @:pure static function is(value1:T, value2:T):Bool; - @:pure static function isExtensible(obj:{}):Bool; - @:pure static function isFrozen(obj:{}):Bool; - @:pure static function isSealed(obj:{}):Bool; - @:pure static function keys(obj:{}):Array; - static function preventExtensions(obj:T):T; - static function seal(obj:T):T; - static function setPrototypeOf(obj:T, prototype:Null<{}>):T; - static var prototype(default,never):ObjectPrototype; - @:pure function new(?value:Any); -} - -typedef ObjectPrototype = { - var hasOwnProperty(default,never):Function; - var isPrototypeOf(default,never):Function; - var propertyIsEnumerable(default,never):Function; - var toLocaleString(default,never):Function; - var toString(default,never):Function; - var valueOf(default,never):Function; -} +package js; -typedef ObjectPropertyDescriptor = { - @:optional var configurable:Bool; - @:optional var enumerable:Bool; - @:optional var value:Any; - @:optional var writable:Bool; - @:optional var get:Void->Any; - @:optional var set:Any->Void; -} +@:deprecated typedef Object = js.lib.Object; +@:deprecated typedef ObjectPrototype = js.lib.Object.ObjectPrototype; +@:deprecated typedef ObjectPropertyDescriptor = js.lib.Object.ObjectPropertyDescriptor; diff --git a/std/js/Promise.hx b/std/js/Promise.hx index ff8272973ed..5de240ba9de 100644 --- a/std/js/Promise.hx +++ b/std/js/Promise.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,32 +22,7 @@ package js; -import haxe.extern.EitherType; - -@:native("Promise") -extern class Promise -{ - @:overload(function(promise : Promise) : Promise {}) - @:overload(function(thenable : Thenable) : Promise {}) - static function resolve( ?value : T ) : Promise; - - static function reject( ?value : Dynamic ) : Promise; - - static function all( iterable : Array ) : Promise>; - - static function race( iterable : Array ) : Promise; - - /** @throws DOMError */ - function new( init : (T -> Void) -> (Dynamic -> Void) -> Void ) : Void; - - function then( fulfillCallback : Null>, ?rejectCallback : EitherType Void, PromiseCallback> ) : Promise; - - @:native("catch") - function catchError( rejectCallback : EitherType Void, PromiseCallback> ) : Promise; -} - -typedef PromiseCallback = EitherType TOut, T -> Promise>; - -typedef Thenable = { - function then(resolve:T->Void, ?reject:Dynamic->Void):Void; -} +@:deprecated typedef Promise = js.lib.Promise; +@:deprecated typedef PromiseHandler = js.lib.Promise.PromiseHandler; +@:deprecated typedef Thenable = js.lib.Promise.Thenable; +@:deprecated typedef ThenableStruct = js.lib.Promise.ThenableStruct; diff --git a/std/js/RegExp.hx b/std/js/RegExp.hx index 34275a544d9..80df24e1f59 100644 --- a/std/js/RegExp.hx +++ b/std/js/RegExp.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,28 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package js; -/** - Native JavaScript regular expressions. +package js; - For cross-platform regular expressions, use Haxe `EReg` class or - [regexp literals](https://haxe.org/manual/std-regex.html). -**/ -@:native("RegExp") -extern class RegExp { - var global(default,null):Bool; - var ignoreCase(default,null):Bool; - var multiline(default,null):Bool; - var source(default,null):String; - var lastIndex:Int; - function new(pattern:String, ?flags:String); - function exec(str:String):Null; - function test(str:String):Bool; - function toString():String; -} - -extern class RegExpMatch extends Array { - var index:Int; - var input:String; -} +@:deprecated typedef RegExp = js.lib.RegExp; +@:deprecated typedef RegExpMatch = js.lib.RegExp.RegExpMatch; diff --git a/std/js/Selection.hx b/std/js/Selection.hx index 83c03b0944a..6731e3d1fa1 100644 --- a/std/js/Selection.hx +++ b/std/js/Selection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,71 +19,73 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package js; import js.html.TextAreaElement; class Selection { + var doc:Dynamic; - var doc : Dynamic; - - public function new( doc : TextAreaElement ) { + public function new(doc:TextAreaElement) { this.doc = doc; } public function get() { // Mozilla - if( doc.selectionStart != null ) - return doc.value.substring(doc.selectionStart,doc.selectionEnd); + if (doc.selectionStart != null) + return doc.value.substring(doc.selectionStart, doc.selectionEnd); // IE var range = untyped js.Lib.document.selection.createRange(); - if( range.parentElement() != doc ) + if (range.parentElement() != doc) return ""; return range.text; } - public function select( start : Int, end : Int ) { + public function select(start:Int, end:Int) { doc.focus(); // Mozilla - if( doc.selectionStart != null ) { + if (doc.selectionStart != null) { doc.selectionStart = start; doc.selectionEnd = end; return; } // FIX : IE count \r\n as one single char for selection // operations, we must then deal with it - var value : String = doc.value; + var value:String = doc.value; var p = 0, delta = 0; - while( true ) { + while (true) { var i = value.indexOf("\r\n", p); - if( i < 0 || i > start ) break; + if (i < 0 || i > start) + break; delta++; p = i + 2; } start -= delta; - while( true ) { + while (true) { var i = value.indexOf("\r\n", p); - if( i < 0 || i > end ) break; + if (i < 0 || i > end) + break; delta++; p = i + 2; } end -= delta; // IE var r = doc.createTextRange(); - r.moveEnd('textedit',-1); - r.moveStart('character',start); - r.moveEnd('character',end - start); - r.select(); + r.moveEnd('textedit', -1); + r.moveStart('character', start); + r.moveEnd('character', end - start); + r.select(); } - public function insert( left : String, text : String, right : String ) { + public function insert(left:String, text:String, right:String) { doc.focus(); // Mozilla - if( doc.selectionStart != null ) { + if (doc.selectionStart != null) { var top = doc.scrollTop; var start = doc.selectionStart; var end = doc.selectionEnd; - doc.value = doc.value.substr(0,start) + left + text + right + doc.value.substr(end); + doc.value = doc.value.substr(0, start) + left + text + right + doc.value.substr(end); doc.selectionStart = start + left.length; doc.selectionEnd = start + left.length + text.length; doc.scrollTop = top; @@ -92,9 +94,8 @@ class Selection { // IE var range = untyped js.Lib.document.selection.createRange(); range.text = left + text + right; - range.moveStart('character',-text.length-right.length); - range.moveEnd('character',-right.length); + range.moveStart('character', -text.length - right.length); + range.moveEnd('character', -right.length); range.select(); } - } diff --git a/std/js/Set.hx b/std/js/Set.hx new file mode 100644 index 00000000000..42e1d3e6fc0 --- /dev/null +++ b/std/js/Set.hx @@ -0,0 +1,25 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package js; + +@:deprecated typedef Set = js.lib.Set; diff --git a/std/js/Symbol.hx b/std/js/Symbol.hx index dbc9772b6ee..4f811ac36bf 100644 --- a/std/js/Symbol.hx +++ b/std/js/Symbol.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,43 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package js; - -@:native("Symbol") -extern class Symbol { - /** - To create a new primitive symbol, you write `new Symbol()` with an optional string as its `description`. - - NOTE: Unlike plain JavaScript, in Haxe `new Symbol()` syntax is used, however `Symbol(...)` expression - will be generated as required by JavaScript specification. - **/ - @:pure @:selfCall function new(?description:String); - - /** - Searches for existing symbols with the given key and returns it if found. - Otherwise a new symbol gets created in the global symbol registry with this key. - **/ - @:native("for") static function for_(key:String):Symbol; - /** - Retrieves a shared symbol key from the global symbol registry for the given symbol. - **/ - @:pure static function keyFor(sym:Symbol):Null; - - /** - Returns a string containing the description of the Symbol. - **/ - @:pure function toString():String; - - /** - A method returning the default iterator for an object. - **/ - static var iterator(default,null):Symbol; - - /** - Retrieve symbol from a given `object`. +package js; - NOTE: This is a Haxe-specific method that generates `object[symbol]` expression. - **/ - inline function ofObject(object:{}):Null return (cast object)[cast this]; -} +@:deprecated typedef Symbol = js.lib.Symbol; diff --git a/std/js/Syntax.hx b/std/js/Syntax.hx new file mode 100644 index 00000000000..83f3fd347ab --- /dev/null +++ b/std/js/Syntax.hx @@ -0,0 +1,86 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package js; + +import haxe.extern.Rest; + +/** + Generate JavaScript syntax not directly supported by Haxe. + Use only at low-level when specific target-specific code-generation is required. +**/ +@:noClosure +extern class Syntax { + /** + Inject `code` directly into generated source. + + `code` must be a string constant. + + Additional `args` are supported to provide code interpolation, for example: + ```haxe + Syntax.code("console.log({0}, {1})", "hi", 42); + ``` + will generate + ```haxe + console.log("hi", 42); + ``` + **/ + static function code(code:String, args:Rest):Dynamic; + + /** + Generate `new cl(...args)` expression. + **/ + @:overload(function(cl:String, args:Rest):Dynamic {}) + static function construct(cl:Class, args:Rest):T; + + /** + Generate `v instanceof cl` expression. + **/ + @:pure static function instanceof(v:Dynamic, cl:Class):Bool; + + /** + Generate `typeof o` expression. + **/ + @:pure static function typeof(o:Dynamic):String; + + /** + Genearte `a === b` expression. + **/ + @:pure static function strictEq(a:Dynamic, b:Dynamic):Bool; + + /** + Genearte `a !== b` expression. + **/ + @:pure static function strictNeq(a:Dynamic, b:Dynamic):Bool; + + /** + Generate `delete o[f]` expression. + **/ + @:overload(function(o:Dynamic, f:Int):Bool {}) + static function delete(o:Dynamic, f:String):Bool; + + /** + Generate `o.f` expression, if `f` is a constant string, + or `o[f]` if it's any other expression. + **/ + static function field(o:Dynamic, f:String):Dynamic; +} diff --git a/std/js/_std/Array.hx b/std/js/_std/Array.hx index d770223b97e..a200d4508ec 100644 --- a/std/js/_std/Array.hx +++ b/std/js/_std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,60 +21,60 @@ */ @:coreApi extern class Array { + var length(default, null):Int; - var length(default,null) : Int; + function new():Void; + function concat(a:Array):Array; + function join(sep:String):String; + function pop():Null; + function push(x:T):Int; + function reverse():Void; + function shift():Null; + function slice(pos:Int, ?end:Int):Array; + function sort(f:T->T->Int):Void; + function splice(pos:Int, len:Int):Array; + function toString():String; + function unshift(x:T):Void; - function new() : Void; - function concat( a : Array ) : Array; - function join( sep : String ) : String; - function pop() : Null; - function push(x : T) : Int; - function reverse() : Void; - function shift() : Null; - function slice( pos : Int, ?end : Int ) : Array; - function sort( f : T -> T -> Int ) : Void; - function splice( pos : Int, len : Int ) : Array; - function toString() : String; - function unshift( x : T ) : Void; - - inline function insert( pos : Int, x : T ) : Void { - (cast this).splice(pos,0,x); + inline function insert(pos:Int, x:T):Void { + (cast this).splice(pos, 0, x); } - inline function remove( x : T ) : Bool { - return @:privateAccess HxOverrides.remove(this,x); + inline function remove(x:T):Bool { + return @:privateAccess HxOverrides.remove(this, x); } -#if (js_es >= 5) - @:pure function indexOf( x : T, ?fromIndex:Int ) : Int; - @:pure function lastIndexOf( x : T, ?fromIndex:Int ) : Int; - -#else - inline function indexOf( x : T, ?fromIndex:Int ) : Int { - return @:privateAccess HxOverrides.indexOf(this,x,(fromIndex!=null)?fromIndex:0); + #if (js_es >= 5) + @:pure function indexOf(x:T, ?fromIndex:Int):Int; + @:pure function lastIndexOf(x:T, ?fromIndex:Int):Int; + #else + inline function indexOf(x:T, ?fromIndex:Int):Int { + return @:privateAccess HxOverrides.indexOf(this, x, (fromIndex != null) ? fromIndex : 0); } - inline function lastIndexOf( x : T, ?fromIndex:Int ) : Int { - return @:privateAccess HxOverrides.lastIndexOf(this,x,(fromIndex!=null)?fromIndex:length-1); + inline function lastIndexOf(x:T, ?fromIndex:Int):Int { + return @:privateAccess HxOverrides.lastIndexOf(this, x, (fromIndex != null) ? fromIndex : length - 1); } -#end + #end @:pure - inline function copy() : Array { + inline function copy():Array { return (cast this).slice(); } @:runtime inline function map(f:T->S):Array { - var a:Array = untyped __new__(Array, length); - for (i in 0...length) a[i] = f(this[i]); - return a; + return [for (v in this) f(v)]; } + @:runtime inline function filter(f:T->Bool):Array { return [for (v in this) if (f(v)) v]; } - @:runtime inline function iterator() : Iterator { + @:runtime inline function iterator():Iterator { return @:privateAccess HxOverrides.iter(this); } + inline function resize(len:Int):Void { + this.length = len; + } } diff --git a/std/js/_std/Date.hx b/std/js/_std/Date.hx index 5a7c7ff7232..699da1deb33 100644 --- a/std/js/_std/Date.hx +++ b/std/js/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,30 +20,38 @@ * DEALINGS IN THE SOFTWARE. */ @:coreApi extern class Date { + @:pure function new(year:Int, month:Int, day:Int, hour:Int, min:Int, sec:Int):Void; + @:pure function getTime():Float; + @:pure function getHours():Int; + @:pure function getMinutes():Int; + @:pure function getSeconds():Int; + @:pure function getFullYear():Int; + @:pure function getMonth():Int; + @:pure function getDate():Int; + @:pure function getDay():Int; - @:pure function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void; - @:pure function getTime() : Float; - @:pure function getHours() : Int; - @:pure function getMinutes() : Int; - @:pure function getSeconds() : Int; - @:pure function getFullYear() : Int; - @:pure function getMonth() : Int; - @:pure function getDate() : Int; - @:pure function getDay() : Int; + @:pure function getUTCHours():Int; + @:pure function getUTCMinutes():Int; + @:pure function getUTCSeconds():Int; + @:pure function getUTCFullYear():Int; + @:pure function getUTCMonth():Int; + @:pure function getUTCDate():Int; + @:pure function getUTCDay():Int; + @:pure function getTimezoneOffset():Int; - @:pure inline function toString() : String { - return untyped HxOverrides.dateStr(this); + @:pure inline function toString():String { + return @:privateAccess HxOverrides.dateStr(this); } - @:pure static inline function now() : Date { - return untyped __new__(Date); + @:pure static inline function now():Date { + return js.Syntax.construct(Date); } - @:pure static inline function fromTime( t : Float ) : Date { - return untyped __new__(Date, t); + @:pure static inline function fromTime(t:Float):Date { + return js.Syntax.construct(Date, t); } - @:pure static inline function fromString( s : String ) : Date { - return untyped HxOverrides.strDate(s); + @:pure static inline function fromString(s:String):Date { + return @:privateAccess HxOverrides.strDate(s); } } diff --git a/std/js/_std/EReg.hx b/std/js/_std/EReg.hx index 421df55f5c2..ae91f2ff697 100644 --- a/std/js/_std/EReg.hx +++ b/std/js/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,41 +20,44 @@ * DEALINGS IN THE SOFTWARE. */ @:coreApi class EReg { + var r:HaxeRegExp; - var r : HaxeRegExp; - - public inline function new( r : String, opt : String ) : Void { + public inline function new(r:String, opt:String):Void { this.r = new HaxeRegExp(r, opt.split("u").join("")); // 'u' (utf8) depends on page encoding } - public function match( s : String ) : Bool { - if( r.global ) r.lastIndex = 0; + public function match(s:String):Bool { + if (r.global) + r.lastIndex = 0; r.m = r.exec(s); r.s = s; return (r.m != null); } - public function matched( n : Int ) : String { - return if( r.m != null && n >= 0 && n < r.m.length ) r.m[n] else throw "EReg::matched"; + public function matched(n:Int):String { + return if (r.m != null && n >= 0 && n < r.m.length) r.m[n] else throw "EReg::matched"; } - public function matchedLeft() : String { - if( r.m == null ) throw "No string matched"; - return r.s.substr(0,r.m.index); + public function matchedLeft():String { + if (r.m == null) + throw "No string matched"; + return r.s.substr(0, r.m.index); } - public function matchedRight() : String { - if( r.m == null ) throw "No string matched"; - var sz = r.m.index+r.m[0].length; - return r.s.substr(sz,r.s.length-sz); + public function matchedRight():String { + if (r.m == null) + throw "No string matched"; + var sz = r.m.index + r.m[0].length; + return r.s.substr(sz, r.s.length - sz); } - public function matchedPos() : { pos : Int, len : Int } { - if( r.m == null ) throw "No string matched"; - return { pos : r.m.index, len : r.m[0].length }; + public function matchedPos():{pos:Int, len:Int} { + if (r.m == null) + throw "No string matched"; + return {pos: r.m.index, len: r.m[0].length}; } - public function matchSub( s : String, pos : Int, len : Int = -1):Bool { + public function matchSub(s:String, pos:Int, len:Int = -1):Bool { return if (r.global) { r.lastIndex = pos; r.m = r.exec(len < 0 ? s : s.substr(0, pos + len)); @@ -65,7 +68,7 @@ b; } else { // TODO: check some ^/$ related corner cases - var b = match( len < 0 ? s.substr(pos) : s.substr(pos,len) ); + var b = match(len < 0 ? s.substr(pos) : s.substr(pos, len)); if (b) { r.s = s; r.m.index += pos; @@ -74,17 +77,17 @@ } } - public function split( s : String ) : Array { + public function split(s:String):Array { // we can't use directly s.split because it's ignoring the 'g' flag var d = "#__delim__#"; - return untyped s.replace(r,d).split(d); + return replace(s, d).split(d); } - public inline function replace( s : String, by : String ) : String { - return untyped s.replace(r,by); + public inline function replace(s:String, by:String):String { + return (cast s).replace(r, by); } - public function map( s : String, f : EReg -> String ) : String { + public function map(s:String, f:EReg->String):String { var offset = 0; var buf = new StringBuf(); do { @@ -100,8 +103,7 @@ if (p.len == 0) { buf.add(s.substr(p.pos, 1)); offset = p.pos + 1; - } - else + } else offset = p.pos + p.len; } while (r.global); if (!r.global && offset > 0 && offset < s.length) @@ -109,14 +111,15 @@ return buf.toString(); } - public static inline function escape( s : String ) : String { + public static inline function escape(s:String):String { return (cast s).replace(escapeRe, "\\$&"); } - static var escapeRe = new js.RegExp("[.*+?^${}()|[\\]\\\\]", "g"); + + static var escapeRe = new js.lib.RegExp("[.*+?^${}()|[\\]\\\\]", "g"); } @:native("RegExp") -private extern class HaxeRegExp extends js.RegExp { - var m:js.RegExp.RegExpMatch; +private extern class HaxeRegExp extends js.lib.RegExp { + var m:js.lib.RegExp.RegExpMatch; var s:String; } diff --git a/std/js/_std/HxOverrides.hx b/std/js/_std/HxOverrides.hx index 2516bc89ac6..348cd4174ac 100644 --- a/std/js/_std/HxOverrides.hx +++ b/std/js/_std/HxOverrides.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,54 +21,49 @@ */ @:noDoc class HxOverrides { - - static function dateStr( date :Date ) : String { + static function dateStr(date:Date):String { var m = date.getMonth() + 1; var d = date.getDate(); var h = date.getHours(); var mi = date.getMinutes(); var s = date.getSeconds(); - return date.getFullYear() - +"-"+(if( m < 10 ) "0"+m else ""+m) - +"-"+(if( d < 10 ) "0"+d else ""+d) - +" "+(if( h < 10 ) "0"+h else ""+h) - +":"+(if( mi < 10 ) "0"+mi else ""+mi) - +":"+(if( s < 10 ) "0"+s else ""+s); + return date.getFullYear() + "-" + (if (m < 10) "0" + m else "" + m) + "-" + (if (d < 10) "0" + d else "" + d) + " " + + (if (h < 10) "0" + h else "" + h) + ":" + (if (mi < 10) "0" + mi else "" + mi) + ":" + (if (s < 10) "0" + s else "" + s); } - static function strDate( s : String ) : Date { - switch( s.length ) { - case 8: // hh:mm:ss - var k = s.split(":"); - var d : Date = untyped __new__(Date); - untyped d["setTime"](0); - untyped d["setUTCHours"](k[0]); - untyped d["setUTCMinutes"](k[1]); - untyped d["setUTCSeconds"](k[2]); - return d; - case 10: // YYYY-MM-DD - var k = s.split("-"); - return new Date(cast k[0],cast untyped k[1] - 1,cast k[2],0,0,0); - case 19: // YYYY-MM-DD hh:mm:ss - var k = s.split(" "); - var y = k[0].split("-"); - var t = k[1].split(":"); - return new Date(cast y[0],cast untyped y[1] - 1,cast y[2],cast t[0],cast t[1],cast t[2]); - default: - throw "Invalid date format : " + s; + static function strDate(s:String):Date { + switch (s.length) { + case 8: // hh:mm:ss + var k = s.split(":"); + var d = js.Syntax.construct(Date); + (cast d)[cast "setTime"](0); + (cast d)[cast "setUTCHours"](k[0]); + (cast d)[cast "setUTCMinutes"](k[1]); + (cast d)[cast "setUTCSeconds"](k[2]); + return d; + case 10: // YYYY-MM-DD + var k = s.split("-"); + return new Date(cast k[0], (cast k[1]) - 1, cast k[2], 0, 0, 0); + case 19: // YYYY-MM-DD hh:mm:ss + var k = s.split(" "); + var y = k[0].split("-"); + var t = k[1].split(":"); + return new Date(cast y[0], (cast y[1]) - 1, cast y[2], cast t[0], cast t[1], cast t[2]); + default: + throw "Invalid date format : " + s; } } @:pure - static function cca( s : String, index : Int ) : Null { + static function cca(s:String, index:Int):Null { var x = (cast s).charCodeAt(index); - if( x != x ) // fast isNaN + if (x != x) // fast isNaN return js.Lib.undefined; // isNaN will still return true return x; } @:pure - static function substr( s : String, pos : Int, ?len : Int ) : String { + static function substr(s:String, pos:Int, ?len:Int):String { if (len == null) { len = s.length; } else if (len < 0) { @@ -90,15 +85,15 @@ class HxOverrides { } @:pure - static function indexOf( a : Array, obj : T, i : Int) { + static function indexOf(a:Array, obj:T, i:Int) { var len = a.length; if (i < 0) { i += len; - if (i < 0) i = 0; + if (i < 0) + i = 0; } - while (i < len) - { - if (untyped __js__("a[i] === obj")) + while (i < len) { + if (js.Syntax.strictEq(a[i], obj)) return i; i++; } @@ -106,47 +101,50 @@ class HxOverrides { } @:pure - static function lastIndexOf( a : Array, obj : T, i : Int) { + static function lastIndexOf(a:Array, obj:T, i:Int) { var len = a.length; if (i >= len) i = len - 1; else if (i < 0) i += len; - while (i >= 0) - { - if (untyped __js__("a[i] === obj")) + while (i >= 0) { + if (js.Syntax.strictEq(a[i], obj)) return i; i--; } return -1; } - static function remove( a : Array, obj : T ) { + static function remove(a:Array, obj:T) { var i = a.indexOf(obj); - if( i == -1 ) return false; - a.splice(i,1); + if (i == -1) + return false; + a.splice(i, 1); return true; } @:pure - static function iter( a : Array ) : Iterator untyped { - return { - cur : 0, - arr : a, - hasNext : function() { - return __this__.cur < __this__.arr.length; - }, - next : function() { - return __this__.arr[__this__.cur++]; - } - }; - } - - static function __init__() untyped { -#if (js_es < 5) - __feature__('HxOverrides.indexOf', if( Array.prototype.indexOf ) __js__("HxOverrides").indexOf = function(a,o,i) return Array.prototype.indexOf.call(a, o, i)); - __feature__('HxOverrides.lastIndexOf', if( Array.prototype.lastIndexOf ) __js__("HxOverrides").lastIndexOf = function(a,o,i) return Array.prototype.lastIndexOf.call(a, o, i)); -#end - } + static function iter(a:Array):Iterator + untyped { + return { + cur: 0, + arr: a, + hasNext: function() { + return __this__.cur < __this__.arr.length; + }, + next: function() { + return __this__.arr[__this__.cur++]; + } + }; + } + static function __init__() + untyped { + #if (js_es < 5) + __feature__('HxOverrides.indexOf', + if (Array.prototype.indexOf) __js__("HxOverrides").indexOf = function(a, o, i) return Array.prototype.indexOf.call(a, o, i)); + __feature__('HxOverrides.lastIndexOf', + if (Array.prototype.lastIndexOf) __js__("HxOverrides").lastIndexOf = function(a, o, i) return Array.prototype.lastIndexOf.call(a, o, i)); + #end + } } diff --git a/std/js/_std/Math.hx b/std/js/_std/Math.hx index 659344fe9ae..9e41b88ce4f 100644 --- a/std/js/_std/Math.hx +++ b/std/js/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,27 +19,24 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package; - // Can't enable @:coreApi because some fields are now inline getters // @:coreApi @:keepInit -extern class Math -{ - static var PI(default,null) : Float; +extern class Math { + static var PI(default, null):Float; - static var NEGATIVE_INFINITY(get, null) : Float; - @:pure private static inline function get_NEGATIVE_INFINITY () : Float { + static var NEGATIVE_INFINITY(get, null):Float; + @:pure private static inline function get_NEGATIVE_INFINITY():Float { return -(untyped __js__("Infinity")); } - static var POSITIVE_INFINITY(get,null) : Float; - @:pure private static inline function get_POSITIVE_INFINITY () : Float { + static var POSITIVE_INFINITY(get, null):Float; + @:pure private static inline function get_POSITIVE_INFINITY():Float { return (untyped __js__("Infinity")); } - static var NaN(get, null) : Float; - @:pure private static inline function get_NaN () : Float { + static var NaN(get, null):Float; + @:pure private static inline function get_NaN():Float { return (untyped __js__("NaN")); } @@ -56,33 +53,33 @@ extern class Math @:pure static function max(a:Float, b:Float):Float; @:pure static function min(a:Float, b:Float):Float; @:pure static function pow(v:Float, exp:Float):Float; - static function random() : Float; + static function random():Float; @:pure static function round(v:Float):Int; @:pure static function sin(v:Float):Float; @:pure static function sqrt(v:Float):Float; @:pure static function tan(v:Float):Float; - @:pure static inline function ffloor( v : Float ) : Float { + @:pure static inline function ffloor(v:Float):Float { return floor(v); } - @:pure static inline function fceil( v : Float ) : Float { + @:pure static inline function fceil(v:Float):Float { return ceil(v); } - @:pure static inline function fround( v : Float ) : Float { + @:pure static inline function fround(v:Float):Float { return round(v); } - @:pure static inline function isFinite( f : Float ) : Bool { + @:pure static inline function isFinite(f:Float):Bool { return (untyped __js__("isFinite"))(f); } - @:pure static inline function isNaN( f : Float ) : Bool { + @:pure static inline function isNaN(f:Float):Bool { return (untyped __js__("isNaN"))(f); } - static function __init__() : Void { + static function __init__():Void { untyped __feature__("Type.resolveClass", $hxClasses["Math"] = Math); } } diff --git a/std/js/_std/Reflect.hx b/std/js/_std/Reflect.hx index 1c800761b16..69dda1e4a36 100644 --- a/std/js/_std/Reflect.hx +++ b/std/js/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,93 +20,107 @@ * DEALINGS IN THE SOFTWARE. */ @:coreApi class Reflect { - @:pure - public inline static function hasField( o : Dynamic, field : String ) : Bool { - return js.Object.prototype.hasOwnProperty.call(o, field); + public inline static function hasField(o:Dynamic, field:String):Bool { + return js.lib.Object.prototype.hasOwnProperty.call(o, field); } - public static function field( o : Dynamic, field : String ) : Dynamic { - try return untyped o[field] catch( e : Dynamic ) return null; + @:pure + public static function field(o:Dynamic, field:String):Dynamic { + try + return o[cast field] + catch (e:Dynamic) + return null; } - public inline static function setField( o : Dynamic, field : String, value : Dynamic ) : Void untyped { - o[field] = value; + public inline static function setField(o:Dynamic, field:String, value:Dynamic):Void { + o[cast field] = value; } - public static function getProperty( o : Dynamic, field : String ) : Dynamic untyped { - var tmp; - return if( o == null ) __define_feature__("Reflect.getProperty",null) else if( o.__properties__ && (tmp=o.__properties__["get_"+field]) ) o[tmp]() else o[field]; - } + public static function getProperty(o:Dynamic, field:String):Dynamic + untyped { + var tmp; + return if (o == null) __define_feature__("Reflect.getProperty", + null) else if (o.__properties__ && (tmp = o.__properties__["get_" + field])) o[tmp]() else o[field]; + } - public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void untyped { - var tmp; - if( o.__properties__ && (tmp=o.__properties__["set_"+field]) ) o[tmp](value) else o[field] = __define_feature__("Reflect.setProperty",value); - } + public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void + untyped { + var tmp; + if (o.__properties__ && (tmp = o.__properties__["set_" + field])) + o[tmp](value) + else + o[field] = __define_feature__("Reflect.setProperty", value); + } - public inline static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic untyped { - return func.apply(o,args); + public inline static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array):Dynamic { + return (cast func : js.lib.Function).apply(o, args); } - public static function fields( o : Dynamic ) : Array { + public static function fields(o:Dynamic):Array { var a = []; - if (o != null) untyped { - var hasOwnProperty = js.Object.prototype.hasOwnProperty; - __js__("for( var f in o ) {"); - if( f != "__id__" && f != "hx__closures__" && hasOwnProperty.call(o, f) ) a.push(f); - __js__("}"); - } + if (o != null) + untyped { + var hasOwnProperty = js.lib.Object.prototype.hasOwnProperty; + __js__("for( var f in o ) {"); + if (f != "__id__" && f != "hx__closures__" && hasOwnProperty.call(o, f)) + a.push(f); + __js__("}"); + } return a; } @:access(js.Boot) - public static function isFunction( f : Dynamic ) : Bool { - return js.Lib.typeof(f) == "function" && !(js.Boot.isClass(f) || js.Boot.isEnum(f)); + public static function isFunction(f:Dynamic):Bool { + return js.Syntax.typeof(f) == "function" && !(js.Boot.isClass(f) || js.Boot.isEnum(f)); } - public static function compare( a : T, b : T ) : Int { - return ( a == b ) ? 0 : (((cast a) > (cast b)) ? 1 : -1); + public static function compare(a:T, b:T):Int { + return (a == b) ? 0 : (((cast a) > (cast b)) ? 1 : -1); } - public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool { - if( f1 == f2 ) + public static function compareMethods(f1:Dynamic, f2:Dynamic):Bool { + if (f1 == f2) return true; - if( !isFunction(f1) || !isFunction(f2) ) + if (!isFunction(f1) || !isFunction(f2)) return false; return f1.scope == f2.scope && f1.method == f2.method && f1.method != null; } @:access(js.Boot) - public static function isObject( v : Dynamic ) : Bool { - if( v == null ) + public static function isObject(v:Dynamic):Bool { + if (v == null) return false; - var t = js.Lib.typeof(v); - return (t == "string" || (t == "object" && v.__enum__ == null)) || (t == "function" && (js.Boot.isClass(v) || js.Boot.isEnum(v)) != null); + var t = js.Syntax.typeof(v); + return (t == "string" || (t == "object" && v.__enum__ == null)) + || (t == "function" && (js.Boot.isClass(v) || js.Boot.isEnum(v)) != null); } - public static function isEnumValue( v : Dynamic ) : Bool { + public static function isEnumValue(v:Dynamic):Bool { return v != null && v.__enum__ != null; } - public static function deleteField( o : Dynamic, field : String ) : Bool untyped { - if( !hasField(o,field) ) return false; - __js__("delete")(o[field]); + public static function deleteField(o:Dynamic, field:String):Bool { + if (!hasField(o, field)) + return false; + js.Syntax.delete(o, field); return true; } - public static function copy( o : T ) : T { - var o2 : Dynamic = {}; - for( f in Reflect.fields(o) ) - Reflect.setField(o2,f,Reflect.field(o,f)); + public static function copy(o:Null):Null { + if (o == null) + return null; + var o2:Dynamic = {}; + for (f in Reflect.fields(o)) + Reflect.setField(o2, f, Reflect.field(o, f)); return o2; } - @:overload(function( f : Array -> Void ) : Dynamic {}) - public static function makeVarArgs( f : Array -> Dynamic ) : Dynamic { + @:overload(function(f:Array->Void):Dynamic {}) + public static function makeVarArgs(f:Array->Dynamic):Dynamic { return function() { var a = untyped Array.prototype.slice.call(__js__("arguments")); return f(a); }; } - } diff --git a/std/js/_std/Std.hx b/std/js/_std/Std.hx index fb8c25016a5..c0d2b4ca000 100644 --- a/std/js/_std/Std.hx +++ b/std/js/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,85 +19,82 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + import js.Boot; @:keepInit @:coreApi class Std { + public static inline function is(v:Dynamic, t:Dynamic):Bool { + return @:privateAccess js.Boot.__instanceof(v, t); + } - public static inline function is( v : Dynamic, t : Dynamic ) : Bool { - return untyped js.Boot.__instanceof(v,t); + public static inline function downcast(value:T, c:Class):S@:privateAccess { + return if (js.Boot.__downcastCheck(value, c)) cast value else null; } - public static inline function instance( value : T, c : Class ) : S { - return untyped __instanceof__(value, c) ? cast value : null; + @:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.') + public static inline function instance(value:T, c:Class):S { + return downcast(value, c); } @:pure - public static function string( s : Dynamic ) : String { - return untyped js.Boot.__string_rec(s,""); + public static function string(s:Dynamic):String { + return @:privateAccess js.Boot.__string_rec(s, ""); } - public static inline function int( x : Float ) : Int { + public static inline function int(x:Float):Int { return (cast x) | 0; } @:pure - public static function parseInt( x : String ) : Null { - var v = untyped __js__("parseInt")(x, 10); - // parse again if hexadecimal - if( v == 0 && (x.charCodeAt(1) == 'x'.code || x.charCodeAt(1) == 'X'.code) ) - v = untyped __js__("parseInt")(x); - if( untyped __js__("isNaN")(v) ) + public static function parseInt(x:String):Null { + var v = untyped __js__('parseInt({0}, {0} && {0}[0]=="0" && ({0}[1]=="x" || {0}[1]=="X") ? 16 : 10)', x); + if (untyped __js__("isNaN")(v)) return null; return cast v; } - public static inline function parseFloat( x : String ) : Float { + public static inline function parseFloat(x:String):Float { return untyped __js__("parseFloat")(x); } - public static function random( x : Int ) : Int { - return x <= 0 ? 0 : Math.floor(Math.random()*x); + public static function random(x:Int):Int { + return x <= 0 ? 0 : Math.floor(Math.random() * x); } - static function __init__() : Void untyped { - __feature__("js.Boot.getClass",String.prototype.__class__ = __feature__("Type.resolveClass",$hxClasses["String"] = String,String)); - __feature__("js.Boot.isClass",String.__name__ = __feature__("Type.getClassName",["String"],true)); - __feature__("Type.resolveClass",$hxClasses["Array"] = Array); - __feature__("js.Boot.isClass",Array.__name__ = __feature__("Type.getClassName",["Array"],true)); - __feature__("Date.*", { - __feature__("js.Boot.getClass",__js__('Date').prototype.__class__ = __feature__("Type.resolveClass",$hxClasses["Date"] = __js__('Date'),__js__('Date'))); - __feature__("js.Boot.isClass",__js__('Date').__name__ = ["Date"]); - }); - __feature__("Int.*",__js__('var Int = { };')); - __feature__("Dynamic.*",__js__('var Dynamic = { };')); - __feature__("Float.*",__js__('var Float = Number')); - __feature__("Bool.*",__js__('var Bool = Boolean')); - __feature__("Class.*",__js__('var Class = { };')); - __feature__("Enum.*",__js__('var Enum = { };')); - -#if (js_es < 5) - __feature__("Array.map", - if( Array.prototype.map == null ) - Array.prototype.map = function(f) { - var a = []; - for( i in 0...__this__.length ) - a[i] = f(__this__[i]); - return a; + static function __init__():Void + untyped { + __feature__("js.Boot.getClass", String.prototype.__class__ = __feature__("Type.resolveClass", $hxClasses["String"] = String, String)); + __feature__("js.Boot.isClass", String.__name__ = __feature__("Type.getClassName", "String", true)); + __feature__("Type.resolveClass", $hxClasses["Array"] = Array); + __feature__("js.Boot.isClass", Array.__name__ = __feature__("Type.getClassName", "Array", true)); + __feature__("Date.*", { + __feature__("js.Boot.getClass", + __js__('Date').prototype.__class__ = __feature__("Type.resolveClass", $hxClasses["Date"] = __js__('Date'), __js__('Date'))); + __feature__("js.Boot.isClass", __js__('Date').__name__ = "Date"); + }); + __feature__("Int.*", __js__('var Int = { };')); + __feature__("Dynamic.*", __js__('var Dynamic = { };')); + __feature__("Float.*", __js__('var Float = Number')); + __feature__("Bool.*", __js__('var Bool = Boolean')); + __feature__("Class.*", __js__('var Class = { };')); + __feature__("Enum.*", __js__('var Enum = { };')); + #if (js_es < 5) + __feature__("Array.map", if (Array.prototype.map == null) Array.prototype.map = function(f) { + var a = []; + for (i in 0...__this__.length) + a[i] = f(__this__[i]); + return a; + }); + __feature__("Array.filter", if (Array.prototype.filter == null) Array.prototype.filter = function(f) { + var a = []; + for (i in 0...__this__.length) { + var e = __this__[i]; + if (f(e)) + a.push(e); } - ); - __feature__("Array.filter", - if( Array.prototype.filter == null ) - Array.prototype.filter = function(f) { - var a = []; - for( i in 0...__this__.length ) { - var e = __this__[i]; - if( f(e) ) a.push(e); - } - return a; - } - ); -#end - } - + return a; + }); + #end + } } diff --git a/std/js/_std/String.hx b/std/js/_std/String.hx index 7647e08261e..da897547a50 100644 --- a/std/js/_std/String.hx +++ b/std/js/_std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,25 +20,32 @@ * DEALINGS IN THE SOFTWARE. */ @:coreApi extern class String { - var length(default,null) : Int; + var length(default, null):Int; - @:pure function new(string:String) : Void; - @:pure function toUpperCase() : String; - @:pure function toLowerCase() : String; - @:pure function charAt( index : Int) : String; - @:pure function indexOf( str : String, ?startIndex : Int ) : Int; - @:pure function lastIndexOf( str : String, ?startIndex : Int ) : Int; - @:pure function split( delimiter : String ) : Array; - @:pure function toString() : String; - @:pure function substring( startIndex : Int, ?endIndex : Int ) : String; + @:pure function new(string:String):Void; + @:pure function toUpperCase():String; + @:pure function toLowerCase():String; + @:pure function charAt(index:Int):String; + @:pure function indexOf(str:String, ?startIndex:Int):Int; + @:pure function lastIndexOf(str:String, ?startIndex:Int):Int; + @:pure function split(delimiter:String):Array; + @:pure function toString():String; + @:pure function substring(startIndex:Int, ?endIndex:Int):String; - @:pure inline function charCodeAt( index : Int) : Null { + @:pure inline function charCodeAt(index:Int):Null { return @:privateAccess HxOverrides.cca(this, index); } - @:pure inline function substr( pos : Int, ?len : Int ) : String { + @:pure inline function substr(pos:Int, ?len:Int):String { return @:privateAccess HxOverrides.substr(this, pos, len); } - @:pure static function fromCharCode( code : Int ) : String; + @:pure static inline function fromCharCode(code:Int):String { + return untyped __define_feature__('String.fromCharCode', js.Syntax.code("String.fromCodePoint({0})", code)); + } + + static function __init__():Void { + untyped __feature__('String.fromCharCode', + js.Syntax.code("if( String.fromCodePoint == null ) String.fromCodePoint = function(c) { return c < 0x10000 ? String.fromCharCode(c) : String.fromCharCode((c>>10)+0xD7C0)+String.fromCharCode((c&0x3FF)+0xDC00); }")); + } } diff --git a/std/js/_std/Type.hx b/std/js/_std/Type.hx index ee8e4fefaff..5bf6602ccb4 100644 --- a/std/js/_std/Type.hx +++ b/std/js/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,6 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - enum ValueType { TNull; TInt; @@ -27,131 +26,180 @@ enum ValueType { TBool; TObject; TFunction; - TClass( c : Class ); - TEnum( e : Enum ); + TClass(c:Class); + TEnum(e:Enum); TUnknown; } @:coreApi class Type { - - public static inline function getClass( o : T ) : Class { - return if (o == null) null else @:privateAccess js.Boot.getClass(o); + public static inline function getClass(o:T):Class { + return @:privateAccess js.Boot.getClass(o); } - public static function getEnum( o : EnumValue ) : Enum untyped { - if( o == null ) - return null; - #if !js_enums_as_objects - return o.__enum__; - #else - return $hxEnums[o.__enum__]; - #end - } + public static function getEnum(o:EnumValue):Enum + untyped { + if (o == null) + return null; + #if js_enums_as_arrays + return o.__enum__; + #else + return $hxEnums[o.__enum__]; + #end + } - public static function getSuperClass( c : Class ) : Class untyped { - return c.__super__; + public static inline function getSuperClass(c:Class):Class { + return untyped __define_feature__("Type.getSuperClass", c.__super__); } - - public static function getClassName( c : Class ) : String { - var a : Array = untyped c.__name__; - if (a == null) - return null; - return a.join("."); + public static inline function getClassName(c:Class):String { + return untyped __define_feature__("Type.getClassName", c.__name__); } - public static function getEnumName( e : Enum ) : String { - var a : Array = untyped e.__ename__; - return a.join("."); + public static inline function getEnumName(e:Enum):String { + return untyped __define_feature__("Type.getEnumName", e.__ename__); } - public static function resolveClass( name : String ) : Class untyped { - var cl : Class = $hxClasses[name]; - // ensure that this is a class - if( cl == null || !js.Boot.isClass(cl) ) - return null; - return cl; + #if js_enums_as_arrays + public static function resolveClass(name:String):Class + untyped { + var cl:Class = $hxClasses[name]; + // ensure that this is a class + if (cl == null || !js.Boot.isClass(cl)) + return null; + return cl; + } + + public static function resolveEnum(name:String):Enum + untyped { + var e:Dynamic = $hxClasses[name]; + // ensure that this is an enum + if (e == null || !js.Boot.isEnum(e)) + return null; + return e; + } + #else + public static inline function resolveClass(name:String):Class { + return untyped __define_feature__("Type.resolveClass", $hxClasses[name]); } - public static function resolveEnum( name : String ) : Enum untyped { - var e : Dynamic = $hxClasses[name]; - // ensure that this is an enum - if( e == null || !js.Boot.isEnum(e) ) - return null; - return e; + public static inline function resolveEnum(name:String):Enum { + return untyped __define_feature__("Type.resolveEnum", $hxEnums[name]); } + #end #if (js_es < 5) - public static function createInstance( cl : Class, args : Array ) : T untyped { - switch( args.length ) { - case 0: - return __new__(cl); - case 1: - return __new__(cl,args[0]); - case 2: - return __new__(cl,args[0],args[1]); - case 3: - return __new__(cl,args[0],args[1],args[2]); - case 4: - return __new__(cl,args[0],args[1],args[2],args[3]); - case 5: - return __new__(cl,args[0],args[1],args[2],args[3],args[4]); - case 6: - return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5]); - case 7: - return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6]); - case 8: - return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]); - case 9: - return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); - case 10: - return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]); - case 11: - return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]); - case 12: - return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]); - case 13: - return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]); - case 14: - return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]); - default: - throw "Too many arguments"; + public static function createInstance(cl:Class, args:Array):T { + switch (args.length) { + case 0: + return js.Syntax.construct(cl); + case 1: + return js.Syntax.construct(cl, args[0]); + case 2: + return js.Syntax.construct(cl, args[0], args[1]); + case 3: + return js.Syntax.construct(cl, args[0], args[1], args[2]); + case 4: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3]); + case 5: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4]); + case 6: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + case 8: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); + case 9: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + case 10: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); + case 11: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]); + case 12: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]); + case 13: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], + args[12]); + case 14: + return js.Syntax.construct(cl, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], + args[12], args[13]); + default: + throw "Too many arguments"; } } - public static function createEmptyInstance( cl : Class ) : T untyped { - __js__("function empty() {}; empty.prototype = cl.prototype"); - return __js__("new empty()"); - } + public static function createEmptyInstance(cl:Class):T + untyped { + __js__("function empty() {}; empty.prototype = cl.prototype"); + return __js__("new empty()"); + } #else - public static function createInstance( cl : Class, args : Array ) : T untyped { - return untyped __js__("new ({0})", Function.prototype.bind.apply(cl, [null].concat(args))); - } + public static function createInstance(cl:Class, args:Array):T + untyped { + return untyped __js__("new ({0})", Function.prototype.bind.apply(cl, [null].concat(args))); + } - public static inline function createEmptyInstance( cl : Class ) : T { - return js.Object.create((cast cl).prototype); + public static inline function createEmptyInstance(cl:Class):T { + return js.lib.Object.create((cast cl).prototype); } #end - public static function createEnum( e : Enum, constr : String, ?params : Array ) : T { - var f:Dynamic = Reflect.field(e,constr); - if( f == null ) throw "No such constructor "+constr; - if( Reflect.isFunction(f) ) { - if( params == null ) throw "Constructor "+constr+" need parameters"; - return Reflect.callMethod(e,f,params); + public static function createEnum(e:Enum, constr:String, ?params:Array):T { + var f:Dynamic = Reflect.field(e, constr); + if (f == null) + throw "No such constructor " + constr; + if (Reflect.isFunction(f)) { + if (params == null) + throw "Constructor " + constr + " need parameters"; + return Reflect.callMethod(e, f, params); } - if( params != null && params.length != 0 ) - throw "Constructor "+constr+" does not need parameters"; + if (params != null && params.length != 0) + throw "Constructor " + constr + " does not need parameters"; return f; } - public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T { - var c : String = (untyped e.__constructs__)[index]; - if( c == null ) throw index+" is not a valid enum constructor index"; - return createEnum(e,c,params); + public static function createEnumIndex(e:Enum, index:Int, ?params:Array):T { + var c:String = (untyped e.__constructs__)[index]; + if (c == null) + throw index + " is not a valid enum constructor index"; + return createEnum(e, c, params); + } + + #if (js_es >= 6) + public static function getInstanceFields(c:Class):Array { + var result = []; + while (c != null) { + for (name in js.lib.Object.getOwnPropertyNames((cast c).prototype)) { + switch name { + case "constructor" | "__class__" | "__properties__": + // skip special names + case _: + if (result.indexOf(name) == -1) + result.push(name); + } + } + c = getSuperClass(c); + } + return result; } - public static function getInstanceFields( c : Class ) : Array { + public static function getClassFields(c:Class):Array { + var a = js.lib.Object.getOwnPropertyNames(cast c); + a.remove("__id__"); + a.remove("hx__closures__"); + a.remove("__name__"); + a.remove("__interfaces__"); + a.remove("__isInterface__"); + a.remove("__properties__"); + a.remove("__instanceFields__"); + a.remove("__super__"); + a.remove("__meta__"); + a.remove("prototype"); + a.remove("name"); + a.remove("length"); + return a; + } + #else + public static function getInstanceFields(c:Class):Array { var a = []; untyped __js__("for(var i in c.prototype) a.push(i)"); a.remove("__class__"); @@ -159,7 +207,7 @@ enum ValueType { return a; } - public static function getClassFields( c : Class ) : Array { + public static function getClassFields(c:Class):Array { var a = Reflect.fields(c); a.remove("__name__"); a.remove("__interfaces__"); @@ -169,107 +217,113 @@ enum ValueType { a.remove("prototype"); return a; } + #end - public static inline function getEnumConstructs( e : Enum ) : Array { + public static inline function getEnumConstructs(e:Enum):Array { return ((cast e).__constructs__ : Array).copy(); } @:access(js.Boot) - public static function typeof( v : Dynamic ) : ValueType { - switch (js.Lib.typeof(v)) { - case "boolean": - return TBool; - case "string": - return TClass(String); - case "number": - // this should handle all cases : NaN, +/-Inf and Floats outside range - if( Math.ceil(v) == v%2147483648.0 ) - return TInt; - return TFloat; - case "object": - if( v == null ) - return TNull; - var e = v.__enum__; - if( e != null ){ - #if !js_enums_as_objects - return TEnum(e); - #else - return TEnum(untyped $hxEnums[e]); - #end - } - var c = js.Boot.getClass(v); - if( c != null ) - return TClass(c); - return TObject; - case "function": - if( js.Boot.isClass(v) || js.Boot.isEnum(v) ) + public static function typeof(v:Dynamic):ValueType { + switch (js.Syntax.typeof(v)) { + case "boolean": + return TBool; + case "string": + return TClass(String); + case "number": + // this should handle all cases : NaN, +/-Inf and Floats outside range + if (Math.ceil(v) == v % 2147483648.0) + return TInt; + return TFloat; + case "object": + if (v == null) + return TNull; + var e = v.__enum__; + if (e != null) { + #if js_enums_as_arrays + return TEnum(e); + #else + return TEnum(untyped $hxEnums[e]); + #end + } + var c = js.Boot.getClass(v); + if (c != null) + return TClass(c); return TObject; - return TFunction; - case "undefined": - return TNull; - default: - return TUnknown; + case "function": + if (js.Boot.isClass(v) || js.Boot.isEnum(v)) + return TObject; + return TFunction; + case "undefined": + return TNull; + default: + return TUnknown; } } - public static function enumEq( a : T, b : T ) : Bool untyped { - if( a == b ) - return true; - try { - #if !js_enums_as_objects - if( a[0] != b[0] ) - return false; - for( i in 2...a.length ) - if( !enumEq(a[i],b[i]) ) + public static function enumEq(a:T, b:T):Bool + untyped { + if (a == b) + return true; + try { + var e = a.__enum__; + if (e == null || e != b.__enum__) return false; - #else - if (a._hx_index != b._hx_index) - return false; - for (f in Reflect.fields(a)){ - if ( !enumEq(a[f],b[f]) ){ + #if js_enums_as_arrays + if (a[0] != b[0]) + return false; + for (i in 2...a.length) + if (!enumEq(a[i], b[i])) + return false; + #else + if (a._hx_index != b._hx_index) return false; + var enm = $hxEnums[e]; + var ctorName = enm.__constructs__[a._hx_index]; + var params:Array = enm[ctorName].__params__; + for (f in params) { + if (!enumEq(a[f], b[f])) { + return false; + } } - } - #end - var e = a.__enum__; - if( e != b.__enum__ || e == null ) + #end + } catch (e:Dynamic) { return false; - - } catch( e : Dynamic ) { - return false; + } + return true; } - return true; - } - public inline static function enumConstructor( e : EnumValue ) : String { - #if !js_enums_as_objects + public inline static function enumConstructor(e:EnumValue):String { + #if js_enums_as_arrays return untyped e[0]; #else return untyped $hxEnums[e.__enum__].__constructs__[e._hx_index]; #end } - public inline static function enumParameters( e : EnumValue ) : Array { - #if !js_enums_as_objects + #if js_enums_as_arrays + public inline static function enumParameters(e:EnumValue):Array { return untyped e.slice(2); - #else - var n = enumConstructor(e); - var params:Array = untyped __js__("$hxEnums[{0}.__enum__][{1}].__params__",e,n); - return params != null ? [for (p in params) untyped e[p]] : []; - #end } + #else + public static function enumParameters(e:EnumValue):Array + untyped { + var enm:Enum = $hxEnums[e.__enum__]; + var ctorName:String = enm.__constructs__[e._hx_index]; + var params:Array = enm[ctorName].__params__; + return params != null ? [for (p in params) e[p]] : []; + } + #end - public inline static function enumIndex( e : EnumValue ) : Int { - #if js_enums_as_objects + public inline static function enumIndex(e:EnumValue):Int { + #if !js_enums_as_arrays return untyped e._hx_index; #else return untyped e[1]; #end } - public inline static function allEnums( e : Enum ) : Array { - return untyped __define_feature__("Type.allEnums", e.__empty_constructs__); + public inline static function allEnums(e:Enum):Array { + return untyped __define_feature__("Type.allEnums", e.__empty_constructs__.slice()); } - } - diff --git a/std/js/_std/haxe/Json.hx b/std/js/_std/haxe/Json.hx index fa4148407b1..6e04714c263 100644 --- a/std/js/_std/haxe/Json.hx +++ b/std/js/_std/haxe/Json.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,29 +19,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe; @:coreApi -#if (!haxeJSON && !old_browser) -@:native("JSON") extern +#if !haxeJSON +@:native("JSON") +extern #end class Json { - - #if haxeJSON inline #end - public static function parse( text : String ) : Dynamic { - return haxe.format.JsonParser.parse(text); - } - - #if haxeJSON inline #end - 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) - static function __init__():Void untyped { - if( __js__('typeof(JSON)') != 'undefined' ) - Json = __js__('JSON'); - } + #if haxeJSON + inline #end + public static function parse(text:String):Dynamic + #if !haxeJSON; #else { + return haxe.format.JsonParser.parse(text); + } #end + #if haxeJSON + inline + #end + public static function stringify(value:Dynamic, ?replacer:(key:Dynamic, value:Dynamic) -> Dynamic, ?space:String):String + #if !haxeJSON; #else { + return haxe.format.JsonPrinter.print(value, replacer, space); + } #end } diff --git a/std/js/_std/haxe/Log.hx b/std/js/_std/haxe/Log.hx deleted file mode 100644 index eca670cb172..00000000000 --- a/std/js/_std/haxe/Log.hx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -package haxe; - -@:coreApi class Log { - @:access(js.Boot.__string_rec) - public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { - var msg = if (infos != null) infos.fileName + ":" + infos.lineNumber + ": " else ""; - msg += js.Boot.__string_rec(v, ""); - if (infos != null && infos.customParams != null) - for (v in infos.customParams) - msg += "," + js.Boot.__string_rec(v, ""); - if( js.Lib.typeof(untyped console) != "undefined" && (untyped console).log != null ) - (untyped console).log(msg); - } -} diff --git a/std/js/_std/haxe/ds/IntMap.hx b/std/js/_std/haxe/ds/IntMap.hx index 00801368900..f1a103de406 100644 --- a/std/js/_std/haxe/ds/IntMap.hx +++ b/std/js/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,68 +19,78 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe.ds; -@:coreApi class IntMap implements haxe.Constraints.IMap { +package haxe.ds; - private var h : Dynamic; +@:coreApi class IntMap implements haxe.Constraints.IMap { + private var h:Dynamic; - public inline function new() : Void { + public inline function new():Void { h = {}; } - public inline function set( key : Int, value : T ) : Void { - untyped h[key] = value; + public inline function set(key:Int, value:T):Void { + h[key] = value; } - public inline function get( key : Int ) : Null { - return untyped h[key]; + public inline function get(key:Int):Null { + return h[key]; } - public inline function exists( key : Int ) : Bool { - return untyped h.hasOwnProperty(key); + public inline function exists(key:Int):Bool { + return (cast h).hasOwnProperty(key); } - public function remove( key : Int ) : Bool { - if( untyped !h.hasOwnProperty(key) ) return false; - untyped __js__("delete")(h[key]); + public function remove(key:Int):Bool { + if (!(cast h).hasOwnProperty(key)) + return false; + js.Syntax.delete(h, key); return true; } - public function keys() : Iterator { + public function keys():Iterator { var a = []; - untyped __js__("for( var key in {0} ) {1}", h, if( h.hasOwnProperty(key) ) a.push(key|0)); + untyped __js__("for( var key in {0} ) {1}", h, if (h.hasOwnProperty(key)) a.push(key | 0)); return a.iterator(); } - public function iterator() : Iterator { + public function iterator():Iterator { return untyped { - ref : h, - it : keys(), - hasNext : function() { return __this__.it.hasNext(); }, - next : function() { var i = __this__.it.next(); return __this__.ref[i]; } + ref: h, + it: keys(), + hasNext: function() { + return __this__.it.hasNext(); + }, + next: function() { + var i = __this__.it.next(); + return __this__.ref[i]; + } }; } - - public function copy() : IntMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():IntMap { var copied = new IntMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(i); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } - } diff --git a/std/js/_std/haxe/ds/ObjectMap.hx b/std/js/_std/haxe/ds/ObjectMap.hx index be7d0f01286..7a5bc263033 100644 --- a/std/js/_std/haxe/ds/ObjectMap.hx +++ b/std/js/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of h software and associated documentation files (the "Software"), @@ -22,30 +22,39 @@ package haxe.ds; +import js.Syntax; +import js.Lib; + @:coreApi -class ObjectMap implements haxe.Constraints.IMap { +class ObjectMap implements haxe.Constraints.IMap { + static var count:Int; - static var count = 0; + // initialize count through __init__ magic, because these are generated + // before normal static initializations for which ObjectMap should be ready to use + // see https://github.com/HaxeFoundation/haxe/issues/6792 + static inline function __init__():Void + count = 0; - static inline function assignId(obj: { } ):Int { - return untyped obj.__id__ = ++count; + static inline function assignId(obj:{}):Int { + return Syntax.code('({0}.__id__ = {1})', obj, Lib.getNextHaxeUID()); } - static inline function getId(obj: { } ):Int { + static inline function getId(obj:{}):Int { return untyped obj.__id__; } - var h : { }; + var h:{}; - public function new() : Void { - h = { __keys__: {} }; + public function new():Void { + h = {__keys__: {}}; } - public function set(key:K, value:V):Void untyped { - var id : Int = getId(key) || assignId(key); - h[id] = value; - h.__keys__[id] = key; - } + public function set(key:K, value:V):Void + untyped { + var id:Int = getId(key) || assignId(key); + h[id] = value; + h.__keys__[id] = key; + } public inline function get(key:K):Null { return untyped h[getId(key)]; @@ -55,52 +64,63 @@ class ObjectMap implements haxe.Constraints.IMap { return untyped h.__keys__[getId(key)] != null; } - public function remove( key : K ) : Bool { + public function remove(key:K):Bool { var id = getId(key); - if ( untyped h.__keys__[id] == null ) return false; - untyped __js__("delete")(h[id]); - untyped __js__("delete")(h.__keys__[id]); + if (untyped h.__keys__[id] == null) + return false; + untyped __js__("delete")(h[id]); + untyped __js__("delete")(h.__keys__[id]); return true; } - public function keys() : Iterator { + public function keys():Iterator { var a = []; untyped { __js__("for( var key in this.h.__keys__ ) {"); - if( h.hasOwnProperty(key) ) - a.push(h.__keys__[key]); + if (h.hasOwnProperty(key)) + a.push(h.__keys__[key]); __js__("}"); } return a.iterator(); } - public function iterator() : Iterator { + public function iterator():Iterator { return untyped { - ref : h, - it : keys(), - hasNext : function() { return __this__.it.hasNext(); }, - next : function() { var i = __this__.it.next(); return __this__.ref[getId(i)]; } + ref: h, + it: keys(), + hasNext: function() { + return __this__.it.hasNext(); + }, + next: function() { + var i = __this__.it.next(); + return __this__.ref[getId(i)]; + } }; } - - public function copy() : ObjectMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():ObjectMap { var copied = new ObjectMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var it = keys(); - for( i in it ) { + for (i in it) { s.add(Std.string(i)); s.add(" => "); s.add(Std.string(get(i))); - if( it.hasNext() ) + if (it.hasNext()) s.add(", "); } s.add("}"); return s.toString(); } -} \ No newline at end of file +} diff --git a/std/js/_std/haxe/ds/StringMap.hx b/std/js/_std/haxe/ds/StringMap.hx index 34bf95c6a41..367c81b54e6 100644 --- a/std/js/_std/haxe/ds/StringMap.hx +++ b/std/js/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,136 +19,147 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.ds; private class StringMapIterator { - var map : StringMap; - var keys : Array; - var index : Int; - var count : Int; + var map:StringMap; + var keys:Array; + var index:Int; + var count:Int; + public inline function new(map:StringMap, keys:Array) { this.map = map; this.keys = keys; this.index = 0; this.count = keys.length; } + public inline function hasNext() { return index < count; } + public inline function next() { return map.get(keys[index++]); } } -@:coreApi class StringMap implements haxe.Constraints.IMap { +@:coreApi class StringMap implements haxe.Constraints.IMap { + private var h:Dynamic; + private var rh:Dynamic; - private var h : Dynamic; - private var rh : Dynamic; - - public inline function new() : Void { + public inline function new():Void { h = {}; } - inline function isReserved(key:String) : Bool { + inline function isReserved(key:String):Bool { return untyped __js__("__map_reserved")[key] != null; } - public inline function set( key : String, value : T ) : Void { - if( isReserved(key) ) + public inline function set(key:String, value:T):Void { + if (isReserved(key)) setReserved(key, value); else h[cast key] = value; } - public inline function get( key : String ) : Null { - if( isReserved(key) ) + public inline function get(key:String):Null { + if (isReserved(key)) return getReserved(key); return h[cast key]; } - public inline function exists( key : String ) : Bool { - if( isReserved(key) ) + public inline function exists(key:String):Bool { + if (isReserved(key)) return existsReserved(key); return h.hasOwnProperty(key); } - function setReserved( key : String, value : T ) : Void { - if( rh == null ) rh = {}; - rh[cast "$"+key] = value; + function setReserved(key:String, value:T):Void { + if (rh == null) + rh = {}; + rh[cast "$" + key] = value; } - function getReserved( key : String ) : Null { - return rh == null ? null : rh[cast "$"+key]; + function getReserved(key:String):Null { + return rh == null ? null : rh[cast "$" + key]; } - function existsReserved( key : String ) : Bool { - if( rh == null ) return false; - return untyped rh.hasOwnProperty("$"+key); + function existsReserved(key:String):Bool { + if (rh == null) + return false; + return (cast rh).hasOwnProperty("$" + key); } - public function remove( key : String ) : Bool { - if( isReserved(key) ) { + public function remove(key:String):Bool { + if (isReserved(key)) { key = "$" + key; - if( rh == null || !rh.hasOwnProperty(key) ) return false; - untyped __js__("delete")(rh[key]); + if (rh == null || !rh.hasOwnProperty(key)) + return false; + js.Syntax.delete(rh, key); return true; } else { - if( !h.hasOwnProperty(key) ) + if (!h.hasOwnProperty(key)) return false; - untyped __js__("delete")(h[key]); + js.Syntax.delete(h, key); return true; } } - public function keys() : Iterator { + public function keys():Iterator { return arrayKeys().iterator(); } - - function arrayKeys() : Array { + + function arrayKeys():Array { var out = []; untyped { __js__("for( var key in this.h ) {"); - if( h.hasOwnProperty(key) ) - out.push(key); + if (h.hasOwnProperty(key)) + out.push(key); __js__("}"); } - if( rh != null ) untyped { - __js__("for( var key in this.rh ) {"); - if( key.charCodeAt(0) == "$".code ) + if (rh != null) + untyped { + __js__("for( var key in this.rh ) {"); + if (key.charCodeAt(0) == "$".code) out.push(key.substr(1)); - __js__("}"); - } + __js__("}"); + } return out; } - public inline function iterator() : Iterator { + public inline function iterator():Iterator { return new StringMapIterator(this, arrayKeys()); } - - public function copy() : StringMap { + + @:runtime public inline function keyValueIterator():KeyValueIterator { + return new haxe.iterators.MapKeyValueIterator(this); + } + + public function copy():StringMap { var copied = new StringMap(); - for(key in keys()) copied.set(key, get(key)); + for (key in keys()) + copied.set(key, get(key)); return copied; } - public function toString() : String { + public function toString():String { var s = new StringBuf(); s.add("{"); var keys = arrayKeys(); - for( i in 0...keys.length ) { + for (i in 0...keys.length) { var k = keys[i]; s.add(k); s.add(" => "); s.add(Std.string(get(k))); - if( i < keys.length-1 ) + if (i < keys.length - 1) s.add(", "); } s.add("}"); return s.toString(); } - static function __init__() : Void { + static function __init__():Void { untyped __js__("var __map_reserved = {};"); } - } diff --git a/std/js/_std/haxe/io/ArrayBufferView.hx b/std/js/_std/haxe/io/ArrayBufferView.hx index 0026057af28..058fa23f578 100644 --- a/std/js/_std/haxe/io/ArrayBufferView.hx +++ b/std/js/_std/haxe/io/ArrayBufferView.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,45 +19,39 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - package haxe.io; -typedef ArrayBufferViewData = js.html.ArrayBufferView; +package haxe.io; + +typedef ArrayBufferViewData = js.lib.ArrayBufferView; abstract ArrayBufferView(ArrayBufferViewData) { + public var buffer(get, never):haxe.io.Bytes; + public var byteOffset(get, never):Int; + public var byteLength(get, never):Int; - public static var EMULATED(get,never) : Bool; - static inline function get_EMULATED() { - #if nodejs - return false; - #else - return (cast js.html.ArrayBuffer) == js.html.compat.ArrayBuffer; - #end + public inline function new(size:Int) { + this = new js.lib.Uint8Array(size); } - public var buffer(get,never) : haxe.io.Bytes; - public var byteOffset(get, never) : Int; - public var byteLength(get, never) : Int; + inline function get_byteOffset() + return this.byteOffset; - public inline function new( size : Int ) { - this = new js.html.Uint8Array(size); - } + inline function get_byteLength() + return this.byteLength; - inline function get_byteOffset() return this.byteOffset; - inline function get_byteLength() return this.byteLength; - inline function get_buffer() : haxe.io.Bytes { + inline function get_buffer():haxe.io.Bytes { return haxe.io.Bytes.ofData(this.buffer); } - public inline function sub( begin : Int, ?length : Int ) { - return fromData(new js.html.Uint8Array(this.buffer.slice(begin, length == null ? null : begin+length))); + public inline function sub(begin:Int, ?length:Int) { + return fromData(new js.lib.Uint8Array(this.buffer.slice(begin, length == null ? null : begin + length))); } - public inline function getData() : ArrayBufferViewData { + public inline function getData():ArrayBufferViewData { return this; } - public static inline function fromData( a : ArrayBufferViewData ) : ArrayBufferView { + public static inline function fromData(a:ArrayBufferViewData):ArrayBufferView { return cast a; } - -} \ No newline at end of file +} diff --git a/std/js/_std/haxe/io/Bytes.hx b/std/js/_std/haxe/io/Bytes.hx index 0f67ad8bc29..b15e2af5c89 100644 --- a/std/js/_std/haxe/io/Bytes.hx +++ b/std/js/_std/haxe/io/Bytes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,23 +19,19 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe.io; -#if !nodejs -import js.html.compat.Uint8Array; -import js.html.compat.DataView; -#end +package haxe.io; @:coreApi class Bytes { + public var length(default, null):Int; - public var length(default,null) : Int; - var b : js.html.Uint8Array; - var data : js.html.DataView; + var b:js.lib.Uint8Array; + var data:js.lib.DataView; function new(data:BytesData) { this.length = data.byteLength; - this.b = new js.html.Uint8Array(data); + this.b = new js.lib.Uint8Array(data); untyped { b.bufferValue = data; // some impl does not return the same instance in .buffer data.hxBytes = this; @@ -43,121 +39,134 @@ class Bytes { } } - public inline function get( pos : Int ) : Int { + public inline function get(pos:Int):Int { return b[pos]; } - public inline function set( pos : Int, v : Int ) : Void { - b[pos] = v & 0xFF; // the &0xFF is necessary for js.html.compat support + public inline function set(pos:Int, v:Int):Void { + b[pos] = v; } - public function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void { - if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) throw Error.OutsideBounds; - if( srcpos == 0 && len == src.b.byteLength ) - b.set(src.b,pos); + public function blit(pos:Int, src:Bytes, srcpos:Int, len:Int):Void { + if (pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length) + throw Error.OutsideBounds; + if (srcpos == 0 && len == src.b.byteLength) + b.set(src.b, pos); else - b.set(src.b.subarray(srcpos,srcpos+len),pos); + b.set(src.b.subarray(srcpos, srcpos + len), pos); } - public function fill( pos : Int, len : Int, value : Int ) : Void { - for( i in 0...len ) + public function fill(pos:Int, len:Int, value:Int):Void { + for (i in 0...len) set(pos++, value); } - public function sub( pos : Int, len : Int ) : Bytes { - if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; - return new Bytes(b.buffer.slice(pos+b.byteOffset,pos+b.byteOffset+len)); + public function sub(pos:Int, len:Int):Bytes { + if (pos < 0 || len < 0 || pos + len > length) + throw Error.OutsideBounds; + return new Bytes(b.buffer.slice(pos + b.byteOffset, pos + b.byteOffset + len)); } - public function compare( other : Bytes ) : Int { + public function compare(other:Bytes):Int { var b1 = b; var b2 = other.b; var len = (length < other.length) ? length : other.length; - for( i in 0...len ) - if( b1[i] != b2[i] ) + for (i in 0...len) + if (b1[i] != b2[i]) return b1[i] - b2[i]; return length - other.length; } - inline function initData() : Void { - if( data == null ) data = new js.html.DataView(b.buffer, b.byteOffset, b.byteLength); + inline function initData():Void { + if (data == null) + data = new js.lib.DataView(b.buffer, b.byteOffset, b.byteLength); } - public function getDouble( pos : Int ) : Float { + public function getDouble(pos:Int):Float { initData(); return data.getFloat64(pos, true); } - public function getFloat( pos : Int ) : Float { + public function getFloat(pos:Int):Float { initData(); return data.getFloat32(pos, true); } - public function setDouble( pos : Int, v : Float ) : Void { + public function setDouble(pos:Int, v:Float):Void { initData(); data.setFloat64(pos, v, true); } - public function setFloat( pos : Int, v : Float ) : Void { + public function setFloat(pos:Int, v:Float):Void { initData(); data.setFloat32(pos, v, true); } - public function getUInt16( pos : Int ) : Int { + public function getUInt16(pos:Int):Int { initData(); return data.getUint16(pos, true); } - public function setUInt16( pos : Int, v : Int ) : Void { + public function setUInt16(pos:Int, v:Int):Void { initData(); data.setUint16(pos, v, true); } - public function getInt32( pos : Int ) : Int { + public function getInt32(pos:Int):Int { initData(); return data.getInt32(pos, true); } - public function setInt32( pos : Int, v : Int ) : Void { + public function setInt32(pos:Int, v:Int):Void { initData(); data.setInt32(pos, v, true); } - public function getInt64( pos : Int ) : haxe.Int64 { - return Int64.make(getInt32(pos + 4),getInt32(pos)); + public function getInt64(pos:Int):haxe.Int64 { + return Int64.make(getInt32(pos + 4), getInt32(pos)); } - public function setInt64( pos : Int, v : haxe.Int64 ) : Void { + public function setInt64(pos:Int, v:haxe.Int64):Void { setInt32(pos, v.low); setInt32(pos + 4, v.high); } - public function getString( pos : Int, len : Int ) : String { - if( pos < 0 || len < 0 || pos + len > length ) throw Error.OutsideBounds; + public function getString(pos:Int, len:Int, ?encoding:Encoding):String { + if (pos < 0 || len < 0 || pos + len > length) + throw Error.OutsideBounds; + if (encoding == null) + encoding = UTF8; var s = ""; var b = b; - var fcc = String.fromCharCode; var i = pos; - var max = pos+len; - // utf8-decode and utf16-encode - while( i < max ) { - var c = b[i++]; - if( c < 0x80 ) { - if( c == 0 ) break; - s += fcc(c); - } else if( c < 0xE0 ) - s += fcc( ((c & 0x3F) << 6) | (b[i++] & 0x7F) ); - else if( c < 0xF0 ) { - var c2 = b[i++]; - s += fcc( ((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | (b[i++] & 0x7F) ); - } else { - var c2 = b[i++]; - var c3 = b[i++]; - var u = ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 & 0x7F) << 6) | (b[i++] & 0x7F); - // surrogate pair - s += fcc( (u >> 10) + 0xD7C0 ); - s += fcc( (u & 0x3FF) | 0xDC00 ); - } + var max = pos + len; + switch (encoding) { + case UTF8: + var debug = pos > 0; + // utf8-decode and utf16-encode + while (i < max) { + var c = b[i++]; + if (c < 0x80) { + if (c == 0) + break; + s += String.fromCharCode(c); + } else if (c < 0xE0) + s += String.fromCharCode(((c & 0x3F) << 6) | (b[i++] & 0x7F)); + else if (c < 0xF0) { + var c2 = b[i++]; + s += String.fromCharCode(((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | (b[i++] & 0x7F)); + } else { + var c2 = b[i++]; + var c3 = b[i++]; + var u = ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 & 0x7F) << 6) | (b[i++] & 0x7F); + s += String.fromCharCode(u); + } + } + case RawNative: + while (i < max) { + var c = b[i++] | (b[i++] << 8); + s += String.fromCharCode(c); + } } return s; } @@ -168,17 +177,17 @@ class Bytes { return getString(pos, len); } - public function toString() : String { - return getString(0,length); + public function toString():String { + return getString(0, length); } - public function toHex() : String { + public function toHex():String { var s = new StringBuf(); var chars = []; var str = "0123456789abcdef"; - for( i in 0...str.length ) + for (i in 0...str.length) chars.push(str.charCodeAt(i)); - for( i in 0...length ) { + for (i in 0...length) { var c = get(i); s.addChar(chars[c >> 4]); s.addChar(chars[c & 15]); @@ -186,51 +195,78 @@ class Bytes { return s.toString(); } - public inline function getData() : BytesData { + public inline function getData():BytesData { return untyped b.bufferValue; } - public static inline function alloc( length : Int ) : Bytes { + public static inline function alloc(length:Int):Bytes { return new Bytes(new BytesData(length)); } - public static function ofString( s : String ) : Bytes { + public static function ofString(s:String, ?encoding:Encoding):Bytes { + if (encoding == RawNative) { + var buf = new js.lib.Uint8Array(s.length << 1); + for (i in 0...s.length) { + var c:Int = StringTools.fastCodeAt(s, i); + buf[i << 1] = c & 0xFF; + buf[(i << 1) | 1] = c >> 8; + } + return new Bytes(buf.buffer); + } var a = new Array(); // utf16-decode and utf8-encode var i = 0; - while( i < s.length ) { - var c : Int = StringTools.fastCodeAt(s,i++); + while (i < s.length) { + var c:Int = StringTools.fastCodeAt(s, i++); // surrogate pair - if( 0xD800 <= c && c <= 0xDBFF ) - c = (c - 0xD7C0 << 10) | (StringTools.fastCodeAt(s,i++) & 0x3FF); - if( c <= 0x7F ) + if (0xD800 <= c && c <= 0xDBFF) + c = (c - 0xD7C0 << 10) | (StringTools.fastCodeAt(s, i++) & 0x3FF); + if (c <= 0x7F) a.push(c); - else if( c <= 0x7FF ) { - a.push( 0xC0 | (c >> 6) ); - a.push( 0x80 | (c & 63) ); - } else if( c <= 0xFFFF ) { - a.push( 0xE0 | (c >> 12) ); - a.push( 0x80 | ((c >> 6) & 63) ); - a.push( 0x80 | (c & 63) ); + else if (c <= 0x7FF) { + a.push(0xC0 | (c >> 6)); + a.push(0x80 | (c & 63)); + } else if (c <= 0xFFFF) { + a.push(0xE0 | (c >> 12)); + a.push(0x80 | ((c >> 6) & 63)); + a.push(0x80 | (c & 63)); } else { - a.push( 0xF0 | (c >> 18) ); - a.push( 0x80 | ((c >> 12) & 63) ); - a.push( 0x80 | ((c >> 6) & 63) ); - a.push( 0x80 | (c & 63) ); + a.push(0xF0 | (c >> 18)); + a.push(0x80 | ((c >> 12) & 63)); + a.push(0x80 | ((c >> 6) & 63)); + a.push(0x80 | (c & 63)); } } - return new Bytes(new js.html.Uint8Array(a).buffer); + return new Bytes(new js.lib.Uint8Array(a).buffer); } - public static function ofData( b : BytesData ) : Bytes { + public static function ofData(b:BytesData):Bytes { var hb = untyped b.hxBytes; - if( hb != null ) return hb; + if (hb != null) + return hb; return new Bytes(b); } - public inline static function fastGet( b : BytesData, pos : Int ) : Int { + public static function ofHex(s:String):Bytes { + if ((s.length & 1) != 0) + throw "Not a hex string (odd number of digits)"; + var a = new Array(); + var i = 0; + var len = s.length >> 1; + while (i < len) { + var high = StringTools.fastCodeAt(s, i * 2); + var low = StringTools.fastCodeAt(s, i * 2 + 1); + high = (high & 0xF) + ((high & 0x40) >> 6) * 9; + low = (low & 0xF) + ((low & 0x40) >> 6) * 9; + a.push(((high << 4) | low) & 0xFF); + i++; + } + + return new Bytes(new js.lib.Uint8Array(a).buffer); + } + + public inline static function fastGet(b:BytesData, pos:Int):Int { // this requires that we have wrapped it with haxe.io.Bytes beforehand return untyped b.bytes[pos]; } - } diff --git a/std/js/_std/haxe/io/BytesBuffer.hx b/std/js/_std/haxe/io/BytesBuffer.hx index 50fb9d4e7b9..5945943dd6a 100644 --- a/std/js/_std/haxe/io/BytesBuffer.hx +++ b/std/js/_std/haxe/io/BytesBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,99 +19,109 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; +@:coreApi class BytesBuffer { + var buffer:js.lib.ArrayBuffer; + var view:js.lib.DataView; + var u8:js.lib.Uint8Array; + var pos:Int; + var size:Int; - var buffer : js.html.ArrayBuffer; - var view : js.html.DataView; - var u8 : js.html.Uint8Array; - var pos : Int; - var size : Int; - - public var length(get,never) : Int; + public var length(get, never):Int; public function new() { pos = 0; size = 0; } - inline function get_length() : Int { + inline function get_length():Int { return pos; } - public function addByte( byte : Int ) { - if( pos == size ) grow(1); + public function addByte(byte:Int):Void { + if (pos == size) + grow(1); view.setUint8(pos++, byte); } - public function add( src : Bytes ) { - if( pos + src.length > size ) grow(src.length); - if( size == 0 ) return; - var sub = new js.html.Uint8Array(@:privateAccess src.b.buffer, @:privateAccess src.b.byteOffset, src.length); + public function add(src:Bytes):Void { + if (pos + src.length > size) + grow(src.length); + if (size == 0) + return; + var sub = new js.lib.Uint8Array(@:privateAccess src.b.buffer, @:privateAccess src.b.byteOffset, src.length); u8.set(sub, pos); pos += src.length; } - public function addString( v : String ) { - add(Bytes.ofString(v)); + public function addString(v:String, ?encoding:Encoding):Void { + add(Bytes.ofString(v, encoding)); } - public function addInt32( v : Int ) { - if( pos + 4 > size ) grow(4); + public function addInt32(v:Int):Void { + if (pos + 4 > size) + grow(4); view.setInt32(pos, v, true); pos += 4; } - public function addInt64( v : haxe.Int64 ) { - if( pos + 8 > size ) grow(8); + public function addInt64(v:haxe.Int64):Void { + if (pos + 8 > size) + grow(8); view.setInt32(pos, v.low, true); view.setInt32(pos + 4, v.high, true); pos += 8; } - public function addFloat( v : Float ) { - if( pos + 4 > size ) grow(4); + public function addFloat(v:Float):Void { + if (pos + 4 > size) + grow(4); view.setFloat32(pos, v, true); pos += 4; } - public function addDouble( v : Float ) { - if( pos + 8 > size ) grow(8); + public function addDouble(v:Float):Void { + if (pos + 8 > size) + grow(8); view.setFloat64(pos, v, true); pos += 8; } - public function addBytes( src : Bytes, pos : Int, len : Int ) { - if( pos < 0 || len < 0 || pos + len > src.length ) throw Error.OutsideBounds; - if( this.pos + len > size ) grow(len); - if( size == 0 ) return; - var sub = new js.html.Uint8Array(@:privateAccess src.b.buffer, @:privateAccess src.b.byteOffset + pos, len); + public function addBytes(src:Bytes, pos:Int, len:Int):Void { + if (pos < 0 || len < 0 || pos + len > src.length) + throw Error.OutsideBounds; + if (this.pos + len > size) + grow(len); + if (size == 0) + return; + var sub = new js.lib.Uint8Array(@:privateAccess src.b.buffer, @:privateAccess src.b.byteOffset + pos, len); u8.set(sub, this.pos); this.pos += len; } - function grow( delta : Int ) { + function grow(delta:Int):Void { var req = pos + delta; var nsize = size == 0 ? 16 : size; - while( nsize < req ) + while (nsize < req) nsize = (nsize * 3) >> 1; - var nbuf = new js.html.ArrayBuffer(nsize); - var nu8 = new js.html.Uint8Array(nbuf); - if( size > 0 ) + var nbuf = new js.lib.ArrayBuffer(nsize); + var nu8 = new js.lib.Uint8Array(nbuf); + if (size > 0) nu8.set(u8); size = nsize; buffer = nbuf; u8 = nu8; - view = new js.html.DataView(buffer); + view = new js.lib.DataView(buffer); } - public function getBytes() : Bytes @:privateAccess { - if( size == 0 ) + public function getBytes():Bytes@:privateAccess { + if (size == 0) return haxe.io.Bytes.alloc(0); var b = new Bytes(buffer); b.length = pos; return b; } - } diff --git a/std/js/_std/haxe/io/Float32Array.hx b/std/js/_std/haxe/io/Float32Array.hx index fb065ef08d2..96ff0404981 100644 --- a/std/js/_std/haxe/io/Float32Array.hx +++ b/std/js/_std/haxe/io/Float32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,71 +19,70 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe.io; -#if !nodejs -import js.html.compat.Float32Array; -#end +package haxe.io; -typedef Float32ArrayData = js.html.Float32Array; +typedef Float32ArrayData = js.lib.Float32Array; @:coreApi abstract Float32Array(Float32ArrayData) { - public static inline var BYTES_PER_ELEMENT = 4; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) : Void { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int):Void { this = new Float32ArrayData(elements); } - inline function get_length() : Int { + inline function get_length():Int { return this.length; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : Float { + @:arrayAccess public inline function get(index:Int):Float { return this[index]; } - @:arrayAccess public inline function set( index : Int, value : Float ) : Float { + @:arrayAccess public inline function set(index:Int, value:Float):Float { return this[index] = value; } - public inline function sub( begin : Int, ?length : Int ) : Float32Array { - return fromData(this.subarray(begin, length == null ? this.length : begin+length)); + public inline function sub(begin:Int, ?length:Int):Float32Array { + return fromData(this.subarray(begin, length == null ? this.length : begin + length)); } - public inline function subarray( ?begin : Int, ?end : Int ) : Float32Array { + public inline function subarray(?begin:Int, ?end:Int):Float32Array { return fromData(this.subarray(begin, end)); } - public inline function getData() : Float32ArrayData { + public inline function getData():Float32ArrayData { return this; } - public inline static function fromData( d : Float32ArrayData ) : Float32Array { + public inline static function fromData(d:Float32ArrayData):Float32Array { return cast d; } - public static function fromArray( a : Array, pos : Int = 0, ?length : Int ) : Float32Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; - if( pos == 0 && length == a.length ) + public static function fromArray(a:Array, pos:Int = 0, ?length:Int):Float32Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; + if (pos == 0 && length == a.length) return fromData(new Float32ArrayData(a)); var i = new Float32Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos : Int = 0, ?length : Int ) : Float32Array { - if( length == null ) length = (bytes.length - bytePos) >> 2; + public static function fromBytes(bytes:haxe.io.Bytes, bytePos:Int = 0, ?length:Int):Float32Array { + if (length == null) + length = (bytes.length - bytePos) >> 2; return fromData(new Float32ArrayData(bytes.getData(), bytePos, length)); } } - diff --git a/std/js/_std/haxe/io/Float64Array.hx b/std/js/_std/haxe/io/Float64Array.hx index bf0fd36ba44..a363a43d657 100644 --- a/std/js/_std/haxe/io/Float64Array.hx +++ b/std/js/_std/haxe/io/Float64Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,71 +19,70 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package haxe.io; -#if !nodejs -import js.html.compat.Float64Array; -#end +package haxe.io; -typedef Float64ArrayData = js.html.Float64Array; +typedef Float64ArrayData = js.lib.Float64Array; @:coreApi abstract Float64Array(Float64ArrayData) { + public static inline var BYTES_PER_ELEMENT = 8; - public static inline var BYTES_PER_ELEMENT = 4; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; - public inline function new( elements : Int ) : Void { + public inline function new(elements:Int):Void { this = new Float64ArrayData(elements); } - inline function get_length() : Int { + inline function get_length():Int { return this.length; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : Float { + @:arrayAccess public inline function get(index:Int):Float { return this[index]; } - @:arrayAccess public inline function set( index : Int, value : Float ) : Float { + @:arrayAccess public inline function set(index:Int, value:Float):Float { return this[index] = value; } - public inline function sub( begin : Int, ?length : Int ) : Float64Array { - return fromData(this.subarray(begin, length == null ? this.length : begin+length)); + public inline function sub(begin:Int, ?length:Int):Float64Array { + return fromData(this.subarray(begin, length == null ? this.length : begin + length)); } - public inline function subarray( ?begin : Int, ?end : Int ) : Float64Array { + public inline function subarray(?begin:Int, ?end:Int):Float64Array { return fromData(this.subarray(begin, end)); } - public inline function getData() : Float64ArrayData { + public inline function getData():Float64ArrayData { return this; } - public static inline function fromData( d : Float64ArrayData ) : Float64Array { + public static inline function fromData(d:Float64ArrayData):Float64Array { return cast d; } - public static function fromArray( a : Array, pos : Int = 0, ?length : Int ) : Float64Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; - if( pos == 0 && length == a.length ) + public static function fromArray(a:Array, pos:Int = 0, ?length:Int):Float64Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; + if (pos == 0 && length == a.length) return fromData(new Float64ArrayData(a)); var i = new Float64Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos : Int = 0, ?length : Int ) : Float64Array { - if( length == null ) length = (bytes.length - bytePos) >> 3; + public static function fromBytes(bytes:haxe.io.Bytes, bytePos:Int = 0, ?length:Int):Float64Array { + if (length == null) + length = (bytes.length - bytePos) >> 3; return fromData(new Float64ArrayData(bytes.getData(), bytePos, length)); } } - diff --git a/std/js/_std/haxe/io/Int32Array.hx b/std/js/_std/haxe/io/Int32Array.hx index dc0f045ba4b..6a982c864d0 100644 --- a/std/js/_std/haxe/io/Int32Array.hx +++ b/std/js/_std/haxe/io/Int32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,68 +19,70 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; -typedef Int32ArrayData = js.html.Int32Array; +typedef Int32ArrayData = js.lib.Int32Array; @:coreApi abstract Int32Array(Int32ArrayData) { + public static inline var BYTES_PER_ELEMENT = 4; - public static inline var BYTES_PER_ELEMENT = 1; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; - public inline function new( elements : Int ) { - this = new Int32ArrayData(elements * BYTES_PER_ELEMENT); + public inline function new(elements:Int) { + this = new Int32ArrayData(elements); } - inline function get_length() : Int { + inline function get_length():Int { return this.length; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : Int { + @:arrayAccess public inline function get(index:Int):Int { return this[index]; } - @:arrayAccess public inline function set( index : Int, value : Int ) : Int { - return this[index] = value | 0; // necessary for html compat + @:arrayAccess public inline function set(index:Int, value:Int):Int { + return this[index] = value; } - public inline function sub( begin : Int, ?length : Int ) : Int32Array { - return fromData(this.subarray(begin, length == null ? this.length : begin+length)); + public inline function sub(begin:Int, ?length:Int):Int32Array { + return fromData(this.subarray(begin, length == null ? this.length : begin + length)); } - public inline function subarray( ?begin : Int, ?end : Int ) : Int32Array { + public inline function subarray(?begin:Int, ?end:Int):Int32Array { return fromData(this.subarray(begin, end)); } - public inline function getData() : Int32ArrayData { + public inline function getData():Int32ArrayData { return this; } - public static inline function fromData( d : Int32ArrayData ) : Int32Array { + public static inline function fromData(d:Int32ArrayData):Int32Array { return cast d; } - public static function fromArray( a : Array, pos : Int = 0, ?length : Int ) : Int32Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; - if( pos == 0 && length == a.length ) + public static function fromArray(a:Array, pos:Int = 0, ?length:Int):Int32Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; + if (pos == 0 && length == a.length) return fromData(new Int32ArrayData(a)); var i = new Int32Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos : Int = 0, ?length : Int ) : Int32Array { - if( length == null ) length = (bytes.length - bytePos) >> 2; + public static function fromBytes(bytes:haxe.io.Bytes, bytePos:Int = 0, ?length:Int):Int32Array { + if (length == null) + length = (bytes.length - bytePos) >> 2; return fromData(new Int32ArrayData(bytes.getData(), bytePos, length)); } - } - diff --git a/std/js/_std/haxe/io/UInt16Array.hx b/std/js/_std/haxe/io/UInt16Array.hx index 62eb8be3673..3d14faf7437 100644 --- a/std/js/_std/haxe/io/UInt16Array.hx +++ b/std/js/_std/haxe/io/UInt16Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,68 +19,70 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; -typedef UInt16ArrayData = js.html.Uint16Array; +typedef UInt16ArrayData = js.lib.Uint16Array; @:coreApi abstract UInt16Array(UInt16ArrayData) { - public static inline var BYTES_PER_ELEMENT = 2; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int) { this = new UInt16ArrayData(elements); } - inline function get_length() : Int { + inline function get_length():Int { return this.length; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : Int { + @:arrayAccess public inline function get(index:Int):Int { return this[index]; } - @:arrayAccess public inline function set( index : Int, value : Int ) : Int { - return this[index] = value & 0xFFFF; // &0xFFFF necessary for html compat + @:arrayAccess public inline function set(index:Int, value:Int):Int { + return this[index] = value; } - public inline function sub( begin : Int, ?length : Int ) : UInt16Array { - return fromData(this.subarray(begin, length == null ? this.length : begin+length)); + public inline function sub(begin:Int, ?length:Int):UInt16Array { + return fromData(this.subarray(begin, length == null ? this.length : begin + length)); } - public inline function subarray( ?begin : Int, ?end : Int ) : UInt16Array { + public inline function subarray(?begin:Int, ?end:Int):UInt16Array { return fromData(this.subarray(begin, end)); } - public inline function getData() : UInt16ArrayData { + public inline function getData():UInt16ArrayData { return this; } - public static inline function fromData( d : UInt16ArrayData ) : UInt16Array { + public static inline function fromData(d:UInt16ArrayData):UInt16Array { return cast d; } - public static function fromArray( a : Array, pos : Int = 0, ?length : Int ) : UInt16Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; - if( pos == 0 && length == a.length ) + public static function fromArray(a:Array, pos:Int = 0, ?length:Int):UInt16Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; + if (pos == 0 && length == a.length) return fromData(new UInt16ArrayData(a)); var i = new UInt16Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos : Int = 0, ?length : Int ) : UInt16Array { - if( length == null ) length = (bytes.length - bytePos) >> 1; + public static function fromBytes(bytes:haxe.io.Bytes, bytePos:Int = 0, ?length:Int):UInt16Array { + if (length == null) + length = (bytes.length - bytePos) >> 1; return fromData(new UInt16ArrayData(bytes.getData(), bytePos, length)); } - } - diff --git a/std/js/_std/haxe/io/UInt32Array.hx b/std/js/_std/haxe/io/UInt32Array.hx index 87c9a910a30..dde9ef19175 100644 --- a/std/js/_std/haxe/io/UInt32Array.hx +++ b/std/js/_std/haxe/io/UInt32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,68 +19,70 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; -typedef UInt32ArrayData = js.html.Uint32Array; +typedef UInt32ArrayData = js.lib.Uint32Array; @:coreApi abstract UInt32Array(UInt32ArrayData) { - public static inline var BYTES_PER_ELEMENT = 4; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int) { this = new UInt32ArrayData(elements); } - inline function get_length() : Int { + inline function get_length():Int { return this.length; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : UInt { + @:arrayAccess public inline function get(index:Int):UInt { return this[index]; } - @:arrayAccess public inline function set( index : Int, value : UInt ) : UInt { - return this[index] = value | 0; // necessary for html compat + @:arrayAccess public inline function set(index:Int, value:UInt):UInt { + return this[index] = value; } - public inline function sub( begin : Int, ?length : Int ) : UInt32Array { - return fromData(this.subarray(begin, length == null ? this.length : begin+length)); + public inline function sub(begin:Int, ?length:Int):UInt32Array { + return fromData(this.subarray(begin, length == null ? this.length : begin + length)); } - public inline function subarray( ?begin : Int, ?end : Int ) : UInt32Array { + public inline function subarray(?begin:Int, ?end:Int):UInt32Array { return fromData(this.subarray(begin, end)); } - public inline function getData() : UInt32ArrayData { + public inline function getData():UInt32ArrayData { return this; } - public static inline function fromData( d : UInt32ArrayData ) : UInt32Array { + public static inline function fromData(d:UInt32ArrayData):UInt32Array { return cast d; } - public static function fromArray( a : Array, pos : Int = 0, ?length : Int ) : UInt32Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; - if( pos == 0 && length == a.length ) + public static function fromArray(a:Array, pos:Int = 0, ?length:Int):UInt32Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; + if (pos == 0 && length == a.length) return fromData(new UInt32ArrayData(a)); var i = new UInt32Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos : Int = 0, ?length : Int ) : UInt32Array { - if( length == null ) length = (bytes.length - bytePos) >> 2; + public static function fromBytes(bytes:haxe.io.Bytes, bytePos:Int = 0, ?length:Int):UInt32Array { + if (length == null) + length = (bytes.length - bytePos) >> 2; return fromData(new UInt32ArrayData(bytes.getData(), bytePos, length)); } - } - diff --git a/std/js/_std/haxe/io/UInt8Array.hx b/std/js/_std/haxe/io/UInt8Array.hx index cc781fc2af1..1503ff76c17 100644 --- a/std/js/_std/haxe/io/UInt8Array.hx +++ b/std/js/_std/haxe/io/UInt8Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,68 +19,70 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + package haxe.io; -typedef UInt8ArrayData = js.html.Uint8Array; +typedef UInt8ArrayData = js.lib.Uint8Array; @:coreApi abstract UInt8Array(UInt8ArrayData) { - public static inline var BYTES_PER_ELEMENT = 1; - public var length(get,never) : Int; - public var view(get,never) : ArrayBufferView; - public inline function new( elements : Int ) { + public var length(get, never):Int; + public var view(get, never):ArrayBufferView; + + public inline function new(elements:Int) { this = new UInt8ArrayData(elements); } - inline function get_length() : Int { + inline function get_length():Int { return this.length; } - public inline function get_view() : ArrayBufferView { + public inline function get_view():ArrayBufferView { return ArrayBufferView.fromData(this); } - @:arrayAccess public inline function get( index : Int ) : Int { + @:arrayAccess public inline function get(index:Int):Int { return this[index]; } - @:arrayAccess public inline function set( index : Int, value : Int ) : Int { - return this[index] = value & 0xFF; // &0xFF necessary for html compat + @:arrayAccess public inline function set(index:Int, value:Int):Int { + return this[index] = value; } - public inline function sub( begin : Int, ?length : Int ) : UInt8Array { - return fromData(this.subarray(begin, length == null ? this.length : begin+length)); + public inline function sub(begin:Int, ?length:Int):UInt8Array { + return fromData(this.subarray(begin, length == null ? this.length : begin + length)); } - public inline function subarray( ?begin : Int, ?end : Int ) : UInt8Array { + public inline function subarray(?begin:Int, ?end:Int):UInt8Array { return fromData(this.subarray(begin, end)); } - public inline function getData() : UInt8ArrayData { + public inline function getData():UInt8ArrayData { return this; } - public static inline function fromData( d : UInt8ArrayData ) : UInt8Array { + public static inline function fromData(d:UInt8ArrayData):UInt8Array { return cast d; } - public static function fromArray( a : Array, pos : Int = 0, ?length : Int ) : UInt8Array { - if( length == null ) length = a.length - pos; - if( pos < 0 || length < 0 || pos + length > a.length ) throw Error.OutsideBounds; - if( pos == 0 && length == a.length ) + public static function fromArray(a:Array, pos:Int = 0, ?length:Int):UInt8Array { + if (length == null) + length = a.length - pos; + if (pos < 0 || length < 0 || pos + length > a.length) + throw Error.OutsideBounds; + if (pos == 0 && length == a.length) return fromData(new UInt8ArrayData(a)); var i = new UInt8Array(a.length); - for( idx in 0...length ) + for (idx in 0...length) i[idx] = a[idx + pos]; return i; } - public static function fromBytes( bytes : haxe.io.Bytes, bytePos : Int = 0, ?length : Int ) : UInt8Array { - if( length == null ) length = bytes.length - bytePos; + public static function fromBytes(bytes:haxe.io.Bytes, bytePos:Int = 0, ?length:Int):UInt8Array { + if (length == null) + length = bytes.length - bytePos; return fromData(new UInt8ArrayData(bytes.getData(), bytePos, length)); } - } - diff --git a/std/js/html/AbortController.hx b/std/js/html/AbortController.hx new file mode 100644 index 00000000000..86e60a23ac1 --- /dev/null +++ b/std/js/html/AbortController.hx @@ -0,0 +1,49 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\AbortController.webidl. Do not edit! + +package js.html; + +/** + The `AbortController` interface represents a controller object that allows you to abort one or more DOM requests as and when desired. + + Documentation [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AbortController$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("AbortController") +extern class AbortController { + + /** + Returns a `AbortSignal` object instance, which can be used to communicate with/abort a DOM request. + **/ + var signal(default,null) : AbortSignal; + + /** @throws DOMError */ + function new() : Void; + + /** + Aborts a DOM request before it has completed. This is able to abort fetch requests, consumption of any response `Body`, and streams. + **/ + function abort() : Void; +} \ No newline at end of file diff --git a/std/js/html/AbortSignal.hx b/std/js/html/AbortSignal.hx new file mode 100644 index 00000000000..d7cadb477bb --- /dev/null +++ b/std/js/html/AbortSignal.hx @@ -0,0 +1,47 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\AbortSignal.webidl. Do not edit! + +package js.html; + +/** + The `AbortSignal` interface represents a signal object that allows you to communicate with a DOM request (such as a Fetch) and abort it if required via an `AbortController` object. + + Documentation [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("AbortSignal") +extern class AbortSignal extends EventTarget { + + /** + A `Boolean` that indicates whether the request(s) the signal is communicating with is/are aborted (`true`) or not (`false`). + **/ + var aborted(default,null) : Bool; + + /** + Invoked when an `abort_(dom_abort_api)` event fires, i.e. when the DOM request(s) the signal is communicating with is/are aborted. + **/ + var onabort : haxe.Constraints.Function; + +} \ No newline at end of file diff --git a/std/js/html/AddEventListenerOptions.hx b/std/js/html/AddEventListenerOptions.hx new file mode 100644 index 00000000000..edabb701f0f --- /dev/null +++ b/std/js/html/AddEventListenerOptions.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\EventTarget.webidl. Do not edit! + +package js.html; + +typedef AddEventListenerOptions = EventListenerOptions & { + var ?once : Bool; + var ?passive : Bool; +} \ No newline at end of file diff --git a/std/js/html/AlignSetting.hx b/std/js/html/AlignSetting.hx index 8f7ed57742b..b21c8f414c3 100644 --- a/std/js/html/AlignSetting.hx +++ b/std/js/html/AlignSetting.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,10 +24,9 @@ package js.html; -@:enum abstract AlignSetting(String) -{ +enum abstract AlignSetting(String) { var START = "start"; - var MIDDLE = "middle"; + var CENTER = "center"; var END = "end"; var LEFT = "left"; var RIGHT = "right"; diff --git a/std/js/html/AnchorElement.hx b/std/js/html/AnchorElement.hx index 951c3115f07..4903c410916 100644 --- a/std/js/html/AnchorElement.hx +++ b/std/js/html/AnchorElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,15 +25,14 @@ package js.html; /** - The `HTMLAnchorElement` interface represents hyperlink elements and provides special properties and methods (beyond those of the regular `HTMLElement` object interface they also have available to them by inheritance) for manipulating the layout and presentation of such elements. + The `HTMLAnchorElement` interface represents hyperlink elements and provides special properties and methods (beyond those of the regular `HTMLElement` object interface that they inherit from) for manipulating the layout and presentation of such elements. Documentation [HTMLAnchorElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("HTMLAnchorElement") -extern class AnchorElement extends Element -{ +extern class AnchorElement extends Element { /** Is a `DOMString` that reflects the `target` HTML attribute, indicating where to display the linked resource. @@ -41,7 +40,7 @@ extern class AnchorElement extends Element var target : String; /** - Is a `DOMString` indicating that the linked resource is intended to be downloaded rather than displayed in the browser. The value represent the proposed name of the file. If the name is not a valid filename of the underlying OS, browser will adapt it. The value is a URL with a scheme like `http:`, `file:`, `data:` or even `blob:` (created with `URL.createObjectURL`). + Is a `DOMString` indicating that the linked resource is intended to be downloaded rather than displayed in the browser. The value represent the proposed name of the file. If the name is not a valid filename of the underlying OS, browser will adapt it. **/ var download : String; var ping : String; @@ -51,6 +50,11 @@ extern class AnchorElement extends Element **/ var rel : String; + /** + Is a `DOMString` that reflects the `referrerpolicy` HTML attribute indicating which referrer to use. + **/ + var referrerPolicy : String; + /** Returns a `DOMTokenList` that reflects the `rel` HTML attribute, as a list of tokens. **/ @@ -88,6 +92,8 @@ extern class AnchorElement extends Element /** Is a `DOMString` representing that the `rev` HTML attribute, specifying the relationship of the link object to the target object. + Note: Currently the W3C HTML 5.2 spec states that `rev` is no longer obsolete, whereas the WHATWG living standard still has it labeled obsolete. Until this discrepancy is resolved, you should still assume it is obsolete. + **/ var rev : String; diff --git a/std/js/html/Animation.hx b/std/js/html/Animation.hx index ca489992a89..fbaab563fb4 100644 --- a/std/js/html/Animation.hx +++ b/std/js/html/Animation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,6 +24,8 @@ package js.html; +import js.lib.Promise; + /** The `Animation` interface of the Web Animations API represents a single animation player and provides playback controls and a timeline for an animation node or source. @@ -32,93 +34,102 @@ package js.html; @see **/ @:native("Animation") -extern class Animation extends EventTarget -{ - +extern class Animation extends EventTarget { + /** Gets and sets the `String` used to identify the animation. **/ var id : String; - + /** Gets and sets the `AnimationEffectReadOnly` associated with this animation. This will usually be a `KeyframeEffect` object. **/ - var effect(default,null) : AnimationEffectReadOnly; - + var effect : AnimationEffect; + /** Gets or sets the `AnimationTimeline` associated with this animation. **/ - var timeline(default,null) : AnimationTimeline; - + var timeline : AnimationTimeline; + /** Gets or sets the scheduled time when an animation's playback should begin. **/ var startTime : Float; - + /** The current time value of the animation in milliseconds, whether running or paused. If the animation lacks a `AnimationTimeline`, is inactive or hasn't been played yet, its value is `null`. **/ var currentTime : Float; - + /** Gets or sets the playback rate of the animation. **/ var playbackRate : Float; - + /** Returns an enumerated value describing the playback state of an animation. **/ var playState(default,null) : AnimationPlayState; - + + /** + Indicates whether the animation is currently waiting for an asynchronous operation such as initiating playback or pausing a running animation. + **/ + var pending(default,null) : Bool; + /** Returns the current ready Promise for this animation. **/ var ready(default,null) : Promise; - + /** Returns the current finished Promise for this animation. **/ var finished(default,null) : Promise; - + /** Gets and sets the event handler for the `finish` event. **/ var onfinish : haxe.Constraints.Function; - + /** Gets and sets the event handler for the `cancel` event. **/ var oncancel : haxe.Constraints.Function; - + /** @throws DOMError */ - function new( ?effect : KeyframeEffectReadOnly, ?timeline : AnimationTimeline ) : Void; - + function new( ?effect : AnimationEffect, ?timeline : AnimationTimeline ) : Void; + /** Clears all `KeyframeEffect` caused by this animation and aborts its playback. **/ function cancel() : Void; - /** @throws DOMError */ - + /** Seeks either end of an animation, depending on whether the animation is playing or reversing. + @throws DOMError **/ function finish() : Void; - /** @throws DOMError */ - + /** Starts or resumes playing of an animation, or begins the animation again if it previously finished. + @throws DOMError **/ function play() : Void; - /** @throws DOMError */ - + /** Suspends playing of an animation. + @throws DOMError **/ function pause() : Void; - /** @throws DOMError */ - + + /** + Sets the speed of an animation after first synchronizing its playback position. + **/ + function updatePlaybackRate( playbackRate : Float ) : Void; + /** Reverses playback direction, stopping at the start of the animation. If the animation is finished or unplayed, it will play from end to beginning. + @throws DOMError **/ function reverse() : Void; } \ No newline at end of file diff --git a/std/js/html/ApplicationCache.hx b/std/js/html/AnimationEffect.hx similarity index 53% rename from std/js/html/ApplicationCache.hx rename to std/js/html/AnimationEffect.hx index 1267649b4be..fb28106ef9e 100644 --- a/std/js/html/ApplicationCache.hx +++ b/std/js/html/AnimationEffect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,32 +20,21 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\OfflineResourceList.webidl. Do not edit! +// This file is generated from mozilla\AnimationEffect.webidl. Do not edit! package js.html; -@:native("ApplicationCache") -extern class ApplicationCache extends EventTarget implements ArrayAccess -{ - static inline var UNCACHED : Int = 0; - static inline var IDLE : Int = 1; - static inline var CHECKING : Int = 2; - static inline var DOWNLOADING : Int = 3; - static inline var UPDATEREADY : Int = 4; - static inline var OBSOLETE : Int = 5; - - var status(default,null) : Int; - var onchecking : haxe.Constraints.Function; - var onerror : haxe.Constraints.Function; - var onnoupdate : haxe.Constraints.Function; - var ondownloading : haxe.Constraints.Function; - var onprogress : haxe.Constraints.Function; - var onupdateready : haxe.Constraints.Function; - var oncached : haxe.Constraints.Function; - var onobsolete : haxe.Constraints.Function; - - /** @throws DOMError */ - function update() : Void; +/** + The `AnimationEffect` interface of the Web Animations API defines current and future animation effects like `KeyframeEffect`, which can be passed to `Animation` objects for playing, and `KeyframeEffectReadOnly` (which is used by CSS Animations and Transitions). + + Documentation [AnimationEffect](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffect) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffect$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("AnimationEffect") +extern class AnimationEffect { + function getTiming() : EffectTiming; + function getComputedTiming() : ComputedEffectTiming; /** @throws DOMError */ - function swapCache() : Void; + function updateTiming( ?timing : OptionalEffectTiming ) : Void; } \ No newline at end of file diff --git a/std/js/html/AnimationEffectTimingReadOnly.hx b/std/js/html/AnimationEffectTimingReadOnly.hx deleted file mode 100644 index c278f13ecde..00000000000 --- a/std/js/html/AnimationEffectTimingReadOnly.hx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -// This file is generated from mozilla\AnimationEffectTimingReadOnly.webidl. Do not edit! - -package js.html; - -/** - The `AnimationEffectTimingReadOnly` interface of the Web Animations API is comprised of timing properties. - - Documentation [AnimationEffectTimingReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectTimingReadOnly) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectTimingReadOnly$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). - - @see -**/ -@:native("AnimationEffectTimingReadOnly") -extern class AnimationEffectTimingReadOnly -{ - - /** - The number of milliseconds to delay the start of the animation. Defaults to `0`. - **/ - var delay(default,null) : Float; - - /** - The number of milliseconds to delay after the end of an animation. This is primarily of use when sequencing animations based on the end time of another animation. Defaults to `0`. - **/ - var endDelay(default,null) : Float; - - /** - Dictates whether the animation's effects should be reflected by the element(s) state prior to playing (`backwards`), retained after the animation has completed playing (`forwards`), or `both`. Defaults to `none`. - **/ - var fill(default,null) : FillMode; - - /** - A number representing which repetition the animation begins at and its progress through it. - **/ - var iterationStart(default,null) : Float; - - /** - The number of times the animation should repeat. Defaults to `1`, and can also take a value of infinity to make it repeat infinitely. - **/ - var iterations(default,null) : Float; - - /** - The number of milliseconds each iteration of the animation takes to complete. Defaults to `0`. - **/ - var duration(default,null) : haxe.extern.EitherType; - - /** - Whether the animation runs forwards (`normal`), backwards (`reverse`), switches direction after each iteration (`alternate`), or runs backwards and switches direction after each iteration (`alternate-reverse`). Defaults to `normal`. - **/ - var direction(default,null) : PlaybackDirection; - - /** - The rate of the animation's change over time. Accepts the pre-defined values `linear`, `ease`, `ease-in`, `ease-out`, and `ease-in-out`, or a custom cubic-bezier value like `cubic-bezier(0.42, 0, 0.58, 1)`. Defaults to `linear`. - **/ - var easing(default,null) : String; - -} \ No newline at end of file diff --git a/std/js/html/AnimationEvent.hx b/std/js/html/AnimationEvent.hx index 3d5dcc76d2d..7d3e83f5cba 100644 --- a/std/js/html/AnimationEvent.hx +++ b/std/js/html/AnimationEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("AnimationEvent") -extern class AnimationEvent extends Event -{ +extern class AnimationEvent extends Event { /** Is a `DOMString` containing the value of the `animation-name` CSS property associated with the transition. diff --git a/std/js/html/AnimationEventInit.hx b/std/js/html/AnimationEventInit.hx index 25c284e09d1..107ffe58553 100644 --- a/std/js/html/AnimationEventInit.hx +++ b/std/js/html/AnimationEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,10 +24,8 @@ package js.html; -typedef AnimationEventInit = -{ - > EventInit, - @:optional var animationName : String; - @:optional var elapsedTime : Float; - @:optional var pseudoElement : String; +typedef AnimationEventInit = EventInit & { + var ?animationName : String; + var ?elapsedTime : Float; + var ?pseudoElement : String; } \ No newline at end of file diff --git a/std/js/html/CSSUnknownRule.hx b/std/js/html/AnimationFilter.hx similarity index 86% rename from std/js/html/CSSUnknownRule.hx rename to std/js/html/AnimationFilter.hx index f093ea419d5..471cec222df 100644 --- a/std/js/html/CSSUnknownRule.hx +++ b/std/js/html/AnimationFilter.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,11 +20,10 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl. Do not edit! +// This file is generated from mozilla\Animatable.webidl. Do not edit! package js.html; -@:native("CSSUnknownRule") -extern class CSSUnknownRule extends CSSRule -{ +typedef AnimationFilter = { + var ?subtree : Bool; } \ No newline at end of file diff --git a/std/js/html/AnimationPlayState.hx b/std/js/html/AnimationPlayState.hx index 243a7b97047..46b995c88e6 100644 --- a/std/js/html/AnimationPlayState.hx +++ b/std/js/html/AnimationPlayState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,10 +24,8 @@ package js.html; -@:enum abstract AnimationPlayState(String) -{ +enum abstract AnimationPlayState(String) { var IDLE = "idle"; - var PENDING = "pending"; var RUNNING = "running"; var PAUSED = "paused"; var FINISHED = "finished"; diff --git a/std/js/html/AnimationEffectTiming.hx b/std/js/html/AnimationPlaybackEvent.hx similarity index 59% rename from std/js/html/AnimationEffectTiming.hx rename to std/js/html/AnimationPlaybackEvent.hx index 2a29b116142..0541c2191a6 100644 --- a/std/js/html/AnimationEffectTiming.hx +++ b/std/js/html/AnimationPlaybackEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,18 +20,22 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\AnimationEffectTiming.webidl. Do not edit! +// This file is generated from mozilla\AnimationPlaybackEvent.webidl. Do not edit! package js.html; /** - The `AnimationEffectTiming` interface of the Web Animations API is comprised of timing properties. It is returned by the `timing` attribute of a `KeyframeEffect`. + The AnimationPlaybackEvent interface of the Web Animations API represents animation events. - Documentation [AnimationEffectTiming](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectTiming) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectTiming$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + Documentation [AnimationPlaybackEvent](https://developer.mozilla.org/en-US/docs/Web/API/AnimationPlaybackEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnimationPlaybackEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). - @see + @see **/ -@:native("AnimationEffectTiming") -extern class AnimationEffectTiming extends AnimationEffectTimingReadOnly -{ +@:native("AnimationPlaybackEvent") +extern class AnimationPlaybackEvent extends Event { + var currentTime(default,null) : Float; + var timelineTime(default,null) : Float; + + /** @throws DOMError */ + function new( type : String, ?eventInitDict : AnimationPlaybackEventInit ) : Void; } \ No newline at end of file diff --git a/std/js/html/AnimationPlaybackEventInit.hx b/std/js/html/AnimationPlaybackEventInit.hx new file mode 100644 index 00000000000..91fd2f1c3a0 --- /dev/null +++ b/std/js/html/AnimationPlaybackEventInit.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\AnimationPlaybackEvent.webidl. Do not edit! + +package js.html; + +typedef AnimationPlaybackEventInit = EventInit & { + var ?currentTime : Float; + var ?timelineTime : Float; +} \ No newline at end of file diff --git a/std/js/html/AnimationTimeline.hx b/std/js/html/AnimationTimeline.hx index a52c2622f58..c7b7e634810 100644 --- a/std/js/html/AnimationTimeline.hx +++ b/std/js/html/AnimationTimeline.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("AnimationTimeline") -extern class AnimationTimeline -{ +extern class AnimationTimeline { /** Returns the time value in milliseconds for this timeline or `null` if this timeline is inactive. diff --git a/std/js/html/AreaElement.hx b/std/js/html/AreaElement.hx index 8885f48c74e..569cce41b80 100644 --- a/std/js/html/AreaElement.hx +++ b/std/js/html/AreaElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLAreaElement") -extern class AreaElement extends Element -{ +extern class AreaElement extends Element { /** Is a `DOMString` that reflects the `alt` HTML attribute, containing alternative text for the element. @@ -66,6 +65,11 @@ extern class AreaElement extends Element **/ var rel : String; + /** + Is a `DOMString` that reflects the `referrerpolicy` HTML attribute indicating which referrer to use when fetching the linked resource. + **/ + var referrerPolicy : String; + /** Returns a `DOMTokenList` that reflects the `rel` HTML attribute, indicating relationships of the current document to the linked resource, as a list of tokens. **/ diff --git a/std/js/html/ArrayBuffer.hx b/std/js/html/ArrayBuffer.hx index 9ee2b246d1f..f526251fdf1 100644 --- a/std/js/html/ArrayBuffer.hx +++ b/std/js/html/ArrayBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,20 +20,6 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl. Do not edit! - package js.html; -// Explicitly include the compatibility class -import js.html.compat.ArrayBuffer; - -@:native("ArrayBuffer") -extern class ArrayBuffer -{ - static function isView( value : Dynamic ) : Bool; - var byteLength(default,null) : Int; - - /** @throws DOMError */ - function new( length : Int ) : Void; - function slice( begin : Int, ?end : Int ) : ArrayBuffer; -} \ No newline at end of file +@:deprecated typedef ArrayBuffer = js.lib.ArrayBuffer; diff --git a/std/js/html/ArrayBufferView.hx b/std/js/html/ArrayBufferView.hx index 51eacc96d00..6f7dfb77199 100644 --- a/std/js/html/ArrayBufferView.hx +++ b/std/js/html/ArrayBufferView.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,22 +20,6 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl. Do not edit! - package js.html; -/** - `ArrayBufferView` is a helper type representing any of the following JavaScript `TypedArray` types: - - Documentation [ArrayBufferView](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). - - @see -**/ -@:native("ArrayBufferView") -extern class ArrayBufferView -{ - var buffer(default,null) : ArrayBuffer; - var byteOffset(default,null) : Int; - var byteLength(default,null) : Int; - -} \ No newline at end of file +@:deprecated typedef ArrayBufferView = js.lib.ArrayBufferView; diff --git a/std/js/html/AssignedNodesOptions.hx b/std/js/html/AssignedNodesOptions.hx new file mode 100644 index 00000000000..076f6371cab --- /dev/null +++ b/std/js/html/AssignedNodesOptions.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\HTMLSlotElement.webidl. Do not edit! + +package js.html; + +typedef AssignedNodesOptions = { + var ?flatten : Bool; +} \ No newline at end of file diff --git a/std/js/html/Attr.hx b/std/js/html/Attr.hx index 75c944cddd2..39c4a918e33 100644 --- a/std/js/html/Attr.hx +++ b/std/js/html/Attr.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,11 +32,51 @@ package js.html; @see **/ @:native("Attr") -extern class Attr extends Node -{ +extern class Attr extends Node { + + /** + A `DOMString` representing the local part of the qualified name of the attribute. + **/ + var localName(default,null) : String; + + /** + The attribute's value. + **/ var value : String; + + /** + The attribute's name. + **/ var name(default,null) : String; + + /** + A `DOMString` representing the namespace URI of the attribute, or `null` if there is no namespace. + **/ + var namespaceURI(default,null) : String; + + /** + A `DOMString` representing the namespace prefix of the attribute, or `null` if no prefix is specified. + **/ + var prefix(default,null) : String; + + /** + This property always returns `true`. Originally, it returned `true `if the attribute was explicitly specified in the source code or by a script, and `false` if its value came from the default one defined in the document's DTD. + **/ var specified(default,null) : Bool; + + /** + + The element holding the attribute. + + + Note: DOM Level 4 removed this property. The assumption was that since you get an `Attr` object from an `Element`, you should already know the associated element. + + As that doesn't hold true in cases like `Attr` objects being returned by `Document.evaluate`, the DOM Living Standard reintroduced the property. + + Gecko outputs a deprecation note starting from Gecko 7.0 `7.0`. This note was removed again in Gecko 49.0 `49.0`. + + + **/ var ownerElement(default,null) : Element; } \ No newline at end of file diff --git a/std/js/html/Audio.hx b/std/js/html/Audio.hx index 75f98f5b553..5c065fd3953 100644 --- a/std/js/html/Audio.hx +++ b/std/js/html/Audio.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,8 +25,7 @@ package js.html; @:native("Audio") -extern class Audio extends AudioElement -{ +extern class Audio extends AudioElement { /** @throws DOMError */ function new( ?src : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/AudioElement.hx b/std/js/html/AudioElement.hx index c9aaf1f54ef..0c684ff8953 100644 --- a/std/js/html/AudioElement.hx +++ b/std/js/html/AudioElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,6 +32,5 @@ package js.html; @see **/ @:native("HTMLAudioElement") -extern class AudioElement extends MediaElement -{ +extern class AudioElement extends MediaElement { } \ No newline at end of file diff --git a/std/js/html/AudioStreamTrack.hx b/std/js/html/AudioStreamTrack.hx index 0aecfe183e3..cbd5348ac99 100644 --- a/std/js/html/AudioStreamTrack.hx +++ b/std/js/html/AudioStreamTrack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,5 @@ package js.html; @:native("AudioStreamTrack") -extern class AudioStreamTrack extends MediaStreamTrack -{ +extern class AudioStreamTrack extends MediaStreamTrack { } \ No newline at end of file diff --git a/std/js/html/AudioTrack.hx b/std/js/html/AudioTrack.hx index f421d647525..13dfd601083 100644 --- a/std/js/html/AudioTrack.hx +++ b/std/js/html/AudioTrack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,13 +24,39 @@ package js.html; +/** + The `AudioTrack` interface represents a single audio track from one of the HTML media elements, `audio` or `video`. + + Documentation [AudioTrack](https://developer.mozilla.org/en-US/docs/Web/API/AudioTrack) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioTrack$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioTrack") -extern class AudioTrack -{ +extern class AudioTrack { + + /** + A `DOMString` which uniquely identifies the track within the media. This ID can be used to locate a specific track within an audio track list by calling `AudioTrackList.getTrackById()`. The ID can also be used as the fragment part of the URL if the media supports seeking by media fragment per the Media Fragments URI specification. + **/ var id(default,null) : String; + + /** + A `DOMString` specifying the category into which the track falls. For example, the main audio track would have a `kind` of `"main"`. + **/ var kind(default,null) : String; + + /** + A `DOMString` providing a human-readable label for the track. For example, an audio commentary track for a movie might have a `label` of `"Commentary with director John Q. Public and actors John Doe and Jane Eod."` This string is empty if no label is provided. + **/ var label(default,null) : String; + + /** + A `DOMString` specifying the audio track's primary language, or an empty string if unknown. The language is specified as a BCP 47 ({{RFC(5646)}}) language code, such as `"en-US"` or `"pt-BR"`. + **/ var language(default,null) : String; + + /** + A Boolean value which controls whether or not the audio track's sound is enabled. Setting this value to `false` mutes the track's audio. + **/ var enabled : Bool; } \ No newline at end of file diff --git a/std/js/html/AudioTrackList.hx b/std/js/html/AudioTrackList.hx index 1bd14237a01..b8fc4affbdd 100644 --- a/std/js/html/AudioTrackList.hx +++ b/std/js/html/AudioTrackList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,9 +24,19 @@ package js.html; +/** + The `AudioTrackList` interface is used to represent a list of the audio tracks contained within a given HTML media element, with each track represented by a separate `AudioTrack` object in the list. + + Documentation [AudioTrackList](https://developer.mozilla.org/en-US/docs/Web/API/AudioTrackList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioTrackList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioTrackList") -extern class AudioTrackList extends EventTarget implements ArrayAccess -{ +extern class AudioTrackList extends EventTarget implements ArrayAccess { + + /** + The number of tracks in the list. + **/ var length(default,null) : Int; var onchange : haxe.Constraints.Function; var onaddtrack : haxe.Constraints.Function; diff --git a/std/js/html/AutoKeyword.hx b/std/js/html/AutoKeyword.hx new file mode 100644 index 00000000000..c9f7135c651 --- /dev/null +++ b/std/js/html/AutoKeyword.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\VTTCue.webidl. Do not edit! + +package js.html; + +enum abstract AutoKeyword(String) { + var AUTO = "auto"; +} \ No newline at end of file diff --git a/std/js/html/BRElement.hx b/std/js/html/BRElement.hx index 90407625914..e987052cc4b 100644 --- a/std/js/html/BRElement.hx +++ b/std/js/html/BRElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLBRElement") -extern class BRElement extends Element -{ +extern class BRElement extends Element { /** Is a `DOMString` indicating the flow of text around floating objects. diff --git a/std/js/html/BarProp.hx b/std/js/html/BarProp.hx index ed75b50e071..9ba95a6b714 100644 --- a/std/js/html/BarProp.hx +++ b/std/js/html/BarProp.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,8 +25,7 @@ package js.html; @:native("BarProp") -extern class BarProp -{ +extern class BarProp { var visible : Bool; } \ No newline at end of file diff --git a/std/js/html/BaseElement.hx b/std/js/html/BaseElement.hx index 02c63de3ca0..bb4118a7ab7 100644 --- a/std/js/html/BaseElement.hx +++ b/std/js/html/BaseElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLBaseElement") -extern class BaseElement extends Element -{ +extern class BaseElement extends Element { /** Is a `DOMString` that reflects the `href` HTML attribute, containing a base URL for relative URLs in the document. diff --git a/std/js/html/BatteryManager.hx b/std/js/html/BatteryManager.hx index 82a7d2cf578..e554d5d40d5 100644 --- a/std/js/html/BatteryManager.hx +++ b/std/js/html/BatteryManager.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("BatteryManager") -extern class BatteryManager extends EventTarget -{ +extern class BatteryManager extends EventTarget { /** A Boolean value indicating whether or not the battery is currently being charged. diff --git a/std/js/html/BeforeUnloadEvent.hx b/std/js/html/BeforeUnloadEvent.hx index 6492726313d..463dc369576 100644 --- a/std/js/html/BeforeUnloadEvent.hx +++ b/std/js/html/BeforeUnloadEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,5 @@ package js.html; @see **/ @:native("BeforeUnloadEvent") -extern class BeforeUnloadEvent extends Event -{ - var returnValue : String; - +extern class BeforeUnloadEvent extends Event { } \ No newline at end of file diff --git a/std/js/html/BinaryType.hx b/std/js/html/BinaryType.hx index 337e2c92c19..fac33af9c55 100644 --- a/std/js/html/BinaryType.hx +++ b/std/js/html/BinaryType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -@:enum abstract BinaryType(String) -{ +enum abstract BinaryType(String) { var BLOB = "blob"; var ARRAYBUFFER = "arraybuffer"; } \ No newline at end of file diff --git a/std/js/html/Blob.hx b/std/js/html/Blob.hx index 543cc4d9b05..4d75860c0eb 100644 --- a/std/js/html/Blob.hx +++ b/std/js/html/Blob.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -46,12 +46,11 @@ extern class Blob var type(default,null) : String; /** @throws DOMError */ - @:overload( function() : Void {} ) - function new( blobParts : Array>>>, ?options : BlobPropertyBag ) : Void; - /** @throws DOMError */ + function new( ?blobParts : Array>>>, ?options : BlobPropertyBag ) : Void; /** Returns a new `Blob` object containing the data in the specified range of bytes of the source `Blob`. + @throws DOMError **/ - function slice( ?start : Int, ?end : Int, ?contentType : String = "" ) : Blob; -} \ No newline at end of file + function slice( ?start : Int, ?end : Int, ?contentType : String ) : Blob; +} diff --git a/std/js/html/BlobEvent.hx b/std/js/html/BlobEvent.hx new file mode 100644 index 00000000000..ae0ec582242 --- /dev/null +++ b/std/js/html/BlobEvent.hx @@ -0,0 +1,44 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\BlobEvent.webidl. Do not edit! + +package js.html; + +/** + The `BlobEvent` interface represents events associated with a `Blob`. These blobs are typically, but not necessarily,  associated with media content. + + Documentation [BlobEvent](https://developer.mozilla.org/en-US/docs/Web/API/BlobEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/BlobEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("BlobEvent") +extern class BlobEvent extends Event { + + /** + A `Blob` representing the data associated with the event. The event was fired on the `EventTarget` because of something happening on that specific `Blob`. + **/ + var data(default,null) : Blob; + + /** @throws DOMError */ + function new( type : String, ?eventInitDict : BlobEventInit ) : Void; +} \ No newline at end of file diff --git a/std/js/html/BlobEventInit.hx b/std/js/html/BlobEventInit.hx new file mode 100644 index 00000000000..fea08ce7be4 --- /dev/null +++ b/std/js/html/BlobEventInit.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\BlobEvent.webidl. Do not edit! + +package js.html; + +typedef BlobEventInit = EventInit & { + var ?data : Blob; +} \ No newline at end of file diff --git a/std/js/html/BlobPropertyBag.hx b/std/js/html/BlobPropertyBag.hx index b1111dd3a3e..f9083df3574 100644 --- a/std/js/html/BlobPropertyBag.hx +++ b/std/js/html/BlobPropertyBag.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -typedef BlobPropertyBag = -{ - @:optional var endings : Dynamic/*MISSING EndingTypes*/; - @:optional var type : String; +typedef BlobPropertyBag = { + var ?endings : EndingTypes; + var ?type : String; } \ No newline at end of file diff --git a/std/js/html/BodyElement.hx b/std/js/html/BodyElement.hx index e38b050f68c..6d01e708f1d 100644 --- a/std/js/html/BodyElement.hx +++ b/std/js/html/BodyElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLBodyElement") -extern class BodyElement extends Element -{ +extern class BodyElement extends Element { /** Is a `DOMString` that represents the foreground color of text. @@ -66,10 +65,11 @@ extern class BodyElement extends Element var background : String; var onafterprint : haxe.Constraints.Function; var onbeforeprint : haxe.Constraints.Function; - var onbeforeunload : Event -> String; + var onbeforeunload : Event -> Null; var onhashchange : haxe.Constraints.Function; var onlanguagechange : haxe.Constraints.Function; var onmessage : haxe.Constraints.Function; + var onmessageerror : haxe.Constraints.Function; var onoffline : haxe.Constraints.Function; var ononline : haxe.Constraints.Function; var onpagehide : haxe.Constraints.Function; diff --git a/std/js/html/BroadcastChannel.hx b/std/js/html/BroadcastChannel.hx index c9cac75bdbf..fedc0edd759 100644 --- a/std/js/html/BroadcastChannel.hx +++ b/std/js/html/BroadcastChannel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("BroadcastChannel") -extern class BroadcastChannel extends EventTarget -{ +extern class BroadcastChannel extends EventTarget { /** Returns a `DOMString`, the name of the channel. @@ -41,16 +40,21 @@ extern class BroadcastChannel extends EventTarget var name(default,null) : String; /** - Is an `EventHandler` property that specifies the function to execute when a `message` event is fired on this object. + An `EventHandler` property that specifies the function to execute when a `message` event is fired on this object. **/ var onmessage : haxe.Constraints.Function; + /** + An `EventHandler` called when a `MessageEvent` of type `MessageError` is fired—that is, when it receives a message that cannot be deserialized. + **/ + var onmessageerror : haxe.Constraints.Function; + /** @throws DOMError */ function new( channel : String ) : Void; - /** @throws DOMError */ /** Sends the message, of any type of object, to each `BroadcastChannel` object listening to the same channel. + @throws DOMError **/ function postMessage( message : Dynamic ) : Void; diff --git a/std/js/html/ButtonElement.hx b/std/js/html/ButtonElement.hx index 61524fb2a52..85859da9acc 100644 --- a/std/js/html/ButtonElement.hx +++ b/std/js/html/ButtonElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLButtonElement") -extern class ButtonElement extends Element -{ +extern class ButtonElement extends Element { /** Is a `Boolean` indicating whether or not the control should have input focus when the page loads, unless the user overrides it, for example by typing in a different control. Only one form-associated element in a document can have this attribute specified. @@ -48,7 +47,7 @@ extern class ButtonElement extends Element /** Is a `HTMLFormElement` reflecting the form that this button is associated with. If the button is a descendant of a form element, then this attribute is the ID of that form element. - If the button is not a descendant of a form element, then the attribute can be the ID of any form element in the same document it is related to, or the `null` value if none matches. + If the button is not a descendant of a form element, then the attribute can be the ID of any form element in the same document it is related to, or the `null` value if none matches. **/ var form(default,null) : FormElement; @@ -56,6 +55,10 @@ extern class ButtonElement extends Element Is a `DOMString` reflecting the URI of a resource that processes information submitted by the button. If specified, this attribute overrides the `action` attribute of the `form` element that owns this element. **/ var formAction : String; + + /** + Is a `DOMString` reflecting the type of content that is used to submit the form to the server. If specified, this attribute overrides the `enctype` attribute of the `form` element that owns this element. + **/ var formEnctype : String; /** @@ -80,13 +83,13 @@ extern class ButtonElement extends Element /** Is a `DOMString` indicating the behavior of the button. This is an enumerated attribute with the following possible values: - - `"submit"`: The button submits the form. This is the default value if the attribute is not specified, {{HTMLVersionInline(5)}} or if it is dynamically changed to an empty or invalid value. - `"reset"`: The button resets the form. - `"button"`: The button does nothing. - `"menu"`: The button displays a menu. (experimental) - - + + `"submit"`: The button submits the form. This is the default value if the attribute is not specified, {{HTMLVersionInline(5)}} or if it is dynamically changed to an empty or invalid value. + `"reset"`: The button resets the form. + `"button"`: The button does nothing. + `"menu"`: The button displays a menu. (experimental) + + **/ var type : String; @@ -110,6 +113,12 @@ extern class ButtonElement extends Element **/ var validationMessage(default,null) : String; + /** + Is a `NodeList` that represents a list of `label` elements that are labels for this button. + **/ + var labels(default,null) : NodeList; + function checkValidity() : Bool; + function reportValidity() : Bool; function setCustomValidity( error : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/CDATASection.hx b/std/js/html/CDATASection.hx index 481d0c7b852..30ee463ddc3 100644 --- a/std/js/html/CDATASection.hx +++ b/std/js/html/CDATASection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,13 +25,12 @@ package js.html; /** - The `CDATASection` interface represents a CDATA section that can be used within XML to include extended portions of unescaped text, such that the symbols and & do not need escaping as they normally do within XML when used as text. + The `CDATASection` interface represents a CDATA section that can be used within XML to include extended portions of unescaped text. The symbols `` and `&` don’t need escaping as they normally do when inside a CDATA section. Documentation [CDATASection](https://developer.mozilla.org/en-US/docs/Web/API/CDATASection) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CDATASection$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("CDATASection") -extern class CDATASection extends Text -{ +extern class CDATASection extends Text { } \ No newline at end of file diff --git a/std/js/html/CSS.hx b/std/js/html/CSS.hx index 8796002430c..ced1466e884 100644 --- a/std/js/html/CSS.hx +++ b/std/js/html/CSS.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,10 +32,17 @@ package js.html; @see **/ @:native("CSS") -extern class CSS -{ - /** @throws DOMError */ +extern class CSS { + + /** + Returns a `Boolean` indicating if the pair property-value, or the condition, given in parameter is supported. + @throws DOMError + **/ @:overload( function( property : String, value : String ) : Bool {} ) static function supports( conditionText : String ) : Bool; + + /** + Can be used to escape a string mostly for use as part of a CSS selector. + **/ static function escape( ident : String ) : String; } \ No newline at end of file diff --git a/std/js/html/CSSAnimation.hx b/std/js/html/CSSAnimation.hx index 1d9d90fcebe..7a5e9a64928 100644 --- a/std/js/html/CSSAnimation.hx +++ b/std/js/html/CSSAnimation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,8 +25,7 @@ package js.html; @:native("CSSAnimation") -extern class CSSAnimation extends Animation -{ +extern class CSSAnimation extends Animation { var animationName(default,null) : String; } \ No newline at end of file diff --git a/std/js/html/ElementRegistrationOptions.hx b/std/js/html/CSSBoxType.hx similarity index 82% rename from std/js/html/ElementRegistrationOptions.hx rename to std/js/html/CSSBoxType.hx index e522066f091..9fde554f6be 100644 --- a/std/js/html/ElementRegistrationOptions.hx +++ b/std/js/html/CSSBoxType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,13 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\WebComponents.webidl. Do not edit! +// This file is generated from mozilla\GeometryUtils.webidl. Do not edit! package js.html; -typedef ElementRegistrationOptions = -{ - @:native("extends") - @:optional var extends_ : String; - @:optional var prototype : Dynamic; +enum abstract CSSBoxType(String) { + var MARGIN = "margin"; + var BORDER = "border"; + var PADDING = "padding"; + var CONTENT = "content"; } \ No newline at end of file diff --git a/std/js/html/CSSConditionRule.hx b/std/js/html/CSSConditionRule.hx new file mode 100644 index 00000000000..cf7622d2940 --- /dev/null +++ b/std/js/html/CSSConditionRule.hx @@ -0,0 +1,42 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CSSConditionRule.webidl. Do not edit! + +package js.html; + +/** + An object implementing the `CSSConditionRule` interface represents a single condition CSS at-rule, which consists of a condition and a statement block. It is a child of `CSSGroupingRule`. + + Documentation [CSSConditionRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSConditionRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSConditionRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("CSSConditionRule") +extern class CSSConditionRule extends CSSGroupingRule { + + /** + Represents the text of the condition of the rule. + **/ + var conditionText : String; + +} \ No newline at end of file diff --git a/std/js/html/CSSCounterStyleRule.hx b/std/js/html/CSSCounterStyleRule.hx new file mode 100644 index 00000000000..c55e3202522 --- /dev/null +++ b/std/js/html/CSSCounterStyleRule.hx @@ -0,0 +1,92 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CSSCounterStyleRule.webidl. Do not edit! + +package js.html; + +/** + The `CSSCounterStyleRule` interface represents an `@counter-style` at-rule. + + Documentation [CSSCounterStyleRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSCounterStyleRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSCounterStyleRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("CSSCounterStyleRule") +extern class CSSCounterStyleRule extends CSSRule { + + /** + Is a `DOMString` object that contains the serialization of the `counter-style-name` defined for the associated rule. + **/ + var name : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/system` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var system : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/symbols` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var symbols : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/additive-symbols` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var additiveSymbols : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/negative` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var negative : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/prefix` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var prefix : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/suffix` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var suffix : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/range` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var range : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/pad` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var pad : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/speak-as` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var speakAs : String; + + /** + Is a `DOMString` object that contains the serialization of the `@counter-style/fallback` descriptor defined for the associated rule. If the descriptor was not specified in the associated rule, the attribute returns an empty string. + **/ + var fallback : String; + +} \ No newline at end of file diff --git a/std/js/html/CSSFontFaceRule.hx b/std/js/html/CSSFontFaceRule.hx index 68b154b1cf8..489b8883b96 100644 --- a/std/js/html/CSSFontFaceRule.hx +++ b/std/js/html/CSSFontFaceRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,13 +20,12 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl. Do not edit! +// This file is generated from mozilla\CSSFontFaceRule.webidl. Do not edit! package js.html; @:native("CSSFontFaceRule") -extern class CSSFontFaceRule extends CSSRule -{ +extern class CSSFontFaceRule extends CSSRule { var style(default,null) : CSSStyleDeclaration; } \ No newline at end of file diff --git a/std/js/html/CSSFontFeatureValuesRule.hx b/std/js/html/CSSFontFeatureValuesRule.hx new file mode 100644 index 00000000000..967e00b7614 --- /dev/null +++ b/std/js/html/CSSFontFeatureValuesRule.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CSSFontFeatureValuesRule.webidl. Do not edit! + +package js.html; + +@:native("CSSFontFeatureValuesRule") +extern class CSSFontFeatureValuesRule extends CSSRule { + var fontFamily : String; + var valueText : String; + +} \ No newline at end of file diff --git a/std/js/html/CSSGroupingRule.hx b/std/js/html/CSSGroupingRule.hx new file mode 100644 index 00000000000..f1db4da5a81 --- /dev/null +++ b/std/js/html/CSSGroupingRule.hx @@ -0,0 +1,42 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CSSGroupingRule.webidl. Do not edit! + +package js.html; + +/** + An object implementing the `CSSGroupingRule` interface represents any CSS at-rule that contains other rules nested within it. + + Documentation [CSSGroupingRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSGroupingRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSGroupingRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("CSSGroupingRule") +extern class CSSGroupingRule extends CSSRule { + var cssRules(default,null) : CSSRuleList; + + /** @throws DOMError */ + function insertRule( rule : String, index : Int = 0 ) : Int; + /** @throws DOMError */ + function deleteRule( index : Int ) : Void; +} \ No newline at end of file diff --git a/std/js/html/CSSImportRule.hx b/std/js/html/CSSImportRule.hx index 217e4afe641..ce003b88fb2 100644 --- a/std/js/html/CSSImportRule.hx +++ b/std/js/html/CSSImportRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,13 +20,12 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl. Do not edit! +// This file is generated from mozilla\CSSImportRule.webidl. Do not edit! package js.html; @:native("CSSImportRule") -extern class CSSImportRule extends CSSRule -{ +extern class CSSImportRule extends CSSRule { var href(default,null) : String; var media(default,null) : MediaList; var styleSheet(default,null) : CSSStyleSheet; diff --git a/std/js/html/Rect.hx b/std/js/html/CSSKeyframeRule.hx similarity index 55% rename from std/js/html/Rect.hx rename to std/js/html/CSSKeyframeRule.hx index b928fbd8017..fa1573629b8 100644 --- a/std/js/html/Rect.hx +++ b/std/js/html/CSSKeyframeRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,16 +20,20 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\Rect.webidl. Do not edit! +// This file is generated from mozilla\CSSKeyframeRule.webidl. Do not edit! package js.html; -@:native("Rect") -extern class Rect -{ - var top(default,null) : CSSPrimitiveValue; - var right(default,null) : CSSPrimitiveValue; - var bottom(default,null) : CSSPrimitiveValue; - var left(default,null) : CSSPrimitiveValue; +/** + The `CSSKeyframeRule` interface describes an object representing a set of style for a given keyframe. It corresponds to the contains of a single keyframe of a `@keyframes` at-rule. It implements the `CSSRule` interface with a type value of `8` (`CSSRule.KEYFRAME_RULE`). + + Documentation [CSSKeyframeRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSKeyframeRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSKeyframeRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("CSSKeyframeRule") +extern class CSSKeyframeRule extends CSSRule { + var keyText : String; + var style(default,null) : CSSStyleDeclaration; } \ No newline at end of file diff --git a/std/js/html/CSSKeyframesRule.hx b/std/js/html/CSSKeyframesRule.hx new file mode 100644 index 00000000000..94b02ac0b66 --- /dev/null +++ b/std/js/html/CSSKeyframesRule.hx @@ -0,0 +1,62 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CSSKeyframesRule.webidl. Do not edit! + +package js.html; + +/** + The `CSSKeyframesRule` interface describes an object representing a complete set of keyframes for a CSS animation. It corresponds to the contains of a whole `@keyframes` at-rule. It implements the `CSSRule` interface with a type value of `7` (`CSSRule.KEYFRAMES_RULE`). + + Documentation [CSSKeyframesRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSKeyframesRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSKeyframesRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("CSSKeyframesRule") +extern class CSSKeyframesRule extends CSSRule { + + /** + Represents the name of the animation, used by the `animation-name` property. + **/ + var name : String; + + /** + Returns a `CSSRuleList` of the CSS rules in the media rule. + **/ + var cssRules(default,null) : CSSRuleList; + + + /** + Inserts a new keyframe rule into the current CSSKeyframesRule. The parameter is a `DOMString` containing a keyframe in the same format as an entry of a `@keyframes` at-rule. If it contains more than one keyframe rule, a `DOMException` with a `SYNTAX_ERR` is thrown. + **/ + function appendRule( rule : String ) : Void; + + /** + Deletes a keyframe rule from the current CSSKeyframesRule. The parameter is the index of the keyframe to be deleted, expressed as a `DOMString` resolving as a number between `0%` and `100%`. + **/ + function deleteRule( select : String ) : Void; + + /** + Returns a keyframe rule corresponding to the given key. The key is a `DOMString` containing an index of the keyframe to be returned, resolving to a percentage between `0%` and `100%`. If no such keyframe exists, `findRule` returns `null`. + **/ + function findRule( select : String ) : CSSKeyframeRule; +} \ No newline at end of file diff --git a/std/js/html/CSSMediaRule.hx b/std/js/html/CSSMediaRule.hx index 99ff0843590..3b43e3a629b 100644 --- a/std/js/html/CSSMediaRule.hx +++ b/std/js/html/CSSMediaRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl. Do not edit! +// This file is generated from mozilla\CSSMediaRule.webidl. Do not edit! package js.html; @@ -32,15 +32,11 @@ package js.html; @see **/ @:native("CSSMediaRule") -extern class CSSMediaRule extends CSSRule -{ +extern class CSSMediaRule extends CSSConditionRule { /** Specifies a `MediaList` representing the intended destination medium for style information. **/ var media(default,null) : MediaList; - var cssRules(default,null) : CSSRuleList; - function insertRule( rule : String, index : Int ) : Int; - function deleteRule( index : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/CSSMozDocumentRule.hx b/std/js/html/CSSMozDocumentRule.hx new file mode 100644 index 00000000000..8d786d5ecdd --- /dev/null +++ b/std/js/html/CSSMozDocumentRule.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CSSMozDocumentRule.webidl. Do not edit! + +package js.html; + +@:native("CSSMozDocumentRule") +extern class CSSMozDocumentRule extends CSSConditionRule { +} \ No newline at end of file diff --git a/std/js/html/CSSNamespaceRule.hx b/std/js/html/CSSNamespaceRule.hx new file mode 100644 index 00000000000..4d8c293bb9c --- /dev/null +++ b/std/js/html/CSSNamespaceRule.hx @@ -0,0 +1,47 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CSSNamespaceRule.webidl. Do not edit! + +package js.html; + +/** + The `CSSNamespaceRule` interface describes an object representing a single CSS `@namespace` at-rule. It implements the `CSSRule` interface, with a type value of `10` (`CSSRule.NAMESPACE_RULE`). + + Documentation [CSSNamespaceRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSNamespaceRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSNamespaceRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("CSSNamespaceRule") +extern class CSSNamespaceRule extends CSSRule { + + /** + Returns a `DOMString` containing the text of the URI of the given namespace. + **/ + var namespaceURI(default,null) : String; + + /** + Returns a `DOMString` with the name of the prefix associated to this namespace. If there is no such prefix, returns  `null`. + **/ + var prefix(default,null) : String; + +} \ No newline at end of file diff --git a/std/js/html/CSSPageRule.hx b/std/js/html/CSSPageRule.hx index 082ec61e3df..1352d8b05eb 100644 --- a/std/js/html/CSSPageRule.hx +++ b/std/js/html/CSSPageRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl. Do not edit! +// This file is generated from mozilla\CSSPageRule.webidl. Do not edit! package js.html; @@ -32,13 +32,7 @@ package js.html; @see **/ @:native("CSSPageRule") -extern class CSSPageRule extends CSSRule -{ - - /** - Represents the text of the page selector associated with the at-rule. - **/ - var selectorText : String; +extern class CSSPageRule extends CSSRule { /** Returns the declaration block associated with the at-rule. diff --git a/std/js/html/CSSPrimitiveValue.hx b/std/js/html/CSSPrimitiveValue.hx deleted file mode 100644 index 7eaf4db7510..00000000000 --- a/std/js/html/CSSPrimitiveValue.hx +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -// This file is generated from mozilla\CSSPrimitiveValue.webidl. Do not edit! - -package js.html; - -/** - The `CSSPrimitiveValue` interface derives from the `CSSValue` interface and represents the current computed value of a CSS property. - - Documentation [CSSPrimitiveValue](https://developer.mozilla.org/en-US/docs/Web/API/CSSPrimitiveValue) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSPrimitiveValue$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). - - @see -**/ -@:native("CSSPrimitiveValue") -extern class CSSPrimitiveValue extends CSSValue -{ - static inline var CSS_UNKNOWN : Int = 0; - static inline var CSS_NUMBER : Int = 1; - static inline var CSS_PERCENTAGE : Int = 2; - static inline var CSS_EMS : Int = 3; - static inline var CSS_EXS : Int = 4; - static inline var CSS_PX : Int = 5; - static inline var CSS_CM : Int = 6; - static inline var CSS_MM : Int = 7; - static inline var CSS_IN : Int = 8; - static inline var CSS_PT : Int = 9; - static inline var CSS_PC : Int = 10; - static inline var CSS_DEG : Int = 11; - static inline var CSS_RAD : Int = 12; - static inline var CSS_GRAD : Int = 13; - static inline var CSS_MS : Int = 14; - static inline var CSS_S : Int = 15; - static inline var CSS_HZ : Int = 16; - static inline var CSS_KHZ : Int = 17; - static inline var CSS_DIMENSION : Int = 18; - static inline var CSS_STRING : Int = 19; - static inline var CSS_URI : Int = 20; - static inline var CSS_IDENT : Int = 21; - static inline var CSS_ATTR : Int = 22; - static inline var CSS_COUNTER : Int = 23; - static inline var CSS_RECT : Int = 24; - static inline var CSS_RGBCOLOR : Int = 25; - - - /** - An unsigned short representing the type of the value. Possible values are: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ConstantDescription
CSS_ATTRThe value is an attr() function. The value can be obtained by using the getStringValue() method.
CSS_CMThe value is a length in centimeters. The value can be obtained by using the getFloatValue() method.
CSS_COUNTERThe value is a counter or counters function. The value can be obtained by using the getCounterValue() method.
CSS_DEGThe value is an angle in degrees. The value can be obtained by using the getFloatValue() method.
CSS_DIMENSIONThe value is a number with an unknown dimension. The value can be obtained by using the getFloatValue() method.
CSS_EMSThe value is a length in em units. The value can be obtained by using the getFloatValue() method.
CSS_EXSThe value is a length in ex units. The value can be obtained by using the getFloatValue() method.
CSS_GRADThe value is an angle in grads. The value can be obtained by using the getFloatValue() method.
CSS_HZThe value is a frequency in Hertz. The value can be obtained by using the getFloatValue method.
CSS_IDENTThe value is an identifier. The value can be obtained by using the getStringValue() method.
CSS_INThe value is a length in inches. The value can be obtained by using the getFloatValue() method.
CSS_KHZThe value is a frequency in Kilohertz. The value can be obtained by using the getFloatValue() method.
CSS_MMThe value is a length in millimeters. The value can be obtained by using the getFloatValue() method.
CSS_MSThe value is a time in milliseconds. The value can be obtained by using the getFloatValue() method.
CSS_NUMBERThe value is a simple number. The value can be obtained by using the getFloatValue() method.
CSS_PCThe value is a length in picas. The value can be obtained by using the getFloatValue() method.
CSS_PERCENTAGEThe value is a percentage. The value can be obtained by using the getFloatValue() method.
CSS_PTThe value is a length in points. The value can be obtained by using the getFloatValue() method.
CSS_PXThe value is a length in pixels. The value can be obtained by using the getFloatValue() method.
CSS_RADThe value is an angle in radians. The value can be obtained by using the getFloatValue() method.
CSS_RECTThe value is a shape function. The value can be obtained by using the getRectValue() method.
CSS_RGBCOLORThe value is an color. The value can be obtained by using the getRGBColorValue() method.
CSS_SThe value is a time in seconds. The value can be obtained by using the getFloatValue() method.
CSS_STRINGThe value is a string. The value can be obtained by using the getStringValue() method.
CSS_UNKNOWNThe value is not a recognized CSS2 value. The value can only be obtained by using the CSSValue.cssText attribute.
CSS_URIThe value is a uri. The value can be obtained by using the getStringValue() method.
- - **/ - var primitiveType(default,null) : Int; - - /** @throws DOMError */ - - /** - A method to set the float value with a specified unit. If the property attached with this value can not accept the specified unit or the float value, the value will be unchanged and a `DOMException` will be raised. - **/ - function setFloatValue( unitType : Int, floatValue : Float ) : Void; - /** @throws DOMError */ - - /** - This method is used to get a float value in a specified unit. If this CSS value doesn't contain a float value or can't be converted into the specified unit, a `DOMException` is raised. - **/ - function getFloatValue( unitType : Int ) : Float; - /** @throws DOMError */ - - /** - A method to set the string value with the specified unit. If the property attached to this value can't accept the specified unit or the string value, the value will be unchanged and a `DOMException` will be raised. - **/ - function setStringValue( stringType : Int, stringValue : String ) : Void; - /** @throws DOMError */ - - /** - This method is used to get the string value. If the CSS value doesn't contain a string value, a `DOMException` is raised. - **/ - function getStringValue() : String; - /** @throws DOMError */ - - /** - This method is used to get the counter value. If this CSS value doesn't contain a counter value, a `DOMException` is raised. Modification to the corresponding style property can be achieved using the `Counter` interface. - **/ - function getCounterValue() : Dynamic/*MISSING Counter*/; - /** @throws DOMError */ - - /** - This method is used to get the Rect value. If this CSS value doesn't contain a rect value, a `DOMException` is raised. Modification to the corresponding style property can be achieved using the `Rect` interface. - **/ - function getRectValue() : Rect; - /** @throws DOMError */ - - /** - This method is used to get the RGB color. If this CSS value doesn't contain a RGB color value, a `DOMException` is raised. Modification to the corresponding style property can be achieved using the `RGBColor` interface. - **/ - function getRGBColorValue() : RGBColor; -} \ No newline at end of file diff --git a/std/js/html/CSSPseudoElement.hx b/std/js/html/CSSPseudoElement.hx index 5a72edc0592..0ac3c8ea81f 100644 --- a/std/js/html/CSSPseudoElement.hx +++ b/std/js/html/CSSPseudoElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,12 +25,12 @@ package js.html; @:native("CSSPseudoElement") -extern class CSSPseudoElement -{ +extern class CSSPseudoElement { var type(default,null) : String; var parentElement(default,null) : Element; /** @throws DOMError */ - function animate( frames : Dynamic, ?options : haxe.extern.EitherType ) : Animation; - function getAnimations() : Array; + @:overload( function( keyframes : Dynamic, ?options : KeyframeAnimationOptions) : Animation {} ) + function animate( keyframes : Dynamic, ?options : Float ) : Animation; + function getAnimations( ?filter : AnimationFilter ) : Array; } \ No newline at end of file diff --git a/std/js/html/CSSRule.hx b/std/js/html/CSSRule.hx index fefc8aab81d..acd7e888538 100644 --- a/std/js/html/CSSRule.hx +++ b/std/js/html/CSSRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl. Do not edit! +// This file is generated from mozilla\CSSRule.webidl. Do not edit! package js.html; @@ -32,19 +32,23 @@ package js.html; @see **/ @:native("CSSRule") -extern class CSSRule -{ - static inline var UNKNOWN_RULE : Int = 0; +extern class CSSRule { static inline var STYLE_RULE : Int = 1; static inline var CHARSET_RULE : Int = 2; static inline var IMPORT_RULE : Int = 3; static inline var MEDIA_RULE : Int = 4; static inline var FONT_FACE_RULE : Int = 5; static inline var PAGE_RULE : Int = 6; + static inline var NAMESPACE_RULE : Int = 10; + static inline var KEYFRAMES_RULE : Int = 7; + static inline var KEYFRAME_RULE : Int = 8; + static inline var COUNTER_STYLE_RULE : Int = 11; + static inline var SUPPORTS_RULE : Int = 12; + static inline var FONT_FEATURE_VALUES_RULE : Int = 14; var type(default,null) : Int; var cssText : String; - var parentStyleSheet(default,null) : CSSStyleSheet; var parentRule(default,null) : CSSRule; + var parentStyleSheet(default,null) : CSSStyleSheet; } \ No newline at end of file diff --git a/std/js/html/CSSRuleList.hx b/std/js/html/CSSRuleList.hx index 9f77b36af0d..78a6f47700d 100644 --- a/std/js/html/CSSRuleList.hx +++ b/std/js/html/CSSRuleList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("CSSRuleList") -extern class CSSRuleList implements ArrayAccess -{ +extern class CSSRuleList implements ArrayAccess { var length(default,null) : Int; function item( index : Int ) : CSSRule; diff --git a/std/js/html/CSSStyleDeclaration.hx b/std/js/html/CSSStyleDeclaration.hx index b44b68bdcb9..22a1cc071aa 100644 --- a/std/js/html/CSSStyleDeclaration.hx +++ b/std/js/html/CSSStyleDeclaration.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("CSSStyleDeclaration") -extern class CSSStyleDeclaration implements ArrayAccess -{ +extern class CSSStyleDeclaration implements ArrayAccess { var cssText : String; var length(default,null) : Int; var parentRule(default,null) : CSSRule; @@ -78,6 +77,8 @@ extern class CSSStyleDeclaration implements ArrayAccess var background :String; /** Shorthand for the "background-attachment" CSS property. */ var backgroundAttachment :String; + /** Shorthand for the "background-blend-mode" CSS property. */ + var backgroundBlendMode :String; /** Shorthand for the "background-clip" CSS property. */ var backgroundClip :String; /** Shorthand for the "background-color" CSS property. */ @@ -88,8 +89,16 @@ extern class CSSStyleDeclaration implements ArrayAccess var backgroundOrigin :String; /** Shorthand for the "background-position" CSS property. */ var backgroundPosition :String; + /** Shorthand for the "background-position-x" CSS property. */ + var backgroundPositionX :String; + /** Shorthand for the "background-position-y" CSS property. */ + var backgroundPositionY :String; /** Shorthand for the "background-repeat" CSS property. */ var backgroundRepeat :String; + /** Shorthand for the "background-repeat-x" CSS property. */ + var backgroundRepeatX :String; + /** Shorthand for the "background-repeat-y" CSS property. */ + var backgroundRepeatY :String; /** Shorthand for the "background-size" CSS property. */ var backgroundSize :String; /** Shorthand for the "baseline-shift" CSS property. */ @@ -98,6 +107,8 @@ extern class CSSStyleDeclaration implements ArrayAccess var binding :String; /** Shorthand for the "bleed" CSS property. */ var bleed :String; + /** Shorthand for the "block-size" CSS property. */ + var blockSize :String; /** Shorthand for the "bookmark-label" CSS property. */ var bookmarkLabel :String; /** Shorthand for the "bookmark-level" CSS property. */ @@ -106,6 +117,22 @@ extern class CSSStyleDeclaration implements ArrayAccess var bookmarkState :String; /** Shorthand for the "border" CSS property. */ var border :String; + /** Shorthand for the "border-block-end" CSS property. */ + var borderBlockEnd :String; + /** Shorthand for the "border-block-end-color" CSS property. */ + var borderBlockEndColor :String; + /** Shorthand for the "border-block-end-style" CSS property. */ + var borderBlockEndStyle :String; + /** Shorthand for the "border-block-end-width" CSS property. */ + var borderBlockEndWidth :String; + /** Shorthand for the "border-block-start" CSS property. */ + var borderBlockStart :String; + /** Shorthand for the "border-block-start-color" CSS property. */ + var borderBlockStartColor :String; + /** Shorthand for the "border-block-start-style" CSS property. */ + var borderBlockStartStyle :String; + /** Shorthand for the "border-block-start-width" CSS property. */ + var borderBlockStartWidth :String; /** Shorthand for the "border-bottom" CSS property. */ var borderBottom :String; /** Shorthand for the "border-bottom-color" CSS property. */ @@ -134,6 +161,22 @@ extern class CSSStyleDeclaration implements ArrayAccess var borderImageSource :String; /** Shorthand for the "border-image-width" CSS property. */ var borderImageWidth :String; + /** Shorthand for the "border-inline-end" CSS property. */ + var borderInlineEnd :String; + /** Shorthand for the "border-inline-end-color" CSS property. */ + var borderInlineEndColor :String; + /** Shorthand for the "border-inline-end-style" CSS property. */ + var borderInlineEndStyle :String; + /** Shorthand for the "border-inline-end-width" CSS property. */ + var borderInlineEndWidth :String; + /** Shorthand for the "border-inline-start" CSS property. */ + var borderInlineStart :String; + /** Shorthand for the "border-inline-start-color" CSS property. */ + var borderInlineStartColor :String; + /** Shorthand for the "border-inline-start-style" CSS property. */ + var borderInlineStartStyle :String; + /** Shorthand for the "border-inline-start-width" CSS property. */ + var borderInlineStartWidth :String; /** Shorthand for the "border-left" CSS property. */ var borderLeft :String; /** Shorthand for the "border-left-color" CSS property. */ @@ -188,8 +231,12 @@ extern class CSSStyleDeclaration implements ArrayAccess var breakBefore :String; /** Shorthand for the "break-inside" CSS property. */ var breakInside :String; + /** Shorthand for the "buffered-rendering" CSS property. */ + var bufferedRendering :String; /** Shorthand for the "caption-side" CSS property. */ var captionSide :String; + /** Shorthand for the "caret-color" CSS property. */ + var caretColor :String; /** Shorthand for the "chains" CSS property. */ var chains :String; /** Shorthand for the "clear" CSS property. */ @@ -202,8 +249,14 @@ extern class CSSStyleDeclaration implements ArrayAccess var clipRule :String; /** Shorthand for the "color" CSS property. */ var color :String; + /** Shorthand for the "color-adjust" CSS property. */ + var colorAdjust :String; + /** Shorthand for the "color-interpolation" CSS property. */ + var colorInterpolation :String; /** Shorthand for the "color-interpolation-filters" CSS property. */ var colorInterpolationFilters :String; + /** Shorthand for the "color-rendering" CSS property. */ + var colorRendering :String; /** Shorthand for the "column-count" CSS property. */ var columnCount :String; /** Shorthand for the "column-fill" CSS property. */ @@ -236,6 +289,8 @@ extern class CSSStyleDeclaration implements ArrayAccess var counterSet :String; /** Shorthand for the "crop" CSS property. */ var crop :String; + /** Shorthand for the "css-float" CSS property. */ + var cssFloat :String; /** Shorthand for the "cue" CSS property. */ var cue :String; /** Shorthand for the "cue-after" CSS property. */ @@ -244,6 +299,12 @@ extern class CSSStyleDeclaration implements ArrayAccess var cueBefore :String; /** Shorthand for the "cursor" CSS property. */ var cursor :String; + /** Shorthand for the "cx" CSS property. */ + var cx :String; + /** Shorthand for the "cy" CSS property. */ + var cy :String; + /** Shorthand for the "d" CSS property. */ + var d :String; /** Shorthand for the "direction" CSS property. */ var direction :String; /** Shorthand for the "display" CSS property. */ @@ -260,6 +321,12 @@ extern class CSSStyleDeclaration implements ArrayAccess var elevation :String; /** Shorthand for the "empty-cells" CSS property. */ var emptyCells :String; + /** Shorthand for the "fill" CSS property. */ + var fill :String; + /** Shorthand for the "fill-opacity" CSS property. */ + var fillOpacity :String; + /** Shorthand for the "fill-rule" CSS property. */ + var fillRule :String; /** Shorthand for the "filter" CSS property. */ var filter :String; /** Shorthand for the "flex" CSS property. */ @@ -290,6 +357,8 @@ extern class CSSStyleDeclaration implements ArrayAccess var flowInto :String; /** Shorthand for the "font" CSS property. */ var font :String; + /** Shorthand for the "font-display" CSS property. */ + var fontDisplay :String; /** Shorthand for the "font-family" CSS property. */ var fontFamily :String; /** Shorthand for the "font-feature-settings" CSS property. */ @@ -298,6 +367,8 @@ extern class CSSStyleDeclaration implements ArrayAccess var fontKerning :String; /** Shorthand for the "font-language-override" CSS property. */ var fontLanguageOverride :String; + /** Shorthand for the "font-optical-sizing" CSS property. */ + var fontOpticalSizing :String; /** Shorthand for the "font-size" CSS property. */ var fontSize :String; /** Shorthand for the "font-size-adjust" CSS property. */ @@ -322,8 +393,12 @@ extern class CSSStyleDeclaration implements ArrayAccess var fontVariantNumeric :String; /** Shorthand for the "font-variant-position" CSS property. */ var fontVariantPosition :String; + /** Shorthand for the "font-variation-settings" CSS property. */ + var fontVariationSettings :String; /** Shorthand for the "font-weight" CSS property. */ var fontWeight :String; + /** Shorthand for the "gap" CSS property. */ + var gap :String; /** Shorthand for the "grid" CSS property. */ var grid :String; /** Shorthand for the "grid-area" CSS property. */ @@ -338,12 +413,18 @@ extern class CSSStyleDeclaration implements ArrayAccess var gridColumn :String; /** Shorthand for the "grid-column-end" CSS property. */ var gridColumnEnd :String; + /** Shorthand for the "grid-column-gap" CSS property. */ + var gridColumnGap :String; /** Shorthand for the "grid-column-start" CSS property. */ var gridColumnStart :String; + /** Shorthand for the "grid-gap" CSS property. */ + var gridGap :String; /** Shorthand for the "grid-row" CSS property. */ var gridRow :String; /** Shorthand for the "grid-row-end" CSS property. */ var gridRowEnd :String; + /** Shorthand for the "grid-row-gap" CSS property. */ + var gridRowGap :String; /** Shorthand for the "grid-row-start" CSS property. */ var gridRowStart :String; /** Shorthand for the "grid-template" CSS property. */ @@ -364,6 +445,8 @@ extern class CSSStyleDeclaration implements ArrayAccess var icon :String; /** Shorthand for the "image-orientation" CSS property. */ var imageOrientation :String; + /** Shorthand for the "image-rendering" CSS property. */ + var imageRendering :String; /** Shorthand for the "image-resolution" CSS property. */ var imageResolution :String; /** Shorthand for the "ime-mode" CSS property. */ @@ -372,6 +455,10 @@ extern class CSSStyleDeclaration implements ArrayAccess var initialLetters :String; /** Shorthand for the "inline-box-align" CSS property. */ var inlineBoxAlign :String; + /** Shorthand for the "inline-size" CSS property. */ + var inlineSize :String; + /** Shorthand for the "isolation" CSS property. */ + var isolation :String; /** Shorthand for the "justify-content" CSS property. */ var justifyContent :String; /** Shorthand for the "justify-items" CSS property. */ @@ -412,18 +499,34 @@ extern class CSSStyleDeclaration implements ArrayAccess var listStyleType :String; /** Shorthand for the "margin" CSS property. */ var margin :String; + /** Shorthand for the "margin-block-end" CSS property. */ + var marginBlockEnd :String; + /** Shorthand for the "margin-block-start" CSS property. */ + var marginBlockStart :String; /** Shorthand for the "margin-bottom" CSS property. */ var marginBottom :String; + /** Shorthand for the "margin-inline-end" CSS property. */ + var marginInlineEnd :String; + /** Shorthand for the "margin-inline-start" CSS property. */ + var marginInlineStart :String; /** Shorthand for the "margin-left" CSS property. */ var marginLeft :String; /** Shorthand for the "margin-right" CSS property. */ var marginRight :String; /** Shorthand for the "margin-top" CSS property. */ var marginTop :String; + /** Shorthand for the "marker" CSS property. */ + var marker :String; + /** Shorthand for the "marker-end" CSS property. */ + var markerEnd :String; + /** Shorthand for the "marker-mid" CSS property. */ + var markerMid :String; /** Shorthand for the "marker-offset" CSS property. */ var markerOffset :String; /** Shorthand for the "marker-side" CSS property. */ var markerSide :String; + /** Shorthand for the "marker-start" CSS property. */ + var markerStart :String; /** Shorthand for the "marks" CSS property. */ var marks :String; /** Shorthand for the "mask" CSS property. */ @@ -442,12 +545,20 @@ extern class CSSStyleDeclaration implements ArrayAccess var maskBoxWidth :String; /** Shorthand for the "mask-clip" CSS property. */ var maskClip :String; + /** Shorthand for the "mask-composite" CSS property. */ + var maskComposite :String; /** Shorthand for the "mask-image" CSS property. */ var maskImage :String; + /** Shorthand for the "mask-mode" CSS property. */ + var maskMode :String; /** Shorthand for the "mask-origin" CSS property. */ var maskOrigin :String; /** Shorthand for the "mask-position" CSS property. */ var maskPosition :String; + /** Shorthand for the "mask-position-x" CSS property. */ + var maskPositionX :String; + /** Shorthand for the "mask-position-y" CSS property. */ + var maskPositionY :String; /** Shorthand for the "mask-repeat" CSS property. */ var maskRepeat :String; /** Shorthand for the "mask-size" CSS property. */ @@ -456,16 +567,30 @@ extern class CSSStyleDeclaration implements ArrayAccess var maskSourceType :String; /** Shorthand for the "mask-type" CSS property. */ var maskType :String; + /** Shorthand for the "max-block-size" CSS property. */ + var maxBlockSize :String; /** Shorthand for the "max-height" CSS property. */ var maxHeight :String; + /** Shorthand for the "max-inline-size" CSS property. */ + var maxInlineSize :String; /** Shorthand for the "max-lines" CSS property. */ var maxLines :String; /** Shorthand for the "max-width" CSS property. */ var maxWidth :String; + /** Shorthand for the "max-zoom" CSS property. */ + var maxZoom :String; + /** Shorthand for the "min-block-size" CSS property. */ + var minBlockSize :String; /** Shorthand for the "min-height" CSS property. */ var minHeight :String; + /** Shorthand for the "min-inline-size" CSS property. */ + var minInlineSize :String; /** Shorthand for the "min-width" CSS property. */ var minWidth :String; + /** Shorthand for the "min-zoom" CSS property. */ + var minZoom :String; + /** Shorthand for the "mix-blend-mode" CSS property. */ + var mixBlendMode :String; /** Shorthand for the "move-to" CSS property. */ var moveTo :String; /** Shorthand for the "nav-down" CSS property. */ @@ -482,10 +607,28 @@ extern class CSSStyleDeclaration implements ArrayAccess var objectFit :String; /** Shorthand for the "object-position" CSS property. */ var objectPosition :String; + /** Shorthand for the "offset" CSS property. */ + var offset :String; + /** Shorthand for the "offset-block-end" CSS property. */ + var offsetBlockEnd :String; + /** Shorthand for the "offset-block-start" CSS property. */ + var offsetBlockStart :String; + /** Shorthand for the "offset-distance" CSS property. */ + var offsetDistance :String; + /** Shorthand for the "offset-inline-end" CSS property. */ + var offsetInlineEnd :String; + /** Shorthand for the "offset-inline-start" CSS property. */ + var offsetInlineStart :String; + /** Shorthand for the "offset-path" CSS property. */ + var offsetPath :String; + /** Shorthand for the "offset-rotate" CSS property. */ + var offsetRotate :String; /** Shorthand for the "opacity" CSS property. */ var opacity :String; /** Shorthand for the "order" CSS property. */ var order :String; + /** Shorthand for the "orientation" CSS property. */ + var orientation :String; /** Shorthand for the "orphans" CSS property. */ var orphans :String; /** Shorthand for the "outline" CSS property. */ @@ -500,16 +643,32 @@ extern class CSSStyleDeclaration implements ArrayAccess var outlineWidth :String; /** Shorthand for the "overflow" CSS property. */ var overflow :String; + /** Shorthand for the "overflow-anchor" CSS property. */ + var overflowAnchor :String; /** Shorthand for the "overflow-wrap" CSS property. */ var overflowWrap :String; /** Shorthand for the "overflow-x" CSS property. */ var overflowX :String; /** Shorthand for the "overflow-y" CSS property. */ var overflowY :String; + /** Shorthand for the "overscroll-behavior" CSS property. */ + var overscrollBehavior :String; + /** Shorthand for the "overscroll-behavior-x" CSS property. */ + var overscrollBehaviorX :String; + /** Shorthand for the "overscroll-behavior-y" CSS property. */ + var overscrollBehaviorY :String; /** Shorthand for the "padding" CSS property. */ var padding :String; + /** Shorthand for the "padding-block-end" CSS property. */ + var paddingBlockEnd :String; + /** Shorthand for the "padding-block-start" CSS property. */ + var paddingBlockStart :String; /** Shorthand for the "padding-bottom" CSS property. */ var paddingBottom :String; + /** Shorthand for the "padding-inline-end" CSS property. */ + var paddingInlineEnd :String; + /** Shorthand for the "padding-inline-start" CSS property. */ + var paddingInlineStart :String; /** Shorthand for the "padding-left" CSS property. */ var paddingLeft :String; /** Shorthand for the "padding-right" CSS property. */ @@ -526,6 +685,8 @@ extern class CSSStyleDeclaration implements ArrayAccess var pageBreakInside :String; /** Shorthand for the "page-policy" CSS property. */ var pagePolicy :String; + /** Shorthand for the "paint-order" CSS property. */ + var paintOrder :String; /** Shorthand for the "pause" CSS property. */ var pause :String; /** Shorthand for the "pause-after" CSS property. */ @@ -540,14 +701,24 @@ extern class CSSStyleDeclaration implements ArrayAccess var pitch :String; /** Shorthand for the "pitch-range" CSS property. */ var pitchRange :String; + /** Shorthand for the "place-content" CSS property. */ + var placeContent :String; + /** Shorthand for the "place-items" CSS property. */ + var placeItems :String; + /** Shorthand for the "place-self" CSS property. */ + var placeSelf :String; /** Shorthand for the "play-during" CSS property. */ var playDuring :String; + /** Shorthand for the "pointer-events" CSS property. */ + var pointerEvents :String; /** Shorthand for the "position" CSS property. */ var position :String; /** Shorthand for the "presentation-level" CSS property. */ var presentationLevel :String; /** Shorthand for the "quotes" CSS property. */ var quotes :String; + /** Shorthand for the "r" CSS property. */ + var r :String; /** Shorthand for the "region-fragment" CSS property. */ var regionFragment :String; /** Shorthand for the "resize" CSS property. */ @@ -566,18 +737,42 @@ extern class CSSStyleDeclaration implements ArrayAccess var rotation :String; /** Shorthand for the "rotation-point" CSS property. */ var rotationPoint :String; + /** Shorthand for the "row-gap" CSS property. */ + var rowGap :String; /** Shorthand for the "ruby-align" CSS property. */ var rubyAlign :String; /** Shorthand for the "ruby-merge" CSS property. */ var rubyMerge :String; /** Shorthand for the "ruby-position" CSS property. */ var rubyPosition :String; + /** Shorthand for the "rx" CSS property. */ + var rx :String; + /** Shorthand for the "ry" CSS property. */ + var ry :String; + /** Shorthand for the "scroll-behavior" CSS property. */ + var scrollBehavior :String; + /** Shorthand for the "scroll-snap-coordinate" CSS property. */ + var scrollSnapCoordinate :String; + /** Shorthand for the "scroll-snap-destination" CSS property. */ + var scrollSnapDestination :String; + /** Shorthand for the "scroll-snap-points-x" CSS property. */ + var scrollSnapPointsX :String; + /** Shorthand for the "scroll-snap-points-y" CSS property. */ + var scrollSnapPointsY :String; + /** Shorthand for the "scroll-snap-type" CSS property. */ + var scrollSnapType :String; + /** Shorthand for the "scroll-snap-type-x" CSS property. */ + var scrollSnapTypeX :String; + /** Shorthand for the "scroll-snap-type-y" CSS property. */ + var scrollSnapTypeY :String; /** Shorthand for the "shape-image-threshold" CSS property. */ var shapeImageThreshold :String; - /** Shorthand for the "shape-outside" CSS property. */ - var shapeOutside :String; /** Shorthand for the "shape-margin" CSS property. */ var shapeMargin :String; + /** Shorthand for the "shape-outside" CSS property. */ + var shapeOutside :String; + /** Shorthand for the "shape-rendering" CSS property. */ + var shapeRendering :String; /** Shorthand for the "size" CSS property. */ var size :String; /** Shorthand for the "speak" CSS property. */ @@ -592,10 +787,32 @@ extern class CSSStyleDeclaration implements ArrayAccess var speakPunctuation :String; /** Shorthand for the "speech-rate" CSS property. */ var speechRate :String; + /** Shorthand for the "src" CSS property. */ + var src :String; + /** Shorthand for the "stop-color" CSS property. */ + var stopColor :String; + /** Shorthand for the "stop-opacity" CSS property. */ + var stopOpacity :String; /** Shorthand for the "stress" CSS property. */ var stress :String; /** Shorthand for the "string-set" CSS property. */ var stringSet :String; + /** Shorthand for the "stroke" CSS property. */ + var stroke :String; + /** Shorthand for the "stroke-dasharray" CSS property. */ + var strokeDasharray :String; + /** Shorthand for the "stroke-dashoffset" CSS property. */ + var strokeDashoffset :String; + /** Shorthand for the "stroke-linecap" CSS property. */ + var strokeLinecap :String; + /** Shorthand for the "stroke-linejoin" CSS property. */ + var strokeLinejoin :String; + /** Shorthand for the "stroke-miterlimit" CSS property. */ + var strokeMiterlimit :String; + /** Shorthand for the "stroke-opacity" CSS property. */ + var strokeOpacity :String; + /** Shorthand for the "stroke-width" CSS property. */ + var strokeWidth :String; /** Shorthand for the "tab-size" CSS property. */ var tabSize :String; /** Shorthand for the "table-layout" CSS property. */ @@ -604,6 +821,8 @@ extern class CSSStyleDeclaration implements ArrayAccess var textAlign :String; /** Shorthand for the "text-align-last" CSS property. */ var textAlignLast :String; + /** Shorthand for the "text-anchor" CSS property. */ + var textAnchor :String; /** Shorthand for the "text-combine-upright" CSS property. */ var textCombineUpright :String; /** Shorthand for the "text-decoration" CSS property. */ @@ -614,6 +833,8 @@ extern class CSSStyleDeclaration implements ArrayAccess var textDecorationLine :String; /** Shorthand for the "text-decoration-skip" CSS property. */ var textDecorationSkip :String; + /** Shorthand for the "text-decoration-skip-ink" CSS property. */ + var textDecorationSkipInk :String; /** Shorthand for the "text-decoration-style" CSS property. */ var textDecorationStyle :String; /** Shorthand for the "text-emphasis" CSS property. */ @@ -634,8 +855,12 @@ extern class CSSStyleDeclaration implements ArrayAccess var textOrientation :String; /** Shorthand for the "text-overflow" CSS property. */ var textOverflow :String; + /** Shorthand for the "text-rendering" CSS property. */ + var textRendering :String; /** Shorthand for the "text-shadow" CSS property. */ var textShadow :String; + /** Shorthand for the "text-size-adjust" CSS property. */ + var textSizeAdjust :String; /** Shorthand for the "text-space-collapse" CSS property. */ var textSpaceCollapse :String; /** Shorthand for the "text-transform" CSS property. */ @@ -646,8 +871,12 @@ extern class CSSStyleDeclaration implements ArrayAccess var textWrap :String; /** Shorthand for the "top" CSS property. */ var top :String; + /** Shorthand for the "touch-action" CSS property. */ + var touchAction :String; /** Shorthand for the "transform" CSS property. */ var transform :String; + /** Shorthand for the "transform-box" CSS property. */ + var transformBox :String; /** Shorthand for the "transform-origin" CSS property. */ var transformOrigin :String; /** Shorthand for the "transform-style" CSS property. */ @@ -664,6 +893,14 @@ extern class CSSStyleDeclaration implements ArrayAccess var transitionTimingFunction :String; /** Shorthand for the "unicode-bidi" CSS property. */ var unicodeBidi :String; + /** Shorthand for the "unicode-range" CSS property. */ + var unicodeRange :String; + /** Shorthand for the "user-select" CSS property. */ + var userSelect :String; + /** Shorthand for the "user-zoom" CSS property. */ + var userZoom :String; + /** Shorthand for the "vector-effect" CSS property. */ + var vectorEffect :String; /** Shorthand for the "vertical-align" CSS property. */ var verticalAlign :String; /** Shorthand for the "visibility" CSS property. */ @@ -706,17 +943,21 @@ extern class CSSStyleDeclaration implements ArrayAccess var wrapThrough :String; /** Shorthand for the "writing-mode" CSS property. */ var writingMode :String; + /** Shorthand for the "x" CSS property. */ + var x :String; + /** Shorthand for the "y" CSS property. */ + var y :String; /** Shorthand for the "z-index" CSS property. */ var zIndex :String; + /** Shorthand for the "zoom" CSS property. */ + var zoom :String; function item( index : Int ) : String; /** @throws DOMError */ function getPropertyValue( property : String ) : String; - /** @throws DOMError */ - function getPropertyCSSValue( property : String ) : CSSValue; function getPropertyPriority( property : String ) : String; /** @throws DOMError */ - function setProperty( property : String, value : String, ?priority : String = "" ) : Void; + function setProperty( property : String, value : String, priority : String = "" ) : Void; /** @throws DOMError */ function removeProperty( property : String ) : String; } \ No newline at end of file diff --git a/std/js/html/CSSStyleRule.hx b/std/js/html/CSSStyleRule.hx index f94707ef0bf..1fc1d7c9269 100644 --- a/std/js/html/CSSStyleRule.hx +++ b/std/js/html/CSSStyleRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl. Do not edit! +// This file is generated from mozilla\CSSStyleRule.webidl. Do not edit! package js.html; @@ -32,9 +32,16 @@ package js.html; @see **/ @:native("CSSStyleRule") -extern class CSSStyleRule extends CSSRule -{ +extern class CSSStyleRule extends CSSRule { + + /** + Gets the textual representation of the selector for this rule, e.g. `"h1,h2"`. + **/ var selectorText : String; + + /** + Returns the `CSSStyleDeclaration` object for the rule. + **/ var style(default,null) : CSSStyleDeclaration; } \ No newline at end of file diff --git a/std/js/html/CSSStyleSheet.hx b/std/js/html/CSSStyleSheet.hx index d6a03461b94..6ed72d4474b 100644 --- a/std/js/html/CSSStyleSheet.hx +++ b/std/js/html/CSSStyleSheet.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,13 +32,34 @@ package js.html; @see **/ @:native("CSSStyleSheet") -extern class CSSStyleSheet extends StyleSheet -{ +extern class CSSStyleSheet extends StyleSheet { + + /** + If this style sheet is imported into the document using an `@import` rule, the `ownerRule` property will return that `CSSImportRule`, otherwise it returns `null`. + **/ var ownerRule(default,null) : CSSRule; + + /** + Returns a live `CSSRuleList`, listing the `CSSRule` objects in the style sheet. + + This is normally used to access individual rules like this: + + `   styleSheet.cssRules[i] // where i = 0..cssRules.length-1` + + To add or remove items in `cssRules`, use the `CSSStyleSheet`'s `deleteRule()` and `insertRule()` methods, described below. + **/ var cssRules(default,null) : CSSRuleList; - /** @throws DOMError */ - function insertRule( rule : String, index : Int ) : Int; - /** @throws DOMError */ + + /** + Inserts a new rule at the specified position in the style sheet, given the textual representation of the rule. + @throws DOMError + **/ + function insertRule( rule : String, index : Int = 0 ) : Int; + + /** + Deletes a rule at the specified position from the style sheet. + @throws DOMError + **/ function deleteRule( index : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/CSSSupportsRule.hx b/std/js/html/CSSSupportsRule.hx new file mode 100644 index 00000000000..e708dd47dca --- /dev/null +++ b/std/js/html/CSSSupportsRule.hx @@ -0,0 +1,36 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CSSSupportsRule.webidl. Do not edit! + +package js.html; + +/** + The `CSSSupportsRule` interface describes an object representing a single CSS `@supports` at-rule. It implements the `CSSConditionRule` interface, and therefore the `CSSRule` and `CSSGroupingRule` interfaces with a type value of `12` (`CSSRule.SUPPORTS_RULE`). + + Documentation [CSSSupportsRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSSupportsRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSSupportsRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("CSSSupportsRule") +extern class CSSSupportsRule extends CSSConditionRule { +} \ No newline at end of file diff --git a/std/js/html/CSSTransition.hx b/std/js/html/CSSTransition.hx index 0fc880834d4..336547aa2ac 100644 --- a/std/js/html/CSSTransition.hx +++ b/std/js/html/CSSTransition.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,8 +25,7 @@ package js.html; @:native("CSSTransition") -extern class CSSTransition extends Animation -{ +extern class CSSTransition extends Animation { var transitionProperty(default,null) : String; } \ No newline at end of file diff --git a/std/js/html/CSSValue.hx b/std/js/html/CSSValue.hx deleted file mode 100644 index 0f3aea68306..00000000000 --- a/std/js/html/CSSValue.hx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C)2005-2017 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -// This file is generated from mozilla\CSSValue.webidl. Do not edit! - -package js.html; - -/** - The `CSSValue` interface represents the current computed value of a CSS property. - - Documentation [CSSValue](https://developer.mozilla.org/en-US/docs/Web/API/CSSValue) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSValue$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). - - @see -**/ -@:native("CSSValue") -extern class CSSValue -{ - static inline var CSS_INHERIT : Int = 0; - static inline var CSS_PRIMITIVE_VALUE : Int = 1; - static inline var CSS_VALUE_LIST : Int = 2; - static inline var CSS_CUSTOM : Int = 3; - - - /** - A `DOMString` representing the current value. - **/ - var cssText : String; - - /** - An unsigned short representing a code defining the type of the value. Possible values are: - - - - - - - - - - - - - - - - - - - - - - - -
ConstantDescription
CSS_CUSTOMThe value is a custom value.
CSS_INHERITThe value is inherited and the cssText contains "inherit".
CSS_PRIMITIVE_VALUEThe value is a primitive value and an instance of the CSSPrimitiveValue interface can be obtained by using binding-specific casting methods on this instance of the CSSValue interface.
CSS_VALUE_LISTThe value is a CSSValue list and an instance of the CSSValueList interface can be obtained by using binding-specific casting methods on this instance of the CSSValue interface.
- - **/ - var cssValueType(default,null) : Int; - -} \ No newline at end of file diff --git a/std/js/html/Cache.hx b/std/js/html/Cache.hx new file mode 100644 index 00000000000..93b9bd6d39d --- /dev/null +++ b/std/js/html/Cache.hx @@ -0,0 +1,51 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\Cache.webidl. Do not edit! + +package js.html; + +import js.lib.Promise; + +/** + The `Cache` interface provides a storage mechanism for `Request` / `Response` object pairs that are cached, for example as part of the `ServiceWorker` life cycle. Note that the `Cache` interface is exposed to windowed scopes as well as workers. You don't have to use it in conjunction with service workers, even though it is defined in the service worker spec. + + Documentation [Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Cache$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("Cache") +extern class Cache { + @:overload( function( request : String, ?options : CacheQueryOptions) : Promise {} ) + function match( request : Request, ?options : CacheQueryOptions ) : Promise; + @:overload( function( ?request : String, ?options : CacheQueryOptions) : Promise> {} ) + function matchAll( ?request : Request, ?options : CacheQueryOptions ) : Promise>; + @:overload( function( request : String) : Promise {} ) + function add( request : Request ) : Promise; + function addAll( requests : Array> ) : Promise; + @:overload( function( request : String, response : Response) : Promise {} ) + function put( request : Request, response : Response ) : Promise; + @:overload( function( request : String, ?options : CacheQueryOptions) : Promise {} ) + function delete( request : Request, ?options : CacheQueryOptions ) : Promise; + @:overload( function( ?request : String, ?options : CacheQueryOptions) : Promise> {} ) + function keys( ?request : Request, ?options : CacheQueryOptions ) : Promise>; +} \ No newline at end of file diff --git a/std/js/html/CacheQueryOptions.hx b/std/js/html/CacheQueryOptions.hx new file mode 100644 index 00000000000..95ff2936980 --- /dev/null +++ b/std/js/html/CacheQueryOptions.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\Cache.webidl. Do not edit! + +package js.html; + +typedef CacheQueryOptions = { + var ?cacheName : String; + var ?ignoreMethod : Bool; + var ?ignoreSearch : Bool; + var ?ignoreVary : Bool; +} \ No newline at end of file diff --git a/std/js/html/CacheStorage.hx b/std/js/html/CacheStorage.hx new file mode 100644 index 00000000000..8a7546b07f0 --- /dev/null +++ b/std/js/html/CacheStorage.hx @@ -0,0 +1,66 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CacheStorage.webidl. Do not edit! + +package js.html; + +import js.lib.Promise; + +/** + The `CacheStorage` interface represents the storage for `Cache` objects. + + Documentation [CacheStorage](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("CacheStorage") +extern class CacheStorage { + /** @throws DOMError */ + function new( namespace : CacheStorageNamespace, principal : Dynamic/*MISSING Principal*/ ) : Void; + + /** + Checks if a given `Request` is a key in any of the `Cache` objects that the `CacheStorage` object tracks, and returns a `Promise` that resolves to that match. + **/ + @:overload( function( request : String, ?options : CacheQueryOptions) : Promise {} ) + function match( request : Request, ?options : CacheQueryOptions ) : Promise; + + /** + Returns a `Promise` that resolves to `true` if a `Cache` object matching the `cacheName` exists. + **/ + function has( cacheName : String ) : Promise; + + /** + Returns a `Promise` that resolves to the `Cache` object matching the `cacheName` (a new cache is created if it doesn't already exist.) + **/ + function open( cacheName : String ) : Promise; + + /** + Finds the `Cache` object matching the `cacheName`, and if found, deletes the `Cache` object and returns a `Promise` that resolves to `true`. If no `Cache` object is found, it returns `false`. + **/ + function delete( cacheName : String ) : Promise; + + /** + Returns a `Promise` that will resolve with an array containing strings corresponding to all of the named `Cache` objects tracked by the `CacheStorage`. Use this method to iterate over a list of all the `Cache` objects. + **/ + function keys() : Promise>; +} \ No newline at end of file diff --git a/std/js/html/CacheStorageNamespace.hx b/std/js/html/CacheStorageNamespace.hx new file mode 100644 index 00000000000..4a5ed31e90e --- /dev/null +++ b/std/js/html/CacheStorageNamespace.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CacheStorage.webidl. Do not edit! + +package js.html; + +enum abstract CacheStorageNamespace(String) { + var CONTENT = "content"; + var CHROME = "chrome"; +} \ No newline at end of file diff --git a/std/js/html/CanvasCaptureMediaStream.hx b/std/js/html/CanvasCaptureMediaStream.hx new file mode 100644 index 00000000000..935314fbe7a --- /dev/null +++ b/std/js/html/CanvasCaptureMediaStream.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\CanvasCaptureMediaStream.webidl. Do not edit! + +package js.html; + +@:native("CanvasCaptureMediaStream") +extern class CanvasCaptureMediaStream extends MediaStream { + var canvas(default,null) : CanvasElement; + + function requestFrame() : Void; +} \ No newline at end of file diff --git a/std/js/html/CanvasElement.hx b/std/js/html/CanvasElement.hx index ca6b006a449..205485fce29 100644 --- a/std/js/html/CanvasElement.hx +++ b/std/js/html/CanvasElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLCanvasElement") -extern class CanvasElement extends Element -{ +extern class CanvasElement extends Element { /** Is a positive `integer` reflecting the `width` HTML attribute of the `canvas` element interpreted in CSS pixels. When the attribute is not specified, or if it is set to an invalid value, like a negative, the default value of `300` is used. @@ -45,24 +44,30 @@ extern class CanvasElement extends Element **/ var height : Int; - /** @throws DOMError */ /** - Returns a drawing context on the canvas, or null if the context ID is not supported. A drawing context lets you draw on the canvas. Calling getContext with `"2d"` returns a `CanvasRenderingContext2D` object, whereas calling it with `"experimental-webgl"` (or `"webgl"`) returns a `WebGLRenderingContext` object. This context is only available on browsers that implement WebGL. + Returns a drawing context on the canvas, or null if the context ID is not supported. A drawing context lets you draw on the canvas. Calling getContext with `"2d"` returns a `CanvasRenderingContext2D` object, whereas calling it with `"webgl"` (or `"experimental-webgl"`) returns a `WebGLRenderingContext` object. This context is only available on browsers that implement WebGL. + @throws DOMError **/ - function getContext( contextId : String, ?contextOptions : Dynamic ) : Dynamic/*MISSING nsISupports*/; - /** @throws DOMError */ + function getContext( contextId : String, ?contextOptions : Dynamic ) : Dynamic; /** Returns a data-URL containing a representation of the image in the format specified by the `type` parameter (defaults to `png`). The returned image is in a resolution of 96dpi. + @throws DOMError **/ - function toDataURL( ?type : String = "", ?encoderOptions : Dynamic ) : String; - /** @throws DOMError */ + function toDataURL( type : String = "", ?encoderOptions : Dynamic ) : String; /** Creates a `Blob` object representing the image contained in the canvas; this file may be cached on the disk or stored in memory at the discretion of the user agent. + @throws DOMError **/ - function toBlob( callback : Blob -> Void, ?type : String = "", ?encoderOptions : Dynamic ) : Void; + function toBlob( callback : Blob -> Void, type : String = "", ?encoderOptions : Dynamic ) : Void; + + /** + Returns a `CanvasCaptureMediaStream` that is a real-time video capture of the surface of the canvas. + @throws DOMError + **/ + function captureStream( ?frameRate : Float ) : CanvasCaptureMediaStream; /** Shorthand for getting a CanvasRenderingContext2D. */ inline function getContext2d( ?attribs : {} ) : CanvasRenderingContext2D { @@ -72,6 +77,10 @@ extern class CanvasElement extends Element inline function getContextWebGL( ?attribs : js.html.webgl.ContextAttributes ) : js.html.webgl.RenderingContext { return CanvasUtil.getContextWebGL(this, attribs); } + /** Shorthand for getting a js.html.webgl.WebGL2RenderingContext. */ + inline function getContextWebGL2( ?attribs : js.html.webgl.ContextAttributes ) : js.html.webgl.WebGL2RenderingContext { + return this.getContext('webgl2', attribs); + } } private class CanvasUtil { diff --git a/std/js/html/CanvasGradient.hx b/std/js/html/CanvasGradient.hx index 55e9da094db..7934def18dc 100644 --- a/std/js/html/CanvasGradient.hx +++ b/std/js/html/CanvasGradient.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,12 +32,11 @@ package js.html; @see **/ @:native("CanvasGradient") -extern class CanvasGradient -{ - /** @throws DOMError */ +extern class CanvasGradient { /** Adds a new stop, defined by an `offset` and a `color`, to the gradient. If the offset is not between `0` and `1` an `INDEX_SIZE_ERR` is raised, if the color can't be parsed as a CSS `color`, a `SYNTAX_ERR` is raised. + @throws DOMError **/ function addColorStop( offset : Float, color : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/CanvasPattern.hx b/std/js/html/CanvasPattern.hx index b7f4bcecd86..560b10dfebd 100644 --- a/std/js/html/CanvasPattern.hx +++ b/std/js/html/CanvasPattern.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,15 +25,14 @@ package js.html; /** - The `CanvasPattern` interface represents an opaque object describing a pattern, based on an image, a canvas or a video, created by the `CanvasRenderingContext2D.createPattern()` method. + The `CanvasPattern` interface represents an opaque object describing a pattern, based on an image, a canvas, or a video, created by the `CanvasRenderingContext2D.createPattern()` method. Documentation [CanvasPattern](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("CanvasPattern") -extern class CanvasPattern -{ +extern class CanvasPattern { /** Applies an `SVGMatrix` representing a linear transform to the pattern. diff --git a/std/js/html/CanvasRenderingContext2D.hx b/std/js/html/CanvasRenderingContext2D.hx index 2f57327e227..810444c0004 100644 --- a/std/js/html/CanvasRenderingContext2D.hx +++ b/std/js/html/CanvasRenderingContext2D.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,17 +32,12 @@ package js.html; @see **/ @:native("CanvasRenderingContext2D") -extern class CanvasRenderingContext2D -{ +extern class CanvasRenderingContext2D { var canvas(default,null) : CanvasElement; var globalAlpha : Float; var globalCompositeOperation : String; var strokeStyle : haxe.extern.EitherType>; var fillStyle : haxe.extern.EitherType>; - var shadowOffsetX : Float; - var shadowOffsetY : Float; - var shadowBlur : Float; - var shadowColor : String; var filter : String; var imageSmoothingEnabled : Bool; var lineWidth : Float; @@ -50,56 +45,50 @@ extern class CanvasRenderingContext2D var lineJoin : String; var miterLimit : Float; var lineDashOffset : Float; + var shadowOffsetX : Float; + var shadowOffsetY : Float; + var shadowBlur : Float; + var shadowColor : String; var font : String; var textAlign : String; var textBaseline : String; - function save() : Void; - function restore() : Void; - /** @throws DOMError */ - function scale( x : Float, y : Float ) : Void; - /** @throws DOMError */ - function rotate( angle : Float ) : Void; - /** @throws DOMError */ - function translate( x : Float, y : Float ) : Void; /** @throws DOMError */ - function transform( a : Float, b : Float, c : Float, d : Float, e : Float, f : Float ) : Void; - /** @throws DOMError */ - function setTransform( a : Float, b : Float, c : Float, d : Float, e : Float, f : Float ) : Void; - /** @throws DOMError */ - function resetTransform() : Void; - function createLinearGradient( x0 : Float, y0 : Float, x1 : Float, y1 : Float ) : CanvasGradient; - /** @throws DOMError */ - function createRadialGradient( x0 : Float, y0 : Float, r0 : Float, x1 : Float, y1 : Float, r1 : Float ) : CanvasGradient; - /** @throws DOMError */ - function createPattern( image : haxe.extern.EitherType>>, repetition : String ) : CanvasPattern; - function clearRect( x : Float, y : Float, w : Float, h : Float ) : Void; - function fillRect( x : Float, y : Float, w : Float, h : Float ) : Void; - function strokeRect( x : Float, y : Float, w : Float, h : Float ) : Void; + @:overload( function( image : js.html.svg.ImageElement, dx : Float, dy : Float) : Void {} ) + @:overload( function( image : CanvasElement, dx : Float, dy : Float) : Void {} ) + @:overload( function( image : VideoElement, dx : Float, dy : Float) : Void {} ) + @:overload( function( image : ImageBitmap, dx : Float, dy : Float) : Void {} ) + @:overload( function( image : js.html.svg.ImageElement, dx : Float, dy : Float, dw : Float, dh : Float) : Void {} ) + @:overload( function( image : CanvasElement, dx : Float, dy : Float, dw : Float, dh : Float) : Void {} ) + @:overload( function( image : VideoElement, dx : Float, dy : Float, dw : Float, dh : Float) : Void {} ) + @:overload( function( image : ImageBitmap, dx : Float, dy : Float, dw : Float, dh : Float) : Void {} ) + @:overload( function( image : js.html.svg.ImageElement, sx : Float, sy : Float, sw : Float, sh : Float, dx : Float, dy : Float, dw : Float, dh : Float) : Void {} ) + @:overload( function( image : CanvasElement, sx : Float, sy : Float, sw : Float, sh : Float, dx : Float, dy : Float, dw : Float, dh : Float) : Void {} ) + @:overload( function( image : VideoElement, sx : Float, sy : Float, sw : Float, sh : Float, dx : Float, dy : Float, dw : Float, dh : Float) : Void {} ) + @:overload( function( image : ImageBitmap, sx : Float, sy : Float, sw : Float, sh : Float, dx : Float, dy : Float, dw : Float, dh : Float) : Void {} ) + @:overload( function( image : ImageElement, dx : Float, dy : Float ) : Void {} ) + @:overload( function( image : ImageElement, dx : Float, dy : Float, dw : Float, dh : Float ) : Void {} ) + function drawImage( image : ImageElement, sx : Float, sy : Float, sw : Float, sh : Float, dx : Float, dy : Float, dw : Float, dh : Float ) : Void; function beginPath() : Void; - @:overload( function( ?winding : CanvasWindingRule = "nonzero" ) : Void {} ) - function fill( path : Path2D, ?winding : CanvasWindingRule = "nonzero" ) : Void; + @:overload( function( winding : CanvasWindingRule = NONZERO ) : Void {} ) + function fill( path : Path2D, winding : CanvasWindingRule = NONZERO ) : Void; @:overload( function() : Void {} ) function stroke( path : Path2D ) : Void; - /** @throws DOMError */ - function drawFocusIfNeeded( element : Element ) : Void; - function drawCustomFocusRing( element : Element ) : Bool; - @:overload( function( ?winding : CanvasWindingRule = "nonzero" ) : Void {} ) - function clip( path : Path2D, ?winding : CanvasWindingRule = "nonzero" ) : Void; - @:overload( function( x : Float, y : Float, ?winding : CanvasWindingRule = "nonzero" ) : Bool {} ) - function isPointInPath( path : Path2D, x : Float, y : Float, ?winding : CanvasWindingRule = "nonzero" ) : Bool; + @:overload( function( winding : CanvasWindingRule = NONZERO ) : Void {} ) + function clip( path : Path2D, winding : CanvasWindingRule = NONZERO ) : Void; + @:overload( function( x : Float, y : Float, winding : CanvasWindingRule = NONZERO ) : Bool {} ) + function isPointInPath( path : Path2D, x : Float, y : Float, winding : CanvasWindingRule = NONZERO ) : Bool; @:overload( function( x : Float, y : Float ) : Bool {} ) function isPointInStroke( path : Path2D, x : Float, y : Float ) : Bool; + function createLinearGradient( x0 : Float, y0 : Float, x1 : Float, y1 : Float ) : CanvasGradient; /** @throws DOMError */ - function fillText( text : String, x : Float, y : Float, ?maxWidth : Float ) : Void; - /** @throws DOMError */ - function strokeText( text : String, x : Float, y : Float, ?maxWidth : Float ) : Void; - /** @throws DOMError */ - function measureText( text : String ) : TextMetrics; + function createRadialGradient( x0 : Float, y0 : Float, r0 : Float, x1 : Float, y1 : Float, r1 : Float ) : CanvasGradient; /** @throws DOMError */ - @:overload( function( image : haxe.extern.EitherType>>, dx : Float, dy : Float ) : Void {} ) - @:overload( function( image : haxe.extern.EitherType>>, dx : Float, dy : Float, dw : Float, dh : Float ) : Void {} ) - function drawImage( image : haxe.extern.EitherType>>, sx : Float, sy : Float, sw : Float, sh : Float, dx : Float, dy : Float, dw : Float, dh : Float ) : Void; + @:overload( function( image : js.html.svg.ImageElement, repetition : String) : CanvasPattern {} ) + @:overload( function( image : CanvasElement, repetition : String) : CanvasPattern {} ) + @:overload( function( image : VideoElement, repetition : String) : CanvasPattern {} ) + @:overload( function( image : ImageBitmap, repetition : String) : CanvasPattern {} ) + function createPattern( image : ImageElement, repetition : String ) : CanvasPattern; /** @throws DOMError */ function addHitRegion( ?options : HitRegionOptions ) : Void; function removeHitRegion( id : String ) : Void; @@ -124,7 +113,33 @@ extern class CanvasRenderingContext2D function arcTo( x1 : Float, y1 : Float, x2 : Float, y2 : Float, radius : Float ) : Void; function rect( x : Float, y : Float, w : Float, h : Float ) : Void; /** @throws DOMError */ - function arc( x : Float, y : Float, radius : Float, startAngle : Float, endAngle : Float, ?anticlockwise : Bool = false ) : Void; + function arc( x : Float, y : Float, radius : Float, startAngle : Float, endAngle : Float, anticlockwise : Bool = false ) : Void; + /** @throws DOMError */ + function ellipse( x : Float, y : Float, radiusX : Float, radiusY : Float, rotation : Float, startAngle : Float, endAngle : Float, anticlockwise : Bool = false ) : Void; + function clearRect( x : Float, y : Float, w : Float, h : Float ) : Void; + function fillRect( x : Float, y : Float, w : Float, h : Float ) : Void; + function strokeRect( x : Float, y : Float, w : Float, h : Float ) : Void; + function save() : Void; + function restore() : Void; + /** @throws DOMError */ + function fillText( text : String, x : Float, y : Float, ?maxWidth : Float ) : Void; + /** @throws DOMError */ + function strokeText( text : String, x : Float, y : Float, ?maxWidth : Float ) : Void; + /** @throws DOMError */ + function measureText( text : String ) : TextMetrics; + /** @throws DOMError */ + function scale( x : Float, y : Float ) : Void; + /** @throws DOMError */ + function rotate( angle : Float ) : Void; + /** @throws DOMError */ + function translate( x : Float, y : Float ) : Void; + /** @throws DOMError */ + function transform( a : Float, b : Float, c : Float, d : Float, e : Float, f : Float ) : Void; + /** @throws DOMError */ + function setTransform( a : Float, b : Float, c : Float, d : Float, e : Float, f : Float ) : Void; + /** @throws DOMError */ + function resetTransform() : Void; /** @throws DOMError */ - function ellipse( x : Float, y : Float, radiusX : Float, radiusY : Float, rotation : Float, startAngle : Float, endAngle : Float, ?anticlockwise : Bool = false ) : Void; + function drawFocusIfNeeded( element : Element ) : Void; + function drawCustomFocusRing( element : Element ) : Bool; } \ No newline at end of file diff --git a/std/js/html/CanvasWindingRule.hx b/std/js/html/CanvasWindingRule.hx index c0b6c6c26b2..4d7c643746a 100644 --- a/std/js/html/CanvasWindingRule.hx +++ b/std/js/html/CanvasWindingRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -@:enum abstract CanvasWindingRule(String) -{ +enum abstract CanvasWindingRule(String) { var NONZERO = "nonzero"; var EVENODD = "evenodd"; } \ No newline at end of file diff --git a/std/js/html/CaretPosition.hx b/std/js/html/CaretPosition.hx index 45f5fede003..aaa5d77eae4 100644 --- a/std/js/html/CaretPosition.hx +++ b/std/js/html/CaretPosition.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("CaretPosition") -extern class CaretPosition -{ +extern class CaretPosition { /** Returns a `Node` containing the found node at the caret's position. diff --git a/std/js/html/ChannelPixelLayout.hx b/std/js/html/ChannelPixelLayout.hx new file mode 100644 index 00000000000..62671b1f540 --- /dev/null +++ b/std/js/html/ChannelPixelLayout.hx @@ -0,0 +1,34 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\ImageBitmap.webidl. Do not edit! + +package js.html; + +typedef ChannelPixelLayout = { + var dataType : ChannelPixelLayoutDataType; + var height : Int; + var offset : Int; + var skip : Int; + var stride : Int; + var width : Int; +} \ No newline at end of file diff --git a/std/js/html/CommandEvent.hx b/std/js/html/ChannelPixelLayoutDataType.hx similarity index 75% rename from std/js/html/CommandEvent.hx rename to std/js/html/ChannelPixelLayoutDataType.hx index 39b76356e9f..66d6cb77dd3 100644 --- a/std/js/html/CommandEvent.hx +++ b/std/js/html/ChannelPixelLayoutDataType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,14 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\CommandEvent.webidl. Do not edit! +// This file is generated from mozilla\ImageBitmap.webidl. Do not edit! package js.html; -@:native("CommandEvent") -extern class CommandEvent extends Event -{ - var command(default,null) : String; - - function initCommandEvent( type : String, canBubble : Bool, cancelable : Bool, command : String ) : Void; +enum abstract ChannelPixelLayoutDataType(String) { + var UINT8 = "uint8"; + var INT8 = "int8"; + var UINT16 = "uint16"; + var INT16 = "int16"; + var UINT32 = "uint32"; + var INT32 = "int32"; + var FLOAT32 = "float32"; + var FLOAT64 = "float64"; } \ No newline at end of file diff --git a/std/js/html/CharacterData.hx b/std/js/html/CharacterData.hx index a74569586f0..a6ba5aa1899 100644 --- a/std/js/html/CharacterData.hx +++ b/std/js/html/CharacterData.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,15 +25,14 @@ package js.html; /** - The `CharacterData` abstract interface represents a `Node` object that contains characters. This is an abstract interface, meaning there aren't any object of type `CharacterData`: it is implemented by other interfaces, like `Text`, `Comment`, or `ProcessingInstruction` which aren't abstract. + The `CharacterData` abstract interface represents a `Node` object that contains characters. This is an abstract interface, meaning there aren't any object of type `CharacterData`: it is implemented by other interfaces, like `Text`, '. In XML, the character sequence '--' cannot be used within a comment.">`Comment`, or `ProcessingInstruction` which aren't abstract. Documentation [CharacterData](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("CharacterData") -extern class CharacterData extends Node -{ +extern class CharacterData extends Node { /** Is a `DOMString` representing the textual data contained in this object. @@ -47,35 +46,44 @@ extern class CharacterData extends Node var previousElementSibling(default,null) : Element; var nextElementSibling(default,null) : Element; - /** @throws DOMError */ /** Returns a `DOMString` containing the part of `CharacterData.data` of the specified length and starting at the specified offset. + @throws DOMError **/ function substringData( offset : Int, count : Int ) : String; - /** @throws DOMError */ /** Appends the given `DOMString` to the `CharacterData.data` string; when this method returns, `data` contains the concatenated `DOMString`. + @throws DOMError **/ function appendData( data : String ) : Void; - /** @throws DOMError */ /** Inserts the specified characters, at the specified offset, in the `CharacterData.data` string; when this method returns, `data` contains the modified `DOMString`. + @throws DOMError **/ function insertData( offset : Int, data : String ) : Void; - /** @throws DOMError */ /** Removes the specified amount of characters, starting at the specified offset, from the `CharacterData.data` string; when this method returns, `data` contains the shortened `DOMString`. + @throws DOMError **/ function deleteData( offset : Int, count : Int ) : Void; - /** @throws DOMError */ /** Replaces the specified amount of characters, starting at the specified offset, with the specified `DOMString`; when this method returns, `data` contains the modified `DOMString`. + @throws DOMError **/ function replaceData( offset : Int, count : Int, data : String ) : Void; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function before( nodes : haxe.extern.Rest ) : Void; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function after( nodes : haxe.extern.Rest ) : Void; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function replaceWith( nodes : haxe.extern.Rest ) : Void; function remove() : Void; } \ No newline at end of file diff --git a/std/js/html/Client.hx b/std/js/html/Client.hx index 3018a17cfbd..7074b7cf37a 100644 --- a/std/js/html/Client.hx +++ b/std/js/html/Client.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,35 +25,35 @@ package js.html; /** - The `Client` interface of the ServiceWorker API represents the scope of a service worker client. A service worker client is either a document in a browser context or a `SharedWorker`, which is controlled by an active worker. A client object acts as a snapshot representation of its associated service worker client in the scope of a service worker. + The `Client` interface represents an executable context such as a `Worker`, or a `SharedWorker`. `Window` clients are represented by the more-specific `WindowClient`. You can get `Client`/`WindowClient` objects from methods such as `Clients.matchAll()` and `Clients.get()`. Documentation [Client](https://developer.mozilla.org/en-US/docs/Web/API/Client) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Client$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("Client") -extern class Client -{ +extern class Client { /** - The URL of the current service worker client. + The URL of the client as a string. **/ var url(default,null) : String; + var frameType(default,null) : FrameType; /** - Indicates the type of browsing context of the current client. This value can be one of `auxiliary`, `top-level`, `nested`, or `none`. + The client's type as a string. It can be "`window"`, "`worker"`, or "`sharedworker"`. **/ - var frameType(default,null) : FrameType; + var type(default,null) : ClientType; /** - Returns the universally unique identifier of the `Client` object. + The universally unique identifier of the client as a string. **/ var id(default,null) : String; - /** @throws DOMError */ /** - Allows a service worker to send a message to a `ServiceWorkerClient`. + Sends a message to the client. + @throws DOMError **/ function postMessage( message : Dynamic, ?transfer : Array ) : Void; } \ No newline at end of file diff --git a/std/js/html/ClientQueryOptions.hx b/std/js/html/ClientQueryOptions.hx index cea59eb22af..9bccf19ab00 100644 --- a/std/js/html/ClientQueryOptions.hx +++ b/std/js/html/ClientQueryOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -typedef ClientQueryOptions = -{ - @:optional var includeUncontrolled : Bool; - @:optional var type : Dynamic/*MISSING ClientType*/; +typedef ClientQueryOptions = { + var ?includeUncontrolled : Bool; + var ?type : ClientType; } \ No newline at end of file diff --git a/std/js/html/ClientType.hx b/std/js/html/ClientType.hx new file mode 100644 index 00000000000..444f2510b40 --- /dev/null +++ b/std/js/html/ClientType.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\Clients.webidl. Do not edit! + +package js.html; + +enum abstract ClientType(String) { + var WINDOW = "window"; + var WORKER = "worker"; + var SHAREDWORKER = "sharedworker"; + var SERVICEWORKER = "serviceworker"; + var ALL = "all"; +} \ No newline at end of file diff --git a/std/js/html/Clients.hx b/std/js/html/Clients.hx index ba9535c1414..2d5d53099e7 100644 --- a/std/js/html/Clients.hx +++ b/std/js/html/Clients.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,29 +24,35 @@ package js.html; +import js.lib.Promise; + /** - The `Clients` interface of the Service Workers API represents a container for a list of `Client` objects. + The `Clients` interface provides access to `Client` objects. Access it via ``self`.clients` within a service worker. Documentation [Clients](https://developer.mozilla.org/en-US/docs/Web/API/Clients) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Clients$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("Clients") -extern class Clients -{ - +extern class Clients { + /** - Gets a service worker client matching a given `id` and returns it in a `Promise`. + Returns a `Promise` for a `Client` matching a given `Client.id`. **/ function get( id : String ) : Promise; - + /** - Gets a list of service worker clients and returns them in a `Promise`. Include the `options` parameter to return all service worker clients whose origin is the same as the associated service worker's origin. If `options` are not included, the method returns only the service worker clients controlled by the service worker.  + Returns a `Promise` for an array of `Client` objects. An options argument allows you to control the types of clients returned.  **/ function matchAll( ?options : ClientQueryOptions ) : Promise>; - + + /** + Opens a new browser window for a given url and returns a `Promise` for the new `WindowClient`. + **/ + function openWindow( url : String ) : Promise; + /** - Allows an active Service Worker to set itself as the active worker for a client page when the worker and the page are in the same scope.  + Allows an active service worker to set itself as the `ServiceWorkerContainer.controller` for all clients within its `ServiceWorkerRegistration.scope`.  **/ function claim() : Promise; } \ No newline at end of file diff --git a/std/js/html/Clipboard.hx b/std/js/html/Clipboard.hx new file mode 100644 index 00000000000..ee00461d1be --- /dev/null +++ b/std/js/html/Clipboard.hx @@ -0,0 +1,62 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\Clipboard.webidl. Do not edit! + +package js.html; + +import js.lib.Promise; + +/** + The `Clipboard` interface implements the Clipboard API, providing—if the user grants permission—both read and write access to the contents of the system clipboard. + + Documentation [Clipboard](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("Clipboard") +extern class Clipboard extends EventTarget { + + /** + Requests arbitrary data (such as images) from the clipboard, returning a `Promise`. When the data has been retrieved, the promise is resolved with a `DataTransfer` object that provides the data. + @throws DOMError + **/ + function read() : Promise; + + /** + Requests text from the system clipboard; returns a `Promise` which is resolved with a `DOMString` containing the clipboard's text once it's available. + @throws DOMError + **/ + function readText() : Promise; + + /** + Writes arbitrary data to the system clipboard. This asynchronous operation signals that it's finished by resolving the returned `Promise`. + @throws DOMError + **/ + function write( data : DataTransfer ) : Promise; + + /** + Writes text to the system clipboard, returning a `Promise` which is resolved once the text is fully copied into the clipboard. + @throws DOMError + **/ + function writeText( data : String ) : Promise; +} \ No newline at end of file diff --git a/std/js/html/ClipboardEvent.hx b/std/js/html/ClipboardEvent.hx index da5f9c61bcb..6e52531a248 100644 --- a/std/js/html/ClipboardEvent.hx +++ b/std/js/html/ClipboardEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("ClipboardEvent") -extern class ClipboardEvent extends Event -{ +extern class ClipboardEvent extends Event { /** Is a `DataTransfer` object containing the data affected by the user-initiated `cut`, `copy`, or `paste` operation, along with its MIME type. diff --git a/std/js/html/ClipboardEventInit.hx b/std/js/html/ClipboardEventInit.hx index 87ffbc32f8c..07cece3fd76 100644 --- a/std/js/html/ClipboardEventInit.hx +++ b/std/js/html/ClipboardEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,9 +24,7 @@ package js.html; -typedef ClipboardEventInit = -{ - > EventInit, - @:optional var data : String; - @:optional var dataType : String; +typedef ClipboardEventInit = EventInit & { + var ?data : String; + var ?dataType : String; } \ No newline at end of file diff --git a/std/js/html/CloseEvent.hx b/std/js/html/CloseEvent.hx index 752e41facdd..0ee0a7e24ff 100644 --- a/std/js/html/CloseEvent.hx +++ b/std/js/html/CloseEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("CloseEvent") -extern class CloseEvent extends Event -{ +extern class CloseEvent extends Event { /** Returns a `Boolean` that Indicates whether or not the connection was cleanly closed. @@ -41,122 +40,122 @@ extern class CloseEvent extends Event var wasClean(default,null) : Bool; /** - Returns an unsigned short containing the close code send by the server. The following values are permitted status codes. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Status codeNameDescription
0999 Reserved and not used.
1000CLOSE_NORMALNormal closure; the connection successfully completed whatever purpose for which it was created.
1001CLOSE_GOING_AWAYThe endpoint is going away, either because of a server failure or because the browser is navigating away from the page that opened the connection.
1002CLOSE_PROTOCOL_ERRORThe endpoint is terminating the connection due to a protocol error.
1003CLOSE_UNSUPPORTEDThe connection is being terminated because the endpoint received data of a type it cannot accept (for example, a text-only endpoint received binary data).
1004 Reserved. A meaning might be defined in the future.
1005CLOSE_NO_STATUSReserved.  Indicates that no status code was provided even though one was expected.
1006CLOSE_ABNORMALReserved. Used to indicate that a connection was closed abnormally (that is, with no close frame being sent) when a status code is expected.
1007Unsupported DataThe endpoint is terminating the connection because a message was received that contained inconsistent data (e.g., non-UTF-8 data within a text message).
1008Policy ViolationThe endpoint is terminating the connection because it received a message that violates its policy. This is a generic status code, used when codes 1003 and 1009 are not suitable.
1009CLOSE_TOO_LARGEThe endpoint is terminating the connection because a data frame was received that is too large.
1010Missing ExtensionThe client is terminating the connection because it expected the server to negotiate one or more extension, but the server didn't.
1011Internal ErrorThe server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.
1012Service RestartThe server is terminating the connection because it is restarting. [Ref]
1013Try Again LaterThe server is terminating the connection due to a temporary condition, e.g. it is overloaded and is casting off some of its clients. [Ref]
1014 Reserved for future use by the WebSocket standard.
1015TLS HandshakeReserved. Indicates that the connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).
10161999 Reserved for future use by the WebSocket standard.
20002999 Reserved for use by WebSocket extensions.
30003999 Available for use by libraries and frameworks. May not be used by applications. Available for registration at the IANA via first-come, first-serve.
40004999 Available for use by applications.
- + Returns an unsigned short containing the close code send by the server. The following values are permitted status codes. The following definitions are sourced from the IANA website [Ref]. Note that the 1xxx codes are only WebSocket-internal and not for the same meaning by the transported data (like when the application-layer protocol is invalid). The only permitted codes to be specified in Firefox are 1000 and 3000 to 4999 [Source, Bug]. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Status codeNameDescription
0999 Reserved and not used.
1000Normal ClosureNormal closure; the connection successfully completed whatever purpose for which it was created.
1001Going AwayThe endpoint is going away, either because of a server failure or because the browser is navigating away from the page that opened the connection.
1002Protocol ErrorThe endpoint is terminating the connection due to a protocol error.
1003Unsupported DataThe connection is being terminated because the endpoint received data of a type it cannot accept (for example, a text-only endpoint received binary data).
1004 Reserved. A meaning might be defined in the future.
1005No Status RecvdReserved.  Indicates that no status code was provided even though one was expected.
1006Abnormal ClosureReserved. Used to indicate that a connection was closed abnormally (that is, with no close frame being sent) when a status code is expected.
1007Invalid frame payload dataThe endpoint is terminating the connection because a message was received that contained inconsistent data (e.g., non-UTF-8 data within a text message).
1008Policy ViolationThe endpoint is terminating the connection because it received a message that violates its policy. This is a generic status code, used when codes 1003 and 1009 are not suitable.
1009Message too bigThe endpoint is terminating the connection because a data frame was received that is too large.
1010Missing ExtensionThe client is terminating the connection because it expected the server to negotiate one or more extension, but the server didn't.
1011Internal ErrorThe server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.
1012Service RestartThe server is terminating the connection because it is restarting. [Ref]
1013Try Again LaterThe server is terminating the connection due to a temporary condition, e.g. it is overloaded and is casting off some of its clients. [Ref]
1014Bad GatewayThe server was acting as a gateway or proxy and received an invalid response from the upstream server. This is similar to 502 HTTP Status Code.
1015TLS HandshakeReserved. Indicates that the connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).
10161999 Reserved for future use by the WebSocket standard.
20002999 Reserved for use by WebSocket extensions.
30003999 Available for use by libraries and frameworks. May not be used by applications. Available for registration at the IANA via first-come, first-serve.
40004999 Available for use by applications.
+ **/ var code(default,null) : Int; diff --git a/std/js/html/CloseEventInit.hx b/std/js/html/CloseEventInit.hx index 11bcd080cfa..7a33c7e5070 100644 --- a/std/js/html/CloseEventInit.hx +++ b/std/js/html/CloseEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,10 +24,8 @@ package js.html; -typedef CloseEventInit = -{ - > EventInit, - @:optional var code : Int; - @:optional var reason : String; - @:optional var wasClean : Bool; +typedef CloseEventInit = EventInit & { + var ?code : Int; + var ?reason : String; + var ?wasClean : Bool; } \ No newline at end of file diff --git a/std/js/html/Comment.hx b/std/js/html/Comment.hx index 675e435a46b..4042b115ed1 100644 --- a/std/js/html/Comment.hx +++ b/std/js/html/Comment.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("Comment") -extern class Comment extends CharacterData -{ +extern class Comment extends CharacterData { /** @throws DOMError */ - function new( ?data : String = "" ) : Void; + function new( data : String = "" ) : Void; } \ No newline at end of file diff --git a/std/js/html/CompositeOperation.hx b/std/js/html/CompositeOperation.hx index 4190eadb470..5dcdb0bd986 100644 --- a/std/js/html/CompositeOperation.hx +++ b/std/js/html/CompositeOperation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,12 +20,11 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\Keyframe.webidl. Do not edit! +// This file is generated from mozilla\BaseKeyframeTypes.webidl. Do not edit! package js.html; -@:enum abstract CompositeOperation(String) -{ +enum abstract CompositeOperation(String) { var REPLACE = "replace"; var ADD = "add"; var ACCUMULATE = "accumulate"; diff --git a/std/js/html/CompositionEvent.hx b/std/js/html/CompositionEvent.hx index c09a9ede880..77f24ef7dd0 100644 --- a/std/js/html/CompositionEvent.hx +++ b/std/js/html/CompositionEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,10 +32,23 @@ package js.html; @see **/ @:native("CompositionEvent") -extern class CompositionEvent extends UIEvent -{ +extern class CompositionEvent extends UIEvent { + + /** + Returns the characters generated by the input method that raised the event; its varies depending on the type of event that generated the `CompositionEvent` object. + **/ var data(default,null) : String; + + /** + Returns the locale of current input method (for example, the keyboard layout locale if the composition is associated with IME). + **/ var locale(default,null) : String; - function initCompositionEvent( typeArg : String, canBubbleArg : Bool, cancelableArg : Bool, viewArg : Window, dataArg : String, localeArg : String ) : Void; + /** @throws DOMError */ + function new( type : String, ?eventInitDict : CompositionEventInit ) : Void; + + /** + Initializes the attributes of a `CompositionEvent` object. + **/ + function initCompositionEvent( typeArg : String, canBubbleArg : Bool = false, cancelableArg : Bool = false, ?viewArg : Window, ?dataArg : String, localeArg : String = "" ) : Void; } \ No newline at end of file diff --git a/std/js/html/RecordErrorEventInit.hx b/std/js/html/CompositionEventInit.hx similarity index 85% rename from std/js/html/RecordErrorEventInit.hx rename to std/js/html/CompositionEventInit.hx index fafd0143e8f..37134c26070 100644 --- a/std/js/html/RecordErrorEventInit.hx +++ b/std/js/html/CompositionEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,12 +20,10 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\RecordErrorEvent.webidl. Do not edit! +// This file is generated from mozilla\CompositionEvent.webidl. Do not edit! package js.html; -typedef RecordErrorEventInit = -{ - > EventInit, - @:optional var name : String; +typedef CompositionEventInit = UIEventInit & { + var ?data : String; } \ No newline at end of file diff --git a/std/js/html/MessagePortList.hx b/std/js/html/ComputedEffectTiming.hx similarity index 79% rename from std/js/html/MessagePortList.hx rename to std/js/html/ComputedEffectTiming.hx index 7982e9a1ace..ba542df6121 100644 --- a/std/js/html/MessagePortList.hx +++ b/std/js/html/ComputedEffectTiming.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,14 +20,14 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\MessagePortList.webidl. Do not edit! +// This file is generated from mozilla\AnimationEffect.webidl. Do not edit! package js.html; -@:native("MessagePortList") -extern class MessagePortList implements ArrayAccess -{ - var length(default,null) : Int; - - function item( index : Int ) : MessagePort; +typedef ComputedEffectTiming = EffectTiming & { + var ?activeDuration : Float; + var ?currentIteration : Float; + var ?endTime : Float; + var ?localTime : Float; + var ?progress : Float; } \ No newline at end of file diff --git a/std/js/html/Console.hx b/std/js/html/Console.hx index 893c25a7b0b..4f265ad1e55 100644 --- a/std/js/html/Console.hx +++ b/std/js/html/Console.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,123 +25,131 @@ package js.html; /** - The `Console` object provides access to the browser's debugging console (e.g., the Web Console in Firefox). The specifics of how it works vary from browser to browser, but there is a de facto set of features that are typically provided. + The `Console` object provides access to the browser's debugging console (e.g. the Web Console in Firefox). The specifics of how it works varies from browser to browser, but there is a de facto set of features that are typically provided. - Documentation [Console](https://developer.mozilla.org/en-US/docs/Web/API/Console) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Console$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + Documentation [console](https://developer.mozilla.org/en-US/docs/Web/API/console) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/console$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). - @see + @see **/ -@:native("Console") -extern class Console -{ +@:native("console") +extern class Console { /** - For general output of logging information. You may use string substitution and additional arguments with this method. + Log a message and stack trace to console if the first argument is `false`. **/ - function log( data : haxe.extern.Rest ) : Void; + static function assert( condition : Bool = false, data : haxe.extern.Rest ) : Void; /** - Informative logging information. You may use string substitution and additional arguments with this method. + Clear the console. **/ - function info( data : haxe.extern.Rest ) : Void; + static function clear() : Void; /** - Outputs a warning message. You may use string substitution and additional arguments with this method. + Log the number of times this line has been called with the given label. + **/ + static function count( label : String = "default" ) : Void; + + /** + Resets the value of the counter with the given label. **/ - function warn( data : haxe.extern.Rest ) : Void; + static function countReset( label : String = "default" ) : Void; + + /** + Outputs a message to the console with the log level `"debug"`. + Note: Starting with Chromium 58 this method only appears in Chromium browser consoles when level "Verbose" is selected. + + **/ + static function debug( data : haxe.extern.Rest ) : Void; /** Outputs an error message. You may use string substitution and additional arguments with this method. **/ - function error( data : haxe.extern.Rest ) : Void; + static function error( data : haxe.extern.Rest ) : Void; /** - An alias for `error()` + Informative logging of information. You may use string substitution and additional arguments with this method. **/ - function exception( data : haxe.extern.Rest ) : Void; + static function info( data : haxe.extern.Rest ) : Void; /** - An alias for `log()` + For general output of logging information. You may use string substitution and additional arguments with this method. **/ - function debug( data : haxe.extern.Rest ) : Void; + static function log( data : haxe.extern.Rest ) : Void; /** Displays tabular data as a table. **/ - function table( data : haxe.extern.Rest ) : Void; + static function table( data : haxe.extern.Rest ) : Void; /** Outputs a stack trace. **/ - function trace() : Void; + static function trace( data : haxe.extern.Rest ) : Void; + + /** + Outputs a warning message. You may use string substitution and additional arguments with this method. + **/ + static function warn( data : haxe.extern.Rest ) : Void; /** Displays an interactive listing of the properties of a specified JavaScript object. This listing lets you use disclosure triangles to examine the contents of child objects. **/ - function dir( data : haxe.extern.Rest ) : Void; + static function dir( data : haxe.extern.Rest ) : Void; /** - Displays an XML/HTML Element representation of the specified object if possible or the JavaScript Object view if it is not. + Displays an XML/HTML Element representation of the specified object if possible or the JavaScript Object view if it is not possible. **/ - function dirxml( data : haxe.extern.Rest ) : Void; + static function dirxml( data : haxe.extern.Rest ) : Void; /** Creates a new inline group, indenting all following output by another level. To move back out a level, call `groupEnd()`. **/ - function group( data : haxe.extern.Rest ) : Void; + static function group( data : haxe.extern.Rest ) : Void; /** - Creates a new inline group, indenting all following output by another level; unlike `group()`, this starts with the inline group collapsed, requiring the use of a disclosure button to expand it. To move back out a level, call `groupEnd()`. + Creates a new inline group, indenting all following output by another level. However, unlike `group()` this starts with the inline group collapsed requiring the use of a disclosure button to expand it. To move back out a level, call `groupEnd()`. **/ - function groupCollapsed( data : haxe.extern.Rest ) : Void; + static function groupCollapsed( data : haxe.extern.Rest ) : Void; /** Exits the current inline group. **/ - function groupEnd( data : haxe.extern.Rest ) : Void; + static function groupEnd() : Void; /** Starts a timer with a name specified as an input parameter. Up to 10,000 simultaneous timers can run on a given page. **/ - function time( ?time : Dynamic ) : Void; - - /** - Stops the specified timer and logs the elapsed time in seconds since its start. - **/ - function timeEnd( ?time : Dynamic ) : Void; + static function time( label : String = "default" ) : Void; /** - Adds a marker to the browser's Timeline or Waterfall tool. + Logs the value of the specified timer to the console. **/ - function timeStamp( ?data : Dynamic ) : Void; + static function timeLog( label : String = "default", data : haxe.extern.Rest ) : Void; /** - Starts the browser's build-in profiler (for example, the Firefox performance tool). You can specify an optional name for the profile. + Stops the specified timer and logs the elapsed time in seconds since it started. **/ - function profile( data : haxe.extern.Rest ) : Void; + static function timeEnd( label : String = "default" ) : Void; /** - Stops the profiler. You can see the resulting profile in the browser's performance tool (for example, the Firefox performance tool). + An alias for `error()`. **/ - function profileEnd( data : haxe.extern.Rest ) : Void; + static function exception( data : haxe.extern.Rest ) : Void; /** - Log a message and stack trace to console if first argument is `false`. + Adds a marker to the browser's Timeline or Waterfall tool. **/ - function assert( condition : Bool, data : haxe.extern.Rest ) : Void; + static function timeStamp( ?data : Dynamic ) : Void; /** - Log the number of times this line has been called with the given label. + Starts the browser's built-in profiler (for example, the Firefox performance tool). You can specify an optional name for the profile. **/ - function count( data : haxe.extern.Rest ) : Void; + static function profile( data : haxe.extern.Rest ) : Void; /** - Clear the console. + Stops the profiler. You can see the resulting profile in the browser's performance tool (for example, the Firefox performance tool). **/ - function clear() : Void; - function markTimeline() : Void; - function timeline() : Void; - function timelineEnd() : Void; + static function profileEnd( data : haxe.extern.Rest ) : Void; } \ No newline at end of file diff --git a/std/js/html/ConsoleInstance.hx b/std/js/html/ConsoleInstance.hx new file mode 100644 index 00000000000..cded8ec89f9 --- /dev/null +++ b/std/js/html/ConsoleInstance.hx @@ -0,0 +1,154 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\Console.webidl. Do not edit! + +package js.html; + +/** + The `Console` object provides access to the browser's debugging console (e.g. the Web Console in Firefox). The specifics of how it works varies from browser to browser, but there is a de facto set of features that are typically provided. + + Documentation [Console](https://developer.mozilla.org/en-US/docs/Web/API/Console) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Console$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +extern interface ConsoleInstance { + + /** + Log a message and stack trace to console if the first argument is `false`. + **/ + function assert( condition : Bool = false, data : haxe.extern.Rest ) : Void; + + /** + Clear the console. + **/ + function clear() : Void; + + /** + Log the number of times this line has been called with the given label. + **/ + function count( label : String = "default" ) : Void; + + /** + Resets the value of the counter with the given label. + **/ + function countReset( label : String = "default" ) : Void; + + /** + Outputs a message to the console with the log level `"debug"`. + Note: Starting with Chromium 58 this method only appears in Chromium browser consoles when level "Verbose" is selected. + + **/ + function debug( data : haxe.extern.Rest ) : Void; + + /** + Outputs an error message. You may use string substitution and additional arguments with this method. + **/ + function error( data : haxe.extern.Rest ) : Void; + + /** + Informative logging of information. You may use string substitution and additional arguments with this method. + **/ + function info( data : haxe.extern.Rest ) : Void; + + /** + For general output of logging information. You may use string substitution and additional arguments with this method. + **/ + function log( data : haxe.extern.Rest ) : Void; + + /** + Displays tabular data as a table. + **/ + function table( data : haxe.extern.Rest ) : Void; + + /** + Outputs a stack trace. + **/ + function trace( data : haxe.extern.Rest ) : Void; + + /** + Outputs a warning message. You may use string substitution and additional arguments with this method. + **/ + function warn( data : haxe.extern.Rest ) : Void; + + /** + Displays an interactive listing of the properties of a specified JavaScript object. This listing lets you use disclosure triangles to examine the contents of child objects. + **/ + function dir( data : haxe.extern.Rest ) : Void; + + /** + + Displays an XML/HTML Element representation of the specified object if possible or the JavaScript Object view if it is not possible. + + **/ + function dirxml( data : haxe.extern.Rest ) : Void; + + /** + Creates a new inline group, indenting all following output by another level. To move back out a level, call `groupEnd()`. + **/ + function group( data : haxe.extern.Rest ) : Void; + + /** + Creates a new inline group, indenting all following output by another level. However, unlike `group()` this starts with the inline group collapsed requiring the use of a disclosure button to expand it. To move back out a level, call `groupEnd()`. + **/ + function groupCollapsed( data : haxe.extern.Rest ) : Void; + + /** + Exits the current inline group. + **/ + function groupEnd() : Void; + + /** + Starts a timer with a name specified as an input parameter. Up to 10,000 simultaneous timers can run on a given page. + **/ + function time( label : String = "default" ) : Void; + + /** + Logs the value of the specified timer to the console. + **/ + function timeLog( label : String = "default", data : haxe.extern.Rest ) : Void; + + /** + Stops the specified timer and logs the elapsed time in seconds since it started. + **/ + function timeEnd( label : String = "default" ) : Void; + + /** + An alias for `error()`. + **/ + function exception( data : haxe.extern.Rest ) : Void; + + /** + Adds a marker to the browser's Timeline or Waterfall tool. + **/ + function timeStamp( ?data : Dynamic ) : Void; + + /** + Starts the browser's built-in profiler (for example, the Firefox performance tool). You can specify an optional name for the profile. + **/ + function profile( data : haxe.extern.Rest ) : Void; + + /** + Stops the profiler. You can see the resulting profile in the browser's performance tool (for example, the Firefox performance tool). + **/ + function profileEnd( data : haxe.extern.Rest ) : Void; +} \ No newline at end of file diff --git a/std/js/html/ConstrainBooleanParameters.hx b/std/js/html/ConstrainBooleanParameters.hx new file mode 100644 index 00000000000..c1c731337f9 --- /dev/null +++ b/std/js/html/ConstrainBooleanParameters.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\MediaTrackConstraintSet.webidl. Do not edit! + +package js.html; + +typedef ConstrainBooleanParameters = { + var ?exact : Bool; + var ?ideal : Bool; +} \ No newline at end of file diff --git a/std/js/html/ConstrainDOMStringParameters.hx b/std/js/html/ConstrainDOMStringParameters.hx new file mode 100644 index 00000000000..9bc81a67f9a --- /dev/null +++ b/std/js/html/ConstrainDOMStringParameters.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\MediaTrackConstraintSet.webidl. Do not edit! + +package js.html; + +typedef ConstrainDOMStringParameters = { + var ?exact : haxe.extern.EitherType>; + var ?ideal : haxe.extern.EitherType>; +} \ No newline at end of file diff --git a/std/js/html/ConstrainDoubleRange.hx b/std/js/html/ConstrainDoubleRange.hx new file mode 100644 index 00000000000..7b96869918c --- /dev/null +++ b/std/js/html/ConstrainDoubleRange.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\MediaTrackConstraintSet.webidl. Do not edit! + +package js.html; + +typedef ConstrainDoubleRange = { + var ?exact : Float; + var ?ideal : Float; + var ?max : Float; + var ?min : Float; +} \ No newline at end of file diff --git a/std/js/html/ConstrainLongRange.hx b/std/js/html/ConstrainLongRange.hx new file mode 100644 index 00000000000..a83229a4d66 --- /dev/null +++ b/std/js/html/ConstrainLongRange.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\MediaTrackConstraintSet.webidl. Do not edit! + +package js.html; + +typedef ConstrainLongRange = { + var ?exact : Int; + var ?ideal : Int; + var ?max : Int; + var ?min : Int; +} \ No newline at end of file diff --git a/std/js/html/ConvertCoordinateOptions.hx b/std/js/html/ConvertCoordinateOptions.hx index 438ff08069b..f620587c143 100644 --- a/std/js/html/ConvertCoordinateOptions.hx +++ b/std/js/html/ConvertCoordinateOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -typedef ConvertCoordinateOptions = -{ - @:optional var fromBox : Dynamic/*MISSING CSSBoxType*/; - @:optional var toBox : Dynamic/*MISSING CSSBoxType*/; +typedef ConvertCoordinateOptions = { + var ?fromBox : CSSBoxType; + var ?toBox : CSSBoxType; } \ No newline at end of file diff --git a/std/js/html/Coordinates.hx b/std/js/html/Coordinates.hx index a8e23a028f6..e0d3677b136 100644 --- a/std/js/html/Coordinates.hx +++ b/std/js/html/Coordinates.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,9 +31,7 @@ package js.html; @see **/ -@:native("Coordinates") -extern class Coordinates -{ +typedef Coordinates = { /** Returns a `double` representing the position's latitude in decimal degrees. @@ -46,7 +44,7 @@ extern class Coordinates var longitude(default,null) : Float; /** - Returns a `double` representing the position's altitude in metres, relative to sea level. This value can be `null` if the implementation cannot provide the data. + Returns a `double` representing the position's altitude in meters, relative to sea level. This value can be `null` if the implementation cannot provide the data. **/ var altitude(default,null) : Float; diff --git a/std/js/html/Crypto.hx b/std/js/html/Crypto.hx index 5ab5ababa24..ad52941e37e 100644 --- a/std/js/html/Crypto.hx +++ b/std/js/html/Crypto.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,14 +32,17 @@ package js.html; @see **/ @:native("Crypto") -extern class Crypto -{ +extern class Crypto { /** Returns a `SubtleCrypto` object providing access to common cryptographic primitives, like hashing, signing, encryption or decryption. **/ var subtle(default,null) : SubtleCrypto; - /** @throws DOMError */ - function getRandomValues( array : ArrayBufferView ) : ArrayBufferView; + + /** + Fills the passed `TypedArray` with cryptographically sound random values. + @throws DOMError + **/ + function getRandomValues( array : js.lib.ArrayBufferView ) : js.lib.ArrayBufferView; } \ No newline at end of file diff --git a/std/js/html/CryptoKey.hx b/std/js/html/CryptoKey.hx index ba143b1c7ab..9ad095cca5a 100644 --- a/std/js/html/CryptoKey.hx +++ b/std/js/html/CryptoKey.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("CryptoKey") -extern class CryptoKey -{ +extern class CryptoKey { /** Returns an enumerated value representing the type of the key, a secret key (for symmetric algorithm), a public or a private key (for an asymmetric algorithm) diff --git a/std/js/html/CustomEvent.hx b/std/js/html/CustomEvent.hx index 9d74ae097d9..665a10993d3 100644 --- a/std/js/html/CustomEvent.hx +++ b/std/js/html/CustomEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("CustomEvent") -extern class CustomEvent extends Event -{ +extern class CustomEvent extends Event { /** Any data passed when initializing the event. @@ -42,12 +41,11 @@ extern class CustomEvent extends Event /** @throws DOMError */ function new( type : String, ?eventInitDict : CustomEventInit ) : Void; - /** @throws DOMError */ /** Initializes a `CustomEvent` object. If the event has already being dispatched, this method does nothing. **/ - function initCustomEvent( type : String, canBubble : Bool, cancelable : Bool, detail : Dynamic ) : Void; + function initCustomEvent( type : String, canBubble : Bool = false, cancelable : Bool = false, ?detail : Dynamic ) : Void; } \ No newline at end of file diff --git a/std/js/html/CustomEventInit.hx b/std/js/html/CustomEventInit.hx index 381f111c4bb..f7300598bb6 100644 --- a/std/js/html/CustomEventInit.hx +++ b/std/js/html/CustomEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,6 @@ package js.html; -typedef CustomEventInit = -{ - > EventInit, - @:optional var detail : Dynamic; +typedef CustomEventInit = EventInit & { + var ?detail : Dynamic; } \ No newline at end of file diff --git a/std/js/html/DListElement.hx b/std/js/html/DListElement.hx index 05a76ec29a5..540a6411fc7 100644 --- a/std/js/html/DListElement.hx +++ b/std/js/html/DListElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLDListElement") -extern class DListElement extends Element -{ +extern class DListElement extends Element { /** Is a `Boolean` indicating that spacing between list items should be reduced. diff --git a/std/js/html/DOMElement.hx b/std/js/html/DOMElement.hx index eb6dd65b12a..8b3c31e9ad7 100644 --- a/std/js/html/DOMElement.hx +++ b/std/js/html/DOMElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,21 +25,58 @@ package js.html; /** - The `Element` interface represents an object of a `Document`. This interface describes methods and properties common to all kinds of elements. Specific behaviors are described in interfaces which inherit from `Element` but add additional functionality. + `Element` is the most general base class from which all objects in a `Document` inherit. It only has methods and properties common to all kinds of elements. More specific classes inherit from `Element`. Documentation [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Element$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("Element") -extern class DOMElement extends Node -{ +extern class DOMElement extends Node { + + /** + The namespace URI of the element, or `null` if it is no namespace. + + Note: In Firefox 3.5 and earlier, HTML elements are in no namespace. In later versions, HTML elements are in the `http://www.w3.org/1999/xhtml` namespace in both HTML and XML trees. `1.9.2` + + + **/ + var namespaceURI(default,null) : String; + + /** + A `DOMString` representing the namespace prefix of the element, or `null` if no prefix is specified. + **/ + var prefix(default,null) : String; + + /** + A `DOMString` representing the local part of the qualified name of the element. + **/ + var localName(default,null) : String; + + /** + Returns a `String` with the name of the tag for the given element. + **/ var tagName(default,null) : String; + + /** + Is a `DOMString` representing the id of the element. + **/ var id : String; + + /** + Is a `DOMString` representing the class of the element. + **/ var className : String; + + /** + Returns a `DOMTokenList` containing the list of class attributes. + **/ var classList(default,null) : DOMTokenList; + + /** + Returns a `NamedNodeMap` object containing the assigned attributes of the corresponding HTML element. + **/ var attributes(default,null) : NamedNodeMap; - var onwheel : haxe.Constraints.Function; var title : String; var lang : String; var dir : String; @@ -70,31 +107,92 @@ extern class DOMElement extends Node var offsetLeft(default,null) : Int; var offsetWidth(default,null) : Int; var offsetHeight(default,null) : Int; + + /** + A `Number` representing number of pixels the top of the document is scrolled vertically. + **/ var scrollTop : Int; + + /** + Is a `Number` representing the left scroll offset of the element. + **/ var scrollLeft : Int; + + /** + Returns a `Number` representing the scroll view width of the element. + **/ var scrollWidth(default,null) : Int; + + /** + Returns a `Number` representing the scroll view height of an element. + **/ var scrollHeight(default,null) : Int; + + /** + Returns a `Number` representing the width of the top border of the element. + **/ var clientTop(default,null) : Int; + + /** + Returns a `Number` representing the width of the left border of the element. + **/ var clientLeft(default,null) : Int; + + /** + Returns a `Number` representing the inner width of the element. + **/ var clientWidth(default,null) : Int; + + /** + Returns a `Number` representing the inner height of the element. + **/ var clientHeight(default,null) : Int; + + /** + Returns a `Number` representing the maximum top scroll offset possible for the element. + **/ var scrollTopMax(default,null) : Int; + + /** + Returns a `Number` representing the maximum left scroll offset possible for the element. + **/ var scrollLeftMax(default,null) : Int; + + /** + Is a `DOMString` representing the markup of the element's content. + **/ var innerHTML : String; + + /** + Is a `DOMString` representing the markup of the element including its content. When used as a setter, replaces the element with nodes parsed from the given string. + **/ var outerHTML : String; + + /** + Returns the open shadow root that is hosted by the element, or null if no open shadow root is present. + **/ var shadowRoot(default,null) : ShadowRoot; + var assignedSlot(default,null) : SlotElement; + + /** + Returns the name of the shadow DOM slot the element is inserted in. + **/ + var slot : String; var onabort : haxe.Constraints.Function; var onblur : haxe.Constraints.Function; var onfocus : haxe.Constraints.Function; + var onauxclick : haxe.Constraints.Function; var oncanplay : haxe.Constraints.Function; var oncanplaythrough : haxe.Constraints.Function; var onchange : haxe.Constraints.Function; var onclick : haxe.Constraints.Function; + var onclose : haxe.Constraints.Function; var oncontextmenu : haxe.Constraints.Function; var ondblclick : haxe.Constraints.Function; var ondrag : haxe.Constraints.Function; var ondragend : haxe.Constraints.Function; var ondragenter : haxe.Constraints.Function; + var ondragexit : haxe.Constraints.Function; var ondragleave : haxe.Constraints.Function; var ondragover : haxe.Constraints.Function; var ondragstart : haxe.Constraints.Function; @@ -110,6 +208,7 @@ extern class DOMElement extends Node var onload : haxe.Constraints.Function; var onloadeddata : haxe.Constraints.Function; var onloadedmetadata : haxe.Constraints.Function; + var onloadend : haxe.Constraints.Function; var onloadstart : haxe.Constraints.Function; var onmousedown : haxe.Constraints.Function; var onmouseenter : haxe.Constraints.Function; @@ -118,6 +217,11 @@ extern class DOMElement extends Node var onmouseout : haxe.Constraints.Function; var onmouseover : haxe.Constraints.Function; var onmouseup : haxe.Constraints.Function; + + /** + Returns the event handling code for the `wheel` event. This is now implemented on `GlobalEventHandlers.onwheel`. + **/ + var onwheel : haxe.Constraints.Function; var onpause : haxe.Constraints.Function; var onplay : haxe.Constraints.Function; var onplaying : haxe.Constraints.Function; @@ -136,6 +240,8 @@ extern class DOMElement extends Node var ontimeupdate : haxe.Constraints.Function; var onvolumechange : haxe.Constraints.Function; var onwaiting : haxe.Constraints.Function; + var onselectstart : haxe.Constraints.Function; + var ontoggle : haxe.Constraints.Function; var onpointercancel : haxe.Constraints.Function; var onpointerdown : haxe.Constraints.Function; var onpointerup : haxe.Constraints.Function; @@ -144,12 +250,28 @@ extern class DOMElement extends Node var onpointerover : haxe.Constraints.Function; var onpointerenter : haxe.Constraints.Function; var onpointerleave : haxe.Constraints.Function; + + /** + Returns the event handler for the `gotpointercapture` event type. + **/ var ongotpointercapture : haxe.Constraints.Function; + + /** + Returns the event handler for the `lostpointercapture` event type. + **/ var onlostpointercapture : haxe.Constraints.Function; - var onfullscreenchange : haxe.Constraints.Function; - var onfullscreenerror : haxe.Constraints.Function; - var onpointerlockchange : haxe.Constraints.Function; - var onpointerlockerror : haxe.Constraints.Function; + var onanimationcancel : haxe.Constraints.Function; + var onanimationend : haxe.Constraints.Function; + var onanimationiteration : haxe.Constraints.Function; + var onanimationstart : haxe.Constraints.Function; + var ontransitioncancel : haxe.Constraints.Function; + var ontransitionend : haxe.Constraints.Function; + var ontransitionrun : haxe.Constraints.Function; + var ontransitionstart : haxe.Constraints.Function; + var onwebkitanimationend : haxe.Constraints.Function; + var onwebkitanimationiteration : haxe.Constraints.Function; + var onwebkitanimationstart : haxe.Constraints.Function; + var onwebkittransitionend : haxe.Constraints.Function; var previousElementSibling(default,null) : Element; var nextElementSibling(default,null) : Element; var onerror : haxe.Constraints.Function; @@ -162,95 +284,270 @@ extern class DOMElement extends Node var ontouchmove : haxe.Constraints.Function; var ontouchcancel : haxe.Constraints.Function; + + /** + Returns an array of attribute names from the current element. + **/ + @:pure function getAttributeNames() : Array; + + /** + Retrieves the value of the named attribute from the current node and returns it as an `Object`. + **/ + @:pure function getAttribute( name : String ) : String; - function getAttributeNS( namespace_ : String, localName : String ) : String; - /** @throws DOMError */ + + /** + Retrieves the value of the attribute with the specified name and namespace, from the current node and returns it as an `Object`. + **/ + @:pure + function getAttributeNS( namespace : String, localName : String ) : String; + + /** + Toggles a boolean attribute, removing it if it is present and adding it if it is not present, on the specified element. + @throws DOMError + **/ + function toggleAttribute( name : String, ?force : Bool ) : Bool; + + /** + Sets the value of a named attribute of the current node. + @throws DOMError + **/ function setAttribute( name : String, value : String ) : Void; - /** @throws DOMError */ - function setAttributeNS( namespace_ : String, name : String, value : String ) : Void; - /** @throws DOMError */ + + /** + Sets the value of the attribute with the specified name and namespace, from the current node. + @throws DOMError + **/ + function setAttributeNS( namespace : String, name : String, value : String ) : Void; + + /** + Removes the named attribute from the current node. + @throws DOMError + **/ function removeAttribute( name : String ) : Void; - /** @throws DOMError */ - function removeAttributeNS( namespace_ : String, localName : String ) : Void; + + /** + Removes the attribute with the specified name and namespace, from the current node. + @throws DOMError + **/ + function removeAttributeNS( namespace : String, localName : String ) : Void; + + /** + Returns a `Boolean` indicating if the element has the specified attribute or not. + **/ + @:pure function hasAttribute( name : String ) : Bool; - function hasAttributeNS( namespace_ : String, localName : String ) : Bool; + + /** + Returns a `Boolean` indicating if the element has the specified attribute, in the specified namespace, or not. + **/ + @:pure + function hasAttributeNS( namespace : String, localName : String ) : Bool; + + /** + Returns a `Boolean` indicating if the element has one or more HTML attributes present. + **/ + @:pure function hasAttributes() : Bool; - /** @throws DOMError */ + + /** + Returns the `Element` which is the closest ancestor of the current element (or the current element itself) which matches the selectors given in parameter. + @throws DOMError + **/ + @:pure function closest( selector : String ) : Element; - /** @throws DOMError */ + + /** + Returns a `Boolean` indicating whether or not the element would be selected by the specified selector string. + @throws DOMError + **/ + @:pure function matches( selector : String ) : Bool; /** @throws DOMError */ + @:pure function webkitMatchesSelector( selector : String ) : Bool; + + /** + Returns a live `HTMLCollection` containing all descendant elements, of a particular tag name, from the current element. + **/ + @:pure function getElementsByTagName( localName : String ) : HTMLCollection; - /** @throws DOMError */ - function getElementsByTagNameNS( namespace_ : String, localName : String ) : HTMLCollection; + + /** + Returns a live `HTMLCollection` containing all descendant elements, of a particular tag name and namespace, from the current element. + @throws DOMError + **/ + @:pure + function getElementsByTagNameNS( namespace : String, localName : String ) : HTMLCollection; + + /** + Returns a live `HTMLCollection` that contains all descendants of the current element that possess the list of classes given in the parameter. + **/ + @:pure function getElementsByClassName( classNames : String ) : HTMLCollection; - /** @throws DOMError */ /** - Designates a specific element as the capture target of future `PointerEvent`. + Inserts a given element node at a given position relative to the element it is invoked upon. + @throws DOMError + **/ + @:pure + function insertAdjacentElement( where : String, element : Element ) : Element; + + /** + Inserts a given text node at a given position relative to the element it is invoked upon. + @throws DOMError + **/ + function insertAdjacentText( where : String, data : String ) : Void; + + /** + Designates a specific element as the capture target of future pointer events. + @throws DOMError **/ function setPointerCapture( pointerId : Int ) : Void; - /** @throws DOMError */ + + /** + Releases (stops) pointer capture that was previously set for a specific `PointerEvent`. + @throws DOMError + **/ function releasePointerCapture( pointerId : Int ) : Void; - function setCapture( ?retargetToElement : Bool = false ) : Void; + function hasPointerCapture( pointerId : Int ) : Bool; + + /** + Sets up mouse event capture, redirecting all mouse events to this element. + **/ + function setCapture( retargetToElement : Bool = false ) : Void; function releaseCapture() : Void; - function requestPointerLock() : Void; + + /** + Retrieves the node representation of the named attribute from the current node and returns it as an `Attr`. + **/ function getAttributeNode( name : String ) : Attr; - /** @throws DOMError */ + + /** + Sets the node representation of the named attribute from the current node. + @throws DOMError + **/ function setAttributeNode( newAttr : Attr ) : Attr; - /** @throws DOMError */ + + /** + Removes the node representation of the named attribute from the current node. + @throws DOMError + **/ function removeAttributeNode( oldAttr : Attr ) : Attr; + + /** + Retrieves the node representation of the attribute with the specified name and namespace, from the current node and returns it as an `Attr`. + **/ function getAttributeNodeNS( namespaceURI : String, localName : String ) : Attr; - /** @throws DOMError */ + + /** + Sets the node representation of the attribute with the specified name and namespace, from the current node. + @throws DOMError + **/ function setAttributeNodeNS( newAttr : Attr ) : Attr; function click() : Void; /** @throws DOMError */ function focus() : Void; /** @throws DOMError */ function blur() : Void; + + /** + Returns a collection of rectangles that indicate the bounding rectangles for each line of text in a client. + **/ function getClientRects() : DOMRectList; + + /** + Returns the size of an element and its position relative to the viewport. + **/ function getBoundingClientRect() : DOMRect; - @:overload( function( top : Bool ) : Void {} ) - function scrollIntoView( ?options : ScrollIntoViewOptions ) : Void; + + /** + Scrolls the page until the element gets into the view. + **/ + @:overload( function( ?arg : ScrollIntoViewOptions) : Void {} ) + function scrollIntoView( ?arg : Bool ) : Void; @:overload( function( x : Float, y : Float ) : Void {} ) function scroll( ?options : ScrollToOptions ) : Void; @:overload( function( x : Float, y : Float ) : Void {} ) function scrollTo( ?options : ScrollToOptions ) : Void; @:overload( function( x : Float, y : Float ) : Void {} ) function scrollBy( ?options : ScrollToOptions ) : Void; - /** @throws DOMError */ + + /** + Parses the text as HTML or XML and inserts the resulting nodes into the tree in the position given. + @throws DOMError + **/ function insertAdjacentHTML( position : String, text : String ) : Void; - /** @throws DOMError */ + + /** + Returns the first `Node` which matches the specified selector string relative to the element. + @throws DOMError + **/ + @:pure function querySelector( selectors : String ) : Element; - /** @throws DOMError */ + + /** + Returns a `NodeList` of nodes which match the specified selector string relative to the element. + @throws DOMError + **/ + @:pure function querySelectorAll( selectors : String ) : NodeList; - /** @throws DOMError */ - function createShadowRoot() : ShadowRoot; /** - … + Attatches a shadow DOM tree to the specified element and returns a reference to its `ShadowRoot`. + @throws DOMError **/ - function getDestinationInsertionPoints() : NodeList; - /** @throws DOMError */ - function requestFullscreen( ?options : Dynamic ) : Void; - /** @throws DOMError */ + function attachShadow( shadowRootInitDict : ShadowRootInit ) : ShadowRoot; + + /** + Asynchronously asks the browser to make the element full-screen. + @throws DOMError + **/ + function requestFullscreen() : Void; + + /** + Allows to asynchronously ask for the pointer to be locked on the given element. + **/ + function requestPointerLock() : Void; /** A shortcut method to create and run an animation on an element. Returns the created Animation object instance. + @throws DOMError **/ - function animate( frames : Dynamic, ?options : haxe.extern.EitherType ) : Animation; + @:overload( function( keyframes : Dynamic, ?options : KeyframeAnimationOptions) : Animation {} ) + function animate( keyframes : Dynamic, ?options : Float ) : Animation; /** Returns an array of Animation objects currently active on the element. **/ - function getAnimations() : Array; + function getAnimations( ?filter : AnimationFilter ) : Array; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function before( nodes : haxe.extern.Rest ) : Void; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function after( nodes : haxe.extern.Rest ) : Void; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function replaceWith( nodes : haxe.extern.Rest ) : Void; function remove() : Void; /** @throws DOMError */ - function convertQuadFromNode( quad : DOMQuad, from : haxe.extern.EitherType>, ?options : ConvertCoordinateOptions ) : DOMQuad; + @:overload( function( quad : DOMQuad, from : Element, ?options : ConvertCoordinateOptions) : DOMQuad {} ) + @:overload( function( quad : DOMQuad, from : HTMLDocument, ?options : ConvertCoordinateOptions) : DOMQuad {} ) + function convertQuadFromNode( quad : DOMQuad, from : Text, ?options : ConvertCoordinateOptions ) : DOMQuad; + /** @throws DOMError */ + @:overload( function( rect : DOMRectReadOnly, from : Element, ?options : ConvertCoordinateOptions) : DOMQuad {} ) + @:overload( function( rect : DOMRectReadOnly, from : HTMLDocument, ?options : ConvertCoordinateOptions) : DOMQuad {} ) + function convertRectFromNode( rect : DOMRectReadOnly, from : Text, ?options : ConvertCoordinateOptions ) : DOMQuad; + /** @throws DOMError */ + @:overload( function( point : DOMPointInit, from : Element, ?options : ConvertCoordinateOptions) : DOMPoint {} ) + @:overload( function( point : DOMPointInit, from : HTMLDocument, ?options : ConvertCoordinateOptions) : DOMPoint {} ) + function convertPointFromNode( point : DOMPointInit, from : Text, ?options : ConvertCoordinateOptions ) : DOMPoint; /** @throws DOMError */ - function convertRectFromNode( rect : DOMRectReadOnly, from : haxe.extern.EitherType>, ?options : ConvertCoordinateOptions ) : DOMQuad; + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function prepend( nodes : haxe.extern.Rest ) : Void; /** @throws DOMError */ - function convertPointFromNode( point : DOMPointInit, from : haxe.extern.EitherType>, ?options : ConvertCoordinateOptions ) : DOMPoint; + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function append( nodes : haxe.extern.Rest ) : Void; } \ No newline at end of file diff --git a/std/js/html/DOMError.hx b/std/js/html/DOMError.hx index 620d181d5b5..d2d100a3887 100644 --- a/std/js/html/DOMError.hx +++ b/std/js/html/DOMError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,15 +32,18 @@ package js.html; @see **/ @:native("DOMError") -extern class DOMError -{ +extern class DOMError { /** Returns a `DOMString` representing one of the error type names (see below). **/ var name(default,null) : String; + + /** + Returns a `DOMString` representing a message or description associated with the given error type name. + **/ var message(default,null) : String; /** @throws DOMError */ - function new( name : String, ?message : String = "" ) : Void; + function new( name : String, message : String = "" ) : Void; } \ No newline at end of file diff --git a/std/js/html/DOMException.hx b/std/js/html/DOMException.hx index f916d101df8..5729e027d9f 100644 --- a/std/js/html/DOMException.hx +++ b/std/js/html/DOMException.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,15 +25,14 @@ package js.html; /** - The `DOMException` interface represents an abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. This is basically how error conditions are described in web APIs. + The `DOMException` interface represents an abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. Documentation [DOMException](https://developer.mozilla.org/en-US/docs/Web/API/DOMException) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMException$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("DOMException") -extern class DOMException -{ +extern class DOMException { static inline var INDEX_SIZE_ERR : Int = 1; static inline var DOMSTRING_SIZE_ERR : Int = 2; static inline var HIERARCHY_REQUEST_ERR : Int = 3; @@ -60,16 +59,28 @@ extern class DOMException static inline var INVALID_NODE_TYPE_ERR : Int = 24; static inline var DATA_CLONE_ERR : Int = 25; - var code(default,null) : Int; + + /** + Returns a `DOMString` that contains one of the strings associated with an error name. + **/ + var name(default,null) : String; + + /** + Returns a `DOMString` representing a message or description associated with the given error name. + **/ var message(default,null) : String; + + /** + Returns a `short` that contains one of the `Error codes`, or `0` if none match. This field is used for historical reasons. New DOM exceptions don't use this anymore: they put this info in the `DOMException.name` attribute. + **/ + var code(default,null) : Int; var result(default,null) : Int; - var name(default,null) : String; var filename(default,null) : String; var lineNumber(default,null) : Int; var columnNumber(default,null) : Int; - var data(default,null) : Dynamic/*MISSING nsISupports*/; + var data(default,null) : Dynamic; var stack(default,null) : String; /** @throws DOMError */ - function new( ?message : String = "", ?name : String ) : Void; + function new( message : String = "", ?name : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/DOMImplementation.hx b/std/js/html/DOMImplementation.hx index 23b8178d293..ae021c85f65 100644 --- a/std/js/html/DOMImplementation.hx +++ b/std/js/html/DOMImplementation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,29 +32,28 @@ package js.html; @see **/ @:native("DOMImplementation") -extern class DOMImplementation -{ +extern class DOMImplementation { /** Returns a `Boolean` indicating if a given feature is supported or not. This function is unreliable and kept for compatibility purpose alone: except for SVG-related queries, it always returns `true`. Old browsers are very inconsistent in their behavior. **/ - function hasFeature( feature : String, version : String ) : Bool; - /** @throws DOMError */ + function hasFeature() : Bool; /** Creates and returns a `DocumentType`. + @throws DOMError **/ function createDocumentType( qualifiedName : String, publicId : String, systemId : String ) : DocumentType; - /** @throws DOMError */ /** Creates and returns an `XMLDocument`. + @throws DOMError **/ - function createDocument( namespace_ : String, qualifiedName : String, ?doctype : DocumentType ) : HTMLDocument; - /** @throws DOMError */ + function createDocument( namespace : String, qualifiedName : String, ?doctype : DocumentType ) : HTMLDocument; /** Creates and returns an HTML `Document`. + @throws DOMError **/ function createHTMLDocument( ?title : String ) : HTMLDocument; } \ No newline at end of file diff --git a/std/js/html/DOMMatrix.hx b/std/js/html/DOMMatrix.hx index 2382e8b08bd..988908c430c 100644 --- a/std/js/html/DOMMatrix.hx +++ b/std/js/html/DOMMatrix.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,14 +32,13 @@ package js.html; @see **/ @:native("DOMMatrix") -extern class DOMMatrix extends DOMMatrixReadOnly -{ +extern class DOMMatrix extends DOMMatrixReadOnly { /** @throws DOMError */ @:overload( function() : Void {} ) @:overload( function( transformList : String ) : Void {} ) @:overload( function( other : DOMMatrixReadOnly ) : Void {} ) - @:overload( function( array32 : Float32Array ) : Void {} ) - @:overload( function( array64 : Float64Array ) : Void {} ) + @:overload( function( array32 : js.lib.Float32Array ) : Void {} ) + @:overload( function( array64 : js.lib.Float64Array ) : Void {} ) function new( numberSequence : Array ) : Void; function multiplySelf( other : DOMMatrix ) : DOMMatrix; function preMultiplySelf( other : DOMMatrix ) : DOMMatrix; @@ -47,27 +46,27 @@ extern class DOMMatrix extends DOMMatrixReadOnly /** Returns itself, a `DOMMatrix`, with its new content being the result of the matrix being translated by the given vector. **/ - function translateSelf( tx : Float, ty : Float, ?tz : Float = 0.0 ) : DOMMatrix; + function translateSelf( tx : Float, ty : Float, tz : Float = 0.0 ) : DOMMatrix; /** Returns itself, a `DOMMatrix`, with its new content being the result of the matrix x and y dimensions being scaled by the given factor, centered on the origin given. **/ - function scaleSelf( scale : Float, ?originX : Float = 0.0, ?originY : Float = 0.0 ) : DOMMatrix; + function scaleSelf( scale : Float, originX : Float = 0.0, originY : Float = 0.0 ) : DOMMatrix; /** Returns itself, a `DOMMatrix`, with its new content being the result of the matrix x, y and z dimension being scaled by the given factor, centered on the origin given. **/ - function scale3dSelf( scale : Float, ?originX : Float = 0.0, ?originY : Float = 0.0, ?originZ : Float = 0.0 ) : DOMMatrix; + function scale3dSelf( scale : Float, originX : Float = 0.0, originY : Float = 0.0, originZ : Float = 0.0 ) : DOMMatrix; /** Returns itself, a `DOMMatrix`, with its new content being the result of the matrix x, y and z dimension being scaled by the given factor for each dimension, centered on the origin given. **/ - function scaleNonUniformSelf( scaleX : Float, ?scaleY : Float = 1.0, ?scaleZ : Float = 1.0, ?originX : Float = 0.0, ?originY : Float = 0.0, ?originZ : Float = 0.0 ) : DOMMatrix; + function scaleNonUniformSelf( scaleX : Float, scaleY : Float = 1.0, scaleZ : Float = 1.0, originX : Float = 0.0, originY : Float = 0.0, originZ : Float = 0.0 ) : DOMMatrix; /** Returns itself, a `DOMMatrix`, with its new content being the result of the original matrix being rotated by the given angle, with the rotation centered on the origin given. **/ - function rotateSelf( angle : Float, ?originX : Float = 0.0, ?originY : Float = 0.0 ) : DOMMatrix; + function rotateSelf( angle : Float, originX : Float = 0.0, originY : Float = 0.0 ) : DOMMatrix; /** Returns itself, a `DOMMatrix`, with its new content being the result of the original matrix being rotated by the angle between the given vector and (1,0), centered on the origin given. @@ -93,10 +92,10 @@ extern class DOMMatrix extends DOMMatrixReadOnly Returns itself,  a `DOMMatrix`, with its new content being the result of the original matrix being inverted. If the matrix cannot be inverted, all its components are set to `NaN` and `is2D()` returns `false`. **/ function invertSelf() : DOMMatrix; - /** @throws DOMError */ /** Returns itself, a `DOMMatrix`, with its describing the matrix representing the same transformation as the CSS `transform` functions given in parameter. + @throws DOMError **/ function setMatrixValue( transformList : String ) : DOMMatrix; } \ No newline at end of file diff --git a/std/js/html/DOMMatrixReadOnly.hx b/std/js/html/DOMMatrixReadOnly.hx index 840621a4301..9d53f6584e2 100644 --- a/std/js/html/DOMMatrixReadOnly.hx +++ b/std/js/html/DOMMatrixReadOnly.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,46 +32,45 @@ package js.html; @see **/ @:native("DOMMatrixReadOnly") -extern class DOMMatrixReadOnly -{ +extern class DOMMatrixReadOnly { /** Are double representing each component of a 4x4 matrix needed for 2D rotations and translations. They are aliases for some components of the 4x4 matrix: - - - - 2D - 3D equivalent - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
am11
bm12
cm21
dm22
em41
fm42
- They are read-only, but their counterpart, with the same name, in DOMMatrix aren't. + + + + 2D + 3D equivalent + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
am11
bm12
cm21
dm22
em41
fm42
+ They are read-only, but their counterpart, with the same name, in DOMMatrix aren't. **/ var a(default,null) : Float; var b(default,null) : Float; @@ -104,33 +103,40 @@ extern class DOMMatrixReadOnly Is a `Boolean` indicating if the matrix contains a 2D matrix and only accept 2D transformations. **/ var is2D(default,null) : Bool; - var identity(default,null) : Bool; + /** + Is a `Boolean` indincating if the matrix identity, that is a matrix with `1` on the components of its diagonal, and `0` elsewhere. + **/ + var isIdentity(default,null) : Bool; + + /** @throws DOMError */ + @:overload( function( ?init : Array) : DOMMatrixReadOnly {} ) + function new( ?init : String ) : Void; /** Returns a `DOMMatrix` containing a new matrix being the result of the matrix being translated by the given vector. The original matrix is not modified. **/ - function translate( tx : Float, ty : Float, ?tz : Float = 0.0 ) : DOMMatrix; + function translate( tx : Float, ty : Float, tz : Float = 0.0 ) : DOMMatrix; /** Returns a `DOMMatrix` containing a new matrix being the result of the matrix x and y dimensions being scaled by the given factor, centered on the origin given. The original matrix is not modified. **/ - function scale( scale : Float, ?originX : Float = 0.0, ?originY : Float = 0.0 ) : DOMMatrix; + function scale( scale : Float, originX : Float = 0.0, originY : Float = 0.0 ) : DOMMatrix; /** Returns a `DOMMatrix` containing a new matrix being the result of the matrix x, y and z dimension being scaled by the given factor, centered on the origin given. The original matrix is not modified. **/ - function scale3d( scale : Float, ?originX : Float = 0.0, ?originY : Float = 0.0, ?originZ : Float = 0.0 ) : DOMMatrix; + function scale3d( scale : Float, originX : Float = 0.0, originY : Float = 0.0, originZ : Float = 0.0 ) : DOMMatrix; /** Returns a `DOMMatrix` containing a new matrix being the result of the matrix x, y and z dimension being scaled by the given factor for each dimension, centered on the origin given. The original matrix is not modified. **/ - function scaleNonUniform( scaleX : Float, ?scaleY : Float = 1.0, ?scaleZ : Float = 1.0, ?originX : Float = 0.0, ?originY : Float = 0.0, ?originZ : Float = 0.0 ) : DOMMatrix; + function scaleNonUniform( scaleX : Float, scaleY : Float = 1.0, scaleZ : Float = 1.0, originX : Float = 0.0, originY : Float = 0.0, originZ : Float = 0.0 ) : DOMMatrix; /** Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being rotated by the given angle, with the rotation centered on the origin given. The original matrix is not modified. **/ - function rotate( angle : Float, ?originX : Float = 0.0, ?originY : Float = 0.0 ) : DOMMatrix; + function rotate( angle : Float, originX : Float = 0.0, originY : Float = 0.0 ) : DOMMatrix; /** Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being rotated by the angle between the given vector and (1,0), centered on the origin given. The original matrix is not modified. @@ -138,7 +144,7 @@ extern class DOMMatrixReadOnly function rotateFromVector( x : Float, y : Float ) : DOMMatrix; /** - Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being rotated by the given angle and the give vector. The original matrix is not modified. + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being rotated by the given angle and the given vector. The original matrix is not modified. **/ function rotateAxisAngle( x : Float, y : Float, z : Float, angle : Float ) : DOMMatrix; @@ -166,22 +172,31 @@ extern class DOMMatrixReadOnly Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being flipped around the y-axis, that is multiplied by the `DOMMatrix(1, 0, 0, -1, 0, 0)`. The original matrix is not modified. **/ function flipY() : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being inverted. The original matrix is not modified. If the matrix cannot be inverted, all its components are set to `NaN` and `is2D()` returns `false`. + **/ function inverse() : DOMMatrix; /** - Returns a `DOMPoint` that is the point given in parameter multiplied by the matrix. Bot the original point and the matrix aren't modified. + Returns a `DOMPoint` that is the point given in parameter multiplied by the matrix. But the original point and the matrix aren't modified. **/ function transformPoint( ?point : DOMPointInit ) : DOMPoint; - /** @throws DOMError */ /** Returns a `Float32Array` containing the 6 components (`a`, `b`, `c`, `d`, `e`, `f`) in the case of a 2D matrix or the 16 components (`m11`, `m12`, `m13`, `m14`, `m21`, `m22`, `m23`, `m24`, `m31`, `m32`, `m33`, `m34`, `m41`, `m42`, `m43`, `m44`) for a 3D matrix. + @throws DOMError **/ - function toFloat32Array() : Float32Array; - /** @throws DOMError */ + function toFloat32Array() : js.lib.Float32Array; /** Returns a `Float64Array` containing the 6 components (`a`, `b`, `c`, `d`, `e`, `f`) in the case of a 2D matrix or the 16 components (`m11`, `m12`, `m13`, `m14`, `m21`, `m22`, `m23`, `m24`, `m31`, `m32`, `m33`, `m34`, `m41`, `m42`, `m43`, `m44`) for a 3D matrix. + @throws DOMError + **/ + function toFloat64Array() : js.lib.Float64Array; + + /** + Returns a JSON representation of the `DOMMatrixReadOnly` object. **/ - function toFloat64Array() : Float64Array; + function toJSON() : Dynamic; } \ No newline at end of file diff --git a/std/js/html/DOMParser.hx b/std/js/html/DOMParser.hx index c194a513938..23ac2fa4723 100644 --- a/std/js/html/DOMParser.hx +++ b/std/js/html/DOMParser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,18 +25,16 @@ package js.html; /** - `DOMParser` can parse XML or HTML source stored in a string into a DOM Document. `DOMParser` is specified in DOM Parsing and Serialization. + The `DOMParser` interface provides the ability to parse XML or HTML source code from a string into a DOM `Document`. Documentation [DOMParser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("DOMParser") -extern class DOMParser -{ +extern class DOMParser { /** @throws DOMError */ - @:overload( function() : Void {} ) - function new( prin : Dynamic/*MISSING Principal*/, ?documentURI : Dynamic/*MISSING URI*/, ?baseURI : Dynamic/*MISSING URI*/ ) : Void; + function new() : Void; /** @throws DOMError */ function parseFromString( str : String, type : SupportedType ) : HTMLDocument; } \ No newline at end of file diff --git a/std/js/html/DOMPoint.hx b/std/js/html/DOMPoint.hx index 6608b2bb549..efc7962ca71 100644 --- a/std/js/html/DOMPoint.hx +++ b/std/js/html/DOMPoint.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,16 +25,15 @@ package js.html; /** - A `DOMPoint` represents a 2D or 3D point in a coordinate system. + A `DOMPoint` object represents a 2D or 3D point in a coordinate system; it includes values for the coordinates in up to three dimensions, as well as an optional perspective value. Documentation [DOMPoint](https://developer.mozilla.org/en-US/docs/Web/API/DOMPoint) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMPoint$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("DOMPoint") -extern class DOMPoint extends DOMPointReadOnly -{ +extern class DOMPoint extends DOMPointReadOnly { + static function fromPoint( ?other : DOMPointInit ) : DOMPoint; /** @throws DOMError */ - @:overload( function( ?point : DOMPointInit ) : Void {} ) - function new( x : Float, y : Float, ?z : Float = 0.0, ?w : Float = 1.0 ) : Void; + function new( x : Float = 0.0, y : Float = 0.0, z : Float = 0.0, w : Float = 1.0 ) : Void; } \ No newline at end of file diff --git a/std/js/html/DOMPointInit.hx b/std/js/html/DOMPointInit.hx index 54dee931c2e..0c013b6d0cf 100644 --- a/std/js/html/DOMPointInit.hx +++ b/std/js/html/DOMPointInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,10 +24,32 @@ package js.html; -typedef DOMPointInit = -{ - @:optional var w : Float; - @:optional var x : Float; - @:optional var y : Float; - @:optional var z : Float; +/** + The `DOMPointInit` dictionary is used to provide the values of the coordinates and perspective when creating and JSONifying a `DOMPoint` or `DOMPointReadOnly` object. + + Documentation [DOMPointInit](https://developer.mozilla.org/en-US/docs/Web/API/DOMPointInit) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMPointInit$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +typedef DOMPointInit = { + + /** + The point's w perspective value given as an unrestricted floating-point number. The default is 1. + **/ + var ?w : Float; + + /** + An unrestricted floating-point value indicating the x-coordinate of the point in space. This is generally the horizontal coordinate, with positive values being to the right and negative values to the left. The default value is 0. + **/ + var ?x : Float; + + /** + An unrestricted floating-point number providing the point's y-coordinate. This is the vertical coordinate, and barring any transforms applied to the coordinate system, positive values are downward and negative values upward toward the top of the screen. The default is 0. + **/ + var ?y : Float; + + /** + An unrestricted floating-point value which gives the point's z-coordinate, which is (assuming no transformations that alter the situation) the depth coordinate; positive values are closer to the user and negative values retreat back into the screen. The default value is 0. + **/ + var ?z : Float; } \ No newline at end of file diff --git a/std/js/html/DOMPointReadOnly.hx b/std/js/html/DOMPointReadOnly.hx index 9a4f7c882df..ea0d32ab852 100644 --- a/std/js/html/DOMPointReadOnly.hx +++ b/std/js/html/DOMPointReadOnly.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,34 +25,41 @@ package js.html; /** - The `DOMPointReadOnly` interface specifies the standard properties used by `DOMPoint` to define a 2D or 3D point in a coordinate system. + The `DOMPointReadOnly` interface specifies the coordinate and perspective fields used by `DOMPoint` to define a 2D or 3D point in a coordinate system. Documentation [DOMPointReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/DOMPointReadOnly) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMPointReadOnly$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("DOMPointReadOnly") -extern class DOMPointReadOnly -{ +extern class DOMPointReadOnly { + static function fromPoint( ?other : DOMPointInit ) : DOMPointReadOnly; /** - The x coordinate of the `DOMPoint`. + The point's horizontal coordinate, `x`. **/ var x(default,null) : Float; /** - The y coordinate of the `DOMPoint`. + The point's vertical coordinate, `y`. **/ var y(default,null) : Float; /** - The z coordinate of the `DOMPoint`. + The point's depth coordinate, `z`. **/ var z(default,null) : Float; /** - The perspective value of the `DOMPoint`. + The point's perspective value, `w`. **/ var w(default,null) : Float; + /** @throws DOMError */ + function new( x : Float = 0.0, y : Float = 0.0, z : Float = 0.0, w : Float = 1.0 ) : Void; + + /** + Returns a JSON representation of the `DOMPointReadOnly` object. + **/ + function toJSON() : Dynamic; } \ No newline at end of file diff --git a/std/js/html/DOMQuad.hx b/std/js/html/DOMQuad.hx index 9915a5d748f..003bf1f2046 100644 --- a/std/js/html/DOMQuad.hx +++ b/std/js/html/DOMQuad.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,9 +24,19 @@ package js.html; +/** + A `DOMQuad` is a collection of four `DOMPoint`s defining the corners of an arbitrary quadrilateral. Returning `DOMQuad`s lets `getBoxQuads()` return accurate information even when arbitrary 2D or 3D transforms are present. It has a handy `bounds` attribute returning a `DOMRectReadOnly` for those cases where you just want an axis-aligned bounding rectangle. + + Documentation [DOMQuad](https://developer.mozilla.org/en-US/docs/Web/API/DOMQuad) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMQuad$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMQuad") -extern class DOMQuad -{ +extern class DOMQuad { + + /** + are `DOMPoint` objects for each of the `DOMQuad` object's four corners. + **/ var p1(default,null) : DOMPoint; var p2(default,null) : DOMPoint; var p3(default,null) : DOMPoint; @@ -36,4 +46,14 @@ extern class DOMQuad /** @throws DOMError */ @:overload( function( ?p1 : DOMPointInit, ?p2 : DOMPointInit, ?p3 : DOMPointInit, ?p4 : DOMPointInit ) : Void {} ) function new( rect : DOMRectReadOnly ) : Void; + + /** + Returns a `DOMRect` object with the coordinates and dimensions of the `DOMQuad` object. + **/ + function getBounds() : DOMRectReadOnly; + + /** + Returns a JSON representation of the `DOMQuad` object. + **/ + function toJSON() : DOMQuadJSON; } \ No newline at end of file diff --git a/std/js/html/DOMQuadJSON.hx b/std/js/html/DOMQuadJSON.hx new file mode 100644 index 00000000000..7f934fe77fa --- /dev/null +++ b/std/js/html/DOMQuadJSON.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\DOMQuad.webidl. Do not edit! + +package js.html; + +typedef DOMQuadJSON = { + var ?p1 : DOMPoint; + var ?p2 : DOMPoint; + var ?p3 : DOMPoint; + var ?p4 : DOMPoint; +} \ No newline at end of file diff --git a/std/js/html/DOMRect.hx b/std/js/html/DOMRect.hx index 5e3de87d483..ee6a154a2d0 100644 --- a/std/js/html/DOMRect.hx +++ b/std/js/html/DOMRect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,9 +32,7 @@ package js.html; @see **/ @:native("DOMRect") -extern class DOMRect extends DOMRectReadOnly -{ +extern class DOMRect extends DOMRectReadOnly { /** @throws DOMError */ - @:overload( function() : Void {} ) - function new( x : Float, y : Float, width : Float, height : Float ) : Void; + function new( x : Float = 0.0, y : Float = 0.0, width : Float = 0.0, height : Float = 0.0 ) : Void; } \ No newline at end of file diff --git a/std/js/html/DOMRectList.hx b/std/js/html/DOMRectList.hx index 01be0eb5b71..582a84973df 100644 --- a/std/js/html/DOMRectList.hx +++ b/std/js/html/DOMRectList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,8 +25,7 @@ package js.html; @:native("DOMRectList") -extern class DOMRectList implements ArrayAccess -{ +extern class DOMRectList implements ArrayAccess { var length(default,null) : Int; function item( index : Int ) : DOMRect; diff --git a/std/js/html/DOMRectReadOnly.hx b/std/js/html/DOMRectReadOnly.hx index 66f743e3ba1..f12cbe65b66 100644 --- a/std/js/html/DOMRectReadOnly.hx +++ b/std/js/html/DOMRectReadOnly.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("DOMRectReadOnly") -extern class DOMRectReadOnly -{ +extern class DOMRectReadOnly { /** The x coordinate of the `DOMRect`'s origin. @@ -75,4 +74,7 @@ extern class DOMRectReadOnly **/ var left(default,null) : Float; + /** @throws DOMError */ + function new( x : Float = 0.0, y : Float = 0.0, width : Float = 0.0, height : Float = 0.0 ) : Void; + function toJSON() : Dynamic; } \ No newline at end of file diff --git a/std/js/html/DOMRequest.hx b/std/js/html/DOMRequest.hx index 21b49822710..630bc86fb90 100644 --- a/std/js/html/DOMRequest.hx +++ b/std/js/html/DOMRequest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,11 +25,10 @@ package js.html; @:native("DOMRequest") -extern class DOMRequest extends EventTarget -{ +extern class DOMRequest extends EventTarget { var readyState(default,null) : DOMRequestReadyState; var result(default,null) : Dynamic; - var error(default,null) : DOMError; + var error(default,null) : DOMException; var onsuccess : haxe.Constraints.Function; var onerror : haxe.Constraints.Function; diff --git a/std/js/html/DOMRequestReadyState.hx b/std/js/html/DOMRequestReadyState.hx index 6935f2302ce..0fbe5ccaf9b 100644 --- a/std/js/html/DOMRequestReadyState.hx +++ b/std/js/html/DOMRequestReadyState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -@:enum abstract DOMRequestReadyState(String) -{ +enum abstract DOMRequestReadyState(String) { var PENDING = "pending"; var DONE = "done"; } \ No newline at end of file diff --git a/std/js/html/DOMStringList.hx b/std/js/html/DOMStringList.hx index 2b8c6bd9f3f..199603a5166 100644 --- a/std/js/html/DOMStringList.hx +++ b/std/js/html/DOMStringList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("DOMStringList") -extern class DOMStringList implements ArrayAccess -{ +extern class DOMStringList implements ArrayAccess { /** Returns the length of the list, diff --git a/std/js/html/DOMStringMap.hx b/std/js/html/DOMStringMap.hx index b4fed2b3acc..d80115f9ee0 100644 --- a/std/js/html/DOMStringMap.hx +++ b/std/js/html/DOMStringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,6 +32,5 @@ package js.html; @see **/ @:native("DOMStringMap") -extern class DOMStringMap implements Dynamic -{ +extern class DOMStringMap implements Dynamic { } \ No newline at end of file diff --git a/std/js/html/DOMTokenList.hx b/std/js/html/DOMTokenList.hx index 438d4fff6a7..4c2423cf379 100644 --- a/std/js/html/DOMTokenList.hx +++ b/std/js/html/DOMTokenList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,49 +25,63 @@ package js.html; /** - The `DOMTokenList` interface represents a set of space-separated tokens. Such a set is returned by `Element.classList`, `HTMLLinkElement.relList`, `HTMLAnchorElement.relList` or `HTMLAreaElement.relList`. It is indexed beginning with `0` as with JavaScript `Array` objects. `DOMTokenList` is always case-sensitive. + The `DOMTokenList` interface represents a set of space-separated tokens. Such a set is returned by `Element.classList`, `HTMLLinkElement.relList`, `HTMLAnchorElement.relList`, `HTMLAreaElement.relList`, `HTMLIframeElement.sandbox`, or `HTMLOutputElement.htmlFor`. It is indexed beginning with `0` as with JavaScript `Array` objects. `DOMTokenList` is always case-sensitive. Documentation [DOMTokenList](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("DOMTokenList") -extern class DOMTokenList implements ArrayAccess -{ +extern class DOMTokenList implements ArrayAccess { /** Is an `integer` representing the number of objects stored in the object. **/ var length(default,null) : Int; + + /** + The value of the list as a `DOMString`. + **/ var value : String; /** - Returns an item in the list by its index (or undefined if the number is greater than or equal to the length of the list, prior to `7.0` returned null) + Returns an item in the list by its index (returns undefined if the number is greater than or equal to the length of the list). **/ function item( index : Int ) : String; - /** @throws DOMError */ /** - Returns `true` if the underlying string contains token, otherwise `false` + Returns `true` if the list contains the given token, otherwise `false`. **/ function contains( token : String ) : Bool; - /** @throws DOMError */ /** - Adds token to the underlying string + Adds the given token to the list. + @throws DOMError **/ function add( tokens : haxe.extern.Rest ) : Void; - /** @throws DOMError */ /** - Removes token from the underlying string + Removes the specified token from the list. + @throws DOMError **/ function remove( tokens : haxe.extern.Rest ) : Void; - /** @throws DOMError */ /** - Removes token from string and returns false. If token doesn't exist it's added and the function returns true + Replaces an existing token with a new token. + @throws DOMError + **/ + function replace( token : String, newToken : String ) : Bool; + + /** + Removes a given token from the list and returns false. If token doesn't exist it's added and the function returns `true`. + @throws DOMError **/ function toggle( token : String, ?force : Bool ) : Bool; + + /** + Returns `true` if a given token is in the associated attribute's supported tokens. + @throws DOMError + **/ + function supports( token : String ) : Bool; } \ No newline at end of file diff --git a/std/js/html/DataElement.hx b/std/js/html/DataElement.hx index 2ee7b221b9f..ac53859ae69 100644 --- a/std/js/html/DataElement.hx +++ b/std/js/html/DataElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLDataElement") -extern class DataElement extends Element -{ +extern class DataElement extends Element { /** Is a `DOMString` reflecting the `value` HTML attribute, containing a machine-readable form of the element's value. diff --git a/std/js/html/DataListElement.hx b/std/js/html/DataListElement.hx index fa26bd177b1..f29888d35ba 100644 --- a/std/js/html/DataListElement.hx +++ b/std/js/html/DataListElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLDataListElement") -extern class DataListElement extends Element -{ +extern class DataListElement extends Element { /** Is a `HTMLCollection` representing a collection of the contained option elements. diff --git a/std/js/html/DataTransfer.hx b/std/js/html/DataTransfer.hx index 22ae84110c1..c296a87ede9 100644 --- a/std/js/html/DataTransfer.hx +++ b/std/js/html/DataTransfer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("DataTransfer") -extern class DataTransfer -{ +extern class DataTransfer { /** Gets the type of drag-and-drop operation currently selected or sets the operation to a new type. The value must be `none`, `copy`, `link` or `move`. @@ -45,10 +44,15 @@ extern class DataTransfer **/ var effectAllowed : String; + /** + Gives a `DataTransferItemList` object which is a list of all of the drag data. + **/ + var items(default,null) : DataTransferItemList; + /** An array of `DOMString` giving the formats that were set in the `dragstart` event. **/ - var types(default,null) : DOMStringList; + var types(default,null) : Array; /** Contains a list of all the local files available on the data transfer. If the drag operation doesn't involve dragging files, this property is an empty list. @@ -56,35 +60,34 @@ extern class DataTransfer var files(default,null) : FileList; /** @throws DOMError */ - function new( eventType : String, isExternal : Bool ) : Void; - /** @throws DOMError */ + function new() : Void; /** Set the image to be used for dragging if a custom one is desired. **/ function setDragImage( image : Element, x : Int, y : Int ) : Void; - /** @throws DOMError */ /** Retrieves the data for a given type, or an empty string if data for that type does not exist or the data transfer contains no data. + @throws DOMError **/ function getData( format : String ) : String; - /** @throws DOMError */ /** Set the data for a given type. If data for the type does not exist, it is added at the end, such that the last item in the types list will be the new format. If data for the type already exists, the existing data is replaced in the same position. + @throws DOMError **/ function setData( format : String, data : String ) : Void; - /** @throws DOMError */ /** Remove the data associated with a given type. The type argument is optional. If the type is empty or not specified, the data associated with all types is removed. If data for the specified type does not exist, or the data transfer contains no data, this method will have no effect. + @throws DOMError **/ function clearData( ?format : String ) : Void; - /** @throws DOMError */ /** Sets the drag source to the given element. + @throws DOMError **/ function addElement( element : Element ) : Void; } \ No newline at end of file diff --git a/std/js/html/DataTransferItem.hx b/std/js/html/DataTransferItem.hx new file mode 100644 index 00000000000..294fbf0cb7c --- /dev/null +++ b/std/js/html/DataTransferItem.hx @@ -0,0 +1,59 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\DataTransferItem.webidl. Do not edit! + +package js.html; + +/** + The `DataTransferItem` object represents one drag data item. During a drag operation, each `drag event` has a `dataTransfer` property which contains a `list` of drag data items. Each item in the list is a `DataTransferItem` object. + + Documentation [DataTransferItem](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("DataTransferItem") +extern class DataTransferItem { + + /** + The kind of drag data item, `string` or `file`. + **/ + var kind(default,null) : String; + + /** + The drag data item's type, typically a MIME type. + **/ + var type(default,null) : String; + + + /** + Invokes the specified callback with the drag data item string as its argument. + @throws DOMError + **/ + function getAsString( callback : String -> Void ) : Void; + + /** + Returns the `File` object associated with the drag data item (or null if the drag item is not a file). + @throws DOMError + **/ + function getAsFile() : File; +} \ No newline at end of file diff --git a/std/js/html/DataTransferItemList.hx b/std/js/html/DataTransferItemList.hx new file mode 100644 index 00000000000..74ca82687a2 --- /dev/null +++ b/std/js/html/DataTransferItemList.hx @@ -0,0 +1,61 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\DataTransferItemList.webidl. Do not edit! + +package js.html; + +/** + The `DataTransferItemList` object is a list of `DataTransferItem` objects representing items being dragged. During a drag operation, each `DragEvent` has a `dataTransfer` property and that property is a `DataTransferItemList`. + + Documentation [DataTransferItemList](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("DataTransferItemList") +extern class DataTransferItemList implements ArrayAccess { + + /** + An `unsigned long` that is the number of drag items in the list. + **/ + var length(default,null) : Int; + + + /** + Adds an item (either a `File` object or a `DOMString`) to the drag item list and returns a `DataTransferItem` object for the new item. + @throws DOMError + **/ + @:overload( function( data : String, type : String ) : DataTransferItem {} ) + function add( data : File ) : DataTransferItem; + + /** + Removes the drag item from the list at the given index. + @throws DOMError + **/ + function remove( index : Int ) : Void; + + /** + Removes all of the drag items from the list. + @throws DOMError + **/ + function clear() : Void; +} \ No newline at end of file diff --git a/std/js/html/DataView.hx b/std/js/html/DataView.hx index 5e7643db4f1..9c7af11538b 100644 --- a/std/js/html/DataView.hx +++ b/std/js/html/DataView.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,32 +20,6 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl. Do not edit! - package js.html; -// Explicitly include the compatibility class -import js.html.compat.DataView; - -@:native("DataView") -extern class DataView extends ArrayBufferView -{ - /** @throws DOMError */ - function new( buffer : ArrayBuffer, ?byteOffset : Int, ?byteLength : Int ) : Void; - @:pure function getInt8( byteOffset : Int ) : Int; - @:pure function getUint8( byteOffset : Int ) : Int; - @:pure function getInt16( byteOffset : Int, ?littleEndian : Bool ) : Int; - @:pure function getUint16( byteOffset : Int, ?littleEndian : Bool ) : Int; - @:pure function getInt32( byteOffset : Int, ?littleEndian : Bool ) : Int; - @:pure function getUint32( byteOffset : Int, ?littleEndian : Bool ) : Int; - @:pure function getFloat32( byteOffset : Int, ?littleEndian : Bool ) : Float; - @:pure function getFloat64( byteOffset : Int, ?littleEndian : Bool ) : Float; - function setInt8( byteOffset : Int, value : Int ) : Void; - function setUint8( byteOffset : Int, value : Int ) : Void; - function setInt16( byteOffset : Int, value : Int, ?littleEndian : Bool ) : Void; - function setUint16( byteOffset : Int, value : Int, ?littleEndian : Bool ) : Void; - function setInt32( byteOffset : Int, value : Int, ?littleEndian : Bool ) : Void; - function setUint32( byteOffset : Int, value : Int, ?littleEndian : Bool ) : Void; - function setFloat32( byteOffset : Int, value : Float, ?littleEndian : Bool ) : Void; - function setFloat64( byteOffset : Int, value : Float, ?littleEndian : Bool ) : Void; -} \ No newline at end of file +@:deprecated typedef DataView = js.lib.DataView; diff --git a/std/js/html/DedicatedWorkerGlobalScope.hx b/std/js/html/DedicatedWorkerGlobalScope.hx index 944cb1d5157..fc9e709457c 100644 --- a/std/js/html/DedicatedWorkerGlobalScope.hx +++ b/std/js/html/DedicatedWorkerGlobalScope.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,14 +32,32 @@ package js.html; @see **/ @:native("DedicatedWorkerGlobalScope") -extern class DedicatedWorkerGlobalScope extends WorkerGlobalScope -{ +extern class DedicatedWorkerGlobalScope extends WorkerGlobalScope { + + /** + The name that the `Worker` was (optionally) given when it was created using the `Worker.Worker` constructor. This is mainly useful for debugging purposes. + **/ + var name(default,null) : String; /** Is an `EventHandler` representing the code to be called when the `message` event is raised. These events are of type `MessageEvent` and will be called when the worker receives a message from the document that started it (i.e. from the `Worker.postMessage` method.) **/ var onmessage : haxe.Constraints.Function; - /** @throws DOMError */ + /** + Is an `EventHandler` representing the code to be called when the `messageerror` event is raised. + **/ + var onmessageerror : haxe.Constraints.Function; + + + /** + Sends a message — which can consist of `any` JavaScript object — to the parent document that first spawned the worker. + @throws DOMError + **/ function postMessage( message : Dynamic, ?transfer : Array ) : Void; + + /** + Discards any tasks queued in the `WorkerGlobalScope`'s event loop, effectively closing this particular scope. + **/ + function close() : Void; } \ No newline at end of file diff --git a/std/js/html/ContentElement.hx b/std/js/html/DetailsElement.hx similarity index 57% rename from std/js/html/ContentElement.hx rename to std/js/html/DetailsElement.hx index eaade2108c1..6f246118849 100644 --- a/std/js/html/ContentElement.hx +++ b/std/js/html/DetailsElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,29 +20,23 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\HTMLContentElement.webidl. Do not edit! +// This file is generated from mozilla\HTMLDetailsElement.webidl. Do not edit! package js.html; /** - The `HTMLContentElement` interface represents a `content` HTML Element, which is used in Shadow DOM. + The `HTMLDetailsElement` interface provides special properties (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating `details` elements. - Documentation [HTMLContentElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLContentElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLContentElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + Documentation [HTMLDetailsElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDetailsElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDetailsElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). - @see + @see **/ -@:native("HTMLContentElement") -extern class ContentElement extends Element -{ +@:native("HTMLDetailsElement") +extern class DetailsElement extends Element { /** - Is a `DOMString` that reflects the `select` HTML attribute. The value is a comma-separated list of CSS selectors that select the content to insert in place of the `content` element. + Is a `boolean` reflecting the `open` HTML attribute, indicating whether or not the element’s contents (not counting the `summary`) is to be shown to the user. **/ - var select : String; + var open : Bool; - - /** - Returns a static `NodeList` of the `distributed nodes` associated with this `content` element.  - **/ - function getDistributedNodes() : NodeList; } \ No newline at end of file diff --git a/std/js/html/DeviceAcceleration.hx b/std/js/html/DeviceAcceleration.hx index ae83f1ac40a..9b82d24d18a 100644 --- a/std/js/html/DeviceAcceleration.hx +++ b/std/js/html/DeviceAcceleration.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,9 +31,7 @@ package js.html; @see **/ -@:native("DeviceAcceleration") -extern class DeviceAcceleration -{ +typedef DeviceAcceleration = { /** The amount of acceleration along the X axis. Read only. diff --git a/std/js/html/DeviceAccelerationInit.hx b/std/js/html/DeviceAccelerationInit.hx index 3f904339236..6407388b82a 100644 --- a/std/js/html/DeviceAccelerationInit.hx +++ b/std/js/html/DeviceAccelerationInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,9 +24,8 @@ package js.html; -typedef DeviceAccelerationInit = -{ - @:optional var x : Float; - @:optional var y : Float; - @:optional var z : Float; +typedef DeviceAccelerationInit = { + var ?x : Float; + var ?y : Float; + var ?z : Float; } \ No newline at end of file diff --git a/std/js/html/DeviceMotionEvent.hx b/std/js/html/DeviceMotionEvent.hx index 6be1a83e831..9b2fd0ee022 100644 --- a/std/js/html/DeviceMotionEvent.hx +++ b/std/js/html/DeviceMotionEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("DeviceMotionEvent") -extern class DeviceMotionEvent extends Event -{ +extern class DeviceMotionEvent extends Event { /** An object giving the acceleration of the device on the three axis X, Y and Z. Acceleration is expressed in m/s2. @@ -46,7 +45,7 @@ extern class DeviceMotionEvent extends Event var accelerationIncludingGravity(default,null) : DeviceAcceleration; /** - An object giving the rate of change of the device's orientation on the three orientation axis alpha, beta and gamma. Rotation rate is express in degrees per seconds. + An object giving the rate of change of the device's orientation on the three orientation axis alpha, beta and gamma. Rotation rate is expressed in degrees per seconds. **/ var rotationRate(default,null) : DeviceRotationRate; @@ -57,5 +56,5 @@ extern class DeviceMotionEvent extends Event /** @throws DOMError */ function new( type : String, ?eventInitDict : DeviceMotionEventInit ) : Void; - function initDeviceMotionEvent( type : String, canBubble : Bool, cancelable : Bool, acceleration : DeviceAccelerationInit, accelerationIncludingGravity : DeviceAccelerationInit, rotationRate : DeviceRotationRateInit, interval : Float ) : Void; + function initDeviceMotionEvent( type : String, canBubble : Bool = false, cancelable : Bool = false, ?acceleration : DeviceAccelerationInit, ?accelerationIncludingGravity : DeviceAccelerationInit, ?rotationRate : DeviceRotationRateInit, ?interval : Float ) : Void; } \ No newline at end of file diff --git a/std/js/html/DeviceMotionEventInit.hx b/std/js/html/DeviceMotionEventInit.hx index ba1c89a0412..a12ba420adb 100644 --- a/std/js/html/DeviceMotionEventInit.hx +++ b/std/js/html/DeviceMotionEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,11 +24,9 @@ package js.html; -typedef DeviceMotionEventInit = -{ - > EventInit, - @:optional var acceleration : DeviceAccelerationInit; - @:optional var accelerationIncludingGravity : DeviceAccelerationInit; - @:optional var interval : Float; - @:optional var rotationRate : DeviceRotationRateInit; +typedef DeviceMotionEventInit = EventInit & { + var ?acceleration : DeviceAccelerationInit; + var ?accelerationIncludingGravity : DeviceAccelerationInit; + var ?interval : Float; + var ?rotationRate : DeviceRotationRateInit; } \ No newline at end of file diff --git a/std/js/html/DeviceOrientationEvent.hx b/std/js/html/DeviceOrientationEvent.hx index 31c6735da18..abd17758ce3 100644 --- a/std/js/html/DeviceOrientationEvent.hx +++ b/std/js/html/DeviceOrientationEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,11 +32,10 @@ package js.html; @see **/ @:native("DeviceOrientationEvent") -extern class DeviceOrientationEvent extends Event -{ +extern class DeviceOrientationEvent extends Event { /** - A number representing the motion of the device around the z axis, express in degrees with values ranging from 0 to 360 + A number representing the motion of the device around the z axis, express in degrees with values ranging from 0 to 360. **/ var alpha(default,null) : Float; @@ -57,5 +56,5 @@ extern class DeviceOrientationEvent extends Event /** @throws DOMError */ function new( type : String, ?eventInitDict : DeviceOrientationEventInit ) : Void; - function initDeviceOrientationEvent( type : String, canBubble : Bool, cancelable : Bool, alpha : Float, beta : Float, gamma : Float, absolute : Bool ) : Void; + function initDeviceOrientationEvent( type : String, canBubble : Bool = false, cancelable : Bool = false, ?alpha : Float, ?beta : Float, ?gamma : Float, absolute : Bool = false ) : Void; } \ No newline at end of file diff --git a/std/js/html/DeviceOrientationEventInit.hx b/std/js/html/DeviceOrientationEventInit.hx index a47d594902c..34d7f7b0c96 100644 --- a/std/js/html/DeviceOrientationEventInit.hx +++ b/std/js/html/DeviceOrientationEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,11 +24,9 @@ package js.html; -typedef DeviceOrientationEventInit = -{ - > EventInit, - @:optional var absolute : Bool; - @:optional var alpha : Float; - @:optional var beta : Float; - @:optional var gamma : Float; +typedef DeviceOrientationEventInit = EventInit & { + var ?absolute : Bool; + var ?alpha : Float; + var ?beta : Float; + var ?gamma : Float; } \ No newline at end of file diff --git a/std/js/html/DeviceRotationRate.hx b/std/js/html/DeviceRotationRate.hx index 17d6d18355a..dd6d6f5d471 100644 --- a/std/js/html/DeviceRotationRate.hx +++ b/std/js/html/DeviceRotationRate.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,11 +31,21 @@ package js.html; @see **/ -@:native("DeviceRotationRate") -extern class DeviceRotationRate -{ +typedef DeviceRotationRate = { + + /** + The amount of rotation around the Z axis, in degrees per second. + **/ var alpha(default,null) : Float; + + /** + The amount of rotation around the X axis, in degrees per second. + **/ var beta(default,null) : Float; + + /** + The amount of rotation around the Y axis, in degrees per second. + **/ var gamma(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/DeviceRotationRateInit.hx b/std/js/html/DeviceRotationRateInit.hx index 180cb1023a3..1cc295efd3c 100644 --- a/std/js/html/DeviceRotationRateInit.hx +++ b/std/js/html/DeviceRotationRateInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,9 +24,8 @@ package js.html; -typedef DeviceRotationRateInit = -{ - @:optional var alpha : Float; - @:optional var beta : Float; - @:optional var gamma : Float; +typedef DeviceRotationRateInit = { + var ?alpha : Float; + var ?beta : Float; + var ?gamma : Float; } \ No newline at end of file diff --git a/std/js/html/DirectionSetting.hx b/std/js/html/DirectionSetting.hx index b9027c70158..8a4cb3eec37 100644 --- a/std/js/html/DirectionSetting.hx +++ b/std/js/html/DirectionSetting.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -@:enum abstract DirectionSetting(String) -{ +enum abstract DirectionSetting(String) { var NONE = ""; var RL = "rl"; var LR = "lr"; diff --git a/std/js/html/Directory.hx b/std/js/html/Directory.hx index 149e7cb1c81..719d3559727 100644 --- a/std/js/html/Directory.hx +++ b/std/js/html/Directory.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,11 +24,17 @@ package js.html; +import js.lib.Promise; + @:native("Directory") -extern class Directory -{ +extern class Directory { var name(default,null) : String; var path(default,null) : String; - + + /** @throws DOMError */ + function new( path : String ) : Void; + /** @throws DOMError */ function getFilesAndDirectories() : Promise>>; + /** @throws DOMError */ + function getFiles( recursiveFlag : Bool = false ) : Promise>; } \ No newline at end of file diff --git a/std/js/html/DirectoryElement.hx b/std/js/html/DirectoryElement.hx index 0e54e1dc455..35b993f0495 100644 --- a/std/js/html/DirectoryElement.hx +++ b/std/js/html/DirectoryElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,8 +25,7 @@ package js.html; @:native("HTMLDirectoryElement") -extern class DirectoryElement extends Element -{ +extern class DirectoryElement extends Element { var compact : Bool; } \ No newline at end of file diff --git a/std/js/html/DisplayNameOptions.hx b/std/js/html/DisplayNameOptions.hx new file mode 100644 index 00000000000..b91e0e11cc6 --- /dev/null +++ b/std/js/html/DisplayNameOptions.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\IntlUtils.webidl. Do not edit! + +package js.html; + +typedef DisplayNameOptions = { + var ?keys : Array; + var ?style : String; +} \ No newline at end of file diff --git a/std/js/html/DisplayNameResult.hx b/std/js/html/DisplayNameResult.hx new file mode 100644 index 00000000000..d5e8a60ff43 --- /dev/null +++ b/std/js/html/DisplayNameResult.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\IntlUtils.webidl. Do not edit! + +package js.html; + +typedef DisplayNameResult = { + var ?locale : String; + var ?style : String; + var ?values : haxe.DynamicAccess; +} \ No newline at end of file diff --git a/std/js/html/DivElement.hx b/std/js/html/DivElement.hx index 85598fa3bb5..ac1adbaf7c8 100644 --- a/std/js/html/DivElement.hx +++ b/std/js/html/DivElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLDivElement") -extern class DivElement extends Element -{ +extern class DivElement extends Element { /** Is a `DOMString` representing an enumerated property indicating alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, `"justify"`, and `"center"`. diff --git a/std/js/html/Document.hx b/std/js/html/Document.hx index c1362995fcd..8085da99d97 100644 --- a/std/js/html/Document.hx +++ b/std/js/html/Document.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,15 +25,14 @@ package js.html; /** - The `Document` interface represents any web page loaded in the browser and serves as an entry point into the web page's content, which is the DOM tree. The DOM tree includes elements such as `body` and `table`, among many others. It provides functionality global to the document, like how to obtain the page's URL and create new elements in the document. + The `Document` interface represents any web page loaded in the browser and serves as an entry point into the web page's content, which is the DOM tree.`HTMLElement` Documentation [Document](https://developer.mozilla.org/en-US/docs/Web/API/Document) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Document$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("Document") -extern class Document extends Node -{ +extern class Document extends Node { /** Returns the DOM implementation associated with the current document. @@ -81,7 +80,7 @@ extern class Document extends Node var doctype(default,null) : DocumentType; /** - Returns the `Element` that is a direct child of the document. For HTML documents, this is normally the `html` element. + Returns the `Element` that is a direct child of the document. For HTML documents, this is normally the `HTMLElement` element. **/ var documentElement(default,null) : Element; @@ -106,7 +105,7 @@ extern class Document extends Node var readyState(default,null) : String; /** - Sets or gets title of the current document. + Sets or gets the title of the current document. **/ var title : String; @@ -116,39 +115,54 @@ extern class Document extends Node var dir : String; /** - Returns a reference to the window object. + Returns the `body` or `frameset` node of the current document. **/ - var defaultView(default,null) : Window; + var body : Element; /** - Returns the currently focused element. + Returns the `head` element of the current document. **/ - var activeElement(default,null) : Element; + var head(default,null) : HeadElement; /** - Represents the event handling code for the `readystatechange` event. + Returns a list of the images in the current document. **/ - var onreadystatechange : haxe.Constraints.Function; + var images(default,null) : HTMLCollection; /** - Represents the event handling code for the `wheel` event. + Returns a list of the embedded `embed` elements within the current document. **/ - var onwheel : haxe.Constraints.Function; + var embeds(default,null) : HTMLCollection; /** - Represents the event handling code for the `copy` event. + Returns a list of the available plugins. **/ - var oncopy : haxe.Constraints.Function; + var plugins(default,null) : HTMLCollection; /** - Represents the event handling code for the `cut` event. + Returns a list of all the hyperlinks in the document. **/ - var oncut : haxe.Constraints.Function; + var links(default,null) : HTMLCollection; /** - Represents the event handling code for the `paste` event. + Returns a list of the `form` elements within the current document. **/ - var onpaste : haxe.Constraints.Function; + var forms(default,null) : HTMLCollection; + + /** + Returns all the `script` elements on the document. + **/ + var scripts(default,null) : HTMLCollection; + + /** + Returns a reference to the window object. + **/ + var defaultView(default,null) : Window; + + /** + Represents the event handling code for the `readystatechange` event. + **/ + var onreadystatechange : haxe.Constraints.Function; /** Represents the event handling code for the `beforescriptexecute` event. @@ -159,14 +173,48 @@ extern class Document extends Node Represents the event handling code for the `afterscriptexecute` event. **/ var onafterscriptexecute : haxe.Constraints.Function; + + /** + Is an `EventHandler` representing the code to be called when the `selectionchange` event is raised. + **/ + var onselectionchange : haxe.Constraints.Function; var currentScript(default,null) : Element; + + /** + Returns a list of all of the anchors in the document. + **/ + var anchors(default,null) : HTMLCollection; + + /** + Returns an ordered list of the applets within a document. + **/ + var applets(default,null) : HTMLCollection; + + /** + `true` when the document is in `Using_full-screen_mode`. + **/ + var fullscreen(default,null) : Bool; var fullscreenEnabled(default,null) : Bool; - var fullscreenElement(default,null) : Element; /** - Returns the element set as the target for mouse events while the pointer is locked. `null` if lock is pending, pointer is unlocked, or if the target is in another document. + Is an `EventHandler` representing the code to be called when the `fullscreenchange` event is raised. **/ - var pointerLockElement(default,null) : Element; + var onfullscreenchange : haxe.Constraints.Function; + + /** + Is an `EventHandler` representing the code to be called when the `fullscreenerror` event is raised. + **/ + var onfullscreenerror : haxe.Constraints.Function; + + /** + Represents the event handling code for the `pointerlockchange` event. + **/ + var onpointerlockchange : haxe.Constraints.Function; + + /** + Represents the event handling code for the `pointerlockerror` event. + **/ + var onpointerlockerror : haxe.Constraints.Function; /** … @@ -174,16 +222,14 @@ extern class Document extends Node var hidden(default,null) : Bool; /** - - Returns a `string` denoting the visibility state of the document. Possible values are `visible`,  `hidden`,  `prerender`, and `unloaded`. - + Returns a `string` denoting the visibility state of the document. Possible values are `visible`,  `hidden`,  `prerender`, and `unloaded`. **/ var visibilityState(default,null) : VisibilityState; /** - Returns a list of the style sheet objects on the current document. + Is an `EventHandler` representing the code to be called when the `visibilitychange` event is raised. **/ - var styleSheets(default,null) : StyleSheetList; + var onvisibilitychange : haxe.Constraints.Function; /** Returns which style sheet set is currently in use. @@ -205,23 +251,55 @@ extern class Document extends Node **/ var styleSheetSets(default,null) : DOMStringList; + /** + Returns a reference to the `Element` that scrolls the document. + **/ + var scrollingElement(default,null) : Element; + /** … **/ var timeline(default,null) : DocumentTimeline; + var rootElement(default,null) : js.html.svg.SVGElement; + + /** + Represents the event handling code for the `copy` event. + **/ + var oncopy : haxe.Constraints.Function; + + /** + Represents the event handling code for the `cut` event. + **/ + var oncut : haxe.Constraints.Function; + + /** + Represents the event handling code for the `paste` event. + **/ + var onpaste : haxe.Constraints.Function; + var activeElement(default,null) : Element; + var styleSheets(default,null) : StyleSheetList; + var pointerLockElement(default,null) : Element; + + /** + The element that's currently in full screen mode for this document. + **/ + var fullscreenElement(default,null) : Element; var fonts(default,null) : FontFaceSet; var onabort : haxe.Constraints.Function; var onblur : haxe.Constraints.Function; var onfocus : haxe.Constraints.Function; + var onauxclick : haxe.Constraints.Function; var oncanplay : haxe.Constraints.Function; var oncanplaythrough : haxe.Constraints.Function; var onchange : haxe.Constraints.Function; var onclick : haxe.Constraints.Function; + var onclose : haxe.Constraints.Function; var oncontextmenu : haxe.Constraints.Function; var ondblclick : haxe.Constraints.Function; var ondrag : haxe.Constraints.Function; var ondragend : haxe.Constraints.Function; var ondragenter : haxe.Constraints.Function; + var ondragexit : haxe.Constraints.Function; var ondragleave : haxe.Constraints.Function; var ondragover : haxe.Constraints.Function; var ondragstart : haxe.Constraints.Function; @@ -237,6 +315,7 @@ extern class Document extends Node var onload : haxe.Constraints.Function; var onloadeddata : haxe.Constraints.Function; var onloadedmetadata : haxe.Constraints.Function; + var onloadend : haxe.Constraints.Function; var onloadstart : haxe.Constraints.Function; var onmousedown : haxe.Constraints.Function; var onmouseenter : haxe.Constraints.Function; @@ -245,6 +324,11 @@ extern class Document extends Node var onmouseout : haxe.Constraints.Function; var onmouseover : haxe.Constraints.Function; var onmouseup : haxe.Constraints.Function; + + /** + Represents the event handling code for the `wheel` event. + **/ + var onwheel : haxe.Constraints.Function; var onpause : haxe.Constraints.Function; var onplay : haxe.Constraints.Function; var onplaying : haxe.Constraints.Function; @@ -263,6 +347,8 @@ extern class Document extends Node var ontimeupdate : haxe.Constraints.Function; var onvolumechange : haxe.Constraints.Function; var onwaiting : haxe.Constraints.Function; + var onselectstart : haxe.Constraints.Function; + var ontoggle : haxe.Constraints.Function; var onpointercancel : haxe.Constraints.Function; var onpointerdown : haxe.Constraints.Function; var onpointerup : haxe.Constraints.Function; @@ -273,26 +359,18 @@ extern class Document extends Node var onpointerleave : haxe.Constraints.Function; var ongotpointercapture : haxe.Constraints.Function; var onlostpointercapture : haxe.Constraints.Function; - - /** - Is an `EventHandler` representing the code to be called when the `fullscreenchange` event is raised. - **/ - var onfullscreenchange : haxe.Constraints.Function; - - /** - Is an `EventHandler` representing the code to be called when the `fullscreenerror` event is raised. - **/ - var onfullscreenerror : haxe.Constraints.Function; - - /** - Represents the event handling code for the `pointerlockchange` event. - **/ - var onpointerlockchange : haxe.Constraints.Function; - - /** - Represetnts the event handling code for the `pointerlockerror` event. - **/ - var onpointerlockerror : haxe.Constraints.Function; + var onanimationcancel : haxe.Constraints.Function; + var onanimationend : haxe.Constraints.Function; + var onanimationiteration : haxe.Constraints.Function; + var onanimationstart : haxe.Constraints.Function; + var ontransitioncancel : haxe.Constraints.Function; + var ontransitionend : haxe.Constraints.Function; + var ontransitionrun : haxe.Constraints.Function; + var ontransitionstart : haxe.Constraints.Function; + var onwebkitanimationend : haxe.Constraints.Function; + var onwebkitanimationiteration : haxe.Constraints.Function; + var onwebkitanimationstart : haxe.Constraints.Function; + var onwebkittransitionend : haxe.Constraints.Function; var onerror : haxe.Constraints.Function; var children(default,null) : HTMLCollection; var firstElementChild(default,null) : Element; @@ -309,33 +387,37 @@ extern class Document extends Node /** Returns a list of elements with the given tag name. **/ + @:pure function getElementsByTagName( localName : String ) : HTMLCollection; - /** @throws DOMError */ /** Returns a list of elements with the given tag name and namespace. + @throws DOMError **/ - function getElementsByTagNameNS( namespace_ : String, localName : String ) : HTMLCollection; + @:pure + function getElementsByTagNameNS( namespace : String, localName : String ) : HTMLCollection; /** Returns a list of elements with the given class name. **/ + @:pure function getElementsByClassName( classNames : String ) : HTMLCollection; + @:pure function getElementById( elementId : String ) : Element; - /** @throws DOMError */ - @:overload( function( localName : String ) : Element {} ) /** Creates a new element with the given tag name. + @throws DOMError **/ - function createElement( localName : String, typeExtension : String ) : Element; - /** @throws DOMError */ - @:overload( function( namespace_ : String, qualifiedName : String ) : Element {} ) + @:overload( function( localName : String, ?options : String) : Element {} ) + function createElement( localName : String, ?options : ElementCreationOptions ) : Element; /** Creates a new element with the given tag name and namespace URI. + @throws DOMError **/ - function createElementNS( namespace_ : String, qualifiedName : String, typeExtension : String ) : Element; + @:overload( function( namespace : String, qualifiedName : String, ?options : String) : Element {} ) + function createElementNS( namespace : String, qualifiedName : String, ?options : ElementCreationOptions ) : Element; /** Creates a new document fragment. @@ -351,67 +433,77 @@ extern class Document extends Node Creates a new comment node and returns it. **/ function createComment( data : String ) : Comment; - /** @throws DOMError */ /** Creates a new `ProcessingInstruction` object. + @throws DOMError **/ function createProcessingInstruction( target : String, data : String ) : ProcessingInstruction; - /** @throws DOMError */ /** Returns a clone of a node from an external document. + @throws DOMError **/ - function importNode( node : Node, ?deep : Bool = false ) : Node; - /** @throws DOMError */ + function importNode( node : Node, deep : Bool = false ) : Node; /** Adopt node from an external document. + @throws DOMError **/ function adoptNode( node : Node ) : Node; - /** @throws DOMError */ /** Creates an event object. + @throws DOMError **/ function createEvent( interface_ : String ) : Event; - /** @throws DOMError */ /** Creates a `Range` object. + @throws DOMError **/ function createRange() : Range; - /** @throws DOMError */ /** Creates a `NodeIterator` object. + @throws DOMError **/ - function createNodeIterator( root : Node, ?whatToShow : Int = cast 4294967295, ?filter : NodeFilter ) : NodeIterator; - /** @throws DOMError */ + @:overload( function( root : Node, whatToShow : Int = cast 4294967295, ?filter : haxe.Constraints.Function) : NodeIterator {} ) + @:overload( function( root : Node, whatToShow : Int = cast 4294967295, ?filter : NodeFilter) : NodeIterator {} ) + function createNodeIterator( root : Node, whatToShow : Int = cast 4294967295, ?filter : Node -> Int ) : NodeIterator; /** Creates a `TreeWalker` object. + @throws DOMError **/ - function createTreeWalker( root : Node, ?whatToShow : Int = cast 4294967295, ?filter : NodeFilter ) : TreeWalker; - /** @throws DOMError */ + @:overload( function( root : Node, whatToShow : Int = cast 4294967295, ?filter : haxe.Constraints.Function) : TreeWalker {} ) + @:overload( function( root : Node, whatToShow : Int = cast 4294967295, ?filter : NodeFilter) : TreeWalker {} ) + function createTreeWalker( root : Node, whatToShow : Int = cast 4294967295, ?filter : Node -> Int ) : TreeWalker; /** Creates a new CDATA node and returns it. + @throws DOMError **/ function createCDATASection( data : String ) : CDATASection; - /** @throws DOMError */ /** Creates a new `Attr` object and returns it. + @throws DOMError **/ function createAttribute( name : String ) : Attr; - /** @throws DOMError */ /** Creates a new attribute node in a given namespace and returns it. + @throws DOMError + **/ + function createAttributeNS( namespace : String, name : String ) : Attr; + @:pure + function getElementsByName( elementName : String ) : NodeList; + + /** + Returns `true` if the focus is currently located anywhere inside the specified document. + @throws DOMError **/ - function createAttributeNS( namespace_ : String, name : String ) : Attr; - /** @throws DOMError */ function hasFocus() : Bool; /** @@ -424,62 +516,65 @@ extern class Document extends Node Release the pointer lock. **/ function exitPointerLock() : Void; - /** @throws DOMError */ - - /** - Registers a web component. - **/ - function registerElement( name : String, ?options : ElementRegistrationOptions ) : Dynamic; /** Enables the style sheets for the specified style sheet set. **/ function enableStyleSheetsForSet( name : String ) : Void; - - /** - Returns the topmost element at the specified coordinates.  - **/ - function elementFromPoint( x : Float, y : Float ) : Element; - - /** - Returns an array of all elements at the specified coordinates. - **/ - function elementsFromPoint( x : Float, y : Float ) : Array; - - /** - Gets the `CaretPosition` at or near the specified coordinates. - **/ function caretPositionFromPoint( x : Float, y : Float ) : CaretPosition; /** @throws DOMError */ + @:pure function querySelector( selectors : String ) : Element; /** @throws DOMError */ + @:pure function querySelectorAll( selectors : String ) : NodeList; /** - Returns an array of all `Animation` objects currently in effect whose target elements are descendants of the `document`. + Returns an array of all `Animation` objects currently in effect, whose target elements are descendants of the `document`. **/ function getAnimations() : Array; /** Creates a `Touch` object. **/ - function createTouch( ?view : Window, ?target : EventTarget, ?identifier : Int = 0, ?pageX : Int = 0, ?pageY : Int = 0, ?screenX : Int = 0, ?screenY : Int = 0, ?clientX : Int = 0, ?clientY : Int = 0, ?radiusX : Int = 0, ?radiusY : Int = 0, ?rotationAngle : Float = 0.0, ?force : Float = 0.0 ) : Touch; - @:overload( function( touch : Touch, touches : haxe.extern.Rest ) : TouchList {} ) - @:overload( function() : TouchList {} ) + function createTouch( ?view : Window, ?target : EventTarget, identifier : Int = 0, pageX : Int = 0, pageY : Int = 0, screenX : Int = 0, screenY : Int = 0, clientX : Int = 0, clientY : Int = 0, radiusX : Int = 0, radiusY : Int = 0, rotationAngle : Float = 0.0, force : Float = 0.0 ) : Touch; /** Creates a `TouchList` object. **/ + @:overload( function( touch : Touch, touches : haxe.extern.Rest ) : TouchList {} ) + @:overload( function() : TouchList {} ) function createTouchList( touches : Array ) : TouchList; /** @throws DOMError */ - function convertQuadFromNode( quad : DOMQuad, from : haxe.extern.EitherType>, ?options : ConvertCoordinateOptions ) : DOMQuad; + function getSelection() : Selection; + function elementFromPoint( x : Float, y : Float ) : Element; + function elementsFromPoint( x : Float, y : Float ) : Array; + /** @throws DOMError */ + @:overload( function( quad : DOMQuad, from : Element, ?options : ConvertCoordinateOptions) : DOMQuad {} ) + @:overload( function( quad : DOMQuad, from : HTMLDocument, ?options : ConvertCoordinateOptions) : DOMQuad {} ) + function convertQuadFromNode( quad : DOMQuad, from : Text, ?options : ConvertCoordinateOptions ) : DOMQuad; + /** @throws DOMError */ + @:overload( function( rect : DOMRectReadOnly, from : Element, ?options : ConvertCoordinateOptions) : DOMQuad {} ) + @:overload( function( rect : DOMRectReadOnly, from : HTMLDocument, ?options : ConvertCoordinateOptions) : DOMQuad {} ) + function convertRectFromNode( rect : DOMRectReadOnly, from : Text, ?options : ConvertCoordinateOptions ) : DOMQuad; + /** @throws DOMError */ + @:overload( function( point : DOMPointInit, from : Element, ?options : ConvertCoordinateOptions) : DOMPoint {} ) + @:overload( function( point : DOMPointInit, from : HTMLDocument, ?options : ConvertCoordinateOptions) : DOMPoint {} ) + function convertPointFromNode( point : DOMPointInit, from : Text, ?options : ConvertCoordinateOptions ) : DOMPoint; /** @throws DOMError */ - function convertRectFromNode( rect : DOMRectReadOnly, from : haxe.extern.EitherType>, ?options : ConvertCoordinateOptions ) : DOMQuad; + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function prepend( nodes : haxe.extern.Rest ) : Void; /** @throws DOMError */ - function convertPointFromNode( point : DOMPointInit, from : haxe.extern.EitherType>, ?options : ConvertCoordinateOptions ) : DOMPoint; + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function append( nodes : haxe.extern.Rest ) : Void; /** @throws DOMError */ - function createExpression( expression : String, resolver : XPathNSResolver ) : XPathExpression; + @:overload( function( expression : String, ?resolver : haxe.Constraints.Function) : XPathExpression {} ) + @:overload( function( expression : String, ?resolver : XPathNSResolver) : XPathExpression {} ) + function createExpression( expression : String, ?resolver : String -> Null ) : XPathExpression; + @:pure function createNSResolver( nodeResolver : Node ) : Node; /** @throws DOMError */ - function evaluate( expression : String, contextNode : Node, resolver : XPathNSResolver, type : Int, result : Dynamic ) : XPathResult; + @:overload( function( expression : String, contextNode : Node, ?resolver : haxe.Constraints.Function, type : Int = 0, ?result : Dynamic) : XPathResult {} ) + @:overload( function( expression : String, contextNode : Node, ?resolver : XPathNSResolver, type : Int = 0, ?result : Dynamic) : XPathResult {} ) + function evaluate( expression : String, contextNode : Node, ?resolver : String -> Null, type : Int = 0, ?result : Dynamic ) : XPathResult; } \ No newline at end of file diff --git a/std/js/html/DocumentFragment.hx b/std/js/html/DocumentFragment.hx index 9b070b880fe..9919b323844 100644 --- a/std/js/html/DocumentFragment.hx +++ b/std/js/html/DocumentFragment.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,15 +25,14 @@ package js.html; /** - The `DocumentFragment` interface represents a minimal document object that has no parent. It is used as a light-weight version of `Document` to store well-formed or potentially non-well-formed fragments of XML. + The `DocumentFragment` interface represents a minimal document object that has no parent. It is used as a lightweight version of `Document` that stores a segment of a document structure comprised of nodes just like a standard document. The key difference is that because the document fragment isn't part of the active document tree structure, changes made to the fragment don't affect the document, cause reflow, or incur any performance impact that can occur when changes are made. Documentation [DocumentFragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("DocumentFragment") -extern class DocumentFragment extends Node -{ +extern class DocumentFragment extends Node { var children(default,null) : HTMLCollection; var firstElementChild(default,null) : Element; var lastElementChild(default,null) : Element; @@ -46,16 +45,22 @@ extern class DocumentFragment extends Node Returns the first `Element` node within the DocumentFragment`, in document order, that matches the specified ID. **/ function getElementById( elementId : String ) : Element; - /** @throws DOMError */ /** Returns the first `Element` node within the `DocumentFragment`, in document order, that matches the specified selectors. + @throws DOMError **/ function querySelector( selectors : String ) : Element; - /** @throws DOMError */ /** Returns a `NodeList` of all the `Element` nodes within the `DocumentFragment` that match the specified selectors. + @throws DOMError **/ function querySelectorAll( selectors : String ) : NodeList; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function prepend( nodes : haxe.extern.Rest ) : Void; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function append( nodes : haxe.extern.Rest ) : Void; } \ No newline at end of file diff --git a/std/js/html/DocumentTimeline.hx b/std/js/html/DocumentTimeline.hx index b804bdaf5af..d2fdae952d1 100644 --- a/std/js/html/DocumentTimeline.hx +++ b/std/js/html/DocumentTimeline.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,6 +32,7 @@ package js.html; @see **/ @:native("DocumentTimeline") -extern class DocumentTimeline extends AnimationTimeline -{ +extern class DocumentTimeline extends AnimationTimeline { + /** @throws DOMError */ + function new( ?options : DocumentTimelineOptions ) : Void; } \ No newline at end of file diff --git a/std/js/html/DocumentTimelineOptions.hx b/std/js/html/DocumentTimelineOptions.hx new file mode 100644 index 00000000000..5edd9968eed --- /dev/null +++ b/std/js/html/DocumentTimelineOptions.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\DocumentTimeline.webidl. Do not edit! + +package js.html; + +typedef DocumentTimelineOptions = { + var ?originTime : Float; +} \ No newline at end of file diff --git a/std/js/html/DocumentType.hx b/std/js/html/DocumentType.hx index 7c341350c52..5c17b217a01 100644 --- a/std/js/html/DocumentType.hx +++ b/std/js/html/DocumentType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,23 +32,31 @@ package js.html; @see **/ @:native("DocumentType") -extern class DocumentType extends Node -{ +extern class DocumentType extends Node { /** - ... + A `DOMString`, eg `"html"` for `!DOCTYPE HTML`. **/ var name(default,null) : String; /** - ... + A `DOMString`, eg `"-//W3C//DTD HTML 4.01//EN"`, empty string for HTML5. **/ var publicId(default,null) : String; /** - ... + A `DOMString`, eg `"http://www.w3.org/TR/html4/strict.dtd"`, empty string for HTML5. **/ var systemId(default,null) : String; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function before( nodes : haxe.extern.Rest ) : Void; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function after( nodes : haxe.extern.Rest ) : Void; + /** @throws DOMError */ + @:overload( function( nodes : haxe.extern.Rest) : Void {} ) + function replaceWith( nodes : haxe.extern.Rest ) : Void; function remove() : Void; } \ No newline at end of file diff --git a/std/js/html/DragEvent.hx b/std/js/html/DragEvent.hx index 424bec01c4f..775c60ccaf1 100644 --- a/std/js/html/DragEvent.hx +++ b/std/js/html/DragEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,11 +32,14 @@ package js.html; @see **/ @:native("DragEvent") -extern class DragEvent extends MouseEvent -{ +extern class DragEvent extends MouseEvent { + + /** + The data that is transferred during a drag and drop interaction. + **/ var dataTransfer(default,null) : DataTransfer; /** @throws DOMError */ function new( type : String, ?eventInitDict : DragEventInit ) : Void; - function initDragEvent( type : String, canBubble : Bool, cancelable : Bool, aView : Window, aDetail : Int, aScreenX : Int, aScreenY : Int, aClientX : Int, aClientY : Int, aCtrlKey : Bool, aAltKey : Bool, aShiftKey : Bool, aMetaKey : Bool, aButton : Int, aRelatedTarget : EventTarget, aDataTransfer : DataTransfer ) : Void; + function initDragEvent( type : String, canBubble : Bool = false, cancelable : Bool = false, ?aView : Window, aDetail : Int = 0, aScreenX : Int = 0, aScreenY : Int = 0, aClientX : Int = 0, aClientY : Int = 0, aCtrlKey : Bool = false, aAltKey : Bool = false, aShiftKey : Bool = false, aMetaKey : Bool = false, aButton : Int = 0, ?aRelatedTarget : EventTarget, ?aDataTransfer : DataTransfer ) : Void; } \ No newline at end of file diff --git a/std/js/html/DragEventInit.hx b/std/js/html/DragEventInit.hx index 4dce79cce36..77c25e41ce9 100644 --- a/std/js/html/DragEventInit.hx +++ b/std/js/html/DragEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,6 @@ package js.html; -typedef DragEventInit = -{ - > MouseEventInit, - @:optional var dataTransfer : DataTransfer; +typedef DragEventInit = MouseEventInit & { + var ?dataTransfer : DataTransfer; } \ No newline at end of file diff --git a/std/js/html/EffectTiming.hx b/std/js/html/EffectTiming.hx new file mode 100644 index 00000000000..b23e0ff12d8 --- /dev/null +++ b/std/js/html/EffectTiming.hx @@ -0,0 +1,75 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\AnimationEffect.webidl. Do not edit! + +package js.html; + +/** + The `EffectTiming` dictionary, part of the Web Animations API, is used by `Element.animate()`, `KeyframeEffectReadOnly()`, and `KeyframeEffect()` to describe timing properties for animation effects. These properties are all optional, although without setting a `duration` the animation will not play. + + Documentation [EffectTiming](https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +typedef EffectTiming = { + + /** + The number of milliseconds to delay the start of the animation. Defaults to 0. + **/ + var ?delay : Float; + + /** + Whether the animation runs forwards (`normal`), backwards (`reverse`), switches direction after each iteration (`alternate`), or runs backwards and switches direction after each iteration (`alternate-reverse`). Defaults to `"normal"`. + **/ + var ?direction : PlaybackDirection; + + /** + The number of milliseconds each iteration of the animation takes to complete. Defaults to 0. Although this is technically optional, keep in mind that your animation will not run if this value is 0. + **/ + var ?duration : haxe.extern.EitherType; + + /** + The rate of the animation's change over time. Accepts the pre-defined values `"linear"`, `"ease"`, `"ease-in"`, `"ease-out"`, and `"ease-in-out"`, or a custom `"cubic-bezier"` value like `"cubic-bezier(0.42, 0, 0.58, 1)"`. Defaults to `"linear"`. + **/ + var ?easing : String; + + /** + The number of milliseconds to delay after the end of an animation. This is primarily of use when sequencing animations based on the end time of another animation. Defaults to 0.  + **/ + var ?endDelay : Float; + + /** + Dictates whether the animation's effects should be reflected by the element(s) prior to playing (`"backwards"`), retained after the animation has completed playing (`"forwards"`), or `both`. Defaults to `"none"`. + **/ + var ?fill : FillMode; + + /** + Describes at what point in the iteration the animation should start. 0.5 would indicate starting halfway through the first iteration for example, and with this value set, an animation with 2 iterations would end halfway through a third iteration. Defaults to 0.0. + **/ + var ?iterationStart : Float; + + /** + The number of times the animation should repeat. Defaults to `1`, and can also take a value of `Infinity` to make it repeat for as long as the element exists. + **/ + var ?iterations : Float; +} \ No newline at end of file diff --git a/std/js/html/Element.hx b/std/js/html/Element.hx index ac44555cfec..e50498bd7df 100644 --- a/std/js/html/Element.hx +++ b/std/js/html/Element.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,6 +32,22 @@ package js.html; @see **/ @:native("HTMLElement") -extern class Element extends DOMElement -{ +extern class Element extends DOMElement { + + /** + Sends a mouse click event to the element. + **/ + function click() : Void; + + /** + Makes the element the current keyboard focus. + @throws DOMError + **/ + function focus() : Void; + + /** + Removes keyboard focus from the currently focused element. + @throws DOMError + **/ + function blur() : Void; } \ No newline at end of file diff --git a/std/js/html/ElementCreationOptions.hx b/std/js/html/ElementCreationOptions.hx new file mode 100644 index 00000000000..d9ced8054bf --- /dev/null +++ b/std/js/html/ElementCreationOptions.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\Document.webidl. Do not edit! + +package js.html; + +typedef ElementCreationOptions = { + var ?is : String; +} \ No newline at end of file diff --git a/std/js/html/EmbedElement.hx b/std/js/html/EmbedElement.hx index e05f22868d8..3512746679e 100644 --- a/std/js/html/EmbedElement.hx +++ b/std/js/html/EmbedElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLEmbedElement") -extern class EmbedElement extends Element -{ +extern class EmbedElement extends Element { /** Is a `DOMString` that reflects the `src` HTML attribute, containing the address of the resource. @@ -51,12 +50,12 @@ extern class EmbedElement extends Element var width : String; /** - Is a `DOMString` representing an enumerated property indicating alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, `"center"`, and `"justify"`. + Is a `DOMString` reflecting the `height` HTML attribute, containing the displayed height of the resource. **/ var height : String; /** - Is a `DOMString` reflecting the `height` HTML attribute, containing the displayed height of the resource. + Is a `DOMString` representing an enumerated property indicating alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, `"center"`, and `"justify"`. **/ var align : String; diff --git a/std/js/html/CSSCharsetRule.hx b/std/js/html/EndingTypes.hx similarity index 84% rename from std/js/html/CSSCharsetRule.hx rename to std/js/html/EndingTypes.hx index b8066e42628..ea6f6f13005 100644 --- a/std/js/html/CSSCharsetRule.hx +++ b/std/js/html/EndingTypes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,13 +20,11 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl. Do not edit! +// This file is generated from mozilla\Blob.webidl. Do not edit! package js.html; -@:native("CSSCharsetRule") -extern class CSSCharsetRule extends CSSRule -{ - var encoding : String; - +enum abstract EndingTypes(String) { + var TRANSPARENT = "transparent"; + var NATIVE = "native"; } \ No newline at end of file diff --git a/std/js/html/ErrorCallback.hx b/std/js/html/ErrorCallback.hx new file mode 100644 index 00000000000..ca229f8c46e --- /dev/null +++ b/std/js/html/ErrorCallback.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FileSystem.webidl. Do not edit! + +package js.html; + +typedef ErrorCallback = { + function handleEvent( err : DOMException ) : Void; +} \ No newline at end of file diff --git a/std/js/html/ErrorEvent.hx b/std/js/html/ErrorEvent.hx index 1221553bda2..193aa6a379f 100644 --- a/std/js/html/ErrorEvent.hx +++ b/std/js/html/ErrorEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("ErrorEvent") -extern class ErrorEvent extends Event -{ +extern class ErrorEvent extends Event { /** Is a `DOMString` containing a human-readable error message describing the problem. diff --git a/std/js/html/ErrorEventInit.hx b/std/js/html/ErrorEventInit.hx index 7c3711923e5..adc9889acfb 100644 --- a/std/js/html/ErrorEventInit.hx +++ b/std/js/html/ErrorEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,12 +24,10 @@ package js.html; -typedef ErrorEventInit = -{ - > EventInit, - @:optional var colno : Int; - @:optional var error : Dynamic; - @:optional var filename : String; - @:optional var lineno : Int; - @:optional var message : String; +typedef ErrorEventInit = EventInit & { + var ?colno : Int; + var ?error : Dynamic; + var ?filename : String; + var ?lineno : Int; + var ?message : String; } \ No newline at end of file diff --git a/std/js/html/Event.hx b/std/js/html/Event.hx index 6c29755dc01..4a3a9ecd63a 100644 --- a/std/js/html/Event.hx +++ b/std/js/html/Event.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,15 +25,14 @@ package js.html; /** - The `Event` interface represents any event which takes place in the DOM; some are user-generated (such as mouse or keyboard events), while others are generated by APIs (such as events that indicate an animation has finished running, a video has been paused, and so forth). There are many types of event, some of which use are other interfaces based on the main `Event` interface. `Event` itself contains the properties and methods which are common to all events. + The `Event` interface represents any event which takes place in the DOM; some are user-generated (such as mouse or keyboard events), while others are generated by APIs (such as events that indicate an animation has finished running, a video has been paused, and so forth). There are many types of events, some of which use other interfaces based on the main `Event` interface. `Event` itself contains the properties and methods which are common to all events. Documentation [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Event$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("Event") -extern class Event -{ +extern class Event { static inline var NONE : Int = 0; static inline var CAPTURING_PHASE : Int = 1; static inline var AT_TARGET : Int = 2; @@ -55,7 +54,7 @@ extern class Event var target(default,null) : EventTarget; /** - A reference to the currently registered target for the event. This is the object to which the event is currently slated to be sent to; it's possible this has been changed along the way through retargeting. + A reference to the currently registered target for the event. This is the object to which the event is currently slated to be sent; it's possible this has been changed along the way through retargeting. **/ var currentTarget(default,null) : EventTarget; @@ -74,21 +73,36 @@ extern class Event **/ var cancelable(default,null) : Bool; + /** + A historical property introduced by Internet Explorer and eventually adopted into the DOM specification in order to ensure existing sites continue to work. Ideally, you should try to use `Event.preventDefault()` and `Event.defaultPrevented` instead, but you can use `returnValue` if you choose to do so. + **/ + var returnValue : Bool; + /** Indicates whether or not `event.preventDefault()` has been called on the event. **/ var defaultPrevented(default,null) : Bool; /** - Indicates whether or not the event was initiated by the browser (after a user click for instance) or by a script (using an event creation method, like event.initEvent) + A Boolean value indicating whether or not the event can bubble across the boundary between the shadow DOM and the regular DOM. + **/ + var composed(default,null) : Bool; + + /** + Indicates whether or not the event was initiated by the browser (after a user click for instance) or by a script (using an event creation method, like event.initEvent). **/ var isTrusted(default,null) : Bool; /** - The time at which the event was created, in milliseconds. By specification, this value is time since epoch, but in reality browsers' definitions vary; in addition, work is underway to change this to be a `DOMHighResTimeStamp` instead. + The time at which the event was created (in milliseconds). By specification, this value is time since epoch, but in reality browsers' definitions vary; in addition, work is underway to change this to be a `DOMHighResTimeStamp` instead. **/ var timeStamp(default,null) : Float; + /** + A historical alias to `Event.stopPropagation()`. Setting its value to `true` before returning from an event handler prevents propagation of the event. + **/ + var cancelBubble : Bool; + /** The original target of the event, before any retargetings (Mozilla-specific). **/ @@ -102,6 +116,11 @@ extern class Event /** @throws DOMError */ function new( type : String, ?eventInitDict : EventInit ) : Void; + /** + Returns the event’s path (objects on which listeners will be invoked). This does not include nodes in shadow trees if the shadow root was created with its `ShadowRoot.mode` closed. + **/ + function composedPath() : Array; + /** Stops the propagation of events further along in the DOM. **/ @@ -120,10 +139,5 @@ extern class Event /** Initializes the value of an Event created. If the event has already being dispatched, this method does nothing. **/ - function initEvent( type : String, bubbles : Bool, cancelable : Bool ) : Void; - - /** - Non-standard. Returns the value of `Event.defaultPrevented`. Use `Event.defaultPrevented` instead. - **/ - function getPreventDefault() : Bool; + function initEvent( type : String, bubbles : Bool = false, cancelable : Bool = false ) : Void; } \ No newline at end of file diff --git a/std/js/html/EventInit.hx b/std/js/html/EventInit.hx index 48d932555bd..0b8d1f28daf 100644 --- a/std/js/html/EventInit.hx +++ b/std/js/html/EventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,8 @@ package js.html; -typedef EventInit = -{ - @:optional var bubbles : Bool; - @:optional var cancelable : Bool; +typedef EventInit = { + var ?bubbles : Bool; + var ?cancelable : Bool; + var ?composed : Bool; } \ No newline at end of file diff --git a/std/js/html/EventListener.hx b/std/js/html/EventListener.hx index 09ff04ac200..c8e2e85b4c8 100644 --- a/std/js/html/EventListener.hx +++ b/std/js/html/EventListener.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,19 +20,21 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from events.webidl. Do not edit! +// This file is generated from mozilla\EventListener.webidl. Do not edit! package js.html; /** - This method is called whenever an event occurs of the type for which the `EventListener` interface was registered. + The `EventListener` interface represents an object that can handle an event dispatched by an `EventTarget` object. Documentation [EventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventListener) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EventListener$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ -@:native("EventListener") -extern class EventListener -{ +typedef EventListener = { + + /** + A function that is called whenever an event of the specified type occurs. + **/ function handleEvent( event : Event ) : Void; } \ No newline at end of file diff --git a/std/js/html/EventListenerOptions.hx b/std/js/html/EventListenerOptions.hx new file mode 100644 index 00000000000..6cedd9db140 --- /dev/null +++ b/std/js/html/EventListenerOptions.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\EventTarget.webidl. Do not edit! + +package js.html; + +typedef EventListenerOptions = { + var ?capture : Bool; +} \ No newline at end of file diff --git a/std/js/html/EventModifierInit.hx b/std/js/html/EventModifierInit.hx index 8f83f27401b..8cef40a20ea 100644 --- a/std/js/html/EventModifierInit.hx +++ b/std/js/html/EventModifierInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,20 +24,18 @@ package js.html; -typedef EventModifierInit = -{ - > UIEventInit, - @:optional var altKey : Bool; - @:optional var ctrlKey : Bool; - @:optional var metaKey : Bool; - @:optional var modifierAltGraph : Bool; - @:optional var modifierCapsLock : Bool; - @:optional var modifierFn : Bool; - @:optional var modifierFnLock : Bool; - @:optional var modifierNumLock : Bool; - @:optional var modifierOS : Bool; - @:optional var modifierScrollLock : Bool; - @:optional var modifierSymbol : Bool; - @:optional var modifierSymbolLock : Bool; - @:optional var shiftKey : Bool; +typedef EventModifierInit = UIEventInit & { + var ?altKey : Bool; + var ?ctrlKey : Bool; + var ?metaKey : Bool; + var ?modifierAltGraph : Bool; + var ?modifierCapsLock : Bool; + var ?modifierFn : Bool; + var ?modifierFnLock : Bool; + var ?modifierNumLock : Bool; + var ?modifierOS : Bool; + var ?modifierScrollLock : Bool; + var ?modifierSymbol : Bool; + var ?modifierSymbolLock : Bool; + var ?shiftKey : Bool; } \ No newline at end of file diff --git a/std/js/html/EventSource.hx b/std/js/html/EventSource.hx index a56297b4694..d688283ef0e 100644 --- a/std/js/html/EventSource.hx +++ b/std/js/html/EventSource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,15 +25,14 @@ package js.html; /** - The `EventSource` interface is used to receive server-sent events. It connects to a server over HTTP and receives events in `text/event-stream` format without closing the connection. + The `EventSource` interface is web content's interface to server-sent events. An `EventSource` instance opens a persistent connection to an HTTP server, which sends events in `text/event-stream` format. Documentation [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EventSource$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("EventSource") -extern class EventSource extends EventTarget -{ +extern class EventSource extends EventTarget { static inline var CONNECTING : Int = 0; static inline var OPEN : Int = 1; static inline var CLOSED : Int = 2; @@ -43,25 +42,29 @@ extern class EventSource extends EventTarget A `DOMString` representing the URL of the source. **/ var url(default,null) : String; + + /** + A `Boolean` indicating whether the `EventSource` object was instantiated with cross-origin (CORS) credentials set (`true`), or not (`false`, the default). + **/ var withCredentials(default,null) : Bool; /** - An `unsigned short` representing the state of the connection. Possible values are `CONNECTING` (`0`), `OPEN` (`1`), or `CLOSED` (`2`). + A number representing the state of the connection. Possible values are `CONNECTING` (`0`), `OPEN` (`1`), or `CLOSED` (`2`). **/ var readyState(default,null) : Int; /** - Is an `EventHandler` being called when an `open` event is received, that is when the connection was just opened. + Is an `EventHandler` called when an `open` event is received, that is when the connection was just opened. **/ var onopen : haxe.Constraints.Function; /** - Is an `EventHandler` being called when a `message` event is received, that is when a message is coming from the source. + Is an `EventHandler` called when a `message` event is received, that is when a message is coming from the source. **/ var onmessage : haxe.Constraints.Function; /** - Is an `EventHandler` being called when an error occurs and the `error` event is dispatched on this object. + Is an `EventHandler` called when an error occurs and the `error` event is dispatched on an `EventSource` object. **/ var onerror : haxe.Constraints.Function; diff --git a/std/js/html/EventSourceInit.hx b/std/js/html/EventSourceInit.hx index f3fd6bc38d2..1013710002d 100644 --- a/std/js/html/EventSourceInit.hx +++ b/std/js/html/EventSourceInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,7 +24,6 @@ package js.html; -typedef EventSourceInit = -{ - @:optional var withCredentials : Bool; +typedef EventSourceInit = { + var ?withCredentials : Bool; } \ No newline at end of file diff --git a/std/js/html/EventTarget.hx b/std/js/html/EventTarget.hx index f2e6d949058..8e70448ff86 100644 --- a/std/js/html/EventTarget.hx +++ b/std/js/html/EventTarget.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,26 +32,27 @@ package js.html; @see **/ @:native("EventTarget") -extern class EventTarget -{ +extern class EventTarget { /** @throws DOMError */ - @:overload( function( type : String, listener : EventListener, ?capture : Bool = false, ?wantsUntrusted : Bool ) : Void {} ) + function new() : Void; /** Register an event handler of a specific event type on the `EventTarget`. + @throws DOMError **/ - function addEventListener( type : String, listener : haxe.Constraints.Function, ?capture : Bool = false ) : Void; - /** @throws DOMError */ - @:overload( function( type : String, listener : EventListener, ?capture : Bool = false ) : Void {} ) + @:overload( function( type : String, listener : EventListener, ?options : haxe.extern.EitherType, ?wantsUntrusted : Bool ) : Void {} ) + function addEventListener( type: String, listener: haxe.Constraints.Function, ?options : haxe.extern.EitherType, ?wantsUntrusted : Bool ) : Void; /** Removes an event listener from the `EventTarget`. + @throws DOMError **/ - function removeEventListener( type : String, listener : haxe.Constraints.Function, ?capture : Bool = false ) : Void; - /** @throws DOMError */ + @:overload( function( type : String, listener : EventListener, ?options : haxe.extern.EitherType) : Void {} ) + function removeEventListener( type : String, listener : haxe.Constraints.Function, ?options : haxe.extern.EitherType ) : Void; /** Dispatch an event to this `EventTarget`. + @throws DOMError **/ function dispatchEvent( event : Event ) : Bool; } \ No newline at end of file diff --git a/std/js/html/Exception.hx b/std/js/html/Exception.hx index aeeb454519a..8462ae0f97e 100644 --- a/std/js/html/Exception.hx +++ b/std/js/html/Exception.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,16 +24,14 @@ package js.html; -@:native("Exception") -extern class Exception -{ +typedef Exception = { + var name(default,null) : String; var message(default,null) : String; var result(default,null) : Int; - var name(default,null) : String; var filename(default,null) : String; var lineNumber(default,null) : Int; var columnNumber(default,null) : Int; - var data(default,null) : Dynamic/*MISSING nsISupports*/; + var data(default,null) : Dynamic; var stack(default,null) : String; } \ No newline at end of file diff --git a/std/js/html/ExtendableEvent.hx b/std/js/html/ExtendableEvent.hx index a99f2cc2d0f..903e0eaad9c 100644 --- a/std/js/html/ExtendableEvent.hx +++ b/std/js/html/ExtendableEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,6 +24,8 @@ package js.html; +import js.lib.Promise; + /** The `ExtendableEvent` interface extends the lifetime of the `install` and `activate` events dispatched on the global scope as part of the service worker lifecycle. This ensures that any functional events (like `FetchEvent`) are not dispatched until it upgrades database schemas and deletes the outdated cache entries. @@ -32,8 +34,7 @@ package js.html; @see **/ @:native("ExtendableEvent") -extern class ExtendableEvent extends Event -{ +extern class ExtendableEvent extends Event { /** @throws DOMError */ function new( type : String, ?eventInitDict : ExtendableEventInit ) : Void; /** @throws DOMError */ diff --git a/std/js/html/ExtendableEventInit.hx b/std/js/html/ExtendableEventInit.hx index 826fda5bc24..825c6ee2a39 100644 --- a/std/js/html/ExtendableEventInit.hx +++ b/std/js/html/ExtendableEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,7 +24,5 @@ package js.html; -typedef ExtendableEventInit = -{ - > EventInit, +typedef ExtendableEventInit = EventInit & { } \ No newline at end of file diff --git a/std/js/html/ExtendableMessageEvent.hx b/std/js/html/ExtendableMessageEvent.hx index a269066a79b..59b1d07dbb6 100644 --- a/std/js/html/ExtendableMessageEvent.hx +++ b/std/js/html/ExtendableMessageEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("ExtendableMessageEvent") -extern class ExtendableMessageEvent extends ExtendableEvent -{ +extern class ExtendableMessageEvent extends ExtendableEvent { /** Returns the event's data. It can be any data type. @@ -58,7 +57,7 @@ extern class ExtendableMessageEvent extends ExtendableEvent /** Returns the array containing the `MessagePort` objects representing the ports of the associated message channel. **/ - var ports(default,null) : MessagePortList; + var ports(default,null) : Array; /** @throws DOMError */ function new( type : String, ?eventInitDict : ExtendableMessageEventInit ) : Void; diff --git a/std/js/html/ExtendableMessageEventInit.hx b/std/js/html/ExtendableMessageEventInit.hx index 9bf184e0e98..30954125596 100644 --- a/std/js/html/ExtendableMessageEventInit.hx +++ b/std/js/html/ExtendableMessageEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,12 +24,10 @@ package js.html; -typedef ExtendableMessageEventInit = -{ - > ExtendableEventInit, - @:optional var data : Dynamic; - @:optional var lastEventId : String; - @:optional var origin : String; - @:optional var ports : Array; - @:optional var source : haxe.extern.EitherType>; +typedef ExtendableMessageEventInit = ExtendableEventInit & { + var ?data : Dynamic; + var ?lastEventId : String; + var ?origin : String; + var ?ports : Array; + var ?source : haxe.extern.EitherType>; } \ No newline at end of file diff --git a/std/js/html/External.hx b/std/js/html/External.hx index b5f8f20795f..85470c24891 100644 --- a/std/js/html/External.hx +++ b/std/js/html/External.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,10 +24,7 @@ package js.html; -@:native("External") -extern class External -{ +typedef External = { function AddSearchProvider( aDescriptionURL : String ) : Void; function IsSearchProviderInstalled( aSearchURL : String ) : Int; - function addSearchEngine( engineURL : String, iconURL : String, suggestedTitle : String, suggestedCategory : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/FetchEvent.hx b/std/js/html/FetchEvent.hx index 6682fc09f88..7abb7db9cef 100644 --- a/std/js/html/FetchEvent.hx +++ b/std/js/html/FetchEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,38 +24,35 @@ package js.html; +import js.lib.Promise; + /** - The parameter passed into the `ServiceWorkerGlobalScope.onfetch` handler, `FetchEvent` represents a fetch action that is dispatched on the `ServiceWorkerGlobalScope` of a `ServiceWorker`. It contains information about the request and resulting response, and provides the `FetchEvent.respondWith()` method, which allows us to provide an arbitrary response back to the controlled page. + This is the event type for `fetch` events dispatched on the service worker global scope. It contains information about the fetch, including the request and how the receiver will treat the response. It provides the `event.respondWith()` method, which allows us to provide a response to this fetch. Documentation [FetchEvent](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("FetchEvent") -extern class FetchEvent extends ExtendableEvent -{ - +extern class FetchEvent extends ExtendableEvent { + /** - Returns the `Request` that triggered the event handler. + The `Request` the browser intends to make. **/ var request(default,null) : Request; - + /** - Returns the id of the client that the current service worker is controlling. + The `Client.id` of the same-origin `Client` that initiated the fetch. **/ var clientId(default,null) : String; - - /** - Returns a `Boolean` that is `true` if the event was dispatched with the user's intention for the page to reload, and `false` otherwise. Typically, pressing the refresh button in a browser is a reload, while clicking a link and pressing the back button is not. - **/ var isReload(default,null) : Bool; - + /** @throws DOMError */ function new( type : String, eventInitDict : FetchEventInit ) : Void; - /** @throws DOMError */ - + /** - Resolves by returning a `Response` or a network error  to Fetch`. + Prevent the browser's default fetch handling, and provide (a promise for) a response yourself. + @throws DOMError **/ function respondWith( r : Promise ) : Void; } \ No newline at end of file diff --git a/std/js/html/FetchEventInit.hx b/std/js/html/FetchEventInit.hx index 9592ae473b6..1bf3aac2fca 100644 --- a/std/js/html/FetchEventInit.hx +++ b/std/js/html/FetchEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,10 +24,8 @@ package js.html; -typedef FetchEventInit = -{ - > EventInit, - @:optional var clientId : String; - @:optional var isReload : Bool; +typedef FetchEventInit = EventInit & { + var ?clientId : String; + var ?isReload : Bool; var request : Request; } \ No newline at end of file diff --git a/std/js/html/LifecycleCallbacks.hx b/std/js/html/FetchObserver.hx similarity index 74% rename from std/js/html/LifecycleCallbacks.hx rename to std/js/html/FetchObserver.hx index cc0d09a9e76..e3379442588 100644 --- a/std/js/html/LifecycleCallbacks.hx +++ b/std/js/html/FetchObserver.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,14 +20,15 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\WebComponents.webidl. Do not edit! +// This file is generated from mozilla\FetchObserver.webidl. Do not edit! package js.html; -typedef LifecycleCallbacks = -{ - @:optional var attachedCallback : Void -> Void; - @:optional var attributeChangedCallback : String -> String -> String -> Void; - @:optional var createdCallback : Void -> Void; - @:optional var detachedCallback : Void -> Void; +@:native("FetchObserver") +extern class FetchObserver extends EventTarget { + var state(default,null) : FetchState; + var onstatechange : haxe.Constraints.Function; + var onrequestprogress : haxe.Constraints.Function; + var onresponseprogress : haxe.Constraints.Function; + } \ No newline at end of file diff --git a/std/js/html/FetchState.hx b/std/js/html/FetchState.hx new file mode 100644 index 00000000000..a8ae5c3831f --- /dev/null +++ b/std/js/html/FetchState.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FetchObserver.webidl. Do not edit! + +package js.html; + +enum abstract FetchState(String) { + var REQUESTING = "requesting"; + var RESPONDING = "responding"; + var ABORTED = "aborted"; + var ERRORED = "errored"; + var COMPLETE = "complete"; +} \ No newline at end of file diff --git a/std/js/html/FieldSetElement.hx b/std/js/html/FieldSetElement.hx index c5251b81f91..75a2d703403 100644 --- a/std/js/html/FieldSetElement.hx +++ b/std/js/html/FieldSetElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,17 +32,59 @@ package js.html; @see **/ @:native("HTMLFieldSetElement") -extern class FieldSetElement extends Element -{ +extern class FieldSetElement extends Element { + + /** + A `Boolean` reflecting the `disabled` HTML attribute, indicating whether the user can interact with the control. + **/ var disabled : Bool; + + /** + An `HTMLFormControlsCollection` or `HTMLCollection` referencing the containing form element, if this element is in a form. + + If the field set is not a descendant of a form element, then the attribute can be the ID of any form element in the same document it is related to, or the `null` value if none matches. + **/ var form(default,null) : FormElement; + + /** + A `DOMString` reflecting the `name` HTML attribute, containing the name of the field set, used for submitting the form. + **/ var name : String; + + /** + The `DOMString` `"fieldset"`. + **/ var type(default,null) : String; + + /** + The elements belonging to this field set. The type of this property depends on the version of the spec that is implemented by the browser. + **/ var elements(default,null) : HTMLCollection; + + /** + A `Boolean` `false`, because `fieldset` objects are never candidates for constraint validation. + **/ var willValidate(default,null) : Bool; + + /** + A `ValidityState` representing the validity states that this element is in. + **/ var validity(default,null) : ValidityState; + + /** + A `DOMString` representing a localized message that describes the validation constraints that the element does not satisfy (if any). This is the empty string if the element is not a candidate for constraint validation (`willValidate` is `false`), or it satisfies its constraints. + **/ var validationMessage(default,null) : String; + + /** + Always returns `true` because `fieldset` objects are never candidates for constraint validation. + **/ function checkValidity() : Bool; + function reportValidity() : Bool; + + /** + Sets a custom validity message for the field set. If this message is not the empty string, then the field set is suffering from a custom validity error, and does not validate. + **/ function setCustomValidity( error : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/File.hx b/std/js/html/File.hx index 7e7b2c7cdf6..addade81611 100644 --- a/std/js/html/File.hx +++ b/std/js/html/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("File") -extern class File extends Blob -{ +extern class File extends Blob { /** Returns the name of the file referenced by the `File` object. @@ -45,14 +44,6 @@ extern class File extends Blob **/ var lastModified(default,null) : Int; - /** - Returns the last modified `Date` of the file referenced by the `File` object. - **/ - var lastModifiedDate(default,null) : Date; - /** @throws DOMError */ - @:overload( function( fileBits : Array>>>, fileName : String, ?options : FilePropertyBag ) : Void {} ) - @:overload( function( fileBits : Blob, ?options : ChromeFilePropertyBag ) : Void {} ) - @:overload( function( fileBits : Dynamic/*MISSING nsIFile*/, ?options : ChromeFilePropertyBag ) : Void {} ) - function new( fileBits : String, ?options : ChromeFilePropertyBag ) : Void; + function new( fileBits : Array,haxe.extern.EitherType>>, fileName : String, ?options : FilePropertyBag ) : Void; } \ No newline at end of file diff --git a/std/js/html/DOMTransactionEventInit.hx b/std/js/html/FileCallback.hx similarity index 85% rename from std/js/html/DOMTransactionEventInit.hx rename to std/js/html/FileCallback.hx index fa6c9f4f7aa..85e46311053 100644 --- a/std/js/html/DOMTransactionEventInit.hx +++ b/std/js/html/FileCallback.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,12 +20,10 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\DOMTransactionEvent.webidl. Do not edit! +// This file is generated from mozilla\FileSystemFileEntry.webidl. Do not edit! package js.html; -typedef DOMTransactionEventInit = -{ - > EventInit, - @:optional var transactions : Dynamic; +typedef FileCallback = { + function handleEvent( file : File ) : Void; } \ No newline at end of file diff --git a/std/js/html/FileList.hx b/std/js/html/FileList.hx index 558bafbeae6..f30481e78ae 100644 --- a/std/js/html/FileList.hx +++ b/std/js/html/FileList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("FileList") -extern class FileList implements ArrayAccess -{ +extern class FileList implements ArrayAccess { var length(default,null) : Int; function item( index : Int ) : File; diff --git a/std/js/html/FileMode.hx b/std/js/html/FileMode.hx index 9452e350656..61dee013622 100644 --- a/std/js/html/FileMode.hx +++ b/std/js/html/FileMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -@:enum abstract FileMode(String) -{ +enum abstract FileMode(String) { var READONLY = "readonly"; var READWRITE = "readwrite"; } \ No newline at end of file diff --git a/std/js/html/FilePropertyBag.hx b/std/js/html/FilePropertyBag.hx index 6a1af2adbda..a3994d96a15 100644 --- a/std/js/html/FilePropertyBag.hx +++ b/std/js/html/FilePropertyBag.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -typedef FilePropertyBag = -{ - @:optional var lastModified : Int; - @:optional var type : String; +typedef FilePropertyBag = { + var ?lastModified : Int; + var ?type : String; } \ No newline at end of file diff --git a/std/js/html/FileReader.hx b/std/js/html/FileReader.hx index c9002b789f3..261c3de7fcc 100644 --- a/std/js/html/FileReader.hx +++ b/std/js/html/FileReader.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("FileReader") -extern class FileReader extends EventTarget -{ +extern class FileReader extends EventTarget { static inline var EMPTY : Int = 0; static inline var LOADING : Int = 1; static inline var DONE : Int = 2; @@ -70,9 +69,9 @@ extern class FileReader extends EventTarget var result(default,null) : Dynamic; /** - A `DOMError` representing the error that occurred while reading the file. + A `DOMException` representing the error that occurred while reading the file. **/ - var error(default,null) : DOMError; + var error(default,null) : DOMException; /** A handler for the `loadstart` event. This event is triggered each time the reading is starting. @@ -106,34 +105,33 @@ extern class FileReader extends EventTarget /** @throws DOMError */ function new() : Void; - /** @throws DOMError */ /** Starts reading the contents of the specified `Blob`, once finished, the `result` attribute contains an `ArrayBuffer` representing the file's data. + @throws DOMError **/ function readAsArrayBuffer( blob : Blob ) : Void; - /** @throws DOMError */ + + /** + Starts reading the contents of the specified `Blob`, once finished, the `result` attribute contains the raw binary data from the file as a string. + @throws DOMError + **/ + function readAsBinaryString( filedata : Blob ) : Void; /** Starts reading the contents of the specified `Blob`, once finished, the `result` attribute contains the contents of the file as a text string. + @throws DOMError **/ - function readAsText( blob : Blob, ?label : String = "" ) : Void; - /** @throws DOMError */ + function readAsText( blob : Blob, ?label : String ) : Void; /** Starts reading the contents of the specified `Blob`, once finished, the `result` attribute contains a `data:` URL representing the file's data. + @throws DOMError **/ function readAsDataURL( blob : Blob ) : Void; - /** @throws DOMError */ /** Aborts the read operation. Upon return, the `readyState` will be `DONE`. **/ function abort() : Void; - /** @throws DOMError */ - - /** - Starts reading the contents of the specified `Blob`, once finished, the `result` attribute contains the raw binary data from the file as a string. - **/ - function readAsBinaryString( filedata : Blob ) : Void; } \ No newline at end of file diff --git a/std/js/html/FileReaderSync.hx b/std/js/html/FileReaderSync.hx index 986dc54295f..a5c0f4541fd 100644 --- a/std/js/html/FileReaderSync.hx +++ b/std/js/html/FileReaderSync.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,12 +32,11 @@ package js.html; @see **/ @:native("FileReaderSync") -extern class FileReaderSync -{ +extern class FileReaderSync { /** @throws DOMError */ function new() : Void; /** @throws DOMError */ - function readAsArrayBuffer( blob : Blob ) : ArrayBuffer; + function readAsArrayBuffer( blob : Blob ) : js.lib.ArrayBuffer; /** @throws DOMError */ function readAsBinaryString( blob : Blob ) : String; /** @throws DOMError */ diff --git a/std/js/html/FileSystem.hx b/std/js/html/FileSystem.hx new file mode 100644 index 00000000000..c23ee3ff41d --- /dev/null +++ b/std/js/html/FileSystem.hx @@ -0,0 +1,47 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FileSystem.webidl. Do not edit! + +package js.html; + +/** + The File and Directory Entries API interface `FileSystem` is used to represent a file system. These objects can be obtained from the `filesystem` property on any file system entry. Some browsers offer additional APIs to create and manage file systems, such as Chrome's `requestFileSystem()` method. + + Documentation [FileSystem](https://developer.mozilla.org/en-US/docs/Web/API/FileSystem) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FileSystem$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("FileSystem") +extern class FileSystem { + + /** + A `USVString` representing the file system's name. This name is unique among the entire list of exposed file systems. + **/ + var name(default,null) : String; + + /** + A `FileSystemDirectoryEntry` object which represents the file system's root directory. Through this object, you can gain access to all files and directories in the file system. + **/ + var root(default,null) : FileSystemDirectoryEntry; + +} \ No newline at end of file diff --git a/std/js/html/FileSystemDirectoryEntry.hx b/std/js/html/FileSystemDirectoryEntry.hx new file mode 100644 index 00000000000..675448bf1bc --- /dev/null +++ b/std/js/html/FileSystemDirectoryEntry.hx @@ -0,0 +1,43 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FileSystemDirectoryEntry.webidl. Do not edit! + +package js.html; + +/** + The `FileSystemDirectoryEntry` interface of the File and Directory Entries API represents a directory in a file system. It provides methods which make it possible to access and manipulate the files in a directory, as well as to access the entries within the directory. + + Documentation [FileSystemDirectoryEntry](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryEntry) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryEntry$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("FileSystemDirectoryEntry") +extern class FileSystemDirectoryEntry extends FileSystemEntry { + function createReader() : FileSystemDirectoryReader; + @:overload( function( ?path : String, ?options : FileSystemFlags, ?successCallback : haxe.Constraints.Function, ?errorCallback : haxe.Constraints.Function) : Void {} ) + @:overload( function( ?path : String, ?options : FileSystemFlags, ?successCallback : FileSystemEntryCallback, ?errorCallback : ErrorCallback) : Void {} ) + function getFile( ?path : String, ?options : FileSystemFlags, ?successCallback : FileSystemEntry -> Void, ?errorCallback : DOMException -> Void ) : Void; + @:overload( function( ?path : String, ?options : FileSystemFlags, ?successCallback : haxe.Constraints.Function, ?errorCallback : haxe.Constraints.Function) : Void {} ) + @:overload( function( ?path : String, ?options : FileSystemFlags, ?successCallback : FileSystemEntryCallback, ?errorCallback : ErrorCallback) : Void {} ) + function getDirectory( ?path : String, ?options : FileSystemFlags, ?successCallback : FileSystemEntry -> Void, ?errorCallback : DOMException -> Void ) : Void; +} \ No newline at end of file diff --git a/std/js/html/FileSystemDirectoryReader.hx b/std/js/html/FileSystemDirectoryReader.hx new file mode 100644 index 00000000000..097468b714f --- /dev/null +++ b/std/js/html/FileSystemDirectoryReader.hx @@ -0,0 +1,40 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FileSystemDirectoryReader.webidl. Do not edit! + +package js.html; + +/** + The `FileSystemDirectoryReader` interface of the File and Directory Entries API lets you access the `FileEntry`-based objects (generally `FileSystemFileEntry` or `FileSystemDirectoryEntry`) representing each entry in a directory. + + Documentation [FileSystemDirectoryReader](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryReader) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryReader$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("FileSystemDirectoryReader") +extern class FileSystemDirectoryReader { + /** @throws DOMError */ + @:overload( function( successCallback : haxe.Constraints.Function, ?errorCallback : haxe.Constraints.Function) : Void {} ) + @:overload( function( successCallback : FileSystemEntriesCallback, ?errorCallback : ErrorCallback) : Void {} ) + function readEntries( successCallback : Array -> Void, ?errorCallback : DOMException -> Void ) : Void; +} \ No newline at end of file diff --git a/std/js/html/FileSystemEntriesCallback.hx b/std/js/html/FileSystemEntriesCallback.hx new file mode 100644 index 00000000000..8ff8dd3695f --- /dev/null +++ b/std/js/html/FileSystemEntriesCallback.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FileSystemDirectoryReader.webidl. Do not edit! + +package js.html; + +typedef FileSystemEntriesCallback = { + function handleEvent( entries : Array ) : Void; +} \ No newline at end of file diff --git a/std/js/html/FileSystemEntry.hx b/std/js/html/FileSystemEntry.hx new file mode 100644 index 00000000000..1dbfc34de88 --- /dev/null +++ b/std/js/html/FileSystemEntry.hx @@ -0,0 +1,65 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FileSystemEntry.webidl. Do not edit! + +package js.html; + +/** + The `FileSystemEntry` interface of the File and Directory Entries API represents a single in a file system. The entry can be a file or a directory (directories are represented by the `DirectoryEntry` interface). It includes methods for working with files—including copying, moving, removing, and reading files—as well as information about a file it points to—including the file name and its path from the root to the entry. + + Documentation [FileSystemEntry](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemEntry) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemEntry$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("FileSystemEntry") +extern class FileSystemEntry { + + /** + A Boolean which is `true` if the entry represents a file. If it's not a file, this value is `false`. + **/ + var isFile(default,null) : Bool; + + /** + A `Boolean` which is `true` if the entry represents a directory; otherwise, it's `false`. + **/ + var isDirectory(default,null) : Bool; + + /** + A `USVString` containing the name of the entry (the final part of the path, after the last "/" character). + **/ + var name(default,null) : String; + + /** + A `USVString` object which provides the full, absolute path from the file system's root to the entry; it can also be thought of as a path which is relative to the root directory, prepended with a "/" character. + **/ + var fullPath(default,null) : String; + + /** + A `FileSystem` object representing the file system in which the entry is located. + **/ + var filesystem(default,null) : FileSystem; + + @:overload( function( ?successCallback : haxe.Constraints.Function, ?errorCallback : haxe.Constraints.Function) : Void {} ) + @:overload( function( ?successCallback : FileSystemEntryCallback, ?errorCallback : ErrorCallback) : Void {} ) + function getParent( ?successCallback : FileSystemEntry -> Void, ?errorCallback : DOMException -> Void ) : Void; +} \ No newline at end of file diff --git a/std/js/html/FileSystemEntryCallback.hx b/std/js/html/FileSystemEntryCallback.hx new file mode 100644 index 00000000000..ee0e4941186 --- /dev/null +++ b/std/js/html/FileSystemEntryCallback.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FileSystem.webidl. Do not edit! + +package js.html; + +typedef FileSystemEntryCallback = { + function handleEvent( entry : FileSystemEntry ) : Void; +} \ No newline at end of file diff --git a/std/js/html/FileSystemFileEntry.hx b/std/js/html/FileSystemFileEntry.hx new file mode 100644 index 00000000000..8fb5e40be5a --- /dev/null +++ b/std/js/html/FileSystemFileEntry.hx @@ -0,0 +1,39 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FileSystemFileEntry.webidl. Do not edit! + +package js.html; + +/** + The `FileSystemFileEntry` interface of the File System API represents a file in a file system. It offers properties describing the file's attributes, as well as the `file()` method, which creates a `File` object that can be used to read the file. + + Documentation [FileSystemFileEntry](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileEntry) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileEntry$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("FileSystemFileEntry") +extern class FileSystemFileEntry extends FileSystemEntry { + @:overload( function( successCallback : haxe.Constraints.Function, ?errorCallback : haxe.Constraints.Function) : Void {} ) + @:overload( function( successCallback : FileCallback, ?errorCallback : ErrorCallback) : Void {} ) + function file( successCallback : File -> Void, ?errorCallback : DOMException -> Void ) : Void; +} \ No newline at end of file diff --git a/std/js/html/FileSystemFlags.hx b/std/js/html/FileSystemFlags.hx new file mode 100644 index 00000000000..979d8247ddd --- /dev/null +++ b/std/js/html/FileSystemFlags.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FileSystem.webidl. Do not edit! + +package js.html; + +/** + The `FileSystemFlags` dictionary defines a set of values which are used when specifying option flags when calling certain methods in the File and Directory Entries API. Methods which accept an options parameter of this type may specify zero or more of these flags as fields in an object, like this: + + Documentation [FileSystemFlags](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFlags) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFlags$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +typedef FileSystemFlags = { + + /** + If this property is `true`, and the requested file or directory doesn't exist, the user agent should create it. The default is `false`. The parent directory must already exist. + **/ + var ?create : Bool; + + /** + If `true`, and the `create` option is also `true`, the file must not exist prior to issuing the call. Instead, it must be possible for it to be created newly at call time. The default is `false`. + **/ + var ?exclusive : Bool; +} \ No newline at end of file diff --git a/std/js/html/FillMode.hx b/std/js/html/FillMode.hx index 19b8ba1c7b6..57b14a9295c 100644 --- a/std/js/html/FillMode.hx +++ b/std/js/html/FillMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,12 +20,11 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\AnimationEffectReadOnly.webidl. Do not edit! +// This file is generated from mozilla\AnimationEffect.webidl. Do not edit! package js.html; -@:enum abstract FillMode(String) -{ +enum abstract FillMode(String) { var NONE = "none"; var FORWARDS = "forwards"; var BACKWARDS = "backwards"; diff --git a/std/js/html/Float32Array.hx b/std/js/html/Float32Array.hx index 6f8336c0498..3a9b21c5022 100644 --- a/std/js/html/Float32Array.hx +++ b/std/js/html/Float32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,26 +20,6 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl. Do not edit! - package js.html; -// Explicitly include the compatibility class -import js.html.compat.Float32Array; - -@:native("Float32Array") -extern class Float32Array extends ArrayBufferView implements ArrayAccess -{ - static inline var BYTES_PER_ELEMENT : Int = 4; - - var length(default,null) : Int; - - /** @throws DOMError */ - @:overload( function( length : Int ) : Void {} ) - @:overload( function( array : Float32Array ) : Void {} ) - @:overload( function( array : Array ) : Void {} ) - function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - @:overload( function( array : Float32Array, ?offset : Int ) : Void {} ) - function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, ?end : Int ) : Float32Array; -} \ No newline at end of file +@:deprecated typedef Float32Array = js.lib.Float32Array; diff --git a/std/js/html/Float64Array.hx b/std/js/html/Float64Array.hx index 0fa72c2ff97..e1249aa1712 100644 --- a/std/js/html/Float64Array.hx +++ b/std/js/html/Float64Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,26 +20,6 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl. Do not edit! - package js.html; -// Explicitly include the compatibility class -import js.html.compat.Float64Array; - -@:native("Float64Array") -extern class Float64Array extends ArrayBufferView implements ArrayAccess -{ - static inline var BYTES_PER_ELEMENT : Int = 8; - - var length(default,null) : Int; - - /** @throws DOMError */ - @:overload( function( length : Int ) : Void {} ) - @:overload( function( array : Float64Array ) : Void {} ) - @:overload( function( array : Array ) : Void {} ) - function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - @:overload( function( array : Float64Array, ?offset : Int ) : Void {} ) - function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, ?end : Int ) : Float64Array; -} \ No newline at end of file +@:deprecated typedef Float64Array = js.lib.Float64Array; diff --git a/std/js/html/FocusEvent.hx b/std/js/html/FocusEvent.hx index 5193ceaf539..33bf935752f 100644 --- a/std/js/html/FocusEvent.hx +++ b/std/js/html/FocusEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("FocusEvent") -extern class FocusEvent extends UIEvent -{ +extern class FocusEvent extends UIEvent { /** Is an `EventTarget` representing a secondary target for this event. As in some cases (like when tabbing in or out a page), this property may be set to `null` for security reasons. diff --git a/std/js/html/FocusEventInit.hx b/std/js/html/FocusEventInit.hx index ae2dd7ad744..3e6d60c0f89 100644 --- a/std/js/html/FocusEventInit.hx +++ b/std/js/html/FocusEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,6 @@ package js.html; -typedef FocusEventInit = -{ - > UIEventInit, - @:optional var relatedTarget : EventTarget; +typedef FocusEventInit = UIEventInit & { + var ?relatedTarget : EventTarget; } \ No newline at end of file diff --git a/std/js/html/FontElement.hx b/std/js/html/FontElement.hx index 1e669db035d..15d7ffbfae1 100644 --- a/std/js/html/FontElement.hx +++ b/std/js/html/FontElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,11 +24,29 @@ package js.html; +/** + Implements the document object model (DOM) representation of the font element. The HTML Font Element `font` defines the font size, font face and color of text. + + Documentation [HTMLFontElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFontElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFontElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLFontElement") -extern class FontElement extends Element -{ +extern class FontElement extends Element { + + /** + Is a `DOMString` that reflects the `color` HTML attribute, containing either a named color or a color specified in the hexadecimal #RRGGBB format. + **/ var color : String; + + /** + Is a `DOMString` that reflects the `face` HTML attribute, containing a comma-separated list of one or more font names. + **/ var face : String; + + /** + Is a `DOMString` that reflects the `size` HTML attribute, containing either a font size number ranging from 1 to 7 or a relative size to the `size` attribute of the `basefont` element, for example -2 or +1. + **/ var size : String; } \ No newline at end of file diff --git a/std/js/html/FontFace.hx b/std/js/html/FontFace.hx index 953a5d70496..7110e6a3845 100644 --- a/std/js/html/FontFace.hx +++ b/std/js/html/FontFace.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,6 +24,8 @@ package js.html; +import js.lib.Promise; + /** The `FontFace` interface represents a single usable font face. It allows control of the source of the font face, being a URL to an external resource, or a buffer; it also allows control of when the font face is loaded and its current status. @@ -32,60 +34,61 @@ package js.html; @see **/ @:native("FontFace") -extern class FontFace -{ - +extern class FontFace { + /** - Is a `DOMString` that contains the family of the font. It is equivalent to the `@font-face/family` descriptor. + Is a `CSSOMString` that contains the family of the font. It is equivalent to the `@font-face/font-family` descriptor. **/ var family : String; - + /** - Is a `DOMString` that contains the style of the font. It is equivalent to the `@font-face/style` descriptor. + Is a `CSSOMString` that contains the style of the font. It is equivalent to the `@font-face/font-style` descriptor. **/ var style : String; - + /** - Is a `DOMString` that contains the weight of the font. It is equivalent to the `@font-face/weight` descriptor. + Is a `CSSOMString` that contains the weight of the font. It is equivalent to the `@font-face/font-weight` descriptor. **/ var weight : String; - + /** - Is a `DOMString` that contains how the font stretches. It is equivalent to the `@font-face/stretch` descriptor. + Is a `CSSOMString` that contains how the font stretches. It is equivalent to the `@font-face/font-stretch` descriptor. **/ var stretch : String; - + /** - Is a `DOMString` that contains the range of code encompassed the font. It is equivalent to the `@font-face/unicode-range` descriptor. + Is a `CSSOMString` that contains the range of code encompassed the font. It is equivalent to the `@font-face/unicode-range` descriptor. **/ var unicodeRange : String; - + /** - Is a `DOMString` that contains the variant of the font. It is equivalent to the `@font-face/range` descriptor. + Is a `CSSOMString` that contains the variant of the font. It is equivalent to the `@font-face/font-variant` descriptor. **/ var variant : String; - + /** - Is a `DOMString` that contains the features of the font. It is equivalent to the `@font-face/feature-settings` descriptor. + Is a `CSSOMString` that contains the features of the font. It is equivalent to the `@font-face/font-feature-settings`descriptor. **/ var featureSettings : String; - + /** Returns an enumerated value indicating the status of the font. It can be one of the following: `"unloaded"`, `"loading"`, `"loaded"`, or `"error"`. **/ var status(default,null) : FontFaceLoadStatus; - + /** Returns a `Promise` to a `FontFace` that fulfills when the font is completely loaded and rejects when an error happens. **/ var loaded(default,null) : Promise; - - /** @throws DOMError */ - function new( family : String, source : haxe.extern.EitherType>, ?descriptors : FontFaceDescriptors ) : Void; + /** @throws DOMError */ - + @:overload( function( family : String, source : js.lib.ArrayBuffer, ?descriptors : FontFaceDescriptors) : FontFace {} ) + @:overload( function( family : String, source : js.lib.ArrayBufferView, ?descriptors : FontFaceDescriptors) : FontFace {} ) + function new( family : String, source : String, ?descriptors : FontFaceDescriptors ) : Void; + /** Loads the font, returning a `Promise` to a `FontFace` that fulfills when the font is completely loaded and rejects when an error happens. + @throws DOMError **/ function load() : Promise; } \ No newline at end of file diff --git a/std/js/html/FontFaceDescriptors.hx b/std/js/html/FontFaceDescriptors.hx index 609299f2eea..d42f979d0ae 100644 --- a/std/js/html/FontFaceDescriptors.hx +++ b/std/js/html/FontFaceDescriptors.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,13 +24,13 @@ package js.html; -typedef FontFaceDescriptors = -{ - @:optional var display : String; - @:optional var featureSettings : String; - @:optional var stretch : String; - @:optional var style : String; - @:optional var unicodeRange : String; - @:optional var variant : String; - @:optional var weight : String; +typedef FontFaceDescriptors = { + var ?display : String; + var ?featureSettings : String; + var ?stretch : String; + var ?style : String; + var ?unicodeRange : String; + var ?variant : String; + var ?variationSettings : String; + var ?weight : String; } \ No newline at end of file diff --git a/std/js/html/FontFaceLoadStatus.hx b/std/js/html/FontFaceLoadStatus.hx index 178e14e648b..5fec36d2817 100644 --- a/std/js/html/FontFaceLoadStatus.hx +++ b/std/js/html/FontFaceLoadStatus.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -@:enum abstract FontFaceLoadStatus(String) -{ +enum abstract FontFaceLoadStatus(String) { var UNLOADED = "unloaded"; var LOADING = "loading"; var LOADED = "loaded"; diff --git a/std/js/html/FontFaceSet.hx b/std/js/html/FontFaceSet.hx index 2f8bf66965e..85f5de51690 100644 --- a/std/js/html/FontFaceSet.hx +++ b/std/js/html/FontFaceSet.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,50 +24,50 @@ package js.html; +import js.lib.Promise; + /** - The `FontFaceSet` interface of the CSS Font Loading API is an interface for loading font faces and checking their download statuses. + The `FontFaceSet` interface of the CSS Font Loading API manages the loading of font-faces and querying of their download status. Documentation [FontFaceSet](https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("FontFaceSet") -extern class FontFaceSet extends EventTarget -{ +extern class FontFaceSet extends EventTarget { var size(default,null) : Int; - + /** - An `EventListener` property called whenever an event of type `loading` is fired, indicating that a font face set has started to load. + An `EventListener` called whenever an event of type `loading` is fired, indicating a font-face set has started loading. **/ var onloading : haxe.Constraints.Function; - + /** - An `EventListener` property called whenever an event of type `loadingdone` is fired, indicating that a font face set has finished loading. + An `EventListener` called whenever an event of type `loadingdone` is fired, indicating that a font face set has finished loading. **/ var onloadingdone : haxe.Constraints.Function; - + /** - An `EventListener` property called whenever an event of type `loadingerror` is fired, indicating that an error occurred during the loading of a font face set. + An `EventListener` called whenever an event of type `loadingerror` is fired, indicating that an error occurred whilst loading a font-face set. **/ var onloadingerror : haxe.Constraints.Function; var ready(default,null) : Promise; - + /** - Indicates the font face's loading status. It will be one of `'loading'` or `'loaded'`. + Indicates the font-face's loading status. It will be one of `'loading'` or `'loaded'`. **/ var status(default,null) : FontFaceSetLoadStatus; - + /** @throws DOMError */ function add( font : FontFace ) : Void; function has( font : FontFace ) : Bool; - @:native("delete") - function delete_( font : FontFace ) : Bool; + function delete( font : FontFace ) : Bool; function clear() : Void; function entries() : FontFaceSetIterator; function values() : FontFaceSetIterator; /** @throws DOMError */ function forEach( cb : FontFace -> FontFace -> FontFaceSet -> Void, ?thisArg : Dynamic ) : Void; - function load( font : String, ?text : String = " " ) : Promise>; + function load( font : String, text : String = " " ) : Promise>; /** @throws DOMError */ - function check( font : String, ?text : String = " " ) : Bool; + function check( font : String, text : String = " " ) : Bool; } \ No newline at end of file diff --git a/std/js/html/FontFaceSetIterator.hx b/std/js/html/FontFaceSetIterator.hx index 2ecf87aa5e9..972b78ffffa 100644 --- a/std/js/html/FontFaceSetIterator.hx +++ b/std/js/html/FontFaceSetIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,9 +24,7 @@ package js.html; -@:native("FontFaceSetIterator") -extern class FontFaceSetIterator -{ +typedef FontFaceSetIterator = { /** @throws DOMError */ function next() : FontFaceSetIteratorResult; } \ No newline at end of file diff --git a/std/js/html/FontFaceSetIteratorResult.hx b/std/js/html/FontFaceSetIteratorResult.hx index 686f4613a32..219b0ff1e65 100644 --- a/std/js/html/FontFaceSetIteratorResult.hx +++ b/std/js/html/FontFaceSetIteratorResult.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -typedef FontFaceSetIteratorResult = -{ +typedef FontFaceSetIteratorResult = { var done : Bool; var value : Dynamic; } \ No newline at end of file diff --git a/std/js/html/FontFaceSetLoadEvent.hx b/std/js/html/FontFaceSetLoadEvent.hx new file mode 100644 index 00000000000..c445f1c8cf8 --- /dev/null +++ b/std/js/html/FontFaceSetLoadEvent.hx @@ -0,0 +1,44 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FontFaceSetLoadEvent.webidl. Do not edit! + +package js.html; + +/** + The `FontFaceSetLoadEvent` interface of the the Css Font Loading API is fired whenever a `FontFaceSet` loads. + + Documentation [FontFaceSetLoadEvent](https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSetLoadEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSetLoadEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("FontFaceSetLoadEvent") +extern class FontFaceSetLoadEvent extends Event { + + /** + Returns an array of `FontFace` instances each of which represents a single usable font. + **/ + var fontfaces(default,null) : Array; + + /** @throws DOMError */ + function new( type : String, ?eventInitDict : FontFaceSetLoadEventInit ) : Void; +} \ No newline at end of file diff --git a/std/js/html/FontFaceSetLoadEventInit.hx b/std/js/html/FontFaceSetLoadEventInit.hx new file mode 100644 index 00000000000..5cfe37a23ed --- /dev/null +++ b/std/js/html/FontFaceSetLoadEventInit.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\FontFaceSetLoadEvent.webidl. Do not edit! + +package js.html; + +typedef FontFaceSetLoadEventInit = EventInit & { + var ?fontfaces : Array; +} \ No newline at end of file diff --git a/std/js/html/FontFaceSetLoadStatus.hx b/std/js/html/FontFaceSetLoadStatus.hx index c2fbc3178c3..9180e1fdbcc 100644 --- a/std/js/html/FontFaceSetLoadStatus.hx +++ b/std/js/html/FontFaceSetLoadStatus.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -@:enum abstract FontFaceSetLoadStatus(String) -{ +enum abstract FontFaceSetLoadStatus(String) { var LOADING = "loading"; var LOADED = "loaded"; } \ No newline at end of file diff --git a/std/js/html/FormData.hx b/std/js/html/FormData.hx index 80f6966aa6b..0ac334cff00 100644 --- a/std/js/html/FormData.hx +++ b/std/js/html/FormData.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,57 +32,59 @@ package js.html; @see **/ @:native("FormData") -extern class FormData -{ +extern class FormData { /** @throws DOMError */ function new( ?form : FormElement ) : Void; - /** @throws DOMError */ - @:overload( function( name : String, value : Blob, ?filename : String ) : Void {} ) /** Appends a new value onto an existing key inside a `FormData` object, or adds the key if it does not already exist. + @throws DOMError **/ + @:overload( function( name : String, value : Blob, ?filename : String ) : Void {} ) function append( name : String, value : String ) : Void; - @:native("delete") - function delete_( name : String ) : Void; + + /** + Deletes a key/value pair from a `FormData` object. + **/ + function delete( name : String ) : Void; /** Returns the first value associated with a given key from within a `FormData` object. **/ - function get( name : String ) : haxe.extern.EitherType; + function get( name : String ) : haxe.extern.EitherType>; /** Returns an array of all the values associated with a given key from within a `FormData`. **/ - function getAll( name : String ) : Array>; + function getAll( name : String ) : Array>>; /** Returns a boolean stating whether a `FormData` object contains a certain key/value pair. **/ function has( name : String ) : Bool; - /** @throws DOMError */ - @:overload( function( name : String, value : Blob, ?filename : String ) : Void {} ) /** Sets a new value for an existing key inside a `FormData `object, or adds the key/value if it does not already exist. + @throws DOMError **/ + @:overload( function( name : String, value : Blob, ?filename : String ) : Void {} ) function set( name : String, value : String ) : Void; - /** @throws DOMError */ /** Returns an `Iteration_protocols` allowing to go through all key/value pairs contained in this object. + @throws DOMError **/ function entries() : FormDataIterator; - /** @throws DOMError */ /** Returns an `Iteration_protocols` allowing to go through all keys of the key/value pairs contained in this object. + @throws DOMError **/ function keys() : FormDataIterator; - /** @throws DOMError */ /** Returns an `Iteration_protocols` allowing to go through all values of the key/value pairs contained in this object. + @throws DOMError **/ function values() : FormDataIterator; /** @throws DOMError */ diff --git a/std/js/html/FormDataIterator.hx b/std/js/html/FormDataIterator.hx index 2738acda316..1af87400fd4 100644 --- a/std/js/html/FormDataIterator.hx +++ b/std/js/html/FormDataIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,9 +24,7 @@ package js.html; -@:native("FormDataIterator") -extern class FormDataIterator -{ +typedef FormDataIterator = { /** @throws DOMError */ function next() : Dynamic; } \ No newline at end of file diff --git a/std/js/html/FormElement.hx b/std/js/html/FormElement.hx index 062e78b26e1..bfc9d015b43 100644 --- a/std/js/html/FormElement.hx +++ b/std/js/html/FormElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,33 +25,89 @@ package js.html; /** - The `HTMLFormElement` interface provides methods to create and modify `form` elements. - document.forms - returns an array of HTMLFormElement objects referencing all forms on the page. - document.forms[index] - returns an HTMLFormElement object referencing the form at the specified index. - document.forms['id'] - returns an HTMLFormElement object referencing the form with the specified id. - document.forms['name'] - returns an HTMLFormElement object referencing the form with the specified name. + The `HTMLFormElement` interface represents a `form` element in the DOM; it allows access to and in some cases modification of aspects of the form, as well as access to its component elements. Documentation [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("HTMLFormElement") -extern class FormElement extends Element implements ArrayAccess -{ +extern class FormElement extends Element implements ArrayAccess { + + /** + A `DOMString` reflecting the value of the form's `accept-charset` HTML attribute, representing the character encoding that the server accepts. + **/ var acceptCharset : String; + + /** + A `DOMString` reflecting the value of the form's `action` HTML attribute, containing the URI of a program that processes the information submitted by the form. + **/ var action : String; + + /** + A `DOMString` reflecting the value of the form's `autocomplete` HTML attribute, indicating whether the controls in this form can have their values automatically populated by the browser. + **/ var autocomplete : String; + + /** + A `DOMString` reflecting the value of the form's `enctype` HTML attribute, indicating the type of content that is used to transmit the form to the server. Only specified values can be set. The two properties are synonyms. + **/ var enctype : String; + + /** + A `DOMString` reflecting the value of the form's `enctype` HTML attribute, indicating the type of content that is used to transmit the form to the server. Only specified values can be set. The two properties are synonyms. + **/ var encoding : String; + + /** + A `DOMString` reflecting the value of the form's `method` HTML attribute, indicating the HTTP method used to submit the form. Only specified values can be set. + **/ var method : String; + + /** + A `DOMString` reflecting the value of the form's `name` HTML attribute, containing the name of the form. + **/ var name : String; + + /** + A `Boolean` reflecting the value of the form's  `novalidate` HTML attribute, indicating whether the form should not be validated. + **/ var noValidate : Bool; + + /** + A `DOMString` reflecting the value of the form's `target` HTML attribute, indicating where to display the results received from submitting the form. + **/ var target : String; + + /** + A `HTMLFormControlsCollection` holding all form controls belonging to this form element. + **/ var elements(default,null) : HTMLCollection; + + /** + A `long` reflecting  the number of controls in the form. + **/ var length(default,null) : Int; - /** @throws DOMError */ + + /** + Submits the form to the server. + @throws DOMError + **/ function submit() : Void; + + /** + Resets the form to its initial state. + **/ function reset() : Void; + + /** + Returns `true` if the element's child controls are subject to constraint validation and satisfy those contraints; returns `false` if some controls do not satisfy their constraints. Fires an event named `invalid` at any control that does not satisfy its constraints; such controls are considered invalid if the event is not canceled. It is up to the programmer to decide how to respond to `false`. + **/ function checkValidity() : Bool; + + /** + Returns `true` if the element's child controls satisfy their validation constraints. When `false` is returned, cancelable `invalid` events are fired for each invalid child and validation problems are reported to the user. + **/ + function reportValidity() : Bool; } \ No newline at end of file diff --git a/std/js/html/FrameElement.hx b/std/js/html/FrameElement.hx index 204f617c423..f4844c9ef88 100644 --- a/std/js/html/FrameElement.hx +++ b/std/js/html/FrameElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,8 +25,7 @@ package js.html; @:native("HTMLFrameElement") -extern class FrameElement extends Element -{ +extern class FrameElement extends Element { var name : String; var scrolling : String; var src : String; diff --git a/std/js/html/FrameSetElement.hx b/std/js/html/FrameSetElement.hx index 7ddbb9a7979..b9732572d95 100644 --- a/std/js/html/FrameSetElement.hx +++ b/std/js/html/FrameSetElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,24 +32,24 @@ package js.html; @see **/ @:native("HTMLFrameSetElement") -extern class FrameSetElement extends Element -{ +extern class FrameSetElement extends Element { /** - Is a `DOMString` that represents the foreground color of text. + Is a `DOMString` structured as a comma-seperated list specifing the width of each column inside a frameset. **/ var cols : String; /** - Is a `DOMString` that represents the color of visited links. + Is a `DOMString` structured as a comma-seperated list specifing the height of each column inside a frameset. **/ var rows : String; var onafterprint : haxe.Constraints.Function; var onbeforeprint : haxe.Constraints.Function; - var onbeforeunload : Event -> String; + var onbeforeunload : Event -> Null; var onhashchange : haxe.Constraints.Function; var onlanguagechange : haxe.Constraints.Function; var onmessage : haxe.Constraints.Function; + var onmessageerror : haxe.Constraints.Function; var onoffline : haxe.Constraints.Function; var ononline : haxe.Constraints.Function; var onpagehide : haxe.Constraints.Function; diff --git a/std/js/html/FrameType.hx b/std/js/html/FrameType.hx index e196fccb487..9d1860084a6 100644 --- a/std/js/html/FrameType.hx +++ b/std/js/html/FrameType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -@:enum abstract FrameType(String) -{ +enum abstract FrameType(String) { var AUXILIARY = "auxiliary"; var TOP_LEVEL = "top-level"; var NESTED = "nested"; diff --git a/std/js/html/Gamepad.hx b/std/js/html/Gamepad.hx index 0036ee3ba18..47b9cba5e81 100644 --- a/std/js/html/Gamepad.hx +++ b/std/js/html/Gamepad.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("Gamepad") -extern class Gamepad -{ +extern class Gamepad { /** A `DOMString` containing identifying information about the controller. @@ -66,7 +65,7 @@ extern class Gamepad var axes(default,null) : Array; /** - A `DOMHighResTimeStamp` representing the last time the data for this gamepad was updated. Note that this property is not currently supported anywhere. + A `DOMHighResTimeStamp` representing the last time the data for this gamepad was updated. **/ var timestamp(default,null) : Float; diff --git a/std/js/html/GamepadButton.hx b/std/js/html/GamepadButton.hx index 1aa6f3dfbd8..2511dd78df1 100644 --- a/std/js/html/GamepadButton.hx +++ b/std/js/html/GamepadButton.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,13 +32,13 @@ package js.html; @see **/ @:native("GamepadButton") -extern class GamepadButton -{ +extern class GamepadButton { /** A boolean value indicating whether the button is currently pressed (`true`) or unpressed (`false`). **/ var pressed(default,null) : Bool; + var touched(default,null) : Bool; /** A double value used to represent the current state of analog buttons, such as the triggers on many modern gamepads. The values are normalized to the range 0.0 —1.0, with 0.0 representing a button that is not pressed, and 1.0 representing a button that is fully pressed. diff --git a/std/js/html/CSSValueList.hx b/std/js/html/GamepadEvent.hx similarity index 54% rename from std/js/html/CSSValueList.hx rename to std/js/html/GamepadEvent.hx index dac04577373..b6d927d4a44 100644 --- a/std/js/html/CSSValueList.hx +++ b/std/js/html/GamepadEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,29 +20,25 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\CSSValueList.webidl. Do not edit! +// This file is generated from mozilla\GamepadEvent.webidl. Do not edit! package js.html; /** - The `CSSValueList` interface derives from the `CSSValue` interface and provides the abstraction of an ordered collection of CSS values. + The GamepadEvent interface of the Gamepad API contains references to gamepads connected to the system, which is what the gamepad events `Window.gamepadconnected` and `Window.gamepaddisconnected` are fired in response to. - Documentation [CSSValueList](https://developer.mozilla.org/en-US/docs/Web/API/CSSValueList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSValueList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + Documentation [GamepadEvent](https://developer.mozilla.org/en-US/docs/Web/API/GamepadEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/GamepadEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). - @see + @see **/ -@:native("CSSValueList") -extern class CSSValueList extends CSSValue implements ArrayAccess -{ +@:native("GamepadEvent") +extern class GamepadEvent extends Event { /** - An `unsigned long` representing the number of `CSSValues` in the list. + Returns a `Gamepad` object, providing access to the associated gamepad data for the event fired. **/ - var length(default,null) : Int; + var gamepad(default,null) : Gamepad; - - /** - This method is used to retrieve a `CSSValue` by ordinal index. The order in this collection represents the order of the values in the CSS style property. If index is greater than or equal to the number of values in the list, this returns `null`. - **/ - function item( index : Int ) : CSSValue; + /** @throws DOMError */ + function new( type : String, ?eventInitDict : GamepadEventInit ) : Void; } \ No newline at end of file diff --git a/std/js/html/DummyInterfaceWorkers.hx b/std/js/html/GamepadEventInit.hx similarity index 86% rename from std/js/html/DummyInterfaceWorkers.hx rename to std/js/html/GamepadEventInit.hx index a1a298611d1..25769491dad 100644 --- a/std/js/html/DummyInterfaceWorkers.hx +++ b/std/js/html/GamepadEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,11 +20,10 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla\DummyBinding.webidl. Do not edit! +// This file is generated from mozilla\GamepadEvent.webidl. Do not edit! package js.html; -@:native("DummyInterfaceWorkers") -extern class DummyInterfaceWorkers -{ +typedef GamepadEventInit = EventInit & { + var ?gamepad : Gamepad; } \ No newline at end of file diff --git a/std/js/html/GamepadMappingType.hx b/std/js/html/GamepadMappingType.hx index 28c6e77cffe..60fc84fe08f 100644 --- a/std/js/html/GamepadMappingType.hx +++ b/std/js/html/GamepadMappingType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,8 +24,7 @@ package js.html; -@:enum abstract GamepadMappingType(String) -{ +enum abstract GamepadMappingType(String) { var NONE = ""; var STANDARD = "standard"; } \ No newline at end of file diff --git a/std/js/html/Geolocation.hx b/std/js/html/Geolocation.hx index 7da368a13b8..5697251e87c 100644 --- a/std/js/html/Geolocation.hx +++ b/std/js/html/Geolocation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,19 +31,17 @@ package js.html; @see **/ -@:native("Geolocation") -extern class Geolocation -{ - /** @throws DOMError */ +typedef Geolocation = { /** Determines the device's current location and gives back a `Position` object with the data. + @throws DOMError **/ function getCurrentPosition( successCallback : Position -> Void, ?errorCallback : PositionError -> Void, ?options : PositionOptions ) : Void; - /** @throws DOMError */ /** Returns a `long` value representing the newly established callback function to be invoked whenever the device location changes. + @throws DOMError **/ function watchPosition( successCallback : Position -> Void, ?errorCallback : PositionError -> Void, ?options : PositionOptions ) : Int; diff --git a/std/js/html/GetNotificationOptions.hx b/std/js/html/GetNotificationOptions.hx new file mode 100644 index 00000000000..313c924928d --- /dev/null +++ b/std/js/html/GetNotificationOptions.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\Notification.webidl. Do not edit! + +package js.html; + +typedef GetNotificationOptions = { + var ?tag : String; +} \ No newline at end of file diff --git a/std/js/html/GetRootNodeOptions.hx b/std/js/html/GetRootNodeOptions.hx new file mode 100644 index 00000000000..1547721d836 --- /dev/null +++ b/std/js/html/GetRootNodeOptions.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2019 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +// This file is generated from mozilla\Node.webidl. Do not edit! + +package js.html; + +typedef GetRootNodeOptions = { + var ?composed : Bool; +} \ No newline at end of file diff --git a/std/js/html/GetUserMediaRequest.hx b/std/js/html/GetUserMediaRequest.hx index ab01b4c38d5..34b30f133f8 100644 --- a/std/js/html/GetUserMediaRequest.hx +++ b/std/js/html/GetUserMediaRequest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,13 +24,14 @@ package js.html; -@:native("GetUserMediaRequest") -extern class GetUserMediaRequest -{ +typedef GetUserMediaRequest = { var windowID(default,null) : Int; var innerWindowID(default,null) : Int; var callID(default,null) : String; + var rawID(default,null) : String; + var mediaSource(default,null) : String; var isSecure(default,null) : Bool; + var isHandlingUserInput(default,null) : Bool; function getConstraints() : MediaStreamConstraints; } \ No newline at end of file diff --git a/std/js/html/HRElement.hx b/std/js/html/HRElement.hx index a2309eac1aa..b3ad0f67f78 100644 --- a/std/js/html/HRElement.hx +++ b/std/js/html/HRElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLHRElement") -extern class HRElement extends Element -{ +extern class HRElement extends Element { var align : String; var color : String; var noShade : Bool; diff --git a/std/js/html/HTMLAllCollection.hx b/std/js/html/HTMLAllCollection.hx index 466b12dd81f..93eace7d0c9 100644 --- a/std/js/html/HTMLAllCollection.hx +++ b/std/js/html/HTMLAllCollection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,8 +25,7 @@ package js.html; @:native("HTMLAllCollection") -extern class HTMLAllCollection implements ArrayAccess -{ +extern class HTMLAllCollection implements ArrayAccess { var length(default,null) : Int; @:overload( function( index : Int ) : Node {} ) diff --git a/std/js/html/HTMLCollection.hx b/std/js/html/HTMLCollection.hx index 756e731d310..50ad111aed9 100644 --- a/std/js/html/HTMLCollection.hx +++ b/std/js/html/HTMLCollection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,8 +32,7 @@ package js.html; @see **/ @:native("HTMLCollection") -extern class HTMLCollection implements ArrayAccess -{ +extern class HTMLCollection implements ArrayAccess { /** Returns the number of items in the collection. diff --git a/std/js/html/HTMLDocument.hx b/std/js/html/HTMLDocument.hx index eb88f85cbb7..8d9d04868c1 100644 --- a/std/js/html/HTMLDocument.hx +++ b/std/js/html/HTMLDocument.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2017 Haxe Foundation + * Copyright (C)2005-2019 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,40 +25,27 @@ package js.html; /** - `HTMLDocument` is an abstract interface of the DOM which provides access to special properties and methods not present by default on a regular (XML) document. + `HTMLDocument` is an abstract interface which extends the `Document` interface to add HTML-specific features to the document object. It represents the root of the HTML document, within which its entire DOM hierarchy resides. Documentation [HTMLDocument](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDocument) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDocument$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). @see **/ @:native("HTMLDocument") -extern class HTMLDocument extends Document -{ +extern class HTMLDocument extends Document { var domain : String; var cookie : String; - var body : BodyElement; - var head(default,null) : HeadElement; - var images(default,null) : HTMLCollection; - var embeds(default,null) : HTMLCollection; - var plugins(default,null) : HTMLCollection; - var links(default,null) : HTMLCollection; - var forms(default,null) : HTMLCollection; - var scripts(default,null) : HTMLCollection; var designMode : String; var fgColor : String; var linkColor : String; var vlinkColor : String; var alinkColor : String; var bgColor : String; - var anchors(default,null) : HTMLCollection; - var applets(default,null) : HTMLCollection; var all(default,null) : HTMLAllCollection; - function getElementsByName( elementName : String ) : NodeList; - function getItems( ?typeNames : String = "" ) : NodeList; /** @throws DOMError */ - @:overload( function( ?type : String = "text/html", ?replace : String = "" ) : HTMLDocument {} ) - function open( url : String, name : String, features : String, ?replace : Bool = false ) : Window; + @:overload( function( ?type : String, replace : String = "" ) : HTMLDocument {} ) + function open( url : String, name : String, features : String, replace : Bool = false ) : Window; /** @throws DOMError */ function close() : Void; /** @throws DOMError */ @@ -66,7 +53,7 @@ extern class HTMLDocument extends Document /** @throws DOMError */ function writeln( text : haxe.extern.Rest ) : Void; /** @throws DOMError */ - function execCommand( commandId : String, ?showUI : Bool = false, ?value : String = "" ) : Bool; + function execCommand( commandId : String, showUI : Bool = false, value : String = "" ) : Bool; /** @throws DOMError */ function queryCommandEnabled( commandId : String ) : Bool; /** @throws DOMError */ @@ -77,80 +64,38 @@ extern class HTMLDocument extends Document /** @throws DOMError */ function queryCommandValue( commandId : String ) : String; function clear() : Void; - /** @throws DOMError */ - function getSelection() : Selection; function captureEvents() : Void; function releaseEvents() : Void; /** Shorthand for creating an HTML `` element. */ inline function createTableCellElement() : TableCellElement { return cast createElement("td"); } - /** Shorthand for creating an HTML `
` element. */ - inline function createHRElement() : HRElement { return cast createElement("hr"); } /** Shorthand for creating an HTML `` element. */ - inline function createInputElement() : InputElement { return cast createElement("input"); } + /** Shorthand for creating an HTML `