Operator overloading: simple cases with ++ and --.

This commit is contained in:
Pavel Talanov
2011-11-23 18:15:14 +04:00
parent cee75c5d36
commit af7d79e4bd
10 changed files with 460 additions and 536 deletions
+1 -3
View File
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="IdProvider" IDEtalkID="C5E9A8C8EEE7359144ADEDA64003CE1D" />
<component name="JavadocGenerationManager">
<option name="OUTPUT_DIRECTORY" />
<option name="OPTION_SCOPE" value="protected" />
+365 -509
View File
File diff suppressed because it is too large Load Diff
@@ -19,6 +19,7 @@ import java.util.List;
* This class contains some code related to BindingContext use. Intention is not to pollute other classes.
*/
public final class BindingUtils {
private BindingUtils() {
}
@@ -44,7 +44,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
public JsNode visitBlockExpression(@NotNull JetBlockExpression jetBlock, @NotNull TranslationContext context) {
List<JetElement> statements = jetBlock.getStatements();
JsBlock jsBlock = new JsBlock();
TranslationContext newContext = context.newBlock();
TranslationContext newContext = context.newBlock(jsBlock);
for (JetElement statement : statements) {
assert statement instanceof JetExpression : "Elements in JetBlockExpression " +
"should be of type JetExpression";
@@ -26,16 +26,24 @@ public final class OperationTranslator extends AbstractTranslator {
}
@NotNull
JsPostfixOperation translatePostfixOperation(@NotNull JetPostfixExpression expression) {
JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression));
JsExpression translatePostfixOperation(@NotNull JetPostfixExpression expression) {
JsExpression baseExpression = translateBaseExpression(expression);
JsNameRef operationReference = getOverloadedOperationReference(expression);
if (operationReference != null) {
return overloadedMethodInvocation(baseExpression, operationReference);
}
JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression));
return new JsPostfixOperation(operator, baseExpression);
}
@NotNull
JsPrefixOperation translatePrefixOperation(@NotNull JetPrefixExpression expression) {
JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression));
JsExpression translatePrefixOperation(@NotNull JetPrefixExpression expression) {
JsExpression baseExpression = translateBaseExpression(expression);
JsNameRef operationReference = getOverloadedOperationReference(expression);
if (operationReference != null) {
return overloadedMethodInvocation(baseExpression, operationReference);
}
JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression));
return new JsPrefixOperation(operator, baseExpression);
}
@@ -46,6 +54,12 @@ public final class OperationTranslator extends AbstractTranslator {
return Translation.translateAsExpression(baseExpression, translationContext());
}
@NotNull
private JsExpression overloadedMethodInvocation(@NotNull JsExpression base, @NotNull JsNameRef operationReference) {
AstUtil.setQualifier(operationReference, base);
return AstUtil.newInvocation(operationReference);
}
@NotNull
private JetToken getOperationToken(@NotNull JetUnaryExpression expression) {
JetSimpleNameExpression operationExpression = expression.getOperationSign();
@@ -104,14 +118,13 @@ public final class OperationTranslator extends AbstractTranslator {
}
private JsExpression overloadedMethodInvocation(JsExpression left, JsExpression right, JsNameRef operationReference) {
operationReference.setQualifier(left);
AstUtil.setQualifier(operationReference, left);
return AstUtil.newInvocation(operationReference, right);
}
@Nullable
private JsNameRef getOverloadedOperationReference(@NotNull JetBinaryExpression expression) {
DeclarationDescriptor operationDescriptor = BindingUtils.getDescriptorForReferenceExpression
(translationContext().bindingContext(), expression.getOperationReference());
private JsNameRef getOverloadedOperationReference(@NotNull JetExpression expression) {
DeclarationDescriptor operationDescriptor = getOperationDescriptor(expression);
if (operationDescriptor == null) {
return null;
}
@@ -121,6 +134,20 @@ public final class OperationTranslator extends AbstractTranslator {
return translationContext().getNameForDescriptor(operationDescriptor).makeRef();
}
@Nullable
private DeclarationDescriptor getOperationDescriptor(@NotNull JetExpression expression) {
JetSimpleNameExpression operationReference = null;
if (expression instanceof JetBinaryExpression) {
operationReference = ((JetBinaryExpression) expression).getOperationReference();
}
if (expression instanceof JetUnaryExpression) {
operationReference = ((JetUnaryExpression) expression).getOperationSign();
}
assert operationReference != null : "should be applied only to unary or binary operations";
return BindingUtils.getDescriptorForReferenceExpression
(translationContext().bindingContext(), operationReference);
}
@NotNull
private JsExpression translateRightExpression(@NotNull JetBinaryExpression expression) {
JetExpression rightExpression = expression.getRight();
@@ -89,7 +89,7 @@ public final class Translation {
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);
TranslationContext context = TranslationContext.rootContext(result, bindingContext, declarations, block);
block.addStatement(Translation.translateNamespace(namespace, context));
}
@@ -1,9 +1,6 @@
package org.jetbrains.k2js.translate;
import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.backend.js.ast.JsProgram;
import com.google.dart.compiler.backend.js.ast.JsScope;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,10 +32,10 @@ public final class TranslationContext {
@NotNull
public static TranslationContext rootContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext,
@NotNull Declarations extractor) {
@NotNull Declarations extractor, @NotNull JsBlock block) {
JsScope rootScope = program.getRootScope();
Scopes scopes = new Scopes(rootScope, rootScope, rootScope);
return new TranslationContext(null, program, bindingContext, scopes, extractor);
return new TranslationContext(null, program, bindingContext, scopes, extractor, block);
}
@NotNull
@@ -51,16 +48,19 @@ public final class TranslationContext {
private final JsName namespaceName;
@NotNull
private final Declarations declarations;
@NotNull
private final JsBlock block;
private TranslationContext(@Nullable JsName namespaceName, @NotNull JsProgram program,
@NotNull BindingContext bindingContext, @NotNull Scopes scopes,
@NotNull Declarations declarations) {
@NotNull Declarations declarations, @NotNull JsBlock block) {
this.program = program;
this.bindingContext = bindingContext;
this.namespaceName = namespaceName;
this.scopes = scopes;
this.declarations = declarations;
this.block = block;
}
@NotNull
@@ -73,14 +73,14 @@ public final class TranslationContext {
JsScope namespaceScope = declarations.getScope(descriptor);
JsName namespaceName = scopes.enclosingScope.findExistingName(descriptor.getName());
Scopes newScopes = new Scopes(namespaceScope, namespaceScope, namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block);
}
@NotNull
public TranslationContext newBlock() {
public TranslationContext newBlock(@NotNull JsBlock newBlock) {
Scopes newScopes = new Scopes(new JsScope
(scopes.enclosingScope, "Scope for a block"), scopes.classScope, scopes.namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, newBlock);
}
@NotNull
@@ -92,7 +92,7 @@ public final class TranslationContext {
public TranslationContext newClass(@NotNull ClassDescriptor descriptor) {
JsScope classScope = declarations.getScope(descriptor);
Scopes newScopes = new Scopes(classScope, classScope, scopes.namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block);
}
@NotNull
@@ -114,20 +114,20 @@ public final class TranslationContext {
public TranslationContext newFunctionDeclaration(@NotNull FunctionDescriptor descriptor) {
JsScope functionScope = declarations.getScope(descriptor);
Scopes newScopes = new Scopes(functionScope, scopes.classScope, scopes.namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block);
}
@NotNull
public TranslationContext newFunctionLiteral(@NotNull JsScope correspondingScope) {
Scopes newScopes = new Scopes(correspondingScope, scopes.classScope, scopes.namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block);
}
// Note: Should be used if and only if scope has no corresponding descriptor
@NotNull
public TranslationContext newEnclosingScope(@NotNull JsScope enclosingScope) {
Scopes newScopes = new Scopes(enclosingScope, scopes.classScope, scopes.namespaceScope);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations);
return new TranslationContext(namespaceName, program, bindingContext, newScopes, declarations, block);
}
@@ -18,4 +18,14 @@ public class OperatorOverloadingTest extends TranslationTest {
public void plusOverload() throws Exception {
testFooBoxIsTrue("plusOverload.kt");
}
@Test
public void postfixInc() throws Exception {
testFooBoxIsTrue("postfixIncOverload.kt");
}
@Test
public void prefixInc() throws Exception {
testFooBoxIsTrue("prefixDecOverload.kt");
}
}
@@ -0,0 +1,16 @@
namespace foo
class MyInt() {
var b = 0
fun inc() {
b = b + 1;
}
}
fun box() : Boolean {
var c = MyInt()
c++;
return (c.b == 1);
}
@@ -0,0 +1,16 @@
namespace foo
class MyInt() {
var b = 0
fun dec() {
b = b + 1;
}
}
fun box() : Boolean {
var c = MyInt()
--c;
return (c.b == 1);
}