From cf7f1368d764b5ed3b727549e57ca5e6e9be3c61 Mon Sep 17 00:00:00 2001 From: Maxim Bolshov Date: Mon, 20 Nov 2023 20:48:46 +0300 Subject: [PATCH] Support array creation with numeric as index Allow pass double/float values as index to array creation expression. Compile-time error will be raised if fractional part is not zero for literal values, runtime error will be raised for such values not known at compile-time. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8NJ7Z Signed-off-by: Maxim Bolshov --- ets2panda/BUILD.gn | 1 + ets2panda/CMakeLists.txt | 1 + ets2panda/checker/ETSAnalyzer.cpp | 2 +- ets2panda/checker/ETSchecker.h | 2 +- ets2panda/checker/ets/object.cpp | 17 +- .../compiler/lowering/ets/expandBrackets.cpp | 75 ++++ .../compiler/lowering/ets/expandBrackets.h | 34 ++ ets2panda/compiler/lowering/phase.cpp | 10 +- .../ir/ets/etsNewArrayInstanceExpression.h | 5 + .../test/parser/ets/array_new-expected.txt | 373 +++++++++++++++++ ets2panda/test/parser/ets/array_new.ets | 18 + .../parser/ets/array_new_failed-expected.txt | 374 ++++++++++++++++++ .../test/parser/ets/array_new_failed.ets | 18 + .../test/runtime/ets/array-new-catched.ets | 27 ++ ets2panda/test/runtime/ets/array-new.ets | 20 + 15 files changed, 970 insertions(+), 7 deletions(-) create mode 100644 ets2panda/compiler/lowering/ets/expandBrackets.cpp create mode 100644 ets2panda/compiler/lowering/ets/expandBrackets.h create mode 100644 ets2panda/test/parser/ets/array_new-expected.txt create mode 100644 ets2panda/test/parser/ets/array_new.ets create mode 100644 ets2panda/test/parser/ets/array_new_failed-expected.txt create mode 100644 ets2panda/test/parser/ets/array_new_failed.ets create mode 100644 ets2panda/test/runtime/ets/array-new-catched.ets create mode 100644 ets2panda/test/runtime/ets/array-new.ets diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index fa8e3f1919..a8e3cbd198 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -155,6 +155,7 @@ libes2panda_sources = [ "compiler/function/functionBuilder.cpp", "compiler/function/generatorFunctionBuilder.cpp", "compiler/lowering/checkerPhase.cpp", + "compiler/lowering/ets/expandBrackets.cpp", "compiler/lowering/ets/generateDeclarations.cpp", "compiler/lowering/ets/lambdaLowering.cpp", "compiler/lowering/ets/objectIndexAccess.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index b56057c828..765a92483f 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -148,6 +148,7 @@ set(ES2PANDA_LIB_SRC compiler/lowering/ets/opAssignment.cpp compiler/lowering/ets/tupleLowering.cpp compiler/lowering/ets/unionLowering.cpp + compiler/lowering/ets/expandBrackets.cpp ir/astDump.cpp ir/astNode.cpp ir/irnode.cpp diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 4f35405def..cd9af081cd 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -504,7 +504,7 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const ETSChecker *checker = GetETSChecker(); auto *element_type = expr->type_reference_->GetType(checker); - checker->ValidateArrayIndex(expr->dimension_); + checker->ValidateArrayIndex(expr->dimension_, true); expr->SetTsType(checker->CreateETSArrayType(element_type)); checker->CreateBuiltinArraySignature(expr->TsType()->AsETSArrayType(), 1); diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 56de58a6ff..ab90084189 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -141,7 +141,7 @@ public: const lexer::SourcePosition &pos); void ResolveDeclaredMembersOfObject(ETSObjectType *type); int32_t GetTupleElementAccessValue(const Type *type) const; - void ValidateArrayIndex(ir::Expression *expr); + void ValidateArrayIndex(ir::Expression *expr, bool relaxed = false); void ValidateTupleIndex(const ETSTupleType *tuple, const ir::MemberExpression *expr); ETSObjectType *CheckThisOrSuperAccess(ir::Expression *node, ETSObjectType *class_type, std::string_view msg); void CreateTypeForClassOrInterfaceTypeParameters(ETSObjectType *type); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index fc8c0d4b9f..9c9cd7bd4e 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -921,7 +921,7 @@ void ETSChecker::CheckInnerClassMembers(const ETSObjectType *class_type) } } -void ETSChecker::ValidateArrayIndex(ir::Expression *const expr) +void ETSChecker::ValidateArrayIndex(ir::Expression *const expr, bool relaxed) { auto *const expression_type = expr->Check(this); auto const *const unboxed_expression_type = ETSBuiltinTypeAsPrimitiveType(expression_type); @@ -932,6 +932,21 @@ void ETSChecker::ValidateArrayIndex(ir::Expression *const expr) expr->AddBoxingUnboxingFlag(GetUnboxingFlag(unboxed_expression_type)); } + if (relaxed && index_type != nullptr && index_type->HasTypeFlag(TypeFlag::ETS_FLOATING_POINT)) { + if (!expr->IsNumberLiteral()) { + return; + } + + auto num = expr->AsNumberLiteral()->Number(); + ASSERT(num.IsReal()); + double value = num.GetDouble(); + double intpart; + if (std::modf(value, &intpart) != 0.0) { + ThrowTypeError("Index fracional part should not be different from 0.0", expr->Start()); + } + return; + } + if (index_type == nullptr || !index_type->HasTypeFlag(TypeFlag::ETS_ARRAY_INDEX)) { std::stringstream message(""); if (expression_type->IsNonPrimitiveType()) { diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.cpp b/ets2panda/compiler/lowering/ets/expandBrackets.cpp new file mode 100644 index 0000000000..fdda661afc --- /dev/null +++ b/ets2panda/compiler/lowering/ets/expandBrackets.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "expandBrackets.h" + +#include "checker/ETSchecker.h" +#include "compiler/lowering/util.h" +#include "compiler/lowering/scopesInit/scopesInitPhase.h" +#include "ir/statements/blockStatement.h" +#include "ir/expressions/memberExpression.h" +#include "parser/ETSparser.h" +#include "varbinder/ETSBinder.h" + +namespace panda::es2panda::compiler { + +bool ExpandBracketsPhase::Perform(public_lib::Context *ctx, parser::Program *program) +{ + auto *const checker = ctx->checker->AsETSChecker(); + auto *const allocator = checker->Allocator(); + auto *const parser = ctx->parser->AsETSParser(); + + program->Ast()->TransformChildrenRecursively([ctx, parser, checker, allocator](ir::AstNode *ast) -> ir::AstNode * { + if (!ast->IsETSNewArrayInstanceExpression()) { + return ast; + } + auto *new_expression = ast->AsETSNewArrayInstanceExpression(); + auto *dimension = new_expression->Dimension(); + auto *dim_type = dimension->TsType(); + if (auto *unboxed = checker->ETSBuiltinTypeAsPrimitiveType(dim_type); unboxed != nullptr) { + dim_type = unboxed; + } + if (!dim_type->HasTypeFlag(checker::TypeFlag::ETS_FLOATING_POINT)) { + return ast; + } + + auto *casted_dimension = + parser->CreateFormattedExpression("@@E1 as int", parser::DEFAULT_SOURCE_FILE, dimension); + casted_dimension->Check(checker); + casted_dimension->SetParent(dimension->Parent()); + new_expression->SetDimension(casted_dimension); + + auto *const scope = NearestScope(new_expression); + auto expression_ctx = varbinder::LexicalScope::Enter(checker->VarBinder(), scope); + auto *ident = Gensym(allocator); + auto *expr_type = checker->AllocNode(dim_type); + auto *sequence_expr = parser->CreateFormattedExpression( + "let @@I1 = (@@E2) as @@T3;" + "if (!isSafeInteger(@@I4)) {" + " throw new TypeError(\"Index fractional part should not be different from 0.0\");" + "};" + "(@@E5);", + parser::DEFAULT_SOURCE_FILE, ident, dimension, expr_type, ident->Clone(allocator), new_expression); + sequence_expr->SetParent(new_expression->Parent()); + ScopesInitPhaseETS::RunExternalNode(sequence_expr, ctx->compiler_context->VarBinder()); + checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(sequence_expr, scope); + sequence_expr->Check(checker); + + return sequence_expr; + }); + return true; +} + +} // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.h b/ets2panda/compiler/lowering/ets/expandBrackets.h new file mode 100644 index 0000000000..7a771f0789 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/expandBrackets.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_EXPAND_BRACKETS_H +#define ES2PANDA_COMPILER_LOWERING_EXPAND_BRACKETS_H + +#include "compiler/lowering/phase.h" + +namespace panda::es2panda::compiler { + +class ExpandBracketsPhase : public Phase { +public: + std::string_view Name() override + { + return "expand-brackets"; + } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; +}; + +} // namespace panda::es2panda::compiler + +#endif diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index 67f22b8149..ca273577a2 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -22,6 +22,7 @@ #include "compiler/lowering/checkerPhase.h" #include "compiler/lowering/plugin_phase.h" #include "compiler/lowering/scopesInit/scopesInitPhase.h" +#include "compiler/lowering/ets/expandBrackets.h" #include "compiler/lowering/ets/generateDeclarations.h" #include "compiler/lowering/ets/lambdaLowering.h" #include "compiler/lowering/ets/opAssignment.h" @@ -46,6 +47,7 @@ static OpAssignmentLowering OP_ASSIGNMENT_LOWERING; static ObjectIndexLowering OBJECT_INDEX_LOWERING; static TupleLowering TUPLE_LOWERING; // Can be only applied after checking phase, and OP_ASSIGNMENT_LOWERING phase static UnionLowering UNION_LOWERING; +static ExpandBracketsPhase EXPAND_BRACKETS_PHASE; static PluginPhase PLUGINS_AFTER_PARSE {"plugins-after-parse", ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse}; static PluginPhase PLUGINS_AFTER_CHECK {"plugins-after-check", ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck}; static PluginPhase PLUGINS_AFTER_LOWERINGS {"plugins-after-lowering", ES2PANDA_STATE_LOWERED, @@ -61,10 +63,10 @@ std::vector GetPhaseList(ScriptExtension ext) switch (ext) { case ScriptExtension::ETS: return { - &scopes_phase_ets, &PLUGINS_AFTER_PARSE, &LAMBDA_LOWERING, - &CHECKER_PHASE, &PLUGINS_AFTER_CHECK, &GENERATE_TS_DECLARATIONS_PHASE, - &OP_ASSIGNMENT_LOWERING, &OBJECT_INDEX_LOWERING, &TUPLE_LOWERING, - &UNION_LOWERING, &PLUGINS_AFTER_LOWERINGS, + &scopes_phase_ets, &PLUGINS_AFTER_PARSE, &LAMBDA_LOWERING, + &CHECKER_PHASE, &PLUGINS_AFTER_CHECK, &GENERATE_TS_DECLARATIONS_PHASE, + &OP_ASSIGNMENT_LOWERING, &OBJECT_INDEX_LOWERING, &TUPLE_LOWERING, + &UNION_LOWERING, &EXPAND_BRACKETS_PHASE, &PLUGINS_AFTER_LOWERINGS, }; case ScriptExtension::AS: return std::vector { diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h index 27c4ab48bf..6a5b70f037 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h @@ -66,6 +66,11 @@ public: return dimension_; } + void SetDimension(ir::Expression *dimension) + { + dimension_ = dimension; + } + // NOLINTNEXTLINE(google-default-arguments) [[nodiscard]] ETSNewArrayInstanceExpression *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; diff --git a/ets2panda/test/parser/ets/array_new-expected.txt b/ets2panda/test/parser/ets/array_new-expected.txt new file mode 100644 index 0000000000..f67a81d376 --- /dev/null +++ b/ets2panda/test/parser/ets/array_new-expected.txt @@ -0,0 +1,373 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 13 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "init": { + "type": "ETSNewArrayInstanceExpression", + "typeReference": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "dimension": { + "type": "NumberLiteral", + "value": 5, + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 23 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 17, + "column": 3 + }, + "end": { + "line": 17, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 22 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 18, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 19, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/array_new.ets b/ets2panda/test/parser/ets/array_new.ets new file mode 100644 index 0000000000..3d6aca46c6 --- /dev/null +++ b/ets2panda/test/parser/ets/array_new.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 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. + */ + +function foo(): void { + let a = new int[5.0] +} diff --git a/ets2panda/test/parser/ets/array_new_failed-expected.txt b/ets2panda/test/parser/ets/array_new_failed-expected.txt new file mode 100644 index 0000000000..7a1d50898a --- /dev/null +++ b/ets2panda/test/parser/ets/array_new_failed-expected.txt @@ -0,0 +1,374 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 13 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 13 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "init": { + "type": "ETSNewArrayInstanceExpression", + "typeReference": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "dimension": { + "type": "NumberLiteral", + "value": 5.1, + "loc": { + "start": { + "line": 17, + "column": 19 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 23 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 17, + "column": 3 + }, + "end": { + "line": 17, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 22 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 18, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 19, + "column": 1 + } + } +} +TypeError: Index fracional part should not be different from 0.0 [array_new_failed.ets:17:19] diff --git a/ets2panda/test/parser/ets/array_new_failed.ets b/ets2panda/test/parser/ets/array_new_failed.ets new file mode 100644 index 0000000000..226b20a4d5 --- /dev/null +++ b/ets2panda/test/parser/ets/array_new_failed.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 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. + */ + +function foo(): void { + let a = new int[5.1] +} diff --git a/ets2panda/test/runtime/ets/array-new-catched.ets b/ets2panda/test/runtime/ets/array-new-catched.ets new file mode 100644 index 0000000000..9fd9a7201f --- /dev/null +++ b/ets2panda/test/runtime/ets/array-new-catched.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 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. + */ + +function baz(): number { + return 5.1 +} +function main(): void { + let catched = false; + try { + let a = new int[baz()] + } catch (e: TypeError) { + catched = true + } + assert catched +} diff --git a/ets2panda/test/runtime/ets/array-new.ets b/ets2panda/test/runtime/ets/array-new.ets new file mode 100644 index 0000000000..16037be12b --- /dev/null +++ b/ets2panda/test/runtime/ets/array-new.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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. + */ + +function main(): void { + let A: Array = new Array(); + let a: Number[] = new Number[A.length + 2] + assert a.length == 2 +} -- Gitee