Finished work on namespaces.

This commit is contained in:
Pavel Talanov
2011-11-22 21:06:36 +04:00
parent f806af4829
commit f5e5ac42dd
12 changed files with 78 additions and 65 deletions
@@ -290,6 +290,7 @@ public class AstUtil {
return new JsBinaryOperation(JsBinaryOperator.OR, op1, op2); return new JsBinaryOperation(JsBinaryOperator.OR, op1, op2);
} }
//TODO
public static void setQualifier(JsExpression selector, JsExpression receiver) { public static void setQualifier(JsExpression selector, JsExpression receiver) {
if (selector instanceof JsInvocation) { if (selector instanceof JsInvocation) {
setQualifier(((JsInvocation) selector).getQualifier(), receiver); setQualifier(((JsInvocation) selector).getQualifier(), receiver);
@@ -149,6 +149,10 @@ public final class BindingUtils {
return null; return null;
} }
static public boolean belongsToNamespace(@NotNull BindingContext context, @NotNull JetProperty property) {
return getPropertyDescriptor(context, property).getContainingDeclaration() instanceof NamespaceDescriptor;
}
@Nullable @Nullable
static public ResolvedCall<?> getResolvedCall(@NotNull BindingContext context, static public ResolvedCall<?> getResolvedCall(@NotNull BindingContext context,
@NotNull JetExpression expression) { @NotNull JetExpression expression) {
@@ -7,6 +7,8 @@ import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetNamedDeclaration; import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.psi.JetNamespace;
//TODO: thing about redesigning this class
public class InitializerGenerator { public class InitializerGenerator {
@NotNull @NotNull
@@ -79,5 +79,9 @@ public final class Namer {
return AstUtil.newQualifiedNameRef("isType"); return AstUtil.newQualifiedNameRef("isType");
} }
public static JsNameRef initializeMethodReference() {
return AstUtil.newQualifiedNameRef("initialize");
}
} }
@@ -2,10 +2,15 @@ package org.jetbrains.k2js.translate;
import com.google.dart.compiler.backend.js.ast.JsFunction; import com.google.dart.compiler.backend.js.ast.JsFunction;
import com.google.dart.compiler.backend.js.ast.JsScope; import com.google.dart.compiler.backend.js.ast.JsScope;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import com.google.dart.compiler.util.AstUtil; import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.psi.JetNamespace;
import java.util.ArrayList;
import java.util.List;
/** /**
* @author Talanov Pavel * @author Talanov Pavel
*/ */
@@ -28,4 +33,14 @@ public final class NamespaceInitializerVisitor extends AbstractInitializerVisito
return result; return result;
} }
@Override
@NotNull
public List<JsStatement> visitNamespace(@NotNull JetNamespace expression, @NotNull TranslationContext context) {
List<JsStatement> initializerStatements = new ArrayList<JsStatement>();
for (JetDeclaration declaration : expression.getDeclarations()) {
initializerStatements.addAll(declaration.accept(this, context));
}
return initializerStatements;
}
} }
@@ -14,48 +14,61 @@ import java.util.List;
public final class NamespaceTranslator extends AbstractTranslator { public final class NamespaceTranslator extends AbstractTranslator {
@NotNull @NotNull
public static NamespaceTranslator newInstance(@NotNull TranslationContext context) { private final JetNamespace namespace;
return new NamespaceTranslator(context); @NotNull
private final JsName namespaceName;
@NotNull
public static JsStatement translate(@NotNull TranslationContext context,
@NotNull JetNamespace namespace) {
return (new NamespaceTranslator(context, namespace)).translateNamespace();
} }
private NamespaceTranslator(@NotNull TranslationContext context) { private NamespaceTranslator(@NotNull TranslationContext context, @NotNull JetNamespace namespace) {
super(context); super(context);
this.namespace = namespace;
this.namespaceName = context.getNameForElement(namespace);
} }
@NotNull @NotNull
public JsStatement translateNamespace(@NotNull JetNamespace namespace) { public JsStatement translateNamespace() {
ClassDeclarationTranslator translator = new ClassDeclarationTranslator(translationContext(), namespace); ClassDeclarationTranslator translator = new ClassDeclarationTranslator(translationContext(), namespace);
translator.generateDeclarations(); translator.generateDeclarations();
JsName declarationsObjectName = translator.getDeclarationsObjectName(); JsName declarationsObjectName = translator.getDeclarationsObjectName();
JsBlock result = new JsBlock(); JsBlock result = new JsBlock();
JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation(namespace); JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation();
namespaceDeclaration.getArguments().add(declarationsObjectName.makeRef()); namespaceDeclaration.getArguments().add(declarationsObjectName.makeRef());
addMemberDeclarations(namespace, namespaceDeclaration); addMemberDeclarations(namespaceDeclaration);
result.addStatement(translator.getDeclarationsStatement()); result.addStatement(translator.getDeclarationsStatement());
result.addStatement(namespaceDeclarationStatement(namespace, namespaceDeclaration)); result.addStatement(namespaceDeclarationStatement(namespaceDeclaration));
result.addStatement(namespaceInitializeStatement());
return result; return result;
} }
private JsStatement namespaceInitializeStatement() {
JsNameRef initializeMethodReference = Namer.initializeMethodReference();
AstUtil.setQualifier(initializeMethodReference, namespaceName.makeRef());
return AstUtil.newInvocation(initializeMethodReference).makeStmt();
}
@NotNull @NotNull
private JsInvocation namespaceCreateMethodInvocation(@NotNull JetNamespace namespace) { private JsInvocation namespaceCreateMethodInvocation() {
return AstUtil.newInvocation(Namer.namespaceCreationMethodReference()); return AstUtil.newInvocation(Namer.namespaceCreationMethodReference());
} }
@NotNull @NotNull
private JsStatement namespaceDeclarationStatement(@NotNull JetNamespace namespace, private JsStatement namespaceDeclarationStatement(@NotNull JsInvocation namespaceDeclaration) {
@NotNull JsInvocation namespaceDeclaration) {
return AstUtil.newAssignmentStatement return AstUtil.newAssignmentStatement
(translationContext().getNameForElement(namespace).makeRef(), namespaceDeclaration); (translationContext().getNameForElement(namespace).makeRef(), namespaceDeclaration);
} }
private void addMemberDeclarations(@NotNull JetNamespace namespace, private void addMemberDeclarations(@NotNull JsInvocation jsNamespace) {
@NotNull JsInvocation jsNamespace) { JsObjectLiteral jsClassDescription = translateNamespaceMemberDeclarations();
JsObjectLiteral jsClassDescription = translateNamespaceMemberDeclarations(namespace);
jsNamespace.getArguments().add(jsClassDescription); jsNamespace.getArguments().add(jsClassDescription);
} }
@NotNull @NotNull
private JsObjectLiteral translateNamespaceMemberDeclarations(@NotNull JetNamespace namespace) { private JsObjectLiteral translateNamespaceMemberDeclarations() {
List<JsPropertyInitializer> propertyList = new ArrayList<JsPropertyInitializer>(); List<JsPropertyInitializer> propertyList = new ArrayList<JsPropertyInitializer>();
propertyList.add(InitializerGenerator.generateInitializeMethod(namespace, translationContext())); propertyList.add(InitializerGenerator.generateInitializeMethod(namespace, translationContext()));
propertyList.addAll(new DeclarationBodyVisitor().traverseNamespace(namespace, propertyList.addAll(new DeclarationBodyVisitor().traverseNamespace(namespace,
@@ -92,7 +92,8 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
if (setterName == null) { if (setterName == null) {
return null; return null;
} }
return AstUtil.newInvocation(AstUtil.thisQualifiedReference(setterName)); JsNameRef setterReference = Translation.generateCorrectReference(translationContext(), expression, setterName);
return AstUtil.newInvocation(setterReference);
} }
@Nullable @Nullable
@@ -32,10 +32,10 @@ public final class ReferenceProvider {
//TODO //TODO
@NotNull @NotNull
public JsNameRef generateCorrectReference() { public JsNameRef generateCorrectReference() {
if (requiresThisQualifier) { if (requiresNamespaceQualifier) {
return AstUtil.thisQualifiedReference(referencedName);
} else if (requiresNamespaceQualifier) {
return context.getNamespaceQualifiedReference(referencedName); return context.getNamespaceQualifiedReference(referencedName);
} else if (requiresThisQualifier) {
return AstUtil.thisQualifiedReference(referencedName);
} }
return referencedName.makeRef(); return referencedName.makeRef();
} }
@@ -46,9 +46,8 @@ public final class ReferenceProvider {
private boolean requiresThisQualifier(@NotNull JetSimpleNameExpression expression) { private boolean requiresThisQualifier(@NotNull JetSimpleNameExpression expression) {
JsName name = context.enclosingScope().findExistingName(referencedName.getIdent()); JsName name = context.enclosingScope().findExistingName(referencedName.getIdent());
boolean isNamespaceMember = requiresNamespaceQualifier;
boolean isClassMember = context.classScope().ownsName(name); boolean isClassMember = context.classScope().ownsName(name);
boolean isBackingFieldAccess = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER; boolean isBackingFieldAccess = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
return (isNamespaceMember && !isClassMember) || isClassMember || isBackingFieldAccess; return isClassMember || isBackingFieldAccess;
} }
} }
@@ -5,6 +5,7 @@ import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.psi.JetWhenExpression; import org.jetbrains.jet.lang.psi.JetWhenExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.declarations.Declarations; import org.jetbrains.k2js.declarations.Declarations;
@@ -32,8 +33,9 @@ public final class Translation {
} }
@NotNull @NotNull
static public NamespaceTranslator namespaceTranslator(@NotNull TranslationContext context) { static public JsStatement translateNamespace(@NotNull JetNamespace namespace,
return NamespaceTranslator.newInstance(context); @NotNull TranslationContext context) {
return NamespaceTranslator.translate(context, namespace);
} }
@NotNull @NotNull
@@ -76,10 +78,19 @@ public final class Translation {
return WhenTranslator.translateWhenExpression(expression, context); return WhenTranslator.translateWhenExpression(expression, context);
} }
@NotNull
static public JsNameRef generateCorrectReference(@NotNull TranslationContext context,
@NotNull JetSimpleNameExpression expression,
@NotNull JsName referencedName) {
return (new ReferenceProvider(context, expression, referencedName)).generateCorrectReference();
}
public static void generateAst(@NotNull JsProgram result, @NotNull BindingContext bindingContext, public static void generateAst(@NotNull JsProgram result, @NotNull BindingContext bindingContext,
@NotNull Declarations declarations, @NotNull JetNamespace namespace) { @NotNull Declarations declarations, @NotNull JetNamespace namespace) {
JsBlock block = result.getFragmentBlock(0); JsBlock block = result.getFragmentBlock(0);
TranslationContext context = TranslationContext.rootContext(result, bindingContext, declarations); TranslationContext context = TranslationContext.rootContext(result, bindingContext, declarations);
block.addStatement(Translation.namespaceTranslator(context).translateNamespace(namespace)); block.addStatement(Translation.translateNamespace(namespace, context));
} }
} }
@@ -26,7 +26,11 @@ public class TranslatorVisitor<T> extends JetVisitor<T, TranslationContext> {
@NotNull @NotNull
protected JsNameRef backingFieldReference(@NotNull JetProperty expression, @NotNull TranslationContext context) { protected JsNameRef backingFieldReference(@NotNull JetProperty expression, @NotNull TranslationContext context) {
return AstUtil.thisQualifiedReference(getBackingFieldName(getPropertyName(expression), context)); JsName backingFieldName = getBackingFieldName(getPropertyName(expression), context);
if (BindingUtils.belongsToNamespace(context.bindingContext(), expression)) {
return context.getNamespaceQualifiedReference(backingFieldName);
}
return AstUtil.thisQualifiedReference(backingFieldName);
} }
@NotNull @NotNull
@@ -89,12 +89,6 @@ public class KotlinLibTest extends IncludeLibraryTest {
new RhinoFunctionResultChecker("test", true)); new RhinoFunctionResultChecker("test", true));
} }
@Test
public void namespacePropertyAccess() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("namespace2.js")),
new RhinoFunctionResultChecker("test", true));
}
@Test @Test
public void isSameType() throws Exception { public void isSameType() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("isSameType.js")), runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("isSameType.js")),
@@ -1,35 +0,0 @@
{
classes = function(){
return {};
}
();
foo = Namespace.create(classes, {initialize:function(){
this.$b = 0
}
, set_b:function(tmp$0){
this.$b = tmp$0;
}
, get_b:function(){
return this.$b;
}
, loop:function(times){
while (times > 0) {
var u = function(){
return this.set_b(this.get_b() + 1);
}
;
u(times--);
}
}
, box:function(){
this.loop(5);
return this.get_b() === 5;
}
});
}
function test() {
return foo.box()
}