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