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.factory = factory;
this.bindingContext = bindingContext;
}
public void generate(JetClass aClass) {
ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass);
String fqName = CodeGenUtil.getInternalInterfaceName(descriptor);
String fqName = CodeGenUtil.getInternalImplementationName(descriptor);
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
@@ -36,8 +35,6 @@ public class ClassCodegen {
String superClassFQN = CodeGenUtil.getInternalInterfaceName((ClassDescriptor) superType.getConstructor().getDeclarationDescriptor());
}
//descriptor.
ClassVisitor v = factory.forClassImplementation(descriptor);
v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC,
@@ -59,5 +56,7 @@ public class ClassCodegen {
functionCodegen.genInInterface((JetFunction) declaration);
}
}
v.visitEnd();
}
}
@@ -1,11 +1,8 @@
package org.jetbrains.jet.codegen;
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.JetFile;
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.types.ClassDescriptor;
import org.objectweb.asm.ClassVisitor;
@@ -51,10 +48,7 @@ public class Codegens {
return newVisitor(CodeGenUtil.getInternalInterfaceName(aClass));
}
public ClassCodegen forClassImplementation(JetClass aClass) {
String fqName = aClass.getName(); // TODO
final BindingContext bindingContext = AnalyzingUtils.analyzeFile((JetFile) aClass.getContainingFile(),
ErrorHandler.THROW_EXCEPTION);
public ClassCodegen forClass(BindingContext bindingContext) {
return new ClassCodegen(project, this, bindingContext);
}
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.jet.lang.types.DeclarationDescriptor;
import org.objectweb.asm.Type;
/**
* @author max
@@ -28,11 +28,11 @@ public class FunctionCodegen {
}
public void genInNamespace(JetFunction f) {
gen(f);
gen(f, OwnerKind.NAMESPACE);
}
public void genInInterface(JetFunction f) {
gen(f, OwnerKind.INTERFACE);
}
public void genInImplementation(JetFunction f) {
@@ -43,27 +43,40 @@ public class FunctionCodegen {
}
private void gen(JetFunction f) {
Method method = typeMapper.mapSignature(f);
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
method.getName(), method.getDescriptor(), null, null);
mv.visitCode();
private void gen(JetFunction f, OwnerKind kind) {
int flags = Opcodes.ACC_PUBLIC; // TODO.
boolean isStatic = kind == OwnerKind.NAMESPACE;
if (isStatic) flags |= Opcodes.ACC_STATIC;
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();
for (int i = 0; i < parameDescrs.size(); i++) {
ValueParameterDescriptor parameter = parameDescrs.get(i);
frameMap.enter(parameter, argTypes[i].getSize());
if (kind != OwnerKind.NAMESPACE) {
frameMap.enterTemp(); // 0 slot for this
}
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) {
@@ -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) {
gen(p, OwnerKind.NAMESPACE);
}
public void genInInterface(JetProperty p) {
gen(p, OwnerKind.INTERFACE);
}
public void genInImplementation(JetProperty p) {
gen(p, OwnerKind.IMPLEMENTATION);
}
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) {
DeclarationDescriptor container = descriptor.getContainingDeclaration();
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();
@@ -9,7 +9,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testPSVMClass() throws Exception {
loadFile("simpleClass.jet");
final Class aClass = generateClass();
final Method[] methods = aClass.getMethods();
final Method[] methods = aClass.getDeclaredMethods();
assertEquals(1, methods.length);
}
}
@@ -5,8 +5,10 @@ import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetLightProjectDescriptor;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetFileType;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.parsing.JetParsingTest;
import java.lang.reflect.Method;
@@ -52,6 +54,7 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
final Codegens state = new Codegens(getProject(), false);
JetFile jetFile = (JetFile) myFixture.getFile();
final Ref<Class> result = new Ref<Class>();
final ClassCodegen codegen = state.forClass(AnalyzingUtils.analyzeFile(jetFile, ErrorHandler.THROW_EXCEPTION));
jetFile.acceptChildren(new JetVisitor() {
@Override
public void visitJetElement(JetElement elem) {
@@ -60,9 +63,8 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
@Override
public void visitClass(JetClass klass) {
final ClassCodegen codegen = state.forClassImplementation(klass);
codegen.generate(klass);
result.set(getJVMClass(state, klass.getName()));
result.set(getJVMClass(state, klass.getName() + "$$Impl"));
}
});
if (result.isNull()) {