Class renaming now works

This commit is contained in:
konsoletyper 2013-11-06 19:46:54 +04:00
parent 9c83d63c86
commit ee10986d05
7 changed files with 78 additions and 58 deletions

View File

@ -9,7 +9,7 @@ import org.teavm.model.MethodReference;
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public class TClassNativeGenerator implements Generator { public class ClassNativeGenerator implements Generator {
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
switch (methodRef.getClassName()) { switch (methodRef.getClassName()) {

View File

@ -11,7 +11,7 @@ import org.teavm.model.ValueType;
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public class TObjectNativeGenerator implements Generator { public class ObjectNativeGenerator implements Generator {
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
switch (methodRef.getDescriptor().getName()) { switch (methodRef.getDescriptor().getName()) {
@ -44,7 +44,8 @@ public class TObjectNativeGenerator implements Generator {
writer.append("if (cls === undefined) {").newLine().indent(); writer.append("if (cls === undefined) {").newLine().indent();
MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew", MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew",
ValueType.object(classClass))); ValueType.object(classClass)));
writer.append("cls = ").appendClass(classClass).appendMethod(createMethodRef).append("();").newLine(); writer.append("cls = ").appendClass(classClass).append('.').appendMethod(createMethodRef)
.append("();").newLine();
writer.append("cls.$data = ").append(thisArg).append(".$class;").newLine().outdent().append("}").newLine(); writer.append("cls.$data = ").append(thisArg).append(".$class;").newLine().outdent().append("}").newLine();
writer.append("return cls;").newLine(); writer.append("return cls;").newLine();
} }
@ -59,7 +60,7 @@ public class TObjectNativeGenerator implements Generator {
} }
private void generateClone(GeneratorContext context, SourceWriter writer) { private void generateClone(GeneratorContext context, SourceWriter writer) {
writer.append("var copy = new ").append(context.getParameterName(0)).append("obj.$class();").newLine(); writer.append("var copy = new ").append(context.getParameterName(0)).append(".$class();").newLine();
writer.append("for (var field in obj) {").newLine().indent(); writer.append("for (var field in obj) {").newLine().indent();
writer.append("if (!obj.hasOwnProperty(field)) {").newLine().indent(); writer.append("if (!obj.hasOwnProperty(field)) {").newLine().indent();
writer.append("continue;").newLine().outdent().append("}").newLine(); writer.append("continue;").newLine().outdent().append("}").newLine();

View File

@ -7,6 +7,10 @@ import org.teavm.javascript.ni.GeneratedBy;
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public class TClass<T> extends TObject { public class TClass<T> extends TObject {
@GeneratedBy(TClassNativeGenerator.class) static TClass<?> createNew() {
return new TClass<>();
}
@GeneratedBy(ClassNativeGenerator.class)
public native boolean isInstance(TObject obj); public native boolean isInstance(TObject obj);
} }

View File

@ -12,22 +12,22 @@ public class TObject {
init(); init();
} }
@GeneratedBy(TObjectNativeGenerator.class) @GeneratedBy(ObjectNativeGenerator.class)
private native void init(); private native void init();
@GeneratedBy(TObjectNativeGenerator.class) @GeneratedBy(ObjectNativeGenerator.class)
@Rename("getClass") @Rename("getClass")
public native final TClass<?> getClass0(); public native final TClass<?> getClass0();
@Override @Override
@GeneratedBy(TObjectNativeGenerator.class) @GeneratedBy(ObjectNativeGenerator.class)
public native int hashCode(); public native int hashCode();
@GeneratedBy(TObjectNativeGenerator.class) @GeneratedBy(ObjectNativeGenerator.class)
public native boolean equals(TObject other); public native boolean equals(TObject other);
@Override @Override
@GeneratedBy(TObjectNativeGenerator.class) @GeneratedBy(ObjectNativeGenerator.class)
protected native TObject clone(); protected native TObject clone();
@Rename("notify") @Rename("notify")

View File

@ -401,31 +401,31 @@ public class Renderer implements ExprVisitor, StatementVisitor {
visitBinary(expr, "+"); visitBinary(expr, "+");
break; break;
case ADD_LONG: case ADD_LONG:
visitBinaryFunction(expr, "Long.add"); visitBinaryFunction(expr, "Long_add");
break; break;
case SUBTRACT: case SUBTRACT:
visitBinary(expr, "-"); visitBinary(expr, "-");
break; break;
case SUBTRACT_LONG: case SUBTRACT_LONG:
visitBinaryFunction(expr, "Long.sub"); visitBinaryFunction(expr, "Long_sub");
break; break;
case MULTIPLY: case MULTIPLY:
visitBinary(expr, "*"); visitBinary(expr, "*");
break; break;
case MULTIPLY_LONG: case MULTIPLY_LONG:
visitBinaryFunction(expr, "Long.mul"); visitBinaryFunction(expr, "Long_mul");
break; break;
case DIVIDE: case DIVIDE:
visitBinary(expr, "/"); visitBinary(expr, "/");
break; break;
case DIVIDE_LONG: case DIVIDE_LONG:
visitBinaryFunction(expr, "Long.div"); visitBinaryFunction(expr, "Long_div");
break; break;
case MODULO: case MODULO:
visitBinary(expr, "%"); visitBinary(expr, "%");
break; break;
case MODULO_LONG: case MODULO_LONG:
visitBinaryFunction(expr, "Long.rem"); visitBinaryFunction(expr, "Long_rem");
break; break;
case EQUALS: case EQUALS:
visitBinary(expr, "=="); visitBinary(expr, "==");
@ -452,10 +452,10 @@ public class Renderer implements ExprVisitor, StatementVisitor {
visitBinary(expr, "!=="); visitBinary(expr, "!==");
break; break;
case COMPARE: case COMPARE:
visitBinaryFunction(expr, "$rt.compare"); visitBinaryFunction(expr, "$rt_compare");
break; break;
case COMPARE_LONG: case COMPARE_LONG:
visitBinaryFunction(expr, "Long.compare"); visitBinaryFunction(expr, "Long_compare");
break; break;
case OR: case OR:
visitBinary(expr, "||"); visitBinary(expr, "||");
@ -467,37 +467,37 @@ public class Renderer implements ExprVisitor, StatementVisitor {
visitBinary(expr, "|"); visitBinary(expr, "|");
break; break;
case BITWISE_OR_LONG: case BITWISE_OR_LONG:
visitBinaryFunction(expr, "Long.or"); visitBinaryFunction(expr, "Long_or");
break; break;
case BITWISE_AND: case BITWISE_AND:
visitBinary(expr, "&"); visitBinary(expr, "&");
break; break;
case BITWISE_AND_LONG: case BITWISE_AND_LONG:
visitBinaryFunction(expr, "Long.and"); visitBinaryFunction(expr, "Long_and");
break; break;
case BITWISE_XOR: case BITWISE_XOR:
visitBinary(expr, "^"); visitBinary(expr, "^");
break; break;
case BITWISE_XOR_LONG: case BITWISE_XOR_LONG:
visitBinaryFunction(expr, "Long.xor"); visitBinaryFunction(expr, "Long_xor");
break; break;
case LEFT_SHIFT: case LEFT_SHIFT:
visitBinary(expr, "<<"); visitBinary(expr, "<<");
break; break;
case LEFT_SHIFT_LONG: case LEFT_SHIFT_LONG:
visitBinaryFunction(expr, "Long.lsh"); visitBinaryFunction(expr, "Long_lsh");
break; break;
case RIGHT_SHIFT: case RIGHT_SHIFT:
visitBinary(expr, ">>"); visitBinary(expr, ">>");
break; break;
case RIGHT_SHIFT_LONG: case RIGHT_SHIFT_LONG:
visitBinaryFunction(expr, "Long.rsh"); visitBinaryFunction(expr, "Long_rsh");
break; break;
case UNSIGNED_RIGHT_SHIFT: case UNSIGNED_RIGHT_SHIFT:
visitBinary(expr, ">>>"); visitBinary(expr, ">>>");
break; break;
case UNSIGNED_RIGHT_SHIFT_LONG: case UNSIGNED_RIGHT_SHIFT_LONG:
visitBinaryFunction(expr, "Long.rshu"); visitBinaryFunction(expr, "Long_rshu");
break; break;
} }
} }
@ -520,27 +520,27 @@ public class Renderer implements ExprVisitor, StatementVisitor {
writer.append(".length"); writer.append(".length");
break; break;
case INT_TO_LONG: case INT_TO_LONG:
writer.append("Long.fromInt("); writer.append("Long_fromInt(");
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);
writer.append(')'); writer.append(')');
break; break;
case NUM_TO_LONG: case NUM_TO_LONG:
writer.append("Long.fromNumber("); writer.append("Long_fromNumber(");
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);
writer.append(')'); writer.append(')');
break; break;
case LONG_TO_NUM: case LONG_TO_NUM:
writer.append("Long.toNumber("); writer.append("Long_toNumber(");
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);
writer.append(')'); writer.append(')');
break; break;
case NEGATE_LONG: case NEGATE_LONG:
writer.append("Long.neg("); writer.append("Long_neg(");
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);
writer.append(')'); writer.append(')');
break; break;
case NOT_LONG: case NOT_LONG:
writer.append("Long.not("); writer.append("Long_not(");
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);
writer.append(')'); writer.append(')');
break; break;
@ -569,15 +569,15 @@ public class Renderer implements ExprVisitor, StatementVisitor {
} }
if (cst instanceof ValueType) { if (cst instanceof ValueType) {
ValueType type = (ValueType)cst; ValueType type = (ValueType)cst;
return "$rt.cls(" + typeToClsString(naming, type) + ")"; return "$rt_cls(" + typeToClsString(naming, type) + ")";
} else if (cst instanceof String) { } else if (cst instanceof String) {
return "$rt.str(\"" + escapeString((String)cst) + "\")"; return "$rt_str(\"" + escapeString((String)cst) + "\")";
} else if (cst instanceof Long) { } else if (cst instanceof Long) {
long value = (Long)cst; long value = (Long)cst;
if (value == 0) { if (value == 0) {
return "Long.ZERO"; return "Long_ZERO";
} else if ((int)value == value) { } else if ((int)value == value) {
return "Long.fromInt(" + value + ")"; return "Long_fromInt(" + value + ")";
} else { } else {
return "new Long(" + (value & 0xFFFFFFFF) + ", " + (value >>> 32) + ")"; return "new Long(" + (value & 0xFFFFFFFF) + ", " + (value >>> 32) + ")";
} }
@ -597,33 +597,33 @@ public class Renderer implements ExprVisitor, StatementVisitor {
ValueType.Object objType = (ValueType.Object)type; ValueType.Object objType = (ValueType.Object)type;
value = naming.getNameFor(objType.getClassName()); value = naming.getNameFor(objType.getClassName());
} else if (type instanceof ValueType.Void) { } else if (type instanceof ValueType.Void) {
value = "$rt.voidcls()"; value = "$rt_voidcls()";
} else if (type instanceof ValueType.Primitive) { } else if (type instanceof ValueType.Primitive) {
ValueType.Primitive primitiveType = (ValueType.Primitive)type; ValueType.Primitive primitiveType = (ValueType.Primitive)type;
switch (primitiveType.getKind()) { switch (primitiveType.getKind()) {
case BOOLEAN: case BOOLEAN:
value = "$rt.booleancls()"; value = "$rt_booleancls()";
break; break;
case CHARACTER: case CHARACTER:
value = "$rt.charcls()"; value = "$rt_charcls()";
break; break;
case BYTE: case BYTE:
value = "$rt.bytecls()"; value = "$rt_bytecls()";
break; break;
case SHORT: case SHORT:
value = "$rt.shortcls()"; value = "$rt_shortcls()";
break; break;
case INTEGER: case INTEGER:
value = "$rt.intcls()"; value = "$rt_intcls()";
break; break;
case LONG: case LONG:
value = "$rt.longcls()"; value = "$rt_longcls()";
break; break;
case FLOAT: case FLOAT:
value = "$rt.floatcls()"; value = "$rt_floatcls()";
break; break;
case DOUBLE: case DOUBLE:
value = "$rt.doublecls()"; value = "$rt_doublecls()";
break; break;
default: default:
throw new IllegalArgumentException("The type is not renderable"); throw new IllegalArgumentException("The type is not renderable");
@ -633,7 +633,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
} }
for (int i = 0; i < arrayCount; ++i) { for (int i = 0; i < arrayCount; ++i) {
value = "$rt.arraycls(" + value + ")"; value = "$rt_arraycls(" + value + ")";
} }
return value; return value;
} }
@ -755,48 +755,48 @@ public class Renderer implements ExprVisitor, StatementVisitor {
if (type instanceof ValueType.Primitive) { if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive)type).getKind()) { switch (((ValueType.Primitive)type).getKind()) {
case BOOLEAN: case BOOLEAN:
writer.append("$rt.createBooleanArray($rt.booleancls(), "); writer.append("$rt_createBooleanArray($rt_booleancls(), ");
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
break; break;
case BYTE: case BYTE:
writer.append("$rt.createNumericArray($rt.bytecls(), "); writer.append("$rt_createNumericArray($rt_bytecls(), ");
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
break; break;
case SHORT: case SHORT:
writer.append("$rt.createNumericArray($rt.shortcls(), "); writer.append("$rt_createNumericArray($rt_shortcls(), ");
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
break; break;
case INTEGER: case INTEGER:
writer.append("$rt.createNumericArray($rt.intcls(), "); writer.append("$rt_createNumericArray($rt_intcls(), ");
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
break; break;
case LONG: case LONG:
writer.append("$rt.createLongArray("); writer.append("$rt_createLongArray(");
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
break; break;
case FLOAT: case FLOAT:
writer.append("$rt.createNumericArray($rt.floatcls(), "); writer.append("$rt_createNumericArray($rt_floatcls(), ");
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
break; break;
case DOUBLE: case DOUBLE:
writer.append("$rt.createNumericArray($rt.doublecls(), "); writer.append("$rt_createNumericArray($rt_doublecls(), ");
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
break; break;
case CHARACTER: case CHARACTER:
writer.append("$rt.createNumericArray($rt.charcls(), "); writer.append("$rt_createNumericArray($rt_charcls(), ");
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
break; break;
} }
} else { } else {
writer.append("$rt.createArray(").append(typeToClsString(naming, expr.getType())).append(", "); writer.append("$rt_createArray(").append(typeToClsString(naming, expr.getType())).append(", ");
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
} }
@ -804,7 +804,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
@Override @Override
public void visit(NewMultiArrayExpr expr) { public void visit(NewMultiArrayExpr expr) {
writer.append("$rt.createMultiArray(").append(typeToClsString(naming, expr.getType())) writer.append("$rt_createMultiArray(").append(typeToClsString(naming, expr.getType()))
.append(", ["); .append(", [");
boolean first = true; boolean first = true;
for (Expr dimension : expr.getDimensions()) { for (Expr dimension : expr.getDimensions()) {
@ -829,7 +829,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
return; return;
} }
} }
writer.append("$rt.isInstance("); writer.append("$rt_isInstance(");
expr.getExpr().acceptVisitor(this); expr.getExpr().acceptVisitor(this);
writer.append(", ").append(typeToClsString(naming, expr.getType())).append(")"); writer.append(", ").append(typeToClsString(naming, expr.getType())).append(")");
} }

View File

@ -21,7 +21,7 @@ class ClassRefsRenamer implements InstructionVisitor {
ClassHolder renamedCls = new ClassHolder(classNameMapper.map(cls.getName())); ClassHolder renamedCls = new ClassHolder(classNameMapper.map(cls.getName()));
renamedCls.getModifiers().addAll(cls.getModifiers()); renamedCls.getModifiers().addAll(cls.getModifiers());
renamedCls.setLevel(cls.getLevel()); renamedCls.setLevel(cls.getLevel());
if (cls != null) { if (cls.getParent() != null) {
renamedCls.setParent(classNameMapper.map(cls.getParent())); renamedCls.setParent(classNameMapper.map(cls.getParent()));
} }
for (MethodHolder method : cls.getMethods()) { for (MethodHolder method : cls.getMethods()) {
@ -79,7 +79,7 @@ class ClassRefsRenamer implements InstructionVisitor {
private AnnotationHolder rename(AnnotationHolder annot) { private AnnotationHolder rename(AnnotationHolder annot) {
AnnotationHolder renamedAnnot = new AnnotationHolder(classNameMapper.map(annot.getType())); AnnotationHolder renamedAnnot = new AnnotationHolder(classNameMapper.map(annot.getType()));
for (Map.Entry<String, AnnotationValue> entry : renamedAnnot.getValues().entrySet()) { for (Map.Entry<String, AnnotationValue> entry : annot.getValues().entrySet()) {
renamedAnnot.getValues().put(entry.getKey(), entry.getValue()); renamedAnnot.getValues().put(entry.getKey(), entry.getValue());
} }
return renamedAnnot; return renamedAnnot;
@ -216,6 +216,11 @@ class ClassRefsRenamer implements InstructionVisitor {
@Override @Override
public void visit(InvokeInstruction insn) { public void visit(InvokeInstruction insn) {
insn.setClassName(classNameMapper.map(insn.getClassName())); insn.setClassName(classNameMapper.map(insn.getClassName()));
ValueType[] signature = insn.getMethod().getSignature();
for (int i = 0; i < signature.length; ++i) {
signature[i] = rename(signature[i]);
}
insn.setMethod(new MethodDescriptor(insn.getMethod().getName(), signature));
} }
@Override @Override

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.*; import java.util.*;
import org.teavm.codegen.ConcurrentCachedMapper;
import org.teavm.codegen.Mapper; import org.teavm.codegen.Mapper;
import org.teavm.model.ClassHolder; import org.teavm.model.ClassHolder;
@ -16,6 +17,7 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder> {
private static String CLASS_PREFIX = "classPrefix."; private static String CLASS_PREFIX = "classPrefix.";
private Mapper<String, ClassHolder> innerMapper; private Mapper<String, ClassHolder> innerMapper;
private List<Transformation> transformations = new ArrayList<>(); private List<Transformation> transformations = new ArrayList<>();
private ClassRefsRenamer renamer;
private static class Transformation { private static class Transformation {
String packageName; String packageName;
@ -41,6 +43,7 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder> {
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Error reading resources", e); throw new RuntimeException("Error reading resources", e);
} }
renamer = new ClassRefsRenamer(new ConcurrentCachedMapper<>(classNameMapper));
} }
private void loadProperties(Properties properties, Map<String, Transformation> cache) { private void loadProperties(Properties properties, Map<String, Transformation> cache) {
@ -78,24 +81,31 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder> {
String packageName = name.substring(0, index); String packageName = name.substring(0, index);
ClassHolder classHolder = innerMapper.map(transformation.packagePrefix + "." + packageName + ClassHolder classHolder = innerMapper.map(transformation.packagePrefix + "." + packageName +
"." + transformation.classPrefix + className); "." + transformation.classPrefix + className);
return classHolder; return renamer.rename(classHolder);
} }
} }
return innerMapper.map(name); return innerMapper.map(name);
} }
String renameClass(String name) { private String renameClass(String name) {
for (Transformation transformation : transformations) { for (Transformation transformation : transformations) {
if (name.startsWith(transformation.fullPrefix)) { if (name.startsWith(transformation.fullPrefix)) {
int index = name.lastIndexOf('.'); int index = name.lastIndexOf('.');
String className = name.substring(index + 1); String className = name.substring(index + 1);
String packageName = name.substring(0, index); String packageName = name.substring(0, index);
if (className.startsWith(transformation.classPrefix)) { if (className.startsWith(transformation.classPrefix)) {
return packageName.substring(transformation.fullPrefix.length()) + "." + return packageName.substring(transformation.packagePrefix.length()) + "." +
className.substring(transformation.classPrefix.length()); className.substring(transformation.classPrefix.length());
} }
} }
} }
return name; return name;
} }
private Mapper<String, String> classNameMapper = new Mapper<String, String>() {
@Override
public String map(String preimage) {
return renameClass(preimage);
}
};
} }