1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ES2PANDA_PARSER_CORE_MODULERECORD_H
17#define ES2PANDA_PARSER_CORE_MODULERECORD_H
18
19#include <util/ustring.h>
20
21namespace panda::es2panda::binder {
22class ModuleScope;
23class Variable;
24}
25
26namespace panda::es2panda::ir {
27class Identifier;
28}  // namespace panda::es2panda::ir
29
30namespace panda::es2panda::parser {
31class SourceTextModuleRecord {
32public:
33    explicit SourceTextModuleRecord(ArenaAllocator *allocator)
34        : allocator_(allocator),
35          moduleRequestsMap_(allocator_->Adapter()),
36          moduleRequests_(allocator_->Adapter()),
37          localExportEntries_(allocator_->Adapter()),
38          regularImportEntries_(allocator_->Adapter()),
39          namespaceImportEntries_(allocator_->Adapter()),
40          starExportEntries_(allocator_->Adapter()),
41          indirectExportEntries_(allocator_->Adapter())
42    {
43    }
44
45    ~SourceTextModuleRecord() = default;
46    NO_COPY_SEMANTIC(SourceTextModuleRecord);
47    NO_MOVE_SEMANTIC(SourceTextModuleRecord);
48
49    struct ImportEntry {
50        int moduleRequestIdx_;
51        util::StringView localName_;
52        util::StringView importName_;
53        const ir::Identifier *localId_ {nullptr};
54        const ir::Identifier *importId_ {nullptr};
55
56        ImportEntry(const util::StringView localName, const util::StringView importName, int moduleRequestIdx,
57                    const ir::Identifier *localId, const ir::Identifier *importId)
58            : moduleRequestIdx_(moduleRequestIdx), localName_(localName), importName_(importName),
59              localId_(localId), importId_(importId) {}
60        ImportEntry(const util::StringView localName, int moduleRequestIdx, const ir::Identifier *localId)
61            : moduleRequestIdx_(moduleRequestIdx), localName_(localName), localId_(localId) {}
62    };
63
64    struct ExportEntry {
65        int moduleRequestIdx_;
66        util::StringView exportName_;
67        util::StringView localName_;
68        util::StringView importName_;
69        const ir::Identifier *exportId_ {nullptr};
70        const ir::Identifier *localId_ {nullptr};
71        const ir::Identifier *importId_ {nullptr};
72        bool isConstant_ {false};
73
74        explicit ExportEntry(int moduleRequest) : moduleRequestIdx_(moduleRequest) {}
75        ExportEntry(const util::StringView exportName, const util::StringView localName,
76                    const ir::Identifier *exportId, const ir::Identifier *localId)
77            : moduleRequestIdx_(-1), exportName_(exportName), localName_(localName),
78              exportId_(exportId), localId_(localId) {}
79        ExportEntry(const util::StringView exportName, const util::StringView importName, int moduleRequest,
80                    const ir::Identifier *exportId, const ir::Identifier *importId)
81            : moduleRequestIdx_(moduleRequest), exportName_(exportName), importName_(importName),
82              exportId_(exportId), importId_(importId) {}
83
84        void SetAsConstant()
85        {
86            isConstant_ = true;
87        }
88    };
89
90    struct ModuleRequestRecord {
91        util::StringView source_;
92        bool isLazy_ {false};
93
94        explicit ModuleRequestRecord(util::StringView source) : source_{source} {}
95        ModuleRequestRecord(util::StringView source, bool isLazy) : source_{source}, isLazy_{isLazy} {}
96
97        bool operator<(const ModuleRequestRecord &mrr) const
98        {
99            return source_ < mrr.source_ || (source_ == mrr.source_ && isLazy_ && !mrr.isLazy_);
100        }
101    };
102
103    template <typename T, typename... Args>
104    T *NewEntry(Args &&... args)
105    {
106        return allocator_->New<T>(std::forward<Args>(args)...);
107    }
108
109    template <typename... Args>
110    int AddModuleRequest(Args &&... args)
111    {
112        const auto *record = allocator_->New<ModuleRequestRecord>(std::forward<Args>(args)...);
113        CHECK_NOT_NULL(record);
114        return AddModuleRequest(*record);
115    }
116    int AddModuleRequest(const ModuleRequestRecord record);
117    void AddImportEntry(ImportEntry *entry);
118    void AddStarImportEntry(ImportEntry *entry);
119    bool AddLocalExportEntry(ExportEntry *entry);
120    void RemoveDefaultLocalExportEntry();
121    bool AddIndirectExportEntry(ExportEntry *entry);
122    void AddStarExportEntry(ExportEntry *entry);
123
124    bool CheckImplicitIndirectExport(ExportEntry *exportEntry);
125    void CheckImplicitIndirectExport(ImportEntry *importEntry);
126
127    void AssignIndexToModuleVariable(binder::ModuleScope *moduleScope);
128    int GetModuleRequestIdx(const util::StringView localName);
129
130    using ModuleRequestList = ArenaVector<ModuleRequestRecord>;
131    using ModuleRequestMap = ArenaMap<const ModuleRequestRecord, uint32_t>;
132    using LocalExportEntryMap = ArenaMultiMap<const util::StringView, ExportEntry *>;
133    using RegularImportEntryMap = ArenaMap<const util::StringView, ImportEntry *>;
134    using NamespaceImportEntryList = ArenaVector<ImportEntry *>;
135    using SpecialExportEntryList = ArenaVector<ExportEntry *>;
136
137    const ModuleRequestList &GetModuleRequests() const
138    {
139        return moduleRequests_;
140    }
141
142    const LocalExportEntryMap &GetLocalExportEntries() const
143    {
144        return localExportEntries_;
145    }
146
147    const RegularImportEntryMap &GetRegularImportEntries() const
148    {
149        return regularImportEntries_;
150    }
151
152    const NamespaceImportEntryList &GetNamespaceImportEntries() const
153    {
154        return namespaceImportEntries_;
155    }
156
157    const SpecialExportEntryList &GetStarExportEntries() const
158    {
159        return starExportEntries_;
160    }
161
162    const SpecialExportEntryList &GetIndirectExportEntries() const
163    {
164        return indirectExportEntries_;
165    }
166
167    bool HasLazyImport() const
168    {
169        return hasLazyImport_;
170    }
171
172    static constexpr std::string_view DEFAULT_LOCAL_NAME = "*default*";
173    static constexpr std::string_view DEFAULT_EXTERNAL_NAME = "default";
174    static constexpr std::string_view ANONY_NAMESPACE_NAME = "=ens";
175    static constexpr int INVALID_MODULEREQUEST_ID = -1;
176
177private:
178    bool HasDuplicateExport(util::StringView exportName) const;
179    void ConvertLocalExportToIndirect(ImportEntry *importEntry, ExportEntry *exportEntry);
180    binder::Variable *CheckAndAssignIndex(binder::ModuleScope *moduleScope, util::StringView name, uint32_t *idx) const;
181
182    ArenaAllocator *allocator_;
183    ModuleRequestMap moduleRequestsMap_;
184    ModuleRequestList moduleRequests_;
185    LocalExportEntryMap localExportEntries_;
186    RegularImportEntryMap regularImportEntries_;
187    NamespaceImportEntryList namespaceImportEntries_;
188    SpecialExportEntryList starExportEntries_;
189    SpecialExportEntryList indirectExportEntries_;
190    bool hasLazyImport_ { false };
191};
192} // namespace panda::es2panda::parser
193
194#endif