• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "lexenv.h"
17 
18 #include "varbinder/variable.h"
19 #include "compiler/core/envScope.h"
20 #include "compiler/core/pandagen.h"
21 #include "compiler/core/moduleContext.h"
22 #include "ir/expressions/identifier.h"
23 
24 namespace panda::es2panda::compiler {
25 // Helpers
26 
CheckTdz(const ir::AstNode * node)27 static bool CheckTdz(const ir::AstNode *node)
28 {
29     return node->IsIdentifier() && node->AsIdentifier()->IsTdz();
30 }
31 
CheckConstAssignment(PandaGen * pg,const ir::AstNode * node,varbinder::Variable * variable)32 static void CheckConstAssignment(PandaGen *pg, const ir::AstNode *node, varbinder::Variable *variable)
33 {
34     if (!variable->Declaration()->IsConstDecl()) {
35         return;
36     }
37 
38     pg->ThrowConstAssignment(node, variable->Name());
39 }
40 
41 // VirtualLoadVar
42 
ExpandLoadLexVar(PandaGen * pg,const ir::AstNode * node,const varbinder::ConstScopeFindResult & result)43 static void ExpandLoadLexVar(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result)
44 {
45     if (result.variable->Declaration()->IsVarDecl()) {
46         pg->LoadLexicalVar(node, result.lexLevel, result.variable->AsLocalVariable()->LexIdx());
47     } else {
48         pg->LoadLexical(node, result.name, result.lexLevel, result.variable->AsLocalVariable()->LexIdx());
49     }
50 }
51 
ExpandLoadNormalVar(PandaGen * pg,const ir::AstNode * node,const varbinder::ConstScopeFindResult & result)52 static void ExpandLoadNormalVar(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result)
53 {
54     auto *local = result.variable->AsLocalVariable();
55 
56     if (CheckTdz(node)) {
57         pg->ThrowTdz(node, local->Name());
58     } else {
59         pg->LoadAccumulator(node, local->Vreg());
60     }
61 }
62 
Expand(PandaGen * pg,const ir::AstNode * node,const varbinder::ConstScopeFindResult & result)63 void VirtualLoadVar::Expand(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result)
64 {
65     if (result.variable->LexicalBound()) {
66         ExpandLoadLexVar(pg, node, result);
67     } else {
68         ExpandLoadNormalVar(pg, node, result);
69     }
70 }
71 
72 // VirtualStoreVar
73 
StoreLocalExport(PandaGen * pg,const ir::AstNode * node,varbinder::Variable * variable)74 static void StoreLocalExport(PandaGen *pg, const ir::AstNode *node, varbinder::Variable *variable)
75 {
76     if (!variable->HasFlag(varbinder::VariableFlags::LOCAL_EXPORT) || !pg->Scope()->IsModuleScope()) {
77         return;
78     }
79 
80     auto range = pg->Scope()->AsModuleScope()->LocalExports().equal_range(variable);
81 
82     for (auto it = range.first; it != range.second; ++it) {
83         if (it->second != "default") {
84             pg->StoreModuleVar(node, it->second);
85         }
86     }
87 }
88 
ExpandStoreLexVar(PandaGen * pg,const ir::AstNode * node,const varbinder::ConstScopeFindResult & result,bool isDecl)89 static void ExpandStoreLexVar(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result,
90                               bool isDecl)
91 {
92     varbinder::LocalVariable *local = result.variable->AsLocalVariable();
93 
94     const auto *decl = result.variable->Declaration();
95 
96     if (decl->IsLetOrConstDecl() && !isDecl) {
97         if (decl->IsConstDecl()) {
98             pg->ThrowConstAssignment(node, local->Name());
99         }
100 
101         pg->StoreLexical(node, result.name, result.lexLevel, local->LexIdx());
102     } else {
103         pg->StoreLexicalVar(node, result.lexLevel, local->LexIdx());
104     }
105 
106     StoreLocalExport(pg, node, local);
107 }
108 
ExpandStoreNormalVar(PandaGen * pg,const ir::AstNode * node,const varbinder::ConstScopeFindResult & result,bool isDecl)109 static void ExpandStoreNormalVar(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result,
110                                  bool isDecl)
111 {
112     auto *local = result.variable->AsLocalVariable();
113     VReg localReg = local->Vreg();
114 
115     if (!isDecl) {
116         if (CheckTdz(node)) {
117             pg->ThrowTdz(node, local->Name());
118         }
119 
120         CheckConstAssignment(pg, node, local);
121     }
122 
123     pg->StoreAccumulator(node, localReg);
124     StoreLocalExport(pg, node, local);
125 }
126 
Expand(PandaGen * pg,const ir::AstNode * node,const varbinder::ConstScopeFindResult & result,bool isDecl)127 void VirtualStoreVar::Expand(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result,
128                              bool isDecl)
129 {
130     if (result.variable->LexicalBound()) {
131         ExpandStoreLexVar(pg, node, result, isDecl);
132     } else {
133         ExpandStoreNormalVar(pg, node, result, isDecl);
134     }
135 }
136 }  // namespace panda::es2panda::compiler
137