Skip to content

Commit

Permalink
binary reverse OO with <operator>Rev method. for javac8 plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
amelentev committed Nov 16, 2014
1 parent 5e174ff commit 9a1c39a
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.sun.tools.javac.util.Name;
import javaoo.OOMethods;

import static com.sun.tools.javac.code.Kinds.ABSENT_MTH;
import static com.sun.tools.javac.code.Kinds.ERR;

public class OOResolve extends Resolve {
Expand All @@ -31,6 +32,20 @@ public static OOResolve instance(Context context) {
return new OOResolve(context);
}

final Symbol methodNotFound = new SymbolNotFoundError(ABSENT_MTH);

private Symbol findOperatorMethod(Env<AttrContext> env, Name name, List<Type> args) {
String methodName = args.tail.isEmpty() ? OOMethods.unary.get(name.toString()) : OOMethods.binary.get(name.toString());
if (methodName == null)
return methodNotFound;
Symbol res = findMethod(env, args.head, names.fromString(methodName), args.tail, null, true, false, false);
if (res.kind != Kinds.MTH) {
args = args.reverse(); // try reverse with methodRev
res = findMethod(env, args.head, names.fromString(methodName + OOMethods.revSuffix), args.tail, null, true, false, false);
}
return res;
}

@Override
Symbol findMethod(Env<AttrContext> env,
Type site,
Expand All @@ -42,22 +57,12 @@ Symbol findMethod(Env<AttrContext> env,
boolean operator) {
Symbol bestSoFar = super.findMethod(env, site, name, argtypes, typeargtypes, allowBoxing, useVarargs, operator);
if (bestSoFar.kind >= ERR && operator) { // try operator overloading
String opname = null;
List<Type> args = List.nil();
if (argtypes.size() == 2) {
opname = OOMethods.binary.get(name.toString());
args = List.of(argtypes.get(1));
} else if (argtypes.size() == 1)
opname = OOMethods.unary.get(name.toString());
if (opname != null) {
Symbol method = findMethod(env, argtypes.get(0), names.fromString(opname),
args, null, true, false, false);
if (method.kind == Kinds.MTH) {
bestSoFar = new Symbol.OperatorSymbol(method.name, method.type, ByteCodes.error+1, method);
if (OOMethods.compareTo.equals(opname)) { // change result type to boolean if </>
Type.MethodType oldmt = (Type.MethodType) method.type;
bestSoFar.type = new Type.MethodType(oldmt.argtypes, syms.booleanType, oldmt.thrown, oldmt.tsym);
}
Symbol method = findOperatorMethod(env, name, argtypes);
if (method.kind == Kinds.MTH) {
bestSoFar = new Symbol.OperatorSymbol(method.name, method.type, ByteCodes.error+1, method);
if (OOMethods.compareTo.equals(method.name.toString())) { // change result type to boolean if </>
Type.MethodType oldmt = (Type.MethodType) method.type;
bestSoFar.type = new Type.MethodType(oldmt.argtypes, syms.booleanType, oldmt.thrown, oldmt.tsym);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,14 @@ public void visitBinary(JCTree.JCBinary tree) {
Symbol.OperatorSymbol os = (Symbol.OperatorSymbol) tree.operator;
if (os.opcode == ByteCodes.error+1) { // if operator overloading?
Symbol.MethodSymbol ms = (Symbol.MethodSymbol) os.owner;
boolean isRev = ms.name.toString().endsWith(OOMethods.revSuffix); // reverse hs if methodRev
JCTree.JCExpression lhs = isRev ? tree.rhs : tree.lhs;
JCTree.JCExpression rhs = isRev ? tree.lhs : tree.rhs;
// construct method invocation ast
JCTree.JCFieldAccess meth = make.Select(tree.lhs, ms.name);
JCTree.JCFieldAccess meth = make.Select(lhs, ms.name);
meth.type = ms.type;
meth.sym = ms;
result = make.Apply(null, meth, List.of(tree.rhs))
result = make.Apply(null, meth, List.of(rhs))
.setType( ((Type.MethodType)ms.type).restype ); // tree.type may be != ms.type.restype. see below
if (ms.name.contentEquals(OOMethods.compareTo)) {
// rewrite to `left.compareTo(right) </> 0`
Expand Down
3 changes: 3 additions & 0 deletions javac8-oo-plugin/src/test/java/JCPOOTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public class JCPOOTest {
@Test public void testAbstract() throws Exception {
compile("Abstract", "../tests");
}
@Test public void testBinaryRev() throws Exception {
compile("BinaryRev", "../tests");
}
void compile(String clas) throws Exception {
compile(clas, "../examples/");
}
Expand Down
18 changes: 18 additions & 0 deletions tests/BinaryRev.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import java.math.BigInteger;

public class BinaryRev {
static class MyInt {
public int v;
public MyInt(int v) { this.v = v; }
public MyInt multiply(int a) { return new MyInt(v*a); }
public MyInt multiplyRev(int a) { return multiply(a); }
public boolean equals(Object o) {
return (o instanceof MyInt) && ((MyInt)o).v == v;
}
}

public static boolean test() {
MyInt a = new MyInt(1);
return (a*2).equals(2*a);
}
}

0 comments on commit 9a1c39a

Please sign in to comment.