From c66b5c0a3cd4f088b570d8474dc1a49250817087 Mon Sep 17 00:00:00 2001 From: Orlovsky Maxim Date: Fri, 20 Oct 2023 17:03:50 +0300 Subject: [PATCH] Title: Added syntax to float literal coercion Issue: https://gitee.com/open_harmony/dashboard?issue_id=I8G5KF&from=project-issue Testing: Ets tests in compiler and runtime Change-Id: I298d14a0dbc1a4ebc10ada58aa05ade731515db1 Signed-off-by: Orlovsky Maxim --- ets2panda/lexer/ETSLexer.cpp | 15 + ets2panda/lexer/ETSLexer.h | 1 + ets2panda/lexer/lexer.h | 2 +- ets2panda/lexer/token/token.h | 3 +- ets2panda/parser/ETSparser.cpp | 18 +- ets2panda/parser/ETSparser.h | 1 + .../test/parser/ets/literals-expected.txt | 402 ++++++++++++++++-- ets2panda/test/parser/ets/literals.ets | 13 +- ets2panda/test/runtime/ets/float-literal.ets | 24 ++ 9 files changed, 438 insertions(+), 41 deletions(-) create mode 100644 ets2panda/test/runtime/ets/float-literal.ets diff --git a/ets2panda/lexer/ETSLexer.cpp b/ets2panda/lexer/ETSLexer.cpp index aa5b41719e..ba264d73d8 100644 --- a/ets2panda/lexer/ETSLexer.cpp +++ b/ets2panda/lexer/ETSLexer.cpp @@ -72,6 +72,21 @@ bool ETSLexer::ScanCharLiteral() return true; } +void ETSLexer::CheckNumberLiteralEnd() +{ + if (Iterator().Peek() == LEX_CHAR_LOWERCASE_F) { + GetToken().flags_ |= TokenFlags::NUMBER_FLOAT; + GetToken().src_ = SourceView(GetToken().Start().index, Iterator().Index()); + Iterator().Forward(1); + const auto next_cp = Iterator().PeekCp(); + if (KeywordsUtil::IsIdentifierStart(next_cp) || IsDecimalDigit(next_cp)) { + ThrowError("Invalid numeric literal"); + } + } else { + Lexer::CheckNumberLiteralEnd(); + } +} + void ETSLexer::CheckUtf16Compatible(char32_t cp) const { if (cp >= util::StringView::Constants::CELESTIAL_OFFSET) { diff --git a/ets2panda/lexer/ETSLexer.h b/ets2panda/lexer/ETSLexer.h index 1ad9801099..6c7c7b43e9 100644 --- a/ets2panda/lexer/ETSLexer.h +++ b/ets2panda/lexer/ETSLexer.h @@ -48,6 +48,7 @@ public: } } + void CheckNumberLiteralEnd() override; void CheckUtf16Compatible(char32_t cp) const; void ConvertNumber(const std::string &utf8, NumberFlags flags) override; diff --git a/ets2panda/lexer/lexer.h b/ets2panda/lexer/lexer.h index 2a36059a2b..a6e48dee91 100644 --- a/ets2panda/lexer/lexer.h +++ b/ets2panda/lexer/lexer.h @@ -266,7 +266,7 @@ protected: virtual void ConvertNumber(const std::string &utf8, NumberFlags flags); void ScanDecimalLiteral(); void ScanDecimalDigits(bool allow_numeric_separator); - void CheckNumberLiteralEnd(); + virtual void CheckNumberLiteralEnd(); inline static uint32_t HexValue(char32_t ch); inline static bool IsDecimalDigit(uint32_t cp); diff --git a/ets2panda/lexer/token/token.h b/ets2panda/lexer/token/token.h index 860e5cbf4b..500e7ae9a0 100644 --- a/ets2panda/lexer/token/token.h +++ b/ets2panda/lexer/token/token.h @@ -29,7 +29,8 @@ enum class TokenFlags : uint32_t { NEW_LINE = 1U << 0U, HAS_ESCAPE = 1U << 2U, NUMBER_BIGINT = 1U << 3U, - NUMBER_HAS_UNDERSCORE = 1U << 4U, + NUMBER_FLOAT = 1U << 4U, + NUMBER_HAS_UNDERSCORE = 1U << 5U, }; DEFINE_BITOPS(TokenFlags) diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index e86b81930b..b772b35f02 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -3615,7 +3615,7 @@ ir::Expression *ETSParser::ParsePrimaryExpression(ExpressionParseFlags flags) return ParseUndefinedLiteral(); } case lexer::TokenType::LITERAL_NUMBER: { - return ParseNumberLiteral(); + return ParseCoercedNumberLiteral(); } case lexer::TokenType::LITERAL_STRING: { return ParseStringLiteral(); @@ -4435,6 +4435,22 @@ void ETSParser::ParseTrailingBlock(ir::CallExpression *call_expr) } } +ir::Expression *ETSParser::ParseCoercedNumberLiteral() +{ + if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_FLOAT) != 0U) { + auto *number = AllocNode(Lexer()->GetToken().GetNumber()); + number->SetRange(Lexer()->GetToken().Loc()); + auto *float_type = AllocNode(ir::PrimitiveType::FLOAT); + float_type->SetRange(Lexer()->GetToken().Loc()); + auto *as_expression = AllocNode(number, float_type, true); + as_expression->SetRange(Lexer()->GetToken().Loc()); + + Lexer()->NextToken(); + return as_expression; + } + return ParseNumberLiteral(); +} + void ETSParser::CheckDeclare() { ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index ba8e78e359..32dc01e390 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -84,6 +84,7 @@ private: ir::ClassProperty *ParseInterfaceField(const lexer::SourcePosition &start_loc); ir::Expression *ParseInitializer(); ir::ArrayExpression *ParseArrayLiteral(); + ir::Expression *ParseCoercedNumberLiteral(); ir::MethodDefinition *ParseInterfaceMethod(ir::ModifierFlags flags); std::tuple ParseClassMemberAccessModifiers(); ir::ModifierFlags ParseClassFieldModifiers(bool seen_static); diff --git a/ets2panda/test/parser/ets/literals-expected.txt b/ets2panda/test/parser/ets/literals-expected.txt index 102b4b5cf5..5177a122ab 100644 --- a/ets2panda/test/parser/ets/literals-expected.txt +++ b/ets2panda/test/parser/ets/literals-expected.txt @@ -799,8 +799,34 @@ } }, "value": { - "type": "ArrayExpression", - "elements": [], + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 123.45, + "loc": { + "start": { + "line": 31, + "column": 15 + }, + "end": { + "line": 31, + "column": 22 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 31, + "column": 15 + }, + "end": { + "line": 31, + "column": 22 + } + } + }, "loc": { "start": { "line": 31, @@ -808,7 +834,7 @@ }, "end": { "line": 31, - "column": 17 + "column": 22 } } }, @@ -848,6 +874,314 @@ } } }, + "value": { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 1.2345e+12, + "loc": { + "start": { + "line": 32, + "column": 15 + }, + "end": { + "line": 32, + "column": 25 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 32, + "column": 15 + }, + "end": { + "line": 32, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 32, + "column": 15 + }, + "end": { + "line": 32, + "column": 25 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "lit16", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 7 + }, + "end": { + "line": 33, + "column": 12 + } + } + }, + "value": { + "type": "UnaryExpression", + "operator": "-", + "prefix": true, + "argument": { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 123.45, + "loc": { + "start": { + "line": 33, + "column": 16 + }, + "end": { + "line": 33, + "column": 23 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 33, + "column": 16 + }, + "end": { + "line": 33, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 16 + }, + "end": { + "line": 33, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 33, + "column": 15 + }, + "end": { + "line": 33, + "column": 23 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "lit17", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 7 + }, + "end": { + "line": 34, + "column": 12 + } + } + }, + "value": { + "type": "UnaryExpression", + "operator": "-", + "prefix": true, + "argument": { + "type": "TSAsExpression", + "expression": { + "type": "NumberLiteral", + "value": 1.2345e+12, + "loc": { + "start": { + "line": 34, + "column": 16 + }, + "end": { + "line": 34, + "column": 26 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 34, + "column": 16 + }, + "end": { + "line": 34, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 16 + }, + "end": { + "line": 34, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 15 + }, + "end": { + "line": 34, + "column": 26 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "lit18", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 7 + }, + "end": { + "line": 35, + "column": 12 + } + } + }, + "value": { + "type": "ArrayExpression", + "elements": [], + "loc": { + "start": { + "line": 35, + "column": 15 + }, + "end": { + "line": 35, + "column": 17 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "lit19", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 7 + }, + "end": { + "line": 36, + "column": 12 + } + } + }, "value": { "type": "ArrayExpression", "elements": [ @@ -856,11 +1190,11 @@ "value": 1, "loc": { "start": { - "line": 32, + "line": 36, "column": 16 }, "end": { - "line": 32, + "line": 36, "column": 17 } } @@ -870,11 +1204,11 @@ "value": 2, "loc": { "start": { - "line": 32, + "line": 36, "column": 18 }, "end": { - "line": 32, + "line": 36, "column": 19 } } @@ -884,11 +1218,11 @@ "value": 3, "loc": { "start": { - "line": 32, + "line": 36, "column": 20 }, "end": { - "line": 32, + "line": 36, "column": 21 } } @@ -896,11 +1230,11 @@ ], "loc": { "start": { - "line": 32, + "line": 36, "column": 15 }, "end": { - "line": 32, + "line": 36, "column": 22 } } @@ -928,15 +1262,15 @@ "type": "ClassProperty", "key": { "type": "Identifier", - "name": "lit16", + "name": "lit20", "decorators": [], "loc": { "start": { - "line": 33, + "line": 37, "column": 7 }, "end": { - "line": 33, + "line": 37, "column": 12 } } @@ -949,11 +1283,11 @@ "value": "1", "loc": { "start": { - "line": 33, + "line": 37, "column": 16 }, "end": { - "line": 33, + "line": 37, "column": 19 } } @@ -963,11 +1297,11 @@ "value": "2", "loc": { "start": { - "line": 33, + "line": 37, "column": 20 }, "end": { - "line": 33, + "line": 37, "column": 23 } } @@ -977,11 +1311,11 @@ "value": "3", "loc": { "start": { - "line": 33, + "line": 37, "column": 24 }, "end": { - "line": 33, + "line": 37, "column": 27 } } @@ -989,11 +1323,11 @@ ], "loc": { "start": { - "line": 33, + "line": 37, "column": 15 }, "end": { - "line": 33, + "line": 37, "column": 28 } } @@ -1021,15 +1355,15 @@ "type": "ClassProperty", "key": { "type": "Identifier", - "name": "lit17", + "name": "lit21", "decorators": [], "loc": { "start": { - "line": 34, + "line": 38, "column": 7 }, "end": { - "line": 34, + "line": 38, "column": 12 } } @@ -1042,11 +1376,11 @@ "value": 1, "loc": { "start": { - "line": 34, + "line": 38, "column": 16 }, "end": { - "line": 34, + "line": 38, "column": 19 } } @@ -1056,11 +1390,11 @@ "value": 2, "loc": { "start": { - "line": 34, + "line": 38, "column": 20 }, "end": { - "line": 34, + "line": 38, "column": 23 } } @@ -1070,11 +1404,11 @@ "value": 3, "loc": { "start": { - "line": 34, + "line": 38, "column": 24 }, "end": { - "line": 34, + "line": 38, "column": 27 } } @@ -1082,11 +1416,11 @@ ], "loc": { "start": { - "line": 34, + "line": 38, "column": 15 }, "end": { - "line": 34, + "line": 38, "column": 28 } } @@ -1140,7 +1474,7 @@ "column": 1 }, "end": { - "line": 35, + "line": 40, "column": 1 } } diff --git a/ets2panda/test/parser/ets/literals.ets b/ets2panda/test/parser/ets/literals.ets index 5cc6008913..66f10e29ac 100644 --- a/ets2panda/test/parser/ets/literals.ets +++ b/ets2panda/test/parser/ets/literals.ets @@ -28,7 +28,12 @@ const lit10 = c'\u0061'; const lit11 = true; const lit12 = false; const lit13 = null; -const lit14 = []; -const lit15 = [1,2,3]; -const lit16 = ["1","2","3"]; -const lit17 = [1.0,2.0,3.0]; +const lit14 = 123.45f; // equivalent to (123.45 as float) +const lit15 = 123.45e10f; +const lit16 = -123.45f; // equivalent to -(123.45 as float) +const lit17 = -123.45e10f; +const lit18 = []; +const lit19 = [1,2,3]; +const lit20 = ["1","2","3"]; +const lit21 = [1.0,2.0,3.0]; + diff --git a/ets2panda/test/runtime/ets/float-literal.ets b/ets2panda/test/runtime/ets/float-literal.ets new file mode 100644 index 0000000000..df9b6bf771 --- /dev/null +++ b/ets2panda/test/runtime/ets/float-literal.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022-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 id(value: float): float { + return value +} + +function main(): void { + assert id(10) == 10.0f + assert id(-10) == -10.0f + assert id(0) == 0.0f +} -- Gitee