Introducing class context stack
This commit is contained in:
@@ -20,12 +20,14 @@ public abstract class ClassBodyCodegen {
|
|||||||
protected final OwnerKind kind;
|
protected final OwnerKind kind;
|
||||||
protected final ClassDescriptor descriptor;
|
protected final ClassDescriptor descriptor;
|
||||||
protected final ClassVisitor v;
|
protected final ClassVisitor v;
|
||||||
|
protected final ClassContext context;
|
||||||
|
|
||||||
public ClassBodyCodegen(JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, GenerationState state) {
|
public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
||||||
myClass = aClass;
|
myClass = aClass;
|
||||||
this.kind = kind;
|
this.context = context;
|
||||||
|
this.kind = context.getContextKind();
|
||||||
this.v = v;
|
this.v = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,8 +47,8 @@ public abstract class ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateClassBody() {
|
private void generateClassBody() {
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, state);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||||
|
|
||||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||||
generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
||||||
@@ -57,25 +59,26 @@ public abstract class ClassBodyCodegen {
|
|||||||
|
|
||||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
propertyCodegen.gen((JetProperty) declaration, kind);
|
propertyCodegen.gen((JetProperty) declaration);
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetNamedFunction) {
|
else if (declaration instanceof JetNamedFunction) {
|
||||||
try {
|
try {
|
||||||
functionCodegen.gen((JetNamedFunction) declaration, kind);
|
functionCodegen.gen((JetNamedFunction) declaration);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw new RuntimeException("Error generating method " + myClass.getName() + "." + declaration.getName() + " in " + kind, e);
|
throw new RuntimeException("Error generating method " + myClass.getName() + "." + declaration.getName() + " in " + context, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) {
|
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) {
|
||||||
|
OwnerKind kind = context.getContextKind();
|
||||||
for (JetParameter p : getPrimaryConstructorParameters()) {
|
for (JetParameter p : getPrimaryConstructorParameters()) {
|
||||||
if (p.getValOrVarNode() != null) {
|
if (p.getValOrVarNode() != null) {
|
||||||
PropertyDescriptor propertyDescriptor = state.getBindingContext().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);
|
||||||
if (propertyDescriptor.isVar()) {
|
if (propertyDescriptor.isVar()) {
|
||||||
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
|
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && state.getBindingContext().hasBackingField(propertyDescriptor)) {
|
if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && state.getBindingContext().hasBackingField(propertyDescriptor)) {
|
||||||
|
|||||||
@@ -16,36 +16,39 @@ public class ClassCodegen {
|
|||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generate(JetClassOrObject aClass) {
|
public void generate(ClassContext parentContext, JetClassOrObject aClass) {
|
||||||
state.prepareAnonymousClasses((JetElement) aClass);
|
state.prepareAnonymousClasses((JetElement) aClass);
|
||||||
|
|
||||||
if (aClass instanceof JetObjectDeclaration) {
|
if (aClass instanceof JetObjectDeclaration) {
|
||||||
generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
|
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generateInterface(aClass);
|
generateInterface(parentContext, aClass);
|
||||||
generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
|
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
||||||
generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
|
generateImplementation(parentContext, aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
||||||
|
final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
|
||||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetClass) {
|
if (declaration instanceof JetClass) {
|
||||||
generate((JetClass) declaration);
|
generate(contextForInners, (JetClass) declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateInterface(JetClassOrObject aClass) {
|
private void generateInterface(ClassContext parentContext, JetClassOrObject aClass) {
|
||||||
final ClassVisitor visitor = state.forClassInterface(state.getBindingContext().getClassDescriptor(aClass));
|
ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
||||||
new InterfaceBodyCodegen(aClass, visitor, state).generate();
|
final ClassVisitor visitor = state.forClassInterface(descriptor);
|
||||||
|
new InterfaceBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.INTERFACE), visitor, state).generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateImplementation(JetClassOrObject aClass, OwnerKind kind) {
|
private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) {
|
||||||
ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
||||||
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
|
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
|
||||||
? state.forClassImplementation(descriptor)
|
? state.forClassImplementation(descriptor)
|
||||||
: state.forClassDelegatingImplementation(descriptor);
|
: state.forClassDelegatingImplementation(descriptor);
|
||||||
new ImplementationBodyCodegen(aClass, kind, v, state).generate();
|
new ImplementationBodyCodegen(aClass, parentContext.intoClass(descriptor, kind), v, state).generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,18 +3,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
public class ClassContext {
|
public class ClassContext {
|
||||||
public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null);
|
public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null);
|
||||||
private final DeclarationDescriptor contextType;
|
private final DeclarationDescriptor contextType;
|
||||||
private final OwnerKind contextKind;
|
private final OwnerKind contextKind;
|
||||||
private final StackValue thisExpression;
|
private final ClassContext parentContext;
|
||||||
|
|
||||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression) {
|
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext) {
|
||||||
this.contextType = contextType;
|
this.contextType = contextType;
|
||||||
this.contextKind = contextKind;
|
this.contextKind = contextKind;
|
||||||
this.thisExpression = thisExpression;
|
this.parentContext = parentContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeclarationDescriptor getContextType() {
|
public DeclarationDescriptor getContextType() {
|
||||||
@@ -26,6 +31,82 @@ public class ClassContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StackValue getThisExpression() {
|
public StackValue getThisExpression() {
|
||||||
return thisExpression;
|
int thisIdx = -1;
|
||||||
|
if (getContextKind() != OwnerKind.NAMESPACE) {
|
||||||
|
thisIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasReceiver()) {
|
||||||
|
thisIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thisIdx == -1) {
|
||||||
|
throw new RuntimeException("Has no this!" + contextType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return StackValue.local(thisIdx, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassContext intoNamespace(NamespaceDescriptor descriptor) {
|
||||||
|
return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind) {
|
||||||
|
final StackValue thisValue;
|
||||||
|
if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
|
||||||
|
thisValue = StackValue.instanceField(JetTypeMapper.jetInterfaceType(descriptor),
|
||||||
|
JetTypeMapper.jetDelegatingImplementationType(descriptor).getInternalName(),
|
||||||
|
"$this");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
}
|
||||||
|
return new ClassContext(descriptor, kind, thisValue, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassContext intoFunction(FunctionDescriptor descriptor) {
|
||||||
|
return new ClassContext(descriptor, getContextKind(), StackValue.local(0, JetTypeMapper.TYPE_OBJECT), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassContext intoClosure() {
|
||||||
|
return new ClassContext(null, OwnerKind.IMPLEMENTATION, StackValue.local(0, JetTypeMapper.TYPE_OBJECT), this); // TODO!
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameMap prepareFrame() {
|
||||||
|
FrameMap frameMap = new FrameMap();
|
||||||
|
|
||||||
|
if (getContextKind() != OwnerKind.NAMESPACE) {
|
||||||
|
frameMap.enterTemp(); // 0 slot for this
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasReceiver()) {
|
||||||
|
frameMap.enterTemp(); // Next slot for fake this
|
||||||
|
}
|
||||||
|
|
||||||
|
return frameMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JetType receiverType() {
|
||||||
|
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverType() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasReceiver() {
|
||||||
|
return receiverType() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassContext getParentContext() {
|
||||||
|
return parentContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type jvmType(JetTypeMapper mapper) {
|
||||||
|
if (contextType instanceof ClassDescriptor) {
|
||||||
|
if (contextKind == OwnerKind.INTERFACE) {
|
||||||
|
System.out.println("OOps?!");
|
||||||
|
}
|
||||||
|
return mapper.jvmType((ClassDescriptor) contextType, contextKind);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return JetTypeMapper.TYPE_OBJECT; // TODO?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|||||||
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.descriptors.VariableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||||
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;
|
||||||
@@ -25,15 +26,17 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class ClosureCodegen {
|
public class ClosureCodegen {
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
private final ExpressionCodegen context;
|
private final ExpressionCodegen exprContext;
|
||||||
|
private final ClassContext context;
|
||||||
private ClassVisitor cv = null;
|
private ClassVisitor cv = null;
|
||||||
private String name = null;
|
private String name = null;
|
||||||
|
|
||||||
private Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
|
private Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
|
||||||
|
|
||||||
public ClosureCodegen(GenerationState state, ExpressionCodegen context) {
|
public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, ClassContext context) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.context = context;
|
this.exprContext = exprContext;
|
||||||
|
this.context = context.intoClosure();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
|
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
|
||||||
@@ -59,7 +62,7 @@ public class ClosureCodegen {
|
|||||||
EnclosedValueDescriptor answer = closure.get(vd);
|
EnclosedValueDescriptor answer = closure.get(vd);
|
||||||
if (answer != null) return answer.getInnerValue();
|
if (answer != null) return answer.getInnerValue();
|
||||||
|
|
||||||
final int idx = context.lookupLocal(vd);
|
final int idx = exprContext.lookupLocal(vd);
|
||||||
if (idx < 0) return null;
|
if (idx < 0) return null;
|
||||||
|
|
||||||
final Type type = state.getTypeMapper().mapType(vd.getOutType());
|
final Type type = state.getTypeMapper().mapType(vd.getOutType());
|
||||||
@@ -107,7 +110,7 @@ public class ClosureCodegen {
|
|||||||
|
|
||||||
|
|
||||||
generateBridge(name, funDescriptor, cv);
|
generateBridge(name, funDescriptor, cv);
|
||||||
generateBody(funDescriptor, cv, fun.getFunctionLiteral().getBodyExpression().getStatements());
|
generateBody(funDescriptor, cv, fun.getFunctionLiteral());
|
||||||
|
|
||||||
final Method constructor = generateConstructor(funClass);
|
final Method constructor = generateConstructor(funClass);
|
||||||
|
|
||||||
@@ -121,10 +124,9 @@ public class ClosureCodegen {
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, List<JetElement> body) {
|
private void generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, JetFunctionLiteral body) {
|
||||||
FunctionCodegen fc = new FunctionCodegen(null, cv, state);
|
FunctionCodegen fc = new FunctionCodegen(context, cv, state);
|
||||||
fc.generatedMethod(body, OwnerKind.IMPLEMENTATION, invokeSignature(funDescriptor), funDescriptor.getReceiverType(),
|
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
|
||||||
funDescriptor.getValueParameters(), funDescriptor.getTypeParameters(), null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBridge(String className, FunctionDescriptor funDescriptor, ClassVisitor cv) {
|
private void generateBridge(String className, FunctionDescriptor funDescriptor, ClassVisitor cv) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.intellij.psi.*;
|
|||||||
import com.intellij.psi.search.ProjectScope;
|
import com.intellij.psi.search.ProjectScope;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
import gnu.trove.THashSet;
|
||||||
import jet.IntRange;
|
import jet.IntRange;
|
||||||
import jet.JetObject;
|
import jet.JetObject;
|
||||||
import jet.Range;
|
import jet.Range;
|
||||||
@@ -79,7 +80,6 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
private final Type returnType;
|
private final Type returnType;
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
private final Map<ClassDescriptor, StackValue> outerThisExpressions = new HashMap<ClassDescriptor, StackValue>();
|
|
||||||
private final Map<TypeParameterDescriptor, StackValue> typeParameterExpressions = new HashMap<TypeParameterDescriptor, StackValue>();
|
private final Map<TypeParameterDescriptor, StackValue> typeParameterExpressions = new HashMap<TypeParameterDescriptor, StackValue>();
|
||||||
private final ClassContext context;
|
private final ClassContext context;
|
||||||
|
|
||||||
@@ -97,10 +97,6 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOuterThis(ClassDescriptor outer, StackValue expression) {
|
|
||||||
outerThisExpressions.put(outer, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addTypeParameter(TypeParameterDescriptor typeParameter, StackValue expression) {
|
public void addTypeParameter(TypeParameterDescriptor typeParameter, StackValue expression) {
|
||||||
typeParameterExpressions.put(typeParameter, expression);
|
typeParameterExpressions.put(typeParameter, expression);
|
||||||
}
|
}
|
||||||
@@ -315,7 +311,12 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DeclarationDescriptor contextType() {
|
private DeclarationDescriptor contextType() {
|
||||||
return context.getContextType();
|
DeclarationDescriptor descriptor = context.getContextType();
|
||||||
|
while (descriptor != null) {
|
||||||
|
if (descriptor instanceof ClassDescriptor || descriptor instanceof NamespaceDescriptor) return descriptor;
|
||||||
|
descriptor = descriptor.getContainingDeclaration();
|
||||||
|
}
|
||||||
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OwnerKind contextKind() {
|
private OwnerKind contextKind() {
|
||||||
@@ -505,7 +506,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
generateBlock(expression.getFunctionLiteral().getBodyExpression().getStatements());
|
generateBlock(expression.getFunctionLiteral().getBodyExpression().getStatements());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final GeneratedAnonymousClassDescriptor closure = state.generateClosure(expression, this);
|
final GeneratedAnonymousClassDescriptor closure = state.generateClosure(expression, this, context);
|
||||||
|
|
||||||
v.anew(Type.getObjectType(closure.getClassname()));
|
v.anew(Type.getObjectType(closure.getClassname()));
|
||||||
v.dup();
|
v.dup();
|
||||||
@@ -523,7 +524,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
|
public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) {
|
||||||
GeneratedAnonymousClassDescriptor descriptor = state.generateObjectLiteral(expression, this);
|
GeneratedAnonymousClassDescriptor descriptor = state.generateObjectLiteral(expression, this, context);
|
||||||
v.anew(Type.getObjectType(descriptor.getClassname()));
|
v.anew(Type.getObjectType(descriptor.getClassname()));
|
||||||
v.dup();
|
v.dup();
|
||||||
v.invokespecial(descriptor.getClassname(), "<init>", descriptor.getConstructor().getDescriptor());
|
v.invokespecial(descriptor.getClassname(), "<init>", descriptor.getConstructor().getDescriptor());
|
||||||
@@ -885,30 +886,69 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!(expression.getParent() instanceof JetSafeQualifiedExpression)) {
|
else if (!(expression.getParent() instanceof JetSafeQualifiedExpression)) {
|
||||||
final StackValue value = generateThisOrOuter(calleeContainingClass);
|
generateThisOrOuter(calleeContainingClass);
|
||||||
value.put(value.type, v);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
|
private static boolean isSubclass(ClassDescriptor subClass, ClassDescriptor superClass) {
|
||||||
final StackValue value = outerThisExpressions.get(calleeContainingClass);
|
Set<JetType> allSuperTypes = new THashSet<JetType>();
|
||||||
if (value != null) {
|
|
||||||
return value;
|
addSuperTypes(subClass.getDefaultType(), allSuperTypes);
|
||||||
|
|
||||||
|
final DeclarationDescriptor superOriginal = superClass.getOriginal();
|
||||||
|
|
||||||
|
for (JetType superType : allSuperTypes) {
|
||||||
|
final DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor();
|
||||||
|
if (descriptor != null && superOriginal == descriptor.getOriginal()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// TODO hope it works; really need more checks here :)
|
return false;
|
||||||
if (calleeContainingClass != null && contextType() instanceof ClassDescriptor &&
|
}
|
||||||
calleeContainingClass == contextType().getContainingDeclaration()) {
|
|
||||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
private static void addSuperTypes(JetType type, Set<JetType> set) {
|
||||||
return StackValue.field(typeMapper.jvmType(calleeContainingClass, OwnerKind.IMPLEMENTATION),
|
set.add(type);
|
||||||
typeMapper.jvmName((ClassDescriptor) contextType(), OwnerKind.IMPLEMENTATION),
|
|
||||||
"this$0",
|
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||||
false);
|
addSuperTypes(jetType, set);
|
||||||
// TODO handle more levels of class nestng
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return thisExpression() != null ? thisExpression() : StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
public void generateThisOrOuter(ClassDescriptor calleeContainingClass) {
|
||||||
|
boolean thisDone = false;
|
||||||
|
|
||||||
|
ClassContext cur = context;
|
||||||
|
while (true) {
|
||||||
|
ClassContext parentContext = cur.getParentContext();
|
||||||
|
if (parentContext == null) break;
|
||||||
|
|
||||||
|
final DeclarationDescriptor curContextType = cur.getContextType();
|
||||||
|
if (curContextType instanceof ClassDescriptor) {
|
||||||
|
if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break;
|
||||||
|
|
||||||
|
final StackValue outer;
|
||||||
|
if (!thisDone && myMap instanceof ConstructorFrameMap) {
|
||||||
|
outer = StackValue.local(((ConstructorFrameMap) myMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
thisToStack();
|
||||||
|
outer = StackValue.field(parentContext.jvmType(typeMapper),
|
||||||
|
cur.jvmType(typeMapper).getInternalName(),
|
||||||
|
"this$0",
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
thisDone = true;
|
||||||
|
outer.put(outer.type, v);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cur = parentContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thisDone) {
|
||||||
|
thisToStack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1492,7 +1532,8 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
public void visitThisExpression(JetThisExpression expression) {
|
public void visitThisExpression(JetThisExpression expression) {
|
||||||
final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression.getThisReference());
|
final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression.getThisReference());
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
myStack.push(generateThisOrOuter((ClassDescriptor) descriptor));
|
generateThisOrOuter((ClassDescriptor) descriptor);
|
||||||
|
myStack.push(StackValue.onStack(JetTypeMapper.TYPE_OBJECT));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generateThis();
|
generateThis();
|
||||||
@@ -1505,27 +1546,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateThis() {
|
private void generateThis() {
|
||||||
if (thisExpression() != null) {
|
myStack.push(thisExpression());
|
||||||
myStack.push(thisExpression());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (contextKind() != OwnerKind.NAMESPACE) {
|
|
||||||
ClassDescriptor contextClass = (ClassDescriptor) contextType();
|
|
||||||
final Type thisType = typeMapper.jvmType(contextClass, contextKind());
|
|
||||||
if (contextKind() == OwnerKind.IMPLEMENTATION) {
|
|
||||||
myStack.push(StackValue.local(0, thisType));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (contextKind() == OwnerKind.DELEGATING_IMPLEMENTATION) {
|
|
||||||
v.load(0, thisType);
|
|
||||||
myStack.push(StackValue.field(JetTypeMapper.jetInterfaceType(contextClass),
|
|
||||||
thisType.getInternalName(),
|
|
||||||
"$this",
|
|
||||||
false));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new UnsupportedOperationException("'this' expression is not defined in the context");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
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.types.JetType;
|
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -22,49 +19,40 @@ import java.util.List;
|
|||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class FunctionCodegen {
|
public class FunctionCodegen {
|
||||||
private final JetDeclaration owner;
|
private final ClassContext owner;
|
||||||
private final ClassVisitor v;
|
private final ClassVisitor v;
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
|
|
||||||
public FunctionCodegen(JetDeclaration owner, ClassVisitor v, GenerationState state) {
|
public FunctionCodegen(ClassContext owner, ClassVisitor v, GenerationState state) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.v = v;
|
this.v = v;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gen(JetNamedFunction f, OwnerKind kind) {
|
public void gen(JetNamedFunction f) {
|
||||||
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
|
|
||||||
final JetType receiverType = receiverTypeRef == null ? null : state.getBindingContext().resolveTypeReference(receiverTypeRef);
|
|
||||||
Method method = state.getTypeMapper().mapToCallableMethod(f).getSignature();
|
Method method = state.getTypeMapper().mapToCallableMethod(f).getSignature();
|
||||||
final FunctionDescriptor functionDescriptor = state.getBindingContext().getFunctionDescriptor(f);
|
final FunctionDescriptor functionDescriptor = state.getBindingContext().getFunctionDescriptor(f);
|
||||||
generateMethod(f, kind, method, receiverType, functionDescriptor.getValueParameters(),
|
generateMethod(f, method, functionDescriptor);
|
||||||
functionDescriptor.getTypeParameters());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateMethod(JetDeclarationWithBody f,
|
public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) {
|
||||||
OwnerKind kind,
|
ClassContext funContext = owner.intoFunction(functionDescriptor);
|
||||||
Method jvmSignature,
|
|
||||||
@Nullable JetType receiverType,
|
|
||||||
List<ValueParameterDescriptor> paramDescrs,
|
|
||||||
List<TypeParameterDescriptor> typeParameters) {
|
|
||||||
final DeclarationDescriptor contextDesc = owner instanceof JetClassOrObject
|
|
||||||
? state.getBindingContext().getClassDescriptor((JetClassOrObject) 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, typeParameters, contextDesc);
|
generatedMethod(bodyExpressions, jvmMethod, funContext, functionDescriptor.getValueParameters(), functionDescriptor.getTypeParameters());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generatedMethod(List<JetElement> bodyExpressions,
|
private void generatedMethod(List<JetElement> bodyExpressions,
|
||||||
OwnerKind kind,
|
Method jvmSignature,
|
||||||
Method jvmSignature,
|
ClassContext context,
|
||||||
JetType receiverType,
|
List<ValueParameterDescriptor> paramDescrs,
|
||||||
List<ValueParameterDescriptor> paramDescrs,
|
List<TypeParameterDescriptor> typeParameters)
|
||||||
List<TypeParameterDescriptor> typeParameters,
|
|
||||||
DeclarationDescriptor contextDesc)
|
|
||||||
{
|
{
|
||||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||||
|
|
||||||
|
OwnerKind kind = context.getContextKind();
|
||||||
|
|
||||||
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
||||||
if (isStatic) flags |= Opcodes.ACC_STATIC;
|
if (isStatic) flags |= Opcodes.ACC_STATIC;
|
||||||
|
|
||||||
@@ -78,34 +66,19 @@ public class FunctionCodegen {
|
|||||||
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
||||||
if (kind != OwnerKind.INTERFACE) {
|
if (kind != OwnerKind.INTERFACE) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
FrameMap frameMap = new FrameMap();
|
FrameMap frameMap = context.prepareFrame();
|
||||||
|
|
||||||
int thisIdx = -1;
|
|
||||||
if (kind != OwnerKind.NAMESPACE) {
|
|
||||||
frameMap.enterTemp(); // 0 slot for this
|
|
||||||
thisIdx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (receiverType != null) {
|
|
||||||
thisIdx++;
|
|
||||||
frameMap.enterTemp(); // Next slot for fake this
|
|
||||||
}
|
|
||||||
|
|
||||||
StackValue thisExpression = receiverType == null ? null : StackValue.local(thisIdx, state.getTypeMapper().mapType(receiverType));
|
|
||||||
ClassContext context = new ClassContext(contextDesc, kind, thisExpression);
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
|
||||||
|
|
||||||
int firstArg = thisIdx+1;
|
|
||||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
for (int i = 0; i < paramDescrs.size(); i++) {
|
||||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
||||||
frameMap.enter(parameter, argTypes[i].getSize());
|
frameMap.enter(parameter, argTypes[i].getSize());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < typeParameters.size(); i++) {
|
|
||||||
final TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
codegen.addTypeParameter(typeParameterDescriptor,
|
int slot = frameMap.enterTemp();
|
||||||
StackValue.local(firstArg + paramDescrs.size() + i, JetTypeMapper.TYPE_TYPEINFO));
|
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||||
frameMap.enterTemp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind instanceof OwnerKind.DelegateKind) {
|
if (kind instanceof OwnerKind.DelegateKind) {
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ public class GenerationState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneratedAnonymousClassDescriptor generateClosure(JetFunctionLiteralExpression literal, ExpressionCodegen context) {
|
public GeneratedAnonymousClassDescriptor generateClosure(JetFunctionLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) {
|
||||||
final ClosureCodegen codegen = new ClosureCodegen(this, context);
|
final ClosureCodegen codegen = new ClosureCodegen(this, context, classContext);
|
||||||
closureContexts.push(codegen);
|
closureContexts.push(codegen);
|
||||||
try {
|
try {
|
||||||
return codegen.gen(literal);
|
return codegen.gen(literal);
|
||||||
@@ -106,9 +106,12 @@ public class GenerationState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen context) {
|
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) {
|
||||||
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(literal.getObjectDeclaration());
|
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(literal.getObjectDeclaration());
|
||||||
new ImplementationBodyCodegen(literal.getObjectDeclaration(), OwnerKind.IMPLEMENTATION, nameAndVisitor.getSecond(), this).generate();
|
|
||||||
|
final ClassContext objectContext = classContext.intoClass(getBindingContext().getClassDescriptor(literal.getObjectDeclaration()), OwnerKind.IMPLEMENTATION);
|
||||||
|
|
||||||
|
new ImplementationBodyCodegen(literal.getObjectDeclaration(), objectContext, nameAndVisitor.getSecond(), this).generate();
|
||||||
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("<init>", "()V"));
|
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("<init>", "()V"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import java.util.*;
|
|||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||||
public ImplementationBodyCodegen(JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, GenerationState state) {
|
public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
||||||
super(aClass, kind, v, state);
|
super(aClass, context, v, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -112,7 +112,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, kind);
|
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, kind);
|
||||||
|
|
||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ClassContext context = new ClassContext(descriptor, kind, StackValue.local(0, state.getTypeMapper().jvmType(descriptor, kind)));
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||||
|
|
||||||
String classname = state.getTypeMapper().jvmName(descriptor, kind);
|
String classname = state.getTypeMapper().jvmName(descriptor, kind);
|
||||||
@@ -138,7 +137,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if (outerDescriptor instanceof ClassDescriptor) {
|
if (outerDescriptor instanceof ClassDescriptor) {
|
||||||
final ClassDescriptor outerClassDescriptor = (ClassDescriptor) outerDescriptor;
|
final ClassDescriptor outerClassDescriptor = (ClassDescriptor) outerDescriptor;
|
||||||
final Type type = JetTypeMapper.jetImplementationType(outerClassDescriptor);
|
final Type type = JetTypeMapper.jetImplementationType(outerClassDescriptor);
|
||||||
codegen.addOuterThis(outerClassDescriptor, StackValue.local(frameMap.getOuterThisIndex(), type));
|
|
||||||
String interfaceDesc = type.getDescriptor();
|
String interfaceDesc = type.getDescriptor();
|
||||||
final String fieldName = "this$0";
|
final String fieldName = "this$0";
|
||||||
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
|
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
|
||||||
@@ -189,9 +187,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
iv.putfield(classname, delegateField, fieldDesc);
|
iv.putfield(classname, delegateField, fieldDesc);
|
||||||
|
|
||||||
JetClass superClass = (JetClass) state.getBindingContext().getDeclarationPsiElement(superClassDescriptor);
|
JetClass superClass = (JetClass) state.getBindingContext().getDeclarationPsiElement(superClassDescriptor);
|
||||||
generateDelegates(myClass, superClass,
|
final ClassContext delegateContext = context.intoClass(superClassDescriptor,
|
||||||
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)));
|
||||||
|
generateDelegates(superClass, delegateContext, overridden);
|
||||||
}
|
}
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
@@ -291,7 +290,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, kind);
|
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, kind);
|
||||||
|
|
||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ClassContext context = new ClassContext(descriptor, kind, StackValue.local(0, state.getTypeMapper().jvmType(descriptor, kind)));
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||||
|
|
||||||
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
|
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
|
||||||
@@ -358,17 +356,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateDelegates(JetClassOrObject inClass, JetClass toClass, OwnerKind kind, Set<FunctionDescriptor> overriden) {
|
protected void generateDelegates(JetClass toClass, ClassContext delegateContext, Set<FunctionDescriptor> overriden) {
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, state);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state);
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, 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);
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetFunction) {
|
else if (declaration instanceof JetFunction) {
|
||||||
if (!overriden.contains(state.getBindingContext().getFunctionDescriptor((JetNamedFunction) declaration))) {
|
if (!overriden.contains(state.getBindingContext().getFunctionDescriptor((JetNamedFunction) declaration))) {
|
||||||
functionCodegen.gen((JetNamedFunction) declaration, kind);
|
functionCodegen.gen((JetNamedFunction) declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -377,9 +375,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if (p.getValOrVarNode() != null) {
|
if (p.getValOrVarNode() != null) {
|
||||||
PropertyDescriptor propertyDescriptor = state.getBindingContext().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);
|
||||||
if (propertyDescriptor.isVar()) {
|
if (propertyDescriptor.isVar()) {
|
||||||
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
|
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ import java.util.Set;
|
|||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
||||||
public InterfaceBodyCodegen(JetClassOrObject aClass, ClassVisitor v, GenerationState state) {
|
public InterfaceBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
||||||
super(aClass, OwnerKind.INTERFACE, v, state);
|
super(aClass, context, v, state);
|
||||||
|
assert context.getContextKind() == OwnerKind.INTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateDeclaration() {
|
protected void generateDeclaration() {
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ public class NamespaceCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generate(JetNamespace namespace) {
|
public void generate(JetNamespace namespace) {
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, state);
|
final ClassContext context = ClassContext.STATIC.intoNamespace(state.getBindingContext().getNamespaceDescriptor(namespace));
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state);
|
|
||||||
|
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
||||||
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||||
final ClassCodegen classCodegen = state.forClass();
|
final ClassCodegen classCodegen = state.forClass();
|
||||||
|
|
||||||
state.prepareAnonymousClasses(namespace);
|
state.prepareAnonymousClasses(namespace);
|
||||||
@@ -45,17 +47,17 @@ public class NamespaceCodegen {
|
|||||||
|
|
||||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
propertyCodegen.gen((JetProperty) declaration, OwnerKind.NAMESPACE);
|
propertyCodegen.gen((JetProperty) declaration);
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetNamedFunction) {
|
else if (declaration instanceof JetNamedFunction) {
|
||||||
try {
|
try {
|
||||||
functionCodegen.gen((JetNamedFunction) declaration, OwnerKind.NAMESPACE);
|
functionCodegen.gen((JetNamedFunction) declaration);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Failed to generate function " + declaration.getName(), e);
|
throw new RuntimeException("Failed to generate function " + declaration.getName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetClassOrObject) {
|
else if (declaration instanceof JetClassOrObject) {
|
||||||
classCodegen.generate((JetClassOrObject) declaration);
|
classCodegen.generate(context, (JetClassOrObject) declaration);
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetNamespace) {
|
else if (declaration instanceof JetNamespace) {
|
||||||
JetNamespace childNamespace = (JetNamespace) declaration;
|
JetNamespace childNamespace = (JetNamespace) declaration;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
|
||||||
|
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.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;
|
||||||
@@ -11,36 +12,32 @@ import org.objectweb.asm.Opcodes;
|
|||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
*/
|
*/
|
||||||
public class PropertyCodegen {
|
public class PropertyCodegen {
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
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 OwnerKind kind;
|
||||||
|
|
||||||
public PropertyCodegen(ClassVisitor v, FunctionCodegen functionCodegen, GenerationState state) {
|
public PropertyCodegen(ClassContext context, ClassVisitor v, FunctionCodegen functionCodegen, GenerationState state) {
|
||||||
this.v = v;
|
this.v = v;
|
||||||
this.functionCodegen = functionCodegen;
|
this.functionCodegen = functionCodegen;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
mapper = state.getTypeMapper();
|
this.kind = context.getContextKind();
|
||||||
context = state.getBindingContext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gen(JetProperty p, OwnerKind kind) {
|
public void gen(JetProperty p) {
|
||||||
final VariableDescriptor descriptor = context.getVariableDescriptor(p);
|
final VariableDescriptor descriptor = state.getBindingContext().getVariableDescriptor(p);
|
||||||
if (!(descriptor instanceof PropertyDescriptor)) {
|
if (!(descriptor instanceof PropertyDescriptor)) {
|
||||||
throw new UnsupportedOperationException("expect a property to have a property descriptor");
|
throw new UnsupportedOperationException("expect a property to have a property descriptor");
|
||||||
}
|
}
|
||||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
|
if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
|
||||||
generateBackingField(p, kind, propertyDescriptor);
|
generateBackingField(p, propertyDescriptor);
|
||||||
generateGetter(p, kind, propertyDescriptor);
|
generateGetter(p, propertyDescriptor);
|
||||||
generateSetter(p, kind, propertyDescriptor);
|
generateSetter(p, propertyDescriptor);
|
||||||
}
|
}
|
||||||
else if (kind == OwnerKind.INTERFACE) {
|
else if (kind == OwnerKind.INTERFACE) {
|
||||||
final JetPropertyAccessor getter = p.getGetter();
|
final JetPropertyAccessor getter = p.getGetter();
|
||||||
@@ -48,7 +45,7 @@ public class PropertyCodegen {
|
|||||||
(getter == null && isExternallyAccessible(p)))) {
|
(getter == null && isExternallyAccessible(p)))) {
|
||||||
v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
|
v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
|
||||||
getterName(p.getName()),
|
getterName(p.getName()),
|
||||||
mapper.mapGetterSignature(propertyDescriptor).getDescriptor(),
|
state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor(),
|
||||||
null, null);
|
null, null);
|
||||||
}
|
}
|
||||||
final JetPropertyAccessor setter = p.getSetter();
|
final JetPropertyAccessor setter = p.getSetter();
|
||||||
@@ -56,20 +53,20 @@ public class PropertyCodegen {
|
|||||||
(setter == null && isExternallyAccessible(p) && p.isVar()))) {
|
(setter == null && isExternallyAccessible(p) && p.isVar()))) {
|
||||||
v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
|
v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
|
||||||
setterName(p.getName()),
|
setterName(p.getName()),
|
||||||
mapper.mapSetterSignature(propertyDescriptor).getDescriptor(),
|
state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor(),
|
||||||
null, null);
|
null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (kind instanceof OwnerKind.DelegateKind) {
|
else if (kind instanceof OwnerKind.DelegateKind) {
|
||||||
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
|
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||||
if (propertyDescriptor.isVar()) {
|
if (propertyDescriptor.isVar()) {
|
||||||
generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
|
generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBackingField(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) {
|
private void generateBackingField(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||||
if (context.hasBackingField(propertyDescriptor)) {
|
if (state.getBindingContext().hasBackingField(propertyDescriptor)) {
|
||||||
Object value = null;
|
Object value = null;
|
||||||
final JetExpression initializer = p.getInitializer();
|
final JetExpression initializer = p.getInitializer();
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
@@ -85,25 +82,22 @@ public class PropertyCodegen {
|
|||||||
else {
|
else {
|
||||||
modifiers = Opcodes.ACC_PRIVATE;
|
modifiers = Opcodes.ACC_PRIVATE;
|
||||||
}
|
}
|
||||||
v.visitField(modifiers, p.getName(), mapper.mapType(propertyDescriptor.getOutType()).getDescriptor(), null, value);
|
v.visitField(modifiers, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateGetter(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) {
|
private void generateGetter(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||||
final JetPropertyAccessor getter = p.getGetter();
|
final JetPropertyAccessor getter = p.getGetter();
|
||||||
if (getter != null) {
|
if (getter != null) {
|
||||||
if (getter.getBodyExpression() != null) {
|
if (getter.getBodyExpression() != null) {
|
||||||
functionCodegen.generateMethod(getter, kind, mapper.mapGetterSignature(propertyDescriptor),
|
functionCodegen.generateMethod(getter, state.getTypeMapper().mapGetterSignature(propertyDescriptor), propertyDescriptor.getGetter());
|
||||||
null,
|
|
||||||
Collections.<ValueParameterDescriptor>emptyList(),
|
|
||||||
Collections.<TypeParameterDescriptor>emptyList());
|
|
||||||
}
|
}
|
||||||
else if (!getter.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
else if (!getter.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
||||||
generateDefaultGetter(p, getter, kind);
|
generateDefaultGetter(p, getter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isExternallyAccessible(p)) {
|
else if (isExternallyAccessible(p)) {
|
||||||
generateDefaultGetter(p, p, kind);
|
generateDefaultGetter(p, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,33 +105,30 @@ public class PropertyCodegen {
|
|||||||
return !p.hasModifier(JetTokens.PRIVATE_KEYWORD);
|
return !p.hasModifier(JetTokens.PRIVATE_KEYWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateSetter(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) {
|
private void generateSetter(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||||
final JetPropertyAccessor setter = p.getSetter();
|
final JetPropertyAccessor setter = p.getSetter();
|
||||||
if (setter != null) {
|
if (setter != null) {
|
||||||
if (setter.getBodyExpression() != null) {
|
if (setter.getBodyExpression() != null) {
|
||||||
final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
|
final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
|
||||||
assert setterDescriptor != null;
|
assert setterDescriptor != null;
|
||||||
functionCodegen.generateMethod(setter, kind, mapper.mapSetterSignature(propertyDescriptor),
|
functionCodegen.generateMethod(setter, state.getTypeMapper().mapSetterSignature(propertyDescriptor), setterDescriptor);
|
||||||
null,
|
|
||||||
setterDescriptor.getValueParameters(),
|
|
||||||
Collections.<TypeParameterDescriptor>emptyList());
|
|
||||||
}
|
}
|
||||||
else if (!p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
else if (!p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
||||||
generateDefaultSetter(p, setter, kind);
|
generateDefaultSetter(p, setter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isExternallyAccessible(p) && p.isVar()) {
|
else if (isExternallyAccessible(p) && p.isVar()) {
|
||||||
generateDefaultSetter(p, p, kind);
|
generateDefaultSetter(p, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateDefaultGetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) {
|
private void generateDefaultGetter(JetProperty p, JetDeclaration declaration) {
|
||||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p);
|
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().getVariableDescriptor(p);
|
||||||
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
|
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
|
||||||
generateDefaultGetter(propertyDescriptor, flags, kind);
|
generateDefaultGetter(propertyDescriptor, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags, OwnerKind kind) {
|
public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags) {
|
||||||
if (kind == OwnerKind.NAMESPACE) {
|
if (kind == OwnerKind.NAMESPACE) {
|
||||||
flags |= Opcodes.ACC_STATIC;
|
flags |= Opcodes.ACC_STATIC;
|
||||||
}
|
}
|
||||||
@@ -145,7 +136,7 @@ public class PropertyCodegen {
|
|||||||
flags |= Opcodes.ACC_ABSTRACT;
|
flags |= Opcodes.ACC_ABSTRACT;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String signature = mapper.mapGetterSignature(propertyDescriptor).getDescriptor();
|
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
|
||||||
String getterName = getterName(propertyDescriptor.getName());
|
String getterName = getterName(propertyDescriptor.getName());
|
||||||
MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null);
|
MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null);
|
||||||
if (kind != OwnerKind.INTERFACE) {
|
if (kind != OwnerKind.INTERFACE) {
|
||||||
@@ -154,7 +145,7 @@ public class PropertyCodegen {
|
|||||||
if (kind != OwnerKind.NAMESPACE) {
|
if (kind != OwnerKind.NAMESPACE) {
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
final Type type = mapper.mapType(propertyDescriptor.getOutType());
|
final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
|
||||||
if (kind instanceof OwnerKind.DelegateKind) {
|
if (kind instanceof OwnerKind.DelegateKind) {
|
||||||
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
||||||
dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv);
|
dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||||
@@ -162,7 +153,7 @@ public class PropertyCodegen {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD,
|
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD,
|
||||||
mapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(),
|
state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(),
|
||||||
type.getDescriptor());
|
type.getDescriptor());
|
||||||
}
|
}
|
||||||
iv.areturn(type);
|
iv.areturn(type);
|
||||||
@@ -171,13 +162,13 @@ public class PropertyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) {
|
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration) {
|
||||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p);
|
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().getVariableDescriptor(p);
|
||||||
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
|
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
|
||||||
generateDefaultSetter(propertyDescriptor, flags, kind);
|
generateDefaultSetter(propertyDescriptor, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags, OwnerKind kind) {
|
public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags) {
|
||||||
if (kind == OwnerKind.NAMESPACE) {
|
if (kind == OwnerKind.NAMESPACE) {
|
||||||
flags |= Opcodes.ACC_STATIC;
|
flags |= Opcodes.ACC_STATIC;
|
||||||
}
|
}
|
||||||
@@ -185,12 +176,12 @@ public class PropertyCodegen {
|
|||||||
flags |= Opcodes.ACC_ABSTRACT;
|
flags |= Opcodes.ACC_ABSTRACT;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String signature = mapper.mapSetterSignature(propertyDescriptor).getDescriptor();
|
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor();
|
||||||
MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null);
|
MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null);
|
||||||
if (kind != OwnerKind.INTERFACE) {
|
if (kind != OwnerKind.INTERFACE) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
final Type type = mapper.mapType(propertyDescriptor.getOutType());
|
final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
|
||||||
int paramCode = 0;
|
int paramCode = 0;
|
||||||
if (kind != OwnerKind.NAMESPACE) {
|
if (kind != OwnerKind.NAMESPACE) {
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
@@ -208,7 +199,7 @@ public class PropertyCodegen {
|
|||||||
else {
|
else {
|
||||||
iv.load(paramCode, type);
|
iv.load(paramCode, type);
|
||||||
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD,
|
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD,
|
||||||
mapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(),
|
state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(),
|
||||||
type.getDescriptor());
|
type.getDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ public abstract class StackValue {
|
|||||||
return new Field(type, owner, name, isStatic);
|
return new Field(type, owner, name, isStatic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StackValue instanceField(Type type, String owner, String name) {
|
||||||
|
return new InstanceField(type, owner, name);
|
||||||
|
}
|
||||||
|
|
||||||
public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, Method getter, Method setter) {
|
public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, Method getter, Method setter) {
|
||||||
return new Property(name, owner, getter, setter, isStatic, isInterface, type);
|
return new Property(name, owner, getter, setter, isStatic, isInterface, type);
|
||||||
}
|
}
|
||||||
@@ -379,6 +383,7 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class Field extends StackValue {
|
private static class Field extends StackValue {
|
||||||
private final String owner;
|
private final String owner;
|
||||||
private final String name;
|
private final String name;
|
||||||
@@ -414,6 +419,33 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class InstanceField extends StackValue {
|
||||||
|
private final String owner;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public InstanceField(Type type, String owner, String name) {
|
||||||
|
super(type);
|
||||||
|
this.owner = owner;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(Type type, InstructionAdapter v) {
|
||||||
|
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
v.getfield(owner, name, this.type.getDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dupReceiver(InstructionAdapter v, int below) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void store(InstructionAdapter v) {
|
||||||
|
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
v.putfield(owner, name, this.type.getDescriptor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class Property extends StackValue {
|
private static class Property extends StackValue {
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Method getter;
|
private final Method getter;
|
||||||
|
|||||||
Reference in New Issue
Block a user