1   // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import static jminusminus.CLConstants.*;
6   
7   /**
8    * The AST node for an instanceof expression, having two arguments: an expression and a reference
9    * type.
10   */
11  class JInstanceOfOp extends JExpression {
12      // The expression denoting the value to be tested.
13      private JExpression expr;
14  
15      // The reference type we are testing for.
16      private Type typeSpec;
17  
18      /**
19       * Constructs an AST node for an instanceof expression.
20       *
21       * @param line     the line in which the instanceof expression occurs in the source file.
22       * @param expr     the expression denoting the value to be tested.
23       * @param typeSpec the reference type we are testing for.
24       */
25      public JInstanceOfOp(int line, JExpression expr, Type typeSpec) {
26          super(line);
27          this.expr = expr;
28          this.typeSpec = typeSpec;
29      }
30  
31      /**
32       * {@inheritDoc}
33       */
34      public JInstanceOfOp analyze(Context context) {
35          expr = (JExpression) expr.analyze(context);
36          typeSpec = typeSpec.resolve(context);
37          if (!typeSpec.isReference()) {
38              JAST.compilationUnit.reportSemanticError(line(),
39                      "RHS of instanceof must be a reference type");
40          } else if (!(expr.type() == Type.NULLTYPE || expr.type() == Type.ANY ||
41                  expr.type().isReference())) {
42              JAST.compilationUnit.reportSemanticError(line(),
43                      "LHS of instanceof must be a reference type");
44          } else if (expr.type().isReference() && !typeSpec.isJavaAssignableFrom(expr.type()) &&
45                  !expr.type().isJavaAssignableFrom(typeSpec)) {
46              JAST.compilationUnit.reportSemanticError(line(),
47                      "It is impossible for the expression to be an instance of " +
48                              typeSpec.toString());
49          }
50          type = Type.BOOLEAN;
51          return this;
52      }
53  
54      /**
55       * {@inheritDoc}
56       */
57      public void codegen(CLEmitter output) {
58          expr.codegen(output);
59          output.addReferenceInstruction(INSTANCEOF, typeSpec.jvmName());
60      }
61  
62      /**
63       * {@inheritDoc}
64       */
65      public void codegen(CLEmitter output, String targetLabel, boolean onTrue) {
66          codegen(output);
67          if (onTrue) {
68              output.addBranchInstruction(IFNE, targetLabel);
69          } else {
70              output.addBranchInstruction(IFEQ, targetLabel);
71          }
72      }
73  
74      /**
75       * {@inheritDoc}
76       */
77      public void toJSON(JSONElement json) {
78          JSONElement e = new JSONElement();
79          json.addChild("JInstanceOfOp:" + line, e);
80          e.addAttribute("type", type == null ? "" : type.toString());
81          e.addAttribute("referenceType", typeSpec == null ? "" : typeSpec.toString());
82          JSONElement e1 = new JSONElement();
83          e.addChild("Expression", e1);
84          expr.toJSON(e1);
85      }
86  }
87