1/**
2 * Copyright (c) 2021-2024 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#include "moduleContext.h"
17
18#include "varbinder/scope.h"
19#include "varbinder/variable.h"
20#include "compiler/base/lreference.h"
21#include "compiler/core/pandagen.h"
22#include "ir/expressions/literals/stringLiteral.h"
23#include "ir/module/exportAllDeclaration.h"
24#include "ir/module/exportNamedDeclaration.h"
25#include "ir/module/importDeclaration.h"
26
27namespace ark::es2panda::compiler {
28void CompileImports(PandaGen *pg, varbinder::ModuleScope *scope)
29{
30    for (const auto &[importDecl, decls] : scope->Imports()) {
31        pg->ImportModule(importDecl, importDecl->Source()->Str());
32
33        VReg moduleReg = pg->AllocReg();
34        pg->StoreAccumulator(importDecl, moduleReg);
35
36        for (const auto *decl : decls) {
37            varbinder::Variable *v = scope->FindLocal(decl->LocalName(), varbinder::ResolveBindingOptions::BINDINGS);
38
39            if (!v->IsModuleVariable()) {
40                ASSERT(decl->ImportName() == "*");
41
42                varbinder::ConstScopeFindResult result(decl->LocalName(), scope, 0, v);
43                pg->StoreAccToLexEnv(decl->Node(), result, true);
44            } else {
45                v->AsModuleVariable()->ModuleReg() = moduleReg;
46            }
47        }
48    }
49}
50
51void CompileExports(PandaGen *pg, const varbinder::ModuleScope *scope)
52{
53    for (const auto &[exportDecl, decls] : scope->Exports()) {
54        if (exportDecl->IsExportAllDeclaration()) {
55            pg->ImportModule(exportDecl, exportDecl->AsExportAllDeclaration()->Source()->Str());
56        } else if (exportDecl->IsExportNamedDeclaration() &&
57                   (exportDecl->AsExportNamedDeclaration()->Source() != nullptr)) {
58            pg->ImportModule(exportDecl, exportDecl->AsExportNamedDeclaration()->Source()->Str());
59        } else {
60            continue;
61        }
62
63        VReg moduleReg = pg->AllocReg();
64        pg->StoreAccumulator(exportDecl, moduleReg);
65
66        if (exportDecl->IsExportAllDeclaration()) {
67            pg->StoreModuleVar(exportDecl, decls.front()->ExportName());
68            continue;
69        }
70
71        pg->CopyModule(exportDecl, moduleReg);
72
73        for (const auto *decl : decls) {
74            pg->LoadAccumulator(decl->Node(), moduleReg);
75            pg->LoadObjByName(decl->Node(), decl->LocalName());
76            pg->StoreModuleVar(decl->Node(), decl->ExportName());
77        }
78    }
79}
80
81void ModuleContext::Compile(PandaGen *pg, varbinder::ModuleScope *scope)
82{
83    CompileImports(pg, scope);
84    CompileExports(pg, scope);
85}
86}  // namespace ark::es2panda::compiler
87