diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index fd2476ce9496e76741c94c109991d3215a2d3eec..15c93860071c649061a279a08c7e87b9f7b754a4 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -968,22 +968,75 @@ static bool CompileComputed(compiler::ETSGen *etsg, const ir::MemberExpression * void ETSCompiler::Compile(const ir::MemberExpression *expr) const { ETSGen *etsg = GetETSGen(); - auto lambda = etsg->VarBinder()->LambdaObjects().find(expr); - if (lambda != etsg->VarBinder()->LambdaObjects().end()) { - etsg->CreateLambdaObjectFromMemberReference(expr, expr->object_, lambda->second.first); - etsg->SetAccumulatorType(expr->TsType()); + + if (HandleLambdaObject(expr, etsg)) { return; } compiler::RegScope rs(etsg); + if (CompileComputed(etsg, expr)) { + return; + } + + if (HandleArrayTypeLengthProperty(expr, etsg)) { + return; + } + + if (HandleEnumTypes(expr, etsg)) { + return; + } + + if (HandleStaticProperties(expr, etsg)) { + return; + } + auto *const objectType = checker::ETSChecker::GetApparentType(etsg->Checker()->GetNonNullishType(expr->Object()->TsType())); + auto &propName = expr->Property()->AsIdentifier()->Name(); - if (CompileComputed(etsg, expr)) { - return; + auto ottctx = compiler::TargetTypeContext(etsg, expr->Object()->TsType()); + etsg->CompileAndCheck(expr->Object()); + + auto const loadProperty = [expr, etsg, propName, objectType]() { + etsg->ApplyConversion(expr->Object()); + compiler::VReg objReg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, objReg); + + auto ttctx = compiler::TargetTypeContext(etsg, expr->OptionalType()); + + if (expr->PropVar()->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { + checker::Signature *sig = expr->PropVar()->TsType()->AsETSFunctionType()->FindGetter(); + etsg->CallThisVirtual0(expr, objReg, sig->InternalName()); + } else if (objectType->IsETSDynamicType()) { + etsg->LoadPropertyDynamic(expr, expr->OptionalType(), objReg, propName); + } else if (objectType->IsETSUnionType()) { + etsg->LoadUnionProperty(expr, expr->OptionalType(), objReg, propName); + } else { + const auto fullName = etsg->FormClassPropReference(objectType->AsETSObjectType(), propName); + etsg->LoadProperty(expr, expr->OptionalType(), objReg, fullName); + } + etsg->GuardUncheckedType(expr, expr->UncheckedType(), expr->OptionalType()); + }; + + etsg->EmitMaybeOptional(expr, loadProperty, expr->IsOptional()); +} + +bool ETSCompiler::HandleLambdaObject(const ir::MemberExpression *expr, ETSGen *etsg) const +{ + auto lambda = etsg->VarBinder()->LambdaObjects().find(expr); + if (lambda != etsg->VarBinder()->LambdaObjects().end()) { + etsg->CreateLambdaObjectFromMemberReference(expr, expr->object_, lambda->second.first); + etsg->SetAccumulatorType(expr->TsType()); + return true; } + return false; +} +bool ETSCompiler::HandleArrayTypeLengthProperty(const ir::MemberExpression *expr, ETSGen *etsg) const +{ + auto *const objectType = + checker::ETSChecker::GetApparentType(etsg->Checker()->GetNonNullishType(expr->Object()->TsType())); auto &propName = expr->Property()->AsIdentifier()->Name(); if (objectType->IsETSArrayType() && propName.Is("length")) { @@ -1000,9 +1053,15 @@ void ETSCompiler::Compile(const ir::MemberExpression *expr) const }; etsg->EmitMaybeOptional(expr, loadLength, expr->IsOptional()); - return; + return true; } + return false; +} +bool ETSCompiler::HandleEnumTypes(const ir::MemberExpression *expr, ETSGen *etsg) const +{ + auto *const objectType = + checker::ETSChecker::GetApparentType(etsg->Checker()->GetNonNullishType(expr->Object()->TsType())); if (objectType->IsETSEnumType() || objectType->IsETSStringEnumType()) { auto const *const enumInterface = [objectType, expr]() -> checker::ETSEnumInterface const * { if (objectType->IsETSEnumType()) { @@ -1013,9 +1072,14 @@ void ETSCompiler::Compile(const ir::MemberExpression *expr) const auto ttctx = compiler::TargetTypeContext(etsg, expr->OptionalType()); etsg->LoadAccumulatorInt(expr, enumInterface->GetOrdinal()); - return; + return true; } + return false; +} +bool ETSCompiler::HandleStaticProperties(const ir::MemberExpression *expr, ETSGen *etsg) const +{ + auto &propName = expr->Property()->AsIdentifier()->Name(); if (etsg->Checker()->IsVariableStatic(expr->PropVar())) { auto ttctx = compiler::TargetTypeContext(etsg, expr->OptionalType()); @@ -1023,39 +1087,14 @@ void ETSCompiler::Compile(const ir::MemberExpression *expr) const checker::Signature *sig = expr->PropVar()->TsType()->AsETSFunctionType()->FindGetter(); etsg->CallStatic0(expr, sig->InternalName()); etsg->SetAccumulatorType(expr->TsType()); - return; + return true; } util::StringView fullName = etsg->FormClassPropReference(expr->Object()->TsType()->AsETSObjectType(), propName); etsg->LoadStaticProperty(expr, expr->OptionalType(), fullName); - return; + return true; } - - auto ottctx = compiler::TargetTypeContext(etsg, expr->Object()->TsType()); - etsg->CompileAndCheck(expr->Object()); - - auto const loadProperty = [expr, etsg, propName, objectType]() { - etsg->ApplyConversion(expr->Object()); - compiler::VReg objReg = etsg->AllocReg(); - etsg->StoreAccumulator(expr, objReg); - - auto ttctx = compiler::TargetTypeContext(etsg, expr->OptionalType()); - - if (expr->PropVar()->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER)) { - checker::Signature *sig = expr->PropVar()->TsType()->AsETSFunctionType()->FindGetter(); - etsg->CallThisVirtual0(expr, objReg, sig->InternalName()); - } else if (objectType->IsETSDynamicType()) { - etsg->LoadPropertyDynamic(expr, expr->OptionalType(), objReg, propName); - } else if (objectType->IsETSUnionType()) { - etsg->LoadUnionProperty(expr, expr->OptionalType(), objReg, propName); - } else { - const auto fullName = etsg->FormClassPropReference(objectType->AsETSObjectType(), propName); - etsg->LoadProperty(expr, expr->OptionalType(), objReg, fullName); - } - etsg->GuardUncheckedType(expr, expr->UncheckedType(), expr->OptionalType()); - }; - - etsg->EmitMaybeOptional(expr, loadProperty, expr->IsOptional()); + return false; } void ETSCompiler::Compile([[maybe_unused]] const ir::NewExpression *expr) const diff --git a/ets2panda/compiler/core/ETSCompiler.h b/ets2panda/compiler/core/ETSCompiler.h index 5421dde41f556632d1816b3a6b7d8629a288390a..8966469473e5d1a6abb0e101f75c7c91d3911549 100644 --- a/ets2panda/compiler/core/ETSCompiler.h +++ b/ets2panda/compiler/core/ETSCompiler.h @@ -39,6 +39,10 @@ private: void CompileCastUnboxable(const ir::TSAsExpression *expr) const; void CompileCast(const ir::TSAsExpression *expr) const; void EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, bool isStatic) const; + bool HandleLambdaObject(const ir::MemberExpression *expr, ETSGen *etsg) const; + bool HandleArrayTypeLengthProperty(const ir::MemberExpression *expr, ETSGen *etsg) const; + bool HandleEnumTypes(const ir::MemberExpression *expr, ETSGen *etsg) const; + bool HandleStaticProperties(const ir::MemberExpression *expr, ETSGen *etsg) const; ETSGen *GetETSGen() const; }; diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 06d08f355360f8048f07c6523e8c017e54484f05..e7dd17fb674bd58decd4e85f608b9ad32a1cf3f5 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -605,29 +605,10 @@ bool ETSBinder::AddImportSpecifiersToTopBindings(ir::AstNode *const specifier, }(); if (var == nullptr) { - for (auto item : ReExportImports()) { - if (auto source = import->ResolvedSource()->Str().Mutf8(), - program = item->GetProgramPath().Mutf8().substr(0, item->GetProgramPath().Mutf8().find_last_of('.')); - source == program || (source + "/index") == program) { - // clang-format off - ir::StringLiteral dirName(util::UString(util::StringView(item->GetProgramPath().Mutf8().substr( - 0, item->GetProgramPath().Mutf8().find_last_of('/'))), - Allocator()) - .View()); - // clang-format on - dirName.SetStart(item->GetETSImportDeclarations()->Source()->Start()); - - viewedReExport.push_back(item->GetETSImportDeclarations()); - AddSpecifiersToTopBindings( - specifier, item->GetETSImportDeclarations(), - dirName.Str().Is(".") ? item->GetETSImportDeclarations()->Source() : &dirName, viewedReExport); - return true; - } + if (HandleMissingImportedElement(specifier, imported, import, viewedReExport, importPath)) { + return true; } - ThrowError(importPath->Start(), "Cannot find imported element " + imported.Mutf8()); - } - - if (var->Declaration()->Node()->IsDefaultExported()) { + } else if (var->Declaration()->Node()->IsDefaultExported()) { ThrowError(importPath->Start(), "Use the default import syntax to import a default exported element"); } @@ -635,6 +616,33 @@ bool ETSBinder::AddImportSpecifiersToTopBindings(ir::AstNode *const specifier, return true; } +bool ETSBinder::HandleMissingImportedElement(ir::AstNode *const specifier, const util::StringView &imported, + const ir::ETSImportDeclaration *import, + std::vector &viewedReExport, + const ir::StringLiteral *importPath) +{ + for (auto item : ReExportImports()) { + if (auto source = import->ResolvedSource()->Str().Mutf8(), + program = item->GetProgramPath().Mutf8().substr(0, item->GetProgramPath().Mutf8().find_last_of('.')); + source == program || (source + "/index") == program) { + // clang-format off + ir::StringLiteral dirName(util::UString(util::StringView(item->GetProgramPath().Mutf8().substr( + 0, item->GetProgramPath().Mutf8().find_last_of('/'))), + Allocator()) + .View()); + // clang-format on + dirName.SetStart(item->GetETSImportDeclarations()->Source()->Start()); + + viewedReExport.push_back(item->GetETSImportDeclarations()); + AddSpecifiersToTopBindings(specifier, item->GetETSImportDeclarations(), + dirName.Str().Is(".") ? item->GetETSImportDeclarations()->Source() : &dirName, + viewedReExport); + return true; + } + } + ThrowError(importPath->Start(), "Cannot find imported element " + imported.Mutf8()); +} + varbinder::Variable *ETSBinder::FindStaticBinding(const ArenaVector &recordRes, const ir::StringLiteral *const importPath) { diff --git a/ets2panda/varbinder/ETSBinder.h b/ets2panda/varbinder/ETSBinder.h index edd27f9a43a6b9cd3905d994d94ac3fbaf527937..2d065261396e9216928804f733d5a60fd874c3cb 100644 --- a/ets2panda/varbinder/ETSBinder.h +++ b/ets2panda/varbinder/ETSBinder.h @@ -133,6 +133,10 @@ public: const ir::ETSImportDeclaration *import, const ArenaVector &recordRes, std::vector viewedReExport); + bool HandleMissingImportedElement(ir::AstNode *specifier, const util::StringView &imported, + const ir::ETSImportDeclaration *import, + std::vector &viewedReExport, + const ir::StringLiteral *importPath); Variable *FindImportSpecifiersVariable(const util::StringView &imported, const varbinder::Scope::VariableMap &globalBindings, const ArenaVector &recordRes);