diff --git a/ets2panda/ir/statements/forUpdateStatement.cpp b/ets2panda/ir/statements/forUpdateStatement.cpp index 912dd11f40e02c16def7bf72aa490607a2a316e2..cd0d2d53170af2dffb4c3e54d27d413d90e2b4de 100644 --- a/ets2panda/ir/statements/forUpdateStatement.cpp +++ b/ets2panda/ir/statements/forUpdateStatement.cpp @@ -127,9 +127,20 @@ checker::VerifiedType ForUpdateStatement::Check(checker::ETSChecker *checker) ForUpdateStatement *ForUpdateStatement::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const init = init_->Clone(allocator, nullptr); - auto *const test = test_->Clone(allocator, nullptr)->AsExpression(); - auto *const update = update_->Clone(allocator, nullptr)->AsExpression(); + ir::AstNode *init = nullptr; + if (init_ != nullptr) { + init = init_->Clone(allocator, nullptr); + } + + ir::Expression *test = nullptr; + if (test_ != nullptr) { + test = test_->Clone(allocator, nullptr)->AsExpression(); + } + + ir::Expression *update = nullptr; + if (update_ != nullptr) { + update = update_->Clone(allocator, nullptr)->AsExpression(); + } auto *const body = body_->Clone(allocator, nullptr)->AsStatement(); auto *const clone = util::NodeAllocator::ForceSetParent(allocator, init, test, update, body); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index a288b7150ecd3ca663c361bc5da832a80ddbf52a..7f668570a79451d4702285520aa279fe30c64c9e 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -422,6 +422,7 @@ private: ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; // NOLINTNEXTLINE(google-default-arguments) ir::Expression *ParsePropertyDefinition(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; + ir::Expression *ParsePropertyKey(ExpressionParseFlags flags) override; // NOLINTNEXTLINE(google-default-arguments) ir::Expression *ParseDefaultPrimaryExpression(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/parser/ETSparserExpressions.cpp b/ets2panda/parser/ETSparserExpressions.cpp index 594c038963bd7c8ec51e48b6b83b5705e937aff9..e995f8c125e3d35047487a3f3c59d492510fcbd6 100644 --- a/ets2panda/parser/ETSparserExpressions.cpp +++ b/ets2panda/parser/ETSparserExpressions.cpp @@ -234,6 +234,44 @@ ir::Expression *ETSParser::ParsePropertyDefinition(ExpressionParseFlags flags) return returnProperty; } +ir::Expression *ETSParser::ParsePropertyKey([[maybe_unused]] ExpressionParseFlags flags) +{ + ir::Expression *key = nullptr; + + switch (Lexer()->GetToken().Type()) { + case lexer::TokenType::LITERAL_IDENT: { + const util::StringView &ident = Lexer()->GetToken().Ident(); + key = AllocNode(ident, Allocator()); + key->SetRange(Lexer()->GetToken().Loc()); + Lexer()->NextToken(); + return key; + } + case lexer::TokenType::LITERAL_STRING: { + const util::StringView &string = Lexer()->GetToken().String(); + key = AllocNode(string); + key->SetRange(Lexer()->GetToken().Loc()); + Lexer()->NextToken(); + return key; + } + case lexer::TokenType::LITERAL_NUMBER: { + if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) { + key = AllocNode(Lexer()->GetToken().BigInt()); + } else { + key = AllocNode(Lexer()->GetToken().GetNumber()); + } + key->SetRange(Lexer()->GetToken().Loc()); + Lexer()->NextToken(); + return key; + } + default: { + const auto &rangeToken = Lexer()->GetToken().Loc(); + LogError(diagnostic::UNEXPECTED_TOKEN); + Lexer()->NextToken(); + return AllocBrokenExpression(rangeToken); + } + } +} + // NOLINTNEXTLINE(google-default-arguments) ir::Expression *ETSParser::ParseDefaultPrimaryExpression(ExpressionParseFlags flags) { diff --git a/ets2panda/parser/parserImpl.h b/ets2panda/parser/parserImpl.h index d64de90591844ae65634a889dd50971c16c1b197..4491082c2fc9da335bebf71e146c7fc99ca377b6 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -136,7 +136,7 @@ protected: void ValidateGroupedExpression(ir::Expression *lhsExpression); ir::Expression *ParseImportExpression(); ir::Expression *ParseOptionalChain(ir::Expression *leftSideExpr); - ir::Expression *ParsePropertyKey(ExpressionParseFlags flags); + virtual ir::Expression *ParsePropertyKey(ExpressionParseFlags flags); void ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node); void ValidateLvalueAssignmentTarget(ir::Expression *node); void ValidateArrowParameterBindings(const ir::Expression *node); diff --git a/ets2panda/test/ast/compiler/ets/arrow_function_call_as_record_property_key.ets b/ets2panda/test/ast/compiler/ets/arrow_function_call_as_record_property_key.ets index c28cceb5a3850fb6e29cf2ca86386bc020b53570..2bf77c110bc0aa1dd3560e435fcbb449f4204336 100644 --- a/ets2panda/test/ast/compiler/ets/arrow_function_call_as_record_property_key.ets +++ b/ets2panda/test/ast/compiler/ets/arrow_function_call_as_record_property_key.ets @@ -24,30 +24,30 @@ const b: Record number> = { [(():number => +("bar"))()]: (y: string):number => y.length }; -/* @@? 21:21 Error TypeError: Bad operand type, the type of the operand must be numeric type. */ -/* @@? 21:34 Error SyntaxError: Unexpected token. */ -/* @@? 21:34 Error SyntaxError: Unexpected token 'function'. */ -/* @@? 21:43 Error SyntaxError: Unexpected token. */ -/* @@? 21:44 Error SyntaxError: Unexpected token. */ -/* @@? 21:44 Error TypeError: Unresolved reference y */ -/* @@? 21:45 Error SyntaxError: Unexpected token. */ -/* @@? 21:47 Error TypeError: Type 'String' is not compatible with type 'Double' at index 1 */ -/* @@? 21:47 Error TypeError: Type name 'string' used in the wrong context */ -/* @@? 21:53 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 21:54 Error SyntaxError: Unexpected token ':'. */ -/* @@? 21:54 Error SyntaxError: Unexpected token. */ -/* @@? 21:56 Error TypeError: Type name 'number' used in the wrong context */ -/* @@? 21:63 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 22:9 Error SyntaxError: Unexpected token. */ -/* @@? 22:9 Error SyntaxError: Unexpected token 'return'. */ -/* @@? 22:17 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 22:18 Error TypeError: Unresolved reference length */ -/* @@? 22:24 Error SyntaxError: Unexpected token. */ -/* @@? 23:5 Error SyntaxError: Unexpected token '}'. */ -/* @@? 23:6 Error SyntaxError: Unexpected token ','. */ -/* @@? 23:6 Error SyntaxError: Unexpected token ','. */ -/* @@? 24:21 Error TypeError: Bad operand type, the type of the operand must be numeric type. */ -/* @@? 24:32 Error SyntaxError: Unexpected token ':'. */ -/* @@? 24:32 Error SyntaxError: Unexpected token ':'. */ -/* @@? 24:32 Error SyntaxError: Unexpected token ':'. */ -/* @@? 25:1 Error SyntaxError: Unexpected token '}'. */ +/* @@? 16:35 Error TypeError: need to specify target type for class composite */ +/* @@? 17:5 Error SyntaxError: Unexpected token. */ +/* @@? 17:6 Error SyntaxError: Unexpected token, expected ':'. */ +/* @@? 17:22 Error SyntaxError: Unexpected token. */ +/* @@? 17:25 Error SyntaxError: Unexpected token ']'. */ +/* @@? 17:25 Error SyntaxError: Unexpected token ']'. */ +/* @@? 17:25 Error SyntaxError: Unexpected token ']'. */ +/* @@? 17:26 Error SyntaxError: Unexpected token ':'. */ +/* @@? 17:26 Error SyntaxError: Unexpected token ':'. */ +/* @@? 18:1 Error SyntaxError: Unexpected token '}'. */ +/* @@? 20:50 Error TypeError: need to specify target type for class composite */ +/* @@? 21:5 Error SyntaxError: Unexpected token. */ +/* @@? 21:6 Error SyntaxError: Unexpected token, expected ':'. */ +/* @@? 21:28 Error SyntaxError: Unexpected token. */ +/* @@? 21:31 Error SyntaxError: Unexpected token ']'. */ +/* @@? 21:31 Error SyntaxError: Unexpected token ']'. */ +/* @@? 21:31 Error SyntaxError: Unexpected token ']'. */ +/* @@? 21:32 Error SyntaxError: Unexpected token ':'. */ +/* @@? 21:32 Error SyntaxError: Unexpected token ':'. */ +/* @@? 21:43 Error SyntaxError: Unexpected token, expected an identifier. */ +/* @@? 23:6 Error SyntaxError: Unexpected token ','. */ +/* @@? 23:6 Error SyntaxError: Unexpected token ','. */ +/* @@? 24:21 Error TypeError: Bad operand type, the type of the operand must be numeric type. */ +/* @@? 24:32 Error SyntaxError: Unexpected token ':'. */ +/* @@? 24:32 Error SyntaxError: Unexpected token ':'. */ +/* @@? 24:32 Error SyntaxError: Unexpected token ':'. */ +/* @@? 25:1 Error SyntaxError: Unexpected token '}'. */ diff --git a/ets2panda/test/ast/parser/ets/invalid_object_expression.ets b/ets2panda/test/ast/parser/ets/invalid_object_expression.ets new file mode 100644 index 0000000000000000000000000000000000000000..3888c0ab9d18db3b0c2579b0392c592d8ce42b03 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/invalid_object_expression.ets @@ -0,0 +1,29 @@ +/* + * 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. + */ + + +let obj: Record = { + [this.viewModel.ads] : 123 +} + +/* @@? 18:5 Error SyntaxError: Unexpected token. */ +/* @@? 18:6 Error SyntaxError: Unexpected token. */ +/* @@? 18:6 Error TypeError: Cannot reference 'this' in this context. */ +/* @@? 18:11 Error TypeError: Property 'viewModel' does not exist on type 'Error' */ +/* @@? 18:24 Error SyntaxError: Unexpected token. */ +/* @@? 18:26 Error SyntaxError: Unexpected token ':'. */ +/* @@? 18:26 Error SyntaxError: Unexpected token ':'. */ +/* @@? 18:26 Error SyntaxError: Unexpected token ':'. */ +/* @@? 19:1 Error SyntaxError: Unexpected token '}'. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_52.ets b/ets2panda/test/ast/parser/ets/unexpected_token_52.ets index b447ab92d520874dc11995c29a7c4d1c8fd66ce7..37a4bdb67f91000a4e50eeff5ae4889a99464109 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_52.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_52.ets @@ -13,11 +13,24 @@ * limitations under the License. */ -let /* @@ label1 */a = { - get [/* @@ label2 */b/* @@ label3 */)(){}, - ...a, +let a = { + get [b)(){}, + ...a, } -/* @@@ label1 Error TypeError: Cannot infer type for a because class composite needs an explicit target type */ -/* @@@ label2 Error SyntaxError: Object pattern can't contain methods. */ -/* @@@ label3 Error SyntaxError: Unexpected token, expected ']'. */ +/* @@? 16:5 Error TypeError: Cannot infer type for a because class composite needs an explicit target type */ +/* @@? 17:9 Error SyntaxError: Unexpected token. */ +/* @@? 17:10 Error SyntaxError: Unexpected token, expected '('. */ +/* @@? 17:10 Error SyntaxError: Object pattern can't contain methods. */ +/* @@? 17:12 Error SyntaxError: Expected '{', got '('. */ +/* @@? 17:12 Error SyntaxError: Unexpected token. */ +/* @@? 17:13 Error SyntaxError: Unexpected token ')'. */ +/* @@? 17:13 Error SyntaxError: Unexpected token ')'. */ +/* @@? 17:13 Error SyntaxError: Unexpected token ')'. */ +/* @@? 17:16 Error SyntaxError: Unexpected token ','. */ +/* @@? 17:16 Error SyntaxError: Unexpected token ','. */ +/* @@? 18:5 Error SyntaxError: Unexpected token '...'. */ +/* @@? 18:9 Error SyntaxError: Unexpected token ','. */ +/* @@? 18:9 Error SyntaxError: Unexpected token ','. */ +/* @@? 18:9 Error SyntaxError: Unexpected token ','. */ +/* @@? 19:1 Error SyntaxError: Unexpected token '}'. */ diff --git a/ets2panda/test/runtime/ets/empty_for_init.ets b/ets2panda/test/runtime/ets/empty_for_init.ets new file mode 100644 index 0000000000000000000000000000000000000000..de5569aab9613a1d5b28e0e6372335ef3e8c92a7 --- /dev/null +++ b/ets2panda/test/runtime/ets/empty_for_init.ets @@ -0,0 +1,35 @@ +/* + * 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. + */ + + +let foo = (() => { + for (let i = 0; i < 1;) { + } +}) + +let foo1 = (() => { + let i = 0 + for (;; i++) { + } +}) + +let foo2 = (() => { + for (;;) { + } +}) + +function main() { + assertTrue(true); +}