Introducing class context stack
This commit is contained in:
@@ -20,12 +20,14 @@ public abstract class ClassBodyCodegen {
|
||||
protected final OwnerKind kind;
|
||||
protected final ClassDescriptor descriptor;
|
||||
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;
|
||||
descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
||||
myClass = aClass;
|
||||
this.kind = kind;
|
||||
this.context = context;
|
||||
this.kind = context.getContextKind();
|
||||
this.v = v;
|
||||
}
|
||||
|
||||
@@ -45,8 +47,8 @@ public abstract class ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateClassBody() {
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, state);
|
||||
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);
|
||||
|
||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||
generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
||||
@@ -57,25 +59,26 @@ public abstract class ClassBodyCodegen {
|
||||
|
||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
propertyCodegen.gen((JetProperty) declaration, kind);
|
||||
propertyCodegen.gen((JetProperty) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetNamedFunction) {
|
||||
try {
|
||||
functionCodegen.gen((JetNamedFunction) declaration, kind);
|
||||
functionCodegen.gen((JetNamedFunction) declaration);
|
||||
} 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) {
|
||||
OwnerKind kind = context.getContextKind();
|
||||
for (JetParameter p : getPrimaryConstructorParameters()) {
|
||||
if (p.getValOrVarNode() != null) {
|
||||
PropertyDescriptor propertyDescriptor = state.getBindingContext().getPropertyDescriptor(p);
|
||||
if (propertyDescriptor != null) {
|
||||
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
|
||||
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||
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)) {
|
||||
|
||||
@@ -16,36 +16,39 @@ public class ClassCodegen {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void generate(JetClassOrObject aClass) {
|
||||
public void generate(ClassContext parentContext, JetClassOrObject aClass) {
|
||||
state.prepareAnonymousClasses((JetElement) aClass);
|
||||
|
||||
if (aClass instanceof JetObjectDeclaration) {
|
||||
generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
|
||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
else {
|
||||
generateInterface(aClass);
|
||||
generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
|
||||
generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
|
||||
generateInterface(parentContext, aClass);
|
||||
generateImplementation(parentContext, aClass, OwnerKind.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()) {
|
||||
if (declaration instanceof JetClass) {
|
||||
generate((JetClass) declaration);
|
||||
generate(contextForInners, (JetClass) declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateInterface(JetClassOrObject aClass) {
|
||||
final ClassVisitor visitor = state.forClassInterface(state.getBindingContext().getClassDescriptor(aClass));
|
||||
new InterfaceBodyCodegen(aClass, visitor, state).generate();
|
||||
private void generateInterface(ClassContext parentContext, JetClassOrObject aClass) {
|
||||
ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
||||
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);
|
||||
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
|
||||
? state.forClassImplementation(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;
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
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 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 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.contextKind = contextKind;
|
||||
this.thisExpression = thisExpression;
|
||||
this.parentContext = parentContext;
|
||||
}
|
||||
|
||||
public DeclarationDescriptor getContextType() {
|
||||
@@ -26,6 +31,82 @@ public class ClassContext {
|
||||
}
|
||||
|
||||
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.ValueParameterDescriptor;
|
||||
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.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
@@ -25,15 +26,17 @@ import java.util.Map;
|
||||
|
||||
public class ClosureCodegen {
|
||||
private final GenerationState state;
|
||||
private final ExpressionCodegen context;
|
||||
private final ExpressionCodegen exprContext;
|
||||
private final ClassContext context;
|
||||
private ClassVisitor cv = null;
|
||||
private String name = null;
|
||||
|
||||
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.context = context;
|
||||
this.exprContext = exprContext;
|
||||
this.context = context.intoClosure();
|
||||
}
|
||||
|
||||
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
|
||||
@@ -59,7 +62,7 @@ public class ClosureCodegen {
|
||||
EnclosedValueDescriptor answer = closure.get(vd);
|
||||
if (answer != null) return answer.getInnerValue();
|
||||
|
||||
final int idx = context.lookupLocal(vd);
|
||||
final int idx = exprContext.lookupLocal(vd);
|
||||
if (idx < 0) return null;
|
||||
|
||||
final Type type = state.getTypeMapper().mapType(vd.getOutType());
|
||||
@@ -107,7 +110,7 @@ public class ClosureCodegen {
|
||||
|
||||
|
||||
generateBridge(name, funDescriptor, cv);
|
||||
generateBody(funDescriptor, cv, fun.getFunctionLiteral().getBodyExpression().getStatements());
|
||||
generateBody(funDescriptor, cv, fun.getFunctionLiteral());
|
||||
|
||||
final Method constructor = generateConstructor(funClass);
|
||||
|
||||
@@ -121,10 +124,9 @@ public class ClosureCodegen {
|
||||
return answer;
|
||||
}
|
||||
|
||||
private void generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, List<JetElement> body) {
|
||||
FunctionCodegen fc = new FunctionCodegen(null, cv, state);
|
||||
fc.generatedMethod(body, OwnerKind.IMPLEMENTATION, invokeSignature(funDescriptor), funDescriptor.getReceiverType(),
|
||||
funDescriptor.getValueParameters(), funDescriptor.getTypeParameters(), null);
|
||||
private void generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, JetFunctionLiteral body) {
|
||||
FunctionCodegen fc = new FunctionCodegen(context, cv, state);
|
||||
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
|
||||
}
|
||||
|
||||
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.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import jet.IntRange;
|
||||
import jet.JetObject;
|
||||
import jet.Range;
|
||||
@@ -79,7 +80,6 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
private final GenerationState state;
|
||||
private final Type returnType;
|
||||
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 ClassContext context;
|
||||
|
||||
@@ -97,10 +97,6 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void addOuterThis(ClassDescriptor outer, StackValue expression) {
|
||||
outerThisExpressions.put(outer, expression);
|
||||
}
|
||||
|
||||
public void addTypeParameter(TypeParameterDescriptor typeParameter, StackValue expression) {
|
||||
typeParameterExpressions.put(typeParameter, expression);
|
||||
}
|
||||
@@ -315,7 +311,12 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
|
||||
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() {
|
||||
@@ -505,7 +506,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
generateBlock(expression.getFunctionLiteral().getBodyExpression().getStatements());
|
||||
}
|
||||
else {
|
||||
final GeneratedAnonymousClassDescriptor closure = state.generateClosure(expression, this);
|
||||
final GeneratedAnonymousClassDescriptor closure = state.generateClosure(expression, this, context);
|
||||
|
||||
v.anew(Type.getObjectType(closure.getClassname()));
|
||||
v.dup();
|
||||
@@ -523,7 +524,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
|
||||
@Override
|
||||
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.dup();
|
||||
v.invokespecial(descriptor.getClassname(), "<init>", descriptor.getConstructor().getDescriptor());
|
||||
@@ -885,30 +886,69 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
}
|
||||
else if (!(expression.getParent() instanceof JetSafeQualifiedExpression)) {
|
||||
final StackValue value = generateThisOrOuter(calleeContainingClass);
|
||||
value.put(value.type, v);
|
||||
generateThisOrOuter(calleeContainingClass);
|
||||
}
|
||||
}
|
||||
|
||||
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
|
||||
final StackValue value = outerThisExpressions.get(calleeContainingClass);
|
||||
if (value != null) {
|
||||
return value;
|
||||
private static boolean isSubclass(ClassDescriptor subClass, ClassDescriptor superClass) {
|
||||
Set<JetType> allSuperTypes = new THashSet<JetType>();
|
||||
|
||||
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 :)
|
||||
if (calleeContainingClass != null && contextType() instanceof ClassDescriptor &&
|
||||
calleeContainingClass == contextType().getContainingDeclaration()) {
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
return StackValue.field(typeMapper.jvmType(calleeContainingClass, OwnerKind.IMPLEMENTATION),
|
||||
typeMapper.jvmName((ClassDescriptor) contextType(), OwnerKind.IMPLEMENTATION),
|
||||
"this$0",
|
||||
false);
|
||||
// TODO handle more levels of class nestng
|
||||
}
|
||||
else {
|
||||
return thisExpression() != null ? thisExpression() : StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void addSuperTypes(JetType type, Set<JetType> set) {
|
||||
set.add(type);
|
||||
|
||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||
addSuperTypes(jetType, set);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression.getThisReference());
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
myStack.push(generateThisOrOuter((ClassDescriptor) descriptor));
|
||||
generateThisOrOuter((ClassDescriptor) descriptor);
|
||||
myStack.push(StackValue.onStack(JetTypeMapper.TYPE_OBJECT));
|
||||
}
|
||||
else {
|
||||
generateThis();
|
||||
@@ -1505,27 +1546,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
|
||||
private void generateThis() {
|
||||
if (thisExpression() != null) {
|
||||
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");
|
||||
myStack.push(thisExpression());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
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.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -22,49 +19,40 @@ import java.util.List;
|
||||
* @author yole
|
||||
*/
|
||||
public class FunctionCodegen {
|
||||
private final JetDeclaration owner;
|
||||
private final ClassContext owner;
|
||||
private final ClassVisitor v;
|
||||
private final GenerationState state;
|
||||
|
||||
public FunctionCodegen(JetDeclaration owner, ClassVisitor v, GenerationState state) {
|
||||
public FunctionCodegen(ClassContext owner, ClassVisitor v, GenerationState state) {
|
||||
this.owner = owner;
|
||||
this.v = v;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void gen(JetNamedFunction f, OwnerKind kind) {
|
||||
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
|
||||
final JetType receiverType = receiverTypeRef == null ? null : state.getBindingContext().resolveTypeReference(receiverTypeRef);
|
||||
public void gen(JetNamedFunction f) {
|
||||
Method method = state.getTypeMapper().mapToCallableMethod(f).getSignature();
|
||||
final FunctionDescriptor functionDescriptor = state.getBindingContext().getFunctionDescriptor(f);
|
||||
generateMethod(f, kind, method, receiverType, functionDescriptor.getValueParameters(),
|
||||
functionDescriptor.getTypeParameters());
|
||||
generateMethod(f, method, functionDescriptor);
|
||||
}
|
||||
|
||||
public void generateMethod(JetDeclarationWithBody f,
|
||||
OwnerKind kind,
|
||||
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);
|
||||
public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) {
|
||||
ClassContext funContext = owner.intoFunction(functionDescriptor);
|
||||
|
||||
final JetExpression bodyExpression = f.getBodyExpression();
|
||||
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,
|
||||
OwnerKind kind,
|
||||
Method jvmSignature,
|
||||
JetType receiverType,
|
||||
List<ValueParameterDescriptor> paramDescrs,
|
||||
List<TypeParameterDescriptor> typeParameters,
|
||||
DeclarationDescriptor contextDesc)
|
||||
private void generatedMethod(List<JetElement> bodyExpressions,
|
||||
Method jvmSignature,
|
||||
ClassContext context,
|
||||
List<ValueParameterDescriptor> paramDescrs,
|
||||
List<TypeParameterDescriptor> typeParameters)
|
||||
{
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||
|
||||
OwnerKind kind = context.getContextKind();
|
||||
|
||||
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
||||
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);
|
||||
if (kind != OwnerKind.INTERFACE) {
|
||||
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);
|
||||
|
||||
int firstArg = thisIdx+1;
|
||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
||||
frameMap.enter(parameter, argTypes[i].getSize());
|
||||
}
|
||||
for (int i = 0; i < typeParameters.size(); i++) {
|
||||
final TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
|
||||
codegen.addTypeParameter(typeParameterDescriptor,
|
||||
StackValue.local(firstArg + paramDescrs.size() + i, JetTypeMapper.TYPE_TYPEINFO));
|
||||
frameMap.enterTemp();
|
||||
|
||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||
int slot = frameMap.enterTemp();
|
||||
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||
}
|
||||
|
||||
if (kind instanceof OwnerKind.DelegateKind) {
|
||||
|
||||
@@ -94,8 +94,8 @@ public class GenerationState {
|
||||
}
|
||||
}
|
||||
|
||||
public GeneratedAnonymousClassDescriptor generateClosure(JetFunctionLiteralExpression literal, ExpressionCodegen context) {
|
||||
final ClosureCodegen codegen = new ClosureCodegen(this, context);
|
||||
public GeneratedAnonymousClassDescriptor generateClosure(JetFunctionLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) {
|
||||
final ClosureCodegen codegen = new ClosureCodegen(this, context, classContext);
|
||||
closureContexts.push(codegen);
|
||||
try {
|
||||
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());
|
||||
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"));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ import java.util.*;
|
||||
* @author yole
|
||||
*/
|
||||
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
public ImplementationBodyCodegen(JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, GenerationState state) {
|
||||
super(aClass, kind, v, state);
|
||||
public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
||||
super(aClass, context, v, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,7 +112,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, kind);
|
||||
|
||||
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);
|
||||
|
||||
String classname = state.getTypeMapper().jvmName(descriptor, kind);
|
||||
@@ -138,7 +137,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if (outerDescriptor instanceof ClassDescriptor) {
|
||||
final ClassDescriptor outerClassDescriptor = (ClassDescriptor) outerDescriptor;
|
||||
final Type type = JetTypeMapper.jetImplementationType(outerClassDescriptor);
|
||||
codegen.addOuterThis(outerClassDescriptor, StackValue.local(frameMap.getOuterThisIndex(), type));
|
||||
String interfaceDesc = type.getDescriptor();
|
||||
final String fieldName = "this$0";
|
||||
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);
|
||||
|
||||
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),
|
||||
JetTypeMapper.jvmNameForInterface(superClassDescriptor)), overridden);
|
||||
JetTypeMapper.jvmNameForInterface(superClassDescriptor)));
|
||||
generateDelegates(superClass, delegateContext, overridden);
|
||||
}
|
||||
|
||||
n++;
|
||||
@@ -291,7 +290,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, kind);
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, state);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state);
|
||||
protected void generateDelegates(JetClass toClass, ClassContext delegateContext, Set<FunctionDescriptor> overriden) {
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state);
|
||||
|
||||
for (JetDeclaration declaration : toClass.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
propertyCodegen.gen((JetProperty) declaration, kind);
|
||||
propertyCodegen.gen((JetProperty) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetFunction) {
|
||||
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) {
|
||||
PropertyDescriptor propertyDescriptor = state.getBindingContext().getPropertyDescriptor(p);
|
||||
if (propertyDescriptor != null) {
|
||||
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
|
||||
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||
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
|
||||
*/
|
||||
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
||||
public InterfaceBodyCodegen(JetClassOrObject aClass, ClassVisitor v, GenerationState state) {
|
||||
super(aClass, OwnerKind.INTERFACE, v, state);
|
||||
public InterfaceBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
||||
super(aClass, context, v, state);
|
||||
assert context.getContextKind() == OwnerKind.INTERFACE;
|
||||
}
|
||||
|
||||
protected void generateDeclaration() {
|
||||
|
||||
@@ -33,8 +33,10 @@ public class NamespaceCodegen {
|
||||
}
|
||||
|
||||
public void generate(JetNamespace namespace) {
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, state);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, functionCodegen, state);
|
||||
final ClassContext context = ClassContext.STATIC.intoNamespace(state.getBindingContext().getNamespaceDescriptor(namespace));
|
||||
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||
final ClassCodegen classCodegen = state.forClass();
|
||||
|
||||
state.prepareAnonymousClasses(namespace);
|
||||
@@ -45,17 +47,17 @@ public class NamespaceCodegen {
|
||||
|
||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
propertyCodegen.gen((JetProperty) declaration, OwnerKind.NAMESPACE);
|
||||
propertyCodegen.gen((JetProperty) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetNamedFunction) {
|
||||
try {
|
||||
functionCodegen.gen((JetNamedFunction) declaration, OwnerKind.NAMESPACE);
|
||||
functionCodegen.gen((JetNamedFunction) declaration);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to generate function " + declaration.getName(), e);
|
||||
}
|
||||
}
|
||||
else if (declaration instanceof JetClassOrObject) {
|
||||
classCodegen.generate((JetClassOrObject) declaration);
|
||||
classCodegen.generate(context, (JetClassOrObject) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetNamespace) {
|
||||
JetNamespace childNamespace = (JetNamespace) declaration;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
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.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
@@ -11,36 +12,32 @@ import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
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;
|
||||
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.functionCodegen = functionCodegen;
|
||||
this.state = state;
|
||||
mapper = state.getTypeMapper();
|
||||
context = state.getBindingContext();
|
||||
this.kind = context.getContextKind();
|
||||
}
|
||||
|
||||
public void gen(JetProperty p, OwnerKind kind) {
|
||||
final VariableDescriptor descriptor = context.getVariableDescriptor(p);
|
||||
public void gen(JetProperty p) {
|
||||
final VariableDescriptor descriptor = state.getBindingContext().getVariableDescriptor(p);
|
||||
if (!(descriptor instanceof PropertyDescriptor)) {
|
||||
throw new UnsupportedOperationException("expect a property to have a property descriptor");
|
||||
}
|
||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
|
||||
generateBackingField(p, kind, propertyDescriptor);
|
||||
generateGetter(p, kind, propertyDescriptor);
|
||||
generateSetter(p, kind, propertyDescriptor);
|
||||
generateBackingField(p, propertyDescriptor);
|
||||
generateGetter(p, propertyDescriptor);
|
||||
generateSetter(p, propertyDescriptor);
|
||||
}
|
||||
else if (kind == OwnerKind.INTERFACE) {
|
||||
final JetPropertyAccessor getter = p.getGetter();
|
||||
@@ -48,7 +45,7 @@ public class PropertyCodegen {
|
||||
(getter == null && isExternallyAccessible(p)))) {
|
||||
v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
|
||||
getterName(p.getName()),
|
||||
mapper.mapGetterSignature(propertyDescriptor).getDescriptor(),
|
||||
state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor(),
|
||||
null, null);
|
||||
}
|
||||
final JetPropertyAccessor setter = p.getSetter();
|
||||
@@ -56,20 +53,20 @@ public class PropertyCodegen {
|
||||
(setter == null && isExternallyAccessible(p) && p.isVar()))) {
|
||||
v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
|
||||
setterName(p.getName()),
|
||||
mapper.mapSetterSignature(propertyDescriptor).getDescriptor(),
|
||||
state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor(),
|
||||
null, null);
|
||||
}
|
||||
}
|
||||
else if (kind instanceof OwnerKind.DelegateKind) {
|
||||
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
|
||||
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||
if (propertyDescriptor.isVar()) {
|
||||
generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
|
||||
generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateBackingField(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) {
|
||||
if (context.hasBackingField(propertyDescriptor)) {
|
||||
private void generateBackingField(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||
if (state.getBindingContext().hasBackingField(propertyDescriptor)) {
|
||||
Object value = null;
|
||||
final JetExpression initializer = p.getInitializer();
|
||||
if (initializer != null) {
|
||||
@@ -85,25 +82,22 @@ public class PropertyCodegen {
|
||||
else {
|
||||
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();
|
||||
if (getter != null) {
|
||||
if (getter.getBodyExpression() != null) {
|
||||
functionCodegen.generateMethod(getter, kind, mapper.mapGetterSignature(propertyDescriptor),
|
||||
null,
|
||||
Collections.<ValueParameterDescriptor>emptyList(),
|
||||
Collections.<TypeParameterDescriptor>emptyList());
|
||||
functionCodegen.generateMethod(getter, state.getTypeMapper().mapGetterSignature(propertyDescriptor), propertyDescriptor.getGetter());
|
||||
}
|
||||
else if (!getter.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
||||
generateDefaultGetter(p, getter, kind);
|
||||
generateDefaultGetter(p, getter);
|
||||
}
|
||||
}
|
||||
else if (isExternallyAccessible(p)) {
|
||||
generateDefaultGetter(p, p, kind);
|
||||
generateDefaultGetter(p, p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,33 +105,30 @@ public class PropertyCodegen {
|
||||
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();
|
||||
if (setter != null) {
|
||||
if (setter.getBodyExpression() != null) {
|
||||
final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
|
||||
assert setterDescriptor != null;
|
||||
functionCodegen.generateMethod(setter, kind, mapper.mapSetterSignature(propertyDescriptor),
|
||||
null,
|
||||
setterDescriptor.getValueParameters(),
|
||||
Collections.<TypeParameterDescriptor>emptyList());
|
||||
functionCodegen.generateMethod(setter, state.getTypeMapper().mapSetterSignature(propertyDescriptor), setterDescriptor);
|
||||
}
|
||||
else if (!p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
||||
generateDefaultSetter(p, setter, kind);
|
||||
generateDefaultSetter(p, setter);
|
||||
}
|
||||
}
|
||||
else if (isExternallyAccessible(p) && p.isVar()) {
|
||||
generateDefaultSetter(p, p, kind);
|
||||
generateDefaultSetter(p, p);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateDefaultGetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) {
|
||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p);
|
||||
private void generateDefaultGetter(JetProperty p, JetDeclaration declaration) {
|
||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().getVariableDescriptor(p);
|
||||
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) {
|
||||
flags |= Opcodes.ACC_STATIC;
|
||||
}
|
||||
@@ -145,7 +136,7 @@ public class PropertyCodegen {
|
||||
flags |= Opcodes.ACC_ABSTRACT;
|
||||
}
|
||||
|
||||
final String signature = mapper.mapGetterSignature(propertyDescriptor).getDescriptor();
|
||||
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
|
||||
String getterName = getterName(propertyDescriptor.getName());
|
||||
MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null);
|
||||
if (kind != OwnerKind.INTERFACE) {
|
||||
@@ -154,7 +145,7 @@ public class PropertyCodegen {
|
||||
if (kind != OwnerKind.NAMESPACE) {
|
||||
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) {
|
||||
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
||||
dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||
@@ -162,7 +153,7 @@ public class PropertyCodegen {
|
||||
}
|
||||
else {
|
||||
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD,
|
||||
mapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(),
|
||||
state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(),
|
||||
type.getDescriptor());
|
||||
}
|
||||
iv.areturn(type);
|
||||
@@ -171,13 +162,13 @@ public class PropertyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) {
|
||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p);
|
||||
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration) {
|
||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().getVariableDescriptor(p);
|
||||
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) {
|
||||
flags |= Opcodes.ACC_STATIC;
|
||||
}
|
||||
@@ -185,12 +176,12 @@ public class PropertyCodegen {
|
||||
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);
|
||||
if (kind != OwnerKind.INTERFACE) {
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
final Type type = mapper.mapType(propertyDescriptor.getOutType());
|
||||
final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
|
||||
int paramCode = 0;
|
||||
if (kind != OwnerKind.NAMESPACE) {
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
@@ -208,7 +199,7 @@ public class PropertyCodegen {
|
||||
else {
|
||||
iv.load(paramCode, type);
|
||||
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD,
|
||||
mapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(),
|
||||
state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(),
|
||||
type.getDescriptor());
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,10 @@ public abstract class StackValue {
|
||||
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) {
|
||||
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 final String owner;
|
||||
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 final String name;
|
||||
private final Method getter;
|
||||
|
||||
Reference in New Issue
Block a user