Merge remote branch 'origin/master'

This commit is contained in:
Andrey Breslav
2011-05-13 15:57:01 +04:00
11 changed files with 140 additions and 20 deletions
@@ -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);
}
}
+6 -1
View File
@@ -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;