diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index bbbf61b396f61783b6c9cef47605998bf8770358..db7202dfbc996aeffcd7d6d8fe8ef3cd3cf509ae 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -1946,71 +1946,11 @@ void ETSCompiler::CompileCastUnboxable(const ir::TSAsExpression *expr) const void ETSCompiler::CompileCast(const ir::TSAsExpression *expr) const { ETSGen *etsg = GetETSGen(); - auto *targetType = etsg->Checker()->GetApparentType(expr->TsType()); - switch (checker::ETSChecker::TypeKind(targetType)) { - case checker::TypeFlag::ETS_BOOLEAN: { - etsg->CastToBoolean(expr); - break; - } - case checker::TypeFlag::CHAR: { - etsg->CastToChar(expr); - break; - } - case checker::TypeFlag::BYTE: { - etsg->CastToByte(expr); - break; - } - case checker::TypeFlag::SHORT: { - etsg->CastToShort(expr); - break; - } - case checker::TypeFlag::INT: { - etsg->CastToInt(expr); - break; - } - case checker::TypeFlag::LONG: { - etsg->CastToLong(expr); - break; - } - case checker::TypeFlag::FLOAT: { - etsg->CastToFloat(expr); - break; - } - case checker::TypeFlag::DOUBLE: { - etsg->CastToDouble(expr); - break; - } - case checker::TypeFlag::ETS_ARRAY: - case checker::TypeFlag::ETS_OBJECT: - case checker::TypeFlag::ETS_TYPE_PARAMETER: - case checker::TypeFlag::ETS_NONNULLISH: - case checker::TypeFlag::ETS_UNION: - case checker::TypeFlag::ETS_NULL: - case checker::TypeFlag::ETS_UNDEFINED: { - etsg->CastToReftype(expr, targetType, expr->isUncheckedCast_); - break; - } - case checker::TypeFlag::ETS_DYNAMIC_TYPE: { - etsg->CastToDynamic(expr, targetType->AsETSDynamicType()); - break; - } - case checker::TypeFlag::ETS_STRING_ENUM: - [[fallthrough]]; - case checker::TypeFlag::ETS_ENUM: { - auto *const signature = expr->TsType()->IsETSEnumType() - ? expr->TsType()->AsETSEnumType()->FromIntMethod().globalSignature - : expr->TsType()->AsETSStringEnumType()->FromIntMethod().globalSignature; - ArenaVector arguments(etsg->Allocator()->Adapter()); - arguments.push_back(expr->expression_); - etsg->CallStatic(expr, signature, arguments); - etsg->SetAccumulatorType(signature->ReturnType()); - break; - } - default: { - UNREACHABLE(); - } - } + ASSERT(expr); + ASSERT(etsg); + + etsg->CastTo(expr); } void ETSCompiler::Compile(const ir::TSAsExpression *expr) const diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index d06bacd2a9341d9c216d711b791b5cc712ffa21b..e4d47028d43e549d1d4a0dca102d56cbf9dd36ad 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -241,6 +241,52 @@ util::StringView ETSGen::FormDynamicModulePropReference(const varbinder::Variabl return FormDynamicModulePropReference(import); } +ETSGen::CastTableType &ETSGen::CastTable() +{ + static auto castToEnum = [](ETSGen *instance, const ir::TSAsExpression *expr, const checker::Type *) { + instance->CastToEnum(expr); + }; + + static auto castToArrayOrObject = [](ETSGen *instance, const ir::TSAsExpression *expr, + const checker::Type *targetType) { + instance->CastToReftype(expr, targetType, expr->IsUncheckedCast()); + }; + + static CastTableType castTable = { + {checker::TypeFlag::ETS_BOOLEAN, [](ETSGen *instance, const ir::TSAsExpression *expr, + const checker::Type *) { instance->CastToBoolean(expr); }}, + {checker::TypeFlag::CHAR, + [](ETSGen *instance, const ir::TSAsExpression *expr, const checker::Type *) { instance->CastToChar(expr); }}, + {checker::TypeFlag::BYTE, + [](ETSGen *instance, const ir::TSAsExpression *expr, const checker::Type *) { instance->CastToByte(expr); }}, + {checker::TypeFlag::SHORT, + [](ETSGen *instance, const ir::TSAsExpression *expr, const checker::Type *) { instance->CastToShort(expr); }}, + {checker::TypeFlag::DOUBLE, + [](ETSGen *instance, const ir::TSAsExpression *expr, const checker::Type *) { instance->CastToDouble(expr); }}, + {checker::TypeFlag::FLOAT, + [](ETSGen *instance, const ir::TSAsExpression *expr, const checker::Type *) { instance->CastToFloat(expr); }}, + {checker::TypeFlag::LONG, + [](ETSGen *instance, const ir::TSAsExpression *expr, const checker::Type *) { instance->CastToLong(expr); }}, + {checker::TypeFlag::INT, + [](ETSGen *instance, const ir::TSAsExpression *expr, const checker::Type *) { instance->CastToInt(expr); }}, + {checker::TypeFlag::ETS_DYNAMIC_TYPE, + [](ETSGen *instance, const ir::TSAsExpression *expr, const checker::Type *targetType) { + instance->CastToDynamic(expr, targetType->AsETSDynamicType()); + }}, + {checker::TypeFlag::ETS_ENUM, castToEnum}, + {checker::TypeFlag::ETS_STRING_ENUM, castToEnum}, + {checker::TypeFlag::ETS_ARRAY, castToArrayOrObject}, + {checker::TypeFlag::ETS_OBJECT, castToArrayOrObject}, + {checker::TypeFlag::ETS_TYPE_PARAMETER, castToArrayOrObject}, + {checker::TypeFlag::ETS_NONNULLISH, castToArrayOrObject}, + {checker::TypeFlag::ETS_UNION, castToArrayOrObject}, + {checker::TypeFlag::ETS_NULL, castToArrayOrObject}, + {checker::TypeFlag::ETS_UNDEFINED, castToArrayOrObject}, + }; + + return castTable; +} + void ETSGen::LoadAccumulatorDynamicModule(const ir::AstNode *node, const ir::ETSImportDeclaration *import) { ASSERT(import->Language().IsDynamic()); @@ -1395,6 +1441,22 @@ void ETSGen::EmitLocalBoxSet(ir::AstNode const *node, varbinder::LocalVariable * SetAccumulatorType(Checker()->GetGlobalTypesHolder()->GlobalVoidType()); } +void ETSGen::CastTo(const ir::TSAsExpression *expr) +{ + auto targetType = Checker()->GetApparentType(expr->TsType()); + auto typeFlag = checker::ETSChecker::TypeKind(targetType); + auto castTable = CastTable(); + + auto it = castTable.find(typeFlag); + if (it != castTable.end()) { + auto castFunc = it->second; + castFunc(this, expr, targetType); + return; + } + + UNREACHABLE(); +} + void ETSGen::CastToBoolean([[maybe_unused]] const ir::AstNode *node) { auto typeKind = checker::ETSChecker::TypeKind(GetAccumulatorType()); @@ -1959,6 +2021,17 @@ void ETSGen::CastDynamicTo(const ir::AstNode *node, enum checker::TypeFlag typeF SetAccumulatorType(objectType); } +void ETSGen::CastToEnum(const ir::TSAsExpression *expr) +{ + auto *const signature = expr->TsType()->IsETSEnumType() + ? expr->TsType()->AsETSEnumType()->FromIntMethod().globalSignature + : expr->TsType()->AsETSStringEnumType()->FromIntMethod().globalSignature; + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(const_cast(expr->Expr())); + CallStatic(expr, signature, arguments); + SetAccumulatorType(signature->ReturnType()); +} + void ETSGen::ToBinaryResult(const ir::AstNode *node, Label *ifFalse) { Label *end = AllocLabel(); diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index dda9e4e2c8b2f38d1bf85908b9e978e4fd2be651..72817a269884af32b3077eff3efcdd5708d5f298 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -474,6 +474,7 @@ public: void CompileStatements(const ArenaVector &statements); // Cast + void CastTo(const ir::TSAsExpression *expr); void CastToBoolean(const ir::AstNode *node); void CastToByte(const ir::AstNode *node); void CastToChar(const ir::AstNode *node); @@ -487,6 +488,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 CastToEnum(const ir::TSAsExpression *expr); void InternalIsInstance(const ir::AstNode *node, const checker::Type *target); void InternalCheckCast(const ir::AstNode *node, const checker::Type *target); @@ -601,6 +603,11 @@ public: } ~ETSGen() override = default; + + using CastTableType = + std::unordered_map>; + NO_COPY_SEMANTIC(ETSGen); NO_MOVE_SEMANTIC(ETSGen); @@ -1097,6 +1104,8 @@ private: util::StringView FormDynamicModulePropReference(const varbinder::Variable *var); util::StringView FormDynamicModulePropReference(const ir::ETSImportDeclaration *import); + static CastTableType &CastTable(); + friend class TargetTypeContext; VReg acc_ {}; diff --git a/ets2panda/ir/ts/tsAsExpression.h b/ets2panda/ir/ts/tsAsExpression.h index 69688f971e11cfb9c0a12ec592d86aa0c1c580aa..bb16cb169087cf9c86541702fb65b6496d4cf93a 100644 --- a/ets2panda/ir/ts/tsAsExpression.h +++ b/ets2panda/ir/ts/tsAsExpression.h @@ -58,6 +58,11 @@ public: [[nodiscard]] TSAsExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; + bool IsUncheckedCast() const + { + return isUncheckedCast_; + } + void SetUncheckedCast(bool isUncheckedCast) noexcept { isUncheckedCast_ = isUncheckedCast;