JS backend: refactoring LiteralFunctionTranslator -- make possible to store translation state and create an instance for each translation instead of one instance for all translations.
Introduced DefinitionPlace class and make creating a new definition place more safety.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.context
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression
|
||||
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef
|
||||
|
||||
class DefinitionPlace(
|
||||
val properties: MutableList<JsPropertyInitializer>,
|
||||
private val fqName: JsExpression
|
||||
) {
|
||||
fun define(name: String, expression : JsExpression): JsNameRef {
|
||||
properties.add(JsPropertyInitializer(JsNameRef(name), expression))
|
||||
return JsNameRef(name, fqName)
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import org.jetbrains.k2js.config.EcmaVersion;
|
||||
import org.jetbrains.k2js.config.LibrarySourcesConfig;
|
||||
import org.jetbrains.k2js.translate.context.generator.Generator;
|
||||
import org.jetbrains.k2js.translate.context.generator.Rule;
|
||||
import org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator;
|
||||
import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
|
||||
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
|
||||
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
||||
@@ -93,9 +92,6 @@ public final class StaticContext {
|
||||
@NotNull
|
||||
private final EcmaVersion ecmaVersion;
|
||||
|
||||
@NotNull
|
||||
private LiteralFunctionTranslator literalFunctionTranslator;
|
||||
|
||||
//TODO: too many parameters in constructor
|
||||
private StaticContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext,
|
||||
@NotNull Namer namer, @NotNull Intrinsics intrinsics,
|
||||
@@ -109,15 +105,6 @@ public final class StaticContext {
|
||||
this.ecmaVersion = ecmaVersion;
|
||||
}
|
||||
|
||||
public void initTranslators(TranslationContext programContext) {
|
||||
literalFunctionTranslator = new LiteralFunctionTranslator(programContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LiteralFunctionTranslator getLiteralFunctionTranslator() {
|
||||
return literalFunctionTranslator;
|
||||
}
|
||||
|
||||
public boolean isEcma5() {
|
||||
return ecmaVersion == EcmaVersion.v5;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator;
|
||||
import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -46,31 +45,42 @@ public class TranslationContext {
|
||||
private final AliasingContext aliasingContext;
|
||||
@Nullable
|
||||
private final UsageTracker usageTracker;
|
||||
@Nullable
|
||||
private final TranslationContext parent;
|
||||
@Nullable
|
||||
private final DefinitionPlace definitionPlace;
|
||||
|
||||
@NotNull
|
||||
public static TranslationContext rootContext(@NotNull StaticContext staticContext, JsFunction rootFunction) {
|
||||
DynamicContext rootDynamicContext =
|
||||
DynamicContext.rootContext(rootFunction.getScope(), rootFunction.getBody());
|
||||
AliasingContext rootAliasingContext = AliasingContext.getCleanContext();
|
||||
return new TranslationContext(staticContext, rootDynamicContext, rootAliasingContext, null);
|
||||
return new TranslationContext(null, staticContext, rootDynamicContext, rootAliasingContext, null, null);
|
||||
}
|
||||
|
||||
private final HashMap<JsExpression, TemporaryConstVariable> expressionToTempConstVariableCache = new HashMap<JsExpression, TemporaryConstVariable>();
|
||||
|
||||
private TranslationContext(
|
||||
@Nullable TranslationContext parent,
|
||||
@NotNull StaticContext staticContext,
|
||||
@NotNull DynamicContext dynamicContext,
|
||||
@NotNull AliasingContext aliasingContext,
|
||||
@Nullable UsageTracker usageTracker
|
||||
@Nullable UsageTracker usageTracker,
|
||||
@Nullable DefinitionPlace definitionPlace
|
||||
) {
|
||||
this.parent = parent;
|
||||
this.dynamicContext = dynamicContext;
|
||||
this.staticContext = staticContext;
|
||||
this.aliasingContext = aliasingContext;
|
||||
this.usageTracker = usageTracker;
|
||||
this.definitionPlace = definitionPlace;
|
||||
}
|
||||
|
||||
private TranslationContext(@NotNull TranslationContext parent, @NotNull AliasingContext aliasingContext) {
|
||||
this(parent.staticContext, parent.dynamicContext, aliasingContext, parent.usageTracker);
|
||||
private TranslationContext(
|
||||
@NotNull TranslationContext parent,
|
||||
@NotNull AliasingContext aliasingContext
|
||||
) {
|
||||
this(parent, parent.staticContext, parent.dynamicContext, aliasingContext, parent.usageTracker, null);
|
||||
}
|
||||
|
||||
private TranslationContext(
|
||||
@@ -79,8 +89,8 @@ public class TranslationContext {
|
||||
@NotNull AliasingContext aliasingContext,
|
||||
@Nullable UsageTracker usageTracker
|
||||
) {
|
||||
this(parent.staticContext, DynamicContext.newContext(fun.getScope(), fun.getBody()), aliasingContext,
|
||||
usageTracker == null ? parent.usageTracker : usageTracker);
|
||||
this(parent, parent.staticContext, DynamicContext.newContext(fun.getScope(), fun.getBody()), aliasingContext,
|
||||
usageTracker == null ? parent.usageTracker : usageTracker, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -97,14 +107,6 @@ public class TranslationContext {
|
||||
return new TranslationContext(this, fun, aliasingContext, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TranslationContext contextWithScope(@NotNull JsScope newScope,
|
||||
@NotNull JsBlock block,
|
||||
@NotNull AliasingContext aliasingContext,
|
||||
@Nullable UsageTracker usageTracker) {
|
||||
return new TranslationContext(staticContext, DynamicContext.newContext(newScope, block), aliasingContext, usageTracker);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TranslationContext newFunctionBody(
|
||||
@NotNull JsFunction fun,
|
||||
@@ -117,12 +119,13 @@ public class TranslationContext {
|
||||
|
||||
@NotNull
|
||||
public TranslationContext innerBlock(@NotNull JsBlock block) {
|
||||
return new TranslationContext(staticContext, dynamicContext.innerBlock(block), aliasingContext, usageTracker);
|
||||
return new TranslationContext(this, staticContext, dynamicContext.innerBlock(block), aliasingContext, usageTracker, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor) {
|
||||
return contextWithScope(getScopeForDescriptor(descriptor), getBlockForDescriptor(descriptor), aliasingContext, usageTracker);
|
||||
public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor, @Nullable DefinitionPlace place) {
|
||||
DynamicContext dynamicContext = DynamicContext.newContext(getScopeForDescriptor(descriptor), getBlockForDescriptor(descriptor));
|
||||
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext, usageTracker, place);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -247,11 +250,6 @@ public class TranslationContext {
|
||||
return aliasingContext;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LiteralFunctionTranslator literalFunctionTranslator() {
|
||||
return staticContext.getLiteralFunctionTranslator();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsFunction getFunctionObject(@NotNull CallableDescriptor descriptor) {
|
||||
return staticContext.getFunctionWithScope(descriptor);
|
||||
@@ -287,4 +285,12 @@ public class TranslationContext {
|
||||
JsExpression alias = aliasingContext.getAliasForDescriptor(effectiveDescriptor);
|
||||
return alias == null ? JsLiteral.THIS : alias;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DefinitionPlace getDefinitionPlace() {
|
||||
if (definitionPlace != null) return definitionPlace;
|
||||
if (parent != null) return parent.getDefinitionPlace();
|
||||
|
||||
throw new AssertionError("Can not find definition place from rootContext(definitionPlace and parent is null)");
|
||||
}
|
||||
}
|
||||
|
||||
+18
-32
@@ -17,8 +17,6 @@
|
||||
package org.jetbrains.k2js.translate.declaration;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
@@ -29,8 +27,9 @@ import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetParameter;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeConstructor;
|
||||
import org.jetbrains.k2js.translate.LabelGenerator;
|
||||
import org.jetbrains.k2js.translate.context.DefinitionPlace;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator;
|
||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator;
|
||||
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
||||
@@ -39,7 +38,6 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.topologicallySortSuperclassesAndRecordAllInstances;
|
||||
import static org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator.createPlace;
|
||||
import static org.jetbrains.k2js.translate.initializer.InitializerUtils.createClassObjectInitializer;
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor;
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter;
|
||||
@@ -110,7 +108,7 @@ public final class ClassTranslator extends AbstractTranslator {
|
||||
if (containingClass == null) {
|
||||
return translate(context());
|
||||
}
|
||||
return context().literalFunctionTranslator().translate(containingClass, context(), classDeclaration, descriptor, this);
|
||||
return new LiteralFunctionTranslator(context()).translate(containingClass, context(), classDeclaration, descriptor, this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -130,34 +128,26 @@ public final class ClassTranslator extends AbstractTranslator {
|
||||
private List<JsExpression> getClassCreateInvocationArguments(@NotNull TranslationContext declarationContext) {
|
||||
List<JsExpression> invocationArguments = new ArrayList<JsExpression>();
|
||||
|
||||
final List<JsPropertyInitializer> properties = new SmartList<JsPropertyInitializer>();
|
||||
final List<JsPropertyInitializer> staticProperties = new SmartList<JsPropertyInitializer>();
|
||||
List<JsPropertyInitializer> properties = new SmartList<JsPropertyInitializer>();
|
||||
List<JsPropertyInitializer> staticProperties = new SmartList<JsPropertyInitializer>();
|
||||
|
||||
boolean isTopLevelDeclaration = context() == declarationContext;
|
||||
final JsNameRef qualifiedReference;
|
||||
|
||||
JsNameRef qualifiedReference;
|
||||
if (!isTopLevelDeclaration) {
|
||||
qualifiedReference = null;
|
||||
}
|
||||
else if (descriptor.getKind().isSingleton() || isAnonymousObject(descriptor)) {
|
||||
qualifiedReference = null;
|
||||
declarationContext.literalFunctionTranslator().setDefinitionPlace(
|
||||
new NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>>() {
|
||||
@Override
|
||||
@NotNull
|
||||
public Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression> compute() {
|
||||
return createPlace(properties, context().getThisObject(descriptor));
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
qualifiedReference = declarationContext.getQualifiedReference(descriptor);
|
||||
declarationContext.literalFunctionTranslator().setDefinitionPlace(
|
||||
new NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>>() {
|
||||
@Override
|
||||
@NotNull
|
||||
public Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression> compute() {
|
||||
return createPlace(staticProperties, qualifiedReference);
|
||||
}
|
||||
});
|
||||
DefinitionPlace definitionPlace;
|
||||
if (descriptor.getKind().isSingleton() || isAnonymousObject(descriptor)) {
|
||||
qualifiedReference = null;
|
||||
definitionPlace = new DefinitionPlace(properties, context().getThisObject(descriptor));
|
||||
}
|
||||
else {
|
||||
qualifiedReference = declarationContext.getQualifiedReference(descriptor);
|
||||
definitionPlace = new DefinitionPlace(staticProperties, qualifiedReference);
|
||||
}
|
||||
declarationContext = declarationContext.newDeclaration(descriptor, definitionPlace);
|
||||
}
|
||||
|
||||
invocationArguments.add(getSuperclassReferences(declarationContext));
|
||||
@@ -171,10 +161,6 @@ public final class ClassTranslator extends AbstractTranslator {
|
||||
bodyVisitor.traverseContainer(classDeclaration, declarationContext);
|
||||
mayBeAddEnumEntry(bodyVisitor.getEnumEntryList(), staticProperties, declarationContext);
|
||||
|
||||
if (isTopLevelDeclaration) {
|
||||
declarationContext.literalFunctionTranslator().setDefinitionPlace(null);
|
||||
}
|
||||
|
||||
boolean hasStaticProperties = !staticProperties.isEmpty();
|
||||
if (!properties.isEmpty() || hasStaticProperties) {
|
||||
if (properties.isEmpty()) {
|
||||
|
||||
-4
@@ -48,10 +48,6 @@ public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
|
||||
protected final List<JsPropertyInitializer> staticResult;
|
||||
protected final List<JsPropertyInitializer> enumEntryList = new SmartList<JsPropertyInitializer>();
|
||||
|
||||
public DeclarationBodyVisitor() {
|
||||
this(new SmartList<JsPropertyInitializer>(), new SmartList<JsPropertyInitializer>());
|
||||
}
|
||||
|
||||
public DeclarationBodyVisitor(@NotNull List<JsPropertyInitializer> result, @NotNull List<JsPropertyInitializer> staticResult) {
|
||||
this.result = result;
|
||||
this.staticResult = staticResult;
|
||||
|
||||
@@ -30,7 +30,7 @@ public class DefineInvocation {
|
||||
|
||||
/* package */
|
||||
@NotNull
|
||||
static DefineInvocation createDefineInvocation(
|
||||
static DefineInvocation create(
|
||||
@NotNull FqName packageFqName,
|
||||
@Nullable JsExpression initializer,
|
||||
@NotNull JsObjectLiteral members,
|
||||
|
||||
@@ -15,14 +15,11 @@
|
||||
*/
|
||||
package org.jetbrains.k2js.translate.declaration
|
||||
|
||||
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.JsPropertyInitializer
|
||||
import org.jetbrains.k2js.translate.initializer.InitializerVisitor
|
||||
import org.jetbrains.k2js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext
|
||||
import org.jetbrains.jet.lang.psi.JetClassInitializer
|
||||
import com.google.dart.compiler.backend.js.ast.JsStatement
|
||||
import org.jetbrains.k2js.translate.general.Translation
|
||||
import org.jetbrains.jet.lang.psi.JetProperty
|
||||
import org.jetbrains.k2js.translate.initializer.InitializerUtils
|
||||
@@ -32,8 +29,13 @@ import com.google.dart.compiler.backend.js.ast.JsFunction
|
||||
import org.jetbrains.k2js.translate.utils.BindingUtils.*
|
||||
import org.jetbrains.k2js.translate.initializer.InitializerUtils.*
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
|
||||
import com.intellij.util.SmartList
|
||||
|
||||
class FileDeclarationVisitor(
|
||||
val context: TranslationContext,
|
||||
initializers: List<JsPropertyInitializer> = SmartList()
|
||||
) : DeclarationBodyVisitor(initializers, SmartList()) {
|
||||
|
||||
class FileDeclarationVisitor(val context: TranslationContext) : DeclarationBodyVisitor() {
|
||||
private val initializer = JsAstUtils.createFunctionWithEmptyBody(context.scope())
|
||||
private val initializerContext = context.contextWithScope(initializer)
|
||||
private val initializerStatements = initializer.getBody()!!.getStatements()!!
|
||||
|
||||
+5
-4
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.k2js.translate.context.Namer;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
@@ -30,7 +31,6 @@ import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
|
||||
import static org.jetbrains.k2js.translate.declaration.DefineInvocation.createDefineInvocation;
|
||||
|
||||
public final class PackageDeclarationTranslator extends AbstractTranslator {
|
||||
private final Iterable<JetFile> files;
|
||||
@@ -53,12 +53,13 @@ public final class PackageDeclarationTranslator extends AbstractTranslator {
|
||||
Map<FqName, DefineInvocation> packageFqNameToDefineInvocation = new THashMap<FqName, DefineInvocation>();
|
||||
|
||||
for (JetFile file : files) {
|
||||
PackageFragmentDescriptor packageFragment = context().bindingContext().get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, file);
|
||||
PackageFragmentDescriptor packageFragment =
|
||||
BindingContextUtils.getNotNull(context().bindingContext(), BindingContext.FILE_TO_PACKAGE_FRAGMENT, file);
|
||||
|
||||
PackageTranslator translator = packageFragmentToTranslator.get(packageFragment);
|
||||
if (translator == null) {
|
||||
createRootPackageDefineInvocationIfNeeded(packageFqNameToDefineInvocation);
|
||||
translator = new PackageTranslator(packageFragment, packageFqNameToDefineInvocation, context());
|
||||
translator = PackageTranslator.create(packageFragment, context());
|
||||
packageFragmentToTranslator.put(packageFragment, translator);
|
||||
}
|
||||
|
||||
@@ -78,7 +79,7 @@ public final class PackageDeclarationTranslator extends AbstractTranslator {
|
||||
private void createRootPackageDefineInvocationIfNeeded(@NotNull Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) {
|
||||
if (!packageFqNameToDefineInvocation.containsKey(FqName.ROOT)) {
|
||||
packageFqNameToDefineInvocation.put(
|
||||
FqName.ROOT, createDefineInvocation(FqName.ROOT, null, new JsObjectLiteral(true), context()));
|
||||
FqName.ROOT, DefineInvocation.create(FqName.ROOT, null, new JsObjectLiteral(true), context()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+25
-37
@@ -17,15 +17,14 @@
|
||||
package org.jetbrains.k2js.translate.declaration;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.k2js.translate.LabelGenerator;
|
||||
import org.jetbrains.k2js.translate.context.DefinitionPlace;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
|
||||
@@ -34,61 +33,50 @@ import org.jetbrains.k2js.translate.utils.BindingUtils;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.k2js.translate.declaration.DefineInvocation.createDefineInvocation;
|
||||
import static org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator.createPlace;
|
||||
|
||||
final class PackageTranslator extends AbstractTranslator {
|
||||
static PackageTranslator create(
|
||||
@NotNull PackageFragmentDescriptor descriptor,
|
||||
@NotNull TranslationContext context
|
||||
) {
|
||||
SmartList<JsPropertyInitializer> properties = new SmartList<JsPropertyInitializer>();
|
||||
DefinitionPlace definitionPlace = new DefinitionPlace(properties, context.getQualifiedReference(descriptor));
|
||||
|
||||
TranslationContext newContext = context.newDeclaration(descriptor, definitionPlace);
|
||||
FileDeclarationVisitor visitor = new FileDeclarationVisitor(newContext, definitionPlace.getProperties());
|
||||
return new PackageTranslator(descriptor, newContext, visitor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private final PackageFragmentDescriptor descriptor;
|
||||
|
||||
private final FileDeclarationVisitor visitor;
|
||||
|
||||
private final NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>> definitionPlace;
|
||||
|
||||
PackageTranslator(
|
||||
@NotNull final PackageFragmentDescriptor descriptor,
|
||||
@NotNull final Map<FqName, DefineInvocation> packageFqNameToDefineInvocation,
|
||||
@NotNull TranslationContext context
|
||||
private PackageTranslator(
|
||||
@NotNull PackageFragmentDescriptor descriptor,
|
||||
@NotNull TranslationContext context,
|
||||
@NotNull FileDeclarationVisitor visitor
|
||||
) {
|
||||
super(context.newDeclaration(descriptor));
|
||||
|
||||
super(context);
|
||||
this.descriptor = descriptor;
|
||||
|
||||
visitor = new FileDeclarationVisitor(context());
|
||||
|
||||
definitionPlace = new NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>>() {
|
||||
@Override
|
||||
@NotNull
|
||||
public Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression> compute() {
|
||||
DefineInvocation defineInvocation = packageFqNameToDefineInvocation.get(descriptor.getFqName());
|
||||
if (defineInvocation == null) {
|
||||
defineInvocation = createDefinitionPlace(null, packageFqNameToDefineInvocation);
|
||||
}
|
||||
|
||||
return createPlace(defineInvocation.getMembers(), context().getQualifiedReference(descriptor.getFqName()));
|
||||
}
|
||||
};
|
||||
this.visitor = visitor;
|
||||
}
|
||||
|
||||
|
||||
public void translate(JetFile file) {
|
||||
context().literalFunctionTranslator().setDefinitionPlace(definitionPlace);
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
if (!AnnotationsUtils.isPredefinedObject(BindingUtils.getDescriptorForElement(bindingContext(), declaration))) {
|
||||
declaration.accept(visitor, context());
|
||||
}
|
||||
}
|
||||
context().literalFunctionTranslator().setDefinitionPlace(null);
|
||||
}
|
||||
|
||||
private DefineInvocation createDefinitionPlace(
|
||||
private void createDefinitionPlace(
|
||||
@Nullable JsExpression initializer,
|
||||
Map<FqName, DefineInvocation> packageFqNameToDefineInvocation
|
||||
) {
|
||||
FqName fqName = descriptor.getFqName();
|
||||
DefineInvocation place = createDefineInvocation(fqName, initializer, new JsObjectLiteral(visitor.getResult(), true), context());
|
||||
DefineInvocation place = DefineInvocation.create(fqName, initializer, new JsObjectLiteral(visitor.getResult(), true), context());
|
||||
packageFqNameToDefineInvocation.put(fqName, place);
|
||||
addToParent(fqName.parent(), getEntry(fqName, place), packageFqNameToDefineInvocation);
|
||||
return place;
|
||||
}
|
||||
|
||||
public void add(@NotNull Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) {
|
||||
@@ -137,7 +125,7 @@ final class PackageTranslator extends AbstractTranslator {
|
||||
Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) {
|
||||
while (!addEntryIfParentExists(parentFqName, entry, packageFqNameToDefineInvocation)) {
|
||||
JsObjectLiteral members = new JsObjectLiteral(new SmartList<JsPropertyInitializer>(entry), true);
|
||||
DefineInvocation defineInvocation = createDefineInvocation(parentFqName, null, members, context());
|
||||
DefineInvocation defineInvocation = DefineInvocation.create(parentFqName, null, members, context());
|
||||
entry = getEntry(parentFqName, defineInvocation);
|
||||
|
||||
packageFqNameToDefineInvocation.put(parentFqName, defineInvocation);
|
||||
|
||||
+1
-6
@@ -187,7 +187,7 @@ public final class PropertyTranslator extends AbstractTranslator {
|
||||
@NotNull
|
||||
private JsFunction generateDefaultSetterFunction(@NotNull PropertySetterDescriptor setterDescriptor) {
|
||||
JsFunction fun = new JsFunction(context().getScopeForDescriptor(setterDescriptor.getContainingDeclaration()));
|
||||
JsParameter defaultParameter = new JsParameter(propertyAccessContext(setterDescriptor).scope().declareTemporary());
|
||||
JsParameter defaultParameter = new JsParameter(fun.getScope().declareTemporary());
|
||||
fun.getParameters().add(defaultParameter);
|
||||
JsExpression setExpression;
|
||||
|
||||
@@ -208,11 +208,6 @@ public final class PropertyTranslator extends AbstractTranslator {
|
||||
return TranslationUtils.translateFunctionAsEcma5PropertyDescriptor(function, accessorDescriptor, context());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TranslationContext propertyAccessContext(@NotNull PropertySetterDescriptor propertySetterDescriptor) {
|
||||
return context().newDeclaration(propertySetterDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsPropertyInitializer translateCustomAccessor(@NotNull JetPropertyAccessor expression) {
|
||||
FunctionTranslator translator = Translation.functionTranslator(expression, context());
|
||||
|
||||
@@ -403,13 +403,13 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
@Override
|
||||
@NotNull
|
||||
public JsNode visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression, @NotNull TranslationContext context) {
|
||||
return context.literalFunctionTranslator().translate(expression.getFunctionLiteral(), context);
|
||||
return new LiteralFunctionTranslator(context).translate(expression.getFunctionLiteral(), context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JsNode visitNamedFunction(@NotNull JetNamedFunction expression, @NotNull TranslationContext context) {
|
||||
JsExpression alias = context.literalFunctionTranslator().translate(expression, context);
|
||||
JsExpression alias = new LiteralFunctionTranslator(context).translate(expression, context);
|
||||
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
|
||||
JsName name = context.scope().declareFreshName(descriptor.getName().asString());
|
||||
context.aliasingContext().registerAlias(descriptor, name.makeRef());
|
||||
|
||||
+11
-35
@@ -17,9 +17,6 @@
|
||||
package org.jetbrains.k2js.translate.expression;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
@@ -31,42 +28,24 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.k2js.translate.LabelGenerator;
|
||||
import org.jetbrains.k2js.translate.context.AliasingContext;
|
||||
import org.jetbrains.k2js.translate.context.Namer;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.context.UsageTracker;
|
||||
import org.jetbrains.k2js.translate.context.*;
|
||||
import org.jetbrains.k2js.translate.declaration.ClassTranslator;
|
||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
|
||||
import static org.jetbrains.k2js.translate.utils.FunctionBodyTranslator.translateFunctionBody;
|
||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedReceiverDescriptor;
|
||||
|
||||
public class LiteralFunctionTranslator extends AbstractTranslator {
|
||||
private final Stack<NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>>> definitionPlaces =
|
||||
new Stack<NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>>>();
|
||||
private NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>> definitionPlace;
|
||||
private static final LabelGenerator FUNCTION_NAME_GENERATOR = new LabelGenerator('f');
|
||||
|
||||
@NotNull
|
||||
private final DefinitionPlace definitionPlace;
|
||||
|
||||
// TODO: Maybe we need make it private and add static method `translate`
|
||||
public LiteralFunctionTranslator(@NotNull TranslationContext context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public static Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression> createPlace(@NotNull List<JsPropertyInitializer> list,
|
||||
@NotNull JsExpression reference) {
|
||||
return Trinity.create(list, new LabelGenerator('f'), reference);
|
||||
}
|
||||
|
||||
public void setDefinitionPlace(@Nullable NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>> place) {
|
||||
if (place == null) {
|
||||
definitionPlaces.pop();
|
||||
definitionPlace = definitionPlaces.isEmpty() ? null : definitionPlaces.peek();
|
||||
}
|
||||
else {
|
||||
definitionPlaces.push(place);
|
||||
definitionPlace = place;
|
||||
}
|
||||
this.definitionPlace = context.getDefinitionPlace();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -128,16 +107,13 @@ public class LiteralFunctionTranslator extends AbstractTranslator {
|
||||
|
||||
InnerFunctionTranslator translator = new InnerFunctionTranslator(descriptor, funContext, fun);
|
||||
|
||||
JsExpression result = translator.translate(createReference(fun), outerContext);
|
||||
JsExpression result = translator.translate(defineFunction(fun), outerContext);
|
||||
addRegularParameters(descriptor, fun, funContext, receiverName);
|
||||
return result;
|
||||
}
|
||||
|
||||
private JsNameRef createReference(JsFunction fun) {
|
||||
Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression> place = definitionPlace.getValue();
|
||||
JsNameRef nameRef = new JsNameRef(place.second.generate(), place.third);
|
||||
place.first.add(new JsPropertyInitializer(nameRef, fun));
|
||||
return nameRef;
|
||||
private JsNameRef defineFunction(JsFunction fun) {
|
||||
return definitionPlace.define(FUNCTION_NAME_GENERATOR.generate(), fun);
|
||||
}
|
||||
|
||||
private static void addRegularParameters(
|
||||
@@ -172,6 +148,6 @@ public class LiteralFunctionTranslator extends AbstractTranslator {
|
||||
fun.getBody().getStatements().add(new JsReturn(classTranslator.translate(funContext)));
|
||||
JetClassBody body = declaration.getBody();
|
||||
assert body != null;
|
||||
return new InnerObjectTranslator(funContext, fun).translate(createReference(fun), usageTracker.isUsed() ? outerClassRef : null);
|
||||
return new InnerObjectTranslator(funContext, fun).translate(defineFunction(fun), usageTracker.isUsed() ? outerClassRef : null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,6 @@ public final class Translation {
|
||||
statements.add(program.getStringLiteral("use strict").makeStmt());
|
||||
|
||||
TranslationContext context = TranslationContext.rootContext(staticContext, rootFunction);
|
||||
staticContext.initTranslators(context);
|
||||
statements.addAll(PackageDeclarationTranslator.translateFiles(files, context));
|
||||
defineModule(context, statements, config.getModuleId());
|
||||
|
||||
|
||||
+5
-2
@@ -52,10 +52,13 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
|
||||
@NotNull
|
||||
private final List<JsStatement> initializerStatements = new SmartList<JsStatement>();
|
||||
|
||||
public ClassInitializerTranslator(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) {
|
||||
public ClassInitializerTranslator(
|
||||
@NotNull JetClassOrObject classDeclaration,
|
||||
@NotNull TranslationContext context
|
||||
) {
|
||||
// Note: it's important we use scope for class descriptor because anonymous function used in property initializers
|
||||
// belong to the properties themselves
|
||||
super(context.newDeclaration(getConstructor(context.bindingContext(), classDeclaration)));
|
||||
super(context.newDeclaration(getConstructor(context.bindingContext(), classDeclaration), null));
|
||||
this.classDeclaration = classDeclaration;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user