Inner*Translator used by LiteralFunctionTranslator.

Adapted from https://github.com/develar/kotlin/commit/a9e0a42fb1347fa8e21c86b5a073ef8a7c873da0.
This commit is contained in:
Pavel V. Talanov
2012-08-10 21:29:05 +04:00
parent 86b85177b7
commit 02622595b5
3 changed files with 240 additions and 0 deletions
@@ -0,0 +1,85 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.expression;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.utils.closure.ClosureContext;
import org.jetbrains.k2js.translate.utils.closure.ClosureUtils;
import java.util.Collections;
import java.util.List;
abstract class InnerDeclarationTranslator {
protected final ClosureContext closureContext;
protected final TranslationContext context;
protected final JsFunction fun;
public InnerDeclarationTranslator(@NotNull JetElement declaration,
@NotNull DeclarationDescriptor descriptor,
@NotNull TranslationContext context,
@NotNull JsFunction fun) {
this.context = context;
closureContext = ClosureUtils.captureClosure(context.bindingContext(), declaration, descriptor);
this.fun = fun;
}
protected List<ValueParameterDescriptor> getValueParameters() {
return Collections.emptyList();
}
@NotNull
public abstract JsExpression translate(@NotNull JsNameRef nameRef);
protected JsExpression translate(@NotNull JsNameRef nameRef, @Nullable JsExpression self) {
if (closureContext.getDescriptors().isEmpty() && self == JsLiteral.NULL) {
return createExpression(nameRef, self);
}
else {
JsInvocation invocation = createInvocation(nameRef, self);
addCapturedValueParameters(invocation);
return invocation;
}
}
protected abstract JsExpression createExpression(JsNameRef nameRef, JsExpression self);
protected abstract JsInvocation createInvocation(JsNameRef nameRef, JsExpression self);
private void addCapturedValueParameters(JsInvocation bind) {
if (closureContext.getDescriptors().isEmpty()) {
return;
}
List<JsExpression> expressions = getCapturedValueParametersList(bind);
for (VariableDescriptor variableDescriptor : closureContext.getDescriptors()) {
JsName name = context.getNameForDescriptor(variableDescriptor);
fun.getParameters().add(new JsParameter(name));
expressions.add(name.makeRef());
}
}
protected List<JsExpression> getCapturedValueParametersList(JsInvocation invocation) {
return invocation.getArguments();
}
}
@@ -0,0 +1,100 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.expression;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.k2js.translate.context.TranslationContext;
import java.util.List;
class InnerFunctionTranslator extends InnerDeclarationTranslator {
private final FunctionDescriptor descriptor;
public InnerFunctionTranslator(@NotNull JetElement declaration,
@NotNull FunctionDescriptor descriptor,
@NotNull TranslationContext context,
@NotNull JsFunction fun) {
super(declaration, descriptor, context, fun);
this.descriptor = descriptor;
}
public boolean isLocalVariablesAffected() {
return closureContext.isLocalVariablesAffected();
}
@Override
protected List<ValueParameterDescriptor> getValueParameters() {
return descriptor.getValueParameters();
}
@Override
@NotNull
public JsExpression translate(@NotNull JsNameRef nameRef) {
JsExpression result = translate(nameRef, getThis());
FunctionTranslator.addParameters(fun.getParameters(), descriptor, context);
return result;
}
@Override
protected JsExpression createExpression(JsNameRef nameRef, JsExpression self) {
return nameRef;
}
@Override
protected JsInvocation createInvocation(JsNameRef nameRef, JsExpression self) {
JsInvocation bind = new JsInvocation(context.namer().kotlin(getBindMethodName()));
bind.getArguments().add(nameRef);
bind.getArguments().add(self);
return bind;
}
@NotNull
private JsExpression getThis() {
ClassDescriptor outerClassDescriptor = closureContext.outerClassDescriptor;
if (outerClassDescriptor != null && !descriptor.getReceiverParameter().exists()) {
return JsLiteral.THIS;
}
return JsLiteral.NULL;
}
@NotNull
private String getBindMethodName() {
if (closureContext.getDescriptors().isEmpty()) {
return getValueParameters().isEmpty() ? "b3" : "b4";
}
else {
return getValueParameters().isEmpty() ? (closureContext.getDescriptors().size() == 1 ? "b0" : "b1") : "b2";
}
}
@Override
protected List<JsExpression> getCapturedValueParametersList(JsInvocation invocation) {
if (closureContext.getDescriptors().size() > 1 || !getValueParameters().isEmpty()) {
JsArrayLiteral values = new JsArrayLiteral();
invocation.getArguments().add(values);
return values.getExpressions();
}
return super.getCapturedValueParametersList(invocation);
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.expression;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.k2js.translate.context.TraceableThisAliasProvider;
import org.jetbrains.k2js.translate.context.TranslationContext;
class InnerObjectTranslator extends InnerDeclarationTranslator {
public InnerObjectTranslator(@NotNull JetClassOrObject declaration, @NotNull ClassDescriptor descriptor, @NotNull TranslationContext context, @NotNull JsFunction fun) {
super(declaration, descriptor, context, fun);
}
@Override
protected JsExpression createExpression(JsNameRef nameRef, JsExpression self) {
return createInvocation(nameRef, self);
}
@Override
@NotNull
public JsExpression translate(@NotNull JsNameRef nameRef) {
return super.translate(nameRef, thisAliasProvider().getRefIfWasCaptured());
}
private TraceableThisAliasProvider thisAliasProvider() {
return ((TraceableThisAliasProvider) context.thisAliasProvider());
}
@Override
protected JsInvocation createInvocation(JsNameRef nameRef, JsExpression self) {
JsInvocation invocation = new JsInvocation(nameRef);
if (thisAliasProvider().wasThisCaptured()) {
fun.getParameters().add(new JsParameter(((JsNameRef) self).getName()));
invocation.getArguments().add(JsLiteral.THIS);
}
return invocation;
}
}