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);
}
//TODO
public static void setQualifier(JsExpression selector, JsExpression receiver) {
if (selector instanceof JsInvocation) {
setQualifier(((JsInvocation) selector).getQualifier(), receiver);
@@ -149,6 +149,10 @@ public final class BindingUtils {
return null;
}
static public boolean belongsToNamespace(@NotNull BindingContext context, @NotNull JetProperty property) {
return getPropertyDescriptor(context, property).getContainingDeclaration() instanceof NamespaceDescriptor;
}
@Nullable
static public ResolvedCall<?> getResolvedCall(@NotNull BindingContext context,
@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.JetNamespace;
//TODO: thing about redesigning this class
public class InitializerGenerator {
@NotNull
@@ -79,5 +79,9 @@ public final class Namer {
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.JsScope;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetNamespace;
import java.util.ArrayList;
import java.util.List;
/**
* @author Talanov Pavel
*/
@@ -28,4 +33,14 @@ public final class NamespaceInitializerVisitor extends AbstractInitializerVisito
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 {
@NotNull
public static NamespaceTranslator newInstance(@NotNull TranslationContext context) {
return new NamespaceTranslator(context);
private final JetNamespace namespace;
@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);
this.namespace = namespace;
this.namespaceName = context.getNameForElement(namespace);
}
@NotNull
public JsStatement translateNamespace(@NotNull JetNamespace namespace) {
public JsStatement translateNamespace() {
ClassDeclarationTranslator translator = new ClassDeclarationTranslator(translationContext(), namespace);
translator.generateDeclarations();
JsName declarationsObjectName = translator.getDeclarationsObjectName();
JsBlock result = new JsBlock();
JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation(namespace);
JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation();
namespaceDeclaration.getArguments().add(declarationsObjectName.makeRef());
addMemberDeclarations(namespace, namespaceDeclaration);
addMemberDeclarations(namespaceDeclaration);
result.addStatement(translator.getDeclarationsStatement());
result.addStatement(namespaceDeclarationStatement(namespace, namespaceDeclaration));
result.addStatement(namespaceDeclarationStatement(namespaceDeclaration));
result.addStatement(namespaceInitializeStatement());
return result;
}
private JsStatement namespaceInitializeStatement() {
JsNameRef initializeMethodReference = Namer.initializeMethodReference();
AstUtil.setQualifier(initializeMethodReference, namespaceName.makeRef());
return AstUtil.newInvocation(initializeMethodReference).makeStmt();
}
@NotNull
private JsInvocation namespaceCreateMethodInvocation(@NotNull JetNamespace namespace) {
private JsInvocation namespaceCreateMethodInvocation() {
return AstUtil.newInvocation(Namer.namespaceCreationMethodReference());
}
@NotNull
private JsStatement namespaceDeclarationStatement(@NotNull JetNamespace namespace,
@NotNull JsInvocation namespaceDeclaration) {
private JsStatement namespaceDeclarationStatement(@NotNull JsInvocation namespaceDeclaration) {
return AstUtil.newAssignmentStatement
(translationContext().getNameForElement(namespace).makeRef(), namespaceDeclaration);
}
private void addMemberDeclarations(@NotNull JetNamespace namespace,
@NotNull JsInvocation jsNamespace) {
JsObjectLiteral jsClassDescription = translateNamespaceMemberDeclarations(namespace);
private void addMemberDeclarations(@NotNull JsInvocation jsNamespace) {
JsObjectLiteral jsClassDescription = translateNamespaceMemberDeclarations();
jsNamespace.getArguments().add(jsClassDescription);
}
@NotNull
private JsObjectLiteral translateNamespaceMemberDeclarations(@NotNull JetNamespace namespace) {
private JsObjectLiteral translateNamespaceMemberDeclarations() {
List<JsPropertyInitializer> propertyList = new ArrayList<JsPropertyInitializer>();
propertyList.add(InitializerGenerator.generateInitializeMethod(namespace, translationContext()));
propertyList.addAll(new DeclarationBodyVisitor().traverseNamespace(namespace,
@@ -92,7 +92,8 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
if (setterName == null) {
return null;
}
return AstUtil.newInvocation(AstUtil.thisQualifiedReference(setterName));
JsNameRef setterReference = Translation.generateCorrectReference(translationContext(), expression, setterName);
return AstUtil.newInvocation(setterReference);
}
@Nullable
@@ -32,10 +32,10 @@ public final class ReferenceProvider {
//TODO
@NotNull
public JsNameRef generateCorrectReference() {
if (requiresThisQualifier) {
return AstUtil.thisQualifiedReference(referencedName);
} else if (requiresNamespaceQualifier) {
if (requiresNamespaceQualifier) {
return context.getNamespaceQualifiedReference(referencedName);
} else if (requiresThisQualifier) {
return AstUtil.thisQualifiedReference(referencedName);
}
return referencedName.makeRef();
}
@@ -46,9 +46,8 @@ public final class ReferenceProvider {
private boolean requiresThisQualifier(@NotNull JetSimpleNameExpression expression) {
JsName name = context.enclosingScope().findExistingName(referencedName.getIdent());
boolean isNamespaceMember = requiresNamespaceQualifier;
boolean isClassMember = context.classScope().ownsName(name);
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.jet.lang.psi.JetExpression;
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.resolve.BindingContext;
import org.jetbrains.k2js.declarations.Declarations;
@@ -32,8 +33,9 @@ public final class Translation {
}
@NotNull
static public NamespaceTranslator namespaceTranslator(@NotNull TranslationContext context) {
return NamespaceTranslator.newInstance(context);
static public JsStatement translateNamespace(@NotNull JetNamespace namespace,
@NotNull TranslationContext context) {
return NamespaceTranslator.translate(context, namespace);
}
@NotNull
@@ -76,10 +78,19 @@ public final class Translation {
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,
@NotNull Declarations declarations, @NotNull JetNamespace namespace) {
JsBlock block = result.getFragmentBlock(0);
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
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
@@ -89,12 +89,6 @@ public class KotlinLibTest extends IncludeLibraryTest {
new RhinoFunctionResultChecker("test", true));
}
@Test
public void namespacePropertyAccess() throws Exception {
runRhinoTest(Arrays.asList(kotlinLibraryPath(), cases("namespace2.js")),
new RhinoFunctionResultChecker("test", true));
}
@Test
public void isSameType() throws Exception {
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()
}