From 0fa27e6b44ece5f9441da6933cfe06edeb334105 Mon Sep 17 00:00:00 2001 From: kleene Date: Wed, 16 Jul 2025 15:53:01 +0800 Subject: [PATCH 1/9] revert compile mode Issue: ICMQ3F Signed-off-by: kleene Change-Id: I18ae37bdfb6b4b512048a83bdc4b1273138256a9 --- ets2panda/driver/build_system/src/build/base_mode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index abeb5ba7b8..b2cc884429 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -143,7 +143,7 @@ export abstract class BaseMode { this.isBuildConfigModified = buildConfig.isBuildConfigModified as boolean | undefined; this.hasCleanWorker = false; this.byteCodeHar = buildConfig.byteCodeHar as boolean; - this.es2pandaMode = buildConfig?.es2pandaMode ?? ES2PANDA_MODE.RUN; + this.es2pandaMode = buildConfig?.es2pandaMode ?? ES2PANDA_MODE.RUN_PARALLEL; this.skipDeclCheck = buildConfig?.skipDeclCheck as boolean ?? true; } -- Gitee From 048083c4d7fb4aac764448e9791e93323343c7c5 Mon Sep 17 00:00:00 2001 From: fcc Date: Thu, 10 Jul 2025 16:16:56 +0800 Subject: [PATCH 2/9] fix crash when param's type annotation is null Check nullptr before use it to create new node. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICLGH0 Signed-off-by: fcc --- ets2panda/checker/ets/function.cpp | 2 +- ets2panda/checker/ets/utilityTypeHandlers.cpp | 52 +++++++++++-------- .../ets/defaultParametersLowering.cpp | 1 + .../param_typeannotation_null.ets | 24 +++++++++ 4 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/type_error_processing/param_typeannotation_null.ets diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 9c54d7de71..0a27aadae2 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -1617,7 +1617,7 @@ static bool AppendSignatureInfoParam(ETSChecker *checker, SignatureInfo *sigInfo if (!param->IsOptional()) { ++sigInfo->minArgCount; } - ES2PANDA_ASSERT(!param->IsOptional() || + ES2PANDA_ASSERT(!param->IsOptional() || param->Ident()->TsType()->IsTypeError() || checker->Relation()->IsSupertypeOf(param->Ident()->TsType(), checker->GlobalETSUndefinedType())); return true; } diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index 6341a07915..3bc3261558 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -525,6 +525,35 @@ void ETSChecker::CreatePartialClassDeclaration(ir::ClassDefinition *const newCla newClassDefinition->Variable()->SetTsType(nullptr); } +static void SetupFunctionParams(ir::ScriptFunction *function, varbinder::FunctionParamScope *paramScope, + checker::ETSChecker *checker) +{ + for (auto *params : function->Params()) { + auto *paramExpr = params->AsETSParameterExpression(); + if (paramExpr->Ident()->TypeAnnotation() == nullptr) { + paramExpr->Ident()->SetTsTypeAnnotation(nullptr); + } else { + auto *unionType = + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + checker->ProgramAllocNode( + ArenaVector( + {paramExpr->Ident()->TypeAnnotation(), + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + checker->ProgramAllocNode(checker->ProgramAllocator())}, + checker->ProgramAllocator()->Adapter()), + checker->ProgramAllocator()); + paramExpr->Ident()->SetTsTypeAnnotation(unionType); + unionType->SetParent(paramExpr->Ident()); + } + auto [paramVar, node] = paramScope->AddParamDecl(checker->ProgramAllocator(), checker->VarBinder(), paramExpr); + if (node != nullptr) { + checker->VarBinder()->ThrowRedeclaration(node->Start(), paramVar->Name(), paramVar->Declaration()->Type()); + } + + paramExpr->SetVariable(paramVar); + } +} + // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP) solid logic ir::MethodDefinition *ETSChecker::CreateNullishAccessor(ir::MethodDefinition *const accessor, ir::TSInterfaceDeclaration *interface) @@ -572,27 +601,8 @@ ir::MethodDefinition *ETSChecker::CreateNullishAccessor(ir::MethodDefinition *co ProgramAllocator()->Adapter()), ProgramAllocator())); } else { - for (auto *params : function->Params()) { - auto *paramExpr = params->AsETSParameterExpression(); - - auto *unionType = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode( - ArenaVector({paramExpr->Ident()->TypeAnnotation(), - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(ProgramAllocator())}, - ProgramAllocator()->Adapter()), - ProgramAllocator()); - paramExpr->Ident()->SetTsTypeAnnotation(unionType); - unionType->SetParent(paramExpr->Ident()); - - auto [paramVar, node] = paramScope->AddParamDecl(ProgramAllocator(), VarBinder(), paramExpr); - if (node != nullptr) { - VarBinder()->ThrowRedeclaration(node->Start(), paramVar->Name(), paramVar->Declaration()->Type()); - } - - paramExpr->SetVariable(paramVar); - } + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + SetupFunctionParams(function, paramScope, this); } nullishAccessor->SetOverloads(ArenaVector(ProgramAllocator()->Adapter())); diff --git a/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp b/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp index 901046c077..2c7afb91de 100644 --- a/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp +++ b/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp @@ -98,6 +98,7 @@ static void TransformFunction(public_lib::Context *ctx, ir::ScriptFunction *func } if (param->AsETSParameterExpression()->TypeAnnotation() == nullptr) { // #23134 ES2PANDA_ASSERT(ctx->diagnosticEngine->IsAnyError()); + param->AsETSParameterExpression()->SetInitializer(nullptr); continue; } defaultParams.push_back(param->AsETSParameterExpression()); diff --git a/ets2panda/test/ast/compiler/ets/type_error_processing/param_typeannotation_null.ets b/ets2panda/test/ast/compiler/ets/type_error_processing/param_typeannotation_null.ets new file mode 100644 index 0000000000..e23f26a1e7 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/type_error_processing/param_typeannotation_null.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface inter { + get value(): Double; + set value(A = Int.MAX_VALUE + 1); +} + +function foo(i: Partial>): void {} + +/* @@? 18:15 Error TypeError: The type of parameter 'A' cannot be inferred */ +/* @@? 18:17 Error SyntaxError: Parameter declaration should have an explicit type annotation. */ -- Gitee From 8c02a85ec1dbb76cf3d4508fc7d9c115ee8e03a8 Mon Sep 17 00:00:00 2001 From: daizihan Date: Wed, 9 Jul 2025 19:06:08 +0800 Subject: [PATCH 3/9] Fix fuzz crash by adapting recursiveguard Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICL7RW?from=project-issue Signed-off-by: daizihan --- ets2panda/parser/ETSparser.h | 3 --- ets2panda/parser/ETSparserExpressions.cpp | 22 +++++++------------ ets2panda/parser/parserImpl.h | 7 ++++++ ets2panda/parser/statementParser.cpp | 9 ++++++++ ets2panda/test/runtime/ets/too_many_async.ets | 22 +++++++++++++++++++ ets2panda/test/runtime/ets/too_many_await.ets | 22 +++++++++++++++++++ .../test/runtime/ets/too_many_left_brace.ets | 22 +++++++++++++++++++ .../ets/too_many_left_square_brackets.ets | 21 ++++++++++++++++++ .../test/runtime/ets/too_many_new_expr.ets | 22 +++++++++++++++++++ .../srcdumper/srcdumper-ets-ignored.txt | 5 +++++ 10 files changed, 138 insertions(+), 17 deletions(-) create mode 100644 ets2panda/test/runtime/ets/too_many_async.ets create mode 100644 ets2panda/test/runtime/ets/too_many_await.ets create mode 100644 ets2panda/test/runtime/ets/too_many_left_brace.ets create mode 100644 ets2panda/test/runtime/ets/too_many_left_square_brackets.ets create mode 100644 ets2panda/test/runtime/ets/too_many_new_expr.ets diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 8bbfeecf69..0ce7879c46 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -18,7 +18,6 @@ #include "util/arktsconfig.h" #include "util/importPathManager.h" -#include "util/recursiveGuard.h" #include "innerSourceParser.h" #include "TypedParser.h" #include "ir/base/classDefinition.h" @@ -460,7 +459,6 @@ private: friend class ExternalSourceParser; friend class InnerSourceParser; - friend ir::Expression *HandleLeftParanthesis(ETSParser *parser, ExpressionParseFlags flags); private: uint32_t namespaceNestedRank_; @@ -470,7 +468,6 @@ private: parser::Program *globalProgram_; std::vector insertingNodes_ {}; std::unique_ptr importPathManager_ {nullptr}; - RecursiveContext recursiveCtx_; }; class ExternalSourceParser { diff --git a/ets2panda/parser/ETSparserExpressions.cpp b/ets2panda/parser/ETSparserExpressions.cpp index 707d44ad1b..7422c412b5 100644 --- a/ets2panda/parser/ETSparserExpressions.cpp +++ b/ets2panda/parser/ETSparserExpressions.cpp @@ -321,26 +321,20 @@ ir::Expression *ETSParser::ParsePrimaryExpressionWithLiterals(ExpressionParseFla } } -// This function is used to handle the left parenthesis in the expression parsing. -ir::Expression *HandleLeftParanthesis(ETSParser *parser, ExpressionParseFlags flags) +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *ETSParser::ParsePrimaryExpression(ExpressionParseFlags flags) { - TrackRecursive trackRecursive(parser->recursiveCtx_); + TrackRecursive trackRecursive(RecursiveCtx()); if (!trackRecursive) { - parser->LogError(diagnostic::DEEP_NESTING); - while (parser->Lexer()->GetToken().Type() != lexer::TokenType::EOS) { - parser->Lexer()->NextToken(); + LogError(diagnostic::DEEP_NESTING); + while (Lexer()->GetToken().Type() != lexer::TokenType::EOS) { + Lexer()->NextToken(); } - return parser->AllocBrokenExpression(parser->Lexer()->GetToken().Loc()); + return AllocBrokenExpression(Lexer()->GetToken().Loc()); } - return parser->ParseCoverParenthesizedExpressionAndArrowParameterList(flags); -} - -// NOLINTNEXTLINE(google-default-arguments) -ir::Expression *ETSParser::ParsePrimaryExpression(ExpressionParseFlags flags) -{ switch (Lexer()->GetToken().Type()) { case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { - return HandleLeftParanthesis(this, flags); + return ParseCoverParenthesizedExpressionAndArrowParameterList(flags); } case lexer::TokenType::KEYW_THIS: { return ParseThisExpression(); diff --git a/ets2panda/parser/parserImpl.h b/ets2panda/parser/parserImpl.h index 4f134e6a2a..6c9ef85562 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -26,6 +26,7 @@ #include "parser/program/program.h" #include "util/diagnosticEngine.h" #include "util/helpers.h" +#include "util/recursiveGuard.h" namespace ark::es2panda::lexer { class RegExpParser; @@ -574,6 +575,11 @@ protected: const std::function &parseElement, lexer::SourcePosition *sourceEnd = nullptr, bool allowTrailingSep = false); + RecursiveContext &RecursiveCtx() + { + return recursiveCtx_; + } + private: bool GetCanBeForInOf(ir::Expression *leftNode, ir::AstNode *initNode); Program *program_; @@ -584,6 +590,7 @@ private: const util::Options *options_; util::DiagnosticEngine &diagnosticEngine_; public_lib::Context *ctx_ {nullptr}; + RecursiveContext recursiveCtx_; }; } // namespace ark::es2panda::parser diff --git a/ets2panda/parser/statementParser.cpp b/ets2panda/parser/statementParser.cpp index 00a7aae2d6..aa8941392c 100644 --- a/ets2panda/parser/statementParser.cpp +++ b/ets2panda/parser/statementParser.cpp @@ -63,6 +63,7 @@ #include "lexer/lexer.h" #include "lexer/token/letters.h" #include "lexer/token/sourceLocation.h" +#include "util/recursiveGuard.h" #include "util/ustring.h" #include "generated/diagnostic.h" @@ -91,6 +92,14 @@ ir::Statement *ParserImpl::ParseStatementLiteralIdentHelper(StatementParsingFlag // NOLINTNEXTLINE(google-default-arguments) ir::Statement *ParserImpl::ParseStatementPunctuatorsHelper(StatementParsingFlags flags) { + TrackRecursive trackRecursive(RecursiveCtx()); + if (!trackRecursive) { + LogError(diagnostic::DEEP_NESTING); + while (Lexer()->GetToken().Type() != lexer::TokenType::EOS) { + Lexer()->NextToken(); + } + return AllocBrokenStatement(Lexer()->GetToken().Loc()); + } switch (lexer_->GetToken().Type()) { case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: return ParseBlockStatement(); diff --git a/ets2panda/test/runtime/ets/too_many_async.ets b/ets2panda/test/runtime/ets/too_many_async.ets new file mode 100644 index 0000000000..066837c21e --- /dev/null +++ b/ets2panda/test/runtime/ets/too_many_async.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*--- + tags: [compile-only, negative] +---*/ + +// This test cannot moved to astchecker, because this will lead python JSON parse error: +// Failed with maximum recursion depth exceeded while decoding a JSON object from a unicode string + +async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async(ync(async(async(async(async(async(async(async(async(async(async(async( diff --git a/ets2panda/test/runtime/ets/too_many_await.ets b/ets2panda/test/runtime/ets/too_many_await.ets new file mode 100644 index 0000000000..94fe792274 --- /dev/null +++ b/ets2panda/test/runtime/ets/too_many_await.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*--- + tags: [compile-only, negative] +---*/ + +// This test cannot moved to astchecker, because this will lead python JSON parse error: +// Failed with maximum recursion depth exceeded while decoding a JSON object from a unicode string + +await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await await diff --git a/ets2panda/test/runtime/ets/too_many_left_brace.ets b/ets2panda/test/runtime/ets/too_many_left_brace.ets new file mode 100644 index 0000000000..aab155383e --- /dev/null +++ b/ets2panda/test/runtime/ets/too_many_left_brace.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*--- + tags: [compile-only, negative] +---*/ + +// This test cannot moved to astchecker, because this will lead python JSON parse error: +// Failed with maximum recursion depth exceeded while decoding a JSON object from a unicode string + +{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ diff --git a/ets2panda/test/runtime/ets/too_many_left_square_brackets.ets b/ets2panda/test/runtime/ets/too_many_left_square_brackets.ets new file mode 100644 index 0000000000..07d66a05d5 --- /dev/null +++ b/ets2panda/test/runtime/ets/too_many_left_square_brackets.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*--- + tags: [compile-only, negative] +---*/ + +// This test cannot moved to astchecker, because this will lead python JSON parse error: +// Failed with maximum recursion depth exceeded while decoding a JSON object from a unicode string +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ diff --git a/ets2panda/test/runtime/ets/too_many_new_expr.ets b/ets2panda/test/runtime/ets/too_many_new_expr.ets new file mode 100644 index 0000000000..772493b196 --- /dev/null +++ b/ets2panda/test/runtime/ets/too_many_new_expr.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*--- + tags: [compile-only, negative] +---*/ + +// This test cannot moved to astchecker, because this will lead python JSON parse error: +// Failed with maximum recursion depth exceeded while decoding a JSON object from a unicode string + +new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new(new( diff --git a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt index 67a4459f5d..1d0a071b78 100644 --- a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt +++ b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt @@ -39,6 +39,11 @@ runtime/ets/type_param_in_union.ets runtime/ets/StringFasta.ets runtime/ets/struct-identifier.ets runtime/ets/struct-init2.ets +runtime/ets/too_many_async.ets +runtime/ets/too_many_await.ets +runtime/ets/too_many_left_brace.ets +runtime/ets/too_many_left_square_brackets.ets +runtime/ets/too_many_new_expr.ets ast/compiler/ets/DeclareIndexerTest.ets ast/parser/ets/import_tests/import_class_with_static_field/import_class_with_static_field.ets -- Gitee From cfe75f093188cd01c3c7765141b3521303b38ad4 Mon Sep 17 00:00:00 2001 From: Zhelyapov Aleksey Date: Tue, 24 Jun 2025 18:38:23 +0300 Subject: [PATCH 4/9] Implements es2panda benchmarks Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICFWP8 Signed-off-by: Zhelyapov Aleksey Signed-off-by: nikozer --- ets2panda/test/benchmarks/README.md | 76 + ets2panda/test/benchmarks/bench_1-max.txt | 66 + ets2panda/test/benchmarks/bench_1.ets | 1569 +++++++++++++++++ ets2panda/test/benchmarks/etsstdlib-max.txt | 66 + .../test/benchmarks/runner/arg_parser.py | 71 + .../benchmarks/runner/benchmark_comparator.py | 144 ++ .../benchmarks/runner/benchmark_runner.py | 101 ++ .../test/benchmarks/runner/metrics_utils.py | 81 + ets2panda/test/benchmarks/runner/runner.py | 112 ++ 9 files changed, 2286 insertions(+) create mode 100644 ets2panda/test/benchmarks/README.md create mode 100644 ets2panda/test/benchmarks/bench_1-max.txt create mode 100644 ets2panda/test/benchmarks/bench_1.ets create mode 100644 ets2panda/test/benchmarks/etsstdlib-max.txt create mode 100644 ets2panda/test/benchmarks/runner/arg_parser.py create mode 100644 ets2panda/test/benchmarks/runner/benchmark_comparator.py create mode 100644 ets2panda/test/benchmarks/runner/benchmark_runner.py create mode 100644 ets2panda/test/benchmarks/runner/metrics_utils.py create mode 100644 ets2panda/test/benchmarks/runner/runner.py diff --git a/ets2panda/test/benchmarks/README.md b/ets2panda/test/benchmarks/README.md new file mode 100644 index 0000000000..4774895e4d --- /dev/null +++ b/ets2panda/test/benchmarks/README.md @@ -0,0 +1,76 @@ +# Logic +- Run es2panda for benchmark files from this directory +- Dump perfmetrics to `/test-current-perf.txt` for current es2panda +- Dump perfmetrics to `/test-pre_merge-perf.txt` for another (pre-merge) es2panda +- Dump comparison report to `/test-report.txt` in format like `time=-90.00ms (-1.9%)` + +### Static mode +If `actual_perf > max_perf * (1 + static_regression)` - an error occurs. Example: +``` +[PERF REGRESSION] Failed for bench_1-current-perf.txt: Memory exceeded threshold. + Limit: 5.0%, Actual: +406.25% + Base: 32.00MB, New: 162.00MB + Threshold: < 33.60MB +``` + +If `actual_perf < max_perf * (1 + 3 * static_regression)` - an error occurs. Example: +``` +[UPDATE REQUIRED] Very good perf for bench_1-current-perf.txt: Please update *-max.txt. + Hint: use flag '--dump-perf-metrics' and Release build of es2panda. +``` + +### Dynamic mode +If `actual_perf > pre_merge_perf * dynamic_regression` - an error occurs (the same as in static mode). + +### Errors reporting +Errors are printed to the console and also to `/error_log.txt`. + +# Arguments +- `--mode` - 'static' to compare with `*-max.txt` files. 'dynamic' to compare with pre-merge es2panda. +- `--es2panda` - Path to current es2panda (aka /bin/es2panda) +- `--es2panda-pre-merge` - Path to pre-merge es2panda (aka /bin/es2panda) +- `--test-dir` - Path to test directory with test files +- `--work-dir` - Path to the working temp folder with gen, intermediate and report folders +- `--dynamic-regression` - Acceptable regression compared to the another (pre-merge) es2panda +- `--static-regression` - Acceptable regression compared to static vales from `*-max.txt` files +- `--runs` - The number of runs to average +- `--werror` - Warnings as errors + +# Max values +Each file have companion: for `test.ets` companion is `test-max.txt`. This file contains max values for metrics. + +# Local reproduction +```bash +# static mode +python3 /ets2panda/test/benchmarks/runner/runner.py --mode=static --es2panda=/bin/es2panda --work-dir=/e2p_benchmarks --test-dir=/ets2panda/test/benchmarks + +# dynamic mode +python3 /ets2panda/test/benchmarks/runner/runner.py --mode=dynamic --es2panda=/bin/es2panda --work-dir=/e2p_benchmarks --test-dir=/ets2panda/test/benchmarks --es2panda-pre-merge=/bin/es2panda +``` +See `--help` if needed. + +# CI +You can download artifacts for this job with perf stat. + +# Artifacts example + +test-perf.txt +``` +================ es2panda perf metrics (Averaged over 3 runs) ================ +:@phases : time=891.00ms mem=140.00MB +:@phases/ConstantExpressionLowering : time=233.00ms mem=0.26MB +:@phases/TopLevelStatements : time=193.00ms mem=79.00MB +:@phases/ResolveIdentifiers : time=83.40ms mem=6.00MB +:@phases/CheckerPhase : time=78.60ms mem=19.00MB +``` + +test-report.txt +``` +Performance Comparison: 'bench_1-max.txt' vs 'bench_1-current-perf.txt' +================================================================================ +:@EmitProgram : time=+2.90ms (+4.6%) mem=+0.00MB (+0.0%) +:@GenerateProgram : time=+4.67ms (+6.7%) mem=0.00MB (0.0%) +:@GenerateProgram/OptimizeBytecode : time=0.00ms (0.0%) mem=0.00MB (0.0%) +:@phases : time=+22.67ms (+2.6%) mem=+0.00MB (+0.0%) +:@phases/AmbientLowering : time=-0.07ms (-0.6%) mem=0.00MB (0.0%) +``` diff --git a/ets2panda/test/benchmarks/bench_1-max.txt b/ets2panda/test/benchmarks/bench_1-max.txt new file mode 100644 index 0000000000..81e3099f82 --- /dev/null +++ b/ets2panda/test/benchmarks/bench_1-max.txt @@ -0,0 +1,66 @@ +================ es2panda perf metrics (Averaged over 500 runs) ================ + +:@phases : time=1472.50ms mem=159.89MB +:@GenerateProgram : time=439.95ms mem=0.00MB +:@phases/ConstantExpressionLowering : time=374.76ms mem=0.30MB +:@phases/TopLevelStatements : time=273.61ms mem=81.00MB +:@GenerateProgram/OptimizeBytecode : time=264.15ms mem=0.00MB +:@EmitProgram : time=148.99ms mem=31.22MB +:@phases/CheckerPhase : time=132.83ms mem=23.28MB +:@phases/ResolveIdentifiers : time=112.03ms mem=6.00MB +:@phases/InterfaceObjectLiteralLowering : time=81.20ms mem=7.00MB +:@phases/LambdaObjectConversion : time=74.07ms mem=5.00MB +:@phases/ScopesInitPhase : time=62.35ms mem=13.79MB +:@phases/PartialExportClassGen : time=45.10ms mem=8.00MB +:@phases/Unbox : time=29.11ms mem=0.74MB +:@phases/OptionalLowering : time=25.61ms mem=0.99MB +:@phases/ResizableArrayConvert : time=22.40ms mem=0.51MB +:@phases/InterfacePropertyDeclarationsPhase : time=21.20ms mem=1.00MB +:@phases/EnumLoweringPhase : time=19.05ms mem=0.81MB +:@phases/EnumPostCheckLoweringPhase : time=18.67ms mem=0.00MB +:@phases/OverloadMappingLowering : time=18.01ms mem=0.00MB +:@phases/DeclareOverloadLowering : time=17.97ms mem=0.00MB +:@phases/PromiseVoidInferencePhase : time=17.90ms mem=0.00MB +:@phases/InsertOptionalParametersAnnotation : time=17.38ms mem=0.74MB +:@phases/AmbientLowering : time=17.22ms mem=0.00MB +:@phases/ExpressionLambdaConstruction : time=17.15ms mem=0.00MB +:@phases/GradualTypeNarrowing : time=16.99ms mem=1.88MB +:@phases/DefaultParametersInConstructorLowering : time=16.67ms mem=0.52MB +:@phases/ObjectIndexLowering : time=3.65ms mem=0.71MB +:@phases/CreateGenericBridges : time=3.36ms mem=0.00MB +:@phases/ArrayLiteralLowering : time=3.24ms mem=0.52MB +:@phases/BoxingForLocals : time=1.64ms mem=0.00MB +:@phases/ObjectLiteralLowering : time=1.50ms mem=0.23MB +:@phases/PrimitiveConversion : time=1.26ms mem=0.00MB +:@phases/OpAssignmentLowering : time=1.22ms mem=0.00MB +:@phases/UnionLowering : time=0.95ms mem=0.00MB +:@phases/StringConstructorLowering : time=0.74ms mem=0.00MB +:@phases/OptionalArgumentsLowering : time=0.67ms mem=0.03MB +:@phases/LateInitializationConvert : time=0.63ms mem=0.00MB +:@phases/TypeFromLowering : time=0.63ms mem=0.00MB +:@phases/DefaultParametersLowering : time=0.62ms mem=0.00MB +:@phases/ExpandBracketsPhase : time=0.60ms mem=0.00MB +:@phases/CapturedVariables : time=0.57ms mem=0.00MB +:@phases/RestTupleConstructionPhase : time=0.54ms mem=0.00MB +:@phases/SpreadConstructionPhase : time=0.51ms mem=0.00MB +:@phases/DynamicImport : time=0.51ms mem=0.00MB +:@phases/StringComparisonLowering : time=0.47ms mem=0.00MB +:@phases/RestArgsLowering : time=0.37ms mem=0.00MB +:@phases/BigIntLowering : time=0.36ms mem=0.00MB +:@phases/ObjectIteratorLowering : time=0.32ms mem=0.00MB +:@phases/StringConstantsLowering : time=0.32ms mem=0.00MB +:@phases/SetterLowering : time=0.31ms mem=0.00MB +:@phases/RecordLowering : time=0.31ms mem=0.00MB +:@phases/ExtentionAccessorPhase : time=0.31ms mem=0.00MB +:@phases/AsyncMethodLowering : time=0.31ms mem=0.00MB +:@phases/AnnotationCopyPostLowering : time=0.28ms mem=0.00MB +:@phases/AnnotationCopyLowering : time=0.28ms mem=0.00MB +:@phases/SetJumpTargetPhase : time=0.26ms mem=0.00MB +:@phases/plugins-after-parse : time=0.01ms mem=0.00MB +:@phases/ExportAnonymousConstPhase : time=0.00ms mem=0.00MB +:@phases/plugins-after-lowering : time=0.00ms mem=0.00MB +:@phases/DeclGenPhase : time=0.00ms mem=0.00MB +:@phases/plugins-after-bind : time=0.00ms mem=0.00MB +:@phases/PackageImplicitImport : time=0.00ms mem=0.00MB +:@phases/plugins-after-check : time=0.00ms mem=0.00MB +:@phases/CFGBuilder : time=0.00ms mem=0.00MB diff --git a/ets2panda/test/benchmarks/bench_1.ets b/ets2panda/test/benchmarks/bench_1.ets new file mode 100644 index 0000000000..a200b8c29d --- /dev/null +++ b/ets2panda/test/benchmarks/bench_1.ets @@ -0,0 +1,1569 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// --------------------------------------------------------------------------------------------------------------------- +// AccessBinaryTrees.ets +// --------------------------------------------------------------------------------------------------------------------- + +class TreeNode { + private left: TreeNode | null; + private right: TreeNode | null; + private item: int; + + constructor(left: TreeNode | null, right: TreeNode | null, item: int) { + this.left = left; + this.right = right; + this.item = item; + } + + public itemCheck(): int { + if (this.left == null) + return this.item; + else + return this.item + this.left!.itemCheck() - this.right!.itemCheck(); + } +} + +export class AccessBinaryTrees { + static readonly startDepth = 4; + static readonly endDepth = 7; + static readonly expected = -4; + + static bottomUpTree(item: int, depth: int): TreeNode { + if (depth > 0) { + return new TreeNode( + AccessBinaryTrees.bottomUpTree(2*item - 1, depth-1), + AccessBinaryTrees.bottomUpTree(2*item, depth-1), + item + ); + } + return new TreeNode(null, null, item); + } + + public run(): void { + let ret: int = 0; + + for (let n: int = AccessBinaryTrees.startDepth; n <= AccessBinaryTrees.endDepth; n++) { + let minDepth: int = AccessBinaryTrees.startDepth; + let maxDepth: int = max(minDepth + 2, n); + let stretchDepth: int = maxDepth + 1; + let check: int = AccessBinaryTrees.bottomUpTree(0, stretchDepth).itemCheck(); + + let longLivedTree = AccessBinaryTrees.bottomUpTree(0, maxDepth); + + for (let depth = minDepth; depth <= maxDepth; depth += 2) { + let iterations: int = 1 << (maxDepth - depth + minDepth); + + check = 0; + for (let i: int = 1; i <= iterations; i++) { + check += AccessBinaryTrees.bottomUpTree(i, depth).itemCheck(); + check += AccessBinaryTrees.bottomUpTree(-i, depth).itemCheck(); + } + } + + ret += longLivedTree.itemCheck(); + } + + arktest.assertEQ(ret, AccessBinaryTrees.expected, "Incorrect result") + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// RestTuple6.ets +// --------------------------------------------------------------------------------------------------------------------- + +class A2 {} +class B2 {} + +class C2 { + foo(...p: [A2, B2]): boolean { + return p[0] == p[1] + } + + moo(a:int, ...p: [A2, B2]): boolean { + return p[0] == p[1] + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// GenericBridges_02.ets +// --------------------------------------------------------------------------------------------------------------------- + +interface B3 { + f23(v: B3): B3; +} + +class C3 implements B3 { + + f13(v: T3): T3 { + return v; + } + + f23(v: C3): C3 { + return new C3(); + } + + f23(v: B3): B3 { + return this.f23(v as C3); + } + + f33(v: T3|string): string { + return "C3.f33"; + } + + f43(v: C3|Numeric): string { + return "C3.f43"; + } + + f53(x: T1|Z3|C3[]): string { + return "C3.f53"; + } + + f63(x: C3, y: C3): string { + return "C3.f63"; + } + + f73(x: T3, y: C3): string { + return "C3.f73"; + } + + f83(x: string): string { + return "C3.f83"; + } + + f93(z: Z3, y: T1): string { + return "C3.f93"; + } +} + +class D3 extends C3 { + f13(v: string): string { + return "D3.f13"; + } + + f13(v: Numeric|string|C3): string { + return this.f13(v as string); + } + + f13(v: Int): Int { + return 7; + } + + f23(v: D3): D3 { + return new D3(); + } + + f33(v: string): string { + return "D3.f33"; + } + + f43(v: D3): string { + return "D3.f43"; + } + + f43 (x: int, y: int): int { + return x + y; + } + + f53(x: string|W3|C3[]): string { + return "D3.f53"; + } + + f63(): string { + return "D3.f63"; + } + +// f73(x: string, y: D3): string { +// return "D3.f73"; +// } + + f83(x: string): string { + return "D3.f83"; + } + + f93(z: W3, y: string): string { + return "D3.f93-1"; + } + + f93(z: W3, y: Int): string { + return "D3.f93-2"; + } +} + +class F3 extends D3 {} + +class G3 extends C3 {} + +class E3 extends C3 { + + f13(v: U3): Integral { + if (v instanceof Int) { + return new Int(7); + } else if (v instanceof Long) { + return new Long(8); + } else { + return new Int(-1); + } + } + + f23(v: E3): E3 { + return new E3(); + } + + f33(){} + + f43(x:int, y: int): int { return x + y; } + +// f73(x: U3, y: E3): string { +// return "E3.f73"; +// } +} + +function foo13(c: C3) { + arktest.assertEQ(c.f13(0), 7) + arktest.assertEQ(c.f23(c).f13(0), 7) + arktest.assertEQ(c.f53(""), "C3.f53") + arktest.assertEQ(c.f63(c, c), "C3.f63") +} + +function foo23(c: C3) { + arktest.assertEQ(c.f13(0), 8) + arktest.assertEQ(c.f23(c).f13(0), 8) + arktest.assertEQ(c.f53(""), "C3.f53") + arktest.assertEQ(c.f73(3, c), "E3.f73") +} + +function ttt3(c: C3): void { + arktest.assertEQ(c.f13("ah"), "D3.f13") + arktest.assertEQ(c.f23(c).f13("ah"), "D3.f13") + arktest.assertEQ((c.f23(c as B3) as C3).f13("ah"), "D3.f13") + arktest.assertEQ(c.f33("ah"), "D3.f33") + arktest.assertEQ(c.f43(c), "D3.f43") + arktest.assertEQ(c.f53("ah"), "D3.f53") + arktest.assertEQ(c.f63(c, c), "C3.f63") + arktest.assertEQ((c as D3).f63(), "D3.f63") + arktest.assertEQ(c.f73("ah", c), "D3.f73") + arktest.assertEQ(c.f83(""), "D3.f83") + arktest.assertEQ(c.f93("", ""), "C3.f93") + arktest.assertEQ((c as D3).f93("", 0), "D3.f93-2") +} + +// --------------------------------------------------------------------------------------------------------------------- +// ArrowArity.ets +// --------------------------------------------------------------------------------------------------------------------- + +type S4 = string + +function xassert4(a: S4, b: S4) { arktest.assertEQ(a, b) } + +function p0call4(f: () => S4, a: S4[]) { + return f() +} +function p1call4(f: (p1: S4) => S4, a: S4[]) { + return f(a[0]) +} +function p2call4(f: (p1: S4, p2: S4) => S4, a: S4[]) { + return f(a[0], a[1]) +} +function p012call4(f: () => S4, a: S4[]) { + return p0call4(f, a) + p1call4(f, a) + p2call4(f, a) +} +function p_12call4(f: (p1: S4) => S4, a: S4[]) { + return p1call4(f, a) + p2call4(f, a) +} +function p__2call4(f: (p1: S4, p2: S4) => S4, a: S4[]) { + return p2call4(f, a) +} + +function r0__call4(f: (p1?: S4, p2?: S4) => S4, a: S4[]) { + return f() + f(a[0]) + f(a[0], a[1]) +} +function r_1_call4(f: (p1: S4, p2?: S4) => S4, a: S4[]) { + return f(a[0]) + f(a[0], a[1]) +} + +function testBasicArity4() { + let args = ["a", "b"] + let f0 = () => "/f0:" + let f1 = (a1: S4) => "/f1:" + a1 + let f2 = (a1: S4, a2: S4) => "/f2:" + a1 + a2 + + xassert4(p012call4(f0, args), "/f0:/f0:/f0:") + xassert4(p_12call4(f0, args), "/f0:/f0:") + xassert4(p_12call4(f1, args), "/f1:a/f1:a") + xassert4(p__2call4(f0, args), "/f0:") + xassert4(p__2call4(f1, args), "/f1:a") + xassert4(p__2call4(f2, args), "/f2:ab") + + xassert4(r0__call4(f0, args), "/f0:/f0:/f0:") + xassert4(r_1_call4(f0, args), "/f0:/f0:") + xassert4(r_1_call4(f1, args), "/f1:a/f1:a") +} +testBasicArity4(); + +function testOptionalArity4() { + let args = ["a", "b"] + let tou = (v?: string) => v ?? "u" + let f0 = (a1?: S4, a2?: S4) => "/f0:" + tou(a1) + tou(a2) + let f1 = (a1: S4, a2?: S4) => "/f1:" + a1 + tou(a2) + let f2 = (a1: S4, a2: S4) => "/f2:" + a1 + a2 + + xassert4(p012call4(f0, args), "/f0:uu/f0:au/f0:ab") + xassert4(p_12call4(f0, args), "/f0:au/f0:ab") + xassert4(p_12call4(f1, args), "/f1:au/f1:ab") + xassert4(p__2call4(f0, args), "/f0:ab") + xassert4(p__2call4(f1, args), "/f1:ab") + xassert4(p__2call4(f2, args), "/f2:ab") + + xassert4(r0__call4(f0, args), "/f0:uu/f0:au/f0:ab") + xassert4(r_1_call4(f0, args), "/f0:au/f0:ab") + xassert4(r_1_call4(f1, args), "/f1:au/f1:ab") +} +testOptionalArity4(); + +function testDfltArity4() { + let args = ["a", "b"] + let f0 = (a1: S4 = "x", a2: S4 = "y") => "/f0:" + a1 + a2 + let f1 = (a1: S4, a2: S4 = "y") => "/f1:" + a1 + a2 + let f2 = (a1: S4, a2: S4) => "/f2:" + a1 + a2 + + xassert4(p012call4(f0, args), "/f0:xy/f0:ay/f0:ab") + xassert4(p_12call4(f0, args), "/f0:ay/f0:ab") + xassert4(p_12call4(f1, args), "/f1:ay/f1:ab") + xassert4(p__2call4(f0, args), "/f0:ab") + xassert4(p__2call4(f1, args), "/f1:ab") + xassert4(p__2call4(f2, args), "/f2:ab") + + xassert4(r0__call4(f0, args), "/f0:xy/f0:ay/f0:ab") + xassert4(r_1_call4(f0, args), "/f0:ay/f0:ab") + xassert4(r_1_call4(f1, args), "/f1:ay/f1:ab") +} +testDfltArity4() + +function testDfltEvaluation4() { + let counter = "c" + let inc = () => (counter += "x") + let f = (a: string = inc()) => a + xassert4(f("a"), "a") + xassert4(f(), "cx") + xassert4(f(), "cxx") + xassert4(f(undefined), "cxxx") +} +testDfltEvaluation4() + +function testArrowExprCalls4() { + let x = (a1: S4, a2?: S4, a3?: S4) => a1 + (a2 ?? "u") + (a3 ?? "u") + xassert4(x("a"), "auu") + xassert4(x("a", "b"), "abu") + xassert4(x("a", "b", "c"), "abc") + + xassert4(((a?: S4) => a ?? "u")(), "u") + // xassert4(((a?: S4) => a ?? "u")("a"), "a") // #22952: broken +} +testArrowExprCalls4() + +class X4 { + constructor(v: (p?: T4) => T4) { this.fv = v } + get f() { return this.fv } + fv: (p?: T4) => T4 +} +function gcall4(x: X4, a: T4) { + (x.f)(); + (x.f)(a); + (x.fv)(); + (x.fv)(a); +} +function testGenerics4() { + let res: string = ":" + let fn = (a?: string) => { + res += (a ?? "D"); + return res; + }; + gcall4(new X4(fn), "a") // #22952: inference fails + xassert4(res, ":DaDa") +} +testGenerics4(); + +function foo4(a1: S4, a2?: S4) { return a1 + (a2 ?? "D") } +function testFuncRef4() { + let f = (a1: S4, a2?: S4) => foo4(a1, a2) // #22952: foo4 is overloaded + xassert4(f("a"), "aD") + xassert4(f("a", undefined), "aD") + xassert4(f("a", "b"), "ab") +} +testFuncRef4(); + +// --------------------------------------------------------------------------------------------------------------------- +// OptionalChains.ets +// --------------------------------------------------------------------------------------------------------------------- + +function assert_n5(v: Object | null | undefined) { arktest.assertTrue(v === null); } +function assert_u5(v: Object | null | undefined) { arktest.assertTrue(v === undefined); } +function assert_o5(v: Object | null | undefined) { arktest.assertTrue(v !== null && v !== undefined); } +function assert_npe5(f: () => void) { + try { + f(); + } catch (e: NullPointerError) { + return; + } + arktest.assertTrue(false, "npe was not thrown") +} + +class Link5 { + m(): Link5 { return this; } + f: Link5 = this; + a: Link5[] = [(this)]; + c: () => Link5 = () => this + + om(): Link5 | null { return this.m() } + of: Link5 | null = this.f; + oa: Link5[] | null = this.a; + oc: (() => Link5) | null = this.c; + + nm(): Link5 | null { return null } + nf: Link5 | null = null; + na: Link5[] | null = null; + nc: (() => Link5) | null = null; + + static noevalFlag = true; + noeval(): Link5 { if (Link5.noevalFlag) { throw new Error("never evaluated"); } return this; } +} + +function test15(l: Link5 | null, nl: Link5 | null) { + assert_o5(l?.m()); + assert_o5(l?.f); + assert_o5(l?.a[0]); + assert_o5(l?.c()); + assert_o5(l?.of!.f); + + assert_u5(nl?.m()); + assert_u5(nl?.f); + assert_u5(nl?.a[0]); + assert_u5(nl?.c()); + assert_u5(nl?.of!.f); + assert_u5(nl?.nf!.f); + + nl?.m().noeval(); + nl?.f.noeval(); + nl?.a[0].noeval(); + nl?.c().noeval(); + nl?.of!.f.noeval(); + assert_npe5(() => { nl?.of!.f! }); +} + +function test25(l: Link5 | null, nl: Link5 | null) { + assert_o5(l?.m().f.a[0].c()); + assert_o5(l?.f.m().c().a[0]); + assert_o5(l?.a[0].c().f.m()); + assert_o5(l?.c().m().a[0].f); + assert_o5(l?.c().m().of!.a[0].oc!().f); + + assert_u5(nl?.m().f.a[0].c()); + assert_u5(nl?.f.m().c().a[0]); + assert_u5(nl?.a[0].c().f.m()); + assert_u5(nl?.c().m().a[0].f); + assert_u5(nl?.c().m().of!.a[0].oc!().f); + + nl?.m().f.a[0].c().noeval(); + nl?.f.m().c().a[0].noeval(); + nl?.a[0].c().f.m().noeval(); + nl?.c().m().a[0].f.noeval(); + nl?.c().m().of!.a[0].oc!().f.noeval(); +} + +function test35(l: Link5 | null, nl: Link5 | null) { + assert_o5(l?.om()?.of?.oa?.[0].oc?.()); + assert_o5(l?.of?.om()?.oc?.().oa?.[0]); + assert_o5(l?.oa?.[0]?.oc?.().of?.om()); + assert_o5(l?.oc?.().om()?.oa?.[0].of); + assert_o5(l?.oc?.().om()?.of!.oa?.[0].oc!().of); + + assert_u5(nl?.om()?.of?.oa?.[0].oc?.()); + assert_u5(nl?.of?.om()?.oc?.().oa?.[0]); + assert_u5(nl?.oa?.[0]?.oc?.().of?.om()); + assert_u5(nl?.oc?.().om()?.oa?.[0].of); + assert_u5(nl?.oc!().om()?.of!.oa![0].oc!().of); + + nl?.om()?.of?.oa?.[0].oc?.().noeval(); + nl?.of?.om()?.oc?.().oa?.[0].noeval(); + nl?.oa?.[0]?.oc?.().of?.om()?.noeval(); + nl?.oc?.().om()?.oa?.[0].of?.noeval(); + nl?.oc?.().om()?.of!.oa?.[0].oc!().of?.noeval(); +} + +function test45(l: Link5 | null, nl: Link5 | null) { + assert_npe5(() => { nl?.of! }); + nl?.of!.f; +} + +function test55(l: Link5 | null, nl: Link5 | null) { + l?.f.a[0]?.f.c(); + nl?.f.a[0]?.f.c().noeval(); + assert_npe5(() => { nl?.f.a[0]?.f.c()! }); + assert_npe5(() => { (nl?.f?.a)?.[0].f! }); + assert_u5(l?.f.a[0].nf?.a[0].noeval()?.m()); + + let u: Link5 | undefined = l?.f.oc?.().na?.[0].noeval().f?.oa?.[0]; +} + +// --------------------------------------------------------------------------------------------------------------------- +// UnionAsAndInstanceof.ets +// --------------------------------------------------------------------------------------------------------------------- + +function assert_ccexc6(f: () => void) { + try { + f(); + } catch (e) { + arktest.assertTrue(e instanceof ClassCastError) + return; + } + arktest.assertTrue(false, "exception expected") +} + +function assert_nothrow6(f: () => void) { + try { + f(); + } catch (e) { + arktest.assertTrue(false, "unexpected exception") + } +} + +class A6 { } +class B6 { } +class C6 { } + +function foo6(x: Object | null | undefined) { return x as Object } + +function test_nullsafety6() { + // Handling of Object may be a bit different, so test it separately + // let f = ... until inference in form ((p)=>expr)(a) is broken + assert_ccexc6(() => { let f = ((x: Object | null | undefined) => x as Object); f(null); }); + assert_ccexc6(() => { let f = ((x: Object | null | undefined) => x as Object); f(undefined); }); + assert_ccexc6(() => { let f = ((x: Object | null) => x as Object); f(null); }); + assert_ccexc6(() => { let f = ((x: Object | undefined) => x as Object); f(undefined); }); + + assert_ccexc6(() => { let f = ((x: Object | null | undefined) => x as Object | undefined); f(null); }); + assert_ccexc6(() => { let f = ((x: Object | null | undefined) => x as Object | null); f(undefined); }); + assert_ccexc6(() => { let f = ((x: Object | null) => x as Object | undefined); f(null); }); + assert_ccexc6(() => { let f = ((x: Object | undefined) => x as Object | null); f(undefined); }); + + assert_ccexc6(() => { let f = ((x: A6 | null | undefined) => x as A6); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | null | undefined) => x as A6); f(undefined); }); + assert_ccexc6(() => { let f = ((x: A6 | null) => x as A6); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | undefined) => x as A6); f(undefined); }); + + assert_ccexc6(() => { let f = ((x: A6 | null | undefined) => x as A6 | undefined); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | null | undefined) => x as A6 | null); f(undefined); }); + assert_ccexc6(() => { let f = ((x: A6 | null) => x as A6 | undefined); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | undefined) => x as A6 | null); f(undefined); }); + + + assert_nothrow6(() => { let f = ((x: Object | null | undefined) => x as Object); f(new Object()); }); + assert_nothrow6(() => { let f = ((x: Object | null | undefined) => x as Object); f(new Object); }); + assert_nothrow6(() => { let f = ((x: Object | null) => x as Object); f(new Object()); }); + assert_nothrow6(() => { let f = ((x: Object | undefined) => x as Object); f(new Object()); }); + + assert_nothrow6(() => { let f = ((x: Object | null | undefined) => x as Object | undefined); f(new Object()); }); + assert_nothrow6(() => { let f = ((x: Object | null | undefined) => x as Object | null); f(new Object()); }); + assert_nothrow6(() => { let f = ((x: Object | null) => x as Object | undefined); f(new Object()); }); + assert_nothrow6(() => { let f = ((x: Object | undefined) => x as Object | null); f(new Object()); }); + + assert_nothrow6(() => { let f = ((x: A6 | null | undefined) => x as A6); f(new A6()); }); + assert_nothrow6(() => { let f = ((x: A6 | null | undefined) => x as A6); f(new A6()); }); + assert_nothrow6(() => { let f = ((x: A6 | null) => x as A6); f(new A6()); }); + assert_nothrow6(() => { let f = ((x: A6 | undefined) => x as A6); f(new A6()); }); + + assert_nothrow6(() => { let f = ((x: A6 | null | undefined) => x as A6 | undefined); f(new A6()); }); + assert_nothrow6(() => { let f = ((x: A6 | null | undefined) => x as A6 | null); f(new A6()); }); + assert_nothrow6(() => { let f = ((x: A6 | null) => x as A6 | undefined); f(new A6()); }); + assert_nothrow6(() => { let f = ((x: A6 | undefined) => x as A6 | null); f(new A6()); }); +} + +function test_unions6() { + assert_ccexc6(() => { let f = ((x: A6 | B6 | C6) => x as A6); f(new C6()); }); + assert_ccexc6(() => { let f = ((x: A6 | B6 | C6) => x as A6 | B6); f(new C6()); }); + assert_ccexc6(() => { let f = ((x: A6 | B6 | C6 | null) => x as A6 | B6); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | B6 | C6 | undefined) => x as A6 | B6); f(undefined); }); + + assert_ccexc6(() => { let f = ((x: A6 | null | undefined) => x as A6 | undefined); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | null | undefined) => x as A6 | null); f(undefined); }); + assert_ccexc6(() => { let f = ((x: A6 | null) => x as A6 | undefined); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | undefined) => x as A6 | null); f(undefined); }); + + assert_ccexc6(() => { let f = ((x: A6 | B6 | C6) => x as A6); f(new C6()); }); + assert_ccexc6(() => { let f = ((x: A6 | B6 | C6) => x as A6 | B6); f(new C6()); }); + assert_ccexc6(() => { let f = ((x: A6 | B6 | C6 | null) => x as A6 | B6); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | B6 | C6 | undefined) => x as A6 | B6); f(undefined); }); + + assert_ccexc6(() => { let f = ((x: A6 | null | undefined) => x as A6 | undefined); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | null | undefined) => x as A6 | null); f(undefined); }); + assert_ccexc6(() => { let f = ((x: A6 | null) => x as A6 | undefined); f(null); }); + assert_ccexc6(() => { let f = ((x: A6 | undefined) => x as A6 | null); f(undefined); }); +} + +// --------------------------------------------------------------------------------------------------------------------- +// UncheckedCasts.ets +// --------------------------------------------------------------------------------------------------------------------- + +function assert_ccexc7(f: () => void) { + try { + f(); + } catch (e) { + arktest.assertTrue(e instanceof ClassCastError) + return; + } + arktest.assertTrue(false, "exception expected") +} + +class A7 { } +class B7 { } +class C7 { } +class X7 { } + +function erase7(x: Object | null | undefined): T7 { return x as T7; } + +function test_substitution7() { + assert_ccexc7(() => { erase7(null); }) + assert_ccexc7(() => { erase7(undefined); }) + assert_ccexc7(() => { erase7(null); }) + assert_ccexc7(() => { erase7(undefined); }) + + assert_ccexc7(() => { erase7(null); }) + assert_ccexc7(() => { erase7(undefined); }) + assert_ccexc7(() => { erase7(null); }) + assert_ccexc7(() => { erase7(undefined); }) + + assert_ccexc7(() => { erase7(undefined); }) + assert_ccexc7(() => { erase7(new Object()); }) + assert_ccexc7(() => { erase7(new B7()); }) + + assert_ccexc7(() => { erase7(undefined); }) + assert_ccexc7(() => { erase7(new Object()); }) + assert_ccexc7(() => { erase7(new C7()); }) + + assert_ccexc7(() => { erase7>(new B7[0]); }) +} + +class Erased7 { + constructor(x: Object | null | undefined) { this.t7 = x as T7; } + t7: T7; +} + +function test_substitution_memberexpr7() { + assert_ccexc7(() => { new Erased7(null).t7; }) + assert_ccexc7(() => { new Erased7(undefined).t7; }) + assert_ccexc7(() => { new Erased7(null).t7; }) + assert_ccexc7(() => { new Erased7(undefined).t7; }) + + assert_ccexc7(() => { new Erased7(null).t7; }) + assert_ccexc7(() => { new Erased7(undefined).t7; }) + assert_ccexc7(() => { new Erased7(null).t7; }) + assert_ccexc7(() => { new Erased7(undefined).t7; }) + + assert_ccexc7(() => { new Erased7(undefined).t7; }) + assert_ccexc7(() => { new Erased7(new Object()).t7; }) + assert_ccexc7(() => { new Erased7(new B7()).t7; }) + + assert_ccexc7(() => { new Erased7(undefined).t7; }) + assert_ccexc7(() => { new Erased7(new Object()).t7; }) + assert_ccexc7(() => { new Erased7(new C7()).t7; }) + + assert_ccexc7(() => { new Erased7>(new B7[0]).t7; }) +} + +function cast_to_tparam7(x: Object | null | undefined) { x as T7; } + +function test_constraint7() { + assert_ccexc7(() => { cast_to_tparam7(undefined); }) + assert_ccexc7(() => { cast_to_tparam7(new Object()); }) + assert_ccexc7(() => { cast_to_tparam7(new C7()); }) +} + +function to_basetype7(x: Object | null | undefined) { return x as X7; } + +function test_basetype7() { + assert_ccexc7(() => { to_basetype7(null); }) + assert_ccexc7(() => { to_basetype7(undefined); }) + assert_ccexc7(() => { to_basetype7(new Object()); }) + assert_ccexc7(() => { to_basetype7(new C7()); }) +} + +// --------------------------------------------------------------------------------------------------------------------- +// partialTypeRuntime_2.ets +// --------------------------------------------------------------------------------------------------------------------- + +class Class18 { fld: Number = 2; } + +function test_18(): void { + let class1_partial: Partial = {fld: 3}; + arktest.assertEQ(class1_partial.fld, 3) + class1_partial.fld = undefined; + arktest.assertTrue(class1_partial.fld === undefined) +} + +// ----------------------------------------------- + +class Class28 { + fld: Number = 2; + foo(a0: Partial) { + a0.fld = undefined; + } +} + +function test_28(): void { + let class2_original: Class28 = new Class28(); + let class2_partial: Partial = {fld: 3}; + arktest.assertEQ(class2_partial.fld, 3) + class2_original.foo(class2_partial); + arktest.assertTrue(class2_partial.fld === undefined) +} + +// ----------------------------------------------- + +class Class38 { + mmeb: Number = 2; + foo(a0: Partial){ + a0.mmeb = undefined; + } +} + +class Class48 extends Class38 {} + +class Class58 extends Class48 { + mmeb: Number = 2; + foo(a0: Partial){ + a0.mmeb = undefined; + } +} + +function test_38(): void { + let class3_original: Class38 = new Class38(); + let class5_original: Class38 = new Class58(); + let class3_partial: Partial = {mmeb: 8}; + let class5_partial: Partial = {mmeb: 10}; + class3_original.foo(class5_partial); + class5_original.foo(class3_partial); + arktest.assertTrue(class3_partial.mmeb === undefined) + arktest.assertTrue(class5_partial.mmeb === undefined) +} + +// ----------------------------------------------- + +class Class68 { + mmeb: Number = 2; + foo(a0: Partial){ + if(this.mmeb == 3){ + return; + } + + this.bar(a0); + } + bar(a0: Partial){ + this.mmeb = 3; + this.foo(a0); + } +} + +class Class78 { fld: Number = 6;} + +class Class88 { + baz(a0: Partial){ + a0.fld = undefined; + } +} + +function test_48(): void { + let class7_partial: Partial = {fld: 8}; + let class6_original: Class68 = new Class68(); + class6_original.foo(class7_partial); +} + +// ----------------------------------------------- + +class Class98 { fld: Number = 8; } + +class Class108 extends Class98 { memb: Number = 9; } + +function test_58(): void { + let class10_partial: Partial = {memb: 7, fld: 5}; + + arktest.assertEQ(class10_partial.memb, 7) + arktest.assertEQ(class10_partial.fld, 5) + + class10_partial.memb = undefined; + class10_partial.fld = undefined; + + arktest.assertTrue(class10_partial.memb === undefined) + arktest.assertTrue(class10_partial.fld === undefined) +} + +//--------------------------------------- + + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_01.ets +// --------------------------------------------------------------------------------------------------------------------- + +class C33 { + bar(): string { + return "Class C33"; + } +} + +function foo33(c: Object|null|undefined): string { + if (c instanceof string) { + arktest.assertEQ(c.length, 11) + c = "Case 1"; + } else if (c instanceof C33) { + arktest.assertEQ(c.bar(), "Class C33") + c = "Case 2"; + } else if (c instanceof Int) { + arktest.assertEQ(c * 7, 49) + c = "Case 3"; + } else if (c instanceof null) { + arktest.assertEQ(c, null) + c = "Case 4"; + } else { + c = "Case 5"; + } + + arktest.assertEQ(c.length, 6) + return c; +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_02.ets +// --------------------------------------------------------------------------------------------------------------------- + +class A31 { + bar(): string { + return "Class A31"; + } +} + +class B31 extends A31 {} + +class C31 extends B31 { + bar(): string { + return "Class C31"; + } +} + +function foo31(c: Int|String|A31|null|undefined): void { + if (c instanceof String) { + arktest.assertEQ(c.length, 11) + } else if (c instanceof C31) { + arktest.assertEQ(c.bar(), "Class C31") + } else if (c instanceof Int) { + arktest.assertEQ(c * c, 49) + } else if (c === undefined) { + arktest.assertEQ(c, undefined) + } else { + arktest.assertEQ(c, null) + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_03.ets +// --------------------------------------------------------------------------------------------------------------------- + +class C32 { + constructor() {} + + constructor(a: int) { + this.x = a; + } + + bar(): string { + return "Class C32"; + } + + baz(): int { + return this.x; + } + + private x: int = 7; +} + +function foo32(c: Object|null|undefined): string { + if (c instanceof string && (c.length == 11 || c == "Test")) { + c = "Case 1"; + } else if (c instanceof C32 && c.baz() == 7) { + arktest.assertEQ(c.bar(), "Class C32") + c = "Case 2"; + } else if (c instanceof Int && c >= 0) { + arktest.assertTrue(c >= 0) + c = "Case 3"; + } else if (c instanceof null) { + arktest.assertEQ(c, null) + c = "Case 4"; + } else { + c = "Case 5"; + } + + arktest.assertEQ(c.length, 6) + return c; +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_04.ets +// --------------------------------------------------------------------------------------------------------------------- + +function fooAnd34(x: String|null, y: String|null): string { + if (x != null && y != null) { + return x + " " + y; + } else if (x == null && y == null) { + return "null"; + } else if (x != null && y == null) { + return x; + } else if (x == null && y != null) { + return y; + } else { + throw new Error("Unreachable"); + } +} + +function fooOr134(x: String|null, y: String|null): string { + if (x != null || y != null) { + return "case 1"; + } else if (x == null && y == null) { + return "null"; + } else { + throw new Error("Unreachable"); + } +} + +function fooOr234(x: String|null, y: String|null): string { + if (x == null || y == null) { + return "case 1"; + } else if (x != null && y != null) { + return x + " " + y; + } else { + throw new Error("Unreachable"); + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_05.ets +// --------------------------------------------------------------------------------------------------------------------- + +class C35 { + readonly a: boolean + constructor(a_: boolean = false) { + this.a = a_; + } +} + +function foo135(x: C35|null|undefined): string { + if (x == null || !x.a) { + return x != null ? "false1" : "null"; + } else { + return x.a ? "true2" : "false2"; + } +} + +function foo235(x: C35|null|undefined): string { + if (x != null && x.a) { + return "true"; + } else { + return x != null ? "false" : "null"; + } +} + +function bar35(x: C35|null|undefined, y: boolean, z: boolean): string { + if ((x instanceof C35 && y) || (x instanceof C35 && z)) { + return (x.a ? "true1" : "false1") + y + z; + } else { + return (x != null ? (x.a ? "true2" : "false2") : "null") + y + z; + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_06.ets +// --------------------------------------------------------------------------------------------------------------------- + +function foo36(x: int): string +{ + let rc: string|undefined = "default"; + + label1: switch(x) { + case 0: + rc = "case 0"; + case 1: { + let rc1: string|undefined = ():string => {return "case 1";}(); + label2: switch(rc) { + case "default": + rc = undefined; + break label2; + default: + break label1; + } + rc = rc1; + break; + } + case 2: + rc = undefined; + let rc2: string|null = ():string => {return "case 2";}(); + return rc2; + case 3: + rc = "case 3"; + break; + case 4: + rc = undefined; + default: + return rc != null ? rc :"case 4" + case 5: + rc = "case 5"; + } + + return rc; +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_08.ets +// --------------------------------------------------------------------------------------------------------------------- + +function foo37(flag37: boolean): int { + + let x: int|undefined = 0; + let y: int|undefined = 1; + let z: int|undefined = 2; + let w: int|undefined = 3; + + try { + y = 1; + if (flag37) { + throw new Error(); + } + } catch(ex: NullPointerError) { + z = 2; + } catch(ex) { + w = undefined; + } + + return x + y! + z + w!; +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_09.ets +// --------------------------------------------------------------------------------------------------------------------- + +class A38 { + prev_: A38|undefined = undefined; + next_: A38|undefined = undefined; + + m() { + const prev = this.prev_; + const next = this.next_; + + if (prev) { + this.prev_ = undefined; + prev.next_ = next; + } + + if (next) { + this.next_ = undefined; + next.prev_ = prev; + } + + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_10.ets +// --------------------------------------------------------------------------------------------------------------------- + +interface It39 { +} + +class Cl39 implements It39 { + + constructor(p: T39) { + this.x = p; + } + + static resolve(value: U|It39): Cl39 { + if (value instanceof Cl39) { + return value as Cl39; + } + return new Cl39(value as U); + } + + x: T39; + + print(): string { + if (this.x == undefined) { + return "value is " + this.x; + } + else if (this.x instanceof string) { + return "string: '" + this.x + "'"; + } else { + return "number = " + this.x; + } + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_11.ets +// --------------------------------------------------------------------------------------------------------------------- + +class C41 {} + +function foo41(arg?: boolean): C41 | undefined { + if (arg == undefined) { + return undefined; + } + return arg == false ? undefined : new C41(); +} + +function bar41(arg?: boolean): C41 | undefined { + if (arg == true) return new C41(); + return arg == false ? undefined : new C41(); +} + +function baz41(arg?: boolean): int { + if (arg == undefined) return 0; + arktest.assertEQ(typeof arg, "boolean") + return 1; +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_13.ets +// --------------------------------------------------------------------------------------------------------------------- + +class C43 {} + +function foo43(arg?: number): C43 | undefined { + if (arg == 5) return new C43(); + return arg == 3 ? undefined : new C43(); +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_14.ets +// --------------------------------------------------------------------------------------------------------------------- + +class A44 { + A44(a44?: T44 | number[]) { + if (a44 instanceof Error) { + return this.D(a44); + } else if (a44 instanceof undefined) { + return this.B(a44); + } else if (a44 instanceof number[]) { + return this.E(a44); + } else { + return this.C(a44); + } + } + + B(b: undefined) { + return "undefined"; + } + + C(c: T44) { + return "Generic"; + } + + D(d: Error) { + return "Error"; + } + + E(e: number[]) { + return "number[]" + } +} + +let a44 = new A44(); +arktest.assertEQ(a44.A44(Error()), "Error"); +arktest.assertEQ(a44.A44(undefined), "undefined"); +arktest.assertEQ(a44.A44(1), "Generic"); +arktest.assertEQ(a44.A44([1, 2, 3]), "number[]") + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_15.ets +// --------------------------------------------------------------------------------------------------------------------- + +// Issue #22779 - smart cast in return statement +function isEmpty45(text?: string): boolean { + return text === undefined || text === null || text.length === 0 +} + +// Some other examples +function foo45(text?: string): boolean { + let a: boolean = (text === undefined || text === null || text.length == 0) ? true : false + let b: boolean = text === undefined || text === null || text.length == 0 + let c: boolean = !(text !== undefined) || text === null || text.length == 0 + let d: boolean = (text !== undefined && text !== null) ? text.length == 0 : true + let e: boolean = (text != undefined && text != null) ? text.length == 0 : true + return a && b && c && d && e +} + +// --------------------------------------------------------------------------------------------------------------------- +// SmartCast_16.ets +// --------------------------------------------------------------------------------------------------------------------- + +class C45 { + readonly fld: T45 + constructor(p: T45) { + this.fld = p + } +} + +type NestedC45 = String | C45 | Error + + +function main(): void { + // ----------------------------------------------------------------------------------------------------------------- + // AccessBinaryTrees.ets + // ----------------------------------------------------------------------------------------------------------------- + + let a = new AccessBinaryTrees; + a.run(); + + // ----------------------------------------------------------------------------------------------------------------- + // ArrayLiteral.ets + // ----------------------------------------------------------------------------------------------------------------- + + let a1: byte = 2; + let b1: short = 20000; + let c1: int = 2000000; + let d1: long = 200000000000; + let e1: float = 2.2f; + let f1: double = 2.2222222222; + let g1: double[] = [a1, b1, c1, d1, e1, f1]; + arktest.assertEQ(g1[0], 2) + arktest.assertEQ(g1[1], 20000) + arktest.assertEQ(g1[2], 2000000) + arktest.assertEQ(g1[3], 200000000000) + arktest.assertEQ(g1[4], (Double.toFloat(2.2))) + arktest.assertEQ(g1[5], 2.2222222222) + + const h1: byte = 2; + const i1: short = 2; + const j1: int = 2; + const k1: long = 2; + const l1: float = 2.0f; + const m1: double = 2.0; + const n1: byte[] = [h1, Short.toByte(i1), j1, Long.toByte(k1), Float.toByte(l1), Double.toByte(m1)]; + arktest.assertEQ(n1[0], 2) + arktest.assertEQ(n1[1], 2) + arktest.assertEQ(n1[2], 2) + arktest.assertEQ(n1[3], 2) + arktest.assertEQ(n1[4], 2) + arktest.assertEQ(n1[5], 2) + + let o1: Object[] = [1, 1.1, "testStr", new Int(2), d1, k1]; + arktest.assertEQ(o1[0] as Int, 1) + arktest.assertEQ(o1[1] as Double, 1.1) + arktest.assertTrue((o1[2] as String).equals("testStr")) + arktest.assertEQ(o1[3] as Int, 2) + arktest.assertEQ(o1[4] as Long, 200000000000) + arktest.assertEQ(o1[5] as Long, 2) + + let p1: long[] = [new Int(3), new Short(2 as short), new Long(4)]; + arktest.assertEQ(p1[0], 3) + arktest.assertEQ(p1[1], 2) + arktest.assertEQ(p1[2], 4) + + // ----------------------------------------------------------------------------------------------------------------- + // RestTuple6.ets + // ----------------------------------------------------------------------------------------------------------------- + + let a12: [A2, B2] = [new A2, new B2] + arktest.assertTrue((new C2()).foo(...a12) == false) + arktest.assertTrue((new C2()).moo(12, ...a12) == false) + arktest.assertTrue((new C2()).foo(...[new A2, new B2]) == false) + arktest.assertTrue((new C2()).moo(12, ...[new A2, new B2]) == false) + arktest.assertTrue((new C2()).foo(...[new A2, new B2] as [A2, B2]) == false) + arktest.assertTrue((new C2()).moo(12, ...[new A2, new B2] as [A2, B2]) == false) + arktest.assertTrue((new C2()).foo(new A2, new B2) == false) + arktest.assertTrue((new C2()).moo(12, new A2, new B2) == false) + + // ----------------------------------------------------------------------------------------------------------------- + // GenericBridges_02.ets + // ----------------------------------------------------------------------------------------------------------------- + + ttt3(new D3()) + let c3: C3 = new E3(); + foo13(c3); + foo23(new E3()); + + // ----------------------------------------------------------------------------------------------------------------- + // OptionalChains.ets + // ----------------------------------------------------------------------------------------------------------------- + + test15(new Link5(), null) + test25(new Link5(), null) + test35(new Link5(), null) + test45(new Link5(), null) + test55(new Link5(), null) + + // ----------------------------------------------------------------------------------------------------------------- + // UnionAsAndInstanceof.ets + // ----------------------------------------------------------------------------------------------------------------- + + test_nullsafety6(); + test_unions6(); + + // ----------------------------------------------------------------------------------------------------------------- + // UncheckedCasts.ets + // ----------------------------------------------------------------------------------------------------------------- + + test_substitution7(); + test_substitution_memberexpr7(); + test_constraint7(); + test_basetype7(); + + // ----------------------------------------------------------------------------------------------------------------- + // partialTypeRuntime_2.ets + // ----------------------------------------------------------------------------------------------------------------- + + test_18(); + test_28(); + test_38(); + test_48(); + test_58(); + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_01.ets + // ----------------------------------------------------------------------------------------------------------------- + + arktest.assertEQ(foo33("Test string"), "Case 1") + arktest.assertEQ(foo33(new Int(7)), "Case 3") + arktest.assertEQ(foo33(new C33()), "Case 2") + arktest.assertEQ(foo33(null), "Case 4") + arktest.assertEQ(foo33(undefined), "Case 5") + arktest.assertEQ(foo33(new Number(3.0)), "Case 5") + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_02.ets + // ----------------------------------------------------------------------------------------------------------------- + + foo31("Test string"); + foo31(new Int(7)); + foo31(new C31()); + foo31(null); + foo31(undefined); + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_03.ets + // ----------------------------------------------------------------------------------------------------------------- + + arktest.assertEQ(foo32("Test string"), "Case 1") + arktest.assertEQ(foo32("Test"), "Case 1") + arktest.assertEQ(foo32("Test string 2"), "Case 5") + arktest.assertEQ(foo32("test"), "Case 5") + + arktest.assertEQ(foo32(new Int(5)), "Case 3") + arktest.assertEQ(foo32(new Int(0)), "Case 3") + arktest.assertEQ(foo32(new Int(-5)), "Case 5") + + arktest.assertEQ(foo32(new C32(7)), "Case 2") + arktest.assertEQ(foo32(new C32()), "Case 2") + arktest.assertEQ(foo32(new C32(17)), "Case 5") + + arktest.assertEQ(foo32(null), "Case 4") + + arktest.assertEQ(foo32(undefined), "Case 5") + arktest.assertEQ(foo32(new Number(3.0)), "Case 5") + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_04.ets + // ----------------------------------------------------------------------------------------------------------------- + + arktest.assertEQ(fooAnd34("Test", "string"), "Test string") + arktest.assertEQ(fooAnd34("Test", null), "Test") + arktest.assertEQ(fooAnd34(null, "string"), "string") + arktest.assertEQ(fooAnd34(null, null), "null") + + arktest.assertEQ(fooOr134("Test", "string"), "case 1") + arktest.assertEQ(fooOr134("Test", null), "case 1") + arktest.assertEQ(fooOr134(null, "string"), "case 1") + arktest.assertEQ(fooOr134(null, null), "null") + + arktest.assertEQ(fooOr234("Test", "string"), "Test string") + arktest.assertEQ(fooOr234("Test", null), "case 1") + arktest.assertEQ(fooOr234(null, "string"), "case 1") + arktest.assertEQ(fooOr234(null, null), "case 1") + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_05.ets + // ----------------------------------------------------------------------------------------------------------------- + + arktest.assertEQ(foo135(null), "null") + arktest.assertEQ(foo235(null), "null") + arktest.assertEQ(bar35(null, true, true), "nulltruetrue") + arktest.assertEQ(bar35(null, true, false), "nulltruefalse") + arktest.assertEQ(bar35(null, false, true), "nullfalsetrue") + arktest.assertEQ(bar35(null, false, false), "nullfalsefalse") + + arktest.assertEQ(foo135(undefined), "null") + arktest.assertEQ(foo235(undefined), "null") + arktest.assertEQ(bar35(undefined, true, true), "nulltruetrue") + arktest.assertEQ(bar35(undefined, true, false), "nulltruefalse") + arktest.assertEQ(bar35(undefined, false, true), "nullfalsetrue") + arktest.assertEQ(bar35(undefined, false, false), "nullfalsefalse") + + let c = new C35(); + arktest.assertEQ(foo135(c), "false1") + arktest.assertEQ(foo235(c), "false") + arktest.assertEQ(bar35(c, true, true), "false1truetrue") + arktest.assertEQ(bar35(c, true, false), "false1truefalse") + arktest.assertEQ(bar35(c, false, true), "false1falsetrue") + arktest.assertEQ(bar35(c, false, false), "false2falsefalse") + + c = new C35(true); + arktest.assertEQ(foo135(c), "true2") + arktest.assertEQ(foo235(c), "true") + arktest.assertEQ(bar35(c, true, true), "true1truetrue") + arktest.assertEQ(bar35(c, true, false), "true1truefalse") + arktest.assertEQ(bar35(c, false, true), "true1falsetrue") + arktest.assertEQ(bar35(c, false, false), "true2falsefalse") + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_06.ets + // ----------------------------------------------------------------------------------------------------------------- + + arktest.assertEQ(foo36(0), "case 0") + arktest.assertEQ(foo36(1), "case 1") + arktest.assertEQ(foo36(2), "case 2") + arktest.assertEQ(foo36(3), "case 3") + arktest.assertEQ(foo36(4), "case 4") + arktest.assertEQ(foo36(5), "case 5") + arktest.assertEQ(foo36(7), "default") + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_07.ets + // ----------------------------------------------------------------------------------------------------------------- + + let x363: int | boolean | string = 7; + arktest.assertEQ(x363, 7) + x363--; + arktest.assertEQ(x363, 6) + x363 = x363 == 7; + arktest.assertTrue(!x363) + x363 = !x363; + arktest.assertEQ(x363, true) + x363 = "x363 = " + x363.toString(); + arktest.assertEQ(x363, "x363 = true") + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_08.ets + // ----------------------------------------------------------------------------------------------------------------- + + let flag37: boolean = false; + arktest.assertEQ(foo37(flag37), 6) + try { + foo37(!flag37); + } catch(ex) { + flag37 = true; + } + arktest.assertTrue(flag37) + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_10.ets + // ----------------------------------------------------------------------------------------------------------------- + + arktest.assertEQ(Cl39.resolve(undefined).print(), "value is undefined") + arktest.assertEQ(Cl39.resolve("test").print(), "string: 'test'") + arktest.assertEQ(Cl39.resolve(5.5).print(), "number = 5.5") + arktest.assertEQ(Cl39.resolve(new Int(8)).print(), "number = 8") + + arktest.assertEQ(Cl39.resolve(new Cl39(null)).print(), "value is null") + arktest.assertEQ(Cl39.resolve(new Cl39("TEST")).print(), "string: 'TEST'") + arktest.assertEQ(Cl39.resolve(new Cl39(7.7)).print(), "number = 7.7") + arktest.assertEQ(Cl39.resolve(new Cl39(new Int(-8))).print(), "number = -8") + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_11.ets + // ----------------------------------------------------------------------------------------------------------------- + + arktest.assertTrue(foo41(true) instanceof C41) + arktest.assertEQ(foo41(false), undefined) + arktest.assertEQ(foo41(), undefined) + + arktest.assertTrue(bar41(true) instanceof C41) + arktest.assertEQ(bar41(false), undefined) + arktest.assertTrue(bar41() instanceof C41) + + arktest.assertEQ(baz41(true), 1) + arktest.assertEQ(baz41(false), 1) + arktest.assertEQ(baz41(), 0) + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_12.ets + // ----------------------------------------------------------------------------------------------------------------- + + let resolve42: ((value: string) => void) | null = null; + + let p42 = new Promise((_resolve: (value: string)=> void): void => { + resolve42 = _resolve; + }); + + resolve42!("abc"); // no smart cast! + + let x42: Number|String|undefined = "test1"; + let y42: Number|String|undefined = "test2" + let z42: Number|String|undefined = 7 + + let lam42: () => void = () => { + let y42: Number|String|undefined = 2; // hides outer declaration! + x42 = z42; + let tmp: number = y42; // smart cast is used + arktest.assertEQ(tmp, 2); + }; + + if (x42 instanceof string) { + let tmp: string = x42 as string; // no smart cast! + arktest.assertEQ(tmp, "test1"); + } + + lam42(); + + arktest.assertEQ(x42, 7); + + if (y42 instanceof string) { + let tmp: string = y42; // smart cast is used + arktest.assertEQ(tmp, "test2"); + } + + let w42: number = z42; // smart cast is used + arktest.assertEQ(w42, 7) + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_13.ets + // ----------------------------------------------------------------------------------------------------------------- + + arktest.assertTrue(foo43(5) instanceof C43) + arktest.assertEQ(foo43(3), undefined) + arktest.assertTrue(foo43(undefined) instanceof C43) + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_15.ets + // ----------------------------------------------------------------------------------------------------------------- + + arktest.assertEQ(isEmpty45(), true) + arktest.assertEQ(isEmpty45(""), true) + arktest.assertEQ(isEmpty45("a"), false) + arktest.assertEQ(foo45(), true) + + // ----------------------------------------------------------------------------------------------------------------- + // SmartCast_16.ets + // ----------------------------------------------------------------------------------------------------------------- + + let x45: NestedC45 = new C45>(new C45(new Error())) + let ok45 = x45 instanceof C45 && x45.fld instanceof C45 && x45.fld.fld instanceof Error + let aaa = ok45 ? 0 : 1 + +} diff --git a/ets2panda/test/benchmarks/etsstdlib-max.txt b/ets2panda/test/benchmarks/etsstdlib-max.txt new file mode 100644 index 0000000000..ab8a25fbeb --- /dev/null +++ b/ets2panda/test/benchmarks/etsstdlib-max.txt @@ -0,0 +1,66 @@ +================ es2panda perf metrics (Averaged over 500 runs) ================ + +:@phases : time=4770.18ms mem=324.00MB +:@GenerateProgram : time=2571.34ms mem=0.00MB +:@GenerateProgram/OptimizeBytecode : time=1896.82ms mem=0.00MB +:@phases/CheckerPhase : time=1781.74ms mem=81.00MB +:@EmitProgram : time=485.84ms mem=130.58MB +:@phases/Unbox : time=437.00ms mem=38.00MB +:@phases/ConstantExpressionLowering : time=363.29ms mem=0.28MB +:@phases/LambdaObjectConversion : time=328.18ms mem=22.00MB +:@phases/TopLevelStatements : time=277.34ms mem=83.00MB +:@phases/GradualTypeNarrowing : time=198.37ms mem=19.00MB +:@phases/ResolveIdentifiers : time=123.95ms mem=5.13MB +:@phases/OpAssignmentLowering : time=116.33ms mem=18.00MB +:@phases/InterfaceObjectLiteralLowering : time=76.22ms mem=7.00MB +:@phases/ScopesInitPhase : time=60.61ms mem=13.00MB +:@phases/ObjectIndexLowering : time=52.64ms mem=1.90MB +:@phases/PartialExportClassGen : time=50.08ms mem=8.00MB +:@phases/CreateGenericBridges : time=43.00ms mem=3.00MB +:@phases/RestArgsLowering : time=42.90ms mem=4.00MB +:@phases/BoxingForLocals : time=41.18ms mem=1.88MB +:@phases/PrimitiveConversion : time=39.01ms mem=4.00MB +:@phases/ArrayLiteralLowering : time=38.51ms mem=4.00MB +:@phases/LateInitializationConvert : time=38.24ms mem=0.00MB +:@phases/ObjectIteratorLowering : time=30.96ms mem=1.00MB +:@phases/UnionLowering : time=25.90ms mem=0.04MB +:@phases/ObjectLiteralLowering : time=25.72ms mem=0.00MB +:@phases/OptionalArgumentsLowering : time=25.23ms mem=0.22MB +:@phases/StringConstructorLowering : time=25.14ms mem=0.00MB +:@phases/TypeFromLowering : time=24.09ms mem=0.00MB +:@phases/ExpandBracketsPhase : time=23.46ms mem=0.00MB +:@phases/SetterLowering : time=23.02ms mem=0.27MB +:@phases/StringComparisonLowering : time=21.98ms mem=0.00MB +:@phases/RecordLowering : time=21.10ms mem=0.00MB +:@phases/ExtentionAccessorPhase : time=20.90ms mem=0.00MB +:@phases/InterfacePropertyDeclarationsPhase : time=20.54ms mem=1.00MB +:@phases/DynamicImport : time=20.29ms mem=0.00MB +:@phases/BigIntLowering : time=19.61ms mem=0.00MB +:@phases/EnumPostCheckLoweringPhase : time=19.03ms mem=0.21MB +:@phases/ResizableArrayConvert : time=18.56ms mem=0.48MB +:@phases/EnumLoweringPhase : time=18.53ms mem=0.83MB +:@phases/RestTupleConstructionPhase : time=18.49ms mem=0.23MB +:@phases/DefaultParametersLowering : time=18.43ms mem=0.26MB +:@phases/OptionalLowering : time=18.42ms mem=0.49MB +:@phases/AsyncMethodLowering : time=18.41ms mem=0.00MB +:@phases/OverloadMappingLowering : time=18.02ms mem=0.00MB +:@phases/SpreadConstructionPhase : time=17.69ms mem=0.00MB +:@phases/DeclareOverloadLowering : time=17.58ms mem=0.00MB +:@phases/PromiseVoidInferencePhase : time=17.22ms mem=0.00MB +:@phases/AnnotationCopyPostLowering : time=16.95ms mem=0.00MB +:@phases/AnnotationCopyLowering : time=16.86ms mem=0.00MB +:@phases/InsertOptionalParametersAnnotation : time=16.86ms mem=0.48MB +:@phases/AmbientLowering : time=16.77ms mem=0.00MB +:@phases/CapturedVariables : time=16.71ms mem=0.00MB +:@phases/ExpressionLambdaConstruction : time=16.60ms mem=0.03MB +:@phases/DefaultParametersInConstructorLowering : time=16.21ms mem=0.51MB +:@phases/SetJumpTargetPhase : time=16.00ms mem=0.00MB +:@phases/DeclGenPhase : time=0.02ms mem=0.00MB +:@phases/plugins-after-parse : time=0.01ms mem=0.00MB +:@phases/plugins-after-lowering : time=0.00ms mem=0.00MB +:@phases/plugins-after-bind : time=0.00ms mem=0.00MB +:@phases/CFGBuilder : time=0.00ms mem=0.00MB +:@phases/StringConstantsLowering : time=0.00ms mem=0.00MB +:@phases/plugins-after-check : time=0.00ms mem=0.00MB +:@phases/ExportAnonymousConstPhase : time=0.00ms mem=0.00MB +:@phases/PackageImplicitImport : time=0.00ms mem=0.00MB diff --git a/ets2panda/test/benchmarks/runner/arg_parser.py b/ets2panda/test/benchmarks/runner/arg_parser.py new file mode 100644 index 0000000000..40cf4e5e8f --- /dev/null +++ b/ets2panda/test/benchmarks/runner/arg_parser.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# coding: utf-8 +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import argparse +import os + + +def parse_arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Cpp headers parser to .yaml") + + parser.add_argument("--mode", "-m", type=str, required=True, help="Mode: 'static' or 'dynamic'") + parser.add_argument("--es2panda", "-e", type=str, required=True, help="Path to current es2panda") + parser.add_argument("--es2panda-pre-merge", "-c", type=str, required=False, help="Path to pre_merge es2panda") + parser.add_argument("--test-dir", "-t", type=str, required=True, help="Path to test directory with test files") + parser.add_argument("--work-dir", "-a", type=str, required=True, help="Path to the working temp folder") + parser.add_argument("--werror", "-w", action="store_true", help="Warnings as errors") + parser.add_argument( + "--dynamic-regression", + "-d", + type=float, + required=False, + default=0.05, + help="Acceptable regression compared to the pre_merge", + ) + parser.add_argument( + "--static-regression", + "-s", + type=float, + required=False, + default=0.1, + help="Acceptable regression compared to static measurement", + ) + parser.add_argument("--runs", "-n", type=int, required=False, default=25, help="Number of times to run the command") + + return parser.parse_args() + + +def check_arguments(args: argparse.Namespace) -> argparse.Namespace: + if args.mode not in ["static", "dynamic"]: + raise RuntimeError(f"Invalid mode: {args.mode}\nSee --help for more.") + if not os.path.isfile(args.es2panda): + raise RuntimeError(f"Bad path to current es2panda: {args.es2panda}\nSee --help for more.") + if args.mode == "dynamic" and not os.path.isfile(args.es2panda_pre_merge): + raise RuntimeError(f"Bad path to pre_merge es2panda: {args.es2panda_pre_merge}\nSee --help for more.") + if not os.path.isdir(args.test_dir): + raise RuntimeError(f"Bad path to test_dir: {args.test_dir}\nSee --help for more.") + if args.dynamic_regression > 1 or args.dynamic_regression < -1: + raise RuntimeError( + f"Static regression must be in value range [-1, 1], current: {args.dynamic_regression}\n" + "See --help for more." + ) + if args.static_regression > 1 or args.static_regression < -1: + raise RuntimeError( + f"Static regression must be in value range [-1, 1], current: {args.static_regression}\n" + "See --help for more." + ) + + return args diff --git a/ets2panda/test/benchmarks/runner/benchmark_comparator.py b/ets2panda/test/benchmarks/runner/benchmark_comparator.py new file mode 100644 index 0000000000..4e521f82f5 --- /dev/null +++ b/ets2panda/test/benchmarks/runner/benchmark_comparator.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +# coding: utf-8 +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import os +from pathlib import Path +from typing import Dict, Optional, Tuple, List, Callable + +from metrics_utils import parse_perf_file, format_diff, format_time_ms, format_mem_mb + + +def _get_phase_comparison(phase: str, base: Optional[Dict], new: Optional[Dict]) -> Tuple[str, str, str]: + if base and new: + label = phase + time_diff = new["time_ns"] - base["time_ns"] + mem_diff = new["mem_bytes"] - base["mem_bytes"] + time_str = format_diff(time_diff, base["time_ns"], format_time_ms) + mem_str = format_diff(mem_diff, base["mem_bytes"], format_mem_mb) + elif new: + label = f"{phase} [NEW]" + time_str = f"+{format_time_ms(new['time_ns'])}" + mem_str = f"+{format_mem_mb(new['mem_bytes'])}" + elif base: + label = f"{phase} [REMOVED]" + time_str = f"-{format_time_ms(base['time_ns'])}" + mem_str = f"-{format_mem_mb(base['mem_bytes'])}" + else: + return "", "", "" + return label, time_str, mem_str + + +def _write_report(report_path: Path, base_name: str, new_name: str, results: List[Dict]) -> None: + if not results: + print("No common or unique phases to compare.") + return + + max_phase_len = max(len(r["phase"]) for r in results) + header = f"Performance Comparison: '{base_name}' vs '{new_name}'\n" + "=" * 80 + + lines = [header] + for r in results: + phase_str = f":@{r['phase']}" + lines.append(f"{phase_str:<{max_phase_len + 3}}: time={r['time_str']:<25} mem={r['mem_str']:<25}") + + report_path.write_text("\n".join(lines), encoding="utf-8") + print(f"\n✅ Comparison finished! Results saved to: {report_path}") + + +def _print_and_log(level: str, msg: str, log_dir: Path) -> None: + if level == "Error": + print(f"\n❌ {msg}") + path = log_dir / "error_log.txt" + else: + print(f"\n⚠️ {msg}") + path = log_dir / "warning_log.txt" + with os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT | os.O_APPEND, mode=511), "a", encoding="utf-8") as f: + f.write(msg + "\n") + + +def _check_regression( + metric_name: str, + base_data: Dict, + new_data: Dict, + regression: float, + perf_name: str, + log_dir: Path, + is_static: bool = False, +) -> None: + format_func: Callable[[float], str] + success = True + if metric_name == "Time": + key = "time_ns" + format_func = format_time_ms + elif metric_name == "Memory": + key = "mem_bytes" + format_func = format_mem_mb + else: + raise RuntimeError(f"Unsupported metric: {metric_name}") + + base_sum = sum(base_data.get(p, {}).get(key, 0) for p in ["phases", "EmitProgram"]) + new_sum = sum(new_data.get(p, {}).get(key, 0) for p in ["phases", "EmitProgram"]) + + upper_threshold = base_sum * (1 + regression) + if new_sum > upper_threshold: + msg = ( + f"[PERF REGRESSION] Failed for {perf_name}: {metric_name} exceeded upper threshold.\n" + f"\tLimit: {regression:.1%}, Actual: +{((new_sum / base_sum) - 1) * 100:.2f}%\n" + f"\tBase: {format_func(base_sum)}, New: {format_func(new_sum)}\n" + f"\tThreshold: < {format_func(upper_threshold)}\n" + ) + _print_and_log("Error", msg, log_dir) + success = False + + lower_threshold = base_sum * (1 - regression * 3) + if is_static and new_sum < lower_threshold: + msg = ( + f"[UPDATE REQUIRED] Very good perf for {perf_name}: {metric_name} exceeded lower threshold.\n" + f"\tLimit: -{regression * 3:.1%}, Actual: {((new_sum / base_sum) - 1) * 100:.2f}%\n" + f"\tBase: {format_func(base_sum)}, New: {format_func(new_sum)}\n" + f"\tThreshold: > {format_func(lower_threshold)}\n\n" + "Please update *-max.txt.\n" + ) + _print_and_log("Warning", msg, log_dir) + success = False + + if success: + print(f"\n✅ {metric_name} regression check for {perf_name} finished!") + + +def compare_perf_files( + new_perf_path: Path, base_perf_path: Path, report_path: Path, regression: float, log_dir: Path +) -> None: + base_data = parse_perf_file(base_perf_path) + new_data = parse_perf_file(new_perf_path) + + if not new_data: + raise RuntimeError("New perf data is empty") + if not base_data: + raise RuntimeError("Base perf data is empty") + + is_static = base_perf_path.name.find("-max.txt") != -1 + _check_regression("Time", base_data, new_data, regression, new_perf_path.name, log_dir, is_static) + _check_regression("Memory", base_data, new_data, regression, new_perf_path.name, log_dir, is_static) + results = [] + all_phases = sorted(list(set(base_data.keys()) | set(new_data.keys()))) + + for phase in all_phases: + label, time_str, mem_str = _get_phase_comparison(phase, base_data.get(phase), new_data.get(phase)) + if label: + results.append({"phase": label, "time_str": time_str, "mem_str": mem_str}) + + _write_report(report_path, base_perf_path.name, new_perf_path.name, results) diff --git a/ets2panda/test/benchmarks/runner/benchmark_runner.py b/ets2panda/test/benchmarks/runner/benchmark_runner.py new file mode 100644 index 0000000000..5d632a0992 --- /dev/null +++ b/ets2panda/test/benchmarks/runner/benchmark_runner.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# coding: utf-8 +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import subprocess +import re +from collections import defaultdict +from pathlib import Path +from typing import List, Dict, Union, DefaultDict + +from metrics_utils import parse_metric_value, format_time_ms, format_mem_mb + + +def run_and_parse(command: List) -> Dict: + print(f"Executing: {' '.join(command)}") + try: + result = subprocess.run(command, capture_output=True, text=True, check=True, encoding="utf-8") + except (FileNotFoundError, subprocess.CalledProcessError) as e: + print(f"Error executing command: {e}") + if isinstance(e, subprocess.CalledProcessError): + print(f"Stderr:\n{e.stderr}") + return {} + + line_regex = re.compile(r":@(?P[\w\/-]+)\s*:\s*time=(?P