1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngcpp/binder/StatementBinder.hpp>
  7 #include <sngcpp/binder/ExpressionBinder.hpp>
  8 #include <sngcpp/ast/SourceFile.hpp>
  9 
 10 namespace sngcpp { namespace binder {
 11 
 12 StatementBinder::StatementBinder(SymbolTable& symbolTable_const std::std::unordered_map<SourceFileNode*BoundSourceFile*>&sourceFileMap_):
 13     symbolTable(symbolTable_)sourceFileMap(sourceFileMap_)currentSourceFile(nullptr)containerScope(nullptr)currentFunction(nullptr)
 14 {
 15 }
 16 
 17 void StatementBinder::Visit(SourceFileNode& sourceFileNode)
 18 {
 19     if (sourceFileNode.SourceFilePath().find("Lexer.cpp") != std::string::npos)
 20     {
 21         int x = 0;
 22     }
 23     auto it = sourceFileMap.find(&sourceFileNode);
 24     if (it != sourceFileMap.cend())
 25     {
 26         currentSourceFile = it->second;
 27     }
 28     else
 29     {
 30         throw std::runtime_error("source file not found");
 31     }
 32     containerScope = symbolTable.GlobalNs()->GetContainerScope();
 33     sourceFileNode.GlobalNs()->Accept(*this);
 34 }
 35 
 36 void StatementBinder::Visit(SourceFileSequenceNode& sourceFileSequenceNode)
 37 {
 38     sourceFileSequenceNode.Left()->Accept(*this);
 39     sourceFileSequenceNode.Right()->Accept(*this);
 40 }
 41 
 42 void StatementBinder::Visit(SimpleDeclarationNode& simpleDeclarationNode)
 43 {
 44     BindExpression(simpleDeclarationNode.TypeExpr()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
 45     BindExpression(simpleDeclarationNode.Declarator()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
 46 }
 47 
 48 void StatementBinder::Visit(NamespaceNode& namespaceNode)
 49 {
 50     if (namespaceNode.Child())
 51     {
 52         namespaceNode.Child()->Accept(*this);
 53     }
 54 }
 55 
 56 void StatementBinder::Visit(MemberAccessDeclarationNode& memberAccessDeclarationNode)
 57 {
 58     memberAccessDeclarationNode.Declaration()->Accept(*this);
 59 }
 60 
 61 void StatementBinder::Visit(MemberDeclarationNode& memberDeclarationNode)
 62 {
 63     if (memberDeclarationNode.TypeExpr())
 64     {
 65         BindExpression(memberDeclarationNode.TypeExpr()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
 66     }
 67     BindExpression(memberDeclarationNode.Declarator()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
 68     if (memberDeclarationNode.Initializer())
 69     {
 70         BindExpression(memberDeclarationNode.Initializer()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
 71     }
 72 }
 73 
 74 void StatementBinder::Visit(DeclarationSequenceNode& declarationSequenceNode)
 75 {
 76     declarationSequenceNode.Left()->Accept(*this);
 77     declarationSequenceNode.Right()->Accept(*this);
 78 }
 79 
 80 void StatementBinder::Visit(LinkageSpecificationNode& linkageSpecificationNode)
 81 {
 82     linkageSpecificationNode.Declarations()->Accept(*this);
 83 }
 84 
 85 void StatementBinder::Visit(TemplateDeclarationNode& templateDeclarationNode)
 86 {
 87     templateDeclarationNode.Declaration()->Accept(*this);
 88 }
 89 
 90 void StatementBinder::Visit(ClassNode& classNode)
 91 {
 92     Symbol* symbol = symbolTable.GetSymbol(&classNode);
 93     if (symbol->IsClassTypeSymbol())
 94     {
 95         ClassTypeSymbol* classTypeSymbol = static_cast<ClassTypeSymbol*>(symbol);
 96         ContainerScope* prevContainerScope = containerScope;
 97         containerScope = classTypeSymbol->GetContainerScope();
 98         if (classNode.Declarations())
 99         {
100             classNode.Declarations()->Accept(*this);
101         }
102         containerScope = prevContainerScope;
103     }
104     else
105     {
106         throw std::runtime_error("class type symbol expected");
107     }
108 }
109 
110 void StatementBinder::Visit(FunctionNode& functionNode)
111 {
112     Symbol* symbol = symbolTable.GetSymbolNothrow(&functionNode);
113     if (symbol)
114     {
115         if (symbol->IsFunctionSymbol())
116         {
117             FunctionSymbol* prevFunction = currentFunction;
118             currentFunction = static_cast<FunctionSymbol*>(symbol);
119             if (currentFunction->GroupName() == U"MakeCanonicalClasses")
120             {
121                 int x = 0;
122             }
123             ContainerScope* prevContainerScope = containerScope;
124             containerScope = currentFunction->GetContainerScope();
125             if (functionNode.Body())
126             {
127                 functionNode.Body()->Accept(*this);
128             }
129             currentFunction = prevFunction;
130             containerScope = prevContainerScope;
131         }
132         else
133         {
134             throw std::runtime_error("function symbol expected");
135         }
136     }
137 }
138 
139 void StatementBinder::Visit(SpecialMemberFunctionNode& specialMemberFunctionNode)
140 {
141     Symbol* symbol = symbolTable.GetSymbolNothrow(&specialMemberFunctionNode);
142     if (symbol)
143     {
144         if (symbol->IsFunctionSymbol())
145         {
146             FunctionSymbol* prevFunction = currentFunction;
147             currentFunction = static_cast<FunctionSymbol*>(symbol);
148             ContainerScope* prevContainerScope = containerScope;
149             containerScope = currentFunction->GetContainerScope();
150             if (specialMemberFunctionNode.CtorInitializer())
151             {
152                 BindExpression(specialMemberFunctionNode.CtorInitializer()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
153             }
154             if (specialMemberFunctionNode.FunctionBody())
155             {
156                 specialMemberFunctionNode.FunctionBody()->Accept(*this);
157             }
158             currentFunction = prevFunction;
159             containerScope = prevContainerScope;
160         }
161         else
162         {
163             throw std::runtime_error("function symbol expected");
164         }
165     }
166 }
167 
168 void StatementBinder::Visit(CompoundStatementNode& compoundStatementNode)
169 {
170     Symbol* symbol = symbolTable.GetSymbol(&compoundStatementNode);
171     if (symbol->IsDeclarationBlockSymbol())
172     {
173         DeclarationBlockSymbol* declarationBlock = static_cast<DeclarationBlockSymbol*>(symbol);
174         ContainerScope* prevContainerScope = containerScope;
175         containerScope = declarationBlock->GetContainerScope();
176         if (compoundStatementNode.Child())
177         {
178             compoundStatementNode.Child()->Accept(*this);
179         }
180         containerScope = prevContainerScope;
181     }
182     else
183     {
184         throw std::runtime_error("declaration block expected");
185     }
186 }
187 
188 void StatementBinder::Visit(StatementSequenceNode& statementSequenceNode)
189 {
190     statementSequenceNode.Left()->Accept(*this);
191     statementSequenceNode.Right()->Accept(*this);
192 }
193 
194 void StatementBinder::Visit(LabeledStatementNode& labeledStatementNode)
195 {
196     labeledStatementNode.Child()->Accept(*this);
197 }
198 
199 void StatementBinder::Visit(IfStatementNode& ifStatementNode)
200 {
201     BindExpression(ifStatementNode.Condition()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
202     ifStatementNode.ThenS()->Accept(*this);
203     if (ifStatementNode.ElseS())
204     {
205         ifStatementNode.ElseS()->Accept(*this);
206     }
207 }
208 
209 void StatementBinder::Visit(SwitchStatementNode& switchStatementNode)
210 {
211     BindExpression(switchStatementNode.Condition()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
212     switchStatementNode.Statement()->Accept(*this);
213 }
214 
215 void StatementBinder::Visit(CaseStatementNode& caseStatementNode)
216 {
217     BindExpression(caseStatementNode.CaseExpr()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
218     caseStatementNode.Child()->Accept(*this);
219 }
220 
221 void StatementBinder::Visit(DefaultStatementNode& defaultStatementNode)
222 {
223     defaultStatementNode.Child()->Accept(*this);
224 }
225 
226 void StatementBinder::Visit(ExpressionStatementNode& expressionStatementNode)
227 {
228     if (expressionStatementNode.Child())
229     {
230         BindExpression(expressionStatementNode.Child()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
231     }
232 }
233 
234 void StatementBinder::Visit(WhileStatementNode& whileStatementNode)
235 {
236     BindExpression(whileStatementNode.Condition()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
237     whileStatementNode.Statement()->Accept(*this);
238 }
239 
240 void StatementBinder::Visit(DoStatementNode& doStatementNode)
241 {
242     doStatementNode.Statement()->Accept(*this);
243     BindExpression(doStatementNode.Condition()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
244 }
245 
246 void StatementBinder::Visit(RangeForStatementNode& rangeForStatementNode)
247 {
248     Symbol* symbol = symbolTable.GetSymbol(&rangeForStatementNode);
249     if (symbol->IsDeclarationBlockSymbol())
250     {
251         DeclarationBlockSymbol* declarationBlock = static_cast<DeclarationBlockSymbol*>(symbol);
252         ContainerScope* prevContainerScope = containerScope;
253         containerScope = declarationBlock->GetContainerScope();
254         BindExpression(rangeForStatementNode.ForRangeDeclaration()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
255         BindExpression(rangeForStatementNode.ForRangeInitializer()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
256         rangeForStatementNode.Statement()->Accept(*this);
257         containerScope = prevContainerScope;
258     }
259     else
260     {
261         throw std::runtime_error("declaration block expected");
262     }
263 }
264 
265 void StatementBinder::Visit(ForStatementNode& forStatementNode)
266 {
267     Symbol* symbol = symbolTable.GetSymbol(&forStatementNode);
268     if (symbol->IsDeclarationBlockSymbol())
269     {
270         DeclarationBlockSymbol* declarationBlock = static_cast<DeclarationBlockSymbol*>(symbol);
271         ContainerScope* prevContainerScope = containerScope;
272         containerScope = declarationBlock->GetContainerScope();
273         if (forStatementNode.InitS())
274         {
275             forStatementNode.InitS()->Accept(*this);
276         }
277         if (forStatementNode.Condition())
278         {
279             BindExpression(forStatementNode.Condition()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
280         }
281         if (forStatementNode.LoopExpr())
282         {
283             BindExpression(forStatementNode.LoopExpr()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
284         }
285         forStatementNode.ActionS()->Accept(*this);
286         containerScope = prevContainerScope;
287     }
288     else
289     {
290         throw std::runtime_error("declaration block expected");
291     }
292 }
293 
294 void StatementBinder::Visit(ReturnStatementNode& returnStatementNode)
295 {
296     if (returnStatementNode.ReturnExpr())
297     {
298         BindExpression(returnStatementNode.ReturnExpr()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
299     }
300 }
301 
302 void StatementBinder::Visit(DeclarationStatementNode& declarationStatementNode)
303 {
304     BindExpression(declarationStatementNode.Child()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
305 }
306 
307 void StatementBinder::Visit(TryStatementNode& tryStatementNode)
308 {
309     tryStatementNode.TryBlock()->Accept(*this);
310     tryStatementNode.Handlers()->Accept(*this);
311 }
312 
313 void StatementBinder::Visit(HandlerNode& handlerNode)
314 {
315     BindExpression(handlerNode.ExceptionDeclaration()symbolTablecontainerScopestd::vector<ContainerScope*>()currentSourceFilecurrentFunctionthis);
316     handlerNode.CatchBlock()->Accept(*this);
317 }
318 
319 void StatementBinder::Visit(HandlerSequenceNode& handlerSequenceNode)
320 {
321     handlerSequenceNode.Left()->Accept(*this);
322     handlerSequenceNode.Right()->Accept(*this);
323 }
324 
325 } } // namespace sngcpp::binder