First green test for class codegen

This commit is contained in:
Maxim Shafirov
2011-04-18 18:24:57 +04:00
parent 9d79320b83
commit ec080358cb
9 changed files with 62 additions and 37 deletions
@@ -23,12 +23,11 @@ public class ClassCodegen {
this.project = project; this.project = project;
this.factory = factory; this.factory = factory;
this.bindingContext = bindingContext; this.bindingContext = bindingContext;
} }
public void generate(JetClass aClass) { public void generate(JetClass aClass) {
ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass); ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass);
String fqName = CodeGenUtil.getInternalInterfaceName(descriptor); String fqName = CodeGenUtil.getInternalImplementationName(descriptor);
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers(); List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
for (JetDelegationSpecifier specifier : delegationSpecifiers) { for (JetDelegationSpecifier specifier : delegationSpecifiers) {
@@ -36,8 +35,6 @@ public class ClassCodegen {
String superClassFQN = CodeGenUtil.getInternalInterfaceName((ClassDescriptor) superType.getConstructor().getDeclarationDescriptor()); String superClassFQN = CodeGenUtil.getInternalInterfaceName((ClassDescriptor) superType.getConstructor().getDeclarationDescriptor());
} }
//descriptor.
ClassVisitor v = factory.forClassImplementation(descriptor); ClassVisitor v = factory.forClassImplementation(descriptor);
v.visit(Opcodes.V1_6, v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC, Opcodes.ACC_PUBLIC,
@@ -59,5 +56,7 @@ public class ClassCodegen {
functionCodegen.genInInterface((JetFunction) declaration); functionCodegen.genInInterface((JetFunction) declaration);
} }
} }
v.visitEnd();
} }
} }
@@ -1,11 +1,8 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.ClassDescriptor; import org.jetbrains.jet.lang.types.ClassDescriptor;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
@@ -51,10 +48,7 @@ public class Codegens {
return newVisitor(CodeGenUtil.getInternalInterfaceName(aClass)); return newVisitor(CodeGenUtil.getInternalInterfaceName(aClass));
} }
public ClassCodegen forClassImplementation(JetClass aClass) { public ClassCodegen forClass(BindingContext bindingContext) {
String fqName = aClass.getName(); // TODO
final BindingContext bindingContext = AnalyzingUtils.analyzeFile((JetFile) aClass.getContainingFile(),
ErrorHandler.THROW_EXCEPTION);
return new ClassCodegen(project, this, bindingContext); return new ClassCodegen(project, this, bindingContext);
} }
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen;
import gnu.trove.TObjectIntHashMap; import gnu.trove.TObjectIntHashMap;
import org.jetbrains.jet.lang.types.DeclarationDescriptor; import org.jetbrains.jet.lang.types.DeclarationDescriptor;
import org.objectweb.asm.Type;
/** /**
* @author max * @author max
@@ -28,11 +28,11 @@ public class FunctionCodegen {
} }
public void genInNamespace(JetFunction f) { public void genInNamespace(JetFunction f) {
gen(f); gen(f, OwnerKind.NAMESPACE);
} }
public void genInInterface(JetFunction f) { public void genInInterface(JetFunction f) {
gen(f, OwnerKind.INTERFACE);
} }
public void genInImplementation(JetFunction f) { public void genInImplementation(JetFunction f) {
@@ -43,27 +43,40 @@ public class FunctionCodegen {
} }
private void gen(JetFunction f) { private void gen(JetFunction f, OwnerKind kind) {
Method method = typeMapper.mapSignature(f); int flags = Opcodes.ACC_PUBLIC; // TODO.
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
method.getName(), method.getDescriptor(), null, null); boolean isStatic = kind == OwnerKind.NAMESPACE;
mv.visitCode(); if (isStatic) flags |= Opcodes.ACC_STATIC;
final JetExpression bodyExpression = f.getBodyExpression(); final JetExpression bodyExpression = f.getBodyExpression();
FrameMap frameMap = new FrameMap(); boolean isAbstract = kind == OwnerKind.INTERFACE || bodyExpression == null;
if (isAbstract) flags |= Opcodes.ACC_ABSTRACT;
List<ValueParameterDescriptor> parameDescrs = bindingContext.getFunctionDescriptor(f).getUnsubstitutedValueParameters(); Method method = typeMapper.mapSignature(f);
final MethodVisitor mv = v.visitMethod(flags, method.getName(), method.getDescriptor(), null, null);
if (kind != OwnerKind.INTERFACE) {
mv.visitCode();
FrameMap frameMap = new FrameMap();
Type[] argTypes = method.getArgumentTypes(); if (kind != OwnerKind.NAMESPACE) {
for (int i = 0; i < parameDescrs.size(); i++) { frameMap.enterTemp(); // 0 slot for this
ValueParameterDescriptor parameter = parameDescrs.get(i); }
frameMap.enter(parameter, argTypes[i].getSize());
List<ValueParameterDescriptor> parameDescrs = bindingContext.getFunctionDescriptor(f).getUnsubstitutedValueParameters();
Type[] argTypes = method.getArgumentTypes();
for (int i = 0; i < parameDescrs.size(); i++) {
ValueParameterDescriptor parameter = parameDescrs.get(i);
frameMap.enter(parameter, argTypes[i].getSize());
}
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, method.getReturnType());
bodyExpression.accept(codegen);
generateReturn(mv, bodyExpression, codegen);
mv.visitMaxs(0, 0);
mv.visitEnd();
} }
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, method.getReturnType());
bodyExpression.accept(codegen);
generateReturn(mv, bodyExpression, codegen);
mv.visitMaxs(0, 0);
mv.visitEnd();
} }
private void generateReturn(MethodVisitor mv, JetExpression bodyExpression, ExpressionCodegen codegen) { private void generateReturn(MethodVisitor mv, JetExpression bodyExpression, ExpressionCodegen codegen) {
@@ -0,0 +1,11 @@
package org.jetbrains.jet.codegen;
/**
* @author max
*/
public enum OwnerKind {
NAMESPACE,
INTERFACE,
IMPLEMENTATION,
DELEGATING_IMPLEMENTATION
}
@@ -14,18 +14,22 @@ public class PropertyCodegen {
} }
public void genInNamespace(JetProperty p) { public void genInNamespace(JetProperty p) {
gen(p, OwnerKind.NAMESPACE);
} }
public void genInInterface(JetProperty p) { public void genInInterface(JetProperty p) {
gen(p, OwnerKind.INTERFACE);
} }
public void genInImplementation(JetProperty p) { public void genInImplementation(JetProperty p) {
gen(p, OwnerKind.IMPLEMENTATION);
} }
public void genInDelegatingImplementation(JetProperty p) { public void genInDelegatingImplementation(JetProperty p) {
gen(p, OwnerKind.DELEGATING_IMPLEMENTATION);
}
public void gen(JetProperty p, OwnerKind kind) {
} }
} }
@@ -129,7 +129,8 @@ public class DescriptorUtil {
public static String getFQName(DeclarationDescriptor descriptor) { public static String getFQName(DeclarationDescriptor descriptor) {
DeclarationDescriptor container = descriptor.getContainingDeclaration(); DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (container != null && !(container instanceof ModuleDescriptor)) { if (container != null && !(container instanceof ModuleDescriptor)) {
return getFQName(container) + "." + descriptor.getName(); String baseName = getFQName(container);
if (!baseName.isEmpty()) return baseName + "." + descriptor.getName();
} }
return descriptor.getName(); return descriptor.getName();
@@ -9,7 +9,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testPSVMClass() throws Exception { public void testPSVMClass() throws Exception {
loadFile("simpleClass.jet"); loadFile("simpleClass.jet");
final Class aClass = generateClass(); final Class aClass = generateClass();
final Method[] methods = aClass.getMethods(); final Method[] methods = aClass.getDeclaredMethods();
assertEquals(1, methods.length); assertEquals(1, methods.length);
} }
} }
@@ -5,8 +5,10 @@ import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetLightProjectDescriptor; import org.jetbrains.jet.JetLightProjectDescriptor;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetFileType; import org.jetbrains.jet.lang.JetFileType;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.parsing.JetParsingTest; import org.jetbrains.jet.parsing.JetParsingTest;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@@ -52,6 +54,7 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
final Codegens state = new Codegens(getProject(), false); final Codegens state = new Codegens(getProject(), false);
JetFile jetFile = (JetFile) myFixture.getFile(); JetFile jetFile = (JetFile) myFixture.getFile();
final Ref<Class> result = new Ref<Class>(); final Ref<Class> result = new Ref<Class>();
final ClassCodegen codegen = state.forClass(AnalyzingUtils.analyzeFile(jetFile, ErrorHandler.THROW_EXCEPTION));
jetFile.acceptChildren(new JetVisitor() { jetFile.acceptChildren(new JetVisitor() {
@Override @Override
public void visitJetElement(JetElement elem) { public void visitJetElement(JetElement elem) {
@@ -60,9 +63,8 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
@Override @Override
public void visitClass(JetClass klass) { public void visitClass(JetClass klass) {
final ClassCodegen codegen = state.forClassImplementation(klass);
codegen.generate(klass); codegen.generate(klass);
result.set(getJVMClass(state, klass.getName())); result.set(getJVMClass(state, klass.getName() + "$$Impl"));
} }
}); });
if (result.isNull()) { if (result.isNull()) {