public Method getSuperConstructor(int parameterCount) { return getExtending().getConstructor(parameterCount); }
@Override public String toString() { return "[new " + type.getName() + "()]"; } }
public String getSignature() { return type.getSignature(); }
private int getReturn(Type type) { if (type.isPrimitive()) { // TODO: other primitive types switch (type.getClassIdentifier().charAt(0)) { case 'I': // int case 'Z': // boolean return IRETURN; case 'J': // long return LRETURN; case 'F': // float return FRETURN; case 'D': // float return DRETURN; default: throw new RuntimeException("Unsupported " + type + " " + type.getClassIdentifier().charAt(0)); } } else { return ARETURN; } }
public TypeConversion getTypeConversion(Type from, Type to) { if (to.equals(from)) { return TypeConversion.NONE; } if (from.isPrimitive() && !to.isPrimitive()) { return new BoxingTypeConversion((PrimitiveType) from); } else if (!from.isPrimitive() && to.isPrimitive()) { return new UnboxingTypeConversion((PrimitiveType) to); } else if (!from.isPrimitive() && !to.isPrimitive()) { if (to.isAssignableFrom(from)) { return TypeConversion.NONE; } else { return new CastTypeConversion(to); } } else { // TODO: add cast in between primitives throw new UnsupportedOperationException("TODO: convert " + from + " to " + to); } }
@Override public void visit(InstantiationExpression instantiationExpression) { // new instance involves creating a new object and then calling the constructor Type type = instantiationExpression.getType(); methodByteCodeContext.incIndent("new ", type.getName(), "()"); methodByteCodeContext.addInstruction(new TypeInsnNode(NEW, type.getClassIdentifier()), "new ", type.getName(), "()"); methodByteCodeContext.dup("for constructor call"); // so that we still have a reference to the object after we call the constructor. Method constructor = type.getConstructor(instantiationExpression.getParameters().size()); if (constructor == null) { throw new RuntimeException( "can't find constructor with " + instantiationExpression.getParameters().size() + " parameters in " + type); } loadParameters("<init>", constructor, instantiationExpression.getParameters()); methodByteCodeContext.addInstruction(new MethodInsnNode(INVOKESPECIAL, type.getClassIdentifier(), "<init>", constructor.getSignature()), "new ", type.getName(), "(...)"); lastExpressionType = type; methodByteCodeContext.decIndent(); }
public void box(PrimitiveType primitiveType, Object... comment) { addInstruction( new MethodInsnNode( INVOKESTATIC, primitiveType.getBoxedType().getClassIdentifier(), "valueOf", "("+primitiveType.getSignature()+")"+primitiveType.getBoxedType().getSignature()), addComment(comment, "unboxing", primitiveType)); }
@Override public Method getMethod(String methodName, int parameterCount) { for (Method method : methods) { if (method.getName().equals(methodName) && method.getParameters().size() == parameterCount) { return method; } } if (extending != null) { return extending.getMethod(methodName, parameterCount); } return null; }
public void cast(Type type, Object... comments) { addInstruction(new TypeInsnNode(CHECKCAST, type.getClassIdentifier()), comments); }
@Override public boolean isAssignableFrom(Type type) { // System.out.println(this+".isAssignableFrom."+type); class TypeVisitorImplementation implements TypeVisitor { boolean isAssignableFrom; public void visit(ExistingType other) { isAssignableFrom = existing.isAssignableFrom(other.existing); } public void visit(FutureType futureType) { isAssignableFrom = isAssignableFrom(futureType.getExtending()); } } TypeVisitorImplementation typeVisitor = new TypeVisitorImplementation(); type.accept(typeVisitor); // System.out.println(this+".isAssignableFrom."+type+"="+typeVisitor.isAssignableFrom); return typeVisitor.isAssignableFrom; }
@Override public Field getField(String varName) { Field field = getField(getFields(), varName); if (field == null) { field = getField(getStaticFields(), varName); } if (field == null && extending != null) { field = extending.getField(varName); } return field; }
@Override public void visit(NewArrayExpression e) { methodByteCodeContext.incIndent("new ", e.getType(), "[]"); e.getSize().accept(this); methodByteCodeContext.newArray(e.getType(), "new ", e.getType(), "[]"); lastExpressionType = e.getType().nestArray(); methodByteCodeContext.decIndent(); }
private int getALoad(Type type) { if (type.isPrimitive()) { // TODO: other primitive types switch (type.getClassIdentifier().charAt(0)) { case 'I': // int case 'Z': // boolean return IALOAD; case 'J': // long return LALOAD; case 'F': // float return FALOAD; case 'D': // double return DALOAD; case 'C': // char case 'V': // void case 'B': // byte case 'S': // short default: throw new RuntimeException("Unsupported "+type); } } else { return AALOAD; } }
method = lastExpressionType.getMethod(methodName, parameterCount); if (method == null) { throw new RuntimeException("can't find method "+methodName+" with " + parameterCount + " parameters in hierarchy of "+lastExpressionType);
@Override public void visit(InstanceOfExpression instanceOfExpression) { methodByteCodeContext.incIndent("instanceOF"); instanceOfExpression.getExpression().accept(this); methodByteCodeContext.addInstruction(new TypeInsnNode(INSTANCEOF, instanceOfExpression.getType().getClassIdentifier())); lastExpressionType = BOOLEAN; methodByteCodeContext.decIndent(); }
@Override public boolean isAssignableFrom(Type type) { System.out.println(this+".isAssignableFrom."+type); class TypeVisitorImplementation implements TypeVisitor { boolean isAssignableFrom; public void visit(ExistingType other) { isAssignableFrom = false; } public void visit(FutureType futureType) { isAssignableFrom = name.equals(futureType.name) || isAssignableFrom(futureType.getExtending()); } } TypeVisitorImplementation typeVisitor = new TypeVisitorImplementation(); type.accept(typeVisitor); System.out.println(this+".isAssignableFrom."+type+"="+typeVisitor.isAssignableFrom); return typeVisitor.isAssignableFrom; }
private void incLocalVarIndex(Type type) { if (!type.isPrimitive()) { ++ currentLocalVariableByteCodeIndex; } else { switch (type.getClassIdentifier().charAt(0)) { case 'I': // int case 'Z': // boolean case 'F': // float case 'C': // char case 'V': // void case 'B': // byte case 'S': // short ++ currentLocalVariableByteCodeIndex; break; case 'J': // long case 'D': // double currentLocalVariableByteCodeIndex += 2; break; default: throw new RuntimeException("Unsupported "+type); } } }
@Override public String toString() { return "["+getClass().getSimpleName()+" "+getName()+"]"; }
public String getSignature() { StringBuilder signature = new StringBuilder("("); for (Parameter parameter : parameters) { signature.append(parameter.getType().getSignature()); } signature.append(")"); signature.append(returnType.getSignature()); return signature.toString(); }
@Override public Method getConstructor(int parameterCount) { for (Method constructor : constructors) { if (constructor.getParameters().size() == parameterCount) { return constructor; } } if (extending!=null) { return extending.getConstructor(parameterCount); } return null; }