Use constexpr in more places and remove some unnecessary external linkage.
[WebKit-https.git] / Source / WebCore / Modules / webgpu / WHLSL / WHLSLNameResolver.cpp
1 /*
2  * Copyright (C) 2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WHLSLNameResolver.h"
28
29 #if ENABLE(WEBGPU)
30
31 #include "WHLSLDoWhileLoop.h"
32 #include "WHLSLDotExpression.h"
33 #include "WHLSLEnumerationDefinition.h"
34 #include "WHLSLEnumerationMemberLiteral.h"
35 #include "WHLSLForLoop.h"
36 #include "WHLSLFunctionDefinition.h"
37 #include "WHLSLIfStatement.h"
38 #include "WHLSLNameContext.h"
39 #include "WHLSLProgram.h"
40 #include "WHLSLReplaceWith.h"
41 #include "WHLSLResolveOverloadImpl.h"
42 #include "WHLSLScopedSetAdder.h"
43 #include "WHLSLTypeReference.h"
44 #include "WHLSLVariableDeclaration.h"
45 #include "WHLSLVariableReference.h"
46 #include "WHLSLWhileLoop.h"
47
48 namespace WebCore {
49
50 namespace WHLSL {
51
52 NameResolver::NameResolver(NameContext& nameContext)
53     : m_nameContext(nameContext)
54 {
55 }
56
57 NameResolver::NameResolver(NameResolver& parentResolver, NameContext& nameContext)
58     : m_nameContext(nameContext)
59     , m_parentNameResolver(&parentResolver)
60     , m_currentNameSpace(parentResolver.m_currentNameSpace)
61 {
62 }
63
64 NameResolver::~NameResolver()
65 {
66     if (hasError() && m_parentNameResolver)
67         m_parentNameResolver->setError(result().error());
68 }
69
70 void NameResolver::visit(AST::TypeReference& typeReference)
71 {
72     ScopedSetAdder<AST::TypeReference*> adder(m_typeReferences, &typeReference);
73     if (!adder.isNewEntry()) {
74         setError(Error("Cannot use recursive type arguments.", typeReference.codeLocation()));
75         return;
76     }
77
78     Visitor::visit(typeReference);
79     if (hasError())
80         return;
81     if (typeReference.maybeResolvedType()) // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198161 Shouldn't we know by now whether the type has been resolved or not?
82         return;
83
84     auto candidates = m_nameContext.getTypes(typeReference.name(), m_currentNameSpace);
85     for (auto& candidate : candidates)
86         Visitor::visit(candidate);
87     if (auto result = resolveTypeOverloadImpl(candidates, typeReference.typeArguments()))
88         typeReference.setResolvedType(*result);
89     else {
90         setError(Error("Cannot resolve type arguments.", typeReference.codeLocation()));
91         return;
92     }
93 }
94
95 void NameResolver::visit(AST::FunctionDefinition& functionDefinition)
96 {
97     NameContext newNameContext(&m_nameContext);
98     NameResolver newNameResolver(*this, newNameContext);
99     checkErrorAndVisit(functionDefinition.type());
100     if (hasError())
101         return;
102     for (auto& parameter : functionDefinition.parameters())
103         newNameResolver.checkErrorAndVisit(parameter);
104     newNameResolver.checkErrorAndVisit(functionDefinition.block());
105 }
106
107 void NameResolver::visit(AST::Block& block)
108 {
109     NameContext nameContext(&m_nameContext);
110     NameResolver newNameResolver(*this, nameContext);
111     newNameResolver.Visitor::visit(block);
112 }
113
114 void NameResolver::visit(AST::IfStatement& ifStatement)
115 {
116     checkErrorAndVisit(ifStatement.conditional());
117     if (hasError())
118         return;
119
120     {
121         NameContext nameContext(&m_nameContext);
122         NameResolver newNameResolver(*this, nameContext);
123         newNameResolver.checkErrorAndVisit(ifStatement.body());
124     }
125     if (hasError())
126         return;
127
128     if (ifStatement.elseBody()) {
129         NameContext nameContext(&m_nameContext);
130         NameResolver newNameResolver(*this, nameContext);
131         newNameResolver.checkErrorAndVisit(*ifStatement.elseBody());
132     }
133 }
134
135 void NameResolver::visit(AST::WhileLoop& whileLoop)
136 {
137     checkErrorAndVisit(whileLoop.conditional());
138     if (hasError())
139         return;
140
141     NameContext nameContext(&m_nameContext);
142     NameResolver newNameResolver(*this, nameContext);
143     newNameResolver.checkErrorAndVisit(whileLoop.body());
144 }
145
146 void NameResolver::visit(AST::DoWhileLoop& whileLoop)
147 {
148     {
149         NameContext nameContext(&m_nameContext);
150         NameResolver newNameResolver(*this, nameContext);
151         newNameResolver.checkErrorAndVisit(whileLoop.body());
152     }
153
154     checkErrorAndVisit(whileLoop.conditional());
155 }
156
157 void NameResolver::visit(AST::ForLoop& forLoop)
158 {
159     NameContext nameContext(&m_nameContext);
160     NameResolver newNameResolver(*this, nameContext);
161     newNameResolver.Visitor::visit(forLoop);
162 }
163
164 void NameResolver::visit(AST::VariableDeclaration& variableDeclaration)
165 {
166     if (!m_nameContext.add(variableDeclaration)) {
167         setError(Error("Cannot declare duplicate variables.", variableDeclaration.codeLocation()));
168         return;
169     }
170     Visitor::visit(variableDeclaration);
171 }
172
173 void NameResolver::visit(AST::VariableReference& variableReference)
174 {
175     if (variableReference.variable())
176         return;
177
178     if (auto* variable = m_nameContext.getVariable(variableReference.name()))
179         variableReference.setVariable(*variable);
180     else {
181         setError(Error("Cannot find the variable declaration.", variableReference.codeLocation()));
182         return;
183     }
184 }
185
186 void NameResolver::visit(AST::DotExpression& dotExpression)
187 {
188     if (is<AST::VariableReference>(dotExpression.base())) {
189         auto& variableReference = downcast<AST::VariableReference>(dotExpression.base());
190         if (!m_nameContext.getVariable(variableReference.name())) {
191             auto baseName = variableReference.name();
192             auto enumerationTypes = m_nameContext.getTypes(baseName, m_currentNameSpace);
193             if (enumerationTypes.size() == 1) {
194                 AST::NamedType& type = enumerationTypes[0];
195                 if (is<AST::EnumerationDefinition>(type)) {
196                     AST::EnumerationDefinition& enumerationDefinition = downcast<AST::EnumerationDefinition>(type);
197                     auto memberName = dotExpression.fieldName();
198                     if (auto* member = enumerationDefinition.memberByName(memberName)) {
199                         auto enumerationMemberLiteral = AST::EnumerationMemberLiteral::wrap(dotExpression.codeLocation(), WTFMove(baseName), WTFMove(memberName), enumerationDefinition, *member);
200                         AST::replaceWith<AST::EnumerationMemberLiteral>(dotExpression, WTFMove(enumerationMemberLiteral));
201                         return;
202                     }
203                     setError(Error("No enum member matches the used name.", dotExpression.codeLocation()));
204                     return;
205                 }
206             } else
207                 ASSERT(enumerationTypes.isEmpty());
208         }
209     }
210
211     Visitor::visit(dotExpression);
212 }
213
214 void NameResolver::visit(AST::EnumerationMemberLiteral& enumerationMemberLiteral)
215 {
216     if (enumerationMemberLiteral.enumerationMember())
217         return;
218
219     auto enumerationTypes = m_nameContext.getTypes(enumerationMemberLiteral.left(), m_currentNameSpace);
220     if (enumerationTypes.size() == 1) {
221         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=199335 This needs to work with typedef'ed enums.
222         AST::NamedType& type = enumerationTypes[0];
223         if (is<AST::EnumerationDefinition>(type)) {
224             AST::EnumerationDefinition& enumerationDefinition = downcast<AST::EnumerationDefinition>(type);
225             if (auto* member = enumerationDefinition.memberByName(enumerationMemberLiteral.right())) {
226                 enumerationMemberLiteral.setEnumerationMember(enumerationDefinition, *member);
227                 return;
228             }
229         }
230     }
231
232     setError(Error("Cannot resolve enumeration member literal.", enumerationMemberLiteral.codeLocation()));
233 }
234
235 void NameResolver::visit(AST::NativeFunctionDeclaration& nativeFunctionDeclaration)
236 {
237     NameContext newNameContext(&m_nameContext);
238     NameResolver newNameResolver(newNameContext);
239     newNameResolver.Visitor::visit(nativeFunctionDeclaration);
240 }
241
242 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198167 Make sure all the names have been resolved.
243
244 Expected<void, Error> resolveNamesInTypes(Program& program, NameResolver& nameResolver)
245 {
246     for (auto& typeDefinition : program.typeDefinitions()) {
247         nameResolver.setCurrentNameSpace(typeDefinition.get().nameSpace());
248         nameResolver.checkErrorAndVisit(typeDefinition);
249         if (nameResolver.hasError())
250             return nameResolver.result();
251     }
252     for (auto& structureDefinition : program.structureDefinitions()) {
253         nameResolver.setCurrentNameSpace(structureDefinition.get().nameSpace());
254         nameResolver.checkErrorAndVisit(structureDefinition);
255         if (nameResolver.hasError())
256             return nameResolver.result();
257     }
258     for (auto& enumerationDefinition : program.enumerationDefinitions()) {
259         nameResolver.setCurrentNameSpace(enumerationDefinition.get().nameSpace());
260         nameResolver.checkErrorAndVisit(enumerationDefinition);
261         if (nameResolver.hasError())
262             return nameResolver.result();
263     }
264     for (auto& nativeTypeDeclaration : program.nativeTypeDeclarations()) {
265         nameResolver.setCurrentNameSpace(nativeTypeDeclaration.get().nameSpace());
266         nameResolver.checkErrorAndVisit(nativeTypeDeclaration);
267         if (nameResolver.hasError())
268             return nameResolver.result();
269     }
270     return { };
271 }
272
273 Expected<void, Error> resolveTypeNamesInFunctions(Program& program, NameResolver& nameResolver)
274 {
275     for (auto& functionDefinition : program.functionDefinitions()) {
276         nameResolver.setCurrentNameSpace(functionDefinition.get().nameSpace());
277         nameResolver.checkErrorAndVisit(functionDefinition);
278         if (nameResolver.hasError())
279             return nameResolver.result();
280     }
281     for (auto& nativeFunctionDeclaration : program.nativeFunctionDeclarations()) {
282         nameResolver.setCurrentNameSpace(nativeFunctionDeclaration.get().nameSpace());
283         nameResolver.checkErrorAndVisit(nativeFunctionDeclaration);
284         if (nameResolver.hasError())
285             return nameResolver.result();
286     }
287     return { };
288 }
289
290 } // namespace WHLSL
291
292 } // namespace WebCore
293
294 #endif // ENABLE(WEBGPU)