1   // Copyright 2013 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
9    * expression and a reference type.
10   */
11  
12  class JInstanceOfOp extends JExpression {
13  
14      /** The expression denoting the value to be tested. */
15      private JExpression expr;
16  
17      /** The reference type we are testing for. */
18      private Type typeSpec;
19  
20      /**
21       * Construct an AST node for an instanceof expression given its line number,
22       * the relational expression and reference type.
23       * 
24       * @param line
25       *            the line in which the instanceof expression occurs in the
26       *            source file.
27       * @param expr
28       *            the expression denoting the value to be tested.
29       * @param typeSpec
30       *            the reference type we are testing for.
31       */
32  
33      public JInstanceOfOp(int line, JExpression expr, Type typeSpec) {
34          super(line);
35          this.expr = expr;
36          this.typeSpec = typeSpec;
37      }
38  
39      /**
40       * Analysis of an instanceof operation requires analyzing the expression to
41       * be tested, resolving the type was are testing for, and determining if the
42       * test is legal, or if the answer can be determined at compile time.
43       * 
44       * @param context
45       *            context in which names are resolved.
46       * @return the analyzed (and possibly rewritten) AST subtree.
47       */
48  
49      public JInstanceOfOp analyze(Context context) {
50          expr = (JExpression) expr.analyze(context);
51          typeSpec = typeSpec.resolve(context);
52          if (!typeSpec.isReference()) {
53              JAST.compilationUnit.reportSemanticError(line(),
54                      "Type argument to instanceof "
55                              + "operator must be a reference type");
56          } else if (!(expr.type() == Type.NULLTYPE || expr.type() == Type.ANY || expr
57                  .type().isReference())) {
58              JAST.compilationUnit.reportSemanticError(line(),
59                      "operand to instanceof "
60                              + "operator must be a reference type");
61          } else if (expr.type().isReference()
62                  && !typeSpec.isJavaAssignableFrom(expr.type())) {
63              JAST.compilationUnit.reportSemanticError(line(),
64                      "It is impossible for the expression "
65                              + "to be an instance of this type");
66          }
67          type = Type.BOOLEAN;
68          return this;
69      }
70  
71      /**
72       * Generate code for the type test.
73       * 
74       * @param output
75       *            the code emitter (basically an abstraction for producing the
76       *            .class file).
77       */
78  
79      public void codegen(CLEmitter output) {
80          expr.codegen(output);
81          output.addReferenceInstruction(INSTANCEOF, typeSpec.toDescriptor());
82      }
83  
84      /**
85       * @inheritDoc
86       */
87  
88      public void writeToStdOut(PrettyPrinter p) {
89          p.printf("<JInstanceOfOp line=\"%d\" type=\"%s\">\n", line(),
90                  ((type == null) ? "" : type.toString()));
91          p.indentRight();
92          p.printf("<RelationalExpression>\n");
93          p.indentRight();
94          expr.writeToStdOut(p);
95          p.indentLeft();
96          p.printf("</RelationalExpression>\n");
97          p.printf("<ReferenceType value=\"%s\"/>\n", ((typeSpec == null) ? ""
98                  : typeSpec.toString()));
99          p.indentLeft();
100         p.printf("</JInstanceOfOp>\n");
101     }
102 
103 }
104