diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index ec729cf22942eacc61d2ca5a674062973d981b88..73f62a41902d6ec114c3fe2482277447a7cd23a9 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -20,16 +20,7 @@ #include "checker/ETSchecker.h" #include "checker/ets/castingContext.h" #include "checker/ets/typeRelationContext.h" -#include "ir/base/catchClause.h" -#include "ir/base/classProperty.h" -#include "ir/base/classStaticBlock.h" -#include "ir/expressions/identifier.h" -#include "ir/expressions/objectExpression.h" -#include "ir/expressions/arrayExpression.h" -#include "ir/statements/blockStatement.h" -#include "ir/statements/returnStatement.h" #include "util/helpers.h" - namespace panda::es2panda::checker { ETSChecker *ETSAnalyzer::GetETSChecker() const @@ -957,8 +948,9 @@ checker::Type *ETSAnalyzer::Check(ir::TSAnyKeyword *node) const checker::Type *ETSAnalyzer::Check(ir::TSArrayType *node) const { - (void)node; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + node->element_type_->Check(checker); + return nullptr; } checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const @@ -967,9 +959,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSBigintKeyword *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSBigintKeyword *node) const { - (void)node; UNREACHABLE(); } @@ -1069,9 +1060,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSIntersectionType *node) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSLiteralType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSLiteralType *node) const { - (void)node; UNREACHABLE(); } @@ -1099,16 +1089,23 @@ checker::Type *ETSAnalyzer::Check(ir::TSNamedTupleMember *node) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSNeverKeyword *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSNeverKeyword *node) const { - (void)node; UNREACHABLE(); } checker::Type *ETSAnalyzer::Check(ir::TSNonNullExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + auto expr_type = expr->expr_->Check(checker); + + if (!expr_type->IsNullish()) { + checker->ThrowTypeError("Bad operand type, the operand of the non-null expression must be a nullable type", + expr->Expr()->Start()); + } + + expr->SetTsType(expr_type->IsNullish() ? checker->GetNonNullishType(expr_type) : expr_type); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::TSNullKeyword *node) const @@ -1135,9 +1132,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSParameterProperty *expr) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSParenthesizedType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSParenthesizedType *node) const { - (void)node; UNREACHABLE(); } @@ -1177,9 +1173,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSTypeAssertion *expr) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSTypeLiteral *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSTypeLiteral *node) const { - (void)node; UNREACHABLE(); } @@ -1231,9 +1226,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSUndefinedKeyword *node) const UNREACHABLE(); } -checker::Type *ETSAnalyzer::Check(ir::TSUnionType *node) const +checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::TSUnionType *node) const { - (void)node; UNREACHABLE(); } diff --git a/ets2panda/checker/TSAnalyzer.cpp b/ets2panda/checker/TSAnalyzer.cpp index d3e96e821ffd6bb149a2337acaa909ed200d7dca..6190e3b84dcb6ee670d4ec07160a963f3eb97c9a 100644 --- a/ets2panda/checker/TSAnalyzer.cpp +++ b/ets2panda/checker/TSAnalyzer.cpp @@ -18,7 +18,6 @@ #include "checker/TSchecker.h" #include "checker/ts/destructuringContext.h" #include "util/helpers.h" - namespace panda::es2panda::checker { TSChecker *TSAnalyzer::GetTSChecker() const @@ -673,8 +672,9 @@ checker::Type *TSAnalyzer::Check(ir::TSAnyKeyword *node) const checker::Type *TSAnalyzer::Check(ir::TSArrayType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + node->element_type_->Check(checker); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSAsExpression *expr) const @@ -683,10 +683,9 @@ checker::Type *TSAnalyzer::Check(ir::TSAsExpression *expr) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSBigintKeyword *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSBigintKeyword *node) const { - (void)node; - UNREACHABLE(); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSBooleanKeyword *node) const @@ -787,8 +786,9 @@ checker::Type *TSAnalyzer::Check(ir::TSIntersectionType *node) const checker::Type *TSAnalyzer::Check(ir::TSLiteralType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + node->GetType(checker); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSMappedType *node) const @@ -815,15 +815,13 @@ checker::Type *TSAnalyzer::Check(ir::TSNamedTupleMember *node) const UNREACHABLE(); } -checker::Type *TSAnalyzer::Check(ir::TSNeverKeyword *node) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSNeverKeyword *node) const { - (void)node; - UNREACHABLE(); + return nullptr; } -checker::Type *TSAnalyzer::Check(ir::TSNonNullExpression *expr) const +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::TSNonNullExpression *expr) const { - (void)expr; UNREACHABLE(); } @@ -853,8 +851,9 @@ checker::Type *TSAnalyzer::Check(ir::TSParameterProperty *expr) const checker::Type *TSAnalyzer::Check(ir::TSParenthesizedType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + node->type_->Check(checker); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSQualifiedName *expr) const @@ -895,8 +894,16 @@ checker::Type *TSAnalyzer::Check(ir::TSTypeAssertion *expr) const checker::Type *TSAnalyzer::Check(ir::TSTypeLiteral *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + + for (auto *it : node->Members()) { + it->Check(checker); + } + + checker::Type *type = node->GetType(checker); + checker->CheckIndexConstraints(type); + + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSTypeOperator *node) const @@ -949,8 +956,13 @@ checker::Type *TSAnalyzer::Check(ir::TSUndefinedKeyword *node) const checker::Type *TSAnalyzer::Check(ir::TSUnionType *node) const { - (void)node; - UNREACHABLE(); + TSChecker *checker = GetTSChecker(); + for (auto *it : node->Types()) { + it->Check(checker); + } + + node->GetType(checker); + return nullptr; } checker::Type *TSAnalyzer::Check(ir::TSUnknownKeyword *node) const diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 46dd096ae82d9c812db8af28704dee330951bdcd..fb340ac0ad86836c6df66dbd4a24ad91884275c6 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -20,7 +20,6 @@ #include "compiler/base/lreference.h" #include "compiler/core/ETSGen.h" #include "compiler/function/functionBuilder.h" - namespace panda::es2panda::compiler { ETSGen *ETSCompiler::GetETSGen() const @@ -684,9 +683,8 @@ void ETSCompiler::Compile(const ir::TSAnyKeyword *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSArrayType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSArrayType *node) const { - (void)node; UNREACHABLE(); } @@ -696,9 +694,8 @@ void ETSCompiler::Compile(const ir::TSAsExpression *expr) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSBigintKeyword *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSBigintKeyword *node) const { - (void)node; UNREACHABLE(); } @@ -798,9 +795,8 @@ void ETSCompiler::Compile(const ir::TSIntersectionType *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSLiteralType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSLiteralType *node) const { - (void)node; UNREACHABLE(); } @@ -828,16 +824,39 @@ void ETSCompiler::Compile(const ir::TSNamedTupleMember *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSNeverKeyword *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSNeverKeyword *node) const { - (void)node; UNREACHABLE(); } void ETSCompiler::Compile(const ir::TSNonNullExpression *expr) const { - (void)expr; - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + compiler::RegScope rs(etsg); + + expr->Expr()->Compile(etsg); + + if (!etsg->GetAccumulatorType()->IsNullishOrNullLike()) { + return; + } + + if (etsg->GetAccumulatorType()->IsETSNullLike()) { + etsg->EmitNullishException(expr); + return; + } + + auto arg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, arg); + etsg->LoadAccumulator(expr, arg); + + auto end_label = etsg->AllocLabel(); + + etsg->BranchIfNotNullish(expr, end_label); + etsg->EmitNullishException(expr); + + etsg->SetLabel(expr, end_label); + etsg->LoadAccumulator(expr, arg); + etsg->ConvertToNonNullish(expr); } void ETSCompiler::Compile(const ir::TSNullKeyword *node) const @@ -864,9 +883,8 @@ void ETSCompiler::Compile(const ir::TSParameterProperty *expr) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSParenthesizedType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSParenthesizedType *node) const { - (void)node; UNREACHABLE(); } @@ -906,9 +924,8 @@ void ETSCompiler::Compile(const ir::TSTypeAssertion *expr) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSTypeLiteral *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSTypeLiteral *node) const { - (void)node; UNREACHABLE(); } @@ -960,9 +977,8 @@ void ETSCompiler::Compile(const ir::TSUndefinedKeyword *node) const UNREACHABLE(); } -void ETSCompiler::Compile(const ir::TSUnionType *node) const +void ETSCompiler::Compile([[maybe_unused]] const ir::TSUnionType *node) const { - (void)node; UNREACHABLE(); } diff --git a/ets2panda/compiler/core/JSCompiler.cpp b/ets2panda/compiler/core/JSCompiler.cpp index 10a894d364243fe8b74d0bd55d96c5d90df2551c..e82028046ed2696898881ded8051355bb37a494b 100644 --- a/ets2panda/compiler/core/JSCompiler.cpp +++ b/ets2panda/compiler/core/JSCompiler.cpp @@ -969,9 +969,8 @@ void JSCompiler::Compile(const ir::TSAnyKeyword *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSArrayType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSArrayType *node) const { - (void)node; UNREACHABLE(); } @@ -981,9 +980,8 @@ void JSCompiler::Compile(const ir::TSAsExpression *expr) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSBigintKeyword *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSBigintKeyword *node) const { - (void)node; UNREACHABLE(); } @@ -1083,9 +1081,8 @@ void JSCompiler::Compile(const ir::TSIntersectionType *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSLiteralType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSLiteralType *node) const { - (void)node; UNREACHABLE(); } @@ -1113,15 +1110,13 @@ void JSCompiler::Compile(const ir::TSNamedTupleMember *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSNeverKeyword *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSNeverKeyword *node) const { - (void)node; UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSNonNullExpression *expr) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSNonNullExpression *expr) const { - (void)expr; UNREACHABLE(); } @@ -1149,9 +1144,8 @@ void JSCompiler::Compile(const ir::TSParameterProperty *expr) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSParenthesizedType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSParenthesizedType *node) const { - (void)node; UNREACHABLE(); } @@ -1191,9 +1185,8 @@ void JSCompiler::Compile(const ir::TSTypeAssertion *expr) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSTypeLiteral *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSTypeLiteral *node) const { - (void)node; UNREACHABLE(); } @@ -1245,9 +1238,8 @@ void JSCompiler::Compile(const ir::TSUndefinedKeyword *node) const UNREACHABLE(); } -void JSCompiler::Compile(const ir::TSUnionType *node) const +void JSCompiler::Compile([[maybe_unused]] const ir::TSUnionType *node) const { - (void)node; UNREACHABLE(); } diff --git a/ets2panda/ir/ts/tsArrayType.cpp b/ets2panda/ir/ts/tsArrayType.cpp index 725b911850243ecc5d0cd605f7b60baa1e4f9685..7233ca4ab5629f7689c2f7df9572fd7216b72ab5 100644 --- a/ets2panda/ir/ts/tsArrayType.cpp +++ b/ets2panda/ir/ts/tsArrayType.cpp @@ -15,6 +15,8 @@ #include "tsArrayType.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" #include "checker/ETSchecker.h" @@ -35,12 +37,19 @@ void TSArrayType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSArrayType"}, {"elementType", element_type_}}); } -void TSArrayType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSArrayType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSArrayType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSArrayType::Check([[maybe_unused]] checker::TSChecker *checker) { - element_type_->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSArrayType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -50,8 +59,7 @@ checker::Type *TSArrayType::GetType([[maybe_unused]] checker::TSChecker *checker checker::Type *TSArrayType::Check(checker::ETSChecker *checker) { - element_type_->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSArrayType::GetType(checker::ETSChecker *checker) diff --git a/ets2panda/ir/ts/tsArrayType.h b/ets2panda/ir/ts/tsArrayType.h index add9c0e33b5e3b66673c445dc79d538a4c55cb77..63c0795822b3be9d1bba0bc437f852da138432b1 100644 --- a/ets2panda/ir/ts/tsArrayType.h +++ b/ets2panda/ir/ts/tsArrayType.h @@ -18,6 +18,11 @@ #include "ir/typeNode.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +class TSAnalyzer; +} // namespace panda::es2panda::checker + namespace panda::es2panda::ir { class TSArrayType : public TypeNode { public: @@ -28,10 +33,15 @@ public: return element_type_; } + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::TSAnalyzer; + friend class checker::ETSAnalyzer; + void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsBigintKeyword.cpp b/ets2panda/ir/ts/tsBigintKeyword.cpp index 0d50b96a5ab9f8b1acd0c49958c48e156adcf09b..baa374d6690499b117dd1e3f6a60a62c8c8d1d0d 100644 --- a/ets2panda/ir/ts/tsBigintKeyword.cpp +++ b/ets2panda/ir/ts/tsBigintKeyword.cpp @@ -15,6 +15,9 @@ #include "tsBigintKeyword.h" +#include "checker/ETSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -27,11 +30,18 @@ void TSBigintKeyword::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSBigIntKeyword"}}); } -void TSBigintKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSBigintKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} +void TSBigintKeyword::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSBigintKeyword::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSBigintKeyword::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -41,6 +51,6 @@ checker::Type *TSBigintKeyword::GetType([[maybe_unused]] checker::TSChecker *che checker::Type *TSBigintKeyword::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsBigintKeyword.h b/ets2panda/ir/ts/tsBigintKeyword.h index 61fe591e040781010a4ff675898e2aea9c5894b1..9405c449a357e0d88a92e4738889042f14a9446d 100644 --- a/ets2panda/ir/ts/tsBigintKeyword.h +++ b/ets2panda/ir/ts/tsBigintKeyword.h @@ -27,6 +27,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsLiteralType.cpp b/ets2panda/ir/ts/tsLiteralType.cpp index 08db35d343e5cac9a3331feac8c26e52e7f3408a..44d05c36f516a882d5a203942a870d6eadc0a5b6 100644 --- a/ets2panda/ir/ts/tsLiteralType.cpp +++ b/ets2panda/ir/ts/tsLiteralType.cpp @@ -15,6 +15,8 @@ #include "tsLiteralType.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -34,12 +36,19 @@ void TSLiteralType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSLiteralType"}, {"literal", literal_}}); } -void TSLiteralType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSLiteralType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSLiteralType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSLiteralType::Check([[maybe_unused]] checker::TSChecker *checker) { - GetType(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSLiteralType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -54,6 +63,6 @@ checker::Type *TSLiteralType::GetType([[maybe_unused]] checker::TSChecker *check checker::Type *TSLiteralType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsLiteralType.h b/ets2panda/ir/ts/tsLiteralType.h index 9569ef38287ecc0ec06c255bd23e81b7731a616b..ee3e8e145581a388f7f47df3aca6814f4628a85a 100644 --- a/ets2panda/ir/ts/tsLiteralType.h +++ b/ets2panda/ir/ts/tsLiteralType.h @@ -32,6 +32,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsNeverKeyword.cpp b/ets2panda/ir/ts/tsNeverKeyword.cpp index 92b64c3dae72fe122fb79f48dee64df640dbc7dd..ee52a42c6b9b112dfa05c6ffbcdb6125fbcf0b5a 100644 --- a/ets2panda/ir/ts/tsNeverKeyword.cpp +++ b/ets2panda/ir/ts/tsNeverKeyword.cpp @@ -15,6 +15,8 @@ #include "tsNeverKeyword.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -27,11 +29,19 @@ void TSNeverKeyword::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSNeverKeyword"}}); } -void TSNeverKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSNeverKeyword::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSNeverKeyword::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSNeverKeyword::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSNeverKeyword::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -41,6 +51,6 @@ checker::Type *TSNeverKeyword::GetType([[maybe_unused]] checker::TSChecker *chec checker::Type *TSNeverKeyword::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsNeverKeyword.h b/ets2panda/ir/ts/tsNeverKeyword.h index 20053e4aa2e1867b8afbc007fa250a07d3615612..35d4aa449f841cfae0e3cf1c47a97631e68c8686 100644 --- a/ets2panda/ir/ts/tsNeverKeyword.h +++ b/ets2panda/ir/ts/tsNeverKeyword.h @@ -27,6 +27,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsNonNullExpression.cpp b/ets2panda/ir/ts/tsNonNullExpression.cpp index 3ce576cef450cfd1c02badd1f54a094a752a0e9f..ac49f17ac8ae1bf8b21f7d09aac60c026cc46a87 100644 --- a/ets2panda/ir/ts/tsNonNullExpression.cpp +++ b/ets2panda/ir/ts/tsNonNullExpression.cpp @@ -16,7 +16,9 @@ #include "tsNonNullExpression.h" #include "checker/ETSchecker.h" +#include "checker/TSchecker.h" #include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" namespace panda::es2panda::ir { @@ -35,52 +37,23 @@ void TSNonNullExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSNonNullExpression"}, {"expression", expr_}}); } -void TSNonNullExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSNonNullExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} void TSNonNullExpression::Compile(compiler::ETSGen *etsg) const { - compiler::RegScope rs(etsg); - - expr_->Compile(etsg); - - if (!etsg->GetAccumulatorType()->IsNullishOrNullLike()) { - return; - } - - if (etsg->GetAccumulatorType()->IsETSNullLike()) { - etsg->EmitNullishException(this); - return; - } - - auto arg = etsg->AllocReg(); - etsg->StoreAccumulator(this, arg); - etsg->LoadAccumulator(this, arg); - - auto end_label = etsg->AllocLabel(); - - etsg->BranchIfNotNullish(this, end_label); - etsg->EmitNullishException(this); - - etsg->SetLabel(this, end_label); - etsg->LoadAccumulator(this, arg); - etsg->ConvertToNonNullish(this); + etsg->GetAstCompiler()->Compile(this); } checker::Type *TSNonNullExpression::Check([[maybe_unused]] checker::TSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSNonNullExpression::Check(checker::ETSChecker *checker) { - auto expr_type = expr_->Check(checker); - - if (!expr_type->IsNullish()) { - checker->ThrowTypeError("Bad operand type, the operand of the non-null expression must be a nullable type", - expr_->Start()); - } - - SetTsType(expr_type->IsNullish() ? checker->GetNonNullishType(expr_type) : expr_type); - return TsType(); + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsNonNullExpression.h b/ets2panda/ir/ts/tsNonNullExpression.h index 22910a2211e31c8a723c6d1d2e871773678ecd52..0819a97fe46be0751d2f619cba5bb815100f2f49 100644 --- a/ets2panda/ir/ts/tsNonNullExpression.h +++ b/ets2panda/ir/ts/tsNonNullExpression.h @@ -18,11 +18,17 @@ #include "ir/expression.h" +namespace panda::es2panda::checker { +class ETSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class TSNonNullExpression : public Expression { public: explicit TSNonNullExpression(Expression *expr) : Expression(AstNodeType::TS_NON_NULL_EXPRESSION), expr_(expr) {} + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::ETSAnalyzer; + const Expression *Expr() const { return expr_; diff --git a/ets2panda/ir/ts/tsParenthesizedType.cpp b/ets2panda/ir/ts/tsParenthesizedType.cpp index ba224d1c703a6ebaaa2c6849f46cf95149c8cb6f..04012a2b20bb43aa0060e3eef2119ab9ea7bb8b3 100644 --- a/ets2panda/ir/ts/tsParenthesizedType.cpp +++ b/ets2panda/ir/ts/tsParenthesizedType.cpp @@ -15,6 +15,8 @@ #include "tsParenthesizedType.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "checker/TSchecker.h" @@ -34,12 +36,19 @@ void TSParenthesizedType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSParenthesizedType"}, {"typeAnnotation", type_}}); } -void TSParenthesizedType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSParenthesizedType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} + +void TSParenthesizedType::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} checker::Type *TSParenthesizedType::Check([[maybe_unused]] checker::TSChecker *checker) { - type_->Check(checker); - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSParenthesizedType::GetType([[maybe_unused]] checker::TSChecker *checker) @@ -54,6 +63,6 @@ checker::Type *TSParenthesizedType::GetType([[maybe_unused]] checker::TSChecker checker::Type *TSParenthesizedType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsParenthesizedType.h b/ets2panda/ir/ts/tsParenthesizedType.h index 8175be39783728c45789a32e77b61bdbbac46367..5818aa2e432f36151adb0cfd72d6289dfcdf49c2 100644 --- a/ets2panda/ir/ts/tsParenthesizedType.h +++ b/ets2panda/ir/ts/tsParenthesizedType.h @@ -17,12 +17,17 @@ #define ES2PANDA_IR_TS_PARENT_TYPE_H #include "ir/typeNode.h" - +namespace panda::es2panda::checker { +class TSAnalyzer; +} // namespace panda::es2panda::checker namespace panda::es2panda::ir { class TSParenthesizedType : public TypeNode { public: explicit TSParenthesizedType(TypeNode *type) : TypeNode(AstNodeType::TS_PARENT_TYPE), type_(type) {} + // TODO (vivienvoros): these friend relationships can be removed once there are getters for private fields + friend class checker::TSAnalyzer; + const Expression *Type() const { return type_; @@ -32,6 +37,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsTypeLiteral.cpp b/ets2panda/ir/ts/tsTypeLiteral.cpp index 48fdf07d8633f6b9a13e972b5d695efcee0a6810..9f9471ab8fb7a9f39625d2f9b8eeb80f420333a7 100644 --- a/ets2panda/ir/ts/tsTypeLiteral.cpp +++ b/ets2panda/ir/ts/tsTypeLiteral.cpp @@ -15,6 +15,8 @@ #include "tsTypeLiteral.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" #include "varbinder/variable.h" @@ -42,18 +44,19 @@ void TSTypeLiteral::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSTypeLiteral"}, {"members", members_}}); } -void TSTypeLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} - -checker::Type *TSTypeLiteral::Check(checker::TSChecker *checker) +void TSTypeLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const { - for (auto *it : members_) { - it->Check(checker); - } + pg->GetAstCompiler()->Compile(this); +} - checker::Type *type = GetType(checker); - checker->CheckIndexConstraints(type); +void TSTypeLiteral::Compile(compiler::ETSGen *etsg) const +{ + etsg->GetAstCompiler()->Compile(this); +} - return nullptr; +checker::Type *TSTypeLiteral::Check(checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } checker::Type *TSTypeLiteral::GetType(checker::TSChecker *checker) @@ -72,6 +75,6 @@ checker::Type *TSTypeLiteral::GetType(checker::TSChecker *checker) checker::Type *TSTypeLiteral::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeLiteral.h b/ets2panda/ir/ts/tsTypeLiteral.h index 9f0cb0a1b7e7c84449abb901d562a46bb8ce0588..a91e051a9373de1e0f7075033ea1add8b3aee56a 100644 --- a/ets2panda/ir/ts/tsTypeLiteral.h +++ b/ets2panda/ir/ts/tsTypeLiteral.h @@ -35,6 +35,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; diff --git a/ets2panda/ir/ts/tsUnionType.cpp b/ets2panda/ir/ts/tsUnionType.cpp index 6a55683ea6a051026af1846a669efbd3171eb8f2..802d5d65c7695cdd3ada084044b419d576a14186 100644 --- a/ets2panda/ir/ts/tsUnionType.cpp +++ b/ets2panda/ir/ts/tsUnionType.cpp @@ -16,6 +16,8 @@ #include "tsUnionType.h" #include "checker/TSchecker.h" +#include "compiler/core/ETSGen.h" +#include "compiler/core/pandagen.h" #include "ir/astDump.h" namespace panda::es2panda::ir { @@ -38,21 +40,24 @@ void TSUnionType::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "TSUnionType"}, {"types", types_}}); } -void TSUnionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSUnionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ + pg->GetAstCompiler()->Compile(this); +} -checker::Type *TSUnionType::Check([[maybe_unused]] checker::TSChecker *checker) +void TSUnionType::Compile(compiler::ETSGen *etsg) const { - for (auto *it : types_) { - it->Check(checker); - } + etsg->GetAstCompiler()->Compile(this); +} - GetType(checker); - return nullptr; +checker::Type *TSUnionType::Check([[maybe_unused]] checker::TSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); } checker::Type *TSUnionType::Check([[maybe_unused]] checker::ETSChecker *checker) { - return nullptr; + return checker->GetAnalyzer()->Check(this); } checker::Type *TSUnionType::GetType(checker::TSChecker *checker) diff --git a/ets2panda/ir/ts/tsUnionType.h b/ets2panda/ir/ts/tsUnionType.h index feaa03b28268044c85a438751015bda6aded7c34..aa31b0ba6e9b9e574e79f953194e51a0aacf0c5c 100644 --- a/ets2panda/ir/ts/tsUnionType.h +++ b/ets2panda/ir/ts/tsUnionType.h @@ -35,6 +35,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override;