First green test for class codegen
This commit is contained in:
@@ -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()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user