diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerDeclarationTranslator.java new file mode 100644 index 00000000000..30a1cc0fc53 --- /dev/null +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerDeclarationTranslator.java @@ -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 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 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 getCapturedValueParametersList(JsInvocation invocation) { + return invocation.getArguments(); + } +} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerFunctionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerFunctionTranslator.java new file mode 100644 index 00000000000..c404a87303b --- /dev/null +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerFunctionTranslator.java @@ -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 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 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); + } +} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerObjectTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerObjectTranslator.java new file mode 100644 index 00000000000..d9f8a66bb03 --- /dev/null +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/InnerObjectTranslator.java @@ -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; + } +}