diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 2ebfd84bc484d56d0067569d8ec1314df2d67697..818c67dd0327163509d60fbfe82f99f16d423091 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -2306,6 +2306,16 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const auto *const sourceType = expr->Expr()->Check(checker); + if (targetType->HasTypeFlag(checker::TypeFlag::ETS_BIGINT)) { + if ((sourceType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && + !sourceType->HasTypeFlag(checker::TypeFlag::VOID)) || + sourceType->HasTypeFlag(checker::TypeFlag::ETS_BIGINT)) { + expr->SetTsType(checker->GlobalBuiltinETSBigIntType()); + return expr->TsType(); + } + checker->ThrowTypeError({"Cast non primitive type to BigInt is prohibited."}, expr->Start()); + } + if (targetType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && sourceType->IsETSReferenceType()) { auto *const boxedTargetType = checker->PrimitiveTypeAsETSBuiltinType(targetType); if (!checker->Relation()->IsIdenticalTo(sourceType, boxedTargetType)) { diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index b0798dd1a77f453011a36621064eb7e110537d36..3e780665888839128c47cd44e735dd3f735ca0b3 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -139,11 +139,7 @@ bool ETSChecker::CheckBinaryOperatorForBigInt(Type *left, Type *right, ir::Expre return false; } - if (!left->IsETSBigIntType()) { - return false; - } - - if (!right->IsETSBigIntType()) { + if (!left->IsETSBigIntType() || !right->IsETSBigIntType()) { return false; } @@ -684,7 +680,7 @@ std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: return {GlobalETSBooleanType(), GlobalETSBooleanType()}; default: - return {leftType, rightType}; + return {GlobalBuiltinETSBigIntType(), GlobalBuiltinETSBigIntType()}; } }; diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index 6ca8ee9d015faa32e0a3ceb9965287e05b199d33..9603b9ffae7e2b77991baa90b86796d1b8a75ca3 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -325,8 +325,9 @@ ETSObjectType *ETSChecker::CreateETSObjectTypeCheckBuiltins(util::StringView nam return GlobalBuiltinETSBigIntType(); } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_BIG_INT_BUILTIN)] = - CreateNewETSObjectType(name, declNode, flags | ETSObjectFlags::BUILTIN_BIGINT); + auto bigintEtsObject = CreateNewETSObjectType(name, declNode, flags | ETSObjectFlags::BUILTIN_BIGINT); + bigintEtsObject->AddTypeFlag(checker::TypeFlag::ETS_BIGINT); + GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_BIG_INT_BUILTIN)] = bigintEtsObject; GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_BIG_INT)] = Allocator()->New(Allocator(), GlobalBuiltinETSBigIntType()); diff --git a/ets2panda/checker/types/ets/etsBigIntType.h b/ets2panda/checker/types/ets/etsBigIntType.h index 2d0eb0ce57834f3aa1efc10cd969416ab2c60155..3bbc546f1df5b2b45407457c02176eb03551ca38 100644 --- a/ets2panda/checker/types/ets/etsBigIntType.h +++ b/ets2panda/checker/types/ets/etsBigIntType.h @@ -27,6 +27,7 @@ public: { SetSuperType(super); SetAssemblerName(compiler::Signatures::BUILTIN_BIGINT); + typeFlags_ |= TypeFlag::ETS_BIGINT; } explicit ETSBigIntType(ArenaAllocator *allocator, ETSObjectType *super, TypeRelation *relation, diff --git a/ets2panda/checker/types/typeFlag.h b/ets2panda/checker/types/typeFlag.h index 54f6541d5f81e6f7ad081a163bed2eb3886b62fd..0e2c6d2379487d1a1e8650fbc2828e294a325b1e 100644 --- a/ets2panda/checker/types/typeFlag.h +++ b/ets2panda/checker/types/typeFlag.h @@ -84,11 +84,12 @@ enum class TypeFlag : uint64_t { ETS_NULL = 1ULL << 59ULL, // ETS null ETS_UNDEFINED = 1ULL << 60ULL, // ETS undefined ETS_NONNULLISH = 1ULL << 61ULL, // ETS nonnullish type parameter + ETS_BIGINT = 1ULL << 62ULL, ETS_DYNAMIC_TYPE = ETS_OBJECT | ETS_DYNAMIC_FLAG, ETS_DYNAMIC_FUNCTION_TYPE = FUNCTION | ETS_DYNAMIC_FLAG, ETS_TYPE = BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | CHAR | ETS_BOOLEAN | ETS_VOID | ETS_OBJECT | ETS_ARRAY | WILDCARD | ETS_TYPE_PARAMETER | ETS_ENUM | ETS_STRING_ENUM | ETS_DYNAMIC_TYPE | ETS_UNION | ETS_NULL | - ETS_UNDEFINED | ETS_NONNULLISH, + ETS_UNDEFINED | ETS_NONNULLISH | ETS_BIGINT, ETS_PRIMITIVE = BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | CHAR | ETS_BOOLEAN, ETS_PRIMITIVE_RETURN = BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | CHAR | ETS_BOOLEAN | ETS_ENUM, ETS_ARRAY_INDEX = BYTE | SHORT | INT, @@ -134,7 +135,8 @@ enum class TypeFlag : uint64_t { UNIT = LITERAL | UNIQUE_SYMBOL | UNDEFINED | NULL_TYPE, GETTER_SETTER = GETTER | SETTER, CONDITION_EXPRESSION_TYPE = ETS_NULL | ETS_UNDEFINED | ETS_OBJECT | ETS_ARRAY | ETS_UNION | CONSTANT | BYTE | CHAR | - SHORT | INT | LONG | FLOAT | DOUBLE | ETS_BOOLEAN | ETS_ENUM | ETS_STRING_ENUM + SHORT | INT | LONG | FLOAT | DOUBLE | ETS_BOOLEAN | ETS_ENUM | ETS_STRING_ENUM, + BIG_INT_OBJECT = ETS_OBJECT | ETS_BIGINT }; DEFINE_BITOPS(TypeFlag) diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 370fcd4fa8c0234fe06cce6e4e2d5fbfc17329bc..87bcd69c5051332e88807fa16d41469f9b396d87 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -2103,6 +2103,10 @@ void ETSCompiler::CompileCast(const ir::TSAsExpression *expr) const etsg->CastToDouble(expr); break; } + case checker::TypeFlag::BIG_INT_OBJECT: { + etsg->CastToBigint(expr); + break; + } case checker::TypeFlag::ETS_ARRAY: case checker::TypeFlag::ETS_OBJECT: case checker::TypeFlag::ETS_TYPE_PARAMETER: diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index c72da309cea0dce361edfa003220e8d1d4035e7b..6d9f8edf3f2b505165daa4166f0d117c4cfe7988 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -637,9 +637,10 @@ void ETSGen::LoadThis(const ir::AstNode *node) LoadAccumulator(node, GetThisReg()); } -void ETSGen::CreateBigIntObject(const ir::AstNode *node, VReg arg0, std::string_view signature) +void ETSGen::CreateBigIntObject(const ir::AstNode *node, VReg arg0, const std::string_view signature) { Ra().Emit(node, signature, arg0, dummyReg_); + SetAccumulatorType(Checker()->GlobalETSBigIntType()); } void ETSGen::CreateLambdaObjectFromIdentReference(const ir::AstNode *node, ir::ClassDefinition *lambdaObj) @@ -1960,6 +1961,54 @@ void ETSGen::CastToReftype(const ir::AstNode *const node, const checker::Type *c SetAccumulatorType(targetType); } +void ETSGen::CastToBigint(const ir::AstNode *const node) +{ + const VReg value = AllocReg(); + StoreAccumulator(node, value); + auto typeKind = checker::ETSChecker::TypeKind(GetAccumulatorType()); + switch (typeKind) { + case checker::TypeFlag::ETS_BIGINT: + case checker::TypeFlag::BIG_INT_OBJECT: { + break; + } + case checker::TypeFlag::INT: { + CreateBigIntObject(node, value, Signatures::BUILTIN_BIGINT_CTOR_INT); + break; + } + case checker::TypeFlag::ETS_BOOLEAN: { + CreateBigIntObject(node, value, Signatures::BUILTIN_BIGINT_CTOR_BOOLEAN); + break; + } + case checker::TypeFlag::CHAR: { + CreateBigIntObject(node, value, Signatures::BUILTIN_BIGINT_CTOR_CHAR); + break; + } + case checker::TypeFlag::BYTE: { + CreateBigIntObject(node, value, Signatures::BUILTIN_BIGINT_CTOR_BYTE); + break; + } + case checker::TypeFlag::SHORT: { + CreateBigIntObject(node, value, Signatures::BUILTIN_BIGINT_CTOR_SHORT); + break; + } + case checker::TypeFlag::LONG: { + CreateBigIntObject(node, value, Signatures::BUILTIN_BIGINT_CTOR_LONG); + break; + } + case checker::TypeFlag::FLOAT: { + CreateBigIntObject(node, value, Signatures::BUILTIN_BIGINT_CTOR_FLOAT); + break; + } + case checker::TypeFlag::DOUBLE: { + CreateBigIntObject(node, value, Signatures::BUILTIN_BIGINT_CTOR_DOUBLE); + break; + } + default: { + UNREACHABLE(); + } + } +} + void ETSGen::CastDynamicToObject(const ir::AstNode *node, const checker::Type *targetType) { if (targetType->IsETSStringType()) { @@ -2829,6 +2878,10 @@ void ETSGen::LoadArrayElement(const ir::AstNode *node, VReg objectReg) Ra().Emit(node, objectReg); break; } + case checker::TypeFlag::BIG_INT_OBJECT: { + Ra().Emit(node, objectReg); + break; + } default: { UNREACHABLE(); @@ -2875,6 +2928,10 @@ void ETSGen::StoreArrayElement(const ir::AstNode *node, VReg objectReg, VReg ind Ra().Emit(node, objectReg, index); break; } + case checker::TypeFlag::BIG_INT_OBJECT: { + Ra().Emit(node, objectReg, index); + break; + } default: { UNREACHABLE(); diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index 1f76640253074841522061a24a0182f5ff723217..63f70669f39eba631d9de77919984f353336e4e2 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -511,6 +511,7 @@ public: void CastDynamicTo(const ir::AstNode *node, enum checker::TypeFlag typeFlag); void CastToReftype(const ir::AstNode *node, const checker::Type *targetType, bool unchecked); void CastDynamicToObject(const ir::AstNode *node, const checker::Type *targetType); + void CastToBigint(const ir::AstNode *node); void InternalIsInstance(const ir::AstNode *node, const checker::Type *target); void InternalCheckCast(const ir::AstNode *node, const checker::Type *target); diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index 813c238ee0a98a02e21fed786c15877e2cb24680..9b5294fb6d4b2da827d1f916fdda380bb247256b 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -439,6 +439,54 @@ signatures: return_type: PRIMITIVE_VOID ref: BUILTIN_BIGINT_CTOR_BIGINT + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [PRIMITIVE_BOOLEAN] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR_BOOLEAN + + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [PRIMITIVE_CHAR] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR_CHAR + + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [PRIMITIVE_BYTE] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR_BYTE + + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [PRIMITIVE_SHORT] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR_SHORT + + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [PRIMITIVE_INT] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR_INT + + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [PRIMITIVE_LONG] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR_LONG + + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [PRIMITIVE_FLOAT] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR_FLOAT + + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [PRIMITIVE_DOUBLE] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR_DOUBLE + - callee: BUILTIN_BIGINT method_name: $CTOR params: [] diff --git a/ets2panda/test/runtime/ets/BigInt.ets b/ets2panda/test/runtime/ets/BigInt.ets index f69ea85c9632e86fee0fa2282d0e23c898a11cde..e4cca1b88b47ab233c40519cda1a7691f81c4bcb 100644 --- a/ets2panda/test/runtime/ets/BigInt.ets +++ b/ets2panda/test/runtime/ets/BigInt.ets @@ -361,13 +361,42 @@ function test_literals() : void { } function test_cast(): void { + let expected: BigInt = 1559053n; + const v = 1559053 + assert (expected == (v as BigInt)) + const b: byte = 44 + expected = 44n; + assert (expected == (b as BigInt)) + const s: short = -17600 + expected = -17600n; + assert (expected == (s as BigInt)) + const i: int = 1150483640 + expected = 1150483640n + assert (expected == (i as BigInt)) + const l: long = -8223372036854775808 + expected = -8223372036854775808n + assert (expected == (l as BigInt)) + + const d: double = 1.44f + expected = new BigInt(d) + assert (expected == d as BigInt) - // NOTE(kkonsw): casts currently do not work + const f: float = 1.44f + expected = new BigInt(f) + assert (expected == f as BigInt) + + const bl: boolean = true + expected = 1n + assert (expected == f as BigInt) + + const be = 10n + (5 as BigInt) + expected = 15n + assert (expected == be) } function test_bigint_methods(): void { @@ -375,6 +404,9 @@ function test_bigint_methods(): void { const s: short = -17600 const i: int = 1150483640 const l: long = -8223372036854775808 + const f: float = 1.44f + const d: double = 15.55f + const bo: boolean = true; /* Testing BigInt constructor */ let n0 = new BigInt(0) @@ -401,24 +433,36 @@ function test_bigint_methods(): void { assert(n5.toString() == "-8223372036854775808") assert n5 == -8223372036854775808n + let n6 = new BigInt(f) + assert(n6.toString() == (f as int).toString()) + assert(n6 == 1n) + + let n7 = new BigInt(d) + assert(n7.toString() == (d as int).toString()) + assert(n7 == 15n) + + let n8 = new BigInt(bo) + assert(n8.toString() == "1") + assert(n8 == 1n) + let dec = new BigInt("-12392320390239294724747283477947923471101032") assert dec == -12392320390239294724747283477947923471101032n - const n7 = 12392320390239294724747283477947923471101032n + const n9 = 12392320390239294724747283477947923471101032n /* Testing asIntN() static method */ - // assert BigInt.asIntN(0, n7) == 0n - // assert BigInt.asIntN(8, n7) == 104n - // assert BigInt.asIntN(16, n7) == 27752n - // assert BigInt.asIntN(32, n7) == -737317784n - // assert BigInt.asIntN(64, n7) == -7098331616643290008n + // assert BigInt.asIntN(0, n9) == 0n + // assert BigInt.asIntN(8, n9) == 104n + // assert BigInt.asIntN(16, n9) == 27752n + // assert BigInt.asIntN(32, n9) == -737317784n + // assert BigInt.asIntN(64, n9) == -7098331616643290008n /* Testing asUintN() static method */ - // assert BigInt.asUintN(0, n7) == 0n - // assert BigInt.asUintN(8, n7) == 104n - // assert BigInt.asUintN(16, n7) == 27752n - // assert BigInt.asUintN(32, n7) == 3557649512n - // assert BigInt.asUintN(64, n7) == 11348412457066261608n + // assert BigInt.asUintN(0, n9) == 0n + // assert BigInt.asUintN(8, n9) == 104n + // assert BigInt.asUintN(16, n9) == 27752n + // assert BigInt.asUintN(32, n9) == 3557649512n + // assert BigInt.asUintN(64, n9) == 11348412457066261608n } function test_unary(): void {