JS backend: complete remove _c object from output code.

This commit is contained in:
Erokhin Stanislav
2013-10-17 16:32:47 +04:00
parent 6422167b5c
commit e9fe0070d7
4 changed files with 6 additions and 212 deletions
@@ -47,7 +47,6 @@ public final class Namer {
private static final String SUPER_METHOD_NAME = "baseInitializer";
private static final String ROOT_NAMESPACE = "_";
private static final String RECEIVER_PARAMETER_NAME = "$receiver";
private static final String CLASSES_OBJECT_NAME = "_c";
private static final String THROW_NPE_FUN_NAME = "throwNPE";
private static final String CLASS_OBJECT_GETTER = "object";
private static final String CLASS_OBJECT_INITIALIZER = "object_initializer$";
@@ -72,11 +71,6 @@ public final class Namer {
return new JsNameRef(SUPER_METHOD_NAME, superClassJsName.makeRef());
}
@NotNull
public static String nameForClassesVariable() {
return CLASSES_OBJECT_NAME;
}
@NotNull
public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter, boolean useNativeAccessor) {
if (useNativeAccessor) {
@@ -170,23 +170,6 @@ public final class StaticContext {
@NotNull
public JsNameRef getQualifiedReference(@NotNull DeclarationDescriptor descriptor) {
ClassDescriptor classDescriptor;
if (descriptor instanceof ConstructorDescriptor) {
classDescriptor = ((ConstructorDescriptor) descriptor).getContainingDeclaration();
}
else if (descriptor instanceof ClassDescriptor) {
classDescriptor = (ClassDescriptor) descriptor;
}
else {
classDescriptor = null;
}
if (classDescriptor != null) {
JsNameRef reference = classDeclarationTranslator.getQualifiedReference((classDescriptor));
if (reference != null) {
return reference;
}
}
return new JsNameRef(getNameForDescriptor(descriptor), getQualifierForDescriptor(descriptor));
}
@@ -16,45 +16,24 @@
package org.jetbrains.k2js.translate.declaration;
import com.google.dart.compiler.backend.js.ast.*;
import com.intellij.util.SmartList;
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 gnu.trove.THashMap;
import gnu.trove.THashSet;
import gnu.trove.TObjectObjectProcedure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.Modality;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.utils.DFS;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassDescriptorForType;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor;
/**
* Generates a big block where are all the classes(objects representing them) are created.
*/
public final class ClassDeclarationTranslator extends AbstractTranslator {
private final THashSet<String> nameClashGuard = new THashSet<String>();
@NotNull
private final THashMap<ClassDescriptor, OpenClassInfo> openClassDescriptorToItem = new THashMap<ClassDescriptor, OpenClassInfo>();
private final LinkedList<OpenClassInfo> openList = new LinkedList<OpenClassInfo>();
@NotNull
private final ClassDescriptorToLabel classDescriptorToLabel = new ClassDescriptorToLabel();
private final THashMap<ClassDescriptor, JsNameRef> openClassDescriptorToQualifiedLabel = new THashMap<ClassDescriptor, JsNameRef>();
@@ -74,123 +53,11 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
}
};
@NotNull
private final JsFunction dummyFunction;
private final JsNameRef declarationsObjectRef;
private final JsVar classesVar;
public ClassDeclarationTranslator(@NotNull TranslationContext context) {
super(context);
dummyFunction = new JsFunction(context.scope());
JsName declarationsObject = context().scope().declareName(Namer.nameForClassesVariable());
classesVar = new JsVars.JsVar(declarationsObject);
declarationsObjectRef = declarationsObject.makeRef();
}
private final class ClassDescriptorToLabel implements ClassAliasingMap {
@Nullable
@Override
public JsNameRef get(ClassDescriptor descriptor, ClassDescriptor referencedDescriptor) {
OpenClassInfo item = openClassDescriptorToItem.get(descriptor);
// class declared in library
if (item == null) {
return null;
}
return item.label;
}
}
private static class OpenClassInfo {
private final ClassDescriptor descriptor;
private final JetClass declaration;
private final JsNameRef label;
private boolean referencedFromOpenClass = false;
private OpenClassInfo(JetClass declaration, ClassDescriptor descriptor, JsNameRef label) {
this.descriptor = descriptor;
this.declaration = declaration;
this.label = label;
}
}
@NotNull
public JsVars.JsVar getDeclaration() {
return classesVar;
}
public void generateDeclarations() {
List<JsVar> vars = new SmartList<JsVar>();
List<JsPropertyInitializer> propertyInitializers = new SmartList<JsPropertyInitializer>();
generateOpenClassDeclarations(vars, propertyInitializers);
fixUnresolvedClassReferences();
if (vars.isEmpty()) {
if (!propertyInitializers.isEmpty()) {
classesVar.setInitExpression(new JsObjectLiteral(propertyInitializers, true));
}
return;
}
if (!vars.isEmpty() || !propertyInitializers.isEmpty()) {
throw new IllegalStateException(); // check, that all class generate as final class
}
dummyFunction.setBody(new JsBlock(new JsVars(vars, true), new JsReturn(new JsObjectLiteral(propertyInitializers))));
classesVar.setInitExpression(new JsInvocation(dummyFunction));
}
private void generateOpenClassDeclarations(@NotNull List<JsVar> vars, @NotNull List<JsPropertyInitializer> propertyInitializers) {
// first pass: set up list order
LinkedList<OpenClassInfo> sortedOpenClasses =
(LinkedList<OpenClassInfo>) DFS.topologicalOrder(openList, new DFS.Neighbors<OpenClassInfo>() {
@NotNull
@Override
public Iterable<OpenClassInfo> getNeighbors(OpenClassInfo current) {
LinkedList<OpenClassInfo> parents = new LinkedList<OpenClassInfo>();
ClassDescriptor classDescriptor = getClassDescriptor(context().bindingContext(), current.declaration);
Collection<JetType> superTypes = classDescriptor.getTypeConstructor().getSupertypes();
for (JetType type : superTypes) {
ClassDescriptor descriptor = getClassDescriptorForType(type);
OpenClassInfo item = openClassDescriptorToItem.get(descriptor);
if (item == null) {
continue;
}
item.referencedFromOpenClass = true;
parents.add(item);
}
return parents;
}
});
assert sortedOpenClasses.size() == openList.size();
// second pass: generate
Iterator<OpenClassInfo> it = sortedOpenClasses.descendingIterator();
while (it.hasNext()) {
OpenClassInfo item = it.next();
JsExpression translatedDeclaration =
new ClassTranslator(item.declaration, item.descriptor, classDescriptorToLabel, context()).translate();
JsExpression value;
if (item.referencedFromOpenClass) {
vars.add(new JsVar(item.label.getName(), translatedDeclaration));
value = item.label;
}
else {
value = translatedDeclaration;
}
propertyInitializers.add(new JsPropertyInitializer(item.label, value));
}
}
private void fixUnresolvedClassReferences() {
public void fixUnresolvedClassReferences() {
openClassDescriptorToQualifiedLabel.forEachEntry(new TObjectObjectProcedure<ClassDescriptor, JsNameRef>() {
@Override
public boolean execute(ClassDescriptor descriptor, JsNameRef ref) {
@@ -204,59 +71,10 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
});
}
private String createNameForClass(ClassDescriptor descriptor) {
String suggestedName = descriptor.getName().asString();
String name = suggestedName;
DeclarationDescriptor containing = descriptor;
while (!nameClashGuard.add(name)) {
containing = containing.getContainingDeclaration();
assert containing != null;
name = suggestedName + '_' + containing.getName().asString();
}
return name;
}
@Nullable
public JsNameRef getQualifiedReference(ClassDescriptor descriptor) {
if (descriptor.getModality() != Modality.FINAL && false) {
//noinspection ConstantConditions
return classDescriptorToQualifiedLabel.get(descriptor, null);
}
return null;
}
@Nullable
public JsPropertyInitializer translate(@NotNull JetClassOrObject declaration, TranslationContext context) {
ClassDescriptor descriptor = getClassDescriptor(context().bindingContext(), declaration);
JsExpression value;
if (descriptor.getModality() == Modality.FINAL || true) {
value = new ClassTranslator(declaration, classDescriptorToQualifiedLabel, context).translate();
}
else {
String label = createNameForClass(descriptor);
JsName name = dummyFunction.getScope().declareName(label);
JsNameRef qualifiedLabel = openClassDescriptorToQualifiedLabel.get(descriptor);
if (qualifiedLabel == null) {
qualifiedLabel = new JsNameRef(name);
openClassDescriptorToQualifiedLabel.put(descriptor, qualifiedLabel);
}
else {
qualifiedLabel.resolve(name);
}
qualifiedLabel.setQualifier(declarationsObjectRef);
OpenClassInfo item = new OpenClassInfo((JetClass) declaration, descriptor, name.makeRef());
openList.add(item);
openClassDescriptorToItem.put(descriptor, item);
value = qualifiedLabel;
// not public api classes referenced to internal var _c
if (!descriptor.getVisibility().isPublicAPI()) {
return null;
}
}
JsExpression value = new ClassTranslator(declaration, classDescriptorToQualifiedLabel, context).translate();
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), value);
}
@@ -72,13 +72,12 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
return Collections.emptyList();
}
context().classDeclarationTranslator().generateDeclarations();
context().classDeclarationTranslator().fixUnresolvedClassReferences();
for (NamespaceTranslator translator : descriptorToTranslator.values()) {
translator.add(descriptorToDefineInvocation);
}
JsVars vars = new JsVars(true);
vars.addIfHasInitializer(context().classDeclarationTranslator().getDeclaration());
vars.addIfHasInitializer(getRootPackageDeclaration(descriptorToDefineInvocation.get(rootNamespaceDescriptor)));
return Collections.<JsStatement>singletonList(vars);