001    /* Copyright (c) 2014, Erik Hogeman <Erik.Hogemn@gmail.com>
002     * All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions are met:
006     *
007     *     * Redistributions of source code must retain the above copyright notice,
008     *       this list of conditions and the following disclaimer.
009     *     * Redistributions in binary form must reproduce the above copyright
010     *       notice, this list of conditions and the following disclaimer in the
011     *       documentation and/or other materials provided with the distribution.
012     *     * Neither the name of the Lund University nor the names of its
013     *       contributors may be used to endorse or promote products derived from
014     *       this software without specific prior written permission.
015     *
016     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
017     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
018     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
019     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
020     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
021     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
022     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
023     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
024     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
025     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
026     * POSSIBILITY OF SUCH DAMAGE.
027     */
028    
029    aspect TargetType {
030      inh lazy TypeDecl Expr.targetType();
031    
032      eq Program.getChild().targetType() = typeNull();
033    
034      eq ConditionalExpr.getTrueExpr().targetType() = targetType();
035      eq ConditionalExpr.getFalseExpr().targetType() = targetType();
036      eq AbstractDot.getRight().targetType() = targetType();
037      eq ParExpr.getExpr().targetType() = targetType();
038      eq AssignExpr.getSource().targetType() = getDest().type();
039      eq VariableDeclaration.getInit().targetType() = getTypeAccess().type();
040      eq FieldDeclaration.getInit().targetType() = getTypeAccess().type();
041      eq ReturnStmt.getResult().targetType() = returnType();
042      eq CastExpr.getExpr().targetType() = type();
043    
044      eq AddExpr.getLeftOperand().targetType() {
045        if (getLeftOperand().stringContext()) {
046          return getRightOperand().type();
047        } else if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) {
048          return type();
049        } else {
050          return targetType();
051        }
052      }
053      eq AddExpr.getRightOperand().targetType() {
054        if (getRightOperand().stringContext()) {
055          return getLeftOperand().type();
056        } else if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) {
057          return type();
058        } else {
059          return targetType();
060        }
061      }
062    
063      eq ArithmeticExpr.getLeftOperand().targetType() {
064        if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) {
065          return type();
066        } else {
067          return targetType();
068        }
069      }
070    
071      eq ArithmeticExpr.getRightOperand().targetType() {
072        if (!getLeftOperand().isPolyExpression() && !getRightOperand().isPolyExpression()) {
073          return type();
074        } else {
075          return targetType();
076        }
077      }
078    
079      eq ArrayInit.getInit().targetType() {
080        if (!(targetType() instanceof ArrayDecl)) {
081          return targetType();
082        } else {
083          return ((ArrayDecl) targetType()).componentType();
084        }
085      }
086    
087      eq MethodAccess.getArg(int i).targetType() {
088        MethodDecl decl = decl();
089        if (decl.unknownMethod() == decl) {
090          return decl.type().unknownType();
091        }
092    
093        if (decl.isVariableArity() && i >= decl.arity() - 1) {
094          return decl.getParameter(decl.arity() - 1).type().componentType();
095        } else {
096          return decl.getParameter(i).type();
097        }
098      }
099    
100      eq ConstructorAccess.getArg(int i).targetType() {
101        ConstructorDecl decl = decl();
102        if (unknownConstructor() == decl) {
103          return decl.type().unknownType();
104        }
105    
106        if (decl.isVariableArity() && i >= decl.arity() - 1) {
107          return decl.getParameter(decl.arity() - 1).type().componentType();
108        } else {
109          return decl.getParameter(i).type();
110        }
111      }
112    
113      eq ClassInstanceExpr.getArg(int i).targetType() {
114        ConstructorDecl decl = decl();
115        if (unknownConstructor() == decl) {
116          return decl.type().unknownType();
117        }
118    
119        if (decl.isVariableArity() && i >= decl.arity() - 1) {
120          return decl.getParameter(decl.arity() - 1).type().componentType();
121        } else {
122          return decl.getParameter(i).type();
123        }
124      }
125    
126      eq ExprLambdaBody.getExpr().targetType() {
127        TypeDecl decl = enclosingLambda().targetType();
128        if (decl.isNull()) {
129          return unknownType();
130        } else if (!(decl instanceof InterfaceDecl)) {
131          return unknownType();
132        } else {
133          InterfaceDecl iDecl = (InterfaceDecl)decl;
134          if (!iDecl.isFunctional()) {
135            return unknownType();
136          } else {
137            return iDecl.functionDescriptor().method.type();
138          }
139        }
140      }
141    
142      syn lazy InterfaceDecl LambdaExpr.targetInterface() {
143        if (targetType().isNull()) {
144          return null;
145        } else if (!(targetType() instanceof InterfaceDecl)) {
146          return null;
147        } else {
148          return (InterfaceDecl)targetType();
149        }
150      }
151    
152      syn lazy InterfaceDecl MethodReference.targetInterface() {
153        if (targetType().isNull()) {
154          return null;
155        } else if (!(targetType() instanceof InterfaceDecl)) {
156          return null;
157        } else {
158          return (InterfaceDecl) targetType();
159        }
160      }
161    
162      syn lazy InterfaceDecl ConstructorReference.targetInterface() {
163        if (targetType().isNull()) {
164          return null;
165        } else if (!(targetType() instanceof InterfaceDecl)) {
166          return null;
167        } else {
168          return (InterfaceDecl)targetType();
169        }
170      }
171    
172    
173      // This is required for type inference to work with method references
174      syn lazy TypeDecl MethodReferenceAccess.assignConvertedType() =
175          targetDescriptor.method.type();
176    
177      syn lazy TypeDecl ParMethodReferenceAccess.assignConvertedType() =
178          targetDescriptor.method.type();
179    
180      // Required for diamond type inference to work
181      eq ClassInstanceExpr.getAccess().assignConvertedType() = targetType();
182    
183      syn lazy TypeDecl ConstructorReferenceAccess.targetType() =
184          targetDescriptor.method.type();
185    
186      syn lazy TypeDecl ParConstructorReferenceAccess.targetType() =
187          targetDescriptor.method.type();
188    
189      eq ConstructorReferenceAccess.getAccess().targetType() =
190          targetDescriptor.method.type();
191    }
192    
193    
194    aspect Contexts {
195      // Ch 5
196      inh lazy boolean Expr.assignmentContext();
197      inh lazy boolean Expr.invocationContext();
198      inh lazy boolean Expr.castContext();
199      inh lazy boolean Expr.stringContext();
200      inh lazy boolean Expr.numericContext();
201    
202      eq CompilationUnit.getChild().assignmentContext() = false;
203      eq CompilationUnit.getChild().invocationContext() = false;
204      eq CompilationUnit.getChild().castContext() = false;
205      eq CompilationUnit.getChild().stringContext() = false;
206      eq CompilationUnit.getChild().numericContext() = false;
207    
208      eq ExprLambdaBody.getExpr().assignmentContext() = true;
209      eq ExprLambdaBody.getExpr().invocationContext() = false;
210      eq ExprLambdaBody.getExpr().castContext() = false;
211      eq ExprLambdaBody.getExpr().stringContext() = false;
212      eq ExprLambdaBody.getExpr().numericContext() = false;
213    
214      eq BlockLambdaBody.getBlock().assignmentContext() = false;
215      eq BlockLambdaBody.getBlock().invocationContext() = false;
216      eq BlockLambdaBody.getBlock().castContext() = false;
217      eq BlockLambdaBody.getBlock().stringContext() = false;
218      eq BlockLambdaBody.getBlock().numericContext() = false;
219    
220      eq Binary.getChild().assignmentContext() = false;
221      eq Binary.getChild().invocationContext() = false;
222      eq Binary.getChild().castContext() = false;
223      eq Binary.getChild().stringContext() = false;
224      eq Binary.getChild().numericContext() = false;
225    
226      eq AddExpr.getLeftOperand().stringContext() {
227        if (!getRightOperand().isPolyExpression() && !getLeftOperand().isPolyExpression()) {
228          if (getRightOperand().type().isString() && !getLeftOperand().type().isString()) {
229            return true;
230          }
231        }
232        return false;
233      }
234      eq AddExpr.getRightOperand().stringContext() {
235        if (!getRightOperand().isPolyExpression() && !getLeftOperand().isPolyExpression()) {
236          if (getLeftOperand().type().isString() && !getRightOperand().type().isString()) {
237            return true;
238          }
239        }
240        return false;
241      }
242    
243      eq ArithmeticExpr.getRightOperand().numericContext() = true;
244      eq ArithmeticExpr.getLeftOperand().numericContext() = true;
245    
246      eq Unary.getOperand().assignmentContext() = false;
247      eq Unary.getOperand().invocationContext() = false;
248      eq Unary.getOperand().castContext() = false;
249      eq Unary.getOperand().stringContext() = false;
250      eq Unary.getOperand().numericContext() = false;
251    
252      eq InstanceOfExpr.getExpr().assignmentContext() = false;
253      eq InstanceOfExpr.getExpr().invocationContext() = false;
254      eq InstanceOfExpr.getExpr().castContext() = false;
255      eq InstanceOfExpr.getExpr().stringContext() = false;
256      eq InstanceOfExpr.getExpr().numericContext() = false;
257    
258      eq ConditionalExpr.getCondition().assignmentContext() = false;
259      eq ConditionalExpr.getCondition().invocationContext() = false;
260      eq ConditionalExpr.getCondition().castContext() = false;
261      eq ConditionalExpr.getCondition().numericContext() = false;
262      eq ConditionalExpr.getCondition().stringContext() = false;
263    
264    
265      eq ConditionalExpr.getTrueExpr().assignmentContext() =
266          isPolyExpression() ? assignmentContext() : false;
267      eq ConditionalExpr.getTrueExpr().invocationContext() =
268          isPolyExpression() ? invocationContext() : false;
269      // 15.25.3
270      eq ConditionalExpr.getTrueExpr().castContext() = false;
271      eq ConditionalExpr.getTrueExpr().stringContext() = false;
272      eq ConditionalExpr.getTrueExpr().numericContext() = false;
273      eq ConditionalExpr.getFalseExpr().assignmentContext() =
274          isPolyExpression() ? assignmentContext() : false;
275      eq ConditionalExpr.getFalseExpr().invocationContext() =
276          isPolyExpression() ? invocationContext() : false;
277      // 15.25.3
278      eq ConditionalExpr.getFalseExpr().castContext() = false;
279      eq ConditionalExpr.getFalseExpr().stringContext() = false;
280      eq ConditionalExpr.getFalseExpr().numericContext() = false;
281    
282      eq ArrayAccess.getExpr().assignmentContext() = false;
283      eq ArrayAccess.getExpr().invocationContext() = false;
284      eq ArrayAccess.getExpr().castContext() = false;
285      eq ArrayAccess.getExpr().stringContext() = false;
286      eq ArrayAccess.getExpr().numericContext() = false;
287    
288      eq AbstractDot.getRight().assignmentContext() = assignmentContext();
289      eq AbstractDot.getRight().invocationContext() = invocationContext();
290      eq AbstractDot.getRight().castContext() = castContext();
291      eq AbstractDot.getRight().stringContext() = stringContext();
292      eq AbstractDot.getRight().numericContext() = numericContext();
293    
294      eq AbstractDot.getLeft().assignmentContext() = false;
295      eq AbstractDot.getLeft().invocationContext() = false;
296      eq AbstractDot.getLeft().castContext() = false;
297      eq AbstractDot.getLeft().stringContext() = false;
298      eq AbstractDot.getLeft().numericContext() = false;
299    
300      // 15.8.5
301      eq ParExpr.getExpr().assignmentContext() = assignmentContext();
302      eq ParExpr.getExpr().invocationContext() = invocationContext();
303      eq ParExpr.getExpr().castContext() = castContext();
304      eq ParExpr.getExpr().stringContext() = stringContext();
305      eq ParExpr.getExpr().numericContext() = numericContext();
306    
307      eq CastExpr.getExpr().assignmentContext() = false;
308      eq CastExpr.getExpr().invocationContext() = false;
309      eq CastExpr.getExpr().castContext() = true;
310      eq CastExpr.getExpr().stringContext() = false;
311      eq CastExpr.getExpr().numericContext() = false;
312    
313      eq AssignExpr.getDest().assignmentContext() = false;
314      eq AssignExpr.getDest().invocationContext() = false;
315      eq AssignExpr.getDest().castContext() = false;
316      eq AssignExpr.getDest().numericContext() = false;
317      eq AssignExpr.getDest().stringContext() = false;
318    
319      eq AssignExpr.getSource().assignmentContext() = true;
320      eq AssignExpr.getSource().invocationContext() = false;
321      eq AssignExpr.getSource().castContext() = false;
322      eq AssignExpr.getSource().stringContext() = false;
323      eq AssignExpr.getSource().numericContext() = false;
324    
325      eq ClassInstanceExpr.getArg().assignmentContext() = false;
326      eq ClassInstanceExpr.getArg().invocationContext() = true;
327      eq ClassInstanceExpr.getArg().castContext() = false;
328      eq ClassInstanceExpr.getArg().stringContext() = false;
329      eq ClassInstanceExpr.getArg().numericContext() = false;
330    
331      eq MethodAccess.getArg().assignmentContext() = false;
332      eq MethodAccess.getArg().invocationContext() = true;
333      eq MethodAccess.getArg().castContext() = false;
334      eq MethodAccess.getArg().stringContext() = false;
335      eq MethodAccess.getArg().numericContext() = false;
336    
337      eq ConstructorAccess.getArg().assignmentContext() = false;
338      eq ConstructorAccess.getArg().invocationContext() = true;
339      eq ConstructorAccess.getArg().castContext() = false;
340      eq ConstructorAccess.getArg().stringContext() = false;
341      eq ConstructorAccess.getArg().numericContext() = false;
342    
343      eq ArrayInit.getInit().assignmentContext() = true;
344      eq ArrayInit.getInit().invocationContext() = false;
345      eq ArrayInit.getInit().castContext() = false;
346      eq ArrayInit.getInit().stringContext() = false;
347      eq ArrayInit.getInit().numericContext() = false;
348    
349      eq VariableDeclaration.getInit().assignmentContext() = true;
350      eq VariableDeclaration.getInit().invocationContext() = false;
351      eq VariableDeclaration.getInit().castContext() = false;
352      eq VariableDeclaration.getInit().numericContext() = false;
353      eq VariableDeclaration.getInit().stringContext() = false;
354    
355      eq ReturnStmt.getResult().assignmentContext() = true;
356      eq ReturnStmt.getResult().invocationContext() = false;
357      eq ReturnStmt.getResult().castContext() = false;
358      eq ReturnStmt.getResult().stringContext() = false;
359      eq ReturnStmt.getResult().numericContext() = false;
360    
361      eq VariableDecl.getInit().assignmentContext() = true;
362      eq VariableDecl.getInit().invocationContext() = false;
363      eq VariableDecl.getInit().castContext() = false;
364      eq VariableDecl.getInit().stringContext() = false;
365      eq VariableDecl.getInit().numericContext() = false;
366    
367      eq ArrayTypeWithSizeAccess.getExpr().assignmentContext() = false;
368      eq ArrayTypeWithSizeAccess.getExpr().invocationContext() = false;
369      eq ArrayTypeWithSizeAccess.getExpr().castContext() = false;
370      eq ArrayTypeWithSizeAccess.getExpr().stringContext() = false;
371      eq ArrayTypeWithSizeAccess.getExpr().numericContext() = false;
372    
373      eq FieldDeclaration.getInit().assignmentContext() = true;
374      eq FieldDeclaration.getInit().invocationContext() = false;
375      eq FieldDeclaration.getInit().castContext() = false;
376      eq FieldDeclaration.getInit().stringContext() = false;
377      eq FieldDeclaration.getInit().numericContext() = false;
378    
379      eq Dims.getExpr().assignmentContext() = false;
380      eq Dims.getExpr().invocationContext() = false;
381      eq Dims.getExpr().castContext() = false;
382      eq Dims.getExpr().stringContext() = false;
383      eq Dims.getExpr().numericContext() = false;
384    
385      eq ExprMethodReference.getExpr().assignmentContext() = false;
386      eq ExprMethodReference.getExpr().invocationContext() = false;
387      eq ExprMethodReference.getExpr().castContext() = false;
388      eq ExprMethodReference.getExpr().stringContext() = false;
389      eq ExprMethodReference.getExpr().numericContext() = false;
390    
391      eq TypeMethodReference.getTypeAccess().assignmentContext() = false;
392      eq TypeMethodReference.getTypeAccess().invocationContext() = false;
393      eq TypeMethodReference.getTypeAccess().castContext() = false;
394      eq TypeMethodReference.getTypeAccess().stringContext() = false;
395      eq TypeMethodReference.getTypeAccess().numericContext() = false;
396    
397      eq ConstructorReference.getTypeAccess().assignmentContext() = false;
398      eq ConstructorReference.getTypeAccess().invocationContext() = false;
399      eq ConstructorReference.getTypeAccess().castContext() = false;
400      eq ConstructorReference.getTypeAccess().stringContext() = false;
401      eq ConstructorReference.getTypeAccess().numericContext() = false;
402    }
403