JS backend: don't aliasing captured variable foo as foo.v.

Moved isVarCapturedInClosure from CodegenBinding to BindingContextUtils.
This commit is contained in:
Zalim Bashorov
2014-02-27 14:33:47 +04:00
parent d55548a1c8
commit 48a28ed406
9 changed files with 47 additions and 22 deletions
@@ -47,6 +47,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.evaluate.EvaluatePackage;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.model.*;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
@@ -75,6 +76,7 @@ import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionImplType;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
@@ -319,12 +319,6 @@ public class CodegenBinding {
return containerInternalName + "$" + klass.getName().getIdentifier();
}
public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false;
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null && variableDescriptor.isVar();
}
public static boolean hasThis0(BindingContext bindingContext, ClassDescriptor classDescriptor) {
//noinspection SuspiciousMethodCalls
CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
@@ -55,6 +55,7 @@ import static org.jetbrains.jet.codegen.AsmUtil.getTraitImplThisParameterType;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionTraitClassName;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
@@ -40,6 +40,7 @@ import java.util.*;
import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.AMBIGUOUS_LABEL;
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_LABEL_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE;
import static org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR;
public class BindingContextUtils {
@@ -363,4 +364,10 @@ public class BindingContextUtils {
}
return result;
}
public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false;
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null && variableDescriptor.isVar();
}
}
@@ -19,14 +19,12 @@ package org.jetbrains.k2js.translate.callTranslator
import com.google.dart.compiler.backend.js.ast.JsExpression
import com.google.dart.compiler.backend.js.ast.JsNameRef
import com.google.dart.compiler.backend.js.ast.JsLiteral
import org.jetbrains.k2js.translate.utils.JsAstUtils
import com.google.dart.compiler.backend.js.ast.JsInvocation
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
import java.util.Collections
import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.jet.lang.resolve.DescriptorFactory
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
import org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure
import org.jetbrains.k2js.translate.context.Namer.getCapturedVarAccessor
object NativeVariableAccessCase : VariableAccessCase {
@@ -39,7 +37,7 @@ object NativeVariableAccessCase : VariableAccessCase {
}
override fun VariableAccessInfo.noReceivers(): JsExpression {
return constructAccessExpression(variableName.makeRef()!!)
return constructAccessExpression(variableName.makeRef())
}
}
@@ -48,7 +46,15 @@ object DefaultVariableAccessCase : VariableAccessCase {
val functionRef = context.aliasOrValue(callableDescriptor) {
context.getQualifiedReference(variableDescriptor)
}
return constructAccessExpression(functionRef)
val ref =
if (isVarCapturedInClosure(context.bindingContext(), callableDescriptor)) {
getCapturedVarAccessor(functionRef)
} else {
functionRef
}
return constructAccessExpression(ref)
}
override fun VariableAccessInfo.thisObject(): JsExpression {
@@ -52,6 +52,7 @@ public final class Namer {
private static final String CLASS_OBJECT_GETTER = "object";
private static final String CLASS_OBJECT_INITIALIZER = "object_initializer$";
private static final String PROTOTYPE_NAME = "prototype";
public static final String CAPTURED_VAR_FIELD = "v";
private static final String DELEGATE_POSTFIX = "$delegate";
@@ -144,6 +145,11 @@ public final class Namer {
return new JsNameRef(APPLY_FUNCTION, functionExpression);
}
@NotNull
public static JsNameRef getCapturedVarAccessor(@NotNull JsExpression ref) {
return new JsNameRef(CAPTURED_VAR_FIELD, ref);
}
@NotNull
public static Namer newInstance(@NotNull JsScope rootScope) {
return new Namer(rootScope);
@@ -21,6 +21,7 @@ import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
@@ -37,7 +38,10 @@ import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.general.TranslatorVisitor;
import org.jetbrains.k2js.translate.operation.BinaryOperationTranslator;
import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator;
import org.jetbrains.k2js.translate.reference.*;
import org.jetbrains.k2js.translate.reference.AccessTranslationUtils;
import org.jetbrains.k2js.translate.reference.CallExpressionTranslator;
import org.jetbrains.k2js.translate.reference.QualifiedExpressionTranslator;
import org.jetbrains.k2js.translate.reference.ReferenceTranslator;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
@@ -45,6 +49,8 @@ import org.jetbrains.k2js.translate.utils.mutator.AssignToExpressionMutator;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure;
import static org.jetbrains.k2js.translate.context.Namer.getCapturedVarAccessor;
import static org.jetbrains.k2js.translate.general.Translation.translateAsExpression;
import static org.jetbrains.k2js.translate.reference.ReferenceTranslator.translateAsFQReference;
import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
@@ -121,7 +127,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
}
@Override
public JsNode visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, @NotNull TranslationContext context) {
public JsNode visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, @NotNull TranslationContext context) {
JetExpression jetInitializer = multiDeclaration.getInitializer();
assert jetInitializer != null : "Initializer for multi declaration must be not null";
JsExpression initializer = Translation.translateAsExpression(jetInitializer, context);
@@ -164,11 +170,9 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
VariableDescriptor descriptor = BindingContextUtils.getNotNull(context.bindingContext(), BindingContext.VARIABLE, expression);
JsExpression initializer = translateInitializerForProperty(expression, context);
JsName name = context.getNameForDescriptor(descriptor);
if (descriptor.isVar() && context.bindingContext().get(BindingContext.CAPTURED_IN_CLOSURE, descriptor) != null) {
// well, wrap it
JsNameRef alias = new JsNameRef("v", new JsNameRef(name));
if (isVarCapturedInClosure(context.bindingContext(), descriptor)) {
JsNameRef alias = getCapturedVarAccessor(name.makeRef());
initializer = JsAstUtils.wrapValue(alias, initializer == null ? JsLiteral.NULL : initializer);
context.aliasingContext().registerAlias(descriptor, alias);
}
return newVar(name, initializer).source(expression);
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
@@ -92,8 +92,13 @@ public final class ReferenceTranslator {
else if (expression instanceof JetSimpleNameExpression) {
simpleNameExpression = (JetSimpleNameExpression) expression;
}
return simpleNameExpression != null &&
(getDescriptorForReferenceExpression(context.bindingContext(), simpleNameExpression) instanceof PropertyDescriptor);
if (simpleNameExpression == null) return false;
DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), simpleNameExpression);
// Skip ValueParameterDescriptor because sometime we can miss resolved call for it, e.g. when set something to delegated property.
return descriptor instanceof VariableDescriptor && !(descriptor instanceof ValueParameterDescriptor);
}
}
@@ -148,7 +148,7 @@ public final class BindingUtils {
public static ResolvedCall<?> getResolvedCallForProperty(@NotNull BindingContext context,
@NotNull JetExpression expression) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = context.get(BindingContext.RESOLVED_CALL, expression);
assert resolvedCall != null : message(expression, expression.getText() + "must resolve to a call");
assert resolvedCall != null : message(expression, expression.getText() + " must resolve to a call");
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
return ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall();
}