From d3f983089840eafb11cce0588b04e9c3e24c4e0f Mon Sep 17 00:00:00 2001 From: Daniel Kofanov Date: Thu, 19 Jun 2025 00:17:03 +0800 Subject: [PATCH] [ArkTS] Fix const-folding * Introduce a new const-folding algorithm based on a dataflow-IR. * Fix CF breaking 'private' visibility of readonly properties. * Fix CF being disrespectful to the explicit types of const-variables and substituting reference to them with "uncasted" literal. * Fix CF hiding errors in case of conditional operator (e.g. unresolved variable). * Fix CF-related crash due to number to boolean assignment. * Fix CF applied to a reference to a const in lvalue-position. * Remove deprecated 'char' operations and conversions. * Fix parsing of float literals. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICHUG8 Change-Id: Ic64e9c3950c117173108f4d2732130ee0e68b98d Signed-off-by: Daniel Kofanov --- ets2panda/checker/ets/arithmetic.cpp | 5 + ets2panda/checker/ets/helpers.cpp | 4 +- ets2panda/checker/ets/validateHelpers.cpp | 5 +- ets2panda/checker/ets/wideningConverter.h | 11 +- ets2panda/checker/types/typeFlag.h | 2 +- .../ets/constantExpressionLowering.cpp | 2036 +++++++-------- .../lowering/ets/constantExpressionLowering.h | 271 +- ets2panda/ir/astNode.h | 44 +- ets2panda/lexer/token/number.cpp | 23 +- ets2panda/lexer/token/number.h | 171 +- .../ast/compiler/ets/DeclareCheckAssign.ets | 1 - ...w_function_call_as_record_property_key.ets | 36 +- .../compiler/ets/circular_variable_init.ets | 2 +- ets2panda/test/ast/parser/ets/enum30.ets | 2 +- .../ets/boxingConversion3-expected.txt | 73 +- .../test/compiler/ets/boxingConversion3.ets | 4 +- .../ets/boxingConversion6-expected.txt | 73 +- .../test/compiler/ets/boxingConversion6.ets | 2 +- .../ets/boxingConversion7-expected.txt | 268 +- .../test/compiler/ets/boxingConversion7.ets | 8 +- .../ets/conversion-w-ASExpr-expected.txt | 81 +- .../test/compiler/ets/conversion-w-ASExpr.ets | 2 +- .../ets/forUpdateCharType-expected.txt | 254 +- .../test/compiler/ets/forUpdateCharType.ets | 2 +- .../ets/implicit-conversion-expected.txt | 108 +- .../test/compiler/ets/implicit-conversion.ets | 2 +- .../test/parser/ets/StringBase64-expected.txt | 2192 ++++++++++++----- ets2panda/test/parser/ets/StringBase64.ets | 18 +- .../parser/ets/cast_expressions-expected.txt | 162 +- .../test/parser/ets/cast_expressions.ets | 4 +- .../conditionalExpressionType-expected.txt | 1043 +++++++- .../parser/ets/conditionalExpressionType.ets | 6 +- .../test/parser/ets/conversions-expected.txt | 145 +- ets2panda/test/parser/ets/conversions.ets | 4 +- .../parser/ets/this_cmp_object-expected.txt | 48 +- .../ets-runtime/ets-runtime-excluded.txt | 14 + ets2panda/util/diagnostic/semantic.yaml | 14 +- 37 files changed, 4934 insertions(+), 2206 deletions(-) create mode 100644 ets2panda/test/test-lists/ets-runtime/ets-runtime-excluded.txt diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index b76c779b5a..cb6480b1d8 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -116,6 +116,7 @@ static Type *EffectivePrimitiveTypeOfNumericOp(ETSChecker *checker, Type *left, if (left->IsLongType() || right->IsLongType()) { return checker->GlobalLongType(); } + // NOTE(dkofanov): Deprecated operations on 'char' #28006 if (left->IsCharType() && right->IsCharType()) { return checker->GlobalCharType(); } @@ -166,6 +167,7 @@ static Type *EffectiveTypeOfNumericOp(ETSChecker *checker, Type *left, Type *rig return globalTypesHolder->GlobalIntegerBuiltinType(); // return Int for Byte, Short, Int } +// NOTE(dkofanov): Deprecated operations on 'char' #28006 static Type *BinaryGetPromotedType(ETSChecker *checker, Type *left, Type *right, bool const promote) { Type *const unboxedL = TryConvertToPrimitiveType(checker, left); @@ -446,6 +448,7 @@ checker::Type *ETSChecker::CheckBinaryOperatorPlus( return nullptr; } +// NOTE(dkofanov): Deprecated operations on 'char' #28006 checker::Type *ETSChecker::CheckBinaryOperatorShift( std::tuple op, bool isEqualOp, std::tuple types) @@ -493,6 +496,7 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift( return nullptr; } +// NOTE(dkofanov): Deprecated operations on 'char' #28006 checker::Type *ETSChecker::CheckBinaryOperatorBitwise( std::tuple op, bool isEqualOp, std::tuple types) @@ -758,6 +762,7 @@ static bool NonNumericTypesAreAppropriateForComparison(ETSChecker *checker, Type return false; } +// NOTE(dkofanov): Deprecated operations on 'char' #28006 std::tuple ETSChecker::CheckBinaryOperatorLessGreater(ir::Expression *left, ir::Expression *right, lexer::TokenType operationType, lexer::SourcePosition pos, bool isEqualOp, diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index d7eb47097e..7fbc5c949d 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -398,11 +398,13 @@ Type *ETSChecker::GetUnaryOperatorPromotedType(Type *type, const bool doPromotio if (doPromotion) { if (type == globalTypesHolder->GlobalByteBuiltinType() || type == globalTypesHolder->GlobalShortBuiltinType() || - type == globalTypesHolder->GlobalCharBuiltinType() || + type == + globalTypesHolder->GlobalCharBuiltinType() || // NOTE(dkofanov): Deprecated operations on 'char' #28006 type == globalTypesHolder->GlobalIntegerBuiltinType()) { return GlobalIntBuiltinType(); } + // NOTE(dkofanov): Deprecated operations on 'char' #28006 if (type->IsIntType() || type->IsByteType() || type->IsShortType() || type->IsCharType()) { return GlobalIntBuiltinType(); } diff --git a/ets2panda/checker/ets/validateHelpers.cpp b/ets2panda/checker/ets/validateHelpers.cpp index a0bf21d4d2..5d0cc4ef8b 100644 --- a/ets2panda/checker/ets/validateHelpers.cpp +++ b/ets2panda/checker/ets/validateHelpers.cpp @@ -249,8 +249,9 @@ void ETSChecker::ValidateUnaryOperatorOperand(varbinder::Variable *variable, ir: return; } if (!HasStatus(CheckerStatus::IN_CONSTRUCTOR | CheckerStatus::IN_STATIC_BLOCK)) { - std::ignore = TypeError(variable, diagnostic::FIELD_ASSIGN_TYPE_MISMATCH, {fieldType, variable->Name()}, - expr->Start()); + const auto &diagKind = variable->Declaration()->IsConstDecl() ? diagnostic::FIELD_ASSIGN_TO_CONST + : diagnostic::FIELD_ASSIGN_TO_READONLY; + std::ignore = TypeError(variable, diagKind, {variable->Name()}, expr->Start()); } if (variable->HasFlag(varbinder::VariableFlags::INIT_IN_STATIC_BLOCK)) { diff --git a/ets2panda/checker/ets/wideningConverter.h b/ets2panda/checker/ets/wideningConverter.h index 163f5545e0..6d7f4088f7 100644 --- a/ets2panda/checker/ets/wideningConverter.h +++ b/ets2panda/checker/ets/wideningConverter.h @@ -34,6 +34,7 @@ public: } private: + // NOTE(dkofanov): Deprecated operations on 'char' #28006 static constexpr TypeFlag WIDENABLE_TO_SHORT = TypeFlag::BYTE; static constexpr TypeFlag WIDENABLE_TO_CHAR = TypeFlag::BYTE; static constexpr TypeFlag WIDENABLE_TO_INT = TypeFlag::CHAR | TypeFlag::SHORT | WIDENABLE_TO_SHORT; @@ -44,6 +45,7 @@ private: void ApplyGlobalWidening() { switch (ETSChecker::ETSChecker::ETSType(Target())) { + // NOTE(dkofanov): Deprecated operations on 'char' #28006 case TypeFlag::CHAR: { ApplyGlobalWidening(WIDENABLE_TO_CHAR); break; @@ -91,14 +93,15 @@ private: Relation()->GetNode()->SetTsType(Checker()->GlobalShortBuiltinType()); break; } - case TypeFlag::CHAR: { - Relation()->GetNode()->SetTsType(Checker()->GlobalCharBuiltinType()); - break; - } case TypeFlag::INT: { Relation()->GetNode()->SetTsType(Checker()->GlobalIntBuiltinType()); break; } + // NOTE(dkofanov): Deprecated operations on 'char' #28006 + case TypeFlag::CHAR: { + Relation()->GetNode()->SetTsType(Checker()->GlobalCharBuiltinType()); + break; + } case TypeFlag::LONG: { Relation()->GetNode()->SetTsType(Checker()->GlobalLongBuiltinType()); break; diff --git a/ets2panda/checker/types/typeFlag.h b/ets2panda/checker/types/typeFlag.h index 5f01ae8225..5b5adf82a5 100644 --- a/ets2panda/checker/types/typeFlag.h +++ b/ets2panda/checker/types/typeFlag.h @@ -95,7 +95,7 @@ enum class TypeFlag : uint64_t { ETS_INTEGRAL = ETS_INTEGRAL_NUMERIC | CHAR, ETS_ENUM = ETS_INT_ENUM | ETS_STRING_ENUM, ETS_ARRAY_INDEX = BYTE | SHORT | INT, - ETS_CONVERTIBLE_TO_NUMERIC = ETS_NUMERIC | CHAR | ETS_INT_ENUM, + ETS_CONVERTIBLE_TO_NUMERIC = ETS_NUMERIC | CHAR | ETS_INT_ENUM, // NOTE char should be removed VALID_SWITCH_TYPE = ETS_INTEGRAL, ETS_ARRAY_OR_OBJECT = ETS_ARRAY | ETS_OBJECT, ANY_OR_UNKNOWN = ANY | UNKNOWN, diff --git a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp index 1667cf0370..bf15a90728 100644 --- a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp @@ -22,84 +22,45 @@ #include "ir/expressions/literals/undefinedLiteral.h" #include "compiler/lowering/scopesInit/scopesInitPhase.h" #include "util/helpers.h" +#include "libpandabase/utils/small_vector.h" namespace ark::es2panda::compiler { -constexpr static char32_t MAX_CHAR = 0xFFFF; +enum class TypeRank { + // Keep this order + INT8, + INT16, + INT32, + INT64, + FLOAT, + DOUBLE +}; -static ir::BooleanLiteral *CreateBooleanLiteral(bool val, ir::AstNode *parent, const lexer::SourceRange &loc, - ArenaAllocator *allocator) +static ir::PrimitiveType GetPrimitiveType(const lexer::Number &number) { - auto resNode = util::NodeAllocator::Alloc(allocator, val); - resNode->SetParent(parent); - resNode->SetRange(loc); - resNode->SetFolded(); - return resNode; -} - -template -static ir::NumberLiteral *CreateNumberLiteral(T val, ir::AstNode *parent, const lexer::SourceRange &loc, - ArenaAllocator *allocator) -{ - auto resNum = lexer::Number(val); - - auto *resNode = util::NodeAllocator::Alloc(allocator, resNum); - - // Some hack to set string representation of lexer::Number - resNode->Number().SetStr(util::UString(resNode->ToString(), allocator).View()); - - resNode->SetParent(parent); - resNode->SetRange(loc); - resNode->SetFolded(); - return resNode; -} - -static ir::Identifier *CreateErrorIdentifier(const ir::AstNode *node, ArenaAllocator *allocator) -{ - // Creating Identifier without passing any arguments leads to creating Error Identifier with *ERROR_LITERAL* - auto res = util::NodeAllocator::Alloc(allocator, allocator); - - res->SetParent(const_cast(node)->Parent()); - res->SetRange(node->Range()); - return res; -} - -static ir::CharLiteral *CreateCharLiteral(char16_t val, ir::AstNode *parent, const lexer::SourceRange &loc, - ArenaAllocator *allocator) -{ - auto *result = util::NodeAllocator::Alloc(allocator, val); - result->SetParent(parent); - result->SetRange(loc); - result->SetFolded(); - return result; -} - -static ir::PrimitiveType TypeRankToPrimitiveType(TypeRank tr) -{ - switch (tr) { - case TypeRank::CHAR: - return ir::PrimitiveType::CHAR; - case TypeRank::INT8: - return ir::PrimitiveType::BYTE; - case TypeRank::INT16: - return ir::PrimitiveType::SHORT; - case TypeRank::INT32: - return ir::PrimitiveType::INT; - case TypeRank::INT64: - return ir::PrimitiveType::LONG; - case TypeRank::FLOAT: - return ir::PrimitiveType::FLOAT; - case TypeRank::DOUBLE: - return ir::PrimitiveType::DOUBLE; + if (number.IsByte()) { + return ir::PrimitiveType::BYTE; + } + if (number.IsShort()) { + return ir::PrimitiveType::SHORT; + } + if (number.IsInt()) { + return ir::PrimitiveType::INT; + } + if (number.IsLong()) { + return ir::PrimitiveType::LONG; + } + if (number.IsFloat()) { + return ir::PrimitiveType::FLOAT; + } + if (number.IsDouble()) { + return ir::PrimitiveType::DOUBLE; } ES2PANDA_UNREACHABLE(); } static TypeRank GetTypeRank(const ir::Literal *literal) { - if (literal->IsCharLiteral()) { - return TypeRank::CHAR; - } if (literal->IsNumberLiteral()) { auto number = literal->AsNumberLiteral()->Number(); if (number.IsByte()) { @@ -132,11 +93,6 @@ static TargetType GetVal(const ir::Literal *node) return node->AsBooleanLiteral()->Value(); } - if constexpr (std::is_same_v) { - ES2PANDA_ASSERT(node->IsCharLiteral()); - return node->AsCharLiteral()->Char(); - } - ES2PANDA_ASSERT(node->IsNumberLiteral()); auto numNode = node->AsNumberLiteral(); @@ -167,6 +123,55 @@ static TargetType GetVal(const ir::Literal *node) ES2PANDA_UNREACHABLE(); } +static bool IsConvertibleToNumericType(const ir::Literal *lit) +{ + return lit->IsNumberLiteral(); +} + +static bool IsBitwiseLogicalExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_BITWISE_XOR || opType == lexer::TokenType::PUNCTUATOR_BITWISE_AND || + opType == lexer::TokenType::PUNCTUATOR_BITWISE_OR; +} + +static bool IsAdditiveExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + + return opType == lexer::TokenType::PUNCTUATOR_PLUS || opType == lexer::TokenType::PUNCTUATOR_MINUS; +} +static bool IsMultiplicativeExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_MULTIPLY || opType == lexer::TokenType::PUNCTUATOR_DIVIDE || + opType == lexer::TokenType::PUNCTUATOR_MOD; +} + +static bool IsRelationalExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_GREATER_THAN || + opType == lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL || + opType == lexer::TokenType::PUNCTUATOR_LESS_THAN || opType == lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL || + opType == lexer::TokenType::PUNCTUATOR_EQUAL || opType == lexer::TokenType::PUNCTUATOR_NOT_EQUAL || + opType == lexer::TokenType::PUNCTUATOR_STRICT_EQUAL || + opType == lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL; +} + +static bool IsShiftExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT || opType == lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT || + opType == lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT; +} + +static bool IsLogicalExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND || opType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR; +} + template static To CastValTo(const ir::Literal *lit) { @@ -174,7 +179,7 @@ static To CastValTo(const ir::Literal *lit) return static_cast(GetVal(lit)); } - ES2PANDA_ASSERT(lit->IsNumberLiteral() || lit->IsCharLiteral()); + ES2PANDA_ASSERT(lit->IsNumberLiteral()); auto rank = GetTypeRank(lit); switch (rank) { @@ -190,970 +195,918 @@ static To CastValTo(const ir::Literal *lit) return static_cast(GetVal(lit)); case TypeRank::INT8: return static_cast(GetVal(lit)); - case TypeRank::CHAR: - return static_cast(GetVal(lit)); } ES2PANDA_UNREACHABLE(); } -static bool IsConvertibleToNumericType(const ir::Literal *lit) -{ - return lit->IsCharLiteral() || lit->IsNumberLiteral(); -} - -static void LogError(public_lib::Context *context, const diagnostic::DiagnosticKind &diagnostic, - const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos) -{ - context->diagnosticEngine->LogDiagnostic(diagnostic, diagnosticParams, pos); -} - -static bool IsCorrectNumberLiteral(const ir::AstNode *lit) +static bool TestLiteral(const ir::Literal *lit) { - if (!lit->IsNumberLiteral()) { - return false; + // 15.10.1 Extended Conditional Expression + if (lit->IsBooleanLiteral()) { + return lit->AsBooleanLiteral()->Value(); } - - return !lit->AsNumberLiteral()->Number().ConversionError(); -} - -static bool IsSupportedLiteral(ir::Expression *const node) -{ - if (!node->IsLiteral()) { - return false; + if (lit->IsStringLiteral()) { + return !lit->AsStringLiteral()->Str().Empty(); } - - auto literal = node->AsLiteral(); - return IsCorrectNumberLiteral(literal) || literal->IsCharLiteral() || literal->IsBooleanLiteral() || - literal->IsStringLiteral(); -} - -template -static ir::AstNode *CommonCastNumberLiteralTo(const ir::Literal *num, ArenaAllocator *allocator) -{ - auto parent = const_cast(num)->Parent(); - - if constexpr (std::is_same_v) { - return CreateCharLiteral(CastValTo(num), parent, num->Range(), allocator); + if (lit->IsCharLiteral()) { + return lit->AsCharLiteral()->Char() != 0; } - - return CreateNumberLiteral(CastValTo(num), parent, num->Range(), allocator); + if (lit->IsNumberLiteral()) { + return !lit->AsNumberLiteral()->Number().IsZero(); + } + ES2PANDA_UNREACHABLE(); } -template -static ir::AstNode *FloatingPointNumberLiteralCast(const ir::Literal *num, public_lib::Context *context) +template +static lexer::Number HandleBitwiseNegate(InputType value, TypeRank rank) { - if (sizeof(From) > sizeof(To)) { - // double -> float - auto doubleVal = GetVal(num); - if (doubleVal < std::numeric_limits::min() || doubleVal > std::numeric_limits::max()) { - LogError(context, diagnostic::CONSTANT_VALUE_OUT_OF_RANGE, {}, num->Start()); - return const_cast(num); + switch (rank) { + case TypeRank::DOUBLE: + case TypeRank::INT64: { + return lexer::Number(static_cast(~static_cast(value))); } - - auto floatVal = static_cast(doubleVal); - if (static_cast(floatVal) == doubleVal) { - auto parent = const_cast(num)->Parent(); - return CreateNumberLiteral(floatVal, parent, num->Range(), context->allocator); + case TypeRank::FLOAT: + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: { + return lexer::Number(static_cast(~static_cast(value))); + } + default: { + ES2PANDA_UNREACHABLE(); } - - LogError(context, diagnostic::CONSTANT_FLOATING_POINT_COVERSION, {}, num->Start()); - return const_cast(num); } - - // float -> double - return CommonCastNumberLiteralTo(num, context->allocator); } -template -static ir::AstNode *NarrowingNumberLiteralCast(const ir::Literal *num, public_lib::Context *context) +static double CalculateFloatZeroDevision(double leftNum) { - auto maxTo = std::numeric_limits::max(); - auto minTo = std::numeric_limits::min(); - auto val = GetVal(num); - if (val < minTo || val > maxTo) { - LogError(context, diagnostic::CONSTANT_VALUE_OUT_OF_RANGE, {}, num->Start()); - return const_cast(num); + if (leftNum == 0.0) { + return std::numeric_limits::quiet_NaN(); } - - return CommonCastNumberLiteralTo(num, context->allocator); + if (leftNum > 0) { + return std::numeric_limits::infinity(); + } + return -std::numeric_limits::infinity(); } -template -static ir::AstNode *IntegralNumberLiteralCast(const ir::Literal *num, public_lib::Context *context) -{ - if (sizeof(From) > sizeof(To)) { - return NarrowingNumberLiteralCast(num, context); +class NodeCalculator { +public: + using DAGNode = ConstantExpressionLoweringImpl::DAGNode; + + NodeCalculator(public_lib::Context *ctx, size_t sz) : context_ {ctx}, inputs_ {} + { + inputs_.resize(sz); + } + void SetInput(ir::Literal *node, size_t i) + { + ES2PANDA_ASSERT(i < inputs_.size()); + inputs_[i] = node; } - // Widening - return CommonCastNumberLiteralTo(num, context->allocator); -} + ir::Literal *Calculate(DAGNode *node); -template -static ir::AstNode *CastNumberOrCharLiteralFromTo(const ir::Literal *num, public_lib::Context *context) -{ - if constexpr (std::is_same_v) { - return const_cast(num); +private: + ir::Literal *SubstituteConstant() + { + ES2PANDA_ASSERT(inputs_.size() == 1); + return inputs_[0]->Clone(context_->allocator, nullptr)->AsExpression()->AsLiteral(); } - if constexpr (std::is_floating_point_v && std::is_floating_point_v) { - return FloatingPointNumberLiteralCast(num, context); + ir::Literal *SubstituteConstantConditionally() + { + ES2PANDA_ASSERT(inputs_.size() == 3U); + const auto *test = inputs_[0]; + auto *conseq = inputs_[1]; + auto *altern = inputs_[2U]; + auto res = TestLiteral(test) ? conseq : altern; + auto resNode = res->Clone(context_->allocator, nullptr)->AsExpression()->AsLiteral(); + return resNode; } - if constexpr (std::is_integral_v && std::is_integral_v) { - return IntegralNumberLiteralCast(num, context); - } + // NOTE(dkofanov) Template literals will be simplified only if each subexpression is constant. + // It may worth to handle partial-simplification, e.g. after the algorithm stops. + ir::Literal *Calculate(ir::TemplateLiteral *expr) + { + auto allocator = context_->allocator; + auto litToString = [allocator](const ir::Literal *lit) { + if (lit->IsNumberLiteral()) { + return util::UString(lit->AsNumberLiteral()->ToString(), allocator).View(); + } + if (lit->IsBooleanLiteral()) { + return util::UString(lit->AsBooleanLiteral()->ToString(), allocator).View(); + } + if (lit->IsStringLiteral()) { + return lit->AsStringLiteral()->Str(); + } + ES2PANDA_UNREACHABLE(); + }; - if constexpr (std::is_integral_v && std::is_floating_point_v) { - // integral -> floating point (widening) - return CommonCastNumberLiteralTo(num, context->allocator); - } + util::UString result(allocator); + auto quasis = expr->Quasis(); + + auto const num = std::max(inputs_.size(), quasis.size()); + for (std::size_t i = 0U; i < num; i++) { + if (i < quasis.size()) { + result.Append(quasis[i]->Cooked()); + } + if (i < inputs_.size()) { + if (inputs_[i]->IsCharLiteral()) { + LogError(diagnostic::CHAR_TO_STR_CONVERSION, {}, expr->Start()); + } + result.Append(litToString(inputs_[i])); + } + } - if constexpr (std::is_floating_point_v && std::is_integral_v) { - // Constant narrowing floating point conversion is not permitted - LogError(context, diagnostic::CONSTANT_FLOATING_POINT_COVERSION, {}, num->Start()); - return const_cast(num); + return util::NodeAllocator::Alloc(allocator, result.View()); } - ES2PANDA_UNREACHABLE(); -} + template + ir::Literal *FoldUnaryNumericConstantHelper(const ir::UnaryExpression *unary, const ir::Literal *node, + TypeRank rank) + { + auto value = CastValTo(node); -template -static ir::AstNode *CastNumberOrCharLiteralFrom(const ir::Literal *lit, ir::PrimitiveType type, - public_lib::Context *context) -{ - switch (type) { - case ir::PrimitiveType::BOOLEAN: - // Note: we do nothing for `class A {b5 : boolean = 7;}` here, type error will be thrown in checker. - return const_cast(lit); - case ir::PrimitiveType::CHAR: - return CastNumberOrCharLiteralFromTo(lit, context); - case ir::PrimitiveType::BYTE: - return CastNumberOrCharLiteralFromTo(lit, context); - case ir::PrimitiveType::SHORT: - return CastNumberOrCharLiteralFromTo(lit, context); - case ir::PrimitiveType::INT: - return CastNumberOrCharLiteralFromTo(lit, context); - case ir::PrimitiveType::LONG: - return CastNumberOrCharLiteralFromTo(lit, context); - case ir::PrimitiveType::FLOAT: - return CastNumberOrCharLiteralFromTo(lit, context); - case ir::PrimitiveType::DOUBLE: - return CastNumberOrCharLiteralFromTo(lit, context); - default: - ES2PANDA_UNREACHABLE(); - } -} + lexer::Number resNum {}; + switch (unary->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_PLUS: { + resNum = lexer::Number(value); + break; + } + case lexer::TokenType::PUNCTUATOR_MINUS: { + resNum = lexer::Number(-value); + break; + } + case lexer::TokenType::PUNCTUATOR_TILDE: { + resNum = std::move(HandleBitwiseNegate(value, rank)); + break; + } + default: { + ES2PANDA_UNREACHABLE(); + } + } -static ir::AstNode *CorrectNumberOrCharLiteral(const ir::Literal *lit, ir::PrimitiveType type, - public_lib::Context *context) -{ - if (TypeRankToPrimitiveType(GetTypeRank(lit)) == type) { - return const_cast(lit); + return CreateNumberLiteral(resNum); } - switch (GetTypeRank(lit)) { - case TypeRank::CHAR: - return CastNumberOrCharLiteralFrom(lit, type, context); - case TypeRank::INT8: - return CastNumberOrCharLiteralFrom(lit, type, context); - case TypeRank::INT16: - return CastNumberOrCharLiteralFrom(lit, type, context); - case TypeRank::INT32: - return CastNumberOrCharLiteralFrom(lit, type, context); - case TypeRank::INT64: - return CastNumberOrCharLiteralFrom(lit, type, context); - case TypeRank::FLOAT: - return CastNumberOrCharLiteralFrom(lit, type, context); - case TypeRank::DOUBLE: - return CastNumberOrCharLiteralFrom(lit, type, context); - default: - ES2PANDA_UNREACHABLE(); - } -} + ir::Literal *FoldUnaryNumericConstant(const ir::UnaryExpression *unary, ir::Literal *literal) + { + TypeRank rank = GetTypeRank(literal); -ir::TypeNode *GetTypeAnnotationFromVarDecl(const ir::Literal *lit) -{ - auto *parent = lit->Parent(); - if (!parent->IsVariableDeclarator()) { - return nullptr; - } - auto vd = parent->AsVariableDeclarator(); - if (!vd->Id()->IsIdentifier()) { - return nullptr; + switch (rank) { + case TypeRank::DOUBLE: { + return FoldUnaryNumericConstantHelper(unary, literal, rank); + } + case TypeRank::FLOAT: { + return FoldUnaryNumericConstantHelper(unary, literal, rank); + } + case TypeRank::INT64: { + return FoldUnaryNumericConstantHelper(unary, literal, rank); + } + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: { + return FoldUnaryNumericConstantHelper(unary, literal, rank); + } + default: { + ES2PANDA_UNREACHABLE(); + } + } } - return vd->Id()->AsIdentifier()->TypeAnnotation(); -} -static ir::PrimitiveType GetRightTypeOfNumberOrCharLiteral(const ir::Literal *lit) -{ - auto *parent = lit->Parent(); - if (parent->IsVariableDeclarator()) { - auto vb = parent->AsVariableDeclarator(); - if (!vb->Id()->IsIdentifier()) { - return TypeRankToPrimitiveType(GetTypeRank(lit)); + ir::Literal *Calculate(ir::UnaryExpression *unary) + { + ES2PANDA_ASSERT(inputs_.size() == 1); + if (unary->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) { + return CreateBooleanLiteral(!TestLiteral(inputs_[0])); } - if (vb->Id()->AsIdentifier()->TypeAnnotation() == nullptr) { - return TypeRankToPrimitiveType(GetTypeRank(lit)); + auto lit = inputs_[0]; + if (lit->IsNumberLiteral()) { + return FoldUnaryNumericConstant(unary, lit); } - if (vb->Id()->AsIdentifier()->TypeAnnotation()->IsETSPrimitiveType()) { - return vb->Id()->AsIdentifier()->TypeAnnotation()->AsETSPrimitiveType()->GetPrimitiveType(); - } - } else if (parent->IsClassProperty()) { - auto cp = parent->AsClassProperty(); - if (cp->TypeAnnotation() == nullptr) { - return TypeRankToPrimitiveType(GetTypeRank(lit)); - } + LogError(diagnostic::WRONG_OPERAND_TYPE_FOR_UNARY_EXPRESSION, {}, unary->Start()); + return nullptr; + } - if (cp->TypeAnnotation()->IsETSPrimitiveType()) { - return cp->TypeAnnotation()->AsETSPrimitiveType()->GetPrimitiveType(); + template + ir::Literal *PerformMultiplicativeOperation(TargetType leftNum, TargetType rightNum, + const ir::BinaryExpression *expr) + { + auto isForbiddenZeroDivision = [&rightNum]() { return std::is_integral_v && rightNum == 0; }; + auto isFloatZeroDevision = [&rightNum]() { return std::is_floating_point_v && rightNum == 0; }; + auto opType = expr->OperatorType(); + TargetType resNum {}; + switch (opType) { + case lexer::TokenType::PUNCTUATOR_MULTIPLY: { + resNum = leftNum * rightNum; + break; + } + case lexer::TokenType::PUNCTUATOR_DIVIDE: { + if (isForbiddenZeroDivision()) { + LogError(diagnostic::DIVISION_BY_ZERO, {}, expr->Start()); + // Max integral value + resNum = std::numeric_limits::max(); + break; + } + if (isFloatZeroDevision()) { + resNum = CalculateFloatZeroDevision(leftNum); + break; + } + + ES2PANDA_ASSERT(rightNum != 0); + // CC-OFFNXT(G.EXP.22-CPP) false positive + resNum = leftNum / rightNum; + break; + } + case lexer::TokenType::PUNCTUATOR_MOD: { + if (isForbiddenZeroDivision()) { + LogError(diagnostic::DIVISION_BY_ZERO, {}, expr->Start()); + // Max integral value + resNum = std::numeric_limits::max(); + break; + } + if constexpr (std::is_integral_v) { + resNum = leftNum % rightNum; + break; + } else { + resNum = std::fmod(leftNum, rightNum); + break; + } + } + default: + ES2PANDA_UNREACHABLE(); } + return CreateNumberLiteral(resNum); } - return TypeRankToPrimitiveType(GetTypeRank(lit)); -} - -static ir::AstNode *TryToCorrectNumberOrCharLiteral(ir::AstNode *node, public_lib::Context *context) -{ - if (IsCorrectNumberLiteral(node) || node->IsCharLiteral()) { - auto lit = node->AsExpression()->AsLiteral(); - return CorrectNumberOrCharLiteral(lit, GetRightTypeOfNumberOrCharLiteral(lit), context); + ir::Literal *HandleMultiplicativeExpression(const ir::BinaryExpression *expr, const ir::Literal *left, + const ir::Literal *right) + { + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); + switch (targetRank) { + case TypeRank::DOUBLE: { + return PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr); + } + case TypeRank::FLOAT: { + return PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr); + } + case TypeRank::INT64: { + return PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr); + } + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: { + return PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr); + } + default: + ES2PANDA_UNREACHABLE(); + } } - return node; -} - -// NOLINTBEGIN(readability-else-after-return) -static bool TestLiteral(const ir::Literal *lit) -{ - // 15.10.1 Extended Conditional Expression - if (lit->IsBooleanLiteral()) { - return lit->AsBooleanLiteral()->Value(); - } - if (lit->IsStringLiteral()) { - return !lit->AsStringLiteral()->Str().Empty(); - } - if (lit->IsCharLiteral()) { - return lit->AsCharLiteral()->Char() != 0; - } - if (lit->IsNumberLiteral()) { - return !lit->AsNumberLiteral()->Number().IsZero(); + template + ir::Literal *PerformAdditiveOperation(TargetType left, TargetType right, lexer::TokenType opType) + { + TargetType res {}; + if constexpr (std::is_floating_point_v) { + switch (opType) { + case lexer::TokenType::PUNCTUATOR_PLUS: + res = left + right; + break; + case lexer::TokenType::PUNCTUATOR_MINUS: + res = left - right; + break; + default: + ES2PANDA_UNREACHABLE(); + } + } else { + // Integral types + // try bit cast to unsigned counterpart to avoid signed integer overflow + auto uLeft = bit_cast, TargetType>(left); + auto uRight = bit_cast, TargetType>(right); + + switch (opType) { + case lexer::TokenType::PUNCTUATOR_PLUS: + res = bit_cast>(uLeft + uRight); + break; + case lexer::TokenType::PUNCTUATOR_MINUS: + res = bit_cast>(uLeft - uRight); + break; + default: + ES2PANDA_UNREACHABLE(); + } + } + return CreateNumberLiteral(res); } - ES2PANDA_UNREACHABLE(); -} -// NOLINTEND(readability-else-after-return) - -ir::AstNode *ConstantExpressionLowering::FoldTernaryConstant(ir::ConditionalExpression *cond) -{ - auto const test = cond->Test()->AsLiteral(); - auto res = TestLiteral(test) ? cond->Consequent() : cond->Alternate(); - auto resNode = res->Clone(context_->allocator, cond->Parent()); - auto *scope = NearestScope(resNode->Parent()); - auto localCtx = varbinder::LexicalScope::Enter(varbinder_, scope); - InitScopesPhaseETS::RunExternalNode(resNode, varbinder_); - resNode->SetRange(cond->Range()); - return resNode; -} -template -static bool PerformRelationOperation(InputType left, InputType right, lexer::TokenType opType) -{ - switch (opType) { - case lexer::TokenType::PUNCTUATOR_GREATER_THAN: { - return left > right; - } - case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: { - return left >= right; - } - case lexer::TokenType::PUNCTUATOR_LESS_THAN: { - return left < right; - } - case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: { - return left <= right; - } - case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: - case lexer::TokenType::PUNCTUATOR_EQUAL: { - return left == right; + ir::Literal *HandleNumericAdditiveExpression(const ir::BinaryExpression *expr, const ir::Literal *left, + const ir::Literal *right) + { + auto opType = expr->OperatorType(); + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); + switch (targetRank) { + case TypeRank::DOUBLE: { + return PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); + } + case TypeRank::FLOAT: { + return PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); + } + case TypeRank::INT64: { + return PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); + } + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: { + return PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); + } + default: + ES2PANDA_UNREACHABLE(); } - case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: - case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - return left != right; + } + + ir::Literal *PerformStringAdditiveOperation(const ir::BinaryExpression *expr, const ir::Literal *left, + const ir::Literal *right) + { + if ((expr->OperatorType() != lexer::TokenType::PUNCTUATOR_PLUS) || + (!left->IsStringLiteral() && !right->IsStringLiteral())) { + LogError(diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); + return nullptr; } - default: { - ES2PANDA_UNREACHABLE(); + if (left->IsCharLiteral() || right->IsCharLiteral()) { + LogError(diagnostic::CHAR_TO_STR_CONVERSION, {}, expr->Start()); + return nullptr; } + auto resStr = util::UString(context_->allocator); + auto appendLiteral = [&resStr, allocator = context_->allocator](const ir::Literal *lit) { + if (lit->IsStringLiteral()) { + // No need to create new temporary string (util::UString) for string literal + resStr.Append(lit->AsStringLiteral()->Str()); + return; + } + resStr.Append(util::UString(lit->ToString(), allocator).View()); + }; + + appendLiteral(left); + appendLiteral(right); + + return util::NodeAllocator::Alloc(context_->allocator, resStr.View()); } -} -static ir::AstNode *HandleNumericalRelationalExpression(const ir::BinaryExpression *expr, ArenaAllocator *allocator) -{ - auto left = expr->Left()->AsLiteral(); - auto right = expr->Right()->AsLiteral(); - auto opType = expr->OperatorType(); + template + ir::Literal *PerformShiftOperation(SignedType left, SignedType right, lexer::TokenType opType) + { + using UnsignedType = std::make_unsigned_t; - ES2PANDA_ASSERT(left->IsNumberLiteral() || left->IsCharLiteral()); - ES2PANDA_ASSERT(right->IsNumberLiteral() || right->IsCharLiteral()); + auto uLeft = bit_cast(left); + auto uRight = bit_cast(right); - TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); + auto mask = std::numeric_limits::digits - 1U; + UnsignedType shift = uRight & mask; - bool res = false; - switch (targetRank) { - case TypeRank::DOUBLE: { - res = PerformRelationOperation(CastValTo(left), CastValTo(right), opType); - break; - } - case TypeRank::FLOAT: { - res = PerformRelationOperation(CastValTo(left), CastValTo(right), opType); - break; - } - case TypeRank::INT64: { - res = PerformRelationOperation(CastValTo(left), CastValTo(right), opType); - break; - } - case TypeRank::INT32: - case TypeRank::INT16: - case TypeRank::INT8: - case TypeRank::CHAR: { - res = PerformRelationOperation(CastValTo(left), CastValTo(right), opType); - break; - } - default: { - ES2PANDA_UNREACHABLE(); + SignedType res {}; + switch (opType) { + case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: { + static_assert(sizeof(UnsignedType) == 4 || sizeof(UnsignedType) == 8); + res = bit_cast(uLeft << shift); + break; + } + case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: { + static_assert(sizeof(SignedType) == 4 || sizeof(SignedType) == 8); + res = bit_cast(left >> shift); // NOLINT(hicpp-signed-bitwise) + break; + } + case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: { + static_assert(sizeof(UnsignedType) == 4 || sizeof(UnsignedType) == 8); + res = bit_cast(uLeft >> shift); + break; + } + default: + ES2PANDA_UNREACHABLE(); } + return CreateNumberLiteral(res); } - return CreateBooleanLiteral(res, const_cast(expr)->Parent(), expr->Range(), allocator); -} - -static ir::AstNode *HandleRelationalExpression(const ir::BinaryExpression *expr, public_lib::Context *context) -{ - auto left = expr->Left()->AsLiteral(); - auto right = expr->Right()->AsLiteral(); - auto opType = expr->OperatorType(); + ir::Literal *HandleShiftExpression(const ir::BinaryExpression *expr, const ir::Literal *left, + const ir::Literal *right) + { + auto opType = expr->OperatorType(); - if (IsConvertibleToNumericType(left) && IsConvertibleToNumericType(right)) { - return HandleNumericalRelationalExpression(expr, context->allocator); + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); + switch (targetRank) { + case TypeRank::DOUBLE: + case TypeRank::INT64: { + return PerformShiftOperation(CastValTo(left), CastValTo(right), opType); + } + case TypeRank::FLOAT: + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: { + return PerformShiftOperation(CastValTo(left), CastValTo(right), opType); + } + default: + ES2PANDA_UNREACHABLE(); + } } - if (left->IsStringLiteral() && right->IsStringLiteral()) { - auto res = PerformRelationOperation(left->AsStringLiteral()->Str(), right->AsStringLiteral()->Str(), opType); - return CreateBooleanLiteral(res, const_cast(expr)->Parent(), expr->Range(), - context->allocator); + ir::Literal *PerformRelationOperation(const ir::CharLiteral *left, const ir::CharLiteral *right, + lexer::TokenType opType) + { + bool res {}; + switch (opType) { + case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: + case lexer::TokenType::PUNCTUATOR_EQUAL: { + res = *left == *right; + break; + } + case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: + case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { + res = !(*left == *right); + break; + } + default: { + return nullptr; + } + } + return CreateBooleanLiteral(res); } - if (left->IsBooleanLiteral() && right->IsBooleanLiteral()) { - auto res = PerformRelationOperation(GetVal(left), GetVal(right), opType); - return CreateBooleanLiteral(res, const_cast(expr)->Parent(), expr->Range(), - context->allocator); + template + auto PerformRelationOperation(InputType left, InputType right, lexer::TokenType opType) + { + bool res {}; + switch (opType) { + case lexer::TokenType::PUNCTUATOR_GREATER_THAN: { + res = left > right; + break; + } + case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: { + res = left >= right; + break; + } + case lexer::TokenType::PUNCTUATOR_LESS_THAN: { + res = left < right; + break; + } + case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: { + res = left <= right; + break; + } + case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: + case lexer::TokenType::PUNCTUATOR_EQUAL: { + res = left == right; + break; + } + case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: + case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { + res = left != right; + break; + } + default: { + ES2PANDA_UNREACHABLE(); + } + } + return CreateBooleanLiteral(res); } - LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); - return CreateErrorIdentifier(expr, context->allocator); -} - -static bool IsMultiplicativeExpression(const ir::BinaryExpression *expr) -{ - auto opType = expr->OperatorType(); - return opType == lexer::TokenType::PUNCTUATOR_MULTIPLY || opType == lexer::TokenType::PUNCTUATOR_DIVIDE || - opType == lexer::TokenType::PUNCTUATOR_MOD; -} + ir::Literal *HandleNumericalRelationalExpression(const ir::BinaryExpression *expr, const ir::Literal *left, + const ir::Literal *right) + { + auto opType = expr->OperatorType(); -static bool IsRelationalExpression(const ir::BinaryExpression *expr) -{ - auto opType = expr->OperatorType(); - return opType == lexer::TokenType::PUNCTUATOR_GREATER_THAN || - opType == lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL || - opType == lexer::TokenType::PUNCTUATOR_LESS_THAN || opType == lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL || - opType == lexer::TokenType::PUNCTUATOR_EQUAL || opType == lexer::TokenType::PUNCTUATOR_NOT_EQUAL || - opType == lexer::TokenType::PUNCTUATOR_STRICT_EQUAL || - opType == lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL; -} - -static bool IsAdditiveExpression(const ir::BinaryExpression *expr) -{ - auto opType = expr->OperatorType(); - - return opType == lexer::TokenType::PUNCTUATOR_PLUS || opType == lexer::TokenType::PUNCTUATOR_MINUS; -} + ES2PANDA_ASSERT(left->IsNumberLiteral()); + ES2PANDA_ASSERT(right->IsNumberLiteral()); -static double CalculateFloatZeroDevision(double leftNum) -{ - if (leftNum == 0.0) { - return std::numeric_limits::quiet_NaN(); - } - if (leftNum > 0) { - return std::numeric_limits::infinity(); - } - return -std::numeric_limits::infinity(); -} + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); -template -static TargetType PerformMultiplicativeOperation(TargetType leftNum, TargetType rightNum, - const ir::BinaryExpression *expr, public_lib::Context *context) -{ - auto isForbiddenZeroDivision = [&rightNum]() { return std::is_integral_v && rightNum == 0; }; - auto isFloatZeroDevision = [&rightNum]() { return std::is_floating_point_v && rightNum == 0; }; - auto isIntegralDivideResOverflow = [&rightNum, &leftNum]() { - // Note: Handle corner cases - return std::is_integral_v && leftNum == std::numeric_limits::min() && rightNum == -1; - }; - auto opType = expr->OperatorType(); - switch (opType) { - case lexer::TokenType::PUNCTUATOR_MULTIPLY: { - return leftNum * rightNum; - } - case lexer::TokenType::PUNCTUATOR_DIVIDE: { - if (isForbiddenZeroDivision()) { - LogError(context, diagnostic::DIVISION_BY_ZERO, {}, expr->Start()); - // Max integral value - return std::numeric_limits::max(); + switch (targetRank) { + case TypeRank::DOUBLE: { + return PerformRelationOperation(CastValTo(left), CastValTo(right), opType); } - if (isFloatZeroDevision()) { - return CalculateFloatZeroDevision(leftNum); + case TypeRank::FLOAT: { + return PerformRelationOperation(CastValTo(left), CastValTo(right), opType); } - - ES2PANDA_ASSERT(rightNum != 0); - if (isIntegralDivideResOverflow()) { - return std::numeric_limits::min(); + case TypeRank::INT64: { + return PerformRelationOperation(CastValTo(left), CastValTo(right), opType); } - return leftNum / rightNum; - } - case lexer::TokenType::PUNCTUATOR_MOD: { - if (isForbiddenZeroDivision()) { - LogError(context, diagnostic::DIVISION_BY_ZERO, {}, expr->Start()); - // Max integral value - return std::numeric_limits::max(); + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: { + return PerformRelationOperation(CastValTo(left), CastValTo(right), opType); } - if constexpr (std::is_integral_v) { - return leftNum % rightNum; - } else { - return std::fmod(leftNum, rightNum); + default: { + ES2PANDA_UNREACHABLE(); } } - default: - ES2PANDA_UNREACHABLE(); } -} -static ir::AstNode *HandleMultiplicativeExpression(const ir::BinaryExpression *expr, public_lib::Context *context) -{ - auto left = expr->Left()->AsLiteral(); - auto right = expr->Right()->AsLiteral(); - if (!IsConvertibleToNumericType(left) || !IsConvertibleToNumericType(right)) { - LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); - return CreateErrorIdentifier(expr, context->allocator); - } - - auto allocator = context->allocator; - auto parent = const_cast(expr)->Parent(); - auto loc = expr->Range(); - - TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); - switch (targetRank) { - case TypeRank::DOUBLE: { - double res = - PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr, context); - return CreateNumberLiteral(res, parent, loc, allocator); - } - case TypeRank::FLOAT: { - float res = PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr, context); - return CreateNumberLiteral(res, parent, loc, allocator); + ir::Literal *HandleNonNumericRelationalExpression(const ir::BinaryExpression *expr, const ir::Literal *left, + const ir::Literal *right) + { + auto opType = expr->OperatorType(); + + if (left->IsStringLiteral() && right->IsStringLiteral()) { + return PerformRelationOperation(left->AsStringLiteral()->Str(), right->AsStringLiteral()->Str(), opType); } - case TypeRank::INT64: { - int64_t res = - PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr, context); - return CreateNumberLiteral(res, parent, loc, allocator); + + if (left->IsBooleanLiteral() && right->IsBooleanLiteral()) { + return PerformRelationOperation(GetVal(left), GetVal(right), opType); } - case TypeRank::INT32: - case TypeRank::INT16: - case TypeRank::INT8: - case TypeRank::CHAR: { - int32_t res = - PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr, context); - return CreateNumberLiteral(res, parent, loc, allocator); + + if (left->IsCharLiteral() && right->IsCharLiteral()) { + auto res = PerformRelationOperation(left->AsCharLiteral(), right->AsCharLiteral(), opType); + if (res != nullptr) { + return res; + } } - default: - ES2PANDA_UNREACHABLE(); + + LogError(diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); + return nullptr; } -} -template -static TargetType PerformAdditiveOperation(TargetType left, TargetType right, lexer::TokenType opType) -{ - if constexpr (std::is_floating_point_v) { + template + ir::Literal *PerformBitwiseLogicalOperation(SignedType left, SignedType right, lexer::TokenType opType) + { + using UnsignedType = std::make_unsigned_t; + + auto uLeft = bit_cast(left); + auto uRight = bit_cast(right); + + SignedType res {}; switch (opType) { - case lexer::TokenType::PUNCTUATOR_PLUS: - return left + right; - case lexer::TokenType::PUNCTUATOR_MINUS: - return left - right; + case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { + res = uLeft & uRight; + break; + } + case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { + res = uLeft | uRight; + break; + } + case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { + res = uLeft ^ uRight; + break; + } default: ES2PANDA_UNREACHABLE(); } - } else { - // Integral types - // try bit cast to unsigned counterpart to avoid signed integer overflow - auto uLeft = bit_cast, TargetType>(left); - auto uRight = bit_cast, TargetType>(right); + return CreateNumberLiteral(res); + } - switch (opType) { - case lexer::TokenType::PUNCTUATOR_PLUS: { - return bit_cast>(uLeft + uRight); + ir::Literal *HandleNumericBitwiseLogicalExpression(const ir::BinaryExpression *expr, const ir::Literal *left, + const ir::Literal *right) + { + auto opType = expr->OperatorType(); + + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); + switch (targetRank) { + case TypeRank::DOUBLE: + case TypeRank::INT64: { + return PerformBitwiseLogicalOperation(CastValTo(left), CastValTo(right), opType); } - case lexer::TokenType::PUNCTUATOR_MINUS: { - return bit_cast>(uLeft - uRight); + case TypeRank::FLOAT: + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: { + return PerformBitwiseLogicalOperation(CastValTo(left), CastValTo(right), opType); } default: ES2PANDA_UNREACHABLE(); } } -} -static ir::AstNode *PerformStringAdditiveOperation(const ir::BinaryExpression *expr, public_lib::Context *context) -{ - auto const lhs = expr->Left()->AsLiteral(); - auto const rhs = expr->Right()->AsLiteral(); - auto resStr = util::UString(context->allocator); + ir::Literal *HandleNonNumericBitwiseLogicalExpression(const ir::BinaryExpression *expr, const ir::Literal *left, + const ir::Literal *right) + { + auto opType = expr->OperatorType(); - auto appendLiteral = [&resStr, allocator = context->allocator](const ir::Literal *lit) { - if (lit->IsCharLiteral()) { - resStr.Append(static_cast(lit->AsCharLiteral()->Char()) & MAX_CHAR); - return; - } - if (lit->IsStringLiteral()) { - // No need to create new temporary string (util::UString) for string literal - resStr.Append(lit->AsStringLiteral()->Str()); - return; + if (!left->IsBooleanLiteral() && !right->IsBooleanLiteral()) { + LogError(diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); + return nullptr; } - resStr.Append(util::UString(lit->ToString(), allocator).View()); - }; - - appendLiteral(lhs); - appendLiteral(rhs); - - auto resNode = util::NodeAllocator::Alloc(context->allocator, resStr.View()); - resNode->SetParent(const_cast(expr)->Parent()); - resNode->SetRange(expr->Range()); - return resNode; -} - -static ir::AstNode *HandleAdditiveExpression(const ir::BinaryExpression *expr, public_lib::Context *context) -{ - auto left = expr->Left()->AsLiteral(); - auto right = expr->Right()->AsLiteral(); - auto opType = expr->OperatorType(); - if ((opType == lexer::TokenType::PUNCTUATOR_PLUS) && (left->IsStringLiteral() || right->IsStringLiteral())) { - return PerformStringAdditiveOperation(expr, context); - } - if (!IsConvertibleToNumericType(left) || !IsConvertibleToNumericType(right)) { - LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); - return CreateErrorIdentifier(expr, context->allocator); + bool res = false; + auto leftVal = left->AsBooleanLiteral()->Value(); + auto rightVal = right->AsBooleanLiteral()->Value(); + switch (opType) { + case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { + res = ((static_cast(leftVal) & static_cast(rightVal)) != 0); + break; + } + case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { + res = ((static_cast(leftVal) | static_cast(rightVal)) != 0); + break; + } + case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { + res = leftVal ^ rightVal; + break; + } + default: + ES2PANDA_UNREACHABLE(); + } + return CreateBooleanLiteral(res); } - auto allocator = context->allocator; - auto parent = const_cast(expr)->Parent(); - auto loc = expr->Range(); + ir::Literal *HandleLogicalExpression(const ir::BinaryExpression *expr, const ir::Literal *left, + const ir::Literal *right) + { + bool lhs = TestLiteral(left); + bool rhs = TestLiteral(right); - TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); - switch (targetRank) { - case TypeRank::DOUBLE: { - auto res = PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); - return CreateNumberLiteral(res, parent, loc, allocator); - } - case TypeRank::FLOAT: { - auto res = PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); - return CreateNumberLiteral(res, parent, loc, allocator); - } - case TypeRank::INT64: { - int64_t res = PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); - return CreateNumberLiteral(res, parent, loc, allocator); - } - case TypeRank::INT32: - case TypeRank::INT16: - case TypeRank::INT8: - case TypeRank::CHAR: { - int32_t res = PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); - return CreateNumberLiteral(res, parent, loc, allocator); + bool res {}; + auto opType = expr->OperatorType(); + switch (opType) { + case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: { + res = lhs && rhs; + break; + } + case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { + res = lhs || rhs; + break; + } + default: { + ES2PANDA_UNREACHABLE(); + } } - default: - ES2PANDA_UNREACHABLE(); + return CreateBooleanLiteral(res); } -} - -static bool IsShiftExpression(const ir::BinaryExpression *expr) -{ - auto opType = expr->OperatorType(); - return opType == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT || opType == lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT || - opType == lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT; -} -template -static SignedType PerformShiftOperation(SignedType left, SignedType right, lexer::TokenType opType) -{ - using UnsignedType = std::make_unsigned_t; - - SignedType result = 0; - auto uLeft = bit_cast(left); - auto uRight = bit_cast(right); + ir::Literal *Calculate(const ir::BinaryExpression *expr) + { + ES2PANDA_ASSERT(inputs_.size() == 2U); + auto left = inputs_[0]; + auto right = inputs_[1]; + if (IsLogicalExpression(expr)) { + return HandleLogicalExpression(expr, left, right); + } - auto mask = std::numeric_limits::digits - 1U; - UnsignedType shift = uRight & mask; + if (IsConvertibleToNumericType(left) && IsConvertibleToNumericType(right)) { + if (IsBitwiseLogicalExpression(expr)) { + return HandleNumericBitwiseLogicalExpression(expr, left, right); + } + if (IsMultiplicativeExpression(expr)) { + return HandleMultiplicativeExpression(expr, left, right); + } + if (IsAdditiveExpression(expr)) { + return HandleNumericAdditiveExpression(expr, left, right); + } + if (IsShiftExpression(expr)) { + return HandleShiftExpression(expr, left, right); + } + if (IsRelationalExpression(expr)) { + return HandleNumericalRelationalExpression(expr, left, right); + } + } else { + if (IsAdditiveExpression(expr)) { + return PerformStringAdditiveOperation(expr, left, right); + } + if (IsBitwiseLogicalExpression(expr)) { + return HandleNonNumericBitwiseLogicalExpression(expr, left, right); + } + if (IsRelationalExpression(expr)) { + return HandleNonNumericRelationalExpression(expr, left, right); + } - switch (opType) { - case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: { - static_assert(sizeof(UnsignedType) == 4 || sizeof(UnsignedType) == 8); - return bit_cast(uLeft << shift); - } - case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: { - static_assert(sizeof(SignedType) == 4 || sizeof(SignedType) == 8); - return bit_cast(left >> shift); // NOLINT(hicpp-signed-bitwise) - } - case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: { - static_assert(sizeof(UnsignedType) == 4 || sizeof(UnsignedType) == 8); - return bit_cast(uLeft >> shift); - } - default: - ES2PANDA_UNREACHABLE(); + LogError(diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); + return nullptr; + } + + ES2PANDA_UNREACHABLE(); } - return result; -} -static ir::AstNode *HandleShiftExpression(const ir::BinaryExpression *expr, public_lib::Context *context) -{ - auto left = expr->Left()->AsLiteral(); - auto right = expr->Right()->AsLiteral(); - auto opType = expr->OperatorType(); + void LogError(const diagnostic::DiagnosticKind &diagnostic, const util::DiagnosticMessageParams &diagnosticParams, + const lexer::SourcePosition &pos) + { + context_->diagnosticEngine->LogDiagnostic(diagnostic, diagnosticParams, pos); + } - if (!IsConvertibleToNumericType(left) || !IsConvertibleToNumericType(right)) { - LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); - return CreateErrorIdentifier(expr, context->allocator); + ir::BooleanLiteral *CreateBooleanLiteral(bool val) + { + auto resNode = util::NodeAllocator::Alloc(context_->allocator, val); + ES2PANDA_ASSERT(resNode != nullptr); + resNode->SetFolded(); + return resNode; } - auto allocator = context->allocator; - auto parent = const_cast(expr)->Parent(); - auto loc = expr->Range(); + template + ir::NumberLiteral *CreateNumberLiteral(T val) + { + auto resNum = lexer::Number(val); + auto *resNode = util::NodeAllocator::Alloc(context_->allocator, resNum); + ES2PANDA_ASSERT(resNode != nullptr); - TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); - switch (targetRank) { - case TypeRank::DOUBLE: - case TypeRank::INT64: { - int64_t res = PerformShiftOperation(CastValTo(left), CastValTo(right), opType); - return CreateNumberLiteral(res, parent, loc, allocator); - } - case TypeRank::FLOAT: - case TypeRank::INT32: - case TypeRank::INT16: - case TypeRank::INT8: - case TypeRank::CHAR: { - int32_t res = PerformShiftOperation(CastValTo(left), CastValTo(right), opType); - return CreateNumberLiteral(res, parent, loc, allocator); - } - default: - ES2PANDA_UNREACHABLE(); + // Some hack to set string representation of lexer::Number + resNode->Number().SetStr(util::UString(resNode->ToString(), context_->allocator).View()); + + resNode->SetFolded(); + return resNode; } -} -static bool IsBitwiseLogicalExpression(const ir::BinaryExpression *expr) +private: + public_lib::Context *context_; + SmallVector inputs_; +}; + +template +static bool TryCastInteger(lexer::Number &number) { - auto opType = expr->OperatorType(); - return opType == lexer::TokenType::PUNCTUATOR_BITWISE_XOR || opType == lexer::TokenType::PUNCTUATOR_BITWISE_AND || - opType == lexer::TokenType::PUNCTUATOR_BITWISE_OR; + if (number.CanGetValue()) { + number = lexer::Number(number.GetValue()); + return true; + } + return false; } -template -static SignedType PerformBitwiseLogicalOperation(SignedType left, SignedType right, lexer::TokenType opType) +auto TryExtractPrimitiveType(ir::TypeNode *constraint) { - using UnsignedType = std::make_unsigned_t; - - auto uLeft = bit_cast(left); - auto uRight = bit_cast(right); + if (constraint->IsETSPrimitiveType()) { + return constraint->AsETSPrimitiveType()->GetPrimitiveType(); + } + // NOTE(dkofanov): Check for known primitive type alias. Need to consider a 'number'->'double' lowering. + if (auto typeRef = Cast(constraint); typeRef != nullptr) { + if (auto part = typeRef->Part(); part->Name()->IsIdentifier() && (part->Previous() == nullptr)) { + const static std::map MAP { + {"Number", ir::PrimitiveType::DOUBLE}, {"number", ir::PrimitiveType::DOUBLE}, + {"Double", ir::PrimitiveType::DOUBLE}, {"Float", ir::PrimitiveType::FLOAT}, + {"Long", ir::PrimitiveType::LONG}, {"Int", ir::PrimitiveType::INT}, + {"Short", ir::PrimitiveType::SHORT}, {"Char", ir::PrimitiveType::CHAR}, + {"Byte", ir::PrimitiveType::BYTE}, {"Boolean", ir::PrimitiveType::BOOLEAN}, + }; - switch (opType) { - case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { - return uLeft & uRight; - } - case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { - return uLeft | uRight; - } - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { - return uLeft ^ uRight; + if (auto it = MAP.find(part->Name()->AsIdentifier()->Name().Utf8()); it != MAP.end()) { + return it->second; + } } - default: - ES2PANDA_UNREACHABLE(); } + return ir::PrimitiveType::VOID; } -static ir::AstNode *HandleNumericBitwiseLogicalExpression(const ir::BinaryExpression *expr, - public_lib::Context *context) +static void LogErrorUnconverted(ir::PrimitiveType dst, ir::PrimitiveType src, util::DiagnosticEngine *de, + lexer::SourcePosition pos) { - auto left = expr->Left()->AsLiteral(); - auto right = expr->Right()->AsLiteral(); - auto opType = expr->OperatorType(); - - auto allocator = context->allocator; - auto parent = const_cast(expr)->Parent(); - auto loc = expr->Range(); - - TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); - switch (targetRank) { - case TypeRank::DOUBLE: - case TypeRank::INT64: { - int64_t res = PerformBitwiseLogicalOperation(CastValTo(left), CastValTo(right), opType); - return CreateNumberLiteral(res, parent, loc, allocator); - } - case TypeRank::FLOAT: - case TypeRank::INT32: - case TypeRank::INT16: - case TypeRank::INT8: - case TypeRank::CHAR: { - int32_t res = PerformBitwiseLogicalOperation(CastValTo(left), CastValTo(right), opType); - return CreateNumberLiteral(res, parent, loc, allocator); - } - default: - ES2PANDA_UNREACHABLE(); + if ((dst == ir::PrimitiveType::FLOAT) && (src == ir::PrimitiveType::DOUBLE)) { + de->LogDiagnostic(diagnostic::CONSTANT_FLOATING_POINT_COVERSION, util::DiagnosticMessageParams {}, pos); + } else if (((dst != ir::PrimitiveType::FLOAT) && (dst != ir::PrimitiveType::DOUBLE)) && + ((dst == ir::PrimitiveType::FLOAT) || (dst == ir::PrimitiveType::DOUBLE))) { + de->LogDiagnostic(diagnostic::CONSTANT_FLOATING_POINT_COVERSION, util::DiagnosticMessageParams {}, pos); + } else { + de->LogDiagnostic(diagnostic::CONSTANT_VALUE_OUT_OF_RANGE, util::DiagnosticMessageParams {}, pos); } } -static ir::AstNode *HandleBitwiseLogicalExpression(const ir::BinaryExpression *expr, public_lib::Context *context) +static bool CheckCastLiteral(util::DiagnosticEngine *de, ir::TypeNode *constraint, ir::Literal *literal) { - auto left = expr->Left()->AsLiteral(); - auto right = expr->Right()->AsLiteral(); - auto opType = expr->OperatorType(); - - if (IsConvertibleToNumericType(left) && IsConvertibleToNumericType(right)) { - return HandleNumericBitwiseLogicalExpression(expr, context); + if (literal->IsStringLiteral()) { + return true; } - if (!left->IsBooleanLiteral() && !right->IsBooleanLiteral()) { - LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); - return CreateErrorIdentifier(expr, context->allocator); + auto dst = TryExtractPrimitiveType(constraint); + if (dst == ir::PrimitiveType::VOID) { + // NOTE(dkofanov): ConstFolding supported only for primitives or strings. + return false; } - auto allocator = context->allocator; - auto parent = const_cast(expr)->Parent(); - auto loc = expr->Range(); - bool res = false; + if (literal->IsBooleanLiteral() || literal->IsCharLiteral() || (dst == ir::PrimitiveType::BOOLEAN) || + (dst == ir::PrimitiveType::CHAR)) { + return (literal->IsBooleanLiteral() && (dst == ir::PrimitiveType::BOOLEAN)) || + (literal->IsCharLiteral() && (dst == ir::PrimitiveType::CHAR)); + } - auto leftVal = left->AsBooleanLiteral()->Value(); - auto rightVal = right->AsBooleanLiteral()->Value(); - switch (opType) { - case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { - res = ((static_cast(leftVal) & static_cast(rightVal)) != 0); + auto &number = literal->AsNumberLiteral()->Number(); + bool converted = false; + switch (dst) { + case ir::PrimitiveType::DOUBLE: + converted = TryCastInteger(number); break; - } - case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { - res = ((static_cast(leftVal) | static_cast(rightVal)) != 0); + case ir::PrimitiveType::FLOAT: + converted = TryCastInteger(number); break; - } - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { - res = leftVal ^ rightVal; + case ir::PrimitiveType::LONG: + converted = TryCastInteger(number); + break; + case ir::PrimitiveType::INT: + converted = TryCastInteger(number); + break; + case ir::PrimitiveType::SHORT: + converted = TryCastInteger(number); + break; + case ir::PrimitiveType::BYTE: + converted = TryCastInteger(number); break; - } default: ES2PANDA_UNREACHABLE(); } - return CreateBooleanLiteral(res, parent, loc, allocator); -} - -static bool IsConditionalExpression(const ir::BinaryExpression *expr) -{ - auto opType = expr->OperatorType(); - return opType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND || opType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR; -} - -static ir::AstNode *HandleConditionalExpression(const ir::BinaryExpression *expr, public_lib::Context *context) -{ - auto left = const_cast(expr)->Left()->AsLiteral(); - auto right = const_cast(expr)->Right()->AsLiteral(); - - auto allocator = context->allocator; - auto parent = const_cast(expr)->Parent(); - auto loc = expr->Range(); - bool lhs = TestLiteral(left); - bool rhs = TestLiteral(right); - - auto opType = expr->OperatorType(); - switch (opType) { - case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: { - return CreateBooleanLiteral(lhs && rhs, parent, loc, allocator); - } - case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { - return CreateBooleanLiteral(lhs || rhs, parent, loc, allocator); - } - default: { - ES2PANDA_UNREACHABLE(); - } + if (!converted) { + LogErrorUnconverted(dst, GetPrimitiveType(number), de, constraint->Start()); } - ES2PANDA_UNREACHABLE(); + return converted; } -static ir::AstNode *FoldBinaryExpression(const ir::BinaryExpression *expr, public_lib::Context *context) +static ir::TypeNode *GetTypeAnnotation(ir::AstNode *initParent) { - if (IsMultiplicativeExpression(expr)) { - return HandleMultiplicativeExpression(expr, context); - } - if (IsAdditiveExpression(expr)) { - return HandleAdditiveExpression(expr, context); - } - if (IsShiftExpression(expr)) { - return HandleShiftExpression(expr, context); + if (auto prop = Cast(initParent); prop != nullptr) { + ES2PANDA_ASSERT(prop->Key()->AsIdentifier()->TypeAnnotation() == nullptr); + return prop->TypeAnnotation(); + } else if (auto vardecl = Cast(initParent); vardecl != nullptr) { + return vardecl->Id()->IsIdentifier() ? vardecl->Id()->AsIdentifier()->TypeAnnotation() : nullptr; } - if (IsRelationalExpression(expr)) { - return HandleRelationalExpression(expr, context); - } - if (IsBitwiseLogicalExpression(expr)) { - return HandleBitwiseLogicalExpression(expr, context); - } - if (IsConditionalExpression(expr)) { - return HandleConditionalExpression(expr, context); - } - ES2PANDA_UNREACHABLE(); + return nullptr; } -template -static lexer::Number HandleBitwiseNegate(InputType value, TypeRank rank) +bool ConstantExpressionLoweringImpl::CalculateAndCheck(DAGNode *user) { - switch (rank) { - case TypeRank::DOUBLE: - case TypeRank::INT64: { - return lexer::Number(static_cast(~static_cast(value))); - } - case TypeRank::FLOAT: - case TypeRank::INT32: - case TypeRank::INT16: - case TypeRank::INT8: - case TypeRank::CHAR: { - return lexer::Number(static_cast(~static_cast(value))); - } - default: { - ES2PANDA_UNREACHABLE(); - } + auto *inputsIds = user->InputsIds(); + NodeCalculator nc {context_, inputsIds->size()}; + size_t i = 0; + for (auto inputId : *inputsIds) { + nc.SetInput(DNode(inputId)->Ir()->AsExpression()->AsLiteral(), i++); } -} -template -static ir::AstNode *FoldUnaryNumericConstantHelper(const ir::UnaryExpression *unary, const ir::Literal *node, - TypeRank rank, ArenaAllocator *allocator) -{ - auto value = CastValTo(node); + auto *res = nc.Calculate(user); + ES2PANDA_ASSERT(!res || res->IsLiteral()); - lexer::Number resNum {}; - switch (unary->OperatorType()) { - case lexer::TokenType::PUNCTUATOR_PLUS: { - resNum = lexer::Number(value); - break; - } - case lexer::TokenType::PUNCTUATOR_MINUS: { - resNum = lexer::Number(-value); - break; - } - case lexer::TokenType::PUNCTUATOR_TILDE: { - resNum = std::move(HandleBitwiseNegate(value, rank)); - break; - } - default: { - ES2PANDA_UNREACHABLE(); - } + if (auto constr = GetTypeAnnotation(user->Ir()->Parent()); + !res || ((constr != nullptr) && !CheckCastLiteral(context_->diagnosticEngine, constr, res))) { + user->UsersIds()->clear(); + return false; + } else { + RegisterReplacement(user, res); + return true; } - - ir::TypedAstNode *resNode = util::NodeAllocator::Alloc(allocator, resNum); - resNode->SetParent(const_cast(unary)->Parent()); - resNode->SetRange(unary->Range()); - return resNode; } -static ir::AstNode *FoldUnaryNumericConstant(const ir::UnaryExpression *unary, ArenaAllocator *allocator) +ir::Literal *NodeCalculator::Calculate(DAGNode *node) { - auto literal = unary->Argument()->AsLiteral(); - TypeRank rank = GetTypeRank(literal); - - switch (rank) { - case TypeRank::DOUBLE: { - return FoldUnaryNumericConstantHelper(unary, literal, rank, allocator); - } - case TypeRank::FLOAT: { - return FoldUnaryNumericConstantHelper(unary, literal, rank, allocator); - } - case TypeRank::INT64: { - return FoldUnaryNumericConstantHelper(unary, literal, rank, allocator); - } - case TypeRank::INT32: - case TypeRank::INT16: - case TypeRank::INT8: - case TypeRank::CHAR: { - return FoldUnaryNumericConstantHelper(unary, literal, rank, allocator); - } - default: { + switch (node->Ir()->Type()) { + case ir::AstNodeType::IDENTIFIER: + case ir::AstNodeType::MEMBER_EXPRESSION: + return SubstituteConstant(); + case ir::AstNodeType::CONDITIONAL_EXPRESSION: + return SubstituteConstantConditionally(); + case ir::AstNodeType::UNARY_EXPRESSION: + return Calculate(node->Ir()->AsUnaryExpression()); + case ir::AstNodeType::BINARY_EXPRESSION: + return Calculate(node->Ir()->AsBinaryExpression()); + case ir::AstNodeType::TEMPLATE_LITERAL: + return Calculate(node->Ir()->AsTemplateLiteral()); + default: ES2PANDA_UNREACHABLE(); - } } } -static ir::AstNode *FoldLogicalUnaryExpression(const ir::UnaryExpression *unary, ArenaAllocator *allocator) -{ - auto resNode = - util::NodeAllocator::Alloc(allocator, !TestLiteral(unary->Argument()->AsLiteral())); - ES2PANDA_ASSERT(resNode != nullptr); - resNode->SetParent(const_cast(unary)->Parent()); - resNode->SetRange(unary->Range()); - return resNode; -} - -static ir::AstNode *FoldUnaryExpression(const ir::UnaryExpression *unary, public_lib::Context *context) +static ir::Expression *AsRValue(ir::Identifier *ident) { - if (unary->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) { - return FoldLogicalUnaryExpression(unary, context->allocator); - } - - auto lit = unary->Argument()->AsLiteral(); - if (lit->IsNumberLiteral() || lit->IsCharLiteral()) { - return FoldUnaryNumericConstant(unary, context->allocator); + if (ident == nullptr) { + return nullptr; } - - LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_UNARY_EXPRESSION, {}, unary->Start()); - return CreateErrorIdentifier(unary, context->allocator); -} - -static ir::AstNode *FoldTemplateLiteral(ir::TemplateLiteral *expr, ArenaAllocator *allocator) -{ - auto litToString = [allocator](const ir::Literal *lit) { - if (lit->IsNumberLiteral()) { - return util::UString(lit->AsNumberLiteral()->ToString(), allocator).View(); - } - if (lit->IsCharLiteral()) { - return util::UString(lit->AsCharLiteral()->ToString(), allocator).View(); - } - if (lit->IsBooleanLiteral()) { - return util::UString(lit->AsBooleanLiteral()->ToString(), allocator).View(); - } - if (lit->IsStringLiteral()) { - return lit->AsStringLiteral()->Str(); + ir::Expression *rvnode = ident; + if (auto mexp = Cast(ident->Parent()); mexp != nullptr) { + if (mexp->Property() != ident) { + return nullptr; } - ES2PANDA_UNREACHABLE(); - }; - - util::UString result(allocator); - auto quasis = expr->Quasis(); - auto expressions = expr->Expressions(); - - auto const num = std::max(expressions.size(), quasis.size()); - for (std::size_t i = 0U; i < num; i++) { - if (i < quasis.size()) { - result.Append(quasis[i]->Cooked()); + // NOTE(dkofanov): 'MemberExpressionKind' should be eliminated and 'ir::MemberExpression' should be splitted + // accordingly: + if (mexp->Kind() == ir::MemberExpressionKind::PROPERTY_ACCESS) { + if (auto mexpPar = Cast(mexp->Parent()); mexpPar && (mexpPar->Object() == mexp)) { + return nullptr; + } + rvnode = mexp; } - if (i < expressions.size()) { - result.Append(litToString(expressions[i]->AsLiteral())); + } + if (rvnode->Parent()->IsUnaryExpression() || rvnode->Parent()->IsBinaryExpression() || + rvnode->Parent()->IsConditionalExpression()) { + return rvnode; + } + // A list of contexts in which there will be an attempt to fold ident/mexp. May be revisited. + if (auto vardecl = Cast(rvnode->Parent()); vardecl && vardecl->Init() == rvnode) { + return rvnode; + } + if (auto propdecl = Cast(rvnode->Parent()); propdecl && propdecl->Value() == rvnode) { + return rvnode; + } + if (auto enummemb = Cast(rvnode->Parent()); enummemb && enummemb->Init() == rvnode) { + return rvnode; + } + if (auto casestmt = Cast(rvnode->Parent()); casestmt && casestmt->Test() == rvnode) { + return rvnode; + } + if (auto assignexp = Cast(rvnode->Parent()); assignexp && assignexp->Right() == rvnode) { + return rvnode; + } + if (auto callexp = Cast(rvnode->Parent()); callexp != nullptr) { + if (const auto &args = callexp->Arguments(); std::find(args.begin(), args.end(), rvnode) != args.end()) { + return rvnode; } + return nullptr; } - - auto *strLit = util::NodeAllocator::Alloc(allocator, result.View()); - strLit->SetParent(expr->Parent()); - strLit->SetRange(expr->Range()); - return strLit; + if (auto newarr = Cast(rvnode->Parent()); + newarr && (newarr->Dimension() == rvnode)) { + return rvnode; + } + if (auto indexexp = Cast(rvnode->Parent()); + indexexp && (indexexp->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS) && indexexp->Property() == rvnode) { + return rvnode; + } + return nullptr; } static varbinder::Variable *ResolveIdentifier(const ir::Identifier *ident) @@ -1170,7 +1123,21 @@ static varbinder::Variable *ResolveIdentifier(const ir::Identifier *ident) return resolved; } -static varbinder::Variable *ResolveMemberExpressionProperty(ir::MemberExpression *me) +// NOTE(dkofanov): Remove this check after enum refactoring. +static bool EnumLiteralIsEnumInitializer(const ir::MemberExpression *enumLiteral) +{ + auto parent = enumLiteral->Parent(); + ES2PANDA_ASSERT(!parent->IsTSEnumMember() || (parent->AsTSEnumMember()->Key() != enumLiteral)); + while (parent != nullptr) { + if (parent->IsTSEnumMember()) { + return true; + } + parent = parent->Parent(); + } + return false; +} + +static varbinder::Variable *ResolveMemberExpressionProperty(const ir::MemberExpression *me) { varbinder::Variable *var = nullptr; auto meObject = me->Object(); @@ -1189,20 +1156,17 @@ static varbinder::Variable *ResolveMemberExpressionProperty(ir::MemberExpression if (decl->IsClassDecl()) { // NOTE(gogabr) : for some reason, ETSGLOBAL points to class declaration instead of definition. auto *declNode = decl->AsClassDecl()->Node(); - if (declNode->IsClassDefinition()) { - scope = declNode->AsClassDefinition()->Scope(); - } else if (declNode->IsClassDeclaration()) { - auto *classDef = declNode->AsClassDeclaration()->Definition(); - if (classDef != nullptr) { - // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) - scope = classDef->Scope(); - } - } + auto *classDef = declNode->IsClassDefinition() ? declNode->AsClassDefinition() + : declNode->IsClassDeclaration() ? declNode->AsClassDeclaration()->Definition() + : nullptr; + ES2PANDA_ASSERT(classDef != nullptr); - if (scope == nullptr) { - return nullptr; - } - } else if (decl->IsEnumLiteralDecl()) { + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) + scope = classDef->Scope(); + + // NOTE(dkofanov): For some reason, EnumLiteralDecl relates to enum-declaration, while EnumDecl - to enum + // members + } else if (decl->IsEnumLiteralDecl() && EnumLiteralIsEnumInitializer(me)) { scope = decl->AsEnumLiteralDecl()->Node()->AsTSEnumDeclaration()->Scope(); } else { return nullptr; @@ -1213,224 +1177,104 @@ static varbinder::Variable *ResolveMemberExpressionProperty(ir::MemberExpression return scope->FindLocal(me->Property()->AsIdentifier()->Name(), option); } -static bool IsConstantExpression(ir::AstNode *expr) -{ - if (!expr->IsExpression()) { - if (expr->IsETSTypeReference()) { - return false; - } - } - - if (expr->IsETSPrimitiveType()) { - return true; - } - - if (expr->IsIdentifier()) { - auto var = ResolveIdentifier(expr->AsIdentifier()); - return var != nullptr && var->Declaration()->IsConstDecl(); - } - - if (expr->IsMemberExpression()) { - auto me = expr->AsMemberExpression(); - if (me->Kind() != ir::MemberExpressionKind::PROPERTY_ACCESS) { - return false; - } - - auto var = ResolveMemberExpressionProperty(me); - return var != nullptr && var->Declaration()->IsReadonlyDecl(); - } - - if (IsSupportedLiteral(expr->AsExpression())) { - return true; - } - - auto isNotConstantExpression = [](ir::AstNode *node) { return !IsConstantExpression(node); }; - - return (expr->IsBinaryExpression() || expr->IsUnaryExpression() || expr->IsTSAsExpression() || - expr->IsConditionalExpression() || expr->IsTemplateLiteral()) && - !expr->IsAnyChild(isNotConstantExpression); -} - -static bool IsInTSEnumMemberInit(const ir::AstNode *n) +static varbinder::Variable *Resolve(const ir::Expression *identOrMexp) { - auto enumMember = util::Helpers::FindAncestorGivenByType(n, ir::AstNodeType::TS_ENUM_MEMBER); - if (enumMember == nullptr) { - return false; + if (identOrMexp->IsIdentifier()) { + return ResolveIdentifier(identOrMexp->AsIdentifier()); } - - auto init = enumMember->AsTSEnumMember()->Init(); - return (init == n) || (init->FindChild([n](auto *child) { return child == n; }) != nullptr); + return ResolveMemberExpressionProperty(identOrMexp->AsMemberExpression()); } -ir::AstNode *ConstantExpressionLowering::UnfoldResolvedReference(ir::AstNode *resolved, ir::AstNode *node) +// Access flags should be checked as use-site may be folded. +static bool CheckPrivateAccess(ir::ClassProperty *propDecl, ir::Expression *rval) { - ir::AstNode *resNode = nullptr; - if (resolved->IsClassProperty()) { - auto propVal = resolved->AsClassElement()->Value(); - if (propVal != nullptr && IsConstantExpression(propVal)) { - resNode = propVal->Clone(context_->allocator, node->Parent()); - resNode->SetRange(node->Range()); - } - } else if (resolved->Parent()->IsVariableDeclarator()) { - auto init = resolved->Parent()->AsVariableDeclarator()->Init(); - if (init != nullptr && IsConstantExpression(init) && !init->IsMemberExpression()) { - resNode = init->Clone(context_->allocator, node->Parent()); - resNode->SetRange(node->Range()); + ES2PANDA_ASSERT(propDecl->IsPrivateElement()); + auto *const cls = propDecl->Parent(); + auto *pred = rval->Parent(); + while (pred != nullptr) { + if (pred == cls) { + return true; } - } else if (resolved->IsTSEnumMember() && IsInTSEnumMemberInit(node)) { - auto init = resolved->AsTSEnumMember()->Init(); - if (init != nullptr && IsConstantExpression(init)) { - resNode = init->Clone(context_->allocator, node->Parent()); - resNode->SetRange(node->Range()); - } - } - - if (resNode != nullptr) { - return MaybeUnfold(resNode); - } - - // failed to unfold - return node; -} - -ir::AstNode *ConstantExpressionLowering::MaybeUnfoldIdentifier(ir::Identifier *node) -{ - if (!node->IsReference(varbinder_->Extension())) { - return node; - } - - // Left-Hand-Side identifiers in UpdateExpression or BinaryExpression cannot be unfolded - if (node->Parent()->IsUpdateExpression() && node->Parent()->AsUpdateExpression()->Argument() == node) { - return node; - } - - if (node->Parent()->IsAssignmentExpression() && node->Parent()->AsAssignmentExpression()->Left() == node) { - return node; + pred = pred->Parent(); } - - auto *resolved = ResolveIdentifier(node); - if (resolved == nullptr || !(resolved->Declaration()->IsConstDecl() || resolved->Declaration()->IsReadonlyDecl())) { - return node; - } - return UnfoldResolvedReference(resolved->Declaration()->Node(), node); -} - -ir::AstNode *ConstantExpressionLowering::MaybeUnfoldMemberExpression(ir::MemberExpression *node) -{ - if (node->Kind() != ir::MemberExpressionKind::PROPERTY_ACCESS) { - return node; - } - - auto resolved = ResolveMemberExpressionProperty(node); - if (resolved == nullptr || !resolved->Declaration()->IsReadonlyDecl()) { - return node; - } - return UnfoldResolvedReference(resolved->Declaration()->Node(), node); -} - -ir::AstNode *ConstantExpressionLowering::MaybeUnfold(ir::AstNode *node) -{ - ir::NodeTransformer handleMaybeUnfold = [this](ir::AstNode *const n) { - if (n->IsIdentifier() && (!n->Parent()->IsMemberExpression() || n->Parent()->AsMemberExpression()->Kind() == - ir::MemberExpressionKind::ELEMENT_ACCESS)) { - return MaybeUnfoldIdentifier(n->AsIdentifier()); - } - - if (n->IsMemberExpression()) { - return MaybeUnfoldMemberExpression(n->AsMemberExpression()); - } - - return n; - }; - - node->TransformChildrenRecursivelyPostorder(handleMaybeUnfold, Name()); - return handleMaybeUnfold(node); -} - -static bool IsPotentialConstant(const ir::AstNodeType type) -{ - return type == ir::AstNodeType::TEMPLATE_LITERAL || type == ir::AstNodeType::TS_AS_EXPRESSION || - type == ir::AstNodeType::UNARY_EXPRESSION || type == ir::AstNodeType::BINARY_EXPRESSION || - type == ir::AstNodeType::CONDITIONAL_EXPRESSION || type == ir::AstNodeType::IDENTIFIER; + return false; } -ir::AstNode *ConstantExpressionLowering::Fold(ir::AstNode *constantNode) +void ConstantExpressionLoweringImpl::PopulateDAGs(ir::Expression *node) { - ir::NodeTransformer handleFoldConstant = [this](ir::AstNode *const node) { - if (node->IsTemplateLiteral()) { - auto tmpLiteral = node->AsTemplateLiteral(); - auto exprs = tmpLiteral->Expressions(); - auto notSupportedLit = std::find_if(exprs.begin(), exprs.end(), - [](ir::Expression *maybeLit) { return !IsSupportedLiteral(maybeLit); }); - // Cannot fold TemplateLiteral containing unsupported literal - if (notSupportedLit != exprs.end()) { - return node; - } - return FoldTemplateLiteral(tmpLiteral, context_->allocator); + if (auto literal = AsSupportedLiteral(node); literal != nullptr) { + if (auto constr = GetTypeAnnotation(node->Parent()); + !constr || CheckCastLiteral(context_->diagnosticEngine, constr, literal)) { + AddRootDNode(literal); } - if (node->IsUnaryExpression()) { - auto unaryOp = node->AsUnaryExpression(); - if (IsSupportedLiteral(unaryOp->Argument())) { - return FoldUnaryExpression(unaryOp, context_); + } else if (auto numLiteral = Cast(node); numLiteral != nullptr) { + ES2PANDA_ASSERT(numLiteral->Number().ConversionError()); + AddDNodeToPretransform(numLiteral); + } else if (auto identOrMExp = AsRValue(Cast(node)); identOrMExp != nullptr) { + auto var = Resolve(identOrMExp); + auto decl = (var != nullptr) ? var->Declaration() : nullptr; + if ((decl != nullptr) && (decl->IsConstDecl() || decl->IsReadonlyDecl())) { + auto declnode = decl->Node(); + // NOTE(dkofanov): Constants initialized via static block/constructor are not supported. + ir::Expression *init = nullptr; + if (auto prop = Cast(declnode); + prop && (!prop->IsPrivateElement() || CheckPrivateAccess(prop, identOrMExp))) { + init = prop->Value(); + // NOTE(dkofanov): 'declnode' points to identifier instead of 'ir::VariableDeclarator'. + } else if (auto enumdecl = Cast(declnode); enumdecl != nullptr) { + init = enumdecl->Init(); + } else if (auto vardecl = Cast(declnode->Parent()); vardecl != nullptr) { + init = vardecl->Init(); } - } - if (node->IsBinaryExpression()) { - auto binop = node->AsBinaryExpression(); - if (IsSupportedLiteral(binop->Left()) && IsSupportedLiteral(binop->Right())) { - return FoldBinaryExpression(binop, context_); + if (init != nullptr) { + AddDNode(identOrMExp, init); } } - if (node->IsConditionalExpression()) { - auto condExp = node->AsConditionalExpression(); - if (IsSupportedLiteral(condExp->Test())) { - return FoldTernaryConstant(condExp); - } + } else if (auto tmpl = Cast(node); tmpl) { + if (tmpl->Expressions().empty()) { + AddDNodeToPretransform(tmpl); + } else { + AddDNode(tmpl, tmpl->Expressions()); } - return node; - }; - constantNode->TransformChildrenRecursivelyPostorder(handleFoldConstant, Name()); - return TryToCorrectNumberOrCharLiteral(handleFoldConstant(constantNode), context_); + } else if (auto unop = Cast(node); unop != nullptr) { + AddDNode(unop, unop->Argument()); + } else if (auto binop = Cast(node); binop != nullptr) { + AddDNode(binop, {binop->Left(), binop->Right()}); + } else if (auto condexpr = Cast(node); condexpr != nullptr) { + // Reduce conditional expression only if each input is known to avoid hiding errors in 'dead' code. + AddDNode(condexpr, {condexpr->Test(), condexpr->Consequent(), condexpr->Alternate()}); + } } // Note: memberExpression can be constant when it is enum property access, this check will be enabled after Issue23082. // for package, we need to check whether its every immediate-initializers is const expression. -void ConstantExpressionLowering::IsInitByConstant(ir::AstNode *node) +static void CheckInitializerInPackage(public_lib::Context *context_, ir::AstNode *node) { - ir::AstNode *initTobeChecked = nullptr; - if (node->IsExpressionStatement() && node->AsExpressionStatement()->GetExpression()->IsAssignmentExpression()) { - auto assignExpr = node->AsExpressionStatement()->GetExpression()->AsAssignmentExpression(); - initTobeChecked = assignExpr->Right(); - if (initTobeChecked->IsExpression() && IsSupportedLiteral(initTobeChecked->AsExpression())) { - return; - } - - if (!IsPotentialConstant(initTobeChecked->Type())) { - LogError(context_, diagnostic::INVALID_INIT_IN_PACKAGE, {}, initTobeChecked->Start()); - return; - } - assignExpr->SetRight(Fold(MaybeUnfold(initTobeChecked))->AsExpression()); - } - - if (node->IsClassProperty()) { - auto classProp = node->AsClassProperty(); - initTobeChecked = classProp->Value(); - if (initTobeChecked == nullptr) { + auto log = [context_](const auto &kind, auto pos) { + context_->diagnosticEngine->LogDiagnostic(kind, util::DiagnosticMessageParams {}, pos); + }; + switch (node->Type()) { + case ir::AstNodeType::EXPRESSION_STATEMENT: { + if (auto assign = Cast(node->AsExpressionStatement()->GetExpression()); assign) { + auto initTobeChecked = assign->Right(); + if (initTobeChecked && (AsSupportedLiteral(initTobeChecked) == nullptr)) { + log(diagnostic::INVALID_INIT_IN_PACKAGE, initTobeChecked->Start()); + } + } return; } - - if (initTobeChecked->IsExpression() && IsSupportedLiteral(initTobeChecked->AsExpression())) { + case ir::AstNodeType::CLASS_PROPERTY: { + if (auto init = node->AsClassProperty()->Value(); init && (AsSupportedLiteral(init) == nullptr)) { + log(diagnostic::INVALID_INIT_IN_PACKAGE, init->Start()); + } return; } - - if (!IsPotentialConstant(initTobeChecked->Type())) { - LogError(context_, diagnostic::INVALID_INIT_IN_PACKAGE, {}, initTobeChecked->Start()); + default: return; - } - classProp->SetValue(Fold(MaybeUnfold(initTobeChecked))->AsExpression()); } } -void ConstantExpressionLowering::TryFoldInitializerOfPackage(ir::ClassDefinition *globalClass) +static void PostCheckGlobalIfPackage(public_lib::Context *context_, ir::ClassDefinition *globalClass) { for (auto element : globalClass->Body()) { if (element->IsMethodDefinition()) { @@ -1446,35 +1290,53 @@ void ConstantExpressionLowering::TryFoldInitializerOfPackage(ir::ClassDefinition } auto const &initStatements = methodBody->AsBlockStatement()->Statements(); std::for_each(initStatements.begin(), initStatements.end(), - [this](ir::AstNode *node) { IsInitByConstant(node); }); + [context_](ir::AstNode *node) { CheckInitializerInPackage(context_, node); }); } if (element->IsClassProperty() && element->AsClassProperty()->IsConst() && !element->AsClassProperty()->NeedInitInStaticBlock()) { - IsInitByConstant(element); + CheckInitializerInPackage(context_, element); } } } -bool ConstantExpressionLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) +bool ConstantExpressionLoweringImpl::PerformForModule(parser::Program *program, std::string_view name) { if (program->GetFlag(parser::ProgramFlags::AST_CONSTANT_EXPRESSION_LOWERED)) { return true; } - context_ = ctx; - program_ = program; - varbinder_ = ctx->parserProgram->VarBinder()->AsETSBinder(); + program->Ast()->IterateRecursively([this](ir::AstNode *node) { + if (node->IsExpression()) { + PopulateDAGs(node->AsExpression()); + } + }); + + Pretransform(); + while (PerformStep()) { + } - program->Ast()->TransformChildrenRecursively( - [this](ir::AstNode *const node) -> checker::AstNodePtr { - // Note: Package need to check whether its immediate initializer is const expression. - if (this->program_->IsPackage() && node->IsClassDefinition() && node->AsClassDefinition()->IsGlobal()) { - TryFoldInitializerOfPackage(node->AsClassDefinition()); + // Preorder to match the "super"-expression. + program->Ast()->TransformChildrenRecursivelyPreorder( + // CC-OFFNXT(G.FMT.14-CPP) project code style + [this](ir::AstNode *node) -> ir::AstNode * { + if (!node->IsExpression()) { + return node; } - return Fold(MaybeUnfold(node)); + auto expr = node->AsExpression(); + if (replacements_.find(expr) == replacements_.end()) { + return node; + } + auto folded = replacements_[expr]; + folded->SetParent(expr->Parent()); + folded->SetRange(expr->Range()); + return folded; }, - Name()); + name); + + if (program->IsPackage()) { + PostCheckGlobalIfPackage(context_, program->GlobalClass()); + } program->SetFlag(parser::ProgramFlags::AST_CONSTANT_EXPRESSION_LOWERED); return true; diff --git a/ets2panda/compiler/lowering/ets/constantExpressionLowering.h b/ets2panda/compiler/lowering/ets/constantExpressionLowering.h index 0bf1aead0f..35d93496e3 100644 --- a/ets2panda/compiler/lowering/ets/constantExpressionLowering.h +++ b/ets2panda/compiler/lowering/ets/constantExpressionLowering.h @@ -20,41 +20,264 @@ namespace ark::es2panda::compiler { -enum class TypeRank { - // Keep this order - INT8, - CHAR, - INT16, - INT32, - INT64, - FLOAT, - DOUBLE -}; +inline bool IsValidNumberLiteral(const ir::Literal *lit) +{ + if (!lit->IsNumberLiteral()) { + return false; + } -class ConstantExpressionLowering : public PhaseForDeclarations { + return !lit->AsNumberLiteral()->Number().ConversionError(); +} + +inline ir::Literal *AsSupportedLiteral(ir::Expression *const node) +{ + if (!node->IsLiteral()) { + return nullptr; + } + + auto literal = node->AsLiteral(); + if (IsValidNumberLiteral(literal) || literal->IsCharLiteral() || literal->IsBooleanLiteral() || + literal->IsStringLiteral()) { + return literal; + } + return nullptr; +} + +class NodeCalculator; + +class ConstantExpressionLoweringImpl { public: - std::string_view Name() const override + explicit ConstantExpressionLoweringImpl(public_lib::Context *context) + : context_(context), + dNodes_(context->Allocator()->Adapter()), + node2DNode_(context->Allocator()->Adapter()), + calculationArguments_(context->Allocator()->Adapter()), + pretransformQueue_(context->Allocator()->Adapter()), + replacements_(context->Allocator()->Adapter()) { - return "ConstantExpressionLowering"; } - bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; + bool PerformForModule(parser::Program *program, std::string_view name); + + using Variable = varbinder::Variable; private: - ir::AstNode *MaybeUnfold(ir::AstNode *node); - ir::AstNode *MaybeUnfoldIdentifier(ir::Identifier *node); - ir::AstNode *MaybeUnfoldMemberExpression(ir::MemberExpression *node); - ir::AstNode *UnfoldResolvedReference(ir::AstNode *resolved, ir::AstNode *node); + void PopulateDAGs(ir::Expression *node); + + using DNId = uint32_t; + inline static constexpr DNId INVALID_DNID = -1; + + struct DAGNode { + using InputsT = std::vector; + using UsersT = std::vector; + explicit DAGNode(ir::Expression *expr) : irNode_ {expr} {} + bool AllowsCalculationAttempt() + { + return !dnodeInputs_.empty(); + } + bool IsCalculated() + { + return AsSupportedLiteral(irNode_) != nullptr; + } + + auto Ir() + { + return irNode_; + } + + auto SetIr(ir::Expression *node) + { + irNode_ = node; + } + + auto *InputsIds() + { + return &dnodeInputs_; + } + auto *UsersIds() + { + return &dnodeUsers_; + } + + private: + ir::Expression *irNode_; + InputsT dnodeInputs_ {}; + UsersT dnodeUsers_ {}; + }; + + void AddRootDNode(ir::Expression *root) + { + calculationArguments_.push_back(FindOrInsertElement(root)); + } + + void AddDNode(ir::Expression *node, ir::Expression *input) + { + AddDNode(node, {input}); + } + + void AddDNode(ir::Expression *node, std::initializer_list inputs) + { + ES2PANDA_ASSERT(inputs.size() != 0); + auto nodeId = FindOrInsertElement(node); + for (auto input : inputs) { + AddInput(nodeId, FindOrInsertElement(input)); + } + } + + template + void AddDNode(ir::TemplateLiteral *node, const T &inputs) + { + ES2PANDA_ASSERT(!inputs.empty()); // trivial template should be handled via pretransform. + auto nodeId = FindOrInsertElement(node); + for (auto input : inputs) { + AddInput(nodeId, FindOrInsertElement(input)); + } + } + + void AddDNodeToPretransform(ir::Expression *node) + { + pretransformQueue_.push_back(FindOrInsertElement(node)); + } + + void Pretransform() + { + for (auto nodeId : pretransformQueue_) { + auto *dnode = DNode(nodeId); + if (dnode->Ir()->IsTemplateLiteral()) { + if (CalculateAndCheck(DNode(nodeId))) { + calculationArguments_.push_back(nodeId); + } + } else if (dnode->Ir()->IsNumberLiteral()) { + // Replace broken literal to prevent further errors. + auto broken = util::NodeAllocator::Alloc(context_->Allocator(), context_->Allocator()); + ES2PANDA_ASSERT(broken->IsErrorPlaceHolder()); + RegisterReplacement(dnode, broken); + } else { + ES2PANDA_UNREACHABLE(); + } + } + } - ir::AstNode *Fold(ir::AstNode *constantNode); - ir::AstNode *FoldTernaryConstant(ir::ConditionalExpression *cond); + bool PerformStep() + { + decltype(calculationArguments_) newCalculationArguments {context_->Allocator()->Adapter()}; + newCalculationArguments.reserve(calculationArguments_.size()); + bool foldingOccurred = false; + + for (auto calculationArgumentId : calculationArguments_) { + auto users = DNode(calculationArgumentId)->UsersIds(); + for (auto &userIdRef : *users) { + if (auto userId = userIdRef; (userId != INVALID_DNID) && TryCalculateUser(&userIdRef, DNode(userId))) { + ES2PANDA_ASSERT(userIdRef == INVALID_DNID); + ES2PANDA_ASSERT(DNode(userId)->InputsIds()->empty()); + newCalculationArguments.push_back(userId); + foldingOccurred = true; + } + } + if (!std::all_of(users->begin(), users->end(), [](auto uid) { return uid == INVALID_DNID; })) { + // Requeue the input-node: + newCalculationArguments.push_back(calculationArgumentId); + } else { + // Speedup iteration over users in case the node was queued for the following algorithm step: + users->clear(); + } + } + + calculationArguments_ = std::move(newCalculationArguments); + return foldingOccurred; + } + + bool TryCalculateUser(DNId *edgeToUser, DAGNode *user) + { + ES2PANDA_ASSERT(DNode(*edgeToUser) == user); + if (!user->AllowsCalculationAttempt()) { + // Was calculated and requeued via another input. + *edgeToUser = INVALID_DNID; + return false; + } + + for (auto iid : *user->InputsIds()) { + if (!DNode(iid)->IsCalculated()) { + // Node isn't ready yet: + return false; + } + } + + auto res = CalculateAndCheck(user); + user->InputsIds()->clear(); + // The rest edges will be cleaned on their visit. + *edgeToUser = INVALID_DNID; + return res; + } + + bool CalculateAndCheck(DAGNode *user); + + void RegisterReplacement(DAGNode *node, ir::Expression *replacement) + { + auto old = node->Ir(); + + ES2PANDA_ASSERT(replacements_.find(old) == replacements_.end()); + replacements_[old] = replacement; + node->SetIr(replacement); + } + + DAGNode *DNode(DNId id) + { + ES2PANDA_ASSERT(id != INVALID_DNID); + return &dNodes_[id]; + } + + DNId FindElement(ir::Expression *node) + { + ES2PANDA_ASSERT(node != nullptr); + if (node2DNode_.find(node) != node2DNode_.end()) { + return node2DNode_[node]; + } + return INVALID_DNID; + } - void IsInitByConstant(ir::AstNode *node); - void TryFoldInitializerOfPackage(ir::ClassDefinition *globalClass); + DNId FindOrInsertElement(ir::Expression *node) + { + if (auto id = FindElement(node); id != INVALID_DNID) { + return id; + } + dNodes_.emplace_back(node->AsExpression()); + auto id = dNodes_.size() - 1; + node2DNode_[node] = id; + return id; + } + + void AddInput(DNId node, DNId input) + { + dNodes_[node].InputsIds()->push_back(input); + dNodes_[input].UsersIds()->push_back(node); + } public_lib::Context *context_ {nullptr}; - parser::Program *program_ {nullptr}; - varbinder::ETSBinder *varbinder_ {nullptr}; + // Base mapping + ArenaVector dNodes_; + ArenaMap node2DNode_; + // Nodes to iterate over at each step: + ArenaVector calculationArguments_; + // Nodes with no inputs which lack "normalization" (i.e. need to be somehow transformed to be used as arguments): + ArenaVector pretransformQueue_; + // Result: + ArenaMap replacements_; + + friend NodeCalculator; +}; + +class ConstantExpressionLowering : public PhaseForDeclarations { + std::string_view Name() const override + { + return "ConstantExpressionLowering"; + } + + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override + { + ConstantExpressionLoweringImpl cf {ctx}; + return cf.PerformForModule(program, Name()); + } }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index 751d44cefc..d239a1df0f 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -571,6 +571,8 @@ public: template void PreTransformChildrenRecursively(const F1 &pre, const F2 &post, std::string_view transformationName) { + static_assert(std::is_convertible_v, ir::AstNode *>); + static_assert(std::is_same_v, void>); std::function hcb = [&](AstNode *child) { AstNode *upd = pre(child); upd->TransformChildren(hcb, transformationName); @@ -581,9 +583,10 @@ public: } template - void PostTransformChildrenRecursively(const NodeTraverser &pre, const NodeTransformer &post, - std::string_view transformationName) + void PostTransformChildrenRecursively(const F1 &pre, const F2 &post, std::string_view transformationName) { + static_assert(std::is_same_v, void>); + static_assert(std::is_convertible_v, ir::AstNode *>); std::function hcb = [&](AstNode *child) { pre(child); child->TransformChildren(hcb, transformationName); @@ -823,4 +826,41 @@ private: }; } // namespace ark::es2panda::ir + +namespace ark::es2panda { + +template +struct Node2Enum; + +/* CC-OFFNXT(G.PRE.02) code gen*/ +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define REGISTER_MAPPING(nodeType, className) \ + template <> \ + struct Node2Enum { \ + static inline auto ENUM = ir::AstNodeType::nodeType; /* CC-OFF(G.PRE.02) qualified name part*/ \ + }; // CC-OFF(G.PRE.09) code gen +AST_NODE_MAPPING(REGISTER_MAPPING) +#undef REGISTER_MAPPING + +/* CC-OFFNXT(G.PRE.02) code gen*/ +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define REGISTER_MAPPING(nodeType1, nodeType2, baseClass, reinterpretClass) \ + template <> \ + struct Node2Enum { \ + static inline auto ENUM = ir::AstNodeType::nodeType1; /* CC-OFF(G.PRE.02) qualified name part*/ \ + }; // CC-OFF(G.PRE.09) code gen +AST_NODE_REINTERPRET_MAPPING(REGISTER_MAPPING) +#undef REGISTER_MAPPING + +template +NodeT *Cast(ir::AstNode *node) +{ + if (node->Type() == Node2Enum::ENUM) { + return static_cast(node); + } + return nullptr; +} + +} // namespace ark::es2panda + #endif diff --git a/ets2panda/lexer/token/number.cpp b/ets2panda/lexer/token/number.cpp index 51de994851..5da7c8e798 100644 --- a/ets2panda/lexer/token/number.cpp +++ b/ets2panda/lexer/token/number.cpp @@ -22,7 +22,8 @@ Number::Number(util::StringView str, NumberFlags flags) noexcept : str_(str), fl { Lexer::ConversionResult res {}; - if ((flags & (NumberFlags::DECIMAL_POINT | NumberFlags::EXPONENT)) == std::underlying_type_t(0)) { + if (((flags & (NumberFlags::DECIMAL_POINT | NumberFlags::EXPONENT)) == std::underlying_type_t(0)) && + (str.Utf8().back() != 'f')) { const int64_t temp = Lexer::StrToNumeric(&std::strtoll, str.Utf8().data(), res, 10); if (res == Lexer::ConversionResult::SUCCESS) { @@ -31,23 +32,19 @@ Number::Number(util::StringView str, NumberFlags flags) noexcept : str_(str), fl } else { num_ = temp; } - } else { - flags_ |= NumberFlags::ERROR; } } else { - const double temp = Lexer::StrToNumeric(&std::strtod, str.Utf8().data(), res); - if (res == Lexer::ConversionResult::SUCCESS) { - if (str.Utf8().back() != 'f') { - num_ = temp; - } else { - num_ = static_cast(temp); - } + double parsed = Lexer::StrToNumeric(&std::strtod, str.Utf8().data(), res); + if (str.Utf8().back() == 'f') { + // NOTE(dkofanov): floats should be parsed via 'strtof', however there are problems with subnormal values. + num_ = static_cast(parsed); } else { - flags_ |= NumberFlags::ERROR; + num_ = parsed; } } - if (res == Lexer::ConversionResult::OUT_OF_RANGE) { - num_ = 0; + if (res != Lexer::ConversionResult::SUCCESS) { + num_ = std::monostate {}; + flags_ |= NumberFlags::ERROR; } } } // namespace ark::es2panda::lexer diff --git a/ets2panda/lexer/token/number.h b/ets2panda/lexer/token/number.h index 1e053da19a..d0b1c0c103 100644 --- a/ets2panda/lexer/token/number.h +++ b/ets2panda/lexer/token/number.h @@ -117,59 +117,79 @@ public: bool ConversionError() const { - return (flags_ & NumberFlags::ERROR) != 0; + bool error = (flags_ & NumberFlags::ERROR) != 0; + ES2PANDA_ASSERT(error == std::holds_alternative(num_)); + return error; + } + + // NOLINTBEGIN(readability-else-after-return) + template + bool CanGetValue() const + { + if constexpr (std::is_same_v) { + return IsInteger(); + } else if constexpr (std::is_same_v) { + return IsInt() || IsShort() || IsByte() || CanBeNarrowed(); + } else if constexpr (std::is_same_v) { + return true; + } else if constexpr (std::is_same_v) { + return IsInteger() || IsFloat() || CanBeNarrowed(); + } else if constexpr (std::is_same_v) { + return IsShort() || IsByte() || CanBeNarrowed(); + } else if constexpr (std::is_same_v) { + return IsByte() || CanBeNarrowed(); + } else { + static_assert(dependent_false_v, "Invalid value type was requested for Number."); + return false; + } + } + + template + auto GetValue() const + { + ES2PANDA_ASSERT(CanGetValue()); + return std::visit(overloaded {[](auto value) { return static_cast(value); }, + []([[maybe_unused]] std::monostate value) -> T { ES2PANDA_UNREACHABLE(); }}, + num_); + } + + template + TargetType GetValueAndCastTo() const + { + return std::visit( + overloaded {[](auto value) { return static_cast(value); }, + []([[maybe_unused]] std::monostate value) -> TargetType { ES2PANDA_UNREACHABLE(); }}, + num_); } int8_t GetByte() const { - ES2PANDA_ASSERT(IsByte()); - return std::get(num_); + return GetValue(); } int16_t GetShort() const { - return std::visit(overloaded {[](int16_t value) { return value; }, - [](int8_t value) { return static_cast(value); }, - []([[maybe_unused]] auto value) -> int16_t { ES2PANDA_UNREACHABLE(); }}, - num_); + return GetValue(); } int32_t GetInt() const { - return std::visit(overloaded {[](int32_t value) { return value; }, - [](int16_t value) { return static_cast(value); }, - [](int8_t value) { return static_cast(value); }, - []([[maybe_unused]] auto value) -> int32_t { ES2PANDA_UNREACHABLE(); }}, - num_); + return GetValue(); } int64_t GetLong() const { - return std::visit(overloaded {[](int64_t value) { return value; }, - [](int32_t value) { return static_cast(value); }, - [](int16_t value) { return static_cast(value); }, - [](int8_t value) { return static_cast(value); }, - []([[maybe_unused]] auto value) -> int64_t { ES2PANDA_UNREACHABLE(); }}, - num_); + return GetValue(); } float GetFloat() const { - return std::visit(overloaded {[](float value) { return value; }, - [](int64_t value) { return static_cast(value); }, - [](int32_t value) { return static_cast(value); }, - [](int16_t value) { return static_cast(value); }, - [](int8_t value) { return static_cast(value); }, - []([[maybe_unused]] auto value) -> float { ES2PANDA_UNREACHABLE(); }}, - num_); + return GetValue(); } double GetDouble() const { - return std::visit(overloaded {[]([[maybe_unused]] std::monostate value) -> double { ES2PANDA_UNREACHABLE(); }, - [](double value) { return value; }, - [](auto value) { return static_cast(value); }}, - num_); + return GetValue(); } const util::StringView &Str() const @@ -182,19 +202,6 @@ public: str_ = str; } - void Negate() - { - std::visit(overloaded {[]([[maybe_unused]] std::monostate value) { ES2PANDA_UNREACHABLE(); }, - [](auto &value) { value = -value; }}, - num_); - if (std::holds_alternative(num_)) { - int64_t num = std::get(num_); - if (num == INT32_MIN) { - SetValue(num); - } - } - } - bool IsZero() const { return std::visit(overloaded {[]([[maybe_unused]] std::monostate value) -> bool { ES2PANDA_UNREACHABLE(); }, @@ -202,69 +209,6 @@ public: num_); } - // NOLINTBEGIN(readability-else-after-return) - template - bool CanGetValue() const noexcept - { - using T = typename std::remove_cv_t>; - - if constexpr (std::is_same_v) { - return IsInteger(); - } else if constexpr (std::is_same_v) { - return IsInt() || IsShort() || IsByte(); - } else if constexpr (std::is_same_v) { - return true; - } else if constexpr (std::is_same_v) { - return IsInteger() || IsFloat(); - } else if constexpr (std::is_same_v) { - return IsShort() || IsByte(); - } else if constexpr (std::is_same_v) { - return IsByte(); - } else { - return false; - } - } - - template - auto GetValue() const - { - using T = typename std::remove_cv_t>; - - if constexpr (std::is_same_v) { - return GetLong(); - } else if constexpr (std::is_same_v) { - return GetInt(); - } else if constexpr (std::is_same_v) { - return GetDouble(); - } else if constexpr (std::is_same_v) { - return GetFloat(); - } else if constexpr (std::is_same_v) { - return GetShort(); - } else if constexpr (std::is_same_v) { - return GetByte(); - } else { - static_assert(dependent_false_v, "Invalid value type was requested for Number."); - } - } - - template - TargetType GetValueAndCastTo() const - { - if (IsByte()) { - return static_cast(GetByte()); - } else if (IsShort()) { - return static_cast(GetShort()); - } else if (IsInt()) { - return static_cast(GetInt()); - } else if (IsLong()) { - return static_cast(GetLong()); - } else if (IsFloat()) { - return static_cast(GetFloat()); - } else if (IsDouble()) { - return static_cast(GetDouble()); - } - ES2PANDA_UNREACHABLE(); - } // NOLINTEND(readability-else-after-return) template @@ -280,6 +224,23 @@ public: } } +private: + template + bool CanBeNarrowed() const + { + return std::visit(overloaded {[](auto integer) { + return (std::numeric_limits::min() <= integer) && + (integer <= std::numeric_limits::max()); + }, // CC-OFF(G.FMT.02-CPP) project code style + []([[maybe_unused]] float value) { return false; }, + []([[maybe_unused]] double value) { + return std::is_same_v && (std::numeric_limits::min() <= value) && + (value <= std::numeric_limits::max()); + }, + []([[maybe_unused]] std::monostate value) -> bool { ES2PANDA_UNREACHABLE(); }}, + num_); + } + private: util::StringView str_ {}; std::variant num_; diff --git a/ets2panda/test/ast/compiler/ets/DeclareCheckAssign.ets b/ets2panda/test/ast/compiler/ets/DeclareCheckAssign.ets index 9e0ebf92e4..ee673f3445 100644 --- a/ets2panda/test/ast/compiler/ets/DeclareCheckAssign.ets +++ b/ets2panda/test/ast/compiler/ets/DeclareCheckAssign.ets @@ -50,7 +50,6 @@ declare const x51 = "abc" /* @@? 18:38 Error TypeError: Initializers are not allowed in ambient contexts: byte_13 */ /* @@? 18:70 Error TypeError: Initializers are not allowed in ambient contexts: byte_23 */ /* @@? 19:38 Error TypeError: Initializers are not allowed in ambient contexts: byte_14 */ -/* @@? 22:31 Error TypeError: A 'const' initializer in an ambient context must be a string or numeric literal: int_12 */ /* @@? 24:36 Error TypeError: Initializers are not allowed in ambient contexts: int_16 */ /* @@? 26:39 Error TypeError: Initializers are not allowed in ambient contexts: int_18 */ /* @@? 27:25 Error TypeError: Initializers are not allowed in ambient contexts: x1 */ 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 4dc414ecae..22ff489278 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,34 +24,8 @@ const b: Record number> = { [(():number => +("bar"))()]: (y: string):number => y.length }; -/* @@? 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 '}'. */ +/* @@? 21:20 Error TypeError: Wrong operand type for unary expression */ +/* @@? 21:21 Error TypeError: Bad operand type, the type of the operand must be numeric type. */ +/* @@? 21:34 Error SyntaxError: Function expressions are not supported, use arrow functions instead */ +/* @@? 24:20 Error TypeError: Wrong operand type for unary expression */ +/* @@? 24:21 Error TypeError: Bad operand type, the type of the operand must be numeric type. */ diff --git a/ets2panda/test/ast/compiler/ets/circular_variable_init.ets b/ets2panda/test/ast/compiler/ets/circular_variable_init.ets index fc6881da7f..af59760eb5 100644 --- a/ets2panda/test/ast/compiler/ets/circular_variable_init.ets +++ b/ets2panda/test/ast/compiler/ets/circular_variable_init.ets @@ -47,7 +47,7 @@ function main() { /* @@? 23:19 Error TypeError: Circular dependency detected for identifier: b */ /* @@? 31:15 Error TypeError: Unresolved reference globalb */ /* @@? 33:5 Error TypeError: Circular dependency detected for identifier: globalc */ -/* @@? 36:7 Error TypeError: Circular dependency detected for identifier: consta */ +/* @@? 37:7 Error TypeError: Circular dependency detected for identifier: constb */ /* @@? 40:17 Error TypeError: Unresolved reference mainb */ /* @@? 42:17 Error TypeError: Variable 'maind' is accessed before it's initialization. */ /* @@? 43:9 Error TypeError: Circular dependency detected for identifier: maind */ diff --git a/ets2panda/test/ast/parser/ets/enum30.ets b/ets2panda/test/ast/parser/ets/enum30.ets index f166e84ac7..321054058b 100644 --- a/ets2panda/test/ast/parser/ets/enum30.ets +++ b/ets2panda/test/ast/parser/ets/enum30.ets @@ -31,7 +31,7 @@ enum ColorE { G = Color.Red | 1 } enum ColorF { - H = Color.Red ? ColorE.G : (ColorD.E | 1) as int, + H = Color.Red ? ColorE.G : (ColorD.E | 1), I = (ColorE.G / 25) } diff --git a/ets2panda/test/compiler/ets/boxingConversion3-expected.txt b/ets2panda/test/compiler/ets/boxingConversion3-expected.txt index 620399e675..f9e0293935 100644 --- a/ets2panda/test/compiler/ets/boxingConversion3-expected.txt +++ b/ets2panda/test/compiler/ets/boxingConversion3-expected.txt @@ -960,8 +960,8 @@ } }, "init": { - "type": "NumberLiteral", - "value": 2, + "type": "CharLiteral", + "value": "\u0002", "loc": { "start": { "line": 27, @@ -970,7 +970,7 @@ }, "end": { "line": 27, - "column": 20, + "column": 26, "program": "boxingConversion3.ets" } } @@ -983,7 +983,7 @@ }, "end": { "line": 27, - "column": 20, + "column": 26, "program": "boxingConversion3.ets" } } @@ -998,7 +998,7 @@ }, "end": { "line": 27, - "column": 21, + "column": 27, "program": "boxingConversion3.ets" } } @@ -1160,9 +1160,60 @@ }, "arguments": [ { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 13, + "program": "boxingConversion3.ets" + }, + "end": { + "line": 30, + "column": 14, + "program": "boxingConversion3.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 15, + "program": "boxingConversion3.ets" + }, + "end": { + "line": 30, + "column": 20, + "program": "boxingConversion3.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 30, + "column": 13, + "program": "boxingConversion3.ets" + }, + "end": { + "line": 30, + "column": 20, + "program": "boxingConversion3.ets" + } + } + }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 30, @@ -1171,7 +1222,7 @@ }, "end": { "line": 30, - "column": 14, + "column": 22, "program": "boxingConversion3.ets" } } @@ -1186,7 +1237,7 @@ }, "end": { "line": 30, - "column": 15, + "column": 23, "program": "boxingConversion3.ets" } } @@ -1199,7 +1250,7 @@ }, "end": { "line": 30, - "column": 16, + "column": 24, "program": "boxingConversion3.ets" } } diff --git a/ets2panda/test/compiler/ets/boxingConversion3.ets b/ets2panda/test/compiler/ets/boxingConversion3.ets index a5ac1143c5..b84a23b50c 100644 --- a/ets2panda/test/compiler/ets/boxingConversion3.ets +++ b/ets2panda/test/compiler/ets/boxingConversion3.ets @@ -24,10 +24,10 @@ function retRefShort(a: short): Short { function main(): void { let a: Byte = 2; let b: Short = 2; - let c: Char = 2; + let c: Char = c'\x02'; primInt(a); primInt(b); - primInt(c); + primInt(c.toInt()); let d: int = retRefShort(b); let e: double = retRefShort(b); } diff --git a/ets2panda/test/compiler/ets/boxingConversion6-expected.txt b/ets2panda/test/compiler/ets/boxingConversion6-expected.txt index 7b5063ec58..9412616ee6 100644 --- a/ets2panda/test/compiler/ets/boxingConversion6-expected.txt +++ b/ets2panda/test/compiler/ets/boxingConversion6-expected.txt @@ -594,9 +594,60 @@ } }, "right": { - "type": "Identifier", - "name": "b", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 15, + "program": "boxingConversion6.ets" + }, + "end": { + "line": 22, + "column": 16, + "program": "boxingConversion6.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 17, + "program": "boxingConversion6.ets" + }, + "end": { + "line": 22, + "column": 23, + "program": "boxingConversion6.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 15, + "program": "boxingConversion6.ets" + }, + "end": { + "line": 22, + "column": 23, + "program": "boxingConversion6.ets" + } + } + }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 22, @@ -605,7 +656,7 @@ }, "end": { "line": 22, - "column": 16, + "column": 25, "program": "boxingConversion6.ets" } } @@ -618,7 +669,7 @@ }, "end": { "line": 22, - "column": 16, + "column": 25, "program": "boxingConversion6.ets" } } @@ -631,7 +682,7 @@ }, "end": { "line": 22, - "column": 16, + "column": 25, "program": "boxingConversion6.ets" } } @@ -645,7 +696,7 @@ }, "end": { "line": 22, - "column": 16, + "column": 25, "program": "boxingConversion6.ets" } } @@ -658,7 +709,7 @@ }, "end": { "line": 22, - "column": 16, + "column": 25, "program": "boxingConversion6.ets" } } @@ -671,7 +722,7 @@ }, "end": { "line": 22, - "column": 16, + "column": 25, "program": "boxingConversion6.ets" } } @@ -686,7 +737,7 @@ }, "end": { "line": 22, - "column": 16, + "column": 25, "program": "boxingConversion6.ets" } } @@ -1263,7 +1314,7 @@ }, "end": { "line": 22, - "column": 16, + "column": 25, "program": "boxingConversion6.ets" } } diff --git a/ets2panda/test/compiler/ets/boxingConversion6.ets b/ets2panda/test/compiler/ets/boxingConversion6.ets index 10443efa37..c1fbcc7f8f 100644 --- a/ets2panda/test/compiler/ets/boxingConversion6.ets +++ b/ets2panda/test/compiler/ets/boxingConversion6.ets @@ -19,4 +19,4 @@ let i: Int = b let l: Long = b let f: Float = b let d: Double = b -let c: Char = b +let c: Char = b.toChar() diff --git a/ets2panda/test/compiler/ets/boxingConversion7-expected.txt b/ets2panda/test/compiler/ets/boxingConversion7-expected.txt index ed0f15234f..8123d7fe9f 100644 --- a/ets2panda/test/compiler/ets/boxingConversion7-expected.txt +++ b/ets2panda/test/compiler/ets/boxingConversion7-expected.txt @@ -269,9 +269,60 @@ } }, "right": { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 14, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 17, + "column": 15, + "program": "boxingConversion7.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 16, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 17, + "column": 21, + "program": "boxingConversion7.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 17, + "column": 14, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 17, + "column": 21, + "program": "boxingConversion7.ets" + } + } + }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 17, @@ -280,7 +331,7 @@ }, "end": { "line": 17, - "column": 15, + "column": 23, "program": "boxingConversion7.ets" } } @@ -293,7 +344,7 @@ }, "end": { "line": 17, - "column": 15, + "column": 23, "program": "boxingConversion7.ets" } } @@ -306,7 +357,7 @@ }, "end": { "line": 17, - "column": 15, + "column": 23, "program": "boxingConversion7.ets" } } @@ -334,9 +385,60 @@ } }, "right": { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 15, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 18, + "column": 16, + "program": "boxingConversion7.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 17, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 18, + "column": 23, + "program": "boxingConversion7.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 18, + "column": 15, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 18, + "column": 23, + "program": "boxingConversion7.ets" + } + } + }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 18, @@ -345,7 +447,7 @@ }, "end": { "line": 18, - "column": 16, + "column": 25, "program": "boxingConversion7.ets" } } @@ -358,7 +460,7 @@ }, "end": { "line": 18, - "column": 16, + "column": 25, "program": "boxingConversion7.ets" } } @@ -371,7 +473,7 @@ }, "end": { "line": 18, - "column": 16, + "column": 25, "program": "boxingConversion7.ets" } } @@ -399,9 +501,60 @@ } }, "right": { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 16, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 19, + "column": 17, + "program": "boxingConversion7.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 18, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 19, + "column": 25, + "program": "boxingConversion7.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 16, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 19, + "column": 25, + "program": "boxingConversion7.ets" + } + } + }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 19, @@ -410,7 +563,7 @@ }, "end": { "line": 19, - "column": 17, + "column": 27, "program": "boxingConversion7.ets" } } @@ -423,7 +576,7 @@ }, "end": { "line": 19, - "column": 17, + "column": 27, "program": "boxingConversion7.ets" } } @@ -436,7 +589,7 @@ }, "end": { "line": 19, - "column": 17, + "column": 27, "program": "boxingConversion7.ets" } } @@ -464,9 +617,60 @@ } }, "right": { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 17, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 20, + "column": 18, + "program": "boxingConversion7.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 19, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 20, + "column": 27, + "program": "boxingConversion7.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 20, + "column": 17, + "program": "boxingConversion7.ets" + }, + "end": { + "line": 20, + "column": 27, + "program": "boxingConversion7.ets" + } + } + }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 20, @@ -475,7 +679,7 @@ }, "end": { "line": 20, - "column": 18, + "column": 29, "program": "boxingConversion7.ets" } } @@ -488,7 +692,7 @@ }, "end": { "line": 20, - "column": 18, + "column": 29, "program": "boxingConversion7.ets" } } @@ -501,7 +705,7 @@ }, "end": { "line": 20, - "column": 18, + "column": 29, "program": "boxingConversion7.ets" } } @@ -515,7 +719,7 @@ }, "end": { "line": 20, - "column": 18, + "column": 29, "program": "boxingConversion7.ets" } } @@ -528,7 +732,7 @@ }, "end": { "line": 20, - "column": 18, + "column": 29, "program": "boxingConversion7.ets" } } @@ -541,7 +745,7 @@ }, "end": { "line": 20, - "column": 18, + "column": 29, "program": "boxingConversion7.ets" } } @@ -556,7 +760,7 @@ }, "end": { "line": 20, - "column": 18, + "column": 29, "program": "boxingConversion7.ets" } } @@ -698,7 +902,7 @@ }, "end": { "line": 17, - "column": 15, + "column": 23, "program": "boxingConversion7.ets" } } @@ -785,7 +989,7 @@ }, "end": { "line": 18, - "column": 16, + "column": 25, "program": "boxingConversion7.ets" } } @@ -872,7 +1076,7 @@ }, "end": { "line": 19, - "column": 17, + "column": 27, "program": "boxingConversion7.ets" } } @@ -959,7 +1163,7 @@ }, "end": { "line": 20, - "column": 18, + "column": 29, "program": "boxingConversion7.ets" } } diff --git a/ets2panda/test/compiler/ets/boxingConversion7.ets b/ets2panda/test/compiler/ets/boxingConversion7.ets index 431a6c3ff3..e869d55494 100644 --- a/ets2panda/test/compiler/ets/boxingConversion7.ets +++ b/ets2panda/test/compiler/ets/boxingConversion7.ets @@ -14,7 +14,7 @@ */ let c: char = c'a' -let i: Int = c -let l: Long = c -let f: Float = c -let d: Double = c +let i: Int = c.toInt() +let l: Long = c.toLong() +let f: Float = c.toFloat() +let d: Double = c.toDouble() diff --git a/ets2panda/test/compiler/ets/conversion-w-ASExpr-expected.txt b/ets2panda/test/compiler/ets/conversion-w-ASExpr-expected.txt index 22661874e6..0907f25c90 100644 --- a/ets2panda/test/compiler/ets/conversion-w-ASExpr-expected.txt +++ b/ets2panda/test/compiler/ets/conversion-w-ASExpr-expected.txt @@ -1381,10 +1381,45 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "NumberLiteral", - "value": 65, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 29, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 25, + "column": 32, + "program": "conversion-w-ASExpr.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 33, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 25, + "column": 39, + "program": "conversion-w-ASExpr.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 25, @@ -1393,26 +1428,30 @@ }, "end": { "line": 25, - "column": 31, + "column": 39, "program": "conversion-w-ASExpr.ets" } } }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 25, - "column": 35, - "program": "conversion-w-ASExpr.ets" - }, - "end": { - "line": 25, - "column": 39, - "program": "conversion-w-ASExpr.ets" + "arguments": [ + { + "type": "NumberLiteral", + "value": 65, + "loc": { + "start": { + "line": 25, + "column": 40, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 25, + "column": 42, + "program": "conversion-w-ASExpr.ets" + } } } - }, + ], + "optional": false, "loc": { "start": { "line": 25, @@ -1421,7 +1460,7 @@ }, "end": { "line": 25, - "column": 31, + "column": 43, "program": "conversion-w-ASExpr.ets" } } @@ -1434,7 +1473,7 @@ }, "end": { "line": 25, - "column": 31, + "column": 43, "program": "conversion-w-ASExpr.ets" } } @@ -1449,7 +1488,7 @@ }, "end": { "line": 25, - "column": 40, + "column": 44, "program": "conversion-w-ASExpr.ets" } } diff --git a/ets2panda/test/compiler/ets/conversion-w-ASExpr.ets b/ets2panda/test/compiler/ets/conversion-w-ASExpr.ets index 786d2f71f6..449a4322e1 100644 --- a/ets2panda/test/compiler/ets/conversion-w-ASExpr.ets +++ b/ets2panda/test/compiler/ets/conversion-w-ASExpr.ets @@ -22,7 +22,7 @@ function main(): void { let fig : Float = 4.0f; let grape : Double = 5 as double; let honeydewmelon : Double = 5.0 as double; - let indian_fig : Char = 65 as char; + let indian_fig : Char = Int.toChar(65); let raspberry : Short = (1.0).toShort(); diff --git a/ets2panda/test/compiler/ets/forUpdateCharType-expected.txt b/ets2panda/test/compiler/ets/forUpdateCharType-expected.txt index a1126a66ef..1fd8379461 100644 --- a/ets2panda/test/compiler/ets/forUpdateCharType-expected.txt +++ b/ets2panda/test/compiler/ets/forUpdateCharType-expected.txt @@ -397,9 +397,77 @@ "type": "BinaryExpression", "operator": "<=", "left": { - "type": "Identifier", - "name": "a", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 28, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 29, + "program": "forUpdateCharType.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "compareTo", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 30, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 39, + "program": "forUpdateCharType.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 28, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 39, + "program": "forUpdateCharType.ets" + } + } + }, + "arguments": [ + { + "type": "CharLiteral", + "value": "d", + "loc": { + "start": { + "line": 19, + "column": 40, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 44, + "program": "forUpdateCharType.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 19, @@ -408,23 +476,23 @@ }, "end": { "line": 19, - "column": 29, + "column": 45, "program": "forUpdateCharType.ets" } } }, "right": { - "type": "CharLiteral", - "value": "d", + "type": "NumberLiteral", + "value": 0, "loc": { "start": { "line": 19, - "column": 33, + "column": 49, "program": "forUpdateCharType.ets" }, "end": { "line": 19, - "column": 37, + "column": 50, "program": "forUpdateCharType.ets" } } @@ -437,28 +505,178 @@ }, "end": { "line": 19, - "column": 37, + "column": 50, "program": "forUpdateCharType.ets" } } }, "update": { - "type": "UpdateExpression", - "operator": "++", - "prefix": false, - "argument": { + "type": "AssignmentExpression", + "operator": "=", + "left": { "type": "Identifier", "name": "a", "decorators": [], "loc": { "start": { "line": 19, - "column": 39, + "column": 52, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 53, + "program": "forUpdateCharType.ets" + } + } + }, + "right": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 57, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 58, + "program": "forUpdateCharType.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 59, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 64, + "program": "forUpdateCharType.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 57, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 64, + "program": "forUpdateCharType.ets" + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 57, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 66, + "program": "forUpdateCharType.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 19, + "column": 69, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 70, + "program": "forUpdateCharType.ets" + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 56, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 71, + "program": "forUpdateCharType.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 72, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 78, + "program": "forUpdateCharType.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 56, + "program": "forUpdateCharType.ets" + }, + "end": { + "line": 19, + "column": 78, + "program": "forUpdateCharType.ets" + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 56, "program": "forUpdateCharType.ets" }, "end": { "line": 19, - "column": 40, + "column": 80, "program": "forUpdateCharType.ets" } } @@ -466,12 +684,12 @@ "loc": { "start": { "line": 19, - "column": 39, + "column": 52, "program": "forUpdateCharType.ets" }, "end": { "line": 19, - "column": 42, + "column": 80, "program": "forUpdateCharType.ets" } } @@ -548,7 +766,7 @@ "loc": { "start": { "line": 19, - "column": 44, + "column": 82, "program": "forUpdateCharType.ets" }, "end": { diff --git a/ets2panda/test/compiler/ets/forUpdateCharType.ets b/ets2panda/test/compiler/ets/forUpdateCharType.ets index dd3310c13e..314d911a21 100644 --- a/ets2panda/test/compiler/ets/forUpdateCharType.ets +++ b/ets2panda/test/compiler/ets/forUpdateCharType.ets @@ -16,7 +16,7 @@ function main(): void { let mystring : String = ""; - for (let a: char = c'a'; a <= c'd'; a++) { + for (let a: char = c'a'; a.compareTo(c'd') <= 0; a = (a.toInt() + 1).toChar()) { mystring += a; } diff --git a/ets2panda/test/compiler/ets/implicit-conversion-expected.txt b/ets2panda/test/compiler/ets/implicit-conversion-expected.txt index 65183ede7d..e0b0f94470 100644 --- a/ets2panda/test/compiler/ets/implicit-conversion-expected.txt +++ b/ets2panda/test/compiler/ets/implicit-conversion-expected.txt @@ -1316,27 +1316,28 @@ "id": { "type": "Identifier", "name": "indian_fig", - "typeAnnotation": { - "type": "ETSTypeReference", - "part": { - "type": "ETSTypeReferencePart", - "name": { - "type": "Identifier", - "name": "Char", - "decorators": [], - "loc": { - "start": { - "line": 25, - "column": 22, - "program": "implicit-conversion.ets" - }, - "end": { - "line": 25, - "column": 26, - "program": "implicit-conversion.ets" - } - } - }, + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 9, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 25, + "column": 19, + "program": "implicit-conversion.ets" + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int", + "decorators": [], "loc": { "start": { "line": 25, @@ -1345,11 +1346,30 @@ }, "end": { "line": 25, - "column": 28, + "column": 25, "program": "implicit-conversion.ets" } } }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 26, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 25, + "column": 32, + "program": "implicit-conversion.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 25, @@ -1358,37 +1378,39 @@ }, "end": { "line": 25, - "column": 28, + "column": 32, "program": "implicit-conversion.ets" } } }, - "decorators": [], - "loc": { - "start": { - "line": 25, - "column": 9, - "program": "implicit-conversion.ets" - }, - "end": { - "line": 25, - "column": 19, - "program": "implicit-conversion.ets" + "arguments": [ + { + "type": "NumberLiteral", + "value": 65, + "loc": { + "start": { + "line": 25, + "column": 33, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 25, + "column": 35, + "program": "implicit-conversion.ets" + } + } } - } - }, - "init": { - "type": "NumberLiteral", - "value": 65, + ], + "optional": false, "loc": { "start": { "line": 25, - "column": 29, + "column": 22, "program": "implicit-conversion.ets" }, "end": { "line": 25, - "column": 31, + "column": 36, "program": "implicit-conversion.ets" } } @@ -1401,7 +1423,7 @@ }, "end": { "line": 25, - "column": 31, + "column": 36, "program": "implicit-conversion.ets" } } @@ -1416,7 +1438,7 @@ }, "end": { "line": 25, - "column": 32, + "column": 37, "program": "implicit-conversion.ets" } } diff --git a/ets2panda/test/compiler/ets/implicit-conversion.ets b/ets2panda/test/compiler/ets/implicit-conversion.ets index 46be1fce99..dd475ece2a 100644 --- a/ets2panda/test/compiler/ets/implicit-conversion.ets +++ b/ets2panda/test/compiler/ets/implicit-conversion.ets @@ -22,7 +22,7 @@ function main(): void { let fig : Float = Double.toFloat(4.0); let grape : Double = -5.0; let honeydewmelon : Double = 5.0; - let indian_fig : Char = 65; + let indian_fig = Int.toChar(65); let raspberry : Short = Double.toShort(1.0); diff --git a/ets2panda/test/parser/ets/StringBase64-expected.txt b/ets2panda/test/parser/ets/StringBase64-expected.txt index 3f5fe930fa..b66f13fea5 100644 --- a/ets2panda/test/parser/ets/StringBase64-expected.txt +++ b/ets2panda/test/parser/ets/StringBase64-expected.txt @@ -3200,8 +3200,43 @@ "callee": { "type": "MemberExpression", "object": { - "type": "StringLiteral", - "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "StringBase64", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 27, + "program": "StringBase64.ets" + }, + "end": { + "line": 25, + "column": 39, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "TO_BASE64_TABLE", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 40, + "program": "StringBase64.ets" + }, + "end": { + "line": 25, + "column": 55, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 25, @@ -3256,9 +3291,78 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 63, + "program": "StringBase64.ets" + }, + "end": { + "line": 25, + "column": 67, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 68, + "program": "StringBase64.ets" + }, + "end": { + "line": 25, + "column": 74, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 25, + "column": 63, + "program": "StringBase64.ets" + }, + "end": { + "line": 25, + "column": 74, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 75, + "program": "StringBase64.ets" + }, + "end": { + "line": 25, + "column": 76, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 25, @@ -3267,24 +3371,24 @@ }, "end": { "line": 25, - "column": 67, + "column": 77, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 25, - "column": 68, + "column": 78, "program": "StringBase64.ets" }, "end": { "line": 25, - "column": 74, + "column": 83, "program": "StringBase64.ets" } } @@ -3299,30 +3403,12 @@ }, "end": { "line": 25, - "column": 74, + "column": 83, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 25, - "column": 75, - "program": "StringBase64.ets" - }, - "end": { - "line": 25, - "column": 76, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { @@ -3332,7 +3418,7 @@ }, "end": { "line": 25, - "column": 77, + "column": 85, "program": "StringBase64.ets" } } @@ -3343,12 +3429,12 @@ "loc": { "start": { "line": 25, - "column": 81, + "column": 89, "program": "StringBase64.ets" }, "end": { "line": 25, - "column": 82, + "column": 90, "program": "StringBase64.ets" } } @@ -3361,7 +3447,7 @@ }, "end": { "line": 25, - "column": 82, + "column": 90, "program": "StringBase64.ets" } } @@ -3376,7 +3462,7 @@ }, "end": { "line": 25, - "column": 83, + "column": 91, "program": "StringBase64.ets" } } @@ -3391,7 +3477,7 @@ }, "end": { "line": 25, - "column": 84, + "column": 92, "program": "StringBase64.ets" } } @@ -3404,7 +3490,7 @@ }, "end": { "line": 25, - "column": 85, + "column": 93, "program": "StringBase64.ets" } } @@ -3470,8 +3556,43 @@ "callee": { "type": "MemberExpression", "object": { - "type": "StringLiteral", - "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "StringBase64", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 27, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 39, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "TO_BASE64_TABLE", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 40, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 55, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 26, @@ -3532,9 +3653,78 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 65, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 69, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 70, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 76, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 65, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 76, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 77, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 78, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 26, @@ -3543,24 +3733,24 @@ }, "end": { "line": 26, - "column": 69, + "column": 79, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 26, - "column": 70, + "column": 80, "program": "StringBase64.ets" }, "end": { "line": 26, - "column": 76, + "column": 85, "program": "StringBase64.ets" } } @@ -3575,30 +3765,12 @@ }, "end": { "line": 26, - "column": 76, + "column": 85, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 77, - "program": "StringBase64.ets" - }, - "end": { - "line": 26, - "column": 78, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { @@ -3608,7 +3780,7 @@ }, "end": { "line": 26, - "column": 79, + "column": 87, "program": "StringBase64.ets" } } @@ -3619,12 +3791,12 @@ "loc": { "start": { "line": 26, - "column": 82, + "column": 90, "program": "StringBase64.ets" }, "end": { "line": 26, - "column": 86, + "column": 94, "program": "StringBase64.ets" } } @@ -3637,7 +3809,7 @@ }, "end": { "line": 26, - "column": 87, + "column": 95, "program": "StringBase64.ets" } } @@ -3648,12 +3820,12 @@ "loc": { "start": { "line": 26, - "column": 91, + "column": 99, "program": "StringBase64.ets" }, "end": { "line": 26, - "column": 92, + "column": 100, "program": "StringBase64.ets" } } @@ -3666,7 +3838,7 @@ }, "end": { "line": 26, - "column": 93, + "column": 101, "program": "StringBase64.ets" } } @@ -3679,35 +3851,136 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 97, - "program": "StringBase64.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 105, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 109, + "program": "StringBase64.ets" + } + } }, - "end": { - "line": 26, - "column": 101, - "program": "StringBase64.ets" + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 110, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 116, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 105, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 116, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 117, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 118, + "program": "StringBase64.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 26, + "column": 121, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 122, + "program": "StringBase64.ets" + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 117, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 122, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 105, + "program": "StringBase64.ets" + }, + "end": { + "line": 26, + "column": 123, + "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 26, - "column": 102, + "column": 124, "program": "StringBase64.ets" }, "end": { "line": 26, - "column": 108, + "column": 129, "program": "StringBase64.ets" } } @@ -3717,77 +3990,27 @@ "loc": { "start": { "line": 26, - "column": 97, + "column": 105, "program": "StringBase64.ets" }, "end": { "line": 26, - "column": 108, + "column": 129, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 109, - "program": "StringBase64.ets" - }, - "end": { - "line": 26, - "column": 110, - "program": "StringBase64.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 26, - "column": 113, - "program": "StringBase64.ets" - }, - "end": { - "line": 26, - "column": 114, - "program": "StringBase64.ets" - } - } - }, - "loc": { - "start": { - "line": 26, - "column": 109, - "program": "StringBase64.ets" - }, - "end": { - "line": 26, - "column": 114, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { "line": 26, - "column": 97, + "column": 105, "program": "StringBase64.ets" }, "end": { "line": 26, - "column": 115, + "column": 131, "program": "StringBase64.ets" } } @@ -3798,12 +4021,12 @@ "loc": { "start": { "line": 26, - "column": 119, + "column": 135, "program": "StringBase64.ets" }, "end": { "line": 26, - "column": 120, + "column": 136, "program": "StringBase64.ets" } } @@ -3811,12 +4034,12 @@ "loc": { "start": { "line": 26, - "column": 96, + "column": 104, "program": "StringBase64.ets" }, "end": { "line": 26, - "column": 121, + "column": 137, "program": "StringBase64.ets" } } @@ -3829,7 +4052,7 @@ }, "end": { "line": 26, - "column": 121, + "column": 137, "program": "StringBase64.ets" } } @@ -3844,7 +4067,7 @@ }, "end": { "line": 26, - "column": 122, + "column": 138, "program": "StringBase64.ets" } } @@ -3859,7 +4082,7 @@ }, "end": { "line": 26, - "column": 123, + "column": 139, "program": "StringBase64.ets" } } @@ -3872,7 +4095,7 @@ }, "end": { "line": 26, - "column": 124, + "column": 140, "program": "StringBase64.ets" } } @@ -3938,8 +4161,43 @@ "callee": { "type": "MemberExpression", "object": { - "type": "StringLiteral", - "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "StringBase64", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 27, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 39, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "TO_BASE64_TABLE", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 40, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 55, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 27, @@ -4000,9 +4258,110 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 65, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 69, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 70, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 76, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 27, + "column": 65, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 76, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 77, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 78, + "program": "StringBase64.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 27, + "column": 81, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 82, + "program": "StringBase64.ets" + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 77, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 82, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 27, @@ -4011,24 +4370,24 @@ }, "end": { "line": 27, - "column": 69, + "column": 83, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 27, - "column": 70, + "column": 84, "program": "StringBase64.ets" }, "end": { "line": 27, - "column": 76, + "column": 89, "program": "StringBase64.ets" } } @@ -4043,62 +4402,12 @@ }, "end": { "line": 27, - "column": 76, + "column": 89, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 77, - "program": "StringBase64.ets" - }, - "end": { - "line": 27, - "column": 78, - "program": "StringBase64.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 27, - "column": 81, - "program": "StringBase64.ets" - }, - "end": { - "line": 27, - "column": 82, - "program": "StringBase64.ets" - } - } - }, - "loc": { - "start": { - "line": 27, - "column": 77, - "program": "StringBase64.ets" - }, - "end": { - "line": 27, - "column": 82, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { @@ -4108,7 +4417,7 @@ }, "end": { "line": 27, - "column": 83, + "column": 91, "program": "StringBase64.ets" } } @@ -4119,12 +4428,12 @@ "loc": { "start": { "line": 27, - "column": 86, + "column": 94, "program": "StringBase64.ets" }, "end": { "line": 27, - "column": 90, + "column": 98, "program": "StringBase64.ets" } } @@ -4137,7 +4446,7 @@ }, "end": { "line": 27, - "column": 91, + "column": 99, "program": "StringBase64.ets" } } @@ -4148,12 +4457,12 @@ "loc": { "start": { "line": 27, - "column": 95, + "column": 103, "program": "StringBase64.ets" }, "end": { "line": 27, - "column": 96, + "column": 104, "program": "StringBase64.ets" } } @@ -4166,7 +4475,7 @@ }, "end": { "line": 27, - "column": 97, + "column": 105, "program": "StringBase64.ets" } } @@ -4179,35 +4488,136 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 109, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 113, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 114, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 120, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 27, + "column": 109, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 120, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 121, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 122, + "program": "StringBase64.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 27, + "column": 125, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 126, + "program": "StringBase64.ets" + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 121, + "program": "StringBase64.ets" + }, + "end": { + "line": 27, + "column": 126, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 27, - "column": 101, + "column": 109, "program": "StringBase64.ets" }, "end": { "line": 27, - "column": 105, + "column": 127, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 27, - "column": 106, + "column": 128, "program": "StringBase64.ets" }, "end": { "line": 27, - "column": 112, + "column": 133, "program": "StringBase64.ets" } } @@ -4217,77 +4627,27 @@ "loc": { "start": { "line": 27, - "column": 101, + "column": 109, "program": "StringBase64.ets" }, "end": { "line": 27, - "column": 112, + "column": 133, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 113, - "program": "StringBase64.ets" - }, - "end": { - "line": 27, - "column": 114, - "program": "StringBase64.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 27, - "column": 117, - "program": "StringBase64.ets" - }, - "end": { - "line": 27, - "column": 118, - "program": "StringBase64.ets" - } - } - }, - "loc": { - "start": { - "line": 27, - "column": 113, - "program": "StringBase64.ets" - }, - "end": { - "line": 27, - "column": 118, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { "line": 27, - "column": 101, + "column": 109, "program": "StringBase64.ets" }, "end": { "line": 27, - "column": 119, + "column": 135, "program": "StringBase64.ets" } } @@ -4298,12 +4658,12 @@ "loc": { "start": { "line": 27, - "column": 123, + "column": 139, "program": "StringBase64.ets" }, "end": { "line": 27, - "column": 124, + "column": 140, "program": "StringBase64.ets" } } @@ -4311,12 +4671,12 @@ "loc": { "start": { "line": 27, - "column": 100, + "column": 108, "program": "StringBase64.ets" }, "end": { "line": 27, - "column": 125, + "column": 141, "program": "StringBase64.ets" } } @@ -4329,7 +4689,7 @@ }, "end": { "line": 27, - "column": 125, + "column": 141, "program": "StringBase64.ets" } } @@ -4344,7 +4704,7 @@ }, "end": { "line": 27, - "column": 126, + "column": 142, "program": "StringBase64.ets" } } @@ -4359,7 +4719,7 @@ }, "end": { "line": 27, - "column": 127, + "column": 143, "program": "StringBase64.ets" } } @@ -4372,7 +4732,7 @@ }, "end": { "line": 27, - "column": 128, + "column": 144, "program": "StringBase64.ets" } } @@ -4438,8 +4798,43 @@ "callee": { "type": "MemberExpression", "object": { - "type": "StringLiteral", - "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "StringBase64", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 27, + "program": "StringBase64.ets" + }, + "end": { + "line": 28, + "column": 39, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "TO_BASE64_TABLE", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 40, + "program": "StringBase64.ets" + }, + "end": { + "line": 28, + "column": 55, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 28, @@ -4494,9 +4889,110 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 63, + "program": "StringBase64.ets" + }, + "end": { + "line": 28, + "column": 67, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 68, + "program": "StringBase64.ets" + }, + "end": { + "line": 28, + "column": 74, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 28, + "column": 63, + "program": "StringBase64.ets" + }, + "end": { + "line": 28, + "column": 74, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 75, + "program": "StringBase64.ets" + }, + "end": { + "line": 28, + "column": 76, + "program": "StringBase64.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 28, + "column": 79, + "program": "StringBase64.ets" + }, + "end": { + "line": 28, + "column": 80, + "program": "StringBase64.ets" + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 75, + "program": "StringBase64.ets" + }, + "end": { + "line": 28, + "column": 80, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 28, @@ -4505,24 +5001,24 @@ }, "end": { "line": 28, - "column": 67, + "column": 81, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 28, - "column": 68, + "column": 82, "program": "StringBase64.ets" }, "end": { "line": 28, - "column": 74, + "column": 87, "program": "StringBase64.ets" } } @@ -4533,66 +5029,16 @@ "start": { "line": 28, "column": 63, - "program": "StringBase64.ets" - }, - "end": { - "line": 28, - "column": 74, - "program": "StringBase64.ets" - } - } - }, - "arguments": [ - { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 28, - "column": 75, - "program": "StringBase64.ets" - }, - "end": { - "line": 28, - "column": 76, - "program": "StringBase64.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 28, - "column": 79, - "program": "StringBase64.ets" - }, - "end": { - "line": 28, - "column": 80, - "program": "StringBase64.ets" - } - } - }, - "loc": { - "start": { - "line": 28, - "column": 75, - "program": "StringBase64.ets" - }, - "end": { - "line": 28, - "column": 80, - "program": "StringBase64.ets" - } + "program": "StringBase64.ets" + }, + "end": { + "line": 28, + "column": 87, + "program": "StringBase64.ets" } } - ], + }, + "arguments": [], "optional": false, "loc": { "start": { @@ -4602,7 +5048,7 @@ }, "end": { "line": 28, - "column": 81, + "column": 89, "program": "StringBase64.ets" } } @@ -4613,12 +5059,12 @@ "loc": { "start": { "line": 28, - "column": 84, + "column": 92, "program": "StringBase64.ets" }, "end": { "line": 28, - "column": 88, + "column": 96, "program": "StringBase64.ets" } } @@ -4631,7 +5077,7 @@ }, "end": { "line": 28, - "column": 88, + "column": 96, "program": "StringBase64.ets" } } @@ -4646,7 +5092,7 @@ }, "end": { "line": 28, - "column": 89, + "column": 97, "program": "StringBase64.ets" } } @@ -4661,7 +5107,7 @@ }, "end": { "line": 28, - "column": 90, + "column": 98, "program": "StringBase64.ets" } } @@ -4674,7 +5120,7 @@ }, "end": { "line": 28, - "column": 91, + "column": 99, "program": "StringBase64.ets" } } @@ -4983,8 +5429,43 @@ "callee": { "type": "MemberExpression", "object": { - "type": "StringLiteral", - "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "StringBase64", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 27, + "program": "StringBase64.ets" + }, + "end": { + "line": 32, + "column": 39, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "TO_BASE64_TABLE", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 40, + "program": "StringBase64.ets" + }, + "end": { + "line": 32, + "column": 55, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 32, @@ -5039,9 +5520,78 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 63, + "program": "StringBase64.ets" + }, + "end": { + "line": 32, + "column": 67, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 68, + "program": "StringBase64.ets" + }, + "end": { + "line": 32, + "column": 74, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 32, + "column": 63, + "program": "StringBase64.ets" + }, + "end": { + "line": 32, + "column": 74, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 75, + "program": "StringBase64.ets" + }, + "end": { + "line": 32, + "column": 76, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 32, @@ -5050,24 +5600,24 @@ }, "end": { "line": 32, - "column": 67, + "column": 77, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 32, - "column": 68, + "column": 78, "program": "StringBase64.ets" }, "end": { "line": 32, - "column": 74, + "column": 83, "program": "StringBase64.ets" } } @@ -5082,30 +5632,12 @@ }, "end": { "line": 32, - "column": 74, + "column": 83, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 32, - "column": 75, - "program": "StringBase64.ets" - }, - "end": { - "line": 32, - "column": 76, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { @@ -5115,7 +5647,7 @@ }, "end": { "line": 32, - "column": 77, + "column": 85, "program": "StringBase64.ets" } } @@ -5126,12 +5658,12 @@ "loc": { "start": { "line": 32, - "column": 81, + "column": 89, "program": "StringBase64.ets" }, "end": { "line": 32, - "column": 82, + "column": 90, "program": "StringBase64.ets" } } @@ -5144,7 +5676,7 @@ }, "end": { "line": 32, - "column": 82, + "column": 90, "program": "StringBase64.ets" } } @@ -5159,7 +5691,7 @@ }, "end": { "line": 32, - "column": 83, + "column": 91, "program": "StringBase64.ets" } } @@ -5174,7 +5706,7 @@ }, "end": { "line": 32, - "column": 84, + "column": 92, "program": "StringBase64.ets" } } @@ -5187,7 +5719,7 @@ }, "end": { "line": 32, - "column": 85, + "column": 93, "program": "StringBase64.ets" } } @@ -5339,8 +5871,43 @@ "callee": { "type": "MemberExpression", "object": { - "type": "StringLiteral", - "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "StringBase64", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 31, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 43, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "TO_BASE64_TABLE", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 44, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 59, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 34, @@ -5401,9 +5968,78 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 69, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 73, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 74, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 80, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 34, + "column": 69, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 80, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 81, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 82, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 34, @@ -5412,24 +6048,24 @@ }, "end": { "line": 34, - "column": 73, + "column": 83, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 34, - "column": 74, + "column": 84, "program": "StringBase64.ets" }, "end": { "line": 34, - "column": 80, + "column": 89, "program": "StringBase64.ets" } } @@ -5444,30 +6080,12 @@ }, "end": { "line": 34, - "column": 80, + "column": 89, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 34, - "column": 81, - "program": "StringBase64.ets" - }, - "end": { - "line": 34, - "column": 82, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { @@ -5477,7 +6095,7 @@ }, "end": { "line": 34, - "column": 83, + "column": 91, "program": "StringBase64.ets" } } @@ -5488,12 +6106,12 @@ "loc": { "start": { "line": 34, - "column": 86, + "column": 94, "program": "StringBase64.ets" }, "end": { "line": 34, - "column": 90, + "column": 98, "program": "StringBase64.ets" } } @@ -5506,7 +6124,7 @@ }, "end": { "line": 34, - "column": 91, + "column": 99, "program": "StringBase64.ets" } } @@ -5517,12 +6135,12 @@ "loc": { "start": { "line": 34, - "column": 95, + "column": 103, "program": "StringBase64.ets" }, "end": { "line": 34, - "column": 96, + "column": 104, "program": "StringBase64.ets" } } @@ -5535,7 +6153,7 @@ }, "end": { "line": 34, - "column": 97, + "column": 105, "program": "StringBase64.ets" } } @@ -5548,35 +6166,136 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 109, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 113, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 114, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 120, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 34, + "column": 109, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 120, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 121, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 122, + "program": "StringBase64.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 34, + "column": 125, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 126, + "program": "StringBase64.ets" + } + } + }, + "loc": { + "start": { + "line": 34, + "column": 121, + "program": "StringBase64.ets" + }, + "end": { + "line": 34, + "column": 126, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 34, - "column": 101, + "column": 109, "program": "StringBase64.ets" }, "end": { "line": 34, - "column": 105, + "column": 127, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 34, - "column": 106, + "column": 128, "program": "StringBase64.ets" }, "end": { "line": 34, - "column": 112, + "column": 133, "program": "StringBase64.ets" } } @@ -5586,77 +6305,27 @@ "loc": { "start": { "line": 34, - "column": 101, + "column": 109, "program": "StringBase64.ets" }, "end": { "line": 34, - "column": 112, + "column": 133, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 34, - "column": 113, - "program": "StringBase64.ets" - }, - "end": { - "line": 34, - "column": 114, - "program": "StringBase64.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 34, - "column": 117, - "program": "StringBase64.ets" - }, - "end": { - "line": 34, - "column": 118, - "program": "StringBase64.ets" - } - } - }, - "loc": { - "start": { - "line": 34, - "column": 113, - "program": "StringBase64.ets" - }, - "end": { - "line": 34, - "column": 118, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { "line": 34, - "column": 101, + "column": 109, "program": "StringBase64.ets" }, "end": { "line": 34, - "column": 119, + "column": 135, "program": "StringBase64.ets" } } @@ -5667,12 +6336,12 @@ "loc": { "start": { "line": 34, - "column": 123, + "column": 139, "program": "StringBase64.ets" }, "end": { "line": 34, - "column": 124, + "column": 140, "program": "StringBase64.ets" } } @@ -5680,12 +6349,12 @@ "loc": { "start": { "line": 34, - "column": 100, + "column": 108, "program": "StringBase64.ets" }, "end": { "line": 34, - "column": 125, + "column": 141, "program": "StringBase64.ets" } } @@ -5698,7 +6367,7 @@ }, "end": { "line": 34, - "column": 125, + "column": 141, "program": "StringBase64.ets" } } @@ -5713,7 +6382,7 @@ }, "end": { "line": 34, - "column": 126, + "column": 142, "program": "StringBase64.ets" } } @@ -5728,7 +6397,7 @@ }, "end": { "line": 34, - "column": 127, + "column": 143, "program": "StringBase64.ets" } } @@ -5741,7 +6410,7 @@ }, "end": { "line": 34, - "column": 128, + "column": 144, "program": "StringBase64.ets" } } @@ -5807,8 +6476,43 @@ "callee": { "type": "MemberExpression", "object": { - "type": "StringLiteral", - "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "StringBase64", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 31, + "program": "StringBase64.ets" + }, + "end": { + "line": 35, + "column": 43, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "TO_BASE64_TABLE", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 44, + "program": "StringBase64.ets" + }, + "end": { + "line": 35, + "column": 59, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 35, @@ -5866,9 +6570,110 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 68, + "program": "StringBase64.ets" + }, + "end": { + "line": 35, + "column": 72, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 73, + "program": "StringBase64.ets" + }, + "end": { + "line": 35, + "column": 79, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 35, + "column": 68, + "program": "StringBase64.ets" + }, + "end": { + "line": 35, + "column": 79, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 80, + "program": "StringBase64.ets" + }, + "end": { + "line": 35, + "column": 81, + "program": "StringBase64.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 35, + "column": 84, + "program": "StringBase64.ets" + }, + "end": { + "line": 35, + "column": 85, + "program": "StringBase64.ets" + } + } + }, + "loc": { + "start": { + "line": 35, + "column": 80, + "program": "StringBase64.ets" + }, + "end": { + "line": 35, + "column": 85, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 35, @@ -5877,24 +6682,24 @@ }, "end": { "line": 35, - "column": 72, + "column": 86, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 35, - "column": 73, + "column": 87, "program": "StringBase64.ets" }, "end": { "line": 35, - "column": 79, + "column": 92, "program": "StringBase64.ets" } } @@ -5909,62 +6714,12 @@ }, "end": { "line": 35, - "column": 79, + "column": 92, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 35, - "column": 80, - "program": "StringBase64.ets" - }, - "end": { - "line": 35, - "column": 81, - "program": "StringBase64.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 35, - "column": 84, - "program": "StringBase64.ets" - }, - "end": { - "line": 35, - "column": 85, - "program": "StringBase64.ets" - } - } - }, - "loc": { - "start": { - "line": 35, - "column": 80, - "program": "StringBase64.ets" - }, - "end": { - "line": 35, - "column": 85, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { @@ -5974,7 +6729,7 @@ }, "end": { "line": 35, - "column": 86, + "column": 94, "program": "StringBase64.ets" } } @@ -5985,12 +6740,12 @@ "loc": { "start": { "line": 35, - "column": 89, + "column": 97, "program": "StringBase64.ets" }, "end": { "line": 35, - "column": 93, + "column": 101, "program": "StringBase64.ets" } } @@ -6003,7 +6758,7 @@ }, "end": { "line": 35, - "column": 94, + "column": 102, "program": "StringBase64.ets" } } @@ -6014,12 +6769,12 @@ "loc": { "start": { "line": 35, - "column": 98, + "column": 106, "program": "StringBase64.ets" }, "end": { "line": 35, - "column": 99, + "column": 107, "program": "StringBase64.ets" } } @@ -6032,7 +6787,7 @@ }, "end": { "line": 35, - "column": 99, + "column": 107, "program": "StringBase64.ets" } } @@ -6047,7 +6802,7 @@ }, "end": { "line": 35, - "column": 100, + "column": 108, "program": "StringBase64.ets" } } @@ -6062,7 +6817,7 @@ }, "end": { "line": 35, - "column": 101, + "column": 109, "program": "StringBase64.ets" } } @@ -6075,7 +6830,7 @@ }, "end": { "line": 35, - "column": 102, + "column": 110, "program": "StringBase64.ets" } } @@ -6258,8 +7013,43 @@ "callee": { "type": "MemberExpression", "object": { - "type": "StringLiteral", - "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "StringBase64", + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 31, + "program": "StringBase64.ets" + }, + "end": { + "line": 39, + "column": 43, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "TO_BASE64_TABLE", + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 44, + "program": "StringBase64.ets" + }, + "end": { + "line": 39, + "column": 59, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 39, @@ -6317,9 +7107,78 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 68, + "program": "StringBase64.ets" + }, + "end": { + "line": 39, + "column": 72, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 73, + "program": "StringBase64.ets" + }, + "end": { + "line": 39, + "column": 79, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 39, + "column": 68, + "program": "StringBase64.ets" + }, + "end": { + "line": 39, + "column": 79, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 39, + "column": 80, + "program": "StringBase64.ets" + }, + "end": { + "line": 39, + "column": 81, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 39, @@ -6328,24 +7187,24 @@ }, "end": { "line": 39, - "column": 72, + "column": 82, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 39, - "column": 73, + "column": 83, "program": "StringBase64.ets" }, "end": { "line": 39, - "column": 79, + "column": 88, "program": "StringBase64.ets" } } @@ -6360,30 +7219,12 @@ }, "end": { "line": 39, - "column": 79, + "column": 88, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 39, - "column": 80, - "program": "StringBase64.ets" - }, - "end": { - "line": 39, - "column": 81, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { @@ -6393,7 +7234,7 @@ }, "end": { "line": 39, - "column": 82, + "column": 90, "program": "StringBase64.ets" } } @@ -6404,12 +7245,12 @@ "loc": { "start": { "line": 39, - "column": 85, + "column": 93, "program": "StringBase64.ets" }, "end": { "line": 39, - "column": 89, + "column": 97, "program": "StringBase64.ets" } } @@ -6422,7 +7263,7 @@ }, "end": { "line": 39, - "column": 90, + "column": 98, "program": "StringBase64.ets" } } @@ -6433,12 +7274,12 @@ "loc": { "start": { "line": 39, - "column": 94, + "column": 102, "program": "StringBase64.ets" }, "end": { "line": 39, - "column": 95, + "column": 103, "program": "StringBase64.ets" } } @@ -6451,7 +7292,7 @@ }, "end": { "line": 39, - "column": 95, + "column": 103, "program": "StringBase64.ets" } } @@ -6466,7 +7307,7 @@ }, "end": { "line": 39, - "column": 96, + "column": 104, "program": "StringBase64.ets" } } @@ -6481,7 +7322,7 @@ }, "end": { "line": 39, - "column": 97, + "column": 105, "program": "StringBase64.ets" } } @@ -6494,7 +7335,7 @@ }, "end": { "line": 39, - "column": 98, + "column": 106, "program": "StringBase64.ets" } } @@ -7695,9 +8536,78 @@ "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 51, + "column": 56, + "program": "StringBase64.ets" + }, + "end": { + "line": 51, + "column": 60, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "charAt", + "decorators": [], + "loc": { + "start": { + "line": 51, + "column": 61, + "program": "StringBase64.ets" + }, + "end": { + "line": 51, + "column": 67, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 51, + "column": 56, + "program": "StringBase64.ets" + }, + "end": { + "line": 51, + "column": 67, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "i", + "decorators": [], + "loc": { + "start": { + "line": 51, + "column": 68, + "program": "StringBase64.ets" + }, + "end": { + "line": 51, + "column": 69, + "program": "StringBase64.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 51, @@ -7706,24 +8616,24 @@ }, "end": { "line": 51, - "column": 60, + "column": 70, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "charAt", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 51, - "column": 61, + "column": 71, "program": "StringBase64.ets" }, "end": { "line": 51, - "column": 67, + "column": 76, "program": "StringBase64.ets" } } @@ -7738,30 +8648,12 @@ }, "end": { "line": 51, - "column": 67, + "column": 76, "program": "StringBase64.ets" } } }, - "arguments": [ - { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 51, - "column": 68, - "program": "StringBase64.ets" - }, - "end": { - "line": 51, - "column": 69, - "program": "StringBase64.ets" - } - } - } - ], + "arguments": [], "optional": false, "loc": { "start": { @@ -7771,7 +8663,7 @@ }, "end": { "line": 51, - "column": 70, + "column": 78, "program": "StringBase64.ets" } } @@ -7782,12 +8674,12 @@ "loc": { "start": { "line": 51, - "column": 73, + "column": 81, "program": "StringBase64.ets" }, "end": { "line": 51, - "column": 77, + "column": 85, "program": "StringBase64.ets" } } @@ -7800,7 +8692,7 @@ }, "end": { "line": 51, - "column": 77, + "column": 85, "program": "StringBase64.ets" } } @@ -7815,7 +8707,7 @@ }, "end": { "line": 51, - "column": 78, + "column": 86, "program": "StringBase64.ets" } } @@ -7828,7 +8720,7 @@ }, "end": { "line": 51, - "column": 78, + "column": 86, "program": "StringBase64.ets" } } @@ -7843,7 +8735,7 @@ }, "end": { "line": 51, - "column": 79, + "column": 87, "program": "StringBase64.ets" } } diff --git a/ets2panda/test/parser/ets/StringBase64.ets b/ets2panda/test/parser/ets/StringBase64.ets index cfde8d36b6..893cc6a855 100644 --- a/ets2panda/test/parser/ets/StringBase64.ets +++ b/ets2panda/test/parser/ets/StringBase64.ets @@ -22,21 +22,21 @@ export class StringBase64 { let length : int = data.length.toInt(); let i : int ; for (i = 0; i < (length - 2); i += 3) { - result.append(StringBase64.TO_BASE64_TABLE.charAt(data.charAt(i) >> 2)); - result.append(StringBase64.TO_BASE64_TABLE.charAt(((data.charAt(i) & 0x03) << 4) + (data.charAt(i + 1) >> 4))); - result.append(StringBase64.TO_BASE64_TABLE.charAt(((data.charAt(i + 1) & 0x0f) << 2) + (data.charAt(i + 2) >> 6))); - result.append(StringBase64.TO_BASE64_TABLE.charAt(data.charAt(i + 2) & 0x3f)); + result.append(StringBase64.TO_BASE64_TABLE.charAt(data.charAt(i).toInt() >> 2)); + result.append(StringBase64.TO_BASE64_TABLE.charAt(((data.charAt(i).toInt() & 0x03) << 4) + (data.charAt(i + 1).toInt() >> 4))); + result.append(StringBase64.TO_BASE64_TABLE.charAt(((data.charAt(i + 1).toInt() & 0x0f) << 2) + (data.charAt(i + 2).toInt() >> 6))); + result.append(StringBase64.TO_BASE64_TABLE.charAt(data.charAt(i + 2).toInt() & 0x3f)); } if (length % 3 != 0) { i = length - (length % 3); - result.append(StringBase64.TO_BASE64_TABLE.charAt(data.charAt(i) >> 2)); + result.append(StringBase64.TO_BASE64_TABLE.charAt(data.charAt(i).toInt() >> 2)); if ((length % 3) == 2) { - result.append(StringBase64.TO_BASE64_TABLE.charAt(((data.charAt(i) & 0x03) << 4) + (data.charAt(i + 1) >> 4))); - result.append(StringBase64.TO_BASE64_TABLE.charAt((data.charAt(i + 1) & 0x0f) << 2)); + result.append(StringBase64.TO_BASE64_TABLE.charAt(((data.charAt(i).toInt() & 0x03) << 4) + (data.charAt(i + 1).toInt() >> 4))); + result.append(StringBase64.TO_BASE64_TABLE.charAt((data.charAt(i + 1).toInt() & 0x0f) << 2)); result.append(StringBase64.BASE64PAD); } else { - result.append(StringBase64.TO_BASE64_TABLE.charAt((data.charAt(i) & 0x03) << 4)); + result.append(StringBase64.TO_BASE64_TABLE.charAt((data.charAt(i).toInt() & 0x03) << 4)); result.append(StringBase64.BASE64PAD); result.append(StringBase64.BASE64PAD); } @@ -48,7 +48,7 @@ export class StringBase64 { let leftbits : int = 0; let leftdata : int = 0; for (let i : int = 0; i < data.length; i++) { - let c : int = StringBase64.TO_BINARY_TABLE[data.charAt(i) & 0x7f]; + let c : int = StringBase64.TO_BINARY_TABLE[data.charAt(i).toInt() & 0x7f]; let padding : boolean = data.charAt(i) == StringBase64.BASE64PAD; if (c == -1) { continue; diff --git a/ets2panda/test/parser/ets/cast_expressions-expected.txt b/ets2panda/test/parser/ets/cast_expressions-expected.txt index 681bcf4150..2b4274116c 100644 --- a/ets2panda/test/parser/ets/cast_expressions-expected.txt +++ b/ets2panda/test/parser/ets/cast_expressions-expected.txt @@ -4953,8 +4953,77 @@ } }, "init": { - "type": "CharLiteral", - "value": "*", + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 76, + "column": 21, + "program": "cast_expressions.ets" + }, + "end": { + "line": 76, + "column": 24, + "program": "cast_expressions.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 76, + "column": 25, + "program": "cast_expressions.ets" + }, + "end": { + "line": 76, + "column": 31, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 76, + "column": 21, + "program": "cast_expressions.ets" + }, + "end": { + "line": 76, + "column": 31, + "program": "cast_expressions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 42, + "loc": { + "start": { + "line": 76, + "column": 32, + "program": "cast_expressions.ets" + }, + "end": { + "line": 76, + "column": 34, + "program": "cast_expressions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 76, @@ -4963,7 +5032,7 @@ }, "end": { "line": 76, - "column": 23, + "column": 35, "program": "cast_expressions.ets" } } @@ -4976,7 +5045,7 @@ }, "end": { "line": 76, - "column": 23, + "column": 35, "program": "cast_expressions.ets" } } @@ -4991,7 +5060,7 @@ }, "end": { "line": 76, - "column": 24, + "column": 36, "program": "cast_expressions.ets" } } @@ -5116,10 +5185,45 @@ }, "arguments": [ { - "type": "TSAsExpression", - "expression": { - "type": "NumberLiteral", - "value": 42, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 77, + "column": 30, + "program": "cast_expressions.ets" + }, + "end": { + "line": 77, + "column": 33, + "program": "cast_expressions.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 77, + "column": 34, + "program": "cast_expressions.ets" + }, + "end": { + "line": 77, + "column": 40, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 77, @@ -5128,26 +5232,30 @@ }, "end": { "line": 77, - "column": 32, + "column": 40, "program": "cast_expressions.ets" } } }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 77, - "column": 36, - "program": "cast_expressions.ets" - }, - "end": { - "line": 77, - "column": 40, - "program": "cast_expressions.ets" + "arguments": [ + { + "type": "NumberLiteral", + "value": 42, + "loc": { + "start": { + "line": 77, + "column": 41, + "program": "cast_expressions.ets" + }, + "end": { + "line": 77, + "column": 43, + "program": "cast_expressions.ets" + } } } - }, + ], + "optional": false, "loc": { "start": { "line": 77, @@ -5156,7 +5264,7 @@ }, "end": { "line": 77, - "column": 32, + "column": 44, "program": "cast_expressions.ets" } } @@ -5170,7 +5278,7 @@ }, "end": { "line": 77, - "column": 42, + "column": 46, "program": "cast_expressions.ets" } } @@ -5183,7 +5291,7 @@ }, "end": { "line": 77, - "column": 42, + "column": 46, "program": "cast_expressions.ets" } } @@ -5198,7 +5306,7 @@ }, "end": { "line": 77, - "column": 42, + "column": 46, "program": "cast_expressions.ets" } } diff --git a/ets2panda/test/parser/ets/cast_expressions.ets b/ets2panda/test/parser/ets/cast_expressions.ets index dafa81bb4f..7dade98a13 100644 --- a/ets2panda/test/parser/ets/cast_expressions.ets +++ b/ets2panda/test/parser/ets/cast_expressions.ets @@ -73,8 +73,8 @@ function short_test(): void { } function char_test(): void { - let char_: char = 42; - let Char_: Char = new Char(42 as char); + let char_: char = Int.toChar(42); + let Char_: Char = new Char(Int.toChar(42)); { // Casting to primitive types diff --git a/ets2panda/test/parser/ets/conditionalExpressionType-expected.txt b/ets2panda/test/parser/ets/conditionalExpressionType-expected.txt index ea9efc5753..57c1c000b0 100644 --- a/ets2panda/test/parser/ets/conditionalExpressionType-expected.txt +++ b/ets2panda/test/parser/ets/conditionalExpressionType-expected.txt @@ -235,8 +235,77 @@ } }, "init": { - "type": "CharLiteral", - "value": "d", + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 20, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 17, + "column": 23, + "program": "conditionalExpressionType.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 24, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 17, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 17, + "column": 20, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 17, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 100, + "loc": { + "start": { + "line": 17, + "column": 31, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 17, + "column": 34, + "program": "conditionalExpressionType.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 17, @@ -245,7 +314,7 @@ }, "end": { "line": 17, - "column": 23, + "column": 35, "program": "conditionalExpressionType.ets" } } @@ -258,7 +327,7 @@ }, "end": { "line": 17, - "column": 23, + "column": 35, "program": "conditionalExpressionType.ets" } } @@ -273,7 +342,7 @@ }, "end": { "line": 17, - "column": 24, + "column": 36, "program": "conditionalExpressionType.ets" } } @@ -301,9 +370,56 @@ } }, "init": { - "type": "Identifier", - "name": "a", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 18, + "column": 17, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 18, + "column": 21, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 24, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 18, + "column": 25, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "NumberLiteral", + "value": 68, + "loc": { + "start": { + "line": 18, + "column": 28, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 18, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 18, @@ -449,8 +565,56 @@ } }, "init": { - "type": "NumberLiteral", - "value": 68, + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 21, + "column": 15, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 21, + "column": 20, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 23, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 21, + "column": 24, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "NumberLiteral", + "value": 68, + "loc": { + "start": { + "line": 21, + "column": 27, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 21, + "column": 29, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 21, @@ -628,9 +792,56 @@ } }, "init": { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 24, + "column": 17, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 24, + "column": 21, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 24, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 24, + "column": 25, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "NumberLiteral", + "value": 419, + "loc": { + "start": { + "line": 24, + "column": 28, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 24, + "column": 31, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 24, @@ -710,8 +921,77 @@ } }, "init": { - "type": "CharLiteral", - "value": "\u0003", + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 20, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 26, + "column": 23, + "program": "conditionalExpressionType.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 24, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 26, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 20, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 26, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 26, + "column": 31, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 26, + "column": 32, + "program": "conditionalExpressionType.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 26, @@ -720,7 +1000,7 @@ }, "end": { "line": 26, - "column": 21, + "column": 33, "program": "conditionalExpressionType.ets" } } @@ -733,7 +1013,7 @@ }, "end": { "line": 26, - "column": 21, + "column": 33, "program": "conditionalExpressionType.ets" } } @@ -748,7 +1028,7 @@ }, "end": { "line": 26, - "column": 22, + "column": 34, "program": "conditionalExpressionType.ets" } } @@ -776,8 +1056,56 @@ } }, "init": { - "type": "NumberLiteral", - "value": 665, + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 27, + "column": 18, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 27, + "column": 23, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 26, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 27, + "column": 27, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "NumberLiteral", + "value": 665, + "loc": { + "start": { + "line": 27, + "column": 30, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 27, + "column": 33, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 27, @@ -955,9 +1283,56 @@ } }, "init": { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 30, + "column": 17, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 30, + "column": 21, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 24, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 30, + "column": 25, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "NumberLiteral", + "value": 665, + "loc": { + "start": { + "line": 30, + "column": 28, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 30, + "column": 31, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 30, @@ -1103,9 +1478,56 @@ } }, "init": { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 33, + "column": 17, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 33, + "column": 21, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 24, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 33, + "column": 25, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "NumberLiteral", + "value": 665419, + "loc": { + "start": { + "line": 33, + "column": 28, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 33, + "column": 34, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 33, @@ -1251,8 +1673,56 @@ } }, "init": { - "type": "NumberLiteral", - "value": 30, + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 36, + "column": 19, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 36, + "column": 24, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "g", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 27, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 36, + "column": 28, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "NumberLiteral", + "value": 30, + "loc": { + "start": { + "line": 36, + "column": 31, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 36, + "column": 33, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 36, @@ -1633,9 +2103,57 @@ } }, "init": { - "type": "Identifier", - "name": "a", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 42, + "column": 17, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 42, + "column": 21, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 42, + "column": 24, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 42, + "column": 25, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 42, + "column": 28, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 42, + "column": 29, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 42, @@ -1891,12 +2409,60 @@ "column": 12, "program": "conditionalExpressionType.ets" } - } - }, - "init": { - "type": "Identifier", - "name": "b", - "decorators": [], + } + }, + "init": { + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 46, + "column": 15, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 46, + "column": 20, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 46, + "column": 23, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 46, + "column": 24, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 46, + "column": 27, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 46, + "column": 28, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 46, @@ -2616,8 +3182,77 @@ } }, "init": { - "type": "CharLiteral", - "value": "\u0002", + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 56, + "column": 20, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 56, + "column": 23, + "program": "conditionalExpressionType.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 56, + "column": 24, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 56, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 56, + "column": 20, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 56, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 56, + "column": 31, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 56, + "column": 32, + "program": "conditionalExpressionType.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 56, @@ -2626,7 +3261,7 @@ }, "end": { "line": 56, - "column": 21, + "column": 33, "program": "conditionalExpressionType.ets" } } @@ -2639,7 +3274,7 @@ }, "end": { "line": 56, - "column": 21, + "column": 33, "program": "conditionalExpressionType.ets" } } @@ -2654,7 +3289,7 @@ }, "end": { "line": 56, - "column": 22, + "column": 34, "program": "conditionalExpressionType.ets" } } @@ -2682,9 +3317,57 @@ } }, "init": { - "type": "Identifier", - "name": "b", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 58, + "column": 17, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 58, + "column": 22, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 58, + "column": 25, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 58, + "column": 26, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 58, + "column": 29, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 58, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 58, @@ -2749,9 +3432,57 @@ } }, "init": { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 59, + "column": 15, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 59, + "column": 20, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "b", + "decorators": [], + "loc": { + "start": { + "line": 59, + "column": 23, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 59, + "column": 24, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 59, + "column": 27, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 59, + "column": 28, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 59, @@ -2816,9 +3547,57 @@ } }, "init": { - "type": "Identifier", - "name": "d", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 60, + "column": 17, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 60, + "column": 22, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 60, + "column": 25, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 60, + "column": 26, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 60, + "column": 29, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 60, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 60, @@ -2883,9 +3662,57 @@ } }, "init": { - "type": "Identifier", - "name": "e", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 61, + "column": 18, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 61, + "column": 23, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 61, + "column": 26, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 61, + "column": 27, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "Identifier", + "name": "e", + "decorators": [], + "loc": { + "start": { + "line": 61, + "column": 30, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 61, + "column": 31, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 61, @@ -2950,9 +3777,57 @@ } }, "init": { - "type": "Identifier", - "name": "f", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 62, + "column": 17, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 62, + "column": 22, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "e", + "decorators": [], + "loc": { + "start": { + "line": 62, + "column": 25, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 62, + "column": 26, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 62, + "column": 29, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 62, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 62, @@ -3017,9 +3892,57 @@ } }, "init": { - "type": "Identifier", - "name": "g", - "decorators": [], + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": false, + "loc": { + "start": { + "line": 63, + "column": 17, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 63, + "column": 22, + "program": "conditionalExpressionType.ets" + } + } + }, + "consequent": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 63, + "column": 25, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 63, + "column": 26, + "program": "conditionalExpressionType.ets" + } + } + }, + "alternate": { + "type": "Identifier", + "name": "g", + "decorators": [], + "loc": { + "start": { + "line": 63, + "column": 29, + "program": "conditionalExpressionType.ets" + }, + "end": { + "line": 63, + "column": 30, + "program": "conditionalExpressionType.ets" + } + } + }, "loc": { "start": { "line": 63, diff --git a/ets2panda/test/parser/ets/conditionalExpressionType.ets b/ets2panda/test/parser/ets/conditionalExpressionType.ets index a3094001cd..5c8719d20b 100644 --- a/ets2panda/test/parser/ets/conditionalExpressionType.ets +++ b/ets2panda/test/parser/ets/conditionalExpressionType.ets @@ -14,7 +14,7 @@ */ function constantCases(): void{ - let a : char = 100; + let a : char = Int.toChar(100); let first = true ? a : 68; let b : byte = 50; @@ -23,7 +23,7 @@ function constantCases(): void{ let c : Short = 721; let third = true ? c : 419; - let d : char = 3; + let d : char = Int.toChar(3); let fourth = false ? c : 665; let e : Byte = 88; @@ -53,7 +53,7 @@ function dominantNumericCases(): void{ let d : int = 2; let e : Short = 2; let f : byte = 2; - let g : char = 2; + let g : char = Int.toChar(2); let first = false ? a : b; let sec = false ? b : c; diff --git a/ets2panda/test/parser/ets/conversions-expected.txt b/ets2panda/test/parser/ets/conversions-expected.txt index 4108a9fc06..3ec0f0bde2 100644 --- a/ets2panda/test/parser/ets/conversions-expected.txt +++ b/ets2panda/test/parser/ets/conversions-expected.txt @@ -235,29 +235,45 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "NumberLiteral", - "value": 0, - "loc": { - "start": { - "line": 17, - "column": 19, - "program": "conversions.ets" + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Byte", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 23, + "program": "conversions.ets" + }, + "end": { + "line": 17, + "column": 27, + "program": "conversions.ets" + } + } }, - "end": { - "line": 17, - "column": 20, - "program": "conversions.ets" + "loc": { + "start": { + "line": 17, + "column": 23, + "program": "conversions.ets" + }, + "end": { + "line": 17, + "column": 28, + "program": "conversions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, "loc": { "start": { "line": 17, - "column": 24, + "column": 23, "program": "conversions.ets" }, "end": { @@ -267,6 +283,24 @@ } } }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 17, + "column": 28, + "program": "conversions.ets" + }, + "end": { + "line": 17, + "column": 29, + "program": "conversions.ets" + } + } + } + ], "loc": { "start": { "line": 17, @@ -274,8 +308,8 @@ "program": "conversions.ets" }, "end": { - "line": 17, - "column": 20, + "line": 18, + "column": 8, "program": "conversions.ets" } } @@ -287,8 +321,8 @@ "program": "conversions.ets" }, "end": { - "line": 17, - "column": 20, + "line": 18, + "column": 8, "program": "conversions.ets" } } @@ -302,8 +336,8 @@ "program": "conversions.ets" }, "end": { - "line": 17, - "column": 20, + "line": 18, + "column": 8, "program": "conversions.ets" } } @@ -346,9 +380,60 @@ } }, "init": { - "type": "Identifier", - "name": "s", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "s", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 19, + "program": "conversions.ets" + }, + "end": { + "line": 18, + "column": 20, + "program": "conversions.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 21, + "program": "conversions.ets" + }, + "end": { + "line": 18, + "column": 27, + "program": "conversions.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 18, + "column": 19, + "program": "conversions.ets" + }, + "end": { + "line": 18, + "column": 27, + "program": "conversions.ets" + } + } + }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 18, @@ -357,7 +442,7 @@ }, "end": { "line": 18, - "column": 20, + "column": 29, "program": "conversions.ets" } } @@ -370,7 +455,7 @@ }, "end": { "line": 18, - "column": 20, + "column": 29, "program": "conversions.ets" } } @@ -385,7 +470,7 @@ }, "end": { "line": 18, - "column": 20, + "column": 29, "program": "conversions.ets" } } diff --git a/ets2panda/test/parser/ets/conversions.ets b/ets2panda/test/parser/ets/conversions.ets index 6a2131281f..d8a9e5a1f3 100644 --- a/ets2panda/test/parser/ets/conversions.ets +++ b/ets2panda/test/parser/ets/conversions.ets @@ -14,8 +14,8 @@ */ function main(): int { - let s: byte = 0 as byte - let d: char = s + let s: byte = new Byte(0) + let d: char = s.toChar() if (d != c'\u0000') { return 1; } diff --git a/ets2panda/test/parser/ets/this_cmp_object-expected.txt b/ets2panda/test/parser/ets/this_cmp_object-expected.txt index a4284a90a5..71d535340c 100644 --- a/ets2panda/test/parser/ets/this_cmp_object-expected.txt +++ b/ets2panda/test/parser/ets/this_cmp_object-expected.txt @@ -161,7 +161,53 @@ } }, "init": { - "type": "ThisExpression", + "type": "ConditionalExpression", + "test": { + "type": "BooleanLiteral", + "value": true, + "loc": { + "start": { + "line": 18, + "column": 26, + "program": "this_cmp_object.ets" + }, + "end": { + "line": 18, + "column": 30, + "program": "this_cmp_object.ets" + } + } + }, + "consequent": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 18, + "column": 33, + "program": "this_cmp_object.ets" + }, + "end": { + "line": 18, + "column": 37, + "program": "this_cmp_object.ets" + } + } + }, + "alternate": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 18, + "column": 40, + "program": "this_cmp_object.ets" + }, + "end": { + "line": 18, + "column": 44, + "program": "this_cmp_object.ets" + } + } + }, "loc": { "start": { "line": 18, diff --git a/ets2panda/test/test-lists/ets-runtime/ets-runtime-excluded.txt b/ets2panda/test/test-lists/ets-runtime/ets-runtime-excluded.txt new file mode 100644 index 0000000000..1afdd6a0ff --- /dev/null +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-excluded.txt @@ -0,0 +1,14 @@ +# Deprecated operations on char #27402 +ArrayLiteral.ets +MaxBoundInt.ets +StringBase64.ets +UpdateExpression.ets +boxingConversions3.ets +boxingConversions4.ets +castSequence.ets +char-type.ets +explicit_cast_boxed_expressions.ets +fieldImplicitCasting.ets +implicit_cast_boxed_expressions.ets +non-const-capture.ets +string-builder.ets \ No newline at end of file diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 4912fbec17..2135d2b61c 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -279,6 +279,10 @@ semantic: id: 205 message: "Argument must be an instance of '{}' or '{}'" +- name: CHAR_TO_STR_CONVERSION + id: 397 + message: "Implicit 'char->string' conversion disallowed." + - name: CIRCULAR_DEPENDENCY id: 308 message: "Circular dependency detected for identifier: {}" @@ -522,11 +526,15 @@ semantic: id: 80 message: "The extension accessor '{}' has the same name with method in class {}" -- name: FIELD_ASSIGN_TYPE_MISMATCH - id: 298 - message: "Cannot assign to a {} variable {}" +- name: FIELD_ASSIGN_TO_CONST + id: 398 + message: "Cannot assign to a const variable {}" code_fix_ids: [FixConvertConstToLet] +- name: FIELD_ASSIGN_TO_READONLY + id: 298 + message: "Cannot assign to a readonly field {}" + - name: FIELD_REASSIGNMENT id: 297 message: "Cannot reassign {} {}" -- Gitee