Merge remote branch 'origin/master'
This commit is contained in:
@@ -3,6 +3,7 @@ package org.jetbrains.jet.codegen;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -27,6 +28,8 @@ public class ClassCodegen {
|
||||
private final Codegens factory;
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
private static final Type TYPEINFO_TYPE = Type.getType(TypeInfo.class);
|
||||
|
||||
public ClassCodegen(Project project, Codegens factory, BindingContext bindingContext) {
|
||||
this.project = project;
|
||||
this.factory = factory;
|
||||
@@ -73,11 +76,17 @@ public class ClassCodegen {
|
||||
JetTypeMapper.jvmName(descriptor, kind),
|
||||
null,
|
||||
superClass,
|
||||
new String[] {JetTypeMapper.jvmNameForInterface(descriptor)}
|
||||
new String[] { "jet/JetObject", JetTypeMapper.jvmNameForInterface(descriptor) }
|
||||
);
|
||||
|
||||
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||
|
||||
generateStaticInitializer(descriptor, v);
|
||||
|
||||
generatePrimaryConstructor(aClass, v, kind);
|
||||
|
||||
generateGetTypeInfo(aClass, v);
|
||||
|
||||
generateClassBody(aClass, v, kind);
|
||||
|
||||
v.visitEnd();
|
||||
@@ -349,4 +358,37 @@ public class ClassCodegen {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateStaticInitializer(ClassDescriptor descriptor, ClassVisitor cv) {
|
||||
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||
"<clinit>", "()V", null, null);
|
||||
mv.visitCode();
|
||||
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
v.anew(TYPEINFO_TYPE);
|
||||
v.dup();
|
||||
v.aconst(Type.getObjectType(JetTypeMapper.jvmNameForInterface(descriptor)));
|
||||
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;)V");
|
||||
v.putstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generateGetTypeInfo(JetClass aClass, ClassVisitor cv) {
|
||||
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC,
|
||||
"getTypeInfo",
|
||||
"()Ljet/typeinfo/TypeInfo;",
|
||||
null /* TODO */,
|
||||
null);
|
||||
mv.visitCode();
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass);
|
||||
v.getstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.areturn(TYPEINFO_TYPE);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,7 @@ import org.objectweb.asm.util.TraceClassVisitor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -22,7 +19,7 @@ public class Codegens {
|
||||
private final Project project;
|
||||
private final boolean isText;
|
||||
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
|
||||
private final Map<String, ClassVisitor> generators = new HashMap<String, ClassVisitor>();
|
||||
private final Map<String, ClassVisitor> generators = new LinkedHashMap<String, ClassVisitor>();
|
||||
private boolean isDone = false;
|
||||
|
||||
public Codegens(Project project, boolean text) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import jet.IntRange;
|
||||
import jet.JetObject;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -44,6 +45,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
|
||||
private static final Type ITERATOR_TYPE = Type.getType(Iterator.class);
|
||||
private static final Type INT_RANGE_TYPE = Type.getType(IntRange.class);
|
||||
private static final Type JET_OBJECT_TYPE = Type.getType(JetObject.class);
|
||||
|
||||
private final Stack<Label> myContinueTargets = new Stack<Label>();
|
||||
private final Stack<Label> myBreakTargets = new Stack<Label>();
|
||||
@@ -1248,6 +1250,12 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeofExpression(JetTypeofExpression expression) {
|
||||
gen(expression.getBaseExpression(), JET_OBJECT_TYPE);
|
||||
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
|
||||
private static class CompilationException extends RuntimeException {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +67,7 @@ public class NamespaceCodegen {
|
||||
|
||||
private void generateStaticInitializers(JetNamespace namespace, BindingContext bindingContext) {
|
||||
MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||
"<clinit>", new Method("<clinit>", Type.VOID_TYPE, new Type[0]).getDescriptor(),
|
||||
null, null);
|
||||
"<clinit>", "()V", null, null);
|
||||
mv.visitCode();
|
||||
|
||||
FrameMap frameMap = new FrameMap();
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
class Point() {
|
||||
}
|
||||
|
||||
fun foo() = new Point()
|
||||
@@ -0,0 +1,7 @@
|
||||
class Point() {
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
val p = new Point();
|
||||
return typeof(p);
|
||||
}
|
||||
@@ -46,10 +46,7 @@ public class ClassGenTest extends CodegenTestCase {
|
||||
public void testNewInstanceExplicitConstructor() throws Exception {
|
||||
loadFile("classes/newInstanceDefaultConstructor.jet");
|
||||
System.out.println(generateToText());
|
||||
final Codegens codegens = generateClassesInFile();
|
||||
loadImplementationClass(codegens, "SimpleClass");
|
||||
Class ns = loadRootNamespaceClass(codegens);
|
||||
final Method method = findMethodByName(ns, "test");
|
||||
final Method method = generateFunction("test");
|
||||
final Integer returnValue = (Integer) method.invoke(null);
|
||||
assertEquals(610, returnValue.intValue());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -12,7 +13,10 @@ import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.channels.NonWritableChannelException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -40,6 +44,14 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
|
||||
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/" + name);
|
||||
}
|
||||
|
||||
protected void loadFile() {
|
||||
loadFile(getPrefix() + "/" + getTestName(true) + ".jet");
|
||||
}
|
||||
|
||||
protected String getPrefix() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected void blackBoxFile(String filename) throws Exception {
|
||||
loadFile(filename);
|
||||
//System.out.println(generateToText());
|
||||
@@ -86,7 +98,8 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
|
||||
JetFile jetFile = (JetFile) myFixture.getFile();
|
||||
final JetNamespace namespace = jetFile.getRootNamespace();
|
||||
String fqName = NamespaceCodegen.getJVMClassName(namespace.getFQName()).replace("/", ".");
|
||||
return loadClass(fqName, state);
|
||||
Map<String, Class> classMap = loadAllClasses(state);
|
||||
return classMap.get(fqName);
|
||||
}
|
||||
|
||||
protected Class loadClass(String fqName, Codegens state) {
|
||||
@@ -102,6 +115,17 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Map<String, Class> loadAllClasses(Codegens state) {
|
||||
Map<String, Class> result = new HashMap<String, Class>();
|
||||
for (String fileName : state.files()) {
|
||||
String className = StringUtil.trimEnd(fileName, ".class").replace('/', '.');
|
||||
byte[] data = state.asBytes(fileName);
|
||||
Class aClass = myClassLoader.doDefineClass(className, data);
|
||||
result.put(className, aClass);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Codegens generateClassesInFile() {
|
||||
Codegens state = new Codegens(getProject(), false);
|
||||
JetFile jetFile = (JetFile) myFixture.getFile();
|
||||
|
||||
@@ -8,18 +8,23 @@ import java.lang.reflect.Modifier;
|
||||
* @author yole
|
||||
*/
|
||||
public class PropertyGenTest extends CodegenTestCase {
|
||||
@Override
|
||||
protected String getPrefix() {
|
||||
return "properties";
|
||||
}
|
||||
|
||||
public void testPrivateVal() throws Exception {
|
||||
loadFile("properties/privateVal.jet");
|
||||
loadFile();
|
||||
System.out.println(generateToText());
|
||||
final Class aClass = loadImplementationClass(generateClassesInFile(), "PrivateVal");
|
||||
final Field[] fields = aClass.getDeclaredFields();
|
||||
assertEquals(1, fields.length);
|
||||
final Field field = fields[0];
|
||||
assertEquals(2, fields.length); // $typeInfo, prop
|
||||
final Field field = fields[1];
|
||||
assertEquals("prop", field.getName());
|
||||
}
|
||||
|
||||
public void testPrivateVar() throws Exception {
|
||||
loadFile("properties/privateVar.jet");
|
||||
loadFile();
|
||||
System.out.println(generateToText());
|
||||
final Class aClass = loadImplementationClass(generateClassesInFile(), "PrivateVar");
|
||||
final Object instance = aClass.newInstance();
|
||||
@@ -73,7 +78,7 @@ public class PropertyGenTest extends CodegenTestCase {
|
||||
}
|
||||
|
||||
public void testFieldSetter() throws Exception {
|
||||
loadFile("properties/fieldSetter.jet");
|
||||
loadFile();
|
||||
System.out.println(generateToText());
|
||||
final Method method = generateFunction("append");
|
||||
method.invoke(null, "IntelliJ ");
|
||||
@@ -82,7 +87,7 @@ public class PropertyGenTest extends CodegenTestCase {
|
||||
}
|
||||
|
||||
public void testFieldSetterPlusEq() throws Exception {
|
||||
loadFile("properties/fieldSetterPlusEq.jet");
|
||||
loadFile();
|
||||
System.out.println(generateToText());
|
||||
final Method method = generateFunction("append");
|
||||
method.invoke(null, "IntelliJ ");
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import jet.JetObject;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class TypeInfoTest extends CodegenTestCase {
|
||||
@Override
|
||||
protected String getPrefix() {
|
||||
return "typeInfo";
|
||||
}
|
||||
|
||||
public void testGetTypeInfo() throws Exception {
|
||||
loadFile();
|
||||
Method foo = generateFunction();
|
||||
JetObject jetObject = (JetObject) foo.invoke(null);
|
||||
TypeInfo<?> typeInfo = jetObject.getTypeInfo();
|
||||
assertNotNull(typeInfo);
|
||||
}
|
||||
|
||||
public void testTypeOfOperator() throws Exception {
|
||||
loadFile();
|
||||
Method foo = generateFunction();
|
||||
TypeInfo typeInfo = (TypeInfo) foo.invoke(null);
|
||||
assertNotNull(typeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,12 @@ import jet.JetObject;
|
||||
public class TypeInfo<T> implements JetObject {
|
||||
|
||||
private TypeInfo<?> typeInfo;
|
||||
private final TypeInfo<?> typeArgument;
|
||||
private TypeInfo<?> typeArgument;
|
||||
private Class<T> theClass;
|
||||
|
||||
public TypeInfo(Class<T> theClass) {
|
||||
this.theClass = theClass;
|
||||
}
|
||||
|
||||
private TypeInfo(TypeInfo<?> typeArgument) {
|
||||
this.typeArgument = typeArgument;
|
||||
|
||||
Reference in New Issue
Block a user