Merge remote branch 'origin/master'

Conflicts:
	idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
This commit is contained in:
Andrey Breslav
2011-06-23 20:31:04 +04:00
17 changed files with 256 additions and 217 deletions
@@ -3,8 +3,6 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
@@ -16,21 +14,16 @@ import java.util.List;
* @author yole * @author yole
*/ */
public abstract class ClassBodyCodegen { public abstract class ClassBodyCodegen {
protected final BindingContext bindingContext; protected final GenerationState state;
protected final JetStandardLibrary stdlib;
protected final JetTypeMapper typeMapper;
protected final Codegens factory;
protected final JetClassOrObject myClass; protected final JetClassOrObject myClass;
protected final OwnerKind kind; protected final OwnerKind kind;
protected final ClassDescriptor descriptor; protected final ClassDescriptor descriptor;
protected final ClassVisitor v; protected final ClassVisitor v;
public ClassBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, Codegens factory) { public ClassBodyCodegen(JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, GenerationState state) {
this.bindingContext = bindingContext; this.state = state;
this.stdlib = stdlib; descriptor = state.getBindingContext().getClassDescriptor(aClass);
this.factory = factory;
this.typeMapper = new JetTypeMapper(stdlib, bindingContext);
descriptor = bindingContext.getClassDescriptor(aClass);
myClass = aClass; myClass = aClass;
this.kind = kind; this.kind = kind;
this.v = v; this.v = v;
@@ -52,8 +45,8 @@ public abstract class ClassBodyCodegen {
} }
private void generateClassBody() { private void generateClassBody() {
final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, stdlib, bindingContext, factory); final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, state);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen); final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state);
for (JetDeclaration declaration : myClass.getDeclarations()) { for (JetDeclaration declaration : myClass.getDeclarations()) {
generateDeclaration(propertyCodegen, declaration, functionCodegen); generateDeclaration(propertyCodegen, declaration, functionCodegen);
@@ -78,15 +71,15 @@ public abstract class ClassBodyCodegen {
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) { private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) {
for (JetParameter p : getPrimaryConstructorParameters()) { for (JetParameter p : getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) { if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(p); PropertyDescriptor propertyDescriptor = state.getBindingContext().getPropertyDescriptor(p);
if (propertyDescriptor != null) { if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
if (propertyDescriptor.isVar()) { if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
} }
if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && bindingContext.hasBackingField(propertyDescriptor)) { if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && state.getBindingContext().hasBackingField(propertyDescriptor)) {
v.visitField(Opcodes.ACC_PRIVATE, p.getName(), typeMapper.mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null); v.visitField(Opcodes.ACC_PRIVATE, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null);
} }
} }
} }
@@ -99,5 +92,4 @@ public abstract class ClassBodyCodegen {
} }
return Collections.emptyList(); return Collections.emptyList();
} }
} }
@@ -1,13 +1,10 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration; import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
@@ -16,14 +13,10 @@ import org.objectweb.asm.commons.InstructionAdapter;
* @author max * @author max
*/ */
public class ClassCodegen { public class ClassCodegen {
private final Project project; private final GenerationState state;
private final BindingContext bindingContext;
private final Codegens factory;
public ClassCodegen(Project project, Codegens factory, BindingContext bindingContext) { public ClassCodegen(GenerationState state) {
this.project = project; this.state = state;
this.factory = factory;
this.bindingContext = bindingContext;
} }
public void generate(JetClassOrObject aClass) { public void generate(JetClassOrObject aClass) {
@@ -44,16 +37,16 @@ public class ClassCodegen {
} }
private void generateInterface(JetClassOrObject aClass) { private void generateInterface(JetClassOrObject aClass) {
final ClassVisitor visitor = factory.forClassInterface(bindingContext.getClassDescriptor(aClass)); final ClassVisitor visitor = state.forClassInterface(state.getBindingContext().getClassDescriptor(aClass));
new InterfaceBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, visitor, factory).generate(); new InterfaceBodyCodegen(aClass, visitor, state).generate();
} }
private void generateImplementation(JetClassOrObject aClass, OwnerKind kind) { private void generateImplementation(JetClassOrObject aClass, OwnerKind kind) {
ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass); ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass);
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
? factory.forClassImplementation(descriptor) ? state.forClassImplementation(descriptor)
: factory.forClassDelegatingImplementation(descriptor); : state.forClassDelegatingImplementation(descriptor);
new ImplementationBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, kind, v, factory).generate(); new ImplementationBodyCodegen(aClass, kind, v, state).generate();
} }
@@ -2,9 +2,7 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.util.TraceClassVisitor; import org.objectweb.asm.util.TraceClassVisitor;
@@ -16,20 +14,22 @@ import java.util.*;
/** /**
* @author max * @author max
*/ */
public class Codegens { public class ClassFileFactory {
private final Project project; private final Project project;
private final boolean isText; private final boolean isText;
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>(); private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
private final Map<String, ClassVisitor> generators = new LinkedHashMap<String, ClassVisitor>(); private final Map<String, ClassVisitor> generators = new LinkedHashMap<String, ClassVisitor>();
private final Map<String, Integer> closuresCount = new HashMap<String, Integer>(); private final Map<String, Integer> closuresCount = new HashMap<String, Integer>();
private boolean isDone = false; private boolean isDone = false;
public final GenerationState state;
public Codegens(Project project, boolean text) { public ClassFileFactory(Project project, boolean text, GenerationState state) {
this.project = project; this.project = project;
isText = text; isText = text;
this.state = state;
} }
public ClassVisitor newVisitor(String filePath) { ClassVisitor newVisitor(String filePath) {
ClassVisitor visitor; ClassVisitor visitor;
if (isText) { if (isText) {
visitor = new TraceClassVisitor(new PrintWriter(new StringWriter())); visitor = new TraceClassVisitor(new PrintWriter(new StringWriter()));
@@ -42,31 +42,7 @@ public class Codegens {
return visitor; return visitor;
} }
public ClassVisitor forClassInterface(ClassDescriptor aClass) { Pair<String, ClassVisitor> forClosureIn(String baseName) {
return newVisitor(JetTypeMapper.jvmNameForInterface(aClass) + ".class");
}
public ClassCodegen forClass(BindingContext bindingContext) {
return new ClassCodegen(project, this, bindingContext);
}
public ClassVisitor forClassImplementation(ClassDescriptor aClass) {
return newVisitor(JetTypeMapper.jvmNameForImplementation(aClass) + ".class");
}
public ClassVisitor forClassDelegatingImplementation(ClassDescriptor aClass) {
return newVisitor(JetTypeMapper.jvmNameForDelegatingImplementation(aClass) + ".class");
}
public Pair<String, ClassVisitor> forClosureIn(ClassDescriptor aClass) {
return forClosureIn(JetTypeMapper.jvmNameForInterface(aClass));
}
public Pair<String, ClassVisitor> forClosureIn(JetNamespace namespace) {
return forClosureIn(NamespaceCodegen.getJVMClassName(namespace.getFQName()));
}
private Pair<String, ClassVisitor> forClosureIn(String baseName) {
Integer count = closuresCount.get(baseName); Integer count = closuresCount.get(baseName);
if (count == null) count = 0; if (count == null) count = 0;
@@ -76,12 +52,12 @@ public class Codegens {
return new Pair<String, ClassVisitor>(className, newVisitor(className + ".class")); return new Pair<String, ClassVisitor>(className, newVisitor(className + ".class"));
} }
public NamespaceCodegen forNamespace(JetNamespace namespace) { NamespaceCodegen forNamespace(JetNamespace namespace) {
assert !isDone : "Already done!"; assert !isDone : "Already done!";
String fqName = namespace.getFQName(); String fqName = namespace.getFQName();
NamespaceCodegen codegen = ns2codegen.get(fqName); NamespaceCodegen codegen = ns2codegen.get(fqName);
if (codegen == null) { if (codegen == null) {
codegen = new NamespaceCodegen(project, newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class"), fqName, this); codegen = new NamespaceCodegen(project, newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class"), fqName, state);
ns2codegen.put(fqName, codegen); ns2codegen.put(fqName, codegen);
} }
@@ -9,8 +9,6 @@ import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@@ -24,14 +22,10 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
public class ClosureCodegen { public class ClosureCodegen {
private final BindingContext bindingContext; private final GenerationState state;
private final JetTypeMapper typeMapper;
private final Codegens factory;
public ClosureCodegen(BindingContext bindingContext, JetTypeMapper typeMapper, Codegens factory) { public ClosureCodegen(GenerationState state) {
this.bindingContext = bindingContext; this.state = state;
this.typeMapper = typeMapper;
this.factory = factory;
} }
public static Method erasedInvokeSignature(FunctionDescriptor fd) { public static Method erasedInvokeSignature(FunctionDescriptor fd) {
@@ -47,7 +41,7 @@ public class ClosureCodegen {
} }
public Method invokeSignature(FunctionDescriptor fd) { public Method invokeSignature(FunctionDescriptor fd) {
return typeMapper.mapSignature("invoke", fd); return state.getTypeMapper().mapSignature("invoke", fd);
} }
public GeneratedClosureDescriptor gen(JetFunctionLiteralExpression fun) { public GeneratedClosureDescriptor gen(JetFunctionLiteralExpression fun) {
@@ -55,14 +49,14 @@ public class ClosureCodegen {
final Pair<String, ClassVisitor> nameAndVisitor; final Pair<String, ClassVisitor> nameAndVisitor;
if (container instanceof JetNamespace) { if (container instanceof JetNamespace) {
nameAndVisitor = factory.forClosureIn((JetNamespace) container); nameAndVisitor = state.forClosureIn((JetNamespace) container);
} }
else { else {
nameAndVisitor = factory.forClosureIn(bindingContext.getClassDescriptor((JetClassOrObject) container)); nameAndVisitor = state.forClosureIn(state.getBindingContext().getClassDescriptor((JetClassOrObject) container));
} }
final FunctionDescriptor funDescriptor = (FunctionDescriptor) bindingContext.getDeclarationDescriptor(fun); final FunctionDescriptor funDescriptor = (FunctionDescriptor) state.getBindingContext().getDeclarationDescriptor(fun);
final ClassVisitor cv = nameAndVisitor.getSecond(); final ClassVisitor cv = nameAndVisitor.getSecond();
final String name = nameAndVisitor.getFirst(); final String name = nameAndVisitor.getFirst();
@@ -98,7 +92,7 @@ public class ClosureCodegen {
} }
private void generateBody(String className, FunctionDescriptor funDescriptor, ClassVisitor cv, Project project, List<JetElement> body) { private void generateBody(String className, FunctionDescriptor funDescriptor, ClassVisitor cv, Project project, List<JetElement> body) {
FunctionCodegen fc = new FunctionCodegen(null, cv, JetStandardLibrary.getJetStandardLibrary(project), bindingContext, factory); FunctionCodegen fc = new FunctionCodegen(null, cv, state);
fc.generatedMethod(body, OwnerKind.IMPLEMENTATION, invokeSignature(funDescriptor), null, funDescriptor.getUnsubstitutedValueParameters(), null); fc.generatedMethod(body, OwnerKind.IMPLEMENTATION, invokeSignature(funDescriptor), null, funDescriptor.getUnsubstitutedValueParameters(), null);
} }
@@ -106,7 +100,7 @@ public class ClosureCodegen {
final Method bridge = erasedInvokeSignature(funDescriptor); final Method bridge = erasedInvokeSignature(funDescriptor);
final Method delegate = invokeSignature(funDescriptor); final Method delegate = invokeSignature(funDescriptor);
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "invoke", bridge.getDescriptor(), typeMapper.genericSignature(funDescriptor), new String[0]); final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]);
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -117,7 +111,7 @@ public class ClosureCodegen {
int count = 1; int count = 1;
for (ValueParameterDescriptor param : params) { for (ValueParameterDescriptor param : params) {
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv); StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(typeMapper.mapType(param.getOutType()), iv); StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(param.getOutType()), iv);
count++; count++;
} }
@@ -160,6 +154,7 @@ public class ClosureCodegen {
private void appendType(SignatureWriter signatureWriter, JetType type, char variance) { private void appendType(SignatureWriter signatureWriter, JetType type, char variance) {
signatureWriter.visitTypeArgument(variance); signatureWriter.visitTypeArgument(variance);
final JetTypeMapper typeMapper = state.getTypeMapper();
final Type rawRetType = typeMapper.boxType(typeMapper.mapType(type)); final Type rawRetType = typeMapper.boxType(typeMapper.mapType(type));
signatureWriter.visitClassType(rawRetType.getInternalName()); signatureWriter.visitClassType(rawRetType.getInternalName());
signatureWriter.visitEnd(); signatureWriter.visitEnd();
@@ -12,7 +12,10 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.resolve.DescriptorRenderer; import org.jetbrains.jet.resolve.DescriptorRenderer;
import org.objectweb.asm.Label; import org.objectweb.asm.Label;
@@ -61,7 +64,7 @@ public class ExpressionCodegen extends JetVisitor {
private final InstructionAdapter v; private final InstructionAdapter v;
private final FrameMap myMap; private final FrameMap myMap;
private final JetTypeMapper typeMapper; private final JetTypeMapper typeMapper;
private final Codegens factory; private final GenerationState state;
private final Type returnType; private final Type returnType;
private final DeclarationDescriptor contextType; private final DeclarationDescriptor contextType;
private final OwnerKind contextKind; private final OwnerKind contextKind;
@@ -70,22 +73,20 @@ public class ExpressionCodegen extends JetVisitor {
private final Map<ClassDescriptor, StackValue> outerThisExpressions = new HashMap<ClassDescriptor, StackValue>(); private final Map<ClassDescriptor, StackValue> outerThisExpressions = new HashMap<ClassDescriptor, StackValue>();
public ExpressionCodegen(MethodVisitor v, public ExpressionCodegen(MethodVisitor v,
BindingContext bindingContext,
FrameMap myMap, FrameMap myMap,
JetTypeMapper typeMapper,
Type returnType, Type returnType,
DeclarationDescriptor contextType, DeclarationDescriptor contextType,
OwnerKind contextKind, OwnerKind contextKind,
@Nullable StackValue thisExpression, @Nullable StackValue thisExpression,
Codegens factory) { GenerationState state) {
this.myMap = myMap; this.myMap = myMap;
this.typeMapper = typeMapper; this.typeMapper = state.getTypeMapper();
this.returnType = returnType; this.returnType = returnType;
this.contextType = contextType; this.contextType = contextType;
this.contextKind = contextKind; this.contextKind = contextKind;
this.factory = factory; this.state = state;
this.v = new InstructionAdapter(v); this.v = new InstructionAdapter(v);
this.bindingContext = bindingContext; this.bindingContext = state.getBindingContext();
this.thisExpression = thisExpression; this.thisExpression = thisExpression;
} }
@@ -481,7 +482,7 @@ public class ExpressionCodegen extends JetVisitor {
generateBlock(expression.getFunctionLiteral().getBodyExpression().getStatements()); generateBlock(expression.getFunctionLiteral().getBodyExpression().getStatements());
} }
else { else {
final GeneratedClosureDescriptor closure = new ClosureCodegen(bindingContext, typeMapper, factory).gen(expression); final GeneratedClosureDescriptor closure = new ClosureCodegen(state).gen(expression);
v.anew(Type.getObjectType(closure.getClassname())); v.anew(Type.getObjectType(closure.getClassname()));
v.dup(); v.dup();
v.invokespecial(closure.getClassname(), "<init>", closure.getConstructor().getDescriptor()); v.invokespecial(closure.getClassname(), "<init>", closure.getConstructor().getDescriptor());
@@ -4,8 +4,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@@ -23,23 +21,19 @@ import java.util.List;
public class FunctionCodegen { public class FunctionCodegen {
private final JetDeclaration owner; private final JetDeclaration owner;
private final ClassVisitor v; private final ClassVisitor v;
private final BindingContext bindingContext; private final GenerationState state;
private final JetTypeMapper typeMapper;
private final Codegens factory;
public FunctionCodegen(JetDeclaration owner, ClassVisitor v, JetStandardLibrary standardLibrary, BindingContext bindingContext, Codegens factory) { public FunctionCodegen(JetDeclaration owner, ClassVisitor v, GenerationState state) {
this.owner = owner; this.owner = owner;
this.v = v; this.v = v;
this.bindingContext = bindingContext; this.state = state;
this.factory = factory;
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
} }
public void gen(JetNamedFunction f, OwnerKind kind) { public void gen(JetNamedFunction f, OwnerKind kind) {
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef(); final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
final JetType receiverType = receiverTypeRef == null ? null : bindingContext.resolveTypeReference(receiverTypeRef); final JetType receiverType = receiverTypeRef == null ? null : state.getBindingContext().resolveTypeReference(receiverTypeRef);
Method method = typeMapper.mapSignature(f); Method method = state.getTypeMapper().mapSignature(f);
List<ValueParameterDescriptor> paramDescrs = bindingContext.getFunctionDescriptor(f).getUnsubstitutedValueParameters(); List<ValueParameterDescriptor> paramDescrs = state.getBindingContext().getFunctionDescriptor(f).getUnsubstitutedValueParameters();
generateMethod(f, kind, method, receiverType, paramDescrs); generateMethod(f, kind, method, receiverType, paramDescrs);
} }
@@ -49,8 +43,8 @@ public class FunctionCodegen {
@Nullable JetType receiverType, @Nullable JetType receiverType,
List<ValueParameterDescriptor> paramDescrs) { List<ValueParameterDescriptor> paramDescrs) {
final DeclarationDescriptor contextDesc = owner instanceof JetClassOrObject final DeclarationDescriptor contextDesc = owner instanceof JetClassOrObject
? bindingContext.getClassDescriptor((JetClassOrObject) owner) ? state.getBindingContext().getClassDescriptor((JetClassOrObject) owner)
: bindingContext.getNamespaceDescriptor((JetNamespace) owner); : state.getBindingContext().getNamespaceDescriptor((JetNamespace) owner);
final JetExpression bodyExpression = f.getBodyExpression(); final JetExpression bodyExpression = f.getBodyExpression();
final List<JetElement> bodyExpressions = bodyExpression != null ? Collections.<JetElement>singletonList(bodyExpression) : null; final List<JetElement> bodyExpressions = bodyExpression != null ? Collections.<JetElement>singletonList(bodyExpression) : null;
generatedMethod(bodyExpressions, kind, jvmSignature, receiverType, paramDescrs, contextDesc); generatedMethod(bodyExpressions, kind, jvmSignature, receiverType, paramDescrs, contextDesc);
@@ -90,9 +84,8 @@ public class FunctionCodegen {
frameMap.enter(parameter, argTypes[i].getSize()); frameMap.enter(parameter, argTypes[i].getSize());
} }
StackValue thisExpression = receiverType == null ? null : StackValue.local(0, typeMapper.mapType(receiverType)); StackValue thisExpression = receiverType == null ? null : StackValue.local(0, state.getTypeMapper().mapType(receiverType));
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), contextDesc, kind, thisExpression, state);
jvmSignature.getReturnType(), contextDesc, kind, thisExpression, factory);
if (kind instanceof OwnerKind.DelegateKind) { if (kind instanceof OwnerKind.DelegateKind) {
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind; OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -0,0 +1,97 @@
/*
* @author max
*/
package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.util.containers.Stack;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
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.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor;
public class GenerationState {
private final ClassFileFactory factory;
private final Project project;
private JetTypeMapper typeMapper;
private final Stack<BindingContext> bindingContexts;
private final JetStandardLibrary standardLibrary;
public GenerationState(Project project, boolean text) {
this.project = project;
this.bindingContexts = new Stack<BindingContext>();
this.standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
this.factory = new ClassFileFactory(project, text, this);
}
public ClassFileFactory getFactory() {
return factory;
}
public Project getProject() {
return project;
}
public JetTypeMapper getTypeMapper() {
return typeMapper;
}
public BindingContext getBindingContext() {
return bindingContexts.peek();
}
public JetStandardLibrary getStandardLibrary() {
return standardLibrary;
}
public ClassVisitor forClassInterface(ClassDescriptor aClass) {
return factory.newVisitor(JetTypeMapper.jvmNameForInterface(aClass) + ".class");
}
public ClassCodegen forClass() {
return new ClassCodegen(this);
}
public ClassVisitor forClassImplementation(ClassDescriptor aClass) {
return factory.newVisitor(JetTypeMapper.jvmNameForImplementation(aClass) + ".class");
}
public ClassVisitor forClassDelegatingImplementation(ClassDescriptor aClass) {
return factory.newVisitor(JetTypeMapper.jvmNameForDelegatingImplementation(aClass) + ".class");
}
public Pair<String, ClassVisitor> forClosureIn(ClassDescriptor aClass) {
return factory.forClosureIn(JetTypeMapper.jvmNameForInterface(aClass));
}
public Pair<String, ClassVisitor> forClosureIn(JetNamespace namespace) {
return factory.forClosureIn(NamespaceCodegen.getJVMClassName(namespace.getFQName()));
}
public NamespaceCodegen forNamespace(JetNamespace namespace) {
return factory.forNamespace(namespace);
}
public void compile(JetFile psiFile) {
final JetNamespace namespace = ((JetFile) psiFile).getRootNamespace();
NamespaceCodegen codegen = forNamespace(namespace);
final BindingContext bindingContext = AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY);
bindingContexts.push(bindingContext);
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
try {
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext);
codegen.generate(namespace);
}
finally {
bindingContexts.pop();
typeMapper = null;
}
}
}
@@ -4,8 +4,6 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@@ -21,9 +19,8 @@ import java.util.*;
* @author yole * @author yole
*/ */
public class ImplementationBodyCodegen extends ClassBodyCodegen { public class ImplementationBodyCodegen extends ClassBodyCodegen {
public ImplementationBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, public ImplementationBodyCodegen(JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, GenerationState state) {
OwnerKind kind, ClassVisitor v, Codegens factory) { super(aClass, kind, v, state);
super(bindingContext, stdlib, aClass, kind, v, factory);
} }
@Override @Override
@@ -55,9 +52,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetDelegationSpecifier first = delegationSpecifiers.get(0); JetDelegationSpecifier first = delegationSpecifiers.get(0);
if (first instanceof JetDelegatorToSuperClass || first instanceof JetDelegatorToSuperCall) { if (first instanceof JetDelegatorToSuperClass || first instanceof JetDelegatorToSuperCall) {
JetType superType = bindingContext.resolveTypeReference(first.getTypeReference()); JetType superType = state.getBindingContext().resolveTypeReference(first.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
return typeMapper.jvmName(superClassDescriptor, kind); return state.getTypeMapper().jvmName(superClassDescriptor, kind);
} }
return "java/lang/Object"; return "java/lang/Object";
@@ -86,7 +83,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
protected void generatePrimaryConstructor() { protected void generatePrimaryConstructor() {
ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor((JetElement) myClass); ConstructorDescriptor constructorDescriptor = state.getBindingContext().getConstructorDescriptor((JetElement) myClass);
if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration)) return; if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration)) return;
Method method; Method method;
@@ -94,7 +91,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
method = new Method("<init>", Type.VOID_TYPE, new Type[0]); method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
} }
else { else {
method = typeMapper.mapConstructorSignature(constructorDescriptor, kind); method = state.getTypeMapper().mapConstructorSignature(constructorDescriptor, kind);
} }
int flags = Opcodes.ACC_PUBLIC; // TODO int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null); final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
@@ -105,13 +102,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
? constructorDescriptor.getUnsubstitutedValueParameters() ? constructorDescriptor.getUnsubstitutedValueParameters()
: Collections.<ValueParameterDescriptor>emptyList(); : Collections.<ValueParameterDescriptor>emptyList();
ConstructorFrameMap frameMap = new ConstructorFrameMap(typeMapper, constructorDescriptor, kind); ConstructorFrameMap frameMap = new ConstructorFrameMap(state.getTypeMapper(), constructorDescriptor, kind);
final InstructionAdapter iv = new InstructionAdapter(mv); final InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE,
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)), factory); descriptor, kind, StackValue.local(0, state.getTypeMapper().jvmType(descriptor, kind)), state);
String classname = typeMapper.jvmName(descriptor, kind); String classname = state.getTypeMapper().jvmName(descriptor, kind);
final Type classType = Type.getType("L" + classname + ";"); final Type classType = Type.getType("L" + classname + ";");
List<JetDelegationSpecifier> specifiers = myClass.getDelegationSpecifiers(); List<JetDelegationSpecifier> specifiers = myClass.getDelegationSpecifiers();
@@ -120,7 +117,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
// TODO correct calculation of super class // TODO correct calculation of super class
String superClass = "java/lang/Object"; String superClass = "java/lang/Object";
if (!specifiers.isEmpty()) { if (!specifiers.isEmpty()) {
final JetType superType = bindingContext.resolveTypeReference(specifiers.get(0).getTypeReference()); final JetType superType = state.getBindingContext().resolveTypeReference(specifiers.get(0).getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (superClassDescriptor.hasConstructors()) { if (superClassDescriptor.hasConstructors()) {
superClass = getSuperClass(); superClass = getSuperClass();
@@ -153,8 +150,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
HashSet<FunctionDescriptor> overridden = new HashSet<FunctionDescriptor>(); HashSet<FunctionDescriptor> overridden = new HashSet<FunctionDescriptor>();
for (JetDeclaration declaration : myClass.getDeclarations()) { for (JetDeclaration declaration : myClass.getDeclarations()) {
if (declaration instanceof JetNamedFunction) { if (declaration instanceof JetFunction) {
overridden.addAll(bindingContext.getFunctionDescriptor((JetNamedFunction) declaration).getOverriddenFunctions()); overridden.addAll(state.getBindingContext().getFunctionDescriptor((JetFunction) declaration).getOverriddenFunctions());
} }
} }
@@ -168,7 +165,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
if (specifier instanceof JetDelegatorToSuperCall) { if (specifier instanceof JetDelegatorToSuperCall) {
ConstructorDescriptor constructorDescriptor1 = bindingContext.resolveSuperConstructor((JetDelegatorToSuperCall) specifier); ConstructorDescriptor constructorDescriptor1 = state.getBindingContext().resolveSuperConstructor((JetDelegatorToSuperCall) specifier);
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) specifier, constructorDescriptor1, n == 0, frameMap); generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) specifier, constructorDescriptor1, n == 0, frameMap);
} }
else if (specifier instanceof JetDelegatorByExpressionSpecifier) { else if (specifier instanceof JetDelegatorByExpressionSpecifier) {
@@ -176,7 +173,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
if (delegateOnStack) { if (delegateOnStack) {
JetType superType = bindingContext.resolveTypeReference(specifier.getTypeReference()); JetType superType = state.getBindingContext().resolveTypeReference(specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
String delegateField = "$delegate_" + n; String delegateField = "$delegate_" + n;
Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor); Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor);
@@ -184,7 +181,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
v.visitField(Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null); v.visitField(Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
iv.putfield(classname, delegateField, fieldDesc); iv.putfield(classname, delegateField, fieldDesc);
JetClass superClass = (JetClass) bindingContext.getDeclarationPsiElement(superClassDescriptor); JetClass superClass = (JetClass) state.getBindingContext().getDeclarationPsiElement(superClassDescriptor);
generateDelegates(myClass, superClass, generateDelegates(myClass, superClass,
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false), new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
JetTypeMapper.jvmNameForInterface(superClassDescriptor)), overridden); JetTypeMapper.jvmNameForInterface(superClassDescriptor)), overridden);
@@ -204,7 +201,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (JetParameter parameter : constructorParameters) { for (JetParameter parameter : constructorParameters) {
if (parameter.getValOrVarNode() != null) { if (parameter.getValOrVarNode() != null) {
VariableDescriptor descriptor = paramDescrs.get(curParam); VariableDescriptor descriptor = paramDescrs.get(curParam);
Type type = typeMapper.mapType(descriptor.getOutType()); Type type = state.getTypeMapper().mapType(descriptor.getOutType());
iv.load(0, classType); iv.load(0, classType);
iv.load(frameMap.getIndex(descriptor), type); iv.load(frameMap.getIndex(descriptor), type);
iv.putfield(classname, descriptor.getName(), type.getDescriptor()); iv.putfield(classname, descriptor.getName(), type.getDescriptor());
@@ -222,7 +219,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ConstructorFrameMap frameMap) { ConstructorFrameMap frameMap) {
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration(); ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
boolean isDelegating = kind == OwnerKind.DELEGATING_IMPLEMENTATION; boolean isDelegating = kind == OwnerKind.DELEGATING_IMPLEMENTATION;
PsiElement declaration = bindingContext.getDeclarationPsiElement(classDecl); PsiElement declaration = state.getBindingContext().getDeclarationPsiElement(classDecl);
Type type; Type type;
if (declaration instanceof PsiClass) { if (declaration instanceof PsiClass) {
type = JetTypeMapper.psiClassType((PsiClass) declaration); type = JetTypeMapper.psiClassType((PsiClass) declaration);
@@ -248,18 +245,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) { if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
iv.load(frameMap.getDelegateThisIndex(), typeMapper.jvmType(classDecl, OwnerKind.INTERFACE)); iv.load(frameMap.getDelegateThisIndex(), state.getTypeMapper().jvmType(classDecl, OwnerKind.INTERFACE));
} }
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) { if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
iv.load(frameMap.getOuterThisIndex(), typeMapper.jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION)); iv.load(frameMap.getOuterThisIndex(), state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION));
} }
Method method = typeMapper.mapConstructorSignature(constructorDescriptor, kind); Method method = state.getTypeMapper().mapConstructorSignature(constructorDescriptor, kind);
List<ValueParameterDescriptor> valueParameters = constructorDescriptor.getUnsubstitutedValueParameters(); List<ValueParameterDescriptor> valueParameters = constructorDescriptor.getUnsubstitutedValueParameters();
List<JetArgument> args = constructorCall.getValueArguments(); List<JetArgument> args = constructorCall.getValueArguments();
for (int i = 0, argsSize = args.size(); i < argsSize; i++) { for (int i = 0, argsSize = args.size(); i < argsSize; i++) {
JetArgument arg = args.get(i); JetArgument arg = args.get(i);
codegen.gen(arg.getArgumentExpression(), typeMapper.mapType(valueParameters.get(i).getOutType())); codegen.gen(arg.getArgumentExpression(), state.getTypeMapper().mapType(valueParameters.get(i).getOutType()));
} }
iv.invokespecial(type.getInternalName(), "<init>", method.getDescriptor()); iv.invokespecial(type.getInternalName(), "<init>", method.getDescriptor());
@@ -276,25 +273,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void generateSecondaryConstructor(JetConstructor constructor) { private void generateSecondaryConstructor(JetConstructor constructor) {
ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor(constructor); ConstructorDescriptor constructorDescriptor = state.getBindingContext().getConstructorDescriptor(constructor);
if (constructorDescriptor == null) { if (constructorDescriptor == null) {
throw new UnsupportedOperationException("failed to get descriptor for secondary constructor"); throw new UnsupportedOperationException("failed to get descriptor for secondary constructor");
} }
Method method = typeMapper.mapConstructorSignature(constructorDescriptor, kind); Method method = state.getTypeMapper().mapConstructorSignature(constructorDescriptor, kind);
int flags = Opcodes.ACC_PUBLIC; // TODO int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null); final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
mv.visitCode(); mv.visitCode();
ConstructorFrameMap frameMap = new ConstructorFrameMap(typeMapper, constructorDescriptor, kind); ConstructorFrameMap frameMap = new ConstructorFrameMap(state.getTypeMapper(), constructorDescriptor, kind);
final InstructionAdapter iv = new InstructionAdapter(mv); final InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE,
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)), factory); descriptor, kind, StackValue.local(0, state.getTypeMapper().jvmType(descriptor, kind)), state);
for (JetDelegationSpecifier initializer : constructor.getInitializers()) { for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
if (initializer instanceof JetDelegatorToThisCall) { if (initializer instanceof JetDelegatorToThisCall) {
JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer; JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer;
DeclarationDescriptor thisDescriptor = bindingContext.resolveReferenceExpression(thisCall.getThisReference()); DeclarationDescriptor thisDescriptor = state.getBindingContext().resolveReferenceExpression(thisCall.getThisReference());
if (!(thisDescriptor instanceof ConstructorDescriptor)) { if (!(thisDescriptor instanceof ConstructorDescriptor)) {
throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor"); throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor");
} }
@@ -320,7 +317,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.anew(JetTypeMapper.TYPE_TYPEINFO); iv.anew(JetTypeMapper.TYPE_TYPEINFO);
iv.dup(); iv.dup();
iv.aconst(typeMapper.jvmType(descriptor, OwnerKind.INTERFACE)); iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.INTERFACE));
iv.iconst(typeParamCount); iv.iconst(typeParamCount);
iv.newarray(JetTypeMapper.TYPE_TYPEINFO); iv.newarray(JetTypeMapper.TYPE_TYPEINFO);
@@ -331,14 +328,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.astore(JetTypeMapper.TYPE_OBJECT); iv.astore(JetTypeMapper.TYPE_OBJECT);
} }
iv.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V"); iv.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V");
iv.putfield(typeMapper.jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
} }
protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) { protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
for (JetDeclaration declaration : myClass.getDeclarations()) { for (JetDeclaration declaration : myClass.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration); final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().getVariableDescriptor((JetProperty) declaration);
if (bindingContext.hasBackingField(propertyDescriptor)) { if (state.getBindingContext().hasBackingField(propertyDescriptor)) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer(); final JetExpression initializer = ((JetProperty) declaration).getInitializer();
if (initializer != null) { if (initializer != null) {
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
@@ -355,23 +352,23 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
protected void generateDelegates(JetClassOrObject inClass, JetClass toClass, OwnerKind kind, Set<FunctionDescriptor> overriden) { protected void generateDelegates(JetClassOrObject inClass, JetClass toClass, OwnerKind kind, Set<FunctionDescriptor> overriden) {
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext, factory); final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, state);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen); final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state);
for (JetDeclaration declaration : toClass.getDeclarations()) { for (JetDeclaration declaration : toClass.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
propertyCodegen.gen((JetProperty) declaration, kind); propertyCodegen.gen((JetProperty) declaration, kind);
} }
else if (declaration instanceof JetNamedFunction) { else if (declaration instanceof JetFunction) {
if (!overriden.contains(bindingContext.getFunctionDescriptor((JetNamedFunction) declaration))) { if (!overriden.contains(state.getBindingContext().getFunctionDescriptor((JetFunction) declaration))) {
functionCodegen.gen((JetNamedFunction) declaration, kind); functionCodegen.gen((JetFunction) declaration, kind);
} }
} }
} }
for (JetParameter p : toClass.getPrimaryConstructorParameters()) { for (JetParameter p : toClass.getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) { if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(p); PropertyDescriptor propertyDescriptor = state.getBindingContext().getPropertyDescriptor(p);
if (propertyDescriptor != null) { if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind); propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
if (propertyDescriptor.isVar()) { if (propertyDescriptor.isVar()) {
@@ -396,7 +393,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
InstructionAdapter v = new InstructionAdapter(mv); InstructionAdapter v = new InstructionAdapter(mv);
if (needTypeInfo) { if (needTypeInfo) {
ClassCodegen.newTypeInfo(v, typeMapper.jvmType(descriptor, OwnerKind.INTERFACE)); ClassCodegen.newTypeInfo(v, state.getTypeMapper().jvmType(descriptor, OwnerKind.INTERFACE));
v.putstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); v.putstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
} }
if (needInstance) { if (needInstance) {
@@ -5,8 +5,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
@@ -19,8 +17,8 @@ import java.util.Set;
* @author yole * @author yole
*/ */
public class InterfaceBodyCodegen extends ClassBodyCodegen { public class InterfaceBodyCodegen extends ClassBodyCodegen {
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, ClassVisitor v, Codegens factory) { public InterfaceBodyCodegen(JetClassOrObject aClass, ClassVisitor v, GenerationState state) {
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v, factory); super(aClass, OwnerKind.INTERFACE, v, state);
} }
protected void generateDeclaration() { protected void generateDeclaration() {
@@ -41,9 +39,9 @@ public class InterfaceBodyCodegen extends ClassBodyCodegen {
String superClassName = null; String superClassName = null;
Set<String> superInterfaces = new LinkedHashSet<String>(); Set<String> superInterfaces = new LinkedHashSet<String>();
for (JetDelegationSpecifier specifier : delegationSpecifiers) { for (JetDelegationSpecifier specifier : delegationSpecifiers) {
JetType superType = bindingContext.resolveTypeReference(specifier.getTypeReference()); JetType superType = state.getBindingContext().resolveTypeReference(specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
PsiElement superPsi = bindingContext.getDeclarationPsiElement(superClassDescriptor); PsiElement superPsi = state.getBindingContext().getDeclarationPsiElement(superClassDescriptor);
if (superPsi instanceof PsiClass) { if (superPsi instanceof PsiClass) {
PsiClass psiClass = (PsiClass) superPsi; PsiClass psiClass = (PsiClass) superPsi;
@@ -1,12 +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.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@@ -20,12 +16,12 @@ import org.objectweb.asm.commons.InstructionAdapter;
public class NamespaceCodegen { public class NamespaceCodegen {
private final Project project; private final Project project;
private final ClassVisitor v; private final ClassVisitor v;
private final Codegens codegens; private final GenerationState state;
public NamespaceCodegen(Project project, ClassVisitor v, String fqName, Codegens codegens) { public NamespaceCodegen(Project project, ClassVisitor v, String fqName, GenerationState state) {
this.project = project; this.project = project;
this.v = v; this.v = v;
this.codegens = codegens; this.state = state;
v.visit(Opcodes.V1_6, v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC, Opcodes.ACC_PUBLIC,
@@ -34,23 +30,17 @@ public class NamespaceCodegen {
//"jet/lang/Namespace", //"jet/lang/Namespace",
"java/lang/Object", "java/lang/Object",
new String[0] new String[0]
); );
} }
public void generate(JetNamespace namespace) { public void generate(JetNamespace namespace) {
generate(namespace, AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY));
}
public void generate(JetNamespace namespace, BindingContext bindingContext) {
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext);
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project); final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, standardLibrary, bindingContext, codegens); final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, state);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen); final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state);
final ClassCodegen classCodegen = codegens.forClass(bindingContext); final ClassCodegen classCodegen = state.forClass();
if (hasNonConstantPropertyInitializers(namespace)) { if (hasNonConstantPropertyInitializers(namespace)) {
generateStaticInitializers(namespace, bindingContext); generateStaticInitializers(namespace);
} }
for (JetDeclaration declaration : namespace.getDeclarations()) { for (JetDeclaration declaration : namespace.getDeclarations()) {
@@ -69,25 +59,24 @@ public class NamespaceCodegen {
} }
else if (declaration instanceof JetNamespace) { else if (declaration instanceof JetNamespace) {
JetNamespace childNamespace = (JetNamespace) declaration; JetNamespace childNamespace = (JetNamespace) declaration;
codegens.forNamespace(childNamespace).generate(childNamespace, bindingContext); state.forNamespace(childNamespace).generate(childNamespace);
} }
} }
} }
private void generateStaticInitializers(JetNamespace namespace, BindingContext bindingContext) { private void generateStaticInitializers(JetNamespace namespace) {
MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"<clinit>", "()V", null, null); "<clinit>", "()V", null, null);
mv.visitCode(); mv.visitCode();
FrameMap frameMap = new FrameMap(); FrameMap frameMap = new FrameMap();
JetTypeMapper typeMapper = new JetTypeMapper(JetStandardLibrary.getJetStandardLibrary(namespace.getProject()), bindingContext); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, null, OwnerKind.NAMESPACE, null, state);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, null, OwnerKind.NAMESPACE, null, codegens);
for (JetDeclaration declaration : namespace.getDeclarations()) { for (JetDeclaration declaration : namespace.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer(); final JetExpression initializer = ((JetProperty) declaration).getInitializer();
if (initializer != null && !(initializer instanceof JetConstantExpression)) { if (initializer != null && !(initializer instanceof JetConstantExpression)) {
final PropertyDescriptor descriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration); final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().getVariableDescriptor((JetProperty) declaration);
codegen.genToJVMStack(initializer); codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(descriptor, false, false).store(new InstructionAdapter(mv)); codegen.intermediateValueForProperty(descriptor, false, false).store(new InstructionAdapter(mv));
} }
@@ -7,7 +7,6 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@@ -21,16 +20,18 @@ import java.util.Collections;
* @author max * @author max
*/ */
public class PropertyCodegen { public class PropertyCodegen {
private final GenerationState state;
private final BindingContext context; private final BindingContext context;
private final FunctionCodegen functionCodegen; private final FunctionCodegen functionCodegen;
private final ClassVisitor v; private final ClassVisitor v;
private final JetTypeMapper mapper; private final JetTypeMapper mapper;
public PropertyCodegen(ClassVisitor v, JetStandardLibrary standardLibrary, BindingContext context, FunctionCodegen functionCodegen) { public PropertyCodegen(ClassVisitor v, FunctionCodegen functionCodegen, GenerationState state) {
this.v = v; this.v = v;
this.context = context;
this.functionCodegen = functionCodegen; this.functionCodegen = functionCodegen;
this.mapper = new JetTypeMapper(standardLibrary, context); this.state = state;
mapper = state.getTypeMapper();
context = state.getBindingContext();
} }
public void gen(JetProperty p, OwnerKind kind) { public void gen(JetProperty p, OwnerKind kind) {
@@ -12,11 +12,10 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager; import com.intellij.psi.PsiManager;
import com.intellij.util.Chunk; import com.intellij.util.Chunk;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.Codegens; import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.NamespaceCodegen; import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.plugin.JetFileType;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -65,7 +64,7 @@ public class JetCompiler implements TranslatingCompiler {
} }
private static class ModuleCompileState { private static class ModuleCompileState {
private final Codegens codegens; private final GenerationState state;
private final CompileContext compileContext; private final CompileContext compileContext;
private final Module module; private final Module module;
private final OutputSink outputSink; private final OutputSink outputSink;
@@ -74,7 +73,7 @@ public class JetCompiler implements TranslatingCompiler {
this.compileContext = compileContext; this.compileContext = compileContext;
this.module = module; this.module = module;
this.outputSink = outputSink; this.outputSink = outputSink;
codegens = new Codegens(compileContext.getProject(), false); state = new GenerationState(compileContext.getProject(), false);
} }
public void compile(final VirtualFile virtualFile) { public void compile(final VirtualFile virtualFile) {
@@ -83,9 +82,7 @@ public class JetCompiler implements TranslatingCompiler {
public void run() { public void run() {
PsiFile psiFile = PsiManager.getInstance(module.getProject()).findFile(virtualFile); PsiFile psiFile = PsiManager.getInstance(module.getProject()).findFile(virtualFile);
if (psiFile instanceof JetFile) { if (psiFile instanceof JetFile) {
final JetNamespace namespace = ((JetFile) psiFile).getRootNamespace(); state.compile((JetFile) psiFile);
NamespaceCodegen codegen = codegens.forNamespace(namespace);
codegen.generate(namespace);
} }
} }
}); });
@@ -93,11 +90,12 @@ public class JetCompiler implements TranslatingCompiler {
public void done() { public void done() {
VirtualFile outputDir = compileContext.getModuleOutputDirectory(module); VirtualFile outputDir = compileContext.getModuleOutputDirectory(module);
List<String> files = codegens.files(); final ClassFileFactory factory = state.getFactory();
List<String> files = factory.files();
for (String file : files) { for (String file : files) {
File target = new File(outputDir.getPath(), file); File target = new File(outputDir.getPath(), file);
try { try {
FileUtil.writeToFile(target, codegens.asBytes(file)); FileUtil.writeToFile(target, factory.asBytes(file));
} catch (IOException e) { } catch (IOException e) {
compileContext.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, 0, 0); compileContext.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, 0, 0);
} }
@@ -0,0 +1,8 @@
fun box() : String {
val cl = 39
return if (sum(200, { cl }) == 2) "OK" else "FAIL"
}
fun sum(arg:Int, f : {() : Int}) : Int {
return arg + f()
}
@@ -72,7 +72,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testAbstractMethod() throws Exception { public void testAbstractMethod() throws Exception {
loadText("class Foo { abstract fun x(): String; fun y(): Int = 0 }"); loadText("class Foo { abstract fun x(): String; fun y(): Int = 0 }");
final Codegens codegens = generateClassesInFile(); final ClassFileFactory codegens = generateClassesInFile();
final Class aClass = loadClass("Foo", codegens); final Class aClass = loadClass("Foo", codegens);
assertNotNull(aClass.getMethod("x")); assertNotNull(aClass.getMethod("x"));
final Class implClass = loadClass("Foo$$Impl", codegens); final Class implClass = loadClass("Foo$$Impl", codegens);
@@ -23,4 +23,8 @@ public class ClosuresGenTest extends CodegenTestCase {
public void testExtensionClosure() throws Exception { public void testExtensionClosure() throws Exception {
blackBoxFile("classes/extensionClosure.jet"); blackBoxFile("classes/extensionClosure.jet");
} }
public void testEnclosingLocalVariable() throws Exception {
blackBoxFile("classes/enclosingLocalVariable.jet");
}
} }
@@ -6,11 +6,11 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetLightProjectDescriptor; import org.jetbrains.jet.JetLightProjectDescriptor;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.lang.psi.JetFile; 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.AnalyzingUtils;
import org.jetbrains.jet.parsing.JetParsingTest; import org.jetbrains.jet.parsing.JetParsingTest;
import org.jetbrains.jet.plugin.JetFileType;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@@ -79,7 +79,7 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
} }
protected String blackBox() throws Exception { protected String blackBox() throws Exception {
Codegens codegens = generateClassesInFile(); ClassFileFactory codegens = generateClassesInFile();
CodegensClassLoader loader = new CodegensClassLoader(codegens); CodegensClassLoader loader = new CodegensClassLoader(codegens);
JetFile jetFile = (JetFile) myFixture.getFile(); JetFile jetFile = (JetFile) myFixture.getFile();
@@ -91,30 +91,29 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
} }
protected String generateToText() { protected String generateToText() {
Codegens state = new Codegens(getProject(), true); GenerationState state = new GenerationState(getProject(), true);
JetFile jetFile = (JetFile) myFixture.getFile(); JetFile jetFile = (JetFile) myFixture.getFile();
AnalyzingUtils.checkForSyntacticErrors(jetFile); AnalyzingUtils.checkForSyntacticErrors(jetFile);
JetNamespace namespace = jetFile.getRootNamespace(); state.compile(jetFile);
NamespaceCodegen codegen = state.forNamespace(namespace);
codegen.generate(namespace);
StringBuilder answer = new StringBuilder(); StringBuilder answer = new StringBuilder();
List<String> files = state.files(); final ClassFileFactory factory = state.getFactory();
List<String> files = factory.files();
for (String file : files) { for (String file : files) {
answer.append("@").append(file).append('\n'); answer.append("@").append(file).append('\n');
answer.append(state.asText(file)); answer.append(factory.asText(file));
} }
return answer.toString(); return answer.toString();
} }
protected Class generateNamespaceClass() { protected Class generateNamespaceClass() {
Codegens state = generateClassesInFile(); ClassFileFactory state = generateClassesInFile();
return loadRootNamespaceClass(state); return loadRootNamespaceClass(state);
} }
protected Class loadRootNamespaceClass(Codegens state) { protected Class loadRootNamespaceClass(ClassFileFactory state) {
JetFile jetFile = (JetFile) myFixture.getFile(); JetFile jetFile = (JetFile) myFixture.getFile();
final JetNamespace namespace = jetFile.getRootNamespace(); final JetNamespace namespace = jetFile.getRootNamespace();
String fqName = NamespaceCodegen.getJVMClassName(namespace.getFQName()).replace("/", "."); String fqName = NamespaceCodegen.getJVMClassName(namespace.getFQName()).replace("/", ".");
@@ -122,7 +121,7 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
return classMap.get(fqName); return classMap.get(fqName);
} }
protected Class loadClass(String fqName, Codegens state) { protected Class loadClass(String fqName, ClassFileFactory state) {
List<String> files = state.files(); List<String> files = state.files();
for (String file : files) { for (String file : files) {
if (file.equals(fqName.replace('.', '/') + ".class")) { if (file.equals(fqName.replace('.', '/') + ".class")) {
@@ -135,7 +134,7 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
return null; return null;
} }
protected Map<String, Class> loadAllClasses(Codegens state) { protected Map<String, Class> loadAllClasses(ClassFileFactory state) {
Map<String, Class> result = new HashMap<String, Class>(); Map<String, Class> result = new HashMap<String, Class>();
for (String fileName : state.files()) { for (String fileName : state.files()) {
String className = StringUtil.trimEnd(fileName, ".class").replace('/', '.'); String className = StringUtil.trimEnd(fileName, ".class").replace('/', '.');
@@ -146,16 +145,14 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
return result; return result;
} }
protected Codegens generateClassesInFile() { protected ClassFileFactory generateClassesInFile() {
try { try {
Codegens state = new Codegens(getProject(), false); GenerationState state = new GenerationState(getProject(), false);
JetFile jetFile = (JetFile) myFixture.getFile(); JetFile jetFile = (JetFile) myFixture.getFile();
AnalyzingUtils.checkForSyntacticErrors(jetFile); AnalyzingUtils.checkForSyntacticErrors(jetFile);
final JetNamespace namespace = jetFile.getRootNamespace(); state.compile(jetFile);
NamespaceCodegen codegen = state.forNamespace(namespace); return state.getFactory();
codegen.generate(namespace);
return state;
} catch (RuntimeException e) { } catch (RuntimeException e) {
System.out.println(generateToText()); System.out.println(generateToText());
throw e; throw e;
@@ -196,7 +193,7 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
assertTrue(Math.abs(returnValue - currentTime) <= 1L); assertTrue(Math.abs(returnValue - currentTime) <= 1L);
} }
protected Class loadImplementationClass(Codegens codegens, final String name) { protected Class loadImplementationClass(ClassFileFactory codegens, final String name) {
loadClass(name, codegens); loadClass(name, codegens);
return loadClass(name + "$$Impl", codegens); return loadClass(name + "$$Impl", codegens);
} }
@@ -217,9 +214,9 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
} }
private static class CodegensClassLoader extends ClassLoader { private static class CodegensClassLoader extends ClassLoader {
private final Codegens state; private final ClassFileFactory state;
public CodegensClassLoader(Codegens state) { public CodegensClassLoader(ClassFileFactory state) {
super(CodegenTestCase.class.getClassLoader()); super(CodegenTestCase.class.getClassLoader());
this.state = state; this.state = state;
} }
@@ -123,7 +123,7 @@ public class PropertyGenTest extends CodegenTestCase {
public void testAbstractVal() throws Exception { public void testAbstractVal() throws Exception {
loadText("class Foo { public abstract val x: String }"); loadText("class Foo { public abstract val x: String }");
final Codegens codegens = generateClassesInFile(); final ClassFileFactory codegens = generateClassesInFile();
final Class aClass = loadClass("Foo", codegens); final Class aClass = loadClass("Foo", codegens);
assertNotNull(aClass.getMethod("getX")); assertNotNull(aClass.getMethod("getX"));
} }