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 8dddff53b552b11d0a614b68096e469630cd1ceb..0b51f678bafa03f5ca8e7eb96dc59507fb7ac694 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -334,6 +334,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 d07eb0720854ac4c231c499b1cf588e204658bdc..daf11fc5cd372c49fb42f30cbab9aec70e869e20 100644 --- a/ets2panda/parser/ETSparserExpressions.cpp +++ b/ets2panda/parser/ETSparserExpressions.cpp @@ -237,6 +237,44 @@ bool CheckNextTokenOfTypeof(const lexer::Token &token) return (pretendTypeof || pretendIdent || pretendOperator || pretendUnary || pretendPuctuator); } +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 533f14d32c005e746bcc9d8da0ab8a9d2b849022..3f828806599d26ad9a604e9683704bd2c70f3cdd 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -151,7 +151,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 aac66bdd5465ff3d70694377378bad0d3ae7ac2c..4dc414ecae8d55007635a4f124f47655944fa159 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,6 +24,34 @@ const b: Record number> = { [(():number => +("bar"))()]: (y: string):number => y.length }; -/* @@? 21:20 Error TypeError: Wrong operand type for unary expression */ -/* @@? 21:34 Error SyntaxError: Function expressions are not supported, use arrow functions instead */ -/* @@? 24:20 Error TypeError: Wrong operand type for unary expression */ +/* @@? 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:26 Error SyntaxError: Unexpected token ':'. */ +/* @@? 17:28 Error SyntaxError: Unexpected token '1'. */ +/* @@? 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:20 Error TypeError: Wrong operand type for unary expression */ +/* @@? 21:28 Error SyntaxError: Unexpected token. */ +/* @@? 21:31 Error SyntaxError: Unexpected token ']'. */ +/* @@? 21:32 Error SyntaxError: Unexpected token ':'. */ +/* @@? 21:34 Error SyntaxError: Unexpected token 'function'. */ +/* @@? 21:43 Error SyntaxError: Unexpected token, expected an identifier. */ +/* @@? 23:6 Error SyntaxError: Unexpected token ','. */ +/* @@? 23:6 Error TypeError: Indexed access is not supported for such expression type. */ +/* @@? 24:20 Error TypeError: Wrong operand type for unary expression */ +/* @@? 24:32 Error SyntaxError: Unexpected token ':'. */ +/* @@? 24:35 Error TypeError: Unresolved reference y */ +/* @@? 24:36 Error SyntaxError: Unexpected token ':'. */ +/* @@? 24:36 Error SyntaxError: Unexpected token, expected ',' or ')'. */ +/* @@? 24:38 Error SyntaxError: Unexpected token 'string'. */ +/* @@? 24:38 Error TypeError: Type name 'string' used in the wrong context */ +/* @@? 24:44 Error SyntaxError: Unexpected token ')'. */ +/* @@? 24:45 Error SyntaxError: Unexpected token ':'. */ +/* @@? 24:46 Error SyntaxError: Unexpected token 'number'. */ +/* @@? 24:46 Error TypeError: The type of parameter 'number' cannot be inferred */ +/* @@? 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..a7b52b85583f9176c23844e417e8b969944357cc --- /dev/null +++ b/ets2panda/test/ast/parser/ets/invalid_object_expression.ets @@ -0,0 +1,28 @@ +/* + * 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:28 Error SyntaxError: Unexpected token '123'. */ +/* @@? 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..9b65b55ca6dfc69334e73db9fd863823f19ec76a 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_52.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_52.ets @@ -13,11 +13,21 @@ * 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:14 Error SyntaxError: Unexpected token '{'. */ +/* @@? 17:16 Error SyntaxError: Unexpected token ','. */ +/* @@? 18:5 Error SyntaxError: Unexpected token '...'. */ +/* @@? 18:8 Error SyntaxError: Unexpected token 'a'. */ +/* @@? 18:9 Error SyntaxError: Unexpected token ','. */ +/* @@? 19:1 Error SyntaxError: Unexpected token '}'. */ diff --git a/ets2panda/test/ast/parser/ets/update_funcscope_error.ets b/ets2panda/test/ast/parser/ets/update_funcscope_error.ets index 966c78d0cc0d6a81c59e142d6857535301990fc1..7ca3f8b98c016452f86634a9eb2894793e19aff9 100644 --- a/ets2panda/test/ast/parser/ets/update_funcscope_error.ets +++ b/ets2panda/test/ast/parser/ets/update_funcscope_error.ets @@ -38,4 +38,14 @@ export const updateIfChanged = (t: Record) => { /* @@? 21:19 Error TypeError: Indexed access is not supported for such expression type. */ /* @@? 24:7 Error TypeError: Type '(v: Record) => Boolean' is not compatible with type '(previousValue: Boolean, currentValue: Boolean, index: Double, array: FixedArray) => Boolean' at index 2 */ /* @@? 27:11 Error TypeError: Invalid record property */ +/* @@? 28:11 Error SyntaxError: Unexpected token. */ +/* @@? 28:12 Error SyntaxError: Unexpected token. */ +/* @@? 28:12 Error TypeError: Type '*ERROR_TYPE*' is not compatible with type 'String' at index 1 */ +/* @@? 28:15 Error SyntaxError: Unexpected token. */ +/* @@? 28:16 Error SyntaxError: Unexpected token ':'. */ +/* @@? 28:18 Error SyntaxError: Unexpected token 'v'. */ +/* @@? 29:10 Error SyntaxError: Unexpected token, expected ',' or ')'. */ /* @@? 30:16 Error TypeError: Unresolved reference update */ +/* @@? 32:5 Error SyntaxError: Unexpected token ')'. */ +/* @@? 33:12 Error TypeError: Unresolved reference reduceResult */ +/* @@? 35: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..5875761b7d9f4f4ef18920cb2e5c46485801a72c --- /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() { + arktest.assertTrue(true); +}