Merge remote branch 'origin/master'
This commit is contained in:
@@ -4,7 +4,6 @@ import com.intellij.psi.PsiElement;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
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.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -28,11 +27,11 @@ public abstract class ClassBodyCodegen {
|
|||||||
protected final OwnerKind kind;
|
protected final OwnerKind kind;
|
||||||
protected final ClassDescriptor descriptor;
|
protected final ClassDescriptor descriptor;
|
||||||
protected final ClassBuilder v;
|
protected final ClassBuilder v;
|
||||||
protected final ClassContext context;
|
protected final CodegenContext context;
|
||||||
|
|
||||||
protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();
|
protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();
|
||||||
|
|
||||||
public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
|
public ClassBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
myClass = aClass;
|
myClass = aClass;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen;
|
|||||||
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
|
||||||
@@ -19,12 +18,12 @@ public class ClassCodegen {
|
|||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generate(ClassContext context, JetClassOrObject aClass) {
|
public void generate(CodegenContext context, JetClassOrObject aClass) {
|
||||||
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
|
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
|
||||||
|
|
||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
|
|
||||||
final ClassContext contextForInners = context.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION);
|
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
|
||||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
||||||
generate(contextForInners, (JetClass) declaration);
|
generate(contextForInners, (JetClass) declaration);
|
||||||
@@ -34,17 +33,15 @@ public class ClassCodegen {
|
|||||||
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors);
|
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateImplementation(ClassContext context, JetClassOrObject aClass, OwnerKind kind, HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
private void generateImplementation(CodegenContext context, JetClassOrObject aClass, OwnerKind kind, HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
ClassBuilder v = state.forClassImplementation(descriptor);
|
ClassBuilder v = state.forClassImplementation(descriptor);
|
||||||
ClassContext classContext = context.intoClass(null, descriptor, kind);
|
CodegenContext classContext = context.intoClass(descriptor, kind);
|
||||||
new ImplementationBodyCodegen(aClass, classContext, v, state).generate(accessors);
|
new ImplementationBodyCodegen(aClass, classContext, v, state).generate(accessors);
|
||||||
|
|
||||||
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
|
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
|
||||||
v = state.forTraitImplementation(descriptor);
|
v = state.forTraitImplementation(descriptor);
|
||||||
new TraitImplBodyCodegen(aClass, context.intoClass(null, descriptor, OwnerKind.TRAIT_IMPL), v, state).generate(null);
|
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL), v, state).generate(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,258 +0,0 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.WRONG_GETTER_RETURN_TYPE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @author max
|
|
||||||
* @author alex.tkachman
|
|
||||||
*/
|
|
||||||
public class ClassContext {
|
|
||||||
public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null, null);
|
|
||||||
private final DeclarationDescriptor contextType;
|
|
||||||
private final OwnerKind contextKind;
|
|
||||||
private final StackValue thisExpression;
|
|
||||||
final ClassContext parentContext;
|
|
||||||
public final FunctionOrClosureCodegen closure;
|
|
||||||
private boolean thisWasUsed = false;
|
|
||||||
|
|
||||||
HashMap<JetType,Integer> typeInfoConstants;
|
|
||||||
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
|
||||||
|
|
||||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) {
|
|
||||||
this.contextType = contextType;
|
|
||||||
this.contextKind = contextKind;
|
|
||||||
this.thisExpression = thisExpression;
|
|
||||||
this.parentContext = parentContext;
|
|
||||||
closure = closureCodegen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeclarationDescriptor getContextDescriptor() {
|
|
||||||
return contextType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNamespaceClassName() {
|
|
||||||
if(parentContext != STATIC)
|
|
||||||
return parentContext.getNamespaceClassName();
|
|
||||||
|
|
||||||
return NamespaceCodegen.getJVMClassName(contextType.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public OwnerKind getContextKind() {
|
|
||||||
return contextKind;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StackValue getThisExpression() {
|
|
||||||
if (parentContext == null) return StackValue.none();
|
|
||||||
|
|
||||||
thisWasUsed = true;
|
|
||||||
if (thisExpression != null) return thisExpression;
|
|
||||||
return parentContext.getThisExpression();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassContext intoNamespace(NamespaceDescriptor descriptor) {
|
|
||||||
return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassContext intoClass(@Nullable FunctionOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
|
|
||||||
final StackValue thisValue;
|
|
||||||
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
|
||||||
|
|
||||||
return new ClassContext(descriptor, kind, thisValue, this, closure);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassContext intoFunction(FunctionDescriptor descriptor) {
|
|
||||||
int thisIdx = -1;
|
|
||||||
if (getContextKind() != OwnerKind.NAMESPACE) {
|
|
||||||
thisIdx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
final boolean hasReceiver = descriptor.getReceiverParameter().exists();
|
|
||||||
if (hasReceiver) {
|
|
||||||
thisIdx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ClassContext(descriptor, getContextKind(), hasReceiver ? StackValue.local(thisIdx, JetTypeMapper.TYPE_OBJECT) : null, this, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassContext intoClosure(String internalClassName, ClosureCodegen closureCodegen) {
|
|
||||||
final Type type = enclosingClassType(closureCodegen.state.getTypeMapper());
|
|
||||||
StackValue outerClass = type != null
|
|
||||||
? StackValue.instanceField(type, internalClassName, "this$0")
|
|
||||||
: StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
|
||||||
return new ClassContext(null, OwnerKind.IMPLEMENTATION, outerClass, this, closureCodegen);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ReceiverDescriptor receiver() {
|
|
||||||
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverParameter() : ReceiverDescriptor.NO_RECEIVER;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasReceiver() {
|
|
||||||
return receiver().exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassContext getParentContext() {
|
|
||||||
return parentContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type jvmType(JetTypeMapper mapper) {
|
|
||||||
if (contextType instanceof ClassDescriptor) {
|
|
||||||
return mapper.jvmType((ClassDescriptor) contextType, contextKind);
|
|
||||||
}
|
|
||||||
else if (closure != null) {
|
|
||||||
return Type.getObjectType(closure.name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return parentContext != null ? parentContext.jvmType(mapper) : JetTypeMapper.TYPE_OBJECT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeclarationDescriptor getContextClass() {
|
|
||||||
DeclarationDescriptor descriptor = getContextDescriptor();
|
|
||||||
if (descriptor == null || descriptor instanceof ClassDescriptor || descriptor instanceof NamespaceDescriptor) return descriptor;
|
|
||||||
|
|
||||||
final ClassContext parent = getParentContext();
|
|
||||||
return parent != null ? parent.getContextClass() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isThisWasUsed() {
|
|
||||||
return thisWasUsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) {
|
|
||||||
final FunctionOrClosureCodegen top = closure;
|
|
||||||
if (top != null) {
|
|
||||||
final StackValue answer = top.lookupInContext(d);
|
|
||||||
if (answer != null) return answer;
|
|
||||||
|
|
||||||
final StackValue thisContext = getThisExpression();
|
|
||||||
if(thisContext instanceof StackValue.Local) {
|
|
||||||
}
|
|
||||||
else if(thisContext instanceof StackValue.InstanceField) {
|
|
||||||
StackValue.InstanceField instanceField = (StackValue.InstanceField) thisContext;
|
|
||||||
v.getfield(instanceField.owner, instanceField.name, instanceField.type.getDescriptor());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return parentContext != null ? parentContext.lookupInContext(d, v) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type enclosingClassType(JetTypeMapper mapper) {
|
|
||||||
DeclarationDescriptor descriptor = getContextDescriptor();
|
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
|
||||||
return Type.getObjectType(mapper.jvmName((ClassDescriptor) descriptor, OwnerKind.IMPLEMENTATION));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor instanceof NamespaceDescriptor) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closure != null) {
|
|
||||||
return Type.getObjectType(closure.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
final ClassContext parent = getParentContext();
|
|
||||||
return parent != null ? parent.enclosingClassType(mapper) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTypeInfoConstantIndex(JetType type) {
|
|
||||||
if(parentContext != STATIC)
|
|
||||||
return parentContext.getTypeInfoConstantIndex(type);
|
|
||||||
|
|
||||||
if(typeInfoConstants == null)
|
|
||||||
typeInfoConstants = new HashMap<JetType, Integer>();
|
|
||||||
|
|
||||||
Integer index = typeInfoConstants.get(type);
|
|
||||||
if(index == null) {
|
|
||||||
index = typeInfoConstants.size();
|
|
||||||
typeInfoConstants.put(type, index);
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeclarationDescriptor getAccessor(DeclarationDescriptor descriptor) {
|
|
||||||
if(accessors == null) {
|
|
||||||
accessors = new HashMap<DeclarationDescriptor,DeclarationDescriptor>();
|
|
||||||
}
|
|
||||||
descriptor = descriptor.getOriginal();
|
|
||||||
DeclarationDescriptor accessor = accessors.get(descriptor);
|
|
||||||
if(accessor != null)
|
|
||||||
return accessor;
|
|
||||||
|
|
||||||
if(descriptor instanceof FunctionDescriptor) {
|
|
||||||
FunctionDescriptorImpl myAccessor = new FunctionDescriptorImpl(contextType,
|
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
|
||||||
descriptor.getName() + "$bridge$" + accessors.size());
|
|
||||||
FunctionDescriptor fd = (FunctionDescriptor) descriptor;
|
|
||||||
myAccessor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null,
|
|
||||||
fd.getExpectedThisObject(),
|
|
||||||
fd.getTypeParameters(),
|
|
||||||
fd.getValueParameters(),
|
|
||||||
fd.getReturnType(),
|
|
||||||
fd.getModality(),
|
|
||||||
fd.getVisibility());
|
|
||||||
accessor = myAccessor;
|
|
||||||
}
|
|
||||||
else if(descriptor instanceof PropertyDescriptor) {
|
|
||||||
PropertyDescriptor pd = (PropertyDescriptor) descriptor;
|
|
||||||
PropertyDescriptor myAccessor = new PropertyDescriptor(contextType,
|
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
|
||||||
pd.getModality(),
|
|
||||||
pd.getVisibility(),
|
|
||||||
pd.isVar(),
|
|
||||||
pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null,
|
|
||||||
pd.getExpectedThisObject(),
|
|
||||||
pd.getName() + "$bridge$" + accessors.size(),
|
|
||||||
pd.getInType(),
|
|
||||||
pd.getOutType());
|
|
||||||
PropertyGetterDescriptor pgd = new PropertyGetterDescriptor(
|
|
||||||
myAccessor, Collections.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
|
|
||||||
myAccessor.getVisibility(),
|
|
||||||
myAccessor.getOutType(), false, false);
|
|
||||||
PropertySetterDescriptor psd = new PropertySetterDescriptor(
|
|
||||||
myAccessor.getModality(),
|
|
||||||
myAccessor.getVisibility(),
|
|
||||||
myAccessor,
|
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
|
||||||
false, false);
|
|
||||||
myAccessor.initialize(Collections.<TypeParameterDescriptor>emptyList(), pgd, psd);
|
|
||||||
accessor = myAccessor;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
accessors.put(descriptor, accessor);
|
|
||||||
return accessor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,14 +5,14 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
|
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
|
||||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
@@ -22,13 +22,14 @@ import org.objectweb.asm.commons.Method;
|
|||||||
import org.objectweb.asm.signature.SignatureWriter;
|
import org.objectweb.asm.signature.SignatureWriter;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
public class ClosureCodegen extends FunctionOrClosureCodegen {
|
public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||||
|
|
||||||
public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, ClassContext context) {
|
public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, CodegenContext context) {
|
||||||
super(exprContext, context, state);
|
super(exprContext, context, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +81,8 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
|
|||||||
|
|
||||||
generateBridge(name, funDescriptor, fun, cv);
|
generateBridge(name, funDescriptor, fun, cv);
|
||||||
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
|
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
|
||||||
final Type enclosingType = context.enclosingClassType(state.getTypeMapper());
|
ClassDescriptor thisDescriptor = context.getThisDescriptor();
|
||||||
|
final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName());
|
||||||
if (enclosingType == null) captureThis = false;
|
if (enclosingType == null) captureThis = false;
|
||||||
|
|
||||||
final Method constructor = generateConstructor(funClass, captureThis, fun, funDescriptor.getReturnType());
|
final Method constructor = generateConstructor(funClass, captureThis, fun, funDescriptor.getReturnType());
|
||||||
@@ -128,10 +130,21 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) {
|
private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) {
|
||||||
final ClassContext closureContext = context.intoClosure(name, this);
|
int arity = funDescriptor.getValueParameters().size();
|
||||||
|
|
||||||
|
ClassDescriptorImpl function = new ClassDescriptorImpl(
|
||||||
|
funDescriptor,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
name);
|
||||||
|
function = function.initialize(
|
||||||
|
false,
|
||||||
|
Collections.<TypeParameterDescriptor>emptyList(),
|
||||||
|
Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.<FunctionDescriptor>emptySet(), null);
|
||||||
|
|
||||||
|
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this);
|
||||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||||
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
|
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
|
||||||
return closureContext.isThisWasUsed();
|
return closureContext.isOuterWasUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBridge(String className, FunctionDescriptor funDescriptor, JetFunctionLiteralExpression fun, ClassBuilder cv) {
|
private void generateBridge(String className, FunctionDescriptor funDescriptor, JetFunctionLiteralExpression fun, ClassBuilder cv) {
|
||||||
@@ -185,7 +198,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
if (captureThis) {
|
if (captureThis) {
|
||||||
i = 1;
|
i = 1;
|
||||||
argTypes[0] = context.enclosingClassType(state.getTypeMapper());
|
argTypes[0] = Type.getObjectType(context.getThisDescriptor().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
||||||
|
|||||||
@@ -0,0 +1,364 @@
|
|||||||
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @author max
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
public abstract class CodegenContext {
|
||||||
|
public static final CodegenContext STATIC = new CodegenContext(null, OwnerKind.NAMESPACE, null, null) {
|
||||||
|
@Override
|
||||||
|
protected ClassDescriptor getThisDescriptor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected static final StackValue local0 = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
protected static final StackValue local1 = StackValue.local(1, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
|
||||||
|
private final DeclarationDescriptor contextType;
|
||||||
|
|
||||||
|
private final OwnerKind contextKind;
|
||||||
|
private final CodegenContext parentContext;
|
||||||
|
public final ObjectOrClosureCodegen closure;
|
||||||
|
|
||||||
|
HashMap<JetType,Integer> typeInfoConstants;
|
||||||
|
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
||||||
|
|
||||||
|
protected DeclarationDescriptor outerDescriptor;
|
||||||
|
protected DeclarationDescriptor outerReceiverDescriptor;
|
||||||
|
|
||||||
|
protected StackValue outerExpression;
|
||||||
|
|
||||||
|
protected StackValue outerReceiverExpression;
|
||||||
|
|
||||||
|
protected boolean outerWasUsed = false;
|
||||||
|
|
||||||
|
public CodegenContext(DeclarationDescriptor contextType, OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
|
||||||
|
this.contextType = contextType;
|
||||||
|
this.contextKind = contextKind;
|
||||||
|
this.parentContext = parentContext;
|
||||||
|
closure = closureCodegen;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ClassDescriptor getThisDescriptor ();
|
||||||
|
|
||||||
|
protected DeclarationDescriptor getReceiverDescriptor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StackValue getOuterExpression(@Nullable StackValue prefix) {
|
||||||
|
if(outerExpression == null)
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
outerWasUsed = true;
|
||||||
|
return prefix != null ? StackValue.composed(prefix, outerExpression) : outerExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeclarationDescriptor getContextDescriptor() {
|
||||||
|
return contextType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespaceClassName() {
|
||||||
|
if(parentContext != STATIC)
|
||||||
|
return parentContext.getNamespaceClassName();
|
||||||
|
|
||||||
|
return NamespaceCodegen.getJVMClassName(contextType.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public OwnerKind getContextKind() {
|
||||||
|
return contextKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoNamespace(NamespaceDescriptor descriptor) {
|
||||||
|
return new NamespaceContext(descriptor, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind) {
|
||||||
|
return new ClassContext(descriptor, kind, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
|
||||||
|
return new AnonymousClassContext(descriptor, kind, this, closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||||
|
return new MethodContext(descriptor, getContextKind(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) {
|
||||||
|
if(descriptor == null) {
|
||||||
|
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
|
||||||
|
.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC);
|
||||||
|
}
|
||||||
|
return new ConstructorContext(descriptor, getContextKind(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen) {
|
||||||
|
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameMap prepareFrame() {
|
||||||
|
FrameMap frameMap = new FrameMap();
|
||||||
|
|
||||||
|
if (getContextKind() != OwnerKind.NAMESPACE) {
|
||||||
|
frameMap.enterTemp(); // 0 slot for this
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getReceiverDescriptor() != null) {
|
||||||
|
frameMap.enterTemp(); // Next slot for fake this
|
||||||
|
}
|
||||||
|
|
||||||
|
return frameMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodegenContext getParentContext() {
|
||||||
|
return parentContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type jvmType(JetTypeMapper mapper) {
|
||||||
|
if (contextType instanceof ClassDescriptor) {
|
||||||
|
return mapper.jvmType((ClassDescriptor) contextType, contextKind);
|
||||||
|
}
|
||||||
|
else if (closure != null) {
|
||||||
|
return Type.getObjectType(closure.name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return parentContext != null ? parentContext.jvmType(mapper) : JetTypeMapper.TYPE_OBJECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) {
|
||||||
|
final ObjectOrClosureCodegen top = closure;
|
||||||
|
if (top != null) {
|
||||||
|
final StackValue answer = top.lookupInContext(d);
|
||||||
|
if (answer != null) return answer;
|
||||||
|
|
||||||
|
getOuterExpression(null).put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parentContext != null ? parentContext.lookupInContext(d, v) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type enclosingClassType() {
|
||||||
|
CodegenContext cur = getParentContext();
|
||||||
|
while(cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor))
|
||||||
|
cur = cur.getParentContext();
|
||||||
|
|
||||||
|
return cur == null ? null : Type.getObjectType(cur.getContextDescriptor().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTypeInfoConstantIndex(JetType type) {
|
||||||
|
if(parentContext != STATIC)
|
||||||
|
return parentContext.getTypeInfoConstantIndex(type);
|
||||||
|
|
||||||
|
if(typeInfoConstants == null)
|
||||||
|
typeInfoConstants = new HashMap<JetType, Integer>();
|
||||||
|
|
||||||
|
Integer index = typeInfoConstants.get(type);
|
||||||
|
if(index == null) {
|
||||||
|
index = typeInfoConstants.size();
|
||||||
|
typeInfoConstants.put(type, index);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeclarationDescriptor getAccessor(DeclarationDescriptor descriptor) {
|
||||||
|
if(accessors == null) {
|
||||||
|
accessors = new HashMap<DeclarationDescriptor,DeclarationDescriptor>();
|
||||||
|
}
|
||||||
|
descriptor = descriptor.getOriginal();
|
||||||
|
DeclarationDescriptor accessor = accessors.get(descriptor);
|
||||||
|
if(accessor != null)
|
||||||
|
return accessor;
|
||||||
|
|
||||||
|
if(descriptor instanceof FunctionDescriptor) {
|
||||||
|
FunctionDescriptorImpl myAccessor = new FunctionDescriptorImpl(contextType,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
descriptor.getName() + "$bridge$" + accessors.size());
|
||||||
|
FunctionDescriptor fd = (FunctionDescriptor) descriptor;
|
||||||
|
myAccessor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null,
|
||||||
|
fd.getExpectedThisObject(),
|
||||||
|
fd.getTypeParameters(),
|
||||||
|
fd.getValueParameters(),
|
||||||
|
fd.getReturnType(),
|
||||||
|
fd.getModality(),
|
||||||
|
fd.getVisibility());
|
||||||
|
accessor = myAccessor;
|
||||||
|
}
|
||||||
|
else if(descriptor instanceof PropertyDescriptor) {
|
||||||
|
PropertyDescriptor pd = (PropertyDescriptor) descriptor;
|
||||||
|
PropertyDescriptor myAccessor = new PropertyDescriptor(contextType,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
pd.getModality(),
|
||||||
|
pd.getVisibility(),
|
||||||
|
pd.isVar(),
|
||||||
|
pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null,
|
||||||
|
pd.getExpectedThisObject(),
|
||||||
|
pd.getName() + "$bridge$" + accessors.size(),
|
||||||
|
pd.getInType(),
|
||||||
|
pd.getOutType());
|
||||||
|
PropertyGetterDescriptor pgd = new PropertyGetterDescriptor(
|
||||||
|
myAccessor, Collections.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
|
||||||
|
myAccessor.getVisibility(),
|
||||||
|
myAccessor.getOutType(), false, false);
|
||||||
|
PropertySetterDescriptor psd = new PropertySetterDescriptor(
|
||||||
|
myAccessor.getModality(),
|
||||||
|
myAccessor.getVisibility(),
|
||||||
|
myAccessor,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
false, false);
|
||||||
|
myAccessor.initialize(Collections.<TypeParameterDescriptor>emptyList(), pgd, psd);
|
||||||
|
accessor = myAccessor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
accessors.put(descriptor, accessor);
|
||||||
|
return accessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOuterWasUsed() {
|
||||||
|
return outerWasUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackValue getReceiverExpression() {
|
||||||
|
assert getReceiverDescriptor() != null;
|
||||||
|
return getThisDescriptor() != null ? local1 : local0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackValue getThisExpression() {
|
||||||
|
assert getThisDescriptor() != null;
|
||||||
|
return local0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class FunctionContext extends CodegenContext {
|
||||||
|
final DeclarationDescriptor receiverDescriptor;
|
||||||
|
|
||||||
|
public FunctionContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
|
||||||
|
super(contextType, contextKind, parentContext, closureCodegen);
|
||||||
|
receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DeclarationDescriptor getReceiverDescriptor() {
|
||||||
|
return receiverDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MethodContext extends FunctionContext {
|
||||||
|
public MethodContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) {
|
||||||
|
super(contextType, contextKind, parentContext, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClassDescriptor getThisDescriptor() {
|
||||||
|
return getParentContext().getThisDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) {
|
||||||
|
return getParentContext().lookupInContext(d, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type enclosingClassType() {
|
||||||
|
return getParentContext().enclosingClassType();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StackValue getOuterExpression(StackValue prefix) {
|
||||||
|
return getParentContext().getOuterExpression(prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConstructorContext extends MethodContext {
|
||||||
|
public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent) {
|
||||||
|
super(contextType, kind, parent);
|
||||||
|
|
||||||
|
final Type type = enclosingClassType();
|
||||||
|
outerExpression = type != null
|
||||||
|
? local1
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StackValue getOuterExpression(StackValue prefix) {
|
||||||
|
return outerExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ClassContext extends CodegenContext {
|
||||||
|
public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) {
|
||||||
|
super(contextType, contextKind, parentContext, null);
|
||||||
|
|
||||||
|
final Type type = enclosingClassType();
|
||||||
|
outerExpression = type != null
|
||||||
|
? StackValue.field(type, DescriptorRenderer.getFQName(contextType).replace('.', '/'), "this$0", false)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClassDescriptor getThisDescriptor() {
|
||||||
|
return (ClassDescriptor) getContextDescriptor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AnonymousClassContext extends CodegenContext {
|
||||||
|
public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure) {
|
||||||
|
super(contextType, contextKind, parentContext, closure);
|
||||||
|
|
||||||
|
final Type type = enclosingClassType();
|
||||||
|
outerExpression = type != null
|
||||||
|
? StackValue.field(type, closure.state.getTypeMapper().jvmName(contextType, OwnerKind.IMPLEMENTATION), "this$0", false)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClassDescriptor getThisDescriptor() {
|
||||||
|
return (ClassDescriptor) getContextDescriptor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ClosureContext extends FunctionContext {
|
||||||
|
private ClassDescriptor classDescriptor;
|
||||||
|
|
||||||
|
public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName) {
|
||||||
|
super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen);
|
||||||
|
this.classDescriptor = classDescriptor;
|
||||||
|
|
||||||
|
final Type type = enclosingClassType();
|
||||||
|
outerExpression = type != null
|
||||||
|
? StackValue.field(type, internalClassName, "this$0", false)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClassDescriptor getThisDescriptor() {
|
||||||
|
return classDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeclarationDescriptor getContextDescriptor() {
|
||||||
|
return classDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NamespaceContext extends CodegenContext {
|
||||||
|
public NamespaceContext(NamespaceDescriptor contextType, CodegenContext parent) {
|
||||||
|
super(contextType, OwnerKind.NAMESPACE, parent, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClassDescriptor getThisDescriptor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,7 +51,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
private int myLastLineNumber = -1;
|
private int myLastLineNumber = -1;
|
||||||
|
|
||||||
private final InstructionAdapter v;
|
final InstructionAdapter v;
|
||||||
private final FrameMap myFrameMap;
|
private final FrameMap myFrameMap;
|
||||||
private final JetTypeMapper typeMapper;
|
private final JetTypeMapper typeMapper;
|
||||||
|
|
||||||
@@ -60,13 +60,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
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 CodegenContext context;
|
||||||
private final IntrinsicMethods intrinsics;
|
private final IntrinsicMethods intrinsics;
|
||||||
|
|
||||||
public ExpressionCodegen(MethodVisitor v,
|
public ExpressionCodegen(MethodVisitor v,
|
||||||
FrameMap myMap,
|
FrameMap myMap,
|
||||||
Type returnType,
|
Type returnType,
|
||||||
ClassContext context,
|
CodegenContext context,
|
||||||
GenerationState state) {
|
GenerationState state) {
|
||||||
this.myFrameMap = myMap;
|
this.myFrameMap = myMap;
|
||||||
this.typeMapper = state.getTypeMapper();
|
this.typeMapper = state.getTypeMapper();
|
||||||
@@ -140,7 +140,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
// return generateThisOrOuter((ClassDescriptor) descriptor);
|
// return generateThisOrOuter((ClassDescriptor) descriptor);
|
||||||
// }
|
// }
|
||||||
// else {
|
// else {
|
||||||
// return thisExpression();
|
// return local0();
|
||||||
// }
|
// }
|
||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
}
|
}
|
||||||
@@ -333,10 +333,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return context.getContextKind();
|
return context.getContextKind();
|
||||||
}
|
}
|
||||||
|
|
||||||
private StackValue thisExpression() {
|
|
||||||
return context.getThisExpression();
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract class ForLoopGenerator {
|
private abstract class ForLoopGenerator {
|
||||||
protected JetForExpression expression;
|
protected JetForExpression expression;
|
||||||
protected Type loopRangeType;
|
protected Type loopRangeType;
|
||||||
@@ -601,7 +597,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) {
|
public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) {
|
||||||
FunctionOrClosureCodegen closureCodegen = new FunctionOrClosureCodegen(this, context, state);
|
ObjectOrClosureCodegen closureCodegen = new ObjectOrClosureCodegen(this, context, state);
|
||||||
GeneratedAnonymousClassDescriptor closure = state.generateObjectLiteral(expression, closureCodegen);
|
GeneratedAnonymousClassDescriptor closure = state.generateObjectLiteral(expression, closureCodegen);
|
||||||
Type type = Type.getObjectType(closure.getClassname());
|
Type type = Type.getObjectType(closure.getClassname());
|
||||||
v.anew(type);
|
v.anew(type);
|
||||||
@@ -888,7 +884,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
String owner;
|
String owner;
|
||||||
|
|
||||||
boolean isInterface;
|
boolean isInterface;
|
||||||
boolean isInsideClass = containingDeclaration == context.getContextClass();
|
boolean isInsideClass = containingDeclaration == context.getThisDescriptor();
|
||||||
if (isInsideClass || isStatic) {
|
if (isInsideClass || isStatic) {
|
||||||
owner = typeMapper.getOwner(functionDescriptor, contextKind());
|
owner = typeMapper.getOwner(functionDescriptor, contextKind());
|
||||||
isInterface = false;
|
isInterface = false;
|
||||||
@@ -915,10 +911,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, @Nullable JetSuperExpression superExpression) {
|
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, @Nullable JetSuperExpression superExpression) {
|
||||||
boolean isSuper = superExpression != null;
|
boolean isSuper = superExpression != null;
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration().getOriginal();
|
||||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
||||||
propertyDescriptor = propertyDescriptor.getOriginal();
|
propertyDescriptor = propertyDescriptor.getOriginal();
|
||||||
boolean isInsideClass = containingDeclaration == context.getContextClass() && contextKind() != OwnerKind.TRAIT_IMPL;
|
boolean isInsideClass = ((containingDeclaration == context.getThisDescriptor()) ||
|
||||||
|
(context.getParentContext() instanceof CodegenContext.NamespaceContext) && context.getParentContext().getContextDescriptor() == containingDeclaration)
|
||||||
|
&& contextKind() != OwnerKind.TRAIT_IMPL;
|
||||||
Method getter;
|
Method getter;
|
||||||
Method setter;
|
Method setter;
|
||||||
if (forceField) {
|
if (forceField) {
|
||||||
@@ -935,8 +933,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
||||||
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
||||||
if(!CodegenUtil.isInterface(propertyDescriptor.getContainingDeclaration())) {
|
if(!CodegenUtil.isInterface(propertyDescriptor.getContainingDeclaration())) {
|
||||||
if(enclosed != null && enclosed != context.getContextClass()) {
|
if(enclosed != null && enclosed != context.getThisDescriptor()) {
|
||||||
ClassContext c = context;
|
CodegenContext c = context;
|
||||||
while(c.getContextDescriptor() != enclosed) {
|
while(c.getContextDescriptor() != enclosed) {
|
||||||
c = c.getParentContext();
|
c = c.getParentContext();
|
||||||
}
|
}
|
||||||
@@ -1002,12 +1000,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
||||||
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
||||||
if(!CodegenUtil.isInterface(fd.getContainingDeclaration())) {
|
if(!CodegenUtil.isInterface(fd.getContainingDeclaration())) {
|
||||||
if(enclosed != null && enclosed != context.getContextClass()) {
|
if(enclosed != null && enclosed != context.getThisDescriptor()) {
|
||||||
ClassContext c = context;
|
CodegenContext c = context;
|
||||||
while(c.getContextDescriptor() != enclosed) {
|
while(c.getContextDescriptor() != enclosed) {
|
||||||
c = c.getParentContext();
|
c = c.getParentContext();
|
||||||
}
|
}
|
||||||
fd = c.getAccessor((FunctionDescriptor) fd);
|
fd = c.getAccessor(fd);
|
||||||
superCall = false;
|
superCall = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1150,41 +1148,31 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
|
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
|
||||||
boolean thisDone = false;
|
CodegenContext cur = context;
|
||||||
StackValue result = null;
|
if(cur.getReceiverDescriptor() == calleeContainingClass) {
|
||||||
|
return cur.getReceiverExpression();
|
||||||
|
}
|
||||||
|
|
||||||
ClassContext cur = context;
|
StackValue result = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
while (true) {
|
while (cur != null) {
|
||||||
ClassContext parentContext = cur.getParentContext();
|
if(cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext))
|
||||||
if (parentContext == null) break;
|
cur = cur.getParentContext();
|
||||||
|
|
||||||
final DeclarationDescriptor curContextType = cur.getContextDescriptor();
|
if (isSubclass(cur.getThisDescriptor(), calleeContainingClass)) {
|
||||||
if (curContextType instanceof ClassDescriptor) {
|
Type type = typeMapper.mapType(calleeContainingClass.getDefaultType());
|
||||||
if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break;
|
result.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
|
return StackValue.onStack(type);
|
||||||
final StackValue outer;
|
|
||||||
if (!thisDone && myFrameMap instanceof ConstructorFrameMap) {
|
|
||||||
outer = StackValue.local(((ConstructorFrameMap) myFrameMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
thisToStack();
|
|
||||||
outer = StackValue.field(parentContext.jvmType(typeMapper),
|
|
||||||
cur.jvmType(typeMapper).getInternalName(),
|
|
||||||
"this$0",
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
|
|
||||||
thisDone = true;
|
|
||||||
result = outer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = parentContext;
|
result = cur.getOuterExpression(result);
|
||||||
}
|
|
||||||
|
|
||||||
if (!thisDone) {
|
if(cur instanceof CodegenContext.ConstructorContext) {
|
||||||
return thisExpression();
|
cur = cur.getParentContext();
|
||||||
|
}
|
||||||
|
cur = cur.getParentContext();
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isReceiver(PsiElement expression) {
|
private static boolean isReceiver(PsiElement expression) {
|
||||||
@@ -2082,15 +2070,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return generateThisOrOuter((ClassDescriptor) descriptor);
|
return generateThisOrOuter((ClassDescriptor) descriptor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// estension function or ???
|
if(descriptor instanceof FunctionDescriptor) {
|
||||||
return thisExpression();
|
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||||
|
Type type = typeMapper.mapType(functionDescriptor.getReceiverParameter().getType());
|
||||||
|
return StackValue.local(descriptor.getContainingDeclaration() instanceof NamespaceDescriptor ? 0 : 1, type);
|
||||||
|
}
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void thisToStack() {
|
|
||||||
thisExpression().put(JetTypeMapper.TYPE_OBJECT, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitTryExpression(JetTryExpression expression, StackValue receiver) {
|
public StackValue visitTryExpression(JetTryExpression expression, StackValue receiver) {
|
||||||
Label tryStart = new Label();
|
Label tryStart = new Label();
|
||||||
@@ -2374,13 +2362,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
||||||
if (context.getContextClass() instanceof ClassDescriptor) {
|
if (context.getThisDescriptor() instanceof ClassDescriptor) {
|
||||||
ClassDescriptor descriptor = (ClassDescriptor) context.getContextClass();
|
ClassDescriptor descriptor = (ClassDescriptor) context.getThisDescriptor();
|
||||||
assert containingDeclaration != null;
|
assert containingDeclaration != null;
|
||||||
JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType();
|
JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType();
|
||||||
Type ownerType = typeMapper.mapType(defaultType);
|
Type ownerType = typeMapper.mapType(defaultType);
|
||||||
ownerType = JetTypeMapper.boxType(ownerType);
|
ownerType = JetTypeMapper.boxType(ownerType);
|
||||||
if (containingDeclaration == context.getContextClass()) {
|
if (containingDeclaration == context.getThisDescriptor()) {
|
||||||
if(!CodegenUtil.isInterface(descriptor)) {
|
if(!CodegenUtil.isInterface(descriptor)) {
|
||||||
if (CodegenUtil.hasTypeInfoField(defaultType)) {
|
if (CodegenUtil.hasTypeInfoField(defaultType)) {
|
||||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ import static org.objectweb.asm.Opcodes.*;
|
|||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class FunctionCodegen {
|
public class FunctionCodegen {
|
||||||
private final ClassContext owner;
|
private final CodegenContext owner;
|
||||||
private final ClassBuilder v;
|
private final ClassBuilder v;
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
|
|
||||||
public FunctionCodegen(ClassContext owner, ClassBuilder v, GenerationState state) {
|
public FunctionCodegen(CodegenContext owner, ClassBuilder v, GenerationState state) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.v = v;
|
this.v = v;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
@@ -40,7 +40,7 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) {
|
public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) {
|
||||||
ClassContext funContext = owner.intoFunction(functionDescriptor);
|
CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor);
|
||||||
|
|
||||||
final JetExpression bodyExpression = f.getBodyExpression();
|
final JetExpression bodyExpression = f.getBodyExpression();
|
||||||
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f);
|
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f);
|
||||||
@@ -48,7 +48,7 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
private void generatedMethod(JetExpression bodyExpressions,
|
private void generatedMethod(JetExpression bodyExpressions,
|
||||||
Method jvmSignature,
|
Method jvmSignature,
|
||||||
ClassContext context,
|
CodegenContext.MethodContext context,
|
||||||
FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
|
FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
|
||||||
{
|
{
|
||||||
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
|
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
|
||||||
@@ -67,9 +67,8 @@ public class FunctionCodegen {
|
|||||||
if (isAbstract) flags |= ACC_ABSTRACT;
|
if (isAbstract) flags |= ACC_ABSTRACT;
|
||||||
|
|
||||||
final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
||||||
boolean hasReceiver = functionDescriptor.getReceiverParameter().exists();
|
|
||||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||||
int start = hasReceiver ? 1 : 0;
|
int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0;
|
||||||
for(int i = 0; i != paramDescrs.size(); ++i) {
|
for(int i = 0; i != paramDescrs.size(); ++i) {
|
||||||
AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "jet/typeinfo/JetParameterName", true);
|
AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "jet/typeinfo/JetParameterName", true);
|
||||||
annotationVisitor.visit("value", paramDescrs.get(i).getName());
|
annotationVisitor.visit("value", paramDescrs.get(i).getName());
|
||||||
@@ -78,16 +77,12 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
if (!isAbstract) {
|
if (!isAbstract) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
Label methodStart = new Label();
|
|
||||||
mv.visitLabel(methodStart);
|
|
||||||
|
|
||||||
FrameMap frameMap = context.prepareFrame();
|
FrameMap frameMap = context.prepareFrame();
|
||||||
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
|
||||||
|
|
||||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||||
int receiverSize = !hasReceiver ? 0 : state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize();
|
int add = functionDescriptor.getReceiverParameter().exists() ? state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize() : 0;
|
||||||
int add = hasReceiver ? 1 : 0;
|
|
||||||
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+add].getSize());
|
frameMap.enter(parameter, argTypes[i+add].getSize());
|
||||||
@@ -128,18 +123,8 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
codegen.returnExpression(bodyExpressions);
|
codegen.returnExpression(bodyExpressions);
|
||||||
}
|
}
|
||||||
|
|
||||||
Label methodEnd = new Label();
|
|
||||||
mv.visitLabel(methodEnd);
|
|
||||||
int index = ((flags & ACC_STATIC) != 0 ? 0 : 1) + receiverSize;
|
|
||||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
|
||||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
|
||||||
mv.visitLocalVariable(parameter.getName(), state.getTypeMapper().mapType(parameter.getOutType()).getDescriptor(), null, methodStart, methodEnd, index);
|
|
||||||
index += argTypes[i+add].getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
System.out.println(t);
|
System.out.println(t);
|
||||||
@@ -153,7 +138,7 @@ public class FunctionCodegen {
|
|||||||
generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind);
|
generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generateBridgeIfNeeded(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
static void generateBridgeIfNeeded(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||||
Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
|
Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
|
||||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||||
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
|
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
|
||||||
@@ -164,8 +149,8 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generateDefaultIfNeeded(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||||
DeclarationDescriptor contextClass = owner.getContextClass();
|
DeclarationDescriptor contextClass = ((FunctionDescriptor)owner.getContextDescriptor()).getContainingDeclaration();
|
||||||
|
|
||||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||||
// we don't generate defaults for traits but do for traitImpl
|
// we don't generate defaults for traits but do for traitImpl
|
||||||
@@ -307,7 +292,7 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkOverride(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
|
private static void checkOverride(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
|
||||||
Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType());
|
Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType());
|
||||||
Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType());
|
Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType());
|
||||||
if(!type1.equals(type2)) {
|
if(!type1.equals(type2)) {
|
||||||
|
|||||||
@@ -114,13 +114,13 @@ public class GenerationState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) {
|
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ObjectOrClosureCodegen closure) {
|
||||||
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
||||||
Pair<String, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
|
Pair<String, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
|
||||||
|
|
||||||
closure.cv = nameAndVisitor.getSecond();
|
closure.cv = nameAndVisitor.getSecond();
|
||||||
closure.name = nameAndVisitor.getFirst();
|
closure.name = nameAndVisitor.getFirst();
|
||||||
final ClassContext objectContext = closure.context.intoClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
|
final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
|
||||||
|
|
||||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null);
|
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
private JetDelegationSpecifier superCall;
|
private JetDelegationSpecifier superCall;
|
||||||
private String superClass = "java/lang/Object";
|
private String superClass = "java/lang/Object";
|
||||||
|
|
||||||
public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
|
public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
||||||
super(aClass, context, v, state);
|
super(aClass, context, v, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,6 +290,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, myClass);
|
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, myClass);
|
||||||
|
|
||||||
|
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
|
||||||
|
|
||||||
Method method;
|
Method method;
|
||||||
CallableMethod callableMethod;
|
CallableMethod callableMethod;
|
||||||
if (constructorDescriptor == null) {
|
if (constructorDescriptor == null) {
|
||||||
@@ -337,7 +339,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, descriptor, kind);
|
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, descriptor, kind);
|
||||||
|
|
||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state);
|
||||||
|
|
||||||
for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
|
for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
|
||||||
if(constructorDescriptor != null)
|
if(constructorDescriptor != null)
|
||||||
@@ -405,7 +407,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
iv.putfield(classname, delegateField, fieldDesc);
|
iv.putfield(classname, delegateField, fieldDesc);
|
||||||
|
|
||||||
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||||
final ClassContext delegateContext = context.intoClass(null, superClassDescriptor,
|
final CodegenContext delegateContext = context.intoClass(superClassDescriptor,
|
||||||
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
||||||
state.getTypeMapper().jvmNameForImplementation(superClassDescriptor, OwnerKind.IMPLEMENTATION)));
|
state.getTypeMapper().jvmNameForImplementation(superClassDescriptor, OwnerKind.IMPLEMENTATION)));
|
||||||
generateDelegates(superClass, delegateContext, overridden);
|
generateDelegates(superClass, delegateContext, overridden);
|
||||||
@@ -441,10 +443,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateInitializers(codegen, iv);
|
|
||||||
|
|
||||||
generateTraitMethods(codegen);
|
|
||||||
|
|
||||||
int curParam = 0;
|
int curParam = 0;
|
||||||
List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
|
List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
|
||||||
for (JetParameter parameter : constructorParameters) {
|
for (JetParameter parameter : constructorParameters) {
|
||||||
@@ -458,6 +456,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
curParam++;
|
curParam++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateInitializers(codegen, iv);
|
||||||
|
|
||||||
|
generateTraitMethods(codegen);
|
||||||
|
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
@@ -741,7 +743,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateDelegates(JetClass toClass, ClassContext delegateContext, Set<FunctionDescriptor> overriden) {
|
protected void generateDelegates(JetClass toClass, CodegenContext delegateContext, Set<FunctionDescriptor> overriden) {
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state);
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state);
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class NamespaceCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generate(JetNamespace namespace) {
|
public void generate(JetNamespace namespace) {
|
||||||
final ClassContext context = ClassContext.STATIC.intoNamespace(state.getBindingContext().get(BindingContext.NAMESPACE, namespace));
|
final CodegenContext context = CodegenContext.STATIC.intoNamespace(state.getBindingContext().get(BindingContext.NAMESPACE, namespace));
|
||||||
|
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||||
@@ -85,7 +85,7 @@ public class NamespaceCodegen {
|
|||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
FrameMap frameMap = new FrameMap();
|
FrameMap frameMap = new FrameMap();
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, ClassContext.STATIC, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);
|
||||||
|
|
||||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
@@ -103,7 +103,7 @@ public class NamespaceCodegen {
|
|||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateTypeInfoFields(JetNamespace namespace, ClassContext context) {
|
private void generateTypeInfoFields(JetNamespace namespace, CodegenContext context) {
|
||||||
if(context.typeInfoConstants != null) {
|
if(context.typeInfoConstants != null) {
|
||||||
String jvmClassName = getJVMClassName(namespace.getName());
|
String jvmClassName = getJVMClassName(namespace.getName());
|
||||||
for(Map.Entry<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>emptyMap()).entrySet()) {
|
for(Map.Entry<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>emptyMap()).entrySet()) {
|
||||||
@@ -130,7 +130,7 @@ public class NamespaceCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void generateTypeInfo(ClassContext context, InstructionAdapter v, JetType jetType, JetTypeMapper typeMapper, JetType root) {
|
private static void generateTypeInfo(CodegenContext context, InstructionAdapter v, JetType jetType, JetTypeMapper typeMapper, JetType root) {
|
||||||
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
|
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
|
||||||
if(knownTypeInfo != null) {
|
if(knownTypeInfo != null) {
|
||||||
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
|
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
|
||||||
|
|||||||
+6
-3
@@ -1,27 +1,30 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptorImpl;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class FunctionOrClosureCodegen {
|
public class ObjectOrClosureCodegen {
|
||||||
protected boolean captureThis;
|
protected boolean captureThis;
|
||||||
|
|
||||||
public final GenerationState state;
|
public final GenerationState state;
|
||||||
protected final ExpressionCodegen exprContext;
|
protected final ExpressionCodegen exprContext;
|
||||||
protected final ClassContext context;
|
protected final CodegenContext context;
|
||||||
protected ClassBuilder cv = null;
|
protected ClassBuilder cv = null;
|
||||||
public String name = null;
|
public String name = null;
|
||||||
protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
|
protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
|
||||||
|
|
||||||
public FunctionOrClosureCodegen(ExpressionCodegen exprContext, ClassContext context, GenerationState state) {
|
public ObjectOrClosureCodegen(ExpressionCodegen exprContext, CodegenContext context, GenerationState state) {
|
||||||
this.exprContext = exprContext;
|
this.exprContext = exprContext;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
@@ -24,7 +24,7 @@ public class PropertyCodegen {
|
|||||||
private final ClassBuilder v;
|
private final ClassBuilder v;
|
||||||
private final OwnerKind kind;
|
private final OwnerKind kind;
|
||||||
|
|
||||||
public PropertyCodegen(ClassContext context, ClassBuilder v, FunctionCodegen functionCodegen, GenerationState state) {
|
public PropertyCodegen(CodegenContext context, ClassBuilder v, FunctionCodegen functionCodegen, GenerationState state) {
|
||||||
this.v = v;
|
this.v = v;
|
||||||
this.functionCodegen = functionCodegen;
|
this.functionCodegen = functionCodegen;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|||||||
@@ -235,6 +235,10 @@ public abstract class StackValue {
|
|||||||
return new FieldForSharedVar(type, name, fieldName);
|
return new FieldForSharedVar(type, name, fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StackValue composed(StackValue prefix, StackValue suffix) {
|
||||||
|
return new Composed(prefix, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
private static class None extends StackValue {
|
private static class None extends StackValue {
|
||||||
public static None INSTANCE = new None();
|
public static None INSTANCE = new None();
|
||||||
private None() {
|
private None() {
|
||||||
@@ -790,4 +794,21 @@ public abstract class StackValue {
|
|||||||
v.visitFieldInsn(Opcodes.PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor());
|
v.visitFieldInsn(Opcodes.PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class Composed extends StackValue {
|
||||||
|
private StackValue prefix;
|
||||||
|
private StackValue suffix;
|
||||||
|
|
||||||
|
public Composed(StackValue prefix, StackValue suffix) {
|
||||||
|
super(suffix.type);
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.suffix = suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(Type type, InstructionAdapter v) {
|
||||||
|
prefix.put(prefix.type, v);
|
||||||
|
suffix.put(type, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.objectweb.asm.Opcodes;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||||
public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
|
public TraitImplBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
||||||
super(aClass, context, v, state);
|
super(aClass, context, v, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public interface JetControlFlowBuilder {
|
|||||||
Label createUnboundLabel();
|
Label createUnboundLabel();
|
||||||
|
|
||||||
void bindLabel(@NotNull Label label);
|
void bindLabel(@NotNull Label label);
|
||||||
|
void allowDead();
|
||||||
|
|
||||||
// Jumps
|
// Jumps
|
||||||
void jump(@NotNull Label label);
|
void jump(@NotNull Label label);
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
|||||||
builder.bindLabel(label);
|
builder.bindLabel(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void allowDead() {
|
||||||
|
assert builder != null;
|
||||||
|
builder.allowDead();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void jump(@NotNull Label label) {
|
public void jump(@NotNull Label label) {
|
||||||
assert builder != null;
|
assert builder != null;
|
||||||
|
|||||||
@@ -5,18 +5,19 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
|
||||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
|
|
||||||
@@ -356,18 +357,35 @@ public class JetControlFlowProcessor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Label onException = builder.createUnboundLabel();
|
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||||
builder.nondeterministicJump(onException);
|
final boolean hasCatches = !catchClauses.isEmpty();
|
||||||
|
Label onException = null;
|
||||||
|
if (hasCatches) {
|
||||||
|
onException = builder.createUnboundLabel();
|
||||||
|
builder.nondeterministicJump(onException);
|
||||||
|
}
|
||||||
value(expression.getTryBlock(), inCondition);
|
value(expression.getTryBlock(), inCondition);
|
||||||
|
|
||||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
if (hasCatches) {
|
||||||
if (!catchClauses.isEmpty()) {
|
builder.allowDead();
|
||||||
Label afterCatches = builder.createUnboundLabel();
|
Label afterCatches = builder.createUnboundLabel();
|
||||||
builder.jump(afterCatches);
|
builder.jump(afterCatches);
|
||||||
|
|
||||||
builder.bindLabel(onException);
|
builder.bindLabel(onException);
|
||||||
for (Iterator<JetCatchClause> iterator = catchClauses.iterator(); iterator.hasNext(); ) {
|
LinkedList<Label> catchLabels = Lists.newLinkedList();
|
||||||
JetCatchClause catchClause = iterator.next();
|
int catchClausesSize = catchClauses.size();
|
||||||
|
for (int i = 0; i < catchClausesSize - 1; i++) {
|
||||||
|
catchLabels.add(builder.createUnboundLabel());
|
||||||
|
}
|
||||||
|
builder.nondeterministicJump(catchLabels);
|
||||||
|
boolean isFirst = true;
|
||||||
|
for (JetCatchClause catchClause : catchClauses) {
|
||||||
|
if (!isFirst) {
|
||||||
|
builder.bindLabel(catchLabels.remove());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isFirst = false;
|
||||||
|
}
|
||||||
JetParameter catchParameter = catchClause.getCatchParameter();
|
JetParameter catchParameter = catchClause.getCatchParameter();
|
||||||
if (catchParameter != null) {
|
if (catchParameter != null) {
|
||||||
builder.write(catchParameter, catchParameter);
|
builder.write(catchParameter, catchParameter);
|
||||||
@@ -376,14 +394,14 @@ public class JetControlFlowProcessor {
|
|||||||
if (catchBody != null) {
|
if (catchBody != null) {
|
||||||
value(catchBody, false);
|
value(catchBody, false);
|
||||||
}
|
}
|
||||||
if (iterator.hasNext()) {
|
builder.allowDead();
|
||||||
builder.nondeterministicJump(afterCatches);
|
builder.jump(afterCatches);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.bindLabel(afterCatches);
|
builder.bindLabel(afterCatches);
|
||||||
} else {
|
}
|
||||||
builder.bindLabel(onException);
|
else {
|
||||||
|
builder.allowDead();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (finallyBlock != null) {
|
if (finallyBlock != null) {
|
||||||
|
|||||||
+7
@@ -243,6 +243,13 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
|||||||
pseudocode.bindLabel(label);
|
pseudocode.bindLabel(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void allowDead() {
|
||||||
|
Label allowedDeadLabel = createUnboundLabel();
|
||||||
|
bindLabel(allowedDeadLabel);
|
||||||
|
pseudocode.allowDead(allowedDeadLabel);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nondeterministicJump(Label label) {
|
public void nondeterministicJump(Label label) {
|
||||||
handleJumpInsideTryFinally(label);
|
handleJumpInsideTryFinally(label);
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ public class NondeterministicJumpInstruction extends InstructionImpl{
|
|||||||
private final Map<Label, Instruction> resolvedTargets;
|
private final Map<Label, Instruction> resolvedTargets;
|
||||||
|
|
||||||
public NondeterministicJumpInstruction(List<Label> targetLabels) {
|
public NondeterministicJumpInstruction(List<Label> targetLabels) {
|
||||||
this.targetLabels = targetLabels;
|
this.targetLabels = Lists.newArrayList(targetLabels);
|
||||||
resolvedTargets = Maps.newLinkedHashMap();
|
resolvedTargets = Maps.newLinkedHashMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,18 +44,20 @@ public class Pseudocode {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private List<Instruction> resolve() {
|
private List<Instruction> resolve() {
|
||||||
assert targetInstructionIndex != null;
|
assert targetInstructionIndex != null;
|
||||||
return instructions.subList(getTargetInstructionIndex(), instructions.size());
|
return mutableInstructionList.subList(getTargetInstructionIndex(), mutableInstructionList.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Instruction resolveToInstruction() {
|
public Instruction resolveToInstruction() {
|
||||||
assert targetInstructionIndex != null;
|
assert targetInstructionIndex != null;
|
||||||
return instructions.get(targetInstructionIndex);
|
return mutableInstructionList.get(targetInstructionIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>();
|
||||||
private final List<Instruction> instructions = new ArrayList<Instruction>();
|
private final List<Instruction> instructions = new ArrayList<Instruction>();
|
||||||
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
|
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
|
||||||
|
private final List<PseudocodeLabel> allowedDeadLabels = new ArrayList<PseudocodeLabel>();
|
||||||
|
|
||||||
private final JetElement correspondingElement;
|
private final JetElement correspondingElement;
|
||||||
private SubroutineExitInstruction exitInstruction;
|
private SubroutineExitInstruction exitInstruction;
|
||||||
@@ -75,11 +77,21 @@ public class Pseudocode {
|
|||||||
labels.add(label);
|
labels.add(label);
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void allowDead(Label label) {
|
||||||
|
allowedDeadLabels.add((PseudocodeLabel) label);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<Instruction> getInstructions() {
|
public List<Instruction> getInstructions() {
|
||||||
return instructions;
|
return instructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated //for tests only
|
||||||
|
@NotNull
|
||||||
|
public List<Instruction> getMutableInstructionList() {
|
||||||
|
return mutableInstructionList;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<Instruction> getDeadInstructions() {
|
public List<Instruction> getDeadInstructions() {
|
||||||
@@ -93,6 +105,7 @@ public class Pseudocode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated //for tests only
|
@Deprecated //for tests only
|
||||||
|
@NotNull
|
||||||
public List<PseudocodeLabel> getLabels() {
|
public List<PseudocodeLabel> getLabels() {
|
||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
@@ -110,7 +123,7 @@ public class Pseudocode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addInstruction(Instruction instruction) {
|
public void addInstruction(Instruction instruction) {
|
||||||
instructions.add(instruction);
|
mutableInstructionList.add(instruction);
|
||||||
instruction.setOwner(this);
|
instruction.setOwner(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,18 +140,18 @@ public class Pseudocode {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public SubroutineEnterInstruction getEnterInstruction() {
|
public SubroutineEnterInstruction getEnterInstruction() {
|
||||||
return (SubroutineEnterInstruction) instructions.get(0);
|
return (SubroutineEnterInstruction) mutableInstructionList.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindLabel(Label label) {
|
public void bindLabel(Label label) {
|
||||||
((PseudocodeLabel) label).setTargetInstructionIndex(instructions.size());
|
((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postProcess() {
|
public void postProcess() {
|
||||||
if (postPrecessed) return;
|
if (postPrecessed) return;
|
||||||
postPrecessed = true;
|
postPrecessed = true;
|
||||||
for (int i = 0, instructionsSize = instructions.size(); i < instructionsSize; i++) {
|
for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) {
|
||||||
Instruction instruction = instructions.get(i);
|
Instruction instruction = mutableInstructionList.get(i);
|
||||||
final int currentPosition = i;
|
final int currentPosition = i;
|
||||||
instruction.accept(new InstructionVisitor() {
|
instruction.accept(new InstructionVisitor() {
|
||||||
@Override
|
@Override
|
||||||
@@ -198,15 +211,20 @@ public class Pseudocode {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
getExitInstruction().setSink(getSinkInstruction());
|
getExitInstruction().setSink(getSinkInstruction());
|
||||||
removeDeadInstructions();
|
Set<Instruction> allowedDeadStartInstructions = prepareAllowedDeadInstructions();
|
||||||
|
markDeadInstructions();
|
||||||
|
Collection<Instruction> allowedDeadInstructions = collectAllowedDeadInstructions(allowedDeadStartInstructions);
|
||||||
|
instructions.addAll(mutableInstructionList);
|
||||||
|
instructions.removeAll(allowedDeadInstructions);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeDeadInstructions() {
|
private void markDeadInstructions() {
|
||||||
boolean hasRemovedInstruction = true;
|
boolean hasRemovedInstruction = true;
|
||||||
Collection<Instruction> processedInstructions = Sets.newHashSet();
|
Collection<Instruction> processedInstructions = Sets.newHashSet();
|
||||||
while (hasRemovedInstruction) {
|
while (hasRemovedInstruction) {
|
||||||
hasRemovedInstruction = false;
|
hasRemovedInstruction = false;
|
||||||
for (Instruction instruction : instructions) {
|
for (Instruction instruction : mutableInstructionList) {
|
||||||
if (!(instruction instanceof SubroutineEnterInstruction || instruction instanceof SubroutineExitInstruction || instruction instanceof SubroutineSinkInstruction) &&
|
if (!(instruction instanceof SubroutineEnterInstruction || instruction instanceof SubroutineExitInstruction || instruction instanceof SubroutineSinkInstruction) &&
|
||||||
instruction.getPreviousInstructions().isEmpty() && !processedInstructions.contains(instruction)) {
|
instruction.getPreviousInstructions().isEmpty() && !processedInstructions.contains(instruction)) {
|
||||||
hasRemovedInstruction = true;
|
hasRemovedInstruction = true;
|
||||||
@@ -220,6 +238,36 @@ public class Pseudocode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Set<Instruction> prepareAllowedDeadInstructions() {
|
||||||
|
Set<Instruction> allowedDeadStartInstructions = Sets.newHashSet();
|
||||||
|
for (PseudocodeLabel allowedDeadLabel : allowedDeadLabels) {
|
||||||
|
Instruction allowedDeadInstruction = getJumpTarget(allowedDeadLabel);
|
||||||
|
if (allowedDeadInstruction.getPreviousInstructions().isEmpty()) {
|
||||||
|
allowedDeadStartInstructions.add(allowedDeadInstruction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allowedDeadStartInstructions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Collection<Instruction> collectAllowedDeadInstructions(@NotNull Set<Instruction> allowedDeadStartInstructions) {
|
||||||
|
Set<Instruction> allowedDeadInstructions = Sets.newHashSet();
|
||||||
|
for (Instruction allowedDeadStartInstruction : allowedDeadStartInstructions) {
|
||||||
|
collectAllowedDeadInstructions(allowedDeadStartInstruction, allowedDeadInstructions);
|
||||||
|
}
|
||||||
|
return allowedDeadInstructions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void collectAllowedDeadInstructions(Instruction allowedDeadInstruction, Set<Instruction> instructionSet) {
|
||||||
|
if (allowedDeadInstruction.isDead()) {
|
||||||
|
instructionSet.add(allowedDeadInstruction);
|
||||||
|
for (Instruction instruction : allowedDeadInstruction.getNextInstructions()) {
|
||||||
|
collectAllowedDeadInstructions(instruction, instructionSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Instruction getJumpTarget(@NotNull Label targetLabel) {
|
private Instruction getJumpTarget(@NotNull Label targetLabel) {
|
||||||
return ((PseudocodeLabel)targetLabel).resolveToInstruction();
|
return ((PseudocodeLabel)targetLabel).resolveToInstruction();
|
||||||
@@ -228,7 +276,7 @@ public class Pseudocode {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private Instruction getNextPosition(int currentPosition) {
|
private Instruction getNextPosition(int currentPosition) {
|
||||||
int targetPosition = currentPosition + 1;
|
int targetPosition = currentPosition + 1;
|
||||||
assert targetPosition < instructions.size() : currentPosition;
|
assert targetPosition < mutableInstructionList.size() : currentPosition;
|
||||||
return instructions.get(targetPosition);
|
return mutableInstructionList.get(targetPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class TypeHierarchyResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection<? extends JetDeclaration> declarations) {
|
public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection<? extends JetDeclaration> declarations) {
|
||||||
collectNamespacesAndClassifiers(outerScope, owner, declarations); // namespaceScopes, classes
|
collectNamespacesAndClassifiers(outerScope, outerScope, owner, declarations); // namespaceScopes, classes
|
||||||
|
|
||||||
processTypeImports();
|
processTypeImports();
|
||||||
|
|
||||||
@@ -62,6 +62,7 @@ public class TypeHierarchyResolver {
|
|||||||
|
|
||||||
private void collectNamespacesAndClassifiers(
|
private void collectNamespacesAndClassifiers(
|
||||||
@NotNull final JetScope outerScope,
|
@NotNull final JetScope outerScope,
|
||||||
|
@NotNull final JetScope outerScopeForStatic,
|
||||||
@NotNull final NamespaceLike owner,
|
@NotNull final NamespaceLike owner,
|
||||||
@NotNull Collection<? extends JetDeclaration> declarations) {
|
@NotNull Collection<? extends JetDeclaration> declarations) {
|
||||||
for (JetDeclaration declaration : declarations) {
|
for (JetDeclaration declaration : declarations) {
|
||||||
@@ -89,7 +90,7 @@ public class TypeHierarchyResolver {
|
|||||||
|
|
||||||
// processImports(namespace, namespaceScope, outerScope);
|
// processImports(namespace, namespaceScope, outerScope);
|
||||||
|
|
||||||
collectNamespacesAndClassifiers(namespaceScope, namespaceDescriptor, namespace.getDeclarations());
|
collectNamespacesAndClassifiers(namespaceScope, namespaceScope, namespaceDescriptor, namespace.getDeclarations());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -116,7 +117,7 @@ public class TypeHierarchyResolver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
|
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
|
||||||
createClassDescriptorForObject(declaration, owner);
|
createClassDescriptorForObject(declaration, owner, outerScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -124,7 +125,7 @@ public class TypeHierarchyResolver {
|
|||||||
MutableClassDescriptor classObjectDescriptor = ((MutableClassDescriptor) owner).getClassObjectDescriptor();
|
MutableClassDescriptor classObjectDescriptor = ((MutableClassDescriptor) owner).getClassObjectDescriptor();
|
||||||
assert classObjectDescriptor != null : enumEntry.getParent().getText();
|
assert classObjectDescriptor != null : enumEntry.getParent().getText();
|
||||||
if (enumEntry.getPrimaryConstructorParameterList() == null) {
|
if (enumEntry.getPrimaryConstructorParameterList() == null) {
|
||||||
MutableClassDescriptor classDescriptor = createClassDescriptorForObject(enumEntry, classObjectDescriptor);
|
MutableClassDescriptor classDescriptor = createClassDescriptorForObject(enumEntry, classObjectDescriptor, outerScopeForStatic);
|
||||||
context.getObjects().remove(enumEntry);
|
context.getObjects().remove(enumEntry);
|
||||||
context.getClasses().put(enumEntry, classDescriptor);
|
context.getClasses().put(enumEntry, classDescriptor);
|
||||||
}
|
}
|
||||||
@@ -140,14 +141,14 @@ public class TypeHierarchyResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutableClassDescriptor createClassDescriptorForObject(@NotNull JetClassOrObject declaration, @NotNull NamespaceLike owner) {
|
private MutableClassDescriptor createClassDescriptorForObject(@NotNull JetClassOrObject declaration, @NotNull NamespaceLike owner, JetScope scope) {
|
||||||
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(context.getTrace(), owner, outerScope, ClassKind.OBJECT) {
|
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(context.getTrace(), owner, scope, ClassKind.OBJECT) {
|
||||||
@Override
|
@Override
|
||||||
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
||||||
return ClassObjectStatus.NOT_ALLOWED;
|
return ClassObjectStatus.NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
visitClassOrObject(declaration, (Map) context.getObjects(), owner, outerScope, mutableClassDescriptor);
|
visitClassOrObject(declaration, (Map) context.getObjects(), owner, scope, mutableClassDescriptor);
|
||||||
createPrimaryConstructorForObject((JetDeclaration) declaration, mutableClassDescriptor);
|
createPrimaryConstructorForObject((JetDeclaration) declaration, mutableClassDescriptor);
|
||||||
context.getTrace().record(BindingContext.CLASS, declaration, mutableClassDescriptor);
|
context.getTrace().record(BindingContext.CLASS, declaration, mutableClassDescriptor);
|
||||||
return mutableClassDescriptor;
|
return mutableClassDescriptor;
|
||||||
@@ -171,7 +172,7 @@ public class TypeHierarchyResolver {
|
|||||||
// declaringScopes.put((JetDeclaration) declaration, outerScope);
|
// declaringScopes.put((JetDeclaration) declaration, outerScope);
|
||||||
|
|
||||||
JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
|
JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
|
||||||
collectNamespacesAndClassifiers(classScope, mutableClassDescriptor, declaration.getDeclarations());
|
collectNamespacesAndClassifiers(classScope, outerScopeForStatic, mutableClassDescriptor, declaration.getDeclarations());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -184,7 +185,7 @@ public class TypeHierarchyResolver {
|
|||||||
public void visitClassObject(JetClassObject classObject) {
|
public void visitClassObject(JetClassObject classObject) {
|
||||||
JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
|
JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
|
||||||
if (objectDeclaration != null) {
|
if (objectDeclaration != null) {
|
||||||
NamespaceLike.ClassObjectStatus status = owner.setClassObjectDescriptor(createClassDescriptorForObject(objectDeclaration, owner));
|
NamespaceLike.ClassObjectStatus status = owner.setClassObjectDescriptor(createClassDescriptorForObject(objectDeclaration, owner, outerScopeForStatic));
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case DUPLICATE:
|
case DUPLICATE:
|
||||||
// context.getTrace().getErrorHandler().genericError(classObject.getNode(), "Only one class object is allowed per class");
|
// context.getTrace().getErrorHandler().genericError(classObject.getNode(), "Only one class object is allowed per class");
|
||||||
|
|||||||
+3
-1
@@ -441,7 +441,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
//TODO move further
|
//TODO move further
|
||||||
if (expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
|
if (expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
|
||||||
if (selectorReturnType != null && !selectorReturnType.isNullable() && !JetStandardClasses.isUnit(selectorReturnType)) {
|
if (selectorReturnType != null && !selectorReturnType.isNullable() && !JetStandardClasses.isUnit(selectorReturnType)) {
|
||||||
selectorReturnType = TypeUtils.makeNullable(selectorReturnType);
|
if (receiverType.isNullable()) {
|
||||||
|
selectorReturnType = TypeUtils.makeNullable(selectorReturnType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,17 +8,16 @@ fun t1() {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||||
r(1) NEXT:[r(2)] PREV:[jmp?(l2)]
|
|
||||||
l2:
|
l2:
|
||||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), r(1)]
|
r(2) NEXT:[<END>] PREV:[r(1)]
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||||
error:
|
error:
|
||||||
<ERROR> NEXT:[] PREV:[]
|
<ERROR> NEXT:[] PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> NEXT:[] PREV:[<END>]
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
=====================
|
=====================
|
||||||
== t2 ==
|
== t2 ==
|
||||||
fun t2() {
|
fun t2() {
|
||||||
@@ -33,22 +32,21 @@ fun t2() {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||||
r(1) NEXT:[r(2)] PREV:[jmp?(l2)]
|
|
||||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(2 > 3) NEXT:[jf(l3)] PREV:[r(>)]
|
r(2 > 3) NEXT:[jf(l2)] PREV:[r(>)]
|
||||||
jf(l3) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
jf(l2) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||||
r(2) NEXT:[ret l1] PREV:[jf(l3)]
|
r(2) NEXT:[ret l1] PREV:[jf(l2)]
|
||||||
ret l1 NEXT:[<END>] PREV:[r(2)]
|
ret l1 NEXT:[<END>] PREV:[r(2)]
|
||||||
* jmp(l4) NEXT:[r(2)] PREV:[]
|
* jmp(l3) NEXT:[r(2)] PREV:[]
|
||||||
l3:
|
|
||||||
read (Unit) NEXT:[r(2)] PREV:[jf(l3)]
|
|
||||||
l2:
|
l2:
|
||||||
|
read (Unit) NEXT:[r(2)] PREV:[jf(l2)]
|
||||||
|
l3:
|
||||||
l4:
|
l4:
|
||||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), read (Unit)]
|
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[ret l1, r(2)]
|
<END> NEXT:[<SINK>] PREV:[ret l1, r(2)]
|
||||||
error:
|
error:
|
||||||
@@ -63,20 +61,20 @@ sink:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l4:
|
l3:
|
||||||
<START> NEXT:[r(2)] PREV:[]
|
<START> NEXT:[r(2)] PREV:[]
|
||||||
r(2) NEXT:[r(3)] PREV:[<START>]
|
r(2) NEXT:[r(3)] PREV:[<START>]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
|
||||||
jf(l6) NEXT:[read (Unit), ret l5] PREV:[r(2 > 3)]
|
jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)]
|
||||||
ret l5 NEXT:[<END>] PREV:[jf(l6)]
|
ret l4 NEXT:[<END>] PREV:[jf(l5)]
|
||||||
* jmp(l7) NEXT:[<END>] PREV:[]
|
* jmp(l6) NEXT:[<END>] PREV:[]
|
||||||
l6:
|
|
||||||
read (Unit) NEXT:[<END>] PREV:[jf(l6)]
|
|
||||||
l5:
|
l5:
|
||||||
l7:
|
read (Unit) NEXT:[<END>] PREV:[jf(l5)]
|
||||||
<END> NEXT:[<SINK>] PREV:[ret l5, read (Unit)]
|
l4:
|
||||||
|
l6:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
|
||||||
error:
|
error:
|
||||||
<ERROR> NEXT:[] PREV:[]
|
<ERROR> NEXT:[] PREV:[]
|
||||||
sink:
|
sink:
|
||||||
@@ -97,43 +95,42 @@ fun t3() {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
r(1) NEXT:[jmp?(l2)] PREV:[<START>]
|
||||||
r(1) NEXT:[jmp?(l3)] PREV:[jmp?(l2)]
|
jmp?(l2) NEXT:[r({ () => if (2 > 3) { retur..), d({ () => if (2 > 3) { retur..)] PREV:[r(1)]
|
||||||
jmp?(l3) NEXT:[r({ () => if (2 > 3) { retur..), d({ () => if (2 > 3) { retur..)] PREV:[r(1)]
|
|
||||||
d({ () =>
|
d({ () =>
|
||||||
if (2 > 3) {
|
if (2 > 3) {
|
||||||
return@
|
return@
|
||||||
}
|
}
|
||||||
}) NEXT:[<SINK>] PREV:[jmp?(l3)]
|
}) NEXT:[<SINK>] PREV:[jmp?(l2)]
|
||||||
l3:
|
l2:
|
||||||
r({ () =>
|
r({ () =>
|
||||||
if (2 > 3) {
|
if (2 > 3) {
|
||||||
return@
|
return@
|
||||||
}
|
}
|
||||||
}) NEXT:[r(2)] PREV:[jmp?(l3)]
|
}) NEXT:[r(2)] PREV:[jmp?(l2)]
|
||||||
l2:
|
l7:
|
||||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), r({ () => if (2 > 3) { retur..)]
|
r(2) NEXT:[<END>] PREV:[r({ () => if (2 > 3) { retur..)]
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||||
error:
|
error:
|
||||||
<ERROR> NEXT:[] PREV:[]
|
<ERROR> NEXT:[] PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> NEXT:[] PREV:[d({ () => if (2 > 3) { retur..), <END>]
|
<SINK> NEXT:[] PREV:[d({ () => if (2 > 3) { retur..), <END>]
|
||||||
l4:
|
l3:
|
||||||
<START> NEXT:[r(2)] PREV:[]
|
<START> NEXT:[r(2)] PREV:[]
|
||||||
r(2) NEXT:[r(3)] PREV:[<START>]
|
r(2) NEXT:[r(3)] PREV:[<START>]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
|
||||||
jf(l6) NEXT:[read (Unit), ret l5] PREV:[r(2 > 3)]
|
jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)]
|
||||||
ret l5 NEXT:[<END>] PREV:[jf(l6)]
|
ret l4 NEXT:[<END>] PREV:[jf(l5)]
|
||||||
* jmp(l7) NEXT:[<END>] PREV:[]
|
* jmp(l6) NEXT:[<END>] PREV:[]
|
||||||
l6:
|
|
||||||
read (Unit) NEXT:[<END>] PREV:[jf(l6)]
|
|
||||||
l5:
|
l5:
|
||||||
l7:
|
read (Unit) NEXT:[<END>] PREV:[jf(l5)]
|
||||||
<END> NEXT:[<SINK>] PREV:[ret l5, read (Unit)]
|
l4:
|
||||||
|
l6:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
|
||||||
error:
|
error:
|
||||||
<ERROR> NEXT:[] PREV:[]
|
<ERROR> NEXT:[] PREV:[]
|
||||||
sink:
|
sink:
|
||||||
@@ -152,22 +149,21 @@ sink:
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l3:
|
l3:
|
||||||
<START> NEXT:[jmp?(l5)] PREV:[]
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
jmp?(l5) NEXT:[r(2), r(1)] PREV:[<START>]
|
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||||
r(1) NEXT:[r(2)] PREV:[jmp?(l5)]
|
|
||||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
|
||||||
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||||
r(2) NEXT:[ret l4] PREV:[jf(l6)]
|
r(2) NEXT:[ret l4] PREV:[jf(l5)]
|
||||||
ret l4 NEXT:[<END>] PREV:[r(2)]
|
ret l4 NEXT:[<END>] PREV:[r(2)]
|
||||||
* jmp(l7) NEXT:[r(2)] PREV:[]
|
* jmp(l6) NEXT:[r(2)] PREV:[]
|
||||||
l6:
|
|
||||||
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
|
||||||
l5:
|
l5:
|
||||||
|
read (Unit) NEXT:[r(2)] PREV:[jf(l5)]
|
||||||
|
l6:
|
||||||
l7:
|
l7:
|
||||||
r(2) NEXT:[<END>] PREV:[jmp?(l5), read (Unit)]
|
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||||
l4:
|
l4:
|
||||||
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
|
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
|
||||||
error:
|
error:
|
||||||
@@ -220,22 +216,21 @@ error:
|
|||||||
sink:
|
sink:
|
||||||
<SINK> NEXT:[] PREV:[d({ () => try { 1 if (2 > 3)..), <END>]
|
<SINK> NEXT:[] PREV:[d({ () => try { 1 if (2 > 3)..), <END>]
|
||||||
l3:
|
l3:
|
||||||
<START> NEXT:[jmp?(l5)] PREV:[]
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
jmp?(l5) NEXT:[r(2), r(1)] PREV:[<START>]
|
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||||
r(1) NEXT:[r(2)] PREV:[jmp?(l5)]
|
|
||||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
|
||||||
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||||
r(2) NEXT:[ret l4] PREV:[jf(l6)]
|
r(2) NEXT:[ret l4] PREV:[jf(l5)]
|
||||||
ret l4 NEXT:[<END>] PREV:[r(2)]
|
ret l4 NEXT:[<END>] PREV:[r(2)]
|
||||||
* jmp(l7) NEXT:[r(2)] PREV:[]
|
* jmp(l6) NEXT:[r(2)] PREV:[]
|
||||||
l6:
|
|
||||||
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
|
||||||
l5:
|
l5:
|
||||||
|
read (Unit) NEXT:[r(2)] PREV:[jf(l5)]
|
||||||
|
l6:
|
||||||
l7:
|
l7:
|
||||||
r(2) NEXT:[<END>] PREV:[jmp?(l5), read (Unit)]
|
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||||
l4:
|
l4:
|
||||||
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
|
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
|
||||||
error:
|
error:
|
||||||
@@ -258,36 +253,35 @@ fun t5() {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[r(true)] PREV:[]
|
<START> NEXT:[r(true)] PREV:[]
|
||||||
l2:
|
l2:
|
||||||
l5:
|
l5:
|
||||||
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
|
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
|
||||||
jf(l3) NEXT:[read (Unit), jmp?(l6)] PREV:[r(true)]
|
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||||
l4:
|
l4:
|
||||||
jmp?(l6) NEXT:[r(2), r(1)] PREV:[jf(l3)]
|
r(1) NEXT:[r(2)] PREV:[jf(l3)]
|
||||||
r(1) NEXT:[r(2)] PREV:[jmp?(l6)]
|
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||||
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
|
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||||
jf(l7) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
r(2) NEXT:[jmp(l3)] PREV:[jf(l6)]
|
||||||
r(2) NEXT:[jmp(l3)] PREV:[jf(l7)]
|
jmp(l3) NEXT:[read (Unit)] PREV:[r(2)]
|
||||||
jmp(l3) NEXT:[read (Unit)] PREV:[r(2)]
|
* jmp(l7) NEXT:[r(2)] PREV:[]
|
||||||
* jmp(l8) NEXT:[r(2)] PREV:[]
|
|
||||||
l7:
|
|
||||||
read (Unit) NEXT:[r(2)] PREV:[jf(l7)]
|
|
||||||
l6:
|
l6:
|
||||||
|
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
||||||
|
l7:
|
||||||
l8:
|
l8:
|
||||||
r(2) NEXT:[jmp(l2)] PREV:[jmp?(l6), read (Unit)]
|
r(2) NEXT:[jmp(l2)] PREV:[read (Unit)]
|
||||||
jmp(l2) NEXT:[r(true)] PREV:[r(2)]
|
jmp(l2) NEXT:[r(true)] PREV:[r(2)]
|
||||||
l3:
|
l3:
|
||||||
read (Unit) NEXT:[<END>] PREV:[jf(l3), jmp(l3)]
|
read (Unit) NEXT:[<END>] PREV:[jf(l3), jmp(l3)]
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||||
error:
|
error:
|
||||||
<ERROR> NEXT:[] PREV:[]
|
<ERROR> NEXT:[] PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> NEXT:[] PREV:[<END>]
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
=====================
|
=====================
|
||||||
== t6 ==
|
== t6 ==
|
||||||
fun t6() {
|
fun t6() {
|
||||||
@@ -305,30 +299,29 @@ fun t6() {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
<START> NEXT:[r(true)] PREV:[]
|
||||||
jmp?(l2) NEXT:[r(2), r(true)] PREV:[<START>]
|
l2:
|
||||||
l3:
|
|
||||||
l6:
|
|
||||||
r(true) NEXT:[jf(l4)] PREV:[jmp?(l2), jmp(l3)]
|
|
||||||
jf(l4) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
|
||||||
l5:
|
l5:
|
||||||
r(1) NEXT:[r(2)] PREV:[jf(l4)]
|
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
|
||||||
|
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||||
|
l4:
|
||||||
|
r(1) NEXT:[r(2)] PREV:[jf(l3)]
|
||||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
|
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||||
jf(l7) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
|
jf(l6) NEXT:[read (Unit), jmp(l3)] PREV:[r(2 > 3)]
|
||||||
jmp(l4) NEXT:[read (Unit)] PREV:[jf(l7)]
|
jmp(l3) NEXT:[read (Unit)] PREV:[jf(l6)]
|
||||||
* jmp(l8) NEXT:[jmp(l3)] PREV:[]
|
* jmp(l7) NEXT:[jmp(l2)] PREV:[]
|
||||||
|
l6:
|
||||||
|
read (Unit) NEXT:[jmp(l2)] PREV:[jf(l6)]
|
||||||
l7:
|
l7:
|
||||||
read (Unit) NEXT:[jmp(l3)] PREV:[jf(l7)]
|
jmp(l2) NEXT:[r(true)] PREV:[read (Unit)]
|
||||||
l8:
|
l3:
|
||||||
jmp(l3) NEXT:[r(true)] PREV:[read (Unit)]
|
read (Unit) NEXT:[r(5)] PREV:[jf(l3), jmp(l3)]
|
||||||
l4:
|
|
||||||
read (Unit) NEXT:[r(5)] PREV:[jf(l4), jmp(l4)]
|
|
||||||
r(5) NEXT:[r(2)] PREV:[read (Unit)]
|
r(5) NEXT:[r(2)] PREV:[read (Unit)]
|
||||||
l2:
|
l8:
|
||||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), r(5)]
|
r(2) NEXT:[<END>] PREV:[r(5)]
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||||
error:
|
error:
|
||||||
@@ -351,29 +344,28 @@ fun t7() {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
<START> NEXT:[r(true)] PREV:[]
|
||||||
jmp?(l2) NEXT:[r(2), r(true)] PREV:[<START>]
|
l2:
|
||||||
l3:
|
|
||||||
l6:
|
|
||||||
r(true) NEXT:[jf(l4)] PREV:[jmp?(l2), jmp(l3)]
|
|
||||||
jf(l4) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
|
||||||
l5:
|
l5:
|
||||||
r(1) NEXT:[r(2)] PREV:[jf(l4)]
|
r(true) NEXT:[jf(l3)] PREV:[<START>, jmp(l2)]
|
||||||
|
jf(l3) NEXT:[read (Unit), r(1)] PREV:[r(true)]
|
||||||
|
l4:
|
||||||
|
r(1) NEXT:[r(2)] PREV:[jf(l3)]
|
||||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
|
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||||
jf(l7) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
|
jf(l6) NEXT:[read (Unit), jmp(l3)] PREV:[r(2 > 3)]
|
||||||
jmp(l4) NEXT:[read (Unit)] PREV:[jf(l7)]
|
jmp(l3) NEXT:[read (Unit)] PREV:[jf(l6)]
|
||||||
* jmp(l8) NEXT:[jmp(l3)] PREV:[]
|
* jmp(l7) NEXT:[jmp(l2)] PREV:[]
|
||||||
|
l6:
|
||||||
|
read (Unit) NEXT:[jmp(l2)] PREV:[jf(l6)]
|
||||||
l7:
|
l7:
|
||||||
read (Unit) NEXT:[jmp(l3)] PREV:[jf(l7)]
|
jmp(l2) NEXT:[r(true)] PREV:[read (Unit)]
|
||||||
|
l3:
|
||||||
|
read (Unit) NEXT:[r(2)] PREV:[jf(l3), jmp(l3)]
|
||||||
l8:
|
l8:
|
||||||
jmp(l3) NEXT:[r(true)] PREV:[read (Unit)]
|
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||||
l4:
|
|
||||||
read (Unit) NEXT:[r(2)] PREV:[jf(l4), jmp(l4)]
|
|
||||||
l2:
|
|
||||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), read (Unit)]
|
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||||
error:
|
error:
|
||||||
@@ -396,40 +388,39 @@ fun t8(a : Int) {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[r(1)] PREV:[]
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
r(1) NEXT:[r(a)] PREV:[<START>]
|
r(1) NEXT:[r(a)] PREV:[<START>]
|
||||||
r(a) NEXT:[r(..)] PREV:[r(1)]
|
r(a) NEXT:[r(..)] PREV:[r(1)]
|
||||||
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
||||||
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
||||||
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
|
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
|
||||||
l3:
|
l3:
|
||||||
jmp?(l2) NEXT:[read (Unit), jmp?(l6)] PREV:[w(i)]
|
jmp?(l2) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
||||||
l4:
|
l4:
|
||||||
l5:
|
l5:
|
||||||
jmp?(l6) NEXT:[r(2), r(1)] PREV:[jmp?(l2), jmp(l4), jmp?(l4)]
|
r(1) NEXT:[r(2)] PREV:[jmp?(l2), jmp(l4), jmp?(l4)]
|
||||||
r(1) NEXT:[r(2)] PREV:[jmp?(l6)]
|
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||||
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
|
jf(l6) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
||||||
jf(l7) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
|
r(2) NEXT:[jmp(l4)] PREV:[jf(l6)]
|
||||||
r(2) NEXT:[jmp(l4)] PREV:[jf(l7)]
|
jmp(l4) NEXT:[r(1)] PREV:[r(2)]
|
||||||
jmp(l4) NEXT:[jmp?(l6)] PREV:[r(2)]
|
* jmp(l7) NEXT:[r(2)] PREV:[]
|
||||||
* jmp(l8) NEXT:[r(2)] PREV:[]
|
|
||||||
l7:
|
|
||||||
read (Unit) NEXT:[r(2)] PREV:[jf(l7)]
|
|
||||||
l6:
|
l6:
|
||||||
|
read (Unit) NEXT:[r(2)] PREV:[jf(l6)]
|
||||||
|
l7:
|
||||||
l8:
|
l8:
|
||||||
r(2) NEXT:[jmp?(l4)] PREV:[jmp?(l6), read (Unit)]
|
r(2) NEXT:[jmp?(l4)] PREV:[read (Unit)]
|
||||||
jmp?(l4) NEXT:[jmp?(l6), read (Unit)] PREV:[r(2)]
|
jmp?(l4) NEXT:[r(1), read (Unit)] PREV:[r(2)]
|
||||||
l2:
|
l2:
|
||||||
read (Unit) NEXT:[<END>] PREV:[jmp?(l2), jmp?(l4)]
|
read (Unit) NEXT:[<END>] PREV:[jmp?(l2), jmp?(l4)]
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||||
error:
|
error:
|
||||||
<ERROR> NEXT:[] PREV:[]
|
<ERROR> NEXT:[] PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> NEXT:[] PREV:[<END>]
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
=====================
|
=====================
|
||||||
== t9 ==
|
== t9 ==
|
||||||
fun t9(a : Int) {
|
fun t9(a : Int) {
|
||||||
@@ -447,34 +438,33 @@ fun t9(a : Int) {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
r(1) NEXT:[r(a)] PREV:[<START>]
|
||||||
r(1) NEXT:[r(a)] PREV:[jmp?(l2)]
|
|
||||||
r(a) NEXT:[r(..)] PREV:[r(1)]
|
r(a) NEXT:[r(..)] PREV:[r(1)]
|
||||||
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
||||||
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
||||||
w(i) NEXT:[jmp?(l3)] PREV:[r(1..a)]
|
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
|
||||||
|
l3:
|
||||||
|
jmp?(l2) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
||||||
l4:
|
l4:
|
||||||
jmp?(l3) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
|
||||||
l5:
|
l5:
|
||||||
l6:
|
r(1) NEXT:[r(2)] PREV:[jmp?(l2), jmp(l4), jmp?(l4)]
|
||||||
r(1) NEXT:[r(2)] PREV:[jmp?(l3), jmp(l5), jmp?(l5)]
|
|
||||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
|
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||||
jf(l7) NEXT:[read (Unit), jmp(l5)] PREV:[r(2 > 3)]
|
jf(l6) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
|
||||||
jmp(l5) NEXT:[r(1)] PREV:[jf(l7)]
|
jmp(l4) NEXT:[r(1)] PREV:[jf(l6)]
|
||||||
* jmp(l8) NEXT:[jmp?(l5)] PREV:[]
|
* jmp(l7) NEXT:[jmp?(l4)] PREV:[]
|
||||||
|
l6:
|
||||||
|
read (Unit) NEXT:[jmp?(l4)] PREV:[jf(l6)]
|
||||||
l7:
|
l7:
|
||||||
read (Unit) NEXT:[jmp?(l5)] PREV:[jf(l7)]
|
jmp?(l4) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
|
||||||
l8:
|
|
||||||
jmp?(l5) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
|
|
||||||
l3:
|
|
||||||
read (Unit) NEXT:[r(5)] PREV:[jmp?(l3), jmp?(l5)]
|
|
||||||
r(5) NEXT:[r(2)] PREV:[read (Unit)]
|
|
||||||
l2:
|
l2:
|
||||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), r(5)]
|
read (Unit) NEXT:[r(5)] PREV:[jmp?(l2), jmp?(l4)]
|
||||||
|
r(5) NEXT:[r(2)] PREV:[read (Unit)]
|
||||||
|
l8:
|
||||||
|
r(2) NEXT:[<END>] PREV:[r(5)]
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||||
error:
|
error:
|
||||||
@@ -497,33 +487,32 @@ fun t10(a : Int) {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
r(1) NEXT:[r(a)] PREV:[<START>]
|
||||||
r(1) NEXT:[r(a)] PREV:[jmp?(l2)]
|
|
||||||
r(a) NEXT:[r(..)] PREV:[r(1)]
|
r(a) NEXT:[r(..)] PREV:[r(1)]
|
||||||
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
r(..) NEXT:[r(1..a)] PREV:[r(a)]
|
||||||
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
r(1..a) NEXT:[w(i)] PREV:[r(..)]
|
||||||
w(i) NEXT:[jmp?(l3)] PREV:[r(1..a)]
|
w(i) NEXT:[jmp?(l2)] PREV:[r(1..a)]
|
||||||
|
l3:
|
||||||
|
jmp?(l2) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
||||||
l4:
|
l4:
|
||||||
jmp?(l3) NEXT:[read (Unit), r(1)] PREV:[w(i)]
|
|
||||||
l5:
|
l5:
|
||||||
l6:
|
r(1) NEXT:[r(2)] PREV:[jmp?(l2), jmp(l4), jmp?(l4)]
|
||||||
r(1) NEXT:[r(2)] PREV:[jmp?(l3), jmp(l5), jmp?(l5)]
|
|
||||||
r(2) NEXT:[r(3)] PREV:[r(1)]
|
r(2) NEXT:[r(3)] PREV:[r(1)]
|
||||||
r(3) NEXT:[r(>)] PREV:[r(2)]
|
r(3) NEXT:[r(>)] PREV:[r(2)]
|
||||||
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
|
||||||
r(2 > 3) NEXT:[jf(l7)] PREV:[r(>)]
|
r(2 > 3) NEXT:[jf(l6)] PREV:[r(>)]
|
||||||
jf(l7) NEXT:[read (Unit), jmp(l5)] PREV:[r(2 > 3)]
|
jf(l6) NEXT:[read (Unit), jmp(l4)] PREV:[r(2 > 3)]
|
||||||
jmp(l5) NEXT:[r(1)] PREV:[jf(l7)]
|
jmp(l4) NEXT:[r(1)] PREV:[jf(l6)]
|
||||||
* jmp(l8) NEXT:[jmp?(l5)] PREV:[]
|
* jmp(l7) NEXT:[jmp?(l4)] PREV:[]
|
||||||
|
l6:
|
||||||
|
read (Unit) NEXT:[jmp?(l4)] PREV:[jf(l6)]
|
||||||
l7:
|
l7:
|
||||||
read (Unit) NEXT:[jmp?(l5)] PREV:[jf(l7)]
|
jmp?(l4) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
|
||||||
l8:
|
|
||||||
jmp?(l5) NEXT:[r(1), read (Unit)] PREV:[read (Unit)]
|
|
||||||
l3:
|
|
||||||
read (Unit) NEXT:[r(2)] PREV:[jmp?(l3), jmp?(l5)]
|
|
||||||
l2:
|
l2:
|
||||||
r(2) NEXT:[<END>] PREV:[jmp?(l2), read (Unit)]
|
read (Unit) NEXT:[r(2)] PREV:[jmp?(l2), jmp?(l4)]
|
||||||
|
l8:
|
||||||
|
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||||
error:
|
error:
|
||||||
@@ -542,19 +531,221 @@ fun t11() {
|
|||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
l0:
|
l0:
|
||||||
<START> NEXT:[jmp?(l2)] PREV:[]
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
jmp?(l2) NEXT:[r(2), r(1)] PREV:[<START>]
|
r(1) NEXT:[r(2)] PREV:[<START>]
|
||||||
r(1) NEXT:[r(2)] PREV:[jmp?(l2)]
|
r(2) NEXT:[ret(*) l1] PREV:[r(1)]
|
||||||
r(2) NEXT:[ret(*) l1] PREV:[r(1)]
|
ret(*) l1 NEXT:[<END>] PREV:[r(2)]
|
||||||
ret(*) l1 NEXT:[<END>] PREV:[r(2)]
|
* ret(*) l1 NEXT:[<END>] PREV:[]
|
||||||
* ret(*) l1 NEXT:[<END>] PREV:[]
|
|
||||||
l2:
|
l2:
|
||||||
r(2) NEXT:[ret(*) l1] PREV:[jmp?(l2)]
|
R r(2) NEXT:[ret(*) l1] PREV:[]
|
||||||
ret(*) l1 NEXT:[<END>] PREV:[r(2)]
|
R ret(*) l1 NEXT:[<END>] PREV:[]
|
||||||
l1:
|
l1:
|
||||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, ret(*) l1]
|
<END> NEXT:[<SINK>] PREV:[ret(*) l1]
|
||||||
error:
|
error:
|
||||||
<ERROR> NEXT:[] PREV:[]
|
<ERROR> NEXT:[] PREV:[]
|
||||||
sink:
|
sink:
|
||||||
<SINK> NEXT:[] PREV:[<END>]
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
|
=====================
|
||||||
|
== t12 ==
|
||||||
|
fun t12() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
l0:
|
||||||
|
<START> NEXT:[r(1)] PREV:[]
|
||||||
|
r(1) NEXT:[r(3)] PREV:[<START>]
|
||||||
|
r(3) NEXT:[r(doSmth)] PREV:[r(1)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||||
|
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||||
|
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||||
|
l2:
|
||||||
|
R r(3) NEXT:[r(doSmth)] PREV:[]
|
||||||
|
R r(doSmth) NEXT:[r(doSmth(3))] PREV:[]
|
||||||
|
R r(doSmth(3)) NEXT:[<END>] PREV:[]
|
||||||
|
l1:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[ret(*) l1]
|
||||||
|
error:
|
||||||
|
<ERROR> NEXT:[] PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
|
=====================
|
||||||
|
== t13 ==
|
||||||
|
fun t13() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
doSmth(2)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
l0:
|
||||||
|
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||||
|
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
|
||||||
|
r(1) NEXT:[r(3)] PREV:[jmp?(l2)]
|
||||||
|
r(3) NEXT:[r(doSmth)] PREV:[r(1)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||||
|
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||||
|
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||||
|
l3:
|
||||||
|
R jmp(l4) NEXT:[r(3)] PREV:[]
|
||||||
|
l2:
|
||||||
|
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
|
||||||
|
w(e) NEXT:[r(2)] PREV:[jmp?()]
|
||||||
|
r(2) NEXT:[r(doSmth)] PREV:[w(e)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(2))] PREV:[r(2)]
|
||||||
|
r(doSmth(2)) NEXT:[jmp(l4)] PREV:[r(doSmth)]
|
||||||
|
l5:
|
||||||
|
jmp(l4) NEXT:[r(3)] PREV:[r(doSmth(2))]
|
||||||
|
l4:
|
||||||
|
r(3) NEXT:[r(doSmth)] PREV:[jmp(l4)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||||
|
r(doSmth(3)) NEXT:[<END>] PREV:[r(doSmth)]
|
||||||
|
l1:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
|
||||||
|
error:
|
||||||
|
<ERROR> NEXT:[] PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
|
=====================
|
||||||
|
== t14 ==
|
||||||
|
fun t14() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
doSmth(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
l0:
|
||||||
|
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||||
|
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
|
||||||
|
r(1) NEXT:[ret(*) l1] PREV:[jmp?(l2)]
|
||||||
|
ret(*) l1 NEXT:[<END>] PREV:[r(1)]
|
||||||
|
l3:
|
||||||
|
R jmp(l4) NEXT:[<END>] PREV:[]
|
||||||
|
l2:
|
||||||
|
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
|
||||||
|
w(e) NEXT:[r(2)] PREV:[jmp?()]
|
||||||
|
r(2) NEXT:[r(doSmth)] PREV:[w(e)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(2))] PREV:[r(2)]
|
||||||
|
r(doSmth(2)) NEXT:[jmp(l4)] PREV:[r(doSmth)]
|
||||||
|
l5:
|
||||||
|
jmp(l4) NEXT:[<END>] PREV:[r(doSmth(2))]
|
||||||
|
l1:
|
||||||
|
l4:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[ret(*) l1, jmp(l4)]
|
||||||
|
error:
|
||||||
|
<ERROR> NEXT:[] PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
|
=====================
|
||||||
|
== t15 ==
|
||||||
|
fun t15() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
l0:
|
||||||
|
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||||
|
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
|
||||||
|
r(1) NEXT:[r(3)] PREV:[jmp?(l2)]
|
||||||
|
r(3) NEXT:[r(doSmth)] PREV:[r(1)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||||
|
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||||
|
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||||
|
l3:
|
||||||
|
R jmp(l4) NEXT:[r(3)] PREV:[]
|
||||||
|
l2:
|
||||||
|
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
|
||||||
|
w(e) NEXT:[r(2)] PREV:[jmp?()]
|
||||||
|
r(2) NEXT:[r(3)] PREV:[w(e)]
|
||||||
|
r(3) NEXT:[r(doSmth)] PREV:[r(2)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||||
|
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||||
|
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||||
|
l5:
|
||||||
|
R jmp(l4) NEXT:[r(3)] PREV:[]
|
||||||
|
l4:
|
||||||
|
R r(3) NEXT:[r(doSmth)] PREV:[]
|
||||||
|
R r(doSmth) NEXT:[r(doSmth(3))] PREV:[]
|
||||||
|
R r(doSmth(3)) NEXT:[<END>] PREV:[]
|
||||||
|
l1:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[ret(*) l1, ret(*) l1]
|
||||||
|
error:
|
||||||
|
<ERROR> NEXT:[] PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
|
=====================
|
||||||
|
== t16 ==
|
||||||
|
fun t16() : Int {
|
||||||
|
try {
|
||||||
|
doSmth(1)
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
l0:
|
||||||
|
<START> NEXT:[jmp?(l2)] PREV:[]
|
||||||
|
jmp?(l2) NEXT:[jmp?(), r(1)] PREV:[<START>]
|
||||||
|
r(1) NEXT:[r(doSmth)] PREV:[jmp?(l2)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(1))] PREV:[r(1)]
|
||||||
|
r(doSmth(1)) NEXT:[jmp(l4)] PREV:[r(doSmth)]
|
||||||
|
l3:
|
||||||
|
jmp(l4) NEXT:[r(3)] PREV:[r(doSmth(1))]
|
||||||
|
l2:
|
||||||
|
jmp?() NEXT:[w(e)] PREV:[jmp?(l2)]
|
||||||
|
w(e) NEXT:[r(2)] PREV:[jmp?()]
|
||||||
|
r(2) NEXT:[r(3)] PREV:[w(e)]
|
||||||
|
r(3) NEXT:[r(doSmth)] PREV:[r(2)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||||
|
r(doSmth(3)) NEXT:[ret(*) l1] PREV:[r(doSmth)]
|
||||||
|
ret(*) l1 NEXT:[<END>] PREV:[r(doSmth(3))]
|
||||||
|
l5:
|
||||||
|
R jmp(l4) NEXT:[r(3)] PREV:[]
|
||||||
|
l4:
|
||||||
|
r(3) NEXT:[r(doSmth)] PREV:[jmp(l4)]
|
||||||
|
r(doSmth) NEXT:[r(doSmth(3))] PREV:[r(3)]
|
||||||
|
r(doSmth(3)) NEXT:[<END>] PREV:[r(doSmth)]
|
||||||
|
l1:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
|
||||||
|
error:
|
||||||
|
<ERROR> NEXT:[] PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
|
=====================
|
||||||
|
== doSmth ==
|
||||||
|
fun doSmth(i: Int) {
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
l0:
|
||||||
|
<START> NEXT:[read (Unit)] PREV:[]
|
||||||
|
read (Unit) NEXT:[<END>] PREV:[<START>]
|
||||||
|
l1:
|
||||||
|
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||||
|
error:
|
||||||
|
<ERROR> NEXT:[] PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> NEXT:[] PREV:[<END>]
|
||||||
=====================
|
=====================
|
||||||
|
|||||||
@@ -130,4 +130,62 @@ fun t11() {
|
|||||||
finally {
|
finally {
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t12() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t13() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
doSmth(2)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t14() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
doSmth(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun t15() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t16() : Int {
|
||||||
|
try {
|
||||||
|
doSmth(1)
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doSmth(i: Int) {
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
//KT-58 Allow finally around definite returns
|
||||||
|
|
||||||
|
namespace kt58
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.Lock
|
||||||
|
|
||||||
|
fun lock<T>(lock : Lock, body : fun () : T) : T {
|
||||||
|
lock.lock()
|
||||||
|
try {
|
||||||
|
return body()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock(); // we report an error, but we chouldn't
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//more tests
|
||||||
|
fun t1() : Int {
|
||||||
|
try {
|
||||||
|
<!UNREACHABLE_CODE!>return 1<!>
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t2() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t3() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
doSmth(2)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>doSmth(3)<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t4() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>doSmth(2)<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t5() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t6() : Int {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
doSmth(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t7() : Int {
|
||||||
|
try {
|
||||||
|
doSmth(1)
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedOperationException) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>doSmth(3)<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doSmth(i: Int) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// http://youtrack.jetbrains.net/issue/KT-20
|
||||||
|
|
||||||
|
class A() {
|
||||||
|
val x = 1
|
||||||
|
|
||||||
|
class object {
|
||||||
|
val y = <!UNRESOLVED_REFERENCE!>x<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// http://youtrack.jetbrains.net/issue/KT-418
|
||||||
|
|
||||||
|
fun ff() {
|
||||||
|
val i: Int = 1
|
||||||
|
val a: Int = i<!UNNECESSARY_SAFE_CALL!>?.<!>plus(2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun Int.gg() = null
|
||||||
|
|
||||||
|
fun ff() {
|
||||||
|
val a: Int = 1
|
||||||
|
val b: Int = <!TYPE_MISMATCH!>a<!UNNECESSARY_SAFE_CALL!>?.<!>gg()<!>
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
class Request(val path: String) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Handler() {
|
||||||
|
fun Int.times(op: fun(): Unit) {
|
||||||
|
for(i in 0..this)
|
||||||
|
op()
|
||||||
|
}
|
||||||
|
|
||||||
|
// fun Request.getPath() : String {
|
||||||
|
// val sb = java.lang.StringBuilder()
|
||||||
|
// 10.times {
|
||||||
|
// sb.append(path)?.append(this)
|
||||||
|
// }
|
||||||
|
// return sb.toString() as String
|
||||||
|
// }
|
||||||
|
|
||||||
|
fun Request.getPath() = path
|
||||||
|
|
||||||
|
fun test(request: Request) = request.getPath()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String = if(Handler().test(Request("239")) == "239") "OK" else "fail"
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jetbrains.jet.cfg;
|
package org.jetbrains.jet.cfg;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
@@ -125,7 +126,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
instructionDump.append("=====================\n");
|
instructionDump.append("=====================\n");
|
||||||
|
|
||||||
//check edges directions
|
//check edges directions
|
||||||
Collection<Instruction> instructions = pseudocode.getInstructions();
|
Collection<Instruction> instructions = pseudocode.getMutableInstructionList();
|
||||||
for (Instruction instruction : instructions) {
|
for (Instruction instruction : instructions) {
|
||||||
if (!instruction.isDead()) {
|
if (!instruction.isDead()) {
|
||||||
for (Instruction nextInstruction : instruction.getNextInstructions()) {
|
for (Instruction nextInstruction : instruction.getNextInstructions()) {
|
||||||
@@ -157,7 +158,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dfsDump(Pseudocode pseudocode, StringBuilder nodes, StringBuilder edges, Map<Instruction, String> nodeNames) {
|
public void dfsDump(Pseudocode pseudocode, StringBuilder nodes, StringBuilder edges, Map<Instruction, String> nodeNames) {
|
||||||
dfsDump(nodes, edges, pseudocode.getInstructions().get(0), nodeNames);
|
dfsDump(nodes, edges, pseudocode.getMutableInstructionList().get(0), nodeNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map<Instruction, String> nodeNames) {
|
private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map<Instruction, String> nodeNames) {
|
||||||
@@ -172,9 +173,10 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatInstruction(Instruction instruction, int maxLength) {
|
private static String formatInstruction(Instruction instruction, int maxLength, Set<Instruction> remainedAfterPostProcessInstructions) {
|
||||||
String[] parts = instruction.toString().split("\n");
|
String[] parts = instruction.toString().split("\n");
|
||||||
String prefix = instruction.isDead() ? "* " : " ";
|
boolean isRemovedThroughPostProcess = !remainedAfterPostProcessInstructions.contains(instruction);
|
||||||
|
String prefix = isRemovedThroughPostProcess ? "R " : instruction.isDead() ? "* " : " ";
|
||||||
if (parts.length == 1) {
|
if (parts.length == 1) {
|
||||||
return prefix + String.format("%1$-" + maxLength + "s", instruction);
|
return prefix + String.format("%1$-" + maxLength + "s", instruction);
|
||||||
}
|
}
|
||||||
@@ -218,7 +220,8 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dumpInstructions(Pseudocode pseudocode, @NotNull StringBuilder out) {
|
public void dumpInstructions(Pseudocode pseudocode, @NotNull StringBuilder out) {
|
||||||
List<Instruction> instructions = pseudocode.getInstructions();
|
List<Instruction> instructions = pseudocode.getMutableInstructionList();
|
||||||
|
Set<Instruction> remainedAfterPostProcessInstructions = Sets.newHashSet(pseudocode.getInstructions());
|
||||||
List<Pseudocode.PseudocodeLabel> labels = pseudocode.getLabels();
|
List<Pseudocode.PseudocodeLabel> labels = pseudocode.getLabels();
|
||||||
List<Pseudocode> locals = new ArrayList<Pseudocode>();
|
List<Pseudocode> locals = new ArrayList<Pseudocode>();
|
||||||
int maxLength = 0;
|
int maxLength = 0;
|
||||||
@@ -257,7 +260,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.append(formatInstruction(instruction, maxLength)).
|
out.append(formatInstruction(instruction, maxLength, remainedAfterPostProcessInstructions)).
|
||||||
append(" NEXT:").append(String.format("%1$-" + maxNextLength + "s", formatInstructionList(instruction.getNextInstructions()))).
|
append(" NEXT:").append(String.format("%1$-" + maxNextLength + "s", formatInstructionList(instruction.getNextInstructions()))).
|
||||||
append(" PREV:").append(formatInstructionList(instruction.getPreviousInstructions())).append("\n");
|
append(" PREV:").append(formatInstructionList(instruction.getPreviousInstructions())).append("\n");
|
||||||
}
|
}
|
||||||
@@ -273,7 +276,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) {
|
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) {
|
||||||
int index = count[0];
|
int index = count[0];
|
||||||
// instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName);
|
// instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName);
|
||||||
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().getInstructions().get(0)), null);
|
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().getMutableInstructionList().get(0)), null);
|
||||||
visitInstructionWithNext(instruction);
|
visitInstructionWithNext(instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +339,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dumpNodes(List<Instruction> instructions, PrintStream out, int[] count, Map<Instruction, String> nodeToName) {
|
public void dumpNodes(List<Instruction> instructions, PrintStream out, int[] count, Map<Instruction, String> nodeToName, Set<Instruction> remainedAfterPostProcessInstructions) {
|
||||||
for (Instruction node : instructions) {
|
for (Instruction node : instructions) {
|
||||||
String name = "n" + count[0]++;
|
String name = "n" + count[0]++;
|
||||||
nodeToName.put(node, name);
|
nodeToName.put(node, name);
|
||||||
@@ -361,6 +364,9 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
else if (node instanceof SubroutineEnterInstruction || node instanceof SubroutineExitInstruction) {
|
else if (node instanceof SubroutineEnterInstruction || node instanceof SubroutineExitInstruction) {
|
||||||
shape = "roundrect, style=rounded";
|
shape = "roundrect, style=rounded";
|
||||||
}
|
}
|
||||||
|
if (!remainedAfterPostProcessInstructions.contains(node)) {
|
||||||
|
shape += "box, fillcolor=grey, style=filled";
|
||||||
|
}
|
||||||
out.println(name + "[label=\"" + text + "\", shape=" + shape + "];");
|
out.println(name + "[label=\"" + text + "\", shape=" + shape + "];");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -385,7 +391,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
int[] count = new int[1];
|
int[] count = new int[1];
|
||||||
Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
|
Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
|
||||||
for (Pseudocode pseudocode : pseudocodes) {
|
for (Pseudocode pseudocode : pseudocodes) {
|
||||||
dumpNodes(pseudocode.getInstructions(), out, count, nodeToName);
|
dumpNodes(pseudocode.getMutableInstructionList(), out, count, nodeToName, Sets.newHashSet(pseudocode.getInstructions()));
|
||||||
}
|
}
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Pseudocode pseudocode : pseudocodes) {
|
for (Pseudocode pseudocode : pseudocodes) {
|
||||||
@@ -401,7 +407,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
|||||||
out.println("subgraph cluster_" + i + " {\n" +
|
out.println("subgraph cluster_" + i + " {\n" +
|
||||||
"label=\"" + label + "\";\n" +
|
"label=\"" + label + "\";\n" +
|
||||||
"color=blue;\n");
|
"color=blue;\n");
|
||||||
dumpEdges(pseudocode.getInstructions(), out, count, nodeToName);
|
dumpEdges(pseudocode.getMutableInstructionList(), out, count, nodeToName);
|
||||||
out.println("}");
|
out.println("}");
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import java.lang.reflect.Method;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class ExtensionFunctionsTest extends CodegenTestCase {
|
public class ExtensionFunctionsTest extends CodegenTestCase {
|
||||||
@Override
|
@Override
|
||||||
@@ -27,4 +28,8 @@ public class ExtensionFunctionsTest extends CodegenTestCase {
|
|||||||
public void testGeneric() throws Exception {
|
public void testGeneric() throws Exception {
|
||||||
blackBoxFile("extensionFunctions/generic.jet");
|
blackBoxFile("extensionFunctions/generic.jet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testVirtual() throws Exception {
|
||||||
|
blackBoxFile("extensionFunctions/virtual.jet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public class PropertyGenTest extends CodegenTestCase {
|
|||||||
|
|
||||||
public void testFieldPropertyAccess() throws Exception {
|
public void testFieldPropertyAccess() throws Exception {
|
||||||
loadFile("properties/fieldPropertyAccess.jet");
|
loadFile("properties/fieldPropertyAccess.jet");
|
||||||
|
System.out.println(generateToText());
|
||||||
final Method method = generateFunction();
|
final Method method = generateFunction();
|
||||||
assertEquals(1, method.invoke(null));
|
assertEquals(1, method.invoke(null));
|
||||||
assertEquals(2, method.invoke(null));
|
assertEquals(2, method.invoke(null));
|
||||||
|
|||||||
Reference in New Issue
Block a user