diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 3955fcc851bfab84788b8f51bdac0b368d59a38a..25eae3b4d4507d17195d888650d0cfac67049ab5 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -378,10 +378,15 @@ void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis) for (auto *extProg : extPrograms) { if (!extProg->IsASTLowered()) { extProg->PushChecker(this); + auto *savedProgram2 = VarBinder()->AsETSBinder()->Program(); varbinder::RecordTableContext recordTableCtx(VarBinder()->AsETSBinder(), extProg); + VarBinder()->AsETSBinder()->SetProgram(extProg); + VarBinder()->AsETSBinder()->ResetTopScope(extProg->GlobalScope()); checker::SavedCheckerContext savedContext(this, Context().Status(), Context().ContainingClass()); AddStatus(checker::CheckerStatus::IN_EXTERNAL); - CheckProgram(extProg, VarBinder()->IsGenStdLib()); + CheckProgram(extProg, VarBinder()->IsGenStdLib() || extProg->IsGenAbc()); + VarBinder()->AsETSBinder()->SetProgram(savedProgram2); + VarBinder()->AsETSBinder()->ResetTopScope(savedProgram2->GlobalScope()); } } } diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 5ae8c1dd92be2afdeb6b72d5b3ef4e5cf7e91987..29d4ed86d2d4ffef9c824ae8e465e5f3fd3fb11d 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -2858,6 +2858,8 @@ void ETSChecker::SetupGetterSetterFlags(ir::ClassProperty *originalProp, ETSObje ir::MethodDefinition *getter, ir::MethodDefinition *setter, const bool inExternal) { + auto GetProgram = [](ir::AstNode *node) { return node->Range().start.Program(); }; + auto *const classDef = classType->GetDeclNode()->AsClassDefinition(); for (auto &method : {getter, setter}) { if (method == nullptr) { @@ -2873,7 +2875,7 @@ void ETSChecker::SetupGetterSetterFlags(ir::ClassProperty *originalProp, ETSObje method->Function()->AddModifier(ir::ModifierFlags::OVERRIDE); } - if (inExternal) { + if (inExternal && !GetProgram(originalProp)->IsGenAbc()) { method->Function()->AddFlag(ir::ScriptFunctionFlags::EXTERNAL); } @@ -2998,6 +3000,7 @@ bool ETSChecker::TryTransformingToStaticInvoke(ir::Identifier *const ident, cons if (instantiateMethod != nullptr) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + auto lexScope {varbinder::LexicalScope::Enter(VarBinder(), compiler::NearestScope(callExpr))}; auto *argExpr = GenerateImplicitInstantiateArg(std::string(className)); argExpr->SetParent(callExpr); diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index c267defa3c8f07b568c3720c739da8bc9d218139..b5572ff93aa655a9cadf4ae8ff9f727fcd613eb7 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -149,7 +149,9 @@ Type *ETSChecker::CreatePartialTypeClass(ETSObjectType *typeToBePartial, ir::Ast // Check if we've already generated the partial class, then don't do it again const auto classNameToFind = - partialProgram == VarBinder()->Program() || VarBinder()->IsGenStdLib() ? partialName : partialQualifiedName; + partialProgram == VarBinder()->Program() || VarBinder()->IsGenStdLib() || partialProgram->IsGenAbc() + ? partialName + : partialQualifiedName; if (auto *var = SearchNamesInMultiplePrograms({partialProgram, VarBinder()->Program()}, {classNameToFind, partialName}); var != nullptr) { diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 8f0b822ef9a54cc8c5890d195f500e6a04a388b0..5b2f900565b84b7bf6d4a139953d0a9bdc34b492 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -275,6 +275,10 @@ void ETSEmitter::GenAnnotation() } for (auto *classDecl : globalRecordTable->ClassDefinitions()) { + static auto s = "ETSGLOBAL"; + if (classDecl->InternalName().Is(s)) { + continue; + } GenClassRecord(classDecl, classDecl->IsDeclare()); } @@ -324,29 +328,36 @@ static bool IsFromSelfHeadFile(const std::string &name, const parser::Program *c void ETSEmitter::GenExternalRecord(varbinder::RecordTable *recordTable, const parser::Program *extProg) { - bool isGenStdLib = recordTable->Program()->VarBinder()->IsGenStdLib(); + bool isExternalFromCompile = !recordTable->Program()->VarBinder()->IsGenStdLib() && !recordTable->Program()->IsGenAbc(); const auto *varbinder = static_cast(Context()->parserProgram->VarBinder()); auto baseName = varbinder->GetRecordTable()->RecordName().Mutf8(); for (auto *annoDecl : recordTable->AnnotationDeclarations()) { auto newBaseName = GenerateMangledName(baseName, annoDecl->GetBaseName()->Name().Mutf8()); - GenCustomAnnotationRecord(annoDecl, newBaseName, !isGenStdLib); + GenCustomAnnotationRecord(annoDecl, newBaseName, isExternalFromCompile || annoDecl->IsDeclare()); } for (auto *classDecl : recordTable->ClassDefinitions()) { - GenClassRecord(classDecl, !isGenStdLib); + GenClassRecord(classDecl, isExternalFromCompile || classDecl->IsDeclare()); } for (auto *interfaceDecl : recordTable->InterfaceDeclarations()) { - GenInterfaceRecord(interfaceDecl, !isGenStdLib); + GenInterfaceRecord(interfaceDecl, isExternalFromCompile || interfaceDecl->IsDeclare()); } - for (auto const *signature : recordTable->Signatures()) { - auto func = GenScriptFunction(signature->Node()->AsScriptFunction(), this); + for (auto *signature : recordTable->Signatures()) { + auto scriptFunc = signature->Node()->AsScriptFunction(); + auto func = GenScriptFunction(scriptFunc, this); - if (!isGenStdLib) { + if (isExternalFromCompile || scriptFunc->IsDeclare()) { func.metadata->SetAttribute(Signatures::EXTERNAL); } + if (extProg->IsGenAbc() && scriptFunc->IsAsyncFunc()) { + std::vector annotations; + annotations.push_back(GenAnnotationAsync(scriptFunc)); + func.metadata->AddAnnotations(annotations); + } + if (func.metadata->IsForeign() && IsFromSelfHeadFile(func.name, Context()->parserProgram, extProg)) { continue; } diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 1e5e752ae776abd6934cf31d8e127a3f69eb6587..2e9dca852388cd448b47d5bb5a593ba334d12970 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -15,6 +15,8 @@ #include "compilerImpl.h" #include +#include +#include #include "es2panda.h" #include "ast_verifier/ASTVerifier.h" @@ -85,6 +87,15 @@ static public_lib::Context::CodeGenCb MakeCompileJob() { return [](public_lib::Context *context, varbinder::FunctionScope *scope, compiler::ProgramElement *programElement) -> void { + if (scope->InternalName().Is("ETSGLOBAL.:void;")) { + return; + } + if (scope->InternalName().Is("ETSGLOBAL._$init$_:void;")) { + return; + } + if (scope->InternalName().Is("ETSGLOBAL.main:void;")) { + return; + } RegSpiller regSpiller; ArenaAllocator allocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); AstCompiler astcompiler; @@ -410,7 +421,62 @@ static bool ExecuteParsingAndCompiling(const CompilationUnit &unit, public_lib:: AddExternalPrograms(context, unit, program); } - context->parser->ParseScript(unit.input, unit.options.GetCompilationMode() == CompilationMode::GEN_STD_LIB); + auto MarkGenAbc = [](std::unordered_set &genAbcList, public_lib::ExternalSource &extSources) { + size_t genCount = 0; + std::unordered_set genAbcListAbsolute; + + for (auto &path : genAbcList) { + std::filesystem::path symlink_path = path; + std::filesystem::path resolved_path = std::filesystem::canonical(symlink_path); + genAbcListAbsolute.insert(resolved_path); + } + for (auto &[_, extPrograms] : extSources) { + (void)_; + for (auto *prog : extPrograms) { + if (auto it = genAbcListAbsolute.find(prog->AbsoluteName().Mutf8()); it != genAbcListAbsolute.end()) { + prog->SetGenAbc(); + ++genCount; + } + } + } + for (auto &[_, extPrograms] : extSources) { + (void)_; + if (std::any_of(extPrograms.begin(), extPrograms.end(), + [](parser::Program *prog) { return prog->IsGenAbc(); })) { + for (auto *prog : extPrograms) { + prog->SetGenAbc(); + } + } + } + + ES2PANDA_ASSERT(genCount == genAbcListAbsolute.size()); + if (genCount != genAbcListAbsolute.size()) { + std::cout << "-----------------------------genabc path------------------------failed" << std::endl; + } + }; + + if (context->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB || + context->config->options->GetExtension() != ScriptExtension::ETS) { + context->parser->ParseScript(unit.input, unit.options.GetCompilationMode() == CompilationMode::GEN_STD_LIB); + } else { + auto ctx = context; + auto allocator = ctx->allocator; + auto ident = allocator->New(compiler::Signatures::ETS_GLOBAL, allocator); + ArenaVector stmts(allocator->Adapter()); + auto etsModule = allocator->New(allocator, std::move(stmts), ident, ir::ModuleFlag::ETSSCRIPT, + ctx->parserProgram); + ctx->parserProgram->SetAst(etsModule); + util::ImportPathManager::ImportMetadata importData {util::ImportFlags::NONE}; + std::unordered_set sourceFileNamesSet; + sourceFileNamesSet.insert(std::string(ctx->sourceFile->filePath)); + importData.resolvedSource = ctx->sourceFile->filePath; + importData.lang = Language::Id::ETS; + importData.declPath = util::ImportPathManager::DUMMY_PATH; + importData.ohmUrl = util::ImportPathManager::DUMMY_PATH; + ctx->parser->AsETSParser()->GetImportPathManager()->AddToParseList(importData); + ctx->parser->AsETSParser()->AddExternalSource(ctx->parser->AsETSParser()->ParseSources(true)); + MarkGenAbc(sourceFileNamesSet, ctx->parserProgram->ExternalSources()); + } // We have to check the return status of 'RunVerifierAndPhase` and 'RunPhases` separately because there can be // some internal errors (say, in Post-Conditional check) or terminate options (say in 'CheckOptionsAfterPhase') @@ -440,6 +506,7 @@ static pandasm::Program *Compile(const CompilationUnit &unit, CompilerImpl *comp auto phaseManager = compiler::PhaseManager(context, unit.ext, context->allocator); context->config = &config; context->config->options = &unit.options; + context->sourceFile = &unit.input; context->queue = compilerImpl->Queue(); context->plugins = &compilerImpl->Plugins(); @@ -474,6 +541,9 @@ static pandasm::Program *Compile(const CompilationUnit &unit, CompilerImpl *comp auto emitter = Emitter(context); context->emitter = &emitter; auto *varbinder = program.VarBinder(); + if (!context->config->options->IsGenStdlib()) { + const_cast(context->config->options)->SetCompilationMode(CompilationMode::GEN_EXTEANL); + } varbinder->SetProgram(&program); varbinder->SetContext(context); context->GetChecker()->Initialize(varbinder); diff --git a/ets2panda/compiler/core/emitter.cpp b/ets2panda/compiler/core/emitter.cpp index 95b7d45aee091ec90d5931fa8cacf7c17d9a676f..d824d2152e6985d28162d64818cb6f4f13064a3f 100644 --- a/ets2panda/compiler/core/emitter.cpp +++ b/ets2panda/compiler/core/emitter.cpp @@ -438,6 +438,9 @@ static void UpdateLiteralBufferId([[maybe_unused]] ark::pandasm::Ins *ins, [[may void Emitter::AddProgramElement(ProgramElement *programElement) { + if (programElement->Function()==nullptr) { + return; + } prog_->strings.insert(programElement->Strings().begin(), programElement->Strings().end()); uint32_t newLiteralBufferIndex = literalBufferIndex_; @@ -535,7 +538,8 @@ pandasm::Program *Emitter::Finalize(bool dumpDebugInfo, std::string_view globalC dumper.Dump(); } - if (context_->parserProgram->VarBinder()->IsGenStdLib()) { + if (context_->parserProgram->VarBinder()->IsGenStdLib() || + context_->parserProgram->VarBinder()->Program()->IsGenAbc()) { auto it = prog_->recordTable.find(std::string(globalClass)); if (it != prog_->recordTable.end()) { prog_->recordTable.erase(it); diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index d3ad50c52ab91206a19b5d2cc231200e6f2a965f..45b0fb97fdae274f9b3ac4ec9709af99fc119d69 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -78,11 +78,11 @@ static size_t g_calleeCount = 0; static std::mutex g_calleeCountMutex {}; // Make calleeCount behaviour predictable -static void ResetCalleeCount() -{ - std::lock_guard lock(g_calleeCountMutex); - g_calleeCount = 0; -} +// static void ResetCalleeCount() +// { +// std::lock_guard lock(g_calleeCountMutex); +// g_calleeCount = 0; +// } static util::StringView CreateCalleeName(ArenaAllocator *allocator) { @@ -1282,7 +1282,7 @@ bool LambdaConversionPhase::PerformForModule(public_lib::Context *ctx, parser::P // For reproducibility of results when several compilation sessions are executed during // the same process's lifetime. if (program == ctx->parserProgram) { - ResetCalleeCount(); + // ResetCalleeCount(); } program->Ast()->TransformChildrenRecursivelyPostorder( diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index ecbedb0619bc957337ddc2ba387c27652a6d1911..d565cfb5ea17667b7a9b54ca3b439988e0a356ee 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -307,6 +307,11 @@ bool UnionLowering::PostconditionForModule(public_lib::Context *ctx, const parse if (!current || ctx->config->options->GetCompilationMode() != CompilationMode::GEN_STD_LIB) { return current; } + // if (!current || ctx->config->options->GetCompilationMode() != CompilationMode::GEN_EXTEANL) { + // if (program->IsStdLib2()) { + // return current; + // } + // } return true; } diff --git a/ets2panda/compiler/lowering/ets/unionLowering.h b/ets2panda/compiler/lowering/ets/unionLowering.h index 0f07e014e3333d6ff43ccbcfa44f5d4c7c89e187..8b3cac14e803345d552352334b895e8f70e45983 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.h +++ b/ets2panda/compiler/lowering/ets/unionLowering.h @@ -26,7 +26,6 @@ public: { return "UnionLowering"; } - bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; bool PostconditionForModule(public_lib::Context *ctx, const parser::Program *program) override; }; diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index 75256702000047ba0936a01fc7844c149bc726c9..7b1345a3bed04f0699e5c2af6e661342465c4954 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -294,21 +294,28 @@ bool PhaseForDeclarations::Postcondition(public_lib::Context *ctx, const parser: bool PhaseForBodies::Precondition(public_lib::Context *ctx, const parser::Program *program) { - auto checkExternalPrograms = [this, ctx](const ArenaVector &programs) { - for (auto *p : programs) { - if (!Precondition(ctx, p)) { - return false; + if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { + for (auto &[_, extPrograms] : program->ExternalSources()) { + (void)_; + for (auto *prog : extPrograms) { + if (!Precondition(ctx, prog)) { + return false; + } } } - return true; - }; + } - if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { + if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_EXTEANL) { for (auto &[_, extPrograms] : program->ExternalSources()) { (void)_; - if (!checkExternalPrograms(extPrograms)) { - return false; - }; + for (auto *prog : extPrograms) { + if (!prog->IsGenAbc()) { + continue; + } + if (!Precondition(ctx, prog)) { + return false; + } + } } } @@ -334,7 +341,28 @@ bool PhaseForBodies::Perform(public_lib::Context *ctx, parser::Program *program) FetchCache(ctx, program); bool result = true; if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { - result &= ProcessExternalPrograms(ctx, program); + for (auto &[_, extPrograms] : program->ExternalSources()) { + (void)_; + for (auto *extProg : extPrograms) { + if (!extProg->IsASTLowered()) { + result &= Perform(ctx, extProg); + } + } + } + } + + if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_EXTEANL) { + for (auto &[_, extPrograms] : program->ExternalSources()) { + (void)_; + for (auto *extProg : extPrograms) { + if (!extProg->IsGenAbc()) { + continue; + } + if (!extProg->IsASTLowered()) { + result &= Perform(ctx, extProg); + } + } + } } result &= PerformForModule(ctx, program); @@ -343,21 +371,28 @@ bool PhaseForBodies::Perform(public_lib::Context *ctx, parser::Program *program) bool PhaseForBodies::Postcondition(public_lib::Context *ctx, const parser::Program *program) { - auto checkExternalPrograms = [this, ctx](const ArenaVector &programs) { - for (auto *p : programs) { - if (!Postcondition(ctx, p)) { - return false; + if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { + for (auto &[_, extPrograms] : program->ExternalSources()) { + (void)_; + for (auto *prog : extPrograms) { + if (!Postcondition(ctx, prog)) { + return false; + } } } - return true; - }; + } - if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { + if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_EXTEANL) { for (auto &[_, extPrograms] : program->ExternalSources()) { (void)_; - if (!checkExternalPrograms(extPrograms)) { - return false; - }; + for (auto *prog : extPrograms) { + if (!prog->IsGenAbc()) { + continue; + } + if (!Postcondition(ctx, prog)) { + return false; + } + } } } diff --git a/ets2panda/driver/build_system/src/types.ts b/ets2panda/driver/build_system/src/types.ts index e375e7d7d83b46afe36ca38e983b716dd07488ec..b75925a387dc4ad4ff6cf46a7e44592c58e6cab3 100644 --- a/ets2panda/driver/build_system/src/types.ts +++ b/ets2panda/driver/build_system/src/types.ts @@ -65,6 +65,7 @@ export interface ArkTSGlobal { export interface ArkTS { Config: { create: Function; + createContextGenerateAbcForExternalSourceFiles: Function; }; Context: { createFromString: Function; diff --git a/ets2panda/es2panda.h b/ets2panda/es2panda.h index 39cdbf9e1b203bdfae6550abb2d6e2f814194403..b2d08e2285e3780538f51970b460006dbd4890dc 100644 --- a/ets2panda/es2panda.h +++ b/ets2panda/es2panda.h @@ -61,6 +61,7 @@ enum class CompilationMode { GEN_STD_LIB, PROJECT, SINGLE_FILE, + GEN_EXTEANL, }; // CC-OFFNXT(G.FUD.06) switch-case, ODR inline Language ToLanguage(ScriptExtension ext) diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 36001a7946a083e80444d63fcd2b0a9da50d1cb3..0ff8dfb96824e62b6e524166b633e692f3c674cb 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -206,6 +206,22 @@ ir::ETSModule *ETSParser::ParseImportsAndReExportOnly(lexer::SourcePosition star return etsModule; } +bool ETSParser::CheckDupAndReplace(Program *&oldProg, Program *newProg) +{ + if (!importPathManager_->ArkTSConfig()->UseUrl() && oldProg->FileName() == newProg->FileName() && + oldProg->FileNameWithExtension() != newProg->FileNameWithExtension()) { + bool oldIsDeclare = oldProg->FileNameWithExtension().Length() > newProg->FileNameWithExtension().Length(); + if (oldIsDeclare) { + Context()->dupPrograms.emplace(oldProg->AbsoluteName(), newProg); + oldProg = newProg; + } else { + Context()->dupPrograms.emplace(newProg->AbsoluteName(), oldProg); + } + return true; + } + return false; +} + void ETSParser::AddExternalSource(const std::vector &programs) { auto &extSources = globalProgram_->ExternalSources(); @@ -216,11 +232,17 @@ void ETSParser::AddExternalSource(const std::vector &programs) extSources.try_emplace(name, Allocator()->Adapter()); } bool found = false; - for (auto *prog : extSources.at(name)) { + auto &extProgs = extSources.at(name); + for (size_t i = 0; i < extProgs.size(); ++i) { + auto *prog = extProgs[i]; if (prog->SourceFilePath() == newProg->SourceFilePath()) { found = true; break; } + if (CheckDupAndReplace(prog, newProg)) { + found = true; + break; + } } if (!found) { extSources.at(name).emplace_back(newProg); @@ -228,6 +250,15 @@ void ETSParser::AddExternalSource(const std::vector &programs) } } +void ETSParser::ParseAndSetStdlib() +{ + auto defaultSources = ParseSources(); + // for (auto prog:defaultSources) { + // prog->SetGenAbcF(); + // } + AddExternalSource(defaultSources); +} + ArenaVector ETSParser::ParseDefaultSources(std::string_view srcFile, std::string_view importSrc) { @@ -248,13 +279,13 @@ ArenaVector ETSParser::ParseDefaultSources(std::stri } if (!Context()->compiledByCapi) { - AddExternalSource(ParseSources()); + ParseAndSetStdlib(); } else { if (Context()->globalContext != nullptr && Context()->globalContext->stdLibAstCache != nullptr) { globalProgram_->MergeExternalSource(Context()->globalContext->stdLibAstCache); importPathManager_->ClearParseList(); } else { - AddExternalSource(ParseSources()); + ParseAndSetStdlib(); } } return statements; @@ -269,7 +300,7 @@ void ETSParser::AddDirectImportsToDirectExternalSources( return; } - const util::StringView name = newProg->Ast()->Statements().empty() ? newProg->FileName() : newProg->ModuleName(); + const util::StringView name = newProg->ModuleName(); if (GetProgram()->DirectExternalSources().count(name) == 0) { GetProgram()->DirectExternalSources().try_emplace(name, Allocator()->Adapter()); } @@ -421,7 +452,12 @@ parser::Program *ETSParser::ParseSource(const SourceFile &sourceFile) ir::ETSModule *script = nullptr; if (decl != nullptr) { statements.emplace_back(decl); + importPathManager_->AddImplicitPackageImportToParseList(program->SourceFile().GetAbsoluteParentFolder(), + Lexer()->GetToken().Start()); + // Global program file is always in the same folder that we scanned, but we don't need to parse it twice + importPathManager_->MarkAsParsed(program->AbsoluteName()); SavedParserContext contextAfterParseDecl(this, GetContext().Status() |= ParserStatus::IN_PACKAGE); + script = ParseETSGlobalScript(startLoc, statements); } else { script = ParseETSGlobalScript(startLoc, statements); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 1d7b1ee848ab4bda4cc268e993862210aa770d2f..20e6d30ecb45c03ea8e54b723c1acf26eaa11d48 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -70,6 +70,7 @@ public: void AddDirectImportsToDirectExternalSources(const ArenaVector &directImportsFromMainSource, parser::Program *newProg) const; + bool CheckDupAndReplace(Program *&oldProg, Program *newProg); ArenaVector ParseDefaultSources(std::string_view srcFile, std::string_view importSrc); lexer::LexerPosition HandleJsDocLikeComments(); @@ -144,6 +145,7 @@ public: std::vector ParseSources(bool firstSource = false); private: + void ParseAndSetStdlib(); NodeFormatType GetFormatPlaceholderType(); ir::Statement *ParseStatementFormatPlaceholder() override; ir::Expression *ParseExpressionFormatPlaceholder(); diff --git a/ets2panda/parser/program/program.cpp b/ets2panda/parser/program/program.cpp index 572ce976dc019b2b7e56d904c9303874ed1e8ce9..d771e7d1589cde536dadd40cc7e5f7dd26a353e4 100644 --- a/ets2panda/parser/program/program.cpp +++ b/ets2panda/parser/program/program.cpp @@ -73,6 +73,11 @@ const checker::Checker *Program::Checker() const return checkers_.at(compiler::GetPhaseManager()->GetCurrentMajor()); } +bool Program::IsGenAbc() const +{ + return VarBinder()->GetContext()->config->options->GetCompilationMode() == CompilationMode::GEN_EXTEANL && genAbc; +} + std::string Program::Dump() const { ir::AstDumper dumper {ast_, SourceCode()}; diff --git a/ets2panda/parser/program/program.h b/ets2panda/parser/program/program.h index c29543942cadcf88358a2ac9db0e08e8f34a4169..34014396cd16e68210c4bab56cd3d1b0dd848d35 100644 --- a/ets2panda/parser/program/program.h +++ b/ets2panda/parser/program/program.h @@ -298,6 +298,17 @@ public: (FileName().Is("etsstdlib")); } + bool IsGenAbc() const; + + void SetGenAbc() + { + genAbc = true; + } + void SetGenAbcF() + { + genAbc = false; + } + varbinder::ClassScope *GlobalClassScope(); const varbinder::ClassScope *GlobalClassScope() const; @@ -382,10 +393,12 @@ private: ExternalSource externalSources_; DirectExternalSource directExternalSources_; ScriptKind kind_ {}; + bool isASTlowered_ {}; + bool genAbc {false}; ScriptExtension extension_ {}; ETSNolintsCollectionMap etsnolintCollection_; util::ModuleInfo moduleInfo_; - bool isASTlowered_ {}; + lexer::SourcePosition packageStartPosition_ {}; compiler::CFG *cfg_; std::vector> declGenExportNodes_; @@ -405,8 +418,7 @@ private: namespace enumbitops { template <> -struct IsAllowedType : std::true_type { -}; +struct IsAllowedType : std::true_type {}; } // namespace enumbitops diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 8df91d24aff6942c01c70ef14542a277129967cd..9028601f2f01d0e41b7007417f7a83e4bd4b2dc9 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -124,8 +124,8 @@ __attribute__((unused)) char *UStringToCString(ArenaAllocator *allocator, util:: return StringViewToCString(allocator, sv.View()); } -__attribute__((unused)) es2panda_variantDoubleCharArrayBool EnumMemberResultToEs2pandaVariant( - ArenaAllocator *allocator, varbinder::EnumMemberResult variant) +__attribute__((unused)) es2panda_variantDoubleCharArrayBool +EnumMemberResultToEs2pandaVariant(ArenaAllocator *allocator, varbinder::EnumMemberResult variant) { // NOLINTBEGIN(cppcoreguidelines-pro-type-union-access) // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) @@ -162,8 +162,8 @@ __attribute__((unused)) es2panda_DynamicImportData *DynamicImportDataToE2pPtr( return es2pandaDynamicImportData; } -__attribute__((unused)) es2panda_DynamicImportData DynamicImportDataToE2p( - const varbinder::DynamicImportData dynamicImportData) +__attribute__((unused)) es2panda_DynamicImportData +DynamicImportDataToE2p(const varbinder::DynamicImportData dynamicImportData) { auto import = reinterpret_cast(dynamicImportData.import); auto specifier = reinterpret_cast(dynamicImportData.specifier); @@ -297,6 +297,15 @@ extern "C" const es2panda_Options *ConfigGetOptions(es2panda_Config *config) static void CompileJob(public_lib::Context *context, varbinder::FunctionScope *scope, compiler::ProgramElement *programElement) { + if (scope->InternalName().Is("ETSGLOBAL.:void;")) { + return; + } + if (scope->InternalName().Is("ETSGLOBAL._$init$_:void;")) { + return; + } + if (scope->InternalName().Is("ETSGLOBAL.main:void;")) { + return; + } compiler::StaticRegSpiller regSpiller; ArenaAllocator allocator {SpaceType::SPACE_TYPE_COMPILER, nullptr, true}; compiler::ETSCompiler astCompiler {}; @@ -395,6 +404,7 @@ __attribute__((unused)) static es2panda_Context *CreateContext(es2panda_Config * res->config = cfg; res->isExternal = isExternal; + res->isGenProjectAbc = false; res->globalContext = reinterpret_cast(globalContext); res->diagnosticEngine = cfg->diagnosticEngine; @@ -466,6 +476,12 @@ extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromFile(es2pa return CreateContext(config, ss.str(), sourceFileName, nullptr, false, false); } +extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromMultiFile(es2panda_Config *config, + char const *sourceFileNames) +{ + return CreateContext(config, "", sourceFileNames, nullptr, false, false); +} + extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromString(es2panda_Config *config, const char *source, char const *fileName) { @@ -473,6 +489,46 @@ extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromString(es2 return CreateContext(config, std::string(source), fileName, nullptr, false, false); } +extern __attribute__((unused)) es2panda_Context *CreateContextGenerateAbcForExternalSourceFiles( + es2panda_Config *config, int fileNamesCount, char const *const *fileNames) +{ + auto *cfg = reinterpret_cast(config); + auto *res = new Context; + res->compiledByCapi = true; + if (cfg == nullptr) { + res->errorMessage = "Config is nullptr."; + res->state = ES2PANDA_STATE_ERROR; + return reinterpret_cast(res); + } + + if (cfg->options->GetExtension() != ScriptExtension::ETS) { + res->errorMessage = "Invalid extension. Plugin API supports only ETS."; + res->state = ES2PANDA_STATE_ERROR; + res->diagnosticEngine = cfg->diagnosticEngine; + return reinterpret_cast(res); + } + + res->config = cfg; + res->isGenProjectAbc = true; + const_cast(res->config->options)->SetCompilationMode(CompilationMode::GEN_EXTEANL); + for (size_t i = 0; i < static_cast(fileNamesCount); ++i) { + const char *cName = *(fileNames + i); + std::string fileName(cName); + res->sourceFileNames.emplace_back(std::move(fileName)); + } + + res->diagnosticEngine = cfg->diagnosticEngine; + + res->input = ""; + res->sourceFileName = ""; + res->sourceFile = new SourceFile(res->sourceFileName, res->input, cfg->options->IsModule()); + ir::DisableContextHistory(); + res->allocator = new ThreadSafeArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + + InitializeContext(res); + return reinterpret_cast(res); +} + __attribute__((unused)) static Context *Parse(Context *ctx) { if (ctx->state != ES2PANDA_STATE_NEW) { @@ -481,6 +537,40 @@ __attribute__((unused)) static Context *Parse(Context *ctx) return ctx; } + auto MarkGenAbc = [](std::unordered_set &genAbcList, ExternalSource &extSources) { + size_t genCount = 0; + std::unordered_set genAbcListAbsolute; + + for (auto &path : genAbcList) { + std::filesystem::path symlink_path = path; + std::filesystem::path resolved_path = std::filesystem::canonical(symlink_path); + genAbcListAbsolute.insert(resolved_path); + } + for (auto &[_, extPrograms] : extSources) { + (void)_; + for (auto *prog : extPrograms) { + if (auto it = genAbcListAbsolute.find(prog->AbsoluteName().Mutf8()); it != genAbcListAbsolute.end()) { + prog->SetGenAbc(); + ++genCount; + } + } + } + for (auto &[_, extPrograms] : extSources) { + (void)_; + if (std::any_of(extPrograms.begin(), extPrograms.end(), + [](parser::Program *prog) { return prog->IsGenAbc(); })) { + for (auto *prog : extPrograms) { + prog->SetGenAbc(); + } + } + } + + ES2PANDA_ASSERT(genCount == genAbcListAbsolute.size()); + if (genCount != genAbcListAbsolute.size()) { + std::cout << "-----------------------------genabc path------------------------failed" << std::endl; + } + }; + ctx->phaseManager->Reset(); if (ctx->isExternal && ctx->allocator != ctx->globalContext->stdLibAllocator) { auto allocator = ctx->allocator; @@ -496,6 +586,24 @@ __attribute__((unused)) static Context *Parse(Context *ctx) importData.ohmUrl = util::ImportPathManager::DUMMY_PATH; ctx->parser->AsETSParser()->GetImportPathManager()->AddToParseList(importData); ctx->parser->AsETSParser()->AddExternalSource(ctx->parser->AsETSParser()->ParseSources(true)); + } else if (ctx->isGenProjectAbc) { + auto allocator = ctx->allocator; + auto ident = allocator->New(compiler::Signatures::ETS_GLOBAL, allocator); + ArenaVector stmts(allocator->Adapter()); + auto etsModule = allocator->New(allocator, std::move(stmts), ident, ir::ModuleFlag::ETSSCRIPT, + ctx->parserProgram); + ctx->parserProgram->SetAst(etsModule); + std::unordered_set sourceFileNamesSet(ctx->sourceFileNames.begin(), ctx->sourceFileNames.end()); + for (auto &sourceName : ctx->sourceFileNames) { + util::ImportPathManager::ImportMetadata importData {util::ImportFlags::NONE}; + importData.resolvedSource = sourceName; + importData.lang = Language::Id::ETS; + importData.declPath = util::ImportPathManager::DUMMY_PATH; + importData.ohmUrl = util::ImportPathManager::DUMMY_PATH; + ctx->parser->AsETSParser()->GetImportPathManager()->AddToParseList(importData); + } + ctx->parser->AsETSParser()->AddExternalSource(ctx->parser->AsETSParser()->ParseSources(true)); + MarkGenAbc(sourceFileNamesSet, ctx->parserProgram->ExternalSources()); } else { ctx->parser->ParseScript(*ctx->sourceFile, ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB); @@ -506,6 +614,22 @@ __attribute__((unused)) static Context *Parse(Context *ctx) return ctx; } +__attribute__((unused)) static bool SetProgramGenAbc(Context *ctx, const char *path) +{ + util::StringView pathView(path); + public_lib::Context *context = reinterpret_cast(ctx); + for (auto &[_, extPrograms] : context->externalSources) { + (void)_; + for (auto *prog : extPrograms) { + if (prog->AbsoluteName() == pathView) { + prog->SetGenAbc(); + return true; + } + } + } + return false; +} + __attribute__((unused)) static Context *Bind(Context *ctx) { if (ctx->state < ES2PANDA_STATE_PARSED) { @@ -1245,6 +1369,7 @@ es2panda_Impl g_impl = { CreateContextFromFile, CreateCacheContextFromFile, CreateContextFromString, + CreateContextGenerateAbcForExternalSourceFiles, ProceedToState, DestroyContext, CreateGlobalContext, diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index cf927443b4f8927ae3bde32e4da2d471051bb38c..d35ac3477f97d69db015e22b71bd30d81001a039 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -187,6 +187,8 @@ struct CAPI_EXPORT es2panda_Impl { es2panda_Context *(*CreateCacheContextFromFile)(es2panda_Config *config, char const *source_file_name, es2panda_GlobalContext *globalContext, bool isExternal); es2panda_Context *(*CreateContextFromString)(es2panda_Config *config, const char *source, char const *file_name); + es2panda_Context *(*CreateContextGenerateAbcForExternalSourceFiles)(es2panda_Config *config, int fileNamesCount, + char const *const *fileNames); es2panda_Context *(*ProceedToState)(es2panda_Context *context, es2panda_ContextState state); // context is consumed void (*DestroyContext)(es2panda_Context *context); diff --git a/ets2panda/public/public.h b/ets2panda/public/public.h index 46ddf91b4cf5295d74d5a601958c7b5ac833a853..9e183728fe620283ff50aba432e458f33079e7d7 100644 --- a/ets2panda/public/public.h +++ b/ets2panda/public/public.h @@ -226,7 +226,10 @@ struct Context { TransitionMemory *transitionMemory {nullptr}; bool isExternal = false; bool compiledByCapi = false; + bool isGenProjectAbc = false; checker::IsolatedDeclgenChecker *isolatedDeclgenChecker {nullptr}; + std::vector sourceFileNames; + std::map dupPrograms {}; // NOLINTEND(misc-non-private-member-variables-in-classes) private: diff --git a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt index bdff84c10b858546bbc682285e61754399df128c..8f64a5b0d59690bf2414f3555c2d9f0506bbb634 100644 --- a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt @@ -86,3 +86,14 @@ import_self_head_tests/B/test.d.ets #Issue 25550 enum-initialize-with-enum3.ets + +class_implements_interface_export.ets +class_implements_interface_import.ets +extension_function_tests/extensionFunctionReturnThis2.ets +getteSetterImplementation.ets +getterSetterImplementationWithConstructor.ets +implementsClassPropertyFunctionType.ets +implementsClassPropertyFunctionType2.ets +lambda_with_receiver/lambda_with_receiver_return_this2.ets +multisource_inheritance-2.ets +readonly_simple_form_pos.ets diff --git a/ets2panda/util/importPathManager.cpp b/ets2panda/util/importPathManager.cpp index 7cf04669276b7b647c1a6d4a086c986641ad2d86..e6d8a1e8b118a667dc39e6898a0199e58aa76edb 100644 --- a/ets2panda/util/importPathManager.cpp +++ b/ets2panda/util/importPathManager.cpp @@ -262,7 +262,7 @@ void ImportPathManager::AddToParseList(const ImportMetadata importMetadata) // surely re-parse it. // // If a file was already not implicitly package imported, then it's just a duplicate, return - if (!found->importData.IsImplicitPackageImported()) { + if (!found->importData.IsImplicitPackageImported() || importMetadata.IsImplicitPackageImported()) { return; } diff --git a/ets2panda/util/importPathManager.h b/ets2panda/util/importPathManager.h index 9e011a215919850377801f2c805284ab4e50a03d..888f5e45fb1e3e9fae3e49de6a298a67d48e9d48 100644 --- a/ets2panda/util/importPathManager.h +++ b/ets2panda/util/importPathManager.h @@ -145,6 +145,10 @@ public: void MarkAsParsed(StringView path); util::StringView FormRelativePath(const util::Path &path); + const std::shared_ptr ArkTSConfig() const + { + return arktsConfig_; + } private: util::StringView FormModuleNameSolelyByAbsolutePath(const util::Path &path); @@ -166,6 +170,7 @@ private: std::string TryMatchDynamicPath(std::string_view fixedPath) const; StringView GetRealPath(StringView path) const; + public: void AddToParseList(ImportMetadata importMetadata); #ifdef USE_UNIX_SYSCALL diff --git a/ets2panda/util/options.h b/ets2panda/util/options.h index 47e693e74c59a76784698f42e4c9e90f833dedcd..96ff13808f25e0faac6947e68ff154067ef6ddcc 100644 --- a/ets2panda/util/options.h +++ b/ets2panda/util/options.h @@ -86,6 +86,11 @@ public: return compilationMode_; } + void SetCompilationMode(CompilationMode compilationMode) + { + compilationMode_ = compilationMode; + } + void SetEvalMode(std::string_view evalModeStr) { ES2PANDA_ASSERT(eval_mode::FromString(evalModeStr) != eval_mode::INVALID); diff --git a/ets2panda/util/options.yaml b/ets2panda/util/options.yaml index 3dab3459f66048e31eae1d9ee80131919daaecf3..6fb7209c4ebd1cdb0a807ad07a06d3599a03e1eb 100644 --- a/ets2panda/util/options.yaml +++ b/ets2panda/util/options.yaml @@ -376,5 +376,5 @@ options: - name: perm-arena type: bool - default: true + default: false description: Place AST trees in permanent arena diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index f2983e06ca9e44054da91bbb320072f9c10867b8..966f14f229c319a9998b612aa9dfb1f24066e4b0 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -389,6 +389,11 @@ void ETSBinder::BuildInterfaceDeclaration(ir::TSInterfaceDeclaration *decl) void ETSBinder::BuildMethodDefinition(ir::MethodDefinition *methodDef) { + if (methodDef->BaseOverloadMethod() != nullptr && + methodDef->GetTopStatement()->AsETSModule()->Program() != Program() && + methodDef->BaseOverloadMethod()->GetTopStatement() != methodDef->GetTopStatement()) { + return; + } if (methodDef->Function()->TypeParams() != nullptr) { auto scopeCtx = LexicalScope::Enter(this, methodDef->Function()->TypeParams()->Scope()); ResolveReferences(methodDef->Function()->TypeParams()); @@ -1201,10 +1206,22 @@ void ETSBinder::InitImplicitThisParam() void ETSBinder::BuildProgram() { + // A tmp solution caused by #23877, needs to check stdlib first to avoid a bug in std/math/math.ets + // After the bug fixed, we can merge these 2 loop. + static const std::string STD_SUFFIX = "std."; + for (auto &[_, extPrograms] : Program()->ExternalSources()) { + if (_.Utf8().substr(0, STD_SUFFIX.length()) == STD_SUFFIX) { + for (auto *extProg : extPrograms) { + BuildExternalProgram(extProg); + } + } + } for (auto &[_, extPrograms] : Program()->ExternalSources()) { (void)_; - for (auto *extProg : extPrograms) { - BuildExternalProgram(extProg); + if (_.Utf8().substr(0, STD_SUFFIX.length()) != STD_SUFFIX) { + for (auto *extProg : extPrograms) { + BuildExternalProgram(extProg); + } } } @@ -1238,7 +1255,8 @@ void ETSBinder::BuildExternalProgram(parser::Program *extProgram) auto *savedRecordTable = recordTable_; auto *savedTopScope = TopScope(); - auto flags = Program()->VarBinder()->IsGenStdLib() ? RecordTableFlags::NONE : RecordTableFlags::EXTERNAL; + auto flags = Program()->VarBinder()->IsGenStdLib() || (extProgram->IsGenAbc()) ? RecordTableFlags::NONE + : RecordTableFlags::EXTERNAL; auto *extRecordTable = Allocator()->New(Allocator(), extProgram, flags); extRecordTable->SetClassDefinition(extProgram->GlobalClass()); @@ -1439,24 +1457,28 @@ const DynamicImportData *ETSBinder::DynamicImportDataForVar(const Variable *var) return &it->second; } -ArenaVector ETSBinder::GetProgramList(const util::StringView &path) const noexcept +ArenaVector ETSBinder::GetProgramList(const util::StringView &oldPath) const noexcept { auto const *globalProgram = globalRecordTable_.Program(); + util::StringView newPath = oldPath; + if (auto it = GetContext()->dupPrograms.find(oldPath); it != GetContext()->dupPrograms.end()) { + newPath = it->second->AbsoluteName(); + } for (const auto &extRecords : globalProgram->ExternalSources()) { for (const auto &program : extRecords.second) { - if (program->AbsoluteName() == path) { + if (program->AbsoluteName() == newPath) { return extRecords.second; } // in case of importing a package folder, the path could not be resolved to a specific file - if (program->IsPackage() && program->SourceFileFolder() == path) { + if (program->IsPackage() && program->SourceFileFolder() == newPath) { return extRecords.second; } } } - if (globalProgram->IsPackage() && path.Compare(globalProgram->SourceFileFolder()) == 0) { + if (globalProgram->IsPackage() && newPath.Compare(globalProgram->SourceFileFolder()) == 0) { return ArenaVector({GetContext()->parserProgram}, Allocator()->Adapter()); }