diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 7917598b0eebf914b29a16698988b4b2413f04ac..a6e56ef1fa088b6e1e7553c664d399702bcc5fe7 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -2596,6 +2596,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->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT | checker::TypeFlag::TYPE_PARAMETER)) { auto *const boxedTargetType = checker->PrimitiveTypeAsETSBuiltinType(targetType); diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index ee308f342429b7330ab2d624f9c09731fe9366f0..4d946c0ac0578e5974fd6ad523c1d62b11143e54 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -142,11 +142,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; } @@ -657,7 +653,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 b02188e7a176a16949585a76863a7527634d42a2..215551200df09280c5b97d1c98788213e1f9e069 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -320,8 +320,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 f2492872b9cb590fc1ba1f67c61d5fbe0e5cb10f..4e31a048defc6c09897d2602a3af61f91a70b651 100644 --- a/ets2panda/checker/types/ets/etsBigIntType.h +++ b/ets2panda/checker/types/ets/etsBigIntType.h @@ -26,6 +26,7 @@ public: ETSObjectFlags::CLASS | ETSObjectFlags::BUILTIN_BIGINT | ETSObjectFlags::RESOLVED_SUPER) { SetSuperType(super); + 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 ef3a9323e2e79b7f4b5d44b8de4b160b10a0ca87..7576628ea6fd11239d1af801eb06962e2fca43b6 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_VOID, ETS_PRIMITIVE_RETURN = BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | CHAR | ETS_BOOLEAN | ETS_ENUM, ETS_ARRAY_INDEX = BYTE | SHORT | INT, @@ -133,7 +134,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 e7c26b723e27ac279a98511046a0115664ff668f..8eb32d7f2360a0883a700a3ab123a5d0090df3a7 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -2042,6 +2042,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 1d6a51b9abcf1dba55e224cd47a2ccfc63f17504..3d59e081fc0cd7fa3a92ad02fa6675901d66073d 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -616,9 +616,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) @@ -1756,6 +1757,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()) { @@ -2582,6 +2631,7 @@ void ETSGen::LoadArrayElement(const ir::AstNode *node, VReg objectReg) Ra().Emit(node, objectReg); break; } + case checker::TypeFlag::BIG_INT_OBJECT: case checker::TypeFlag::ETS_ARRAY: case checker::TypeFlag::ETS_OBJECT: case checker::TypeFlag::ETS_TYPE_PARAMETER: @@ -2631,6 +2681,7 @@ void ETSGen::StoreArrayElement(const ir::AstNode *node, VReg objectReg, VReg ind Ra().Emit(node, objectReg, index); break; } + case checker::TypeFlag::BIG_INT_OBJECT: case checker::TypeFlag::ETS_ARRAY: case checker::TypeFlag::ETS_OBJECT: case checker::TypeFlag::ETS_TYPE_PARAMETER: diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index 1daa3360f7aacc69be86bc85008beb5508cbe640..c3bcebfccb141f43517cb54ad061a19257d17adf 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -487,6 +487,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 7e3cc445f82ada299f3f2f2519a297c88dd7202b..861cfdfaa2abf4afd862ad75c9cc166d1ddae25b 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -432,6 +432,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 {