langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java
changeset 39920 4923274643f2
parent 39806 d3a13ca6013e
child 42827 36468b5fa7f4
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java	Fri Jul 29 12:27:08 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java	Mon Aug 01 08:36:02 2016 -0700
@@ -95,6 +95,7 @@
         names = Names.instance(context);
         log = Log.instance(context);
         types = Types.instance(context);
+        noOpSymbol = new OperatorSymbol(names.empty, Type.noType, -1, syms.noSymbol);
         initOperatorNames();
         initUnaryOperators();
         initBinaryOperators();
@@ -145,7 +146,7 @@
     /**
      * Entry point for resolving a unary operator given an operator tag and an argument type.
      */
-    Symbol resolveUnary(DiagnosticPosition pos, JCTree.Tag tag, Type op) {
+    OperatorSymbol resolveUnary(DiagnosticPosition pos, JCTree.Tag tag, Type op) {
         return resolve(tag,
                 unaryOperators,
                 unop -> unop.test(op),
@@ -156,7 +157,7 @@
     /**
      * Entry point for resolving a binary operator given an operator tag and a pair of argument types.
      */
-    Symbol resolveBinary(DiagnosticPosition pos, JCTree.Tag tag, Type op1, Type op2) {
+    OperatorSymbol resolveBinary(DiagnosticPosition pos, JCTree.Tag tag, Type op1, Type op2) {
         return resolve(tag,
                 binaryOperators,
                 binop -> binop.test(op1, op2),
@@ -169,8 +170,8 @@
      * map. If there's a matching operator, its resolve routine is called and the result is returned;
      * otherwise the result of a fallback function is returned.
      */
-    private <O> Symbol resolve(Tag tag, Map<Name, List<O>> opMap, Predicate<O> opTestFunc,
-                       Function<O, Symbol> resolveFunc, Supplier<Symbol> noResultFunc) {
+    private <O> OperatorSymbol resolve(Tag tag, Map<Name, List<O>> opMap, Predicate<O> opTestFunc,
+                       Function<O, OperatorSymbol> resolveFunc, Supplier<OperatorSymbol> noResultFunc) {
         return opMap.get(operatorName(tag)).stream()
                 .filter(opTestFunc)
                 .map(resolveFunc)
@@ -181,7 +182,7 @@
     /**
      * Creates an operator symbol.
      */
-    private Symbol makeOperator(Name name, List<OperatorType> formals, OperatorType res, int... opcodes) {
+    private OperatorSymbol makeOperator(Name name, List<OperatorType> formals, OperatorType res, int... opcodes) {
         MethodType opType = new MethodType(
                 formals.stream()
                         .map(o -> o.asType(syms))
@@ -201,10 +202,14 @@
                 ((opcodes[0] << ByteCodes.preShift) | opcodes[1]);
     }
 
+    /** A symbol that stands for a missing operator.
+     */
+    public final OperatorSymbol noOpSymbol;
+
     /**
      * Report an operator lookup error.
      */
-    private Symbol reportErrorIfNeeded(DiagnosticPosition pos, Tag tag, Type... args) {
+    private OperatorSymbol reportErrorIfNeeded(DiagnosticPosition pos, Tag tag, Type... args) {
         if (Stream.of(args).noneMatch(Type::isErroneous)) {
             Name opName = operatorName(tag);
             JCDiagnostic.Error opError = (args.length) == 1 ?
@@ -212,7 +217,7 @@
                     Errors.OperatorCantBeApplied1(opName, args[0], args[1]);
             log.error(pos, opError);
         }
-        return syms.noSymbol;
+        return noOpSymbol;
     }
 
     /**
@@ -263,10 +268,10 @@
         final Name name;
 
         /** The list of symbols associated with this operator (lazily populated). */
-        Optional<Symbol[]> alternatives = Optional.empty();
+        Optional<OperatorSymbol[]> alternatives = Optional.empty();
 
         /** An array of operator symbol suppliers (used to lazily populate the symbol list). */
-        List<Supplier<Symbol>> operatorSuppliers = List.nil();
+        List<Supplier<OperatorSymbol>> operatorSuppliers = List.nil();
 
         @SuppressWarnings("varargs")
         OperatorHelper(Tag tag) {
@@ -278,21 +283,21 @@
          * using an applicability predicate; if the test suceeds that same operator is returned,
          * otherwise a dummy symbol is returned.
          */
-        final Symbol doLookup(Predicate<Symbol> applicabilityTest) {
+        final OperatorSymbol doLookup(Predicate<OperatorSymbol> applicabilityTest) {
             return Stream.of(alternatives.orElseGet(this::initOperators))
                     .filter(applicabilityTest)
                     .findFirst()
-                    .orElse(syms.noSymbol);
+                    .orElse(noOpSymbol);
         }
 
         /**
          * This routine performs lazy instantiation of the operator symbols supported by this helper.
          * After initialization is done, the suppliers are cleared, to free up memory.
          */
-        private Symbol[] initOperators() {
-            Symbol[] operators = operatorSuppliers.stream()
+        private OperatorSymbol[] initOperators() {
+            OperatorSymbol[] operators = operatorSuppliers.stream()
                     .map(op -> op.get())
-                    .toArray(Symbol[]::new);
+                    .toArray(OperatorSymbol[]::new);
             alternatives = Optional.of(operators);
             operatorSuppliers = null; //let GC do its work
             return operators;
@@ -311,10 +316,10 @@
         /**
          * This routine implements the unary operator lookup process. It customizes the behavior
          * of the shared lookup routine in {@link OperatorHelper}, by using an unary applicability test
-         * (see {@link UnaryOperatorHelper#isUnaryOperatorApplicable(OperatorSymbol, Type)}
+         * (see {@link UnaryOperatorHelper#isUnaryOperatorApplicable(OperatorOperatorSymbol, Type)}
          */
-        final Symbol doLookup(Type t) {
-            return doLookup(op -> isUnaryOperatorApplicable((OperatorSymbol)op, t));
+        final OperatorSymbol doLookup(Type t) {
+            return doLookup(op -> isUnaryOperatorApplicable(op, t));
         }
 
         /**
@@ -336,7 +341,7 @@
          * This method will be overridden by unary operator helpers to provide custom resolution
          * logic.
          */
-        abstract Symbol resolve(Type t);
+        abstract OperatorSymbol resolve(Type t);
     }
 
     abstract class BinaryOperatorHelper extends OperatorHelper implements BiPredicate<Type, Type> {
@@ -350,8 +355,8 @@
          * of the shared lookup routine in {@link OperatorHelper}, by using an unary applicability test
          * (see {@link BinaryOperatorHelper#isBinaryOperatorApplicable(OperatorSymbol, Type, Type)}
          */
-        final Symbol doLookup(Type t1, Type t2) {
-            return doLookup(op -> isBinaryOperatorApplicable((OperatorSymbol)op, t1, t2));
+        final OperatorSymbol doLookup(Type t1, Type t2) {
+            return doLookup(op -> isBinaryOperatorApplicable(op, t1, t2));
         }
 
         /**
@@ -375,7 +380,7 @@
          * This method will be overridden by binary operator helpers to provide custom resolution
          * logic.
          */
-        abstract Symbol resolve(Type t1, Type t2);
+        abstract OperatorSymbol resolve(Type t1, Type t2);
     }
 
     /**
@@ -393,7 +398,7 @@
         }
 
         @Override
-        public Symbol resolve(Type arg) {
+        public OperatorSymbol resolve(Type arg) {
             return doLookup(syms.objectType);
         }
     }
@@ -421,7 +426,7 @@
         }
 
         @Override
-        public Symbol resolve(Type arg) {
+        public OperatorSymbol resolve(Type arg) {
             return doLookup(unaryPromotion(arg));
         }
     }
@@ -442,7 +447,7 @@
         }
 
         @Override
-        public Symbol resolve(Type arg) {
+        public OperatorSymbol resolve(Type arg) {
             return doLookup(syms.booleanType);
         }
     }
@@ -458,7 +463,7 @@
         }
 
         @Override
-        public Symbol resolve(Type arg) {
+        public OperatorSymbol resolve(Type arg) {
             return doLookup(types.unboxedTypeOrType(arg));
         }
     }
@@ -481,7 +486,7 @@
         }
 
         @Override
-        public Symbol resolve(Type arg1, Type arg2) {
+        public OperatorSymbol resolve(Type arg1, Type arg2) {
             Type t = binaryPromotion(arg1, arg2);
             return doLookup(t, t);
         }
@@ -504,7 +509,7 @@
         }
 
         @Override
-        public Symbol resolve(Type arg1, Type arg2) {
+        public OperatorSymbol resolve(Type arg1, Type arg2) {
             return doLookup(syms.booleanType, syms.booleanType);
         }
 
@@ -527,7 +532,7 @@
         }
 
         @Override
-        public Symbol resolve(Type arg1, Type arg2) {
+        public OperatorSymbol resolve(Type arg1, Type arg2) {
             return doLookup(stringPromotion(arg1), stringPromotion(arg2));
         }
 
@@ -570,7 +575,7 @@
         }
 
         @Override
-        public Symbol resolve(Type arg1, Type arg2) {
+        public OperatorSymbol resolve(Type arg1, Type arg2) {
             return doLookup(unaryPromotion(arg1), unaryPromotion(arg2));
         }
 
@@ -613,7 +618,7 @@
         }
 
         @Override
-        public Symbol resolve(Type t1, Type t2) {
+        public OperatorSymbol resolve(Type t1, Type t2) {
             ComparisonKind kind = getKind(t1, t2);
             Type t = (kind == ComparisonKind.NUMERIC_OR_BOOLEAN) ?
                     binaryPromotion(t1, t2) :
@@ -798,12 +803,12 @@
                     .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, bool_or));
     }
 
-    Symbol lookupBinaryOp(Predicate<Symbol> applicabilityTest) {
+    OperatorSymbol lookupBinaryOp(Predicate<OperatorSymbol> applicabilityTest) {
         return binaryOperators.values().stream()
                 .flatMap(List::stream)
                 .map(helper -> helper.doLookup(applicabilityTest))
                 .distinct()
-                .filter(sym -> sym != syms.noSymbol)
+                .filter(sym -> sym != noOpSymbol)
                 .findFirst().get();
     }