work on intrinsic implementation: split binary expression translation into 2 classes
This commit is contained in:
@@ -1,31 +1,19 @@
|
|||||||
package org.jetbrains.k2js.intrinsic;
|
package org.jetbrains.k2js.intrinsic;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsThisRef;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Talanov Pavel
|
* @author Talanov Pavel
|
||||||
*/
|
*/
|
||||||
public final class BinaryOperationIntrinsic implements Intrinsic {
|
//public final class BinaryOperationIntrinsic implements Intrinsic {
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public JsExpression apply(@NotNull FunctionDescriptor descriptor, @NotNull JetExpression receiver,
|
|
||||||
@NotNull List<JetExpression> arguments) {
|
|
||||||
//TODO: implement
|
|
||||||
//
|
//
|
||||||
// JetToken correspondingToken = OperatorConventions.getTokenForMethodName(descriptor.getName());
|
// @NotNull
|
||||||
// JsBinaryOperator operator = OperatorTable.getBinaryOperator(correspondingToken);
|
// private final JsBinaryOperator operator;
|
||||||
//
|
//
|
||||||
// assert arguments.size() == 1 : "Binary operations expects 2 arguments.";
|
// /*package*/ BinaryOperationIntrinsic() {}
|
||||||
// JsExpression argument = arguments.get(0);
|
|
||||||
// assert argument != null;
|
|
||||||
//
|
//
|
||||||
// return new JsBinaryOperation(operator, receiver, argument);
|
// @NotNull
|
||||||
return new JsThisRef();
|
// @Override
|
||||||
}
|
// public JsExpression apply(@NotNull JetExpression receiver, @NotNull List<JetExpression> arguments,
|
||||||
}
|
// @NotNull TranslationContext context) {
|
||||||
|
// //return BinaryOperationTranslator.translate()
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package org.jetbrains.k2js.intrinsic;
|
|||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.k2js.translate.general.TranslationContext;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ import java.util.List;
|
|||||||
public interface Intrinsic {
|
public interface Intrinsic {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
JsExpression apply(@NotNull FunctionDescriptor descriptor, @NotNull JetExpression receiver,
|
public JsExpression apply(@NotNull JetExpression receiver, @NotNull List<JetExpression> arguments,
|
||||||
@NotNull List<JetExpression> arguments);
|
@NotNull TranslationContext context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public final class IntrinsicDeclarationVisitor extends DeclarationDescriptorVisi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitFunctionDescriptor(@NotNull FunctionDescriptor descriptor, @Nullable Void nothing) {
|
public Void visitFunctionDescriptor(@NotNull FunctionDescriptor descriptor, @Nullable Void nothing) {
|
||||||
if (!intrinsics.isIntrinsic(descriptor)) {
|
if (!intrinsics.hasDescriptor(descriptor)) {
|
||||||
intrinsics.declareIntrinsic(descriptor);
|
intrinsics.declareIntrinsic(descriptor);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package org.jetbrains.k2js.intrinsic;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Talanov Pavel
|
||||||
|
*/
|
||||||
|
public final class IntrinsicFactory {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Intrinsics intrinsics;
|
||||||
|
|
||||||
|
private IntrinsicFactory(@NotNull Intrinsics intrinsics) {
|
||||||
|
this.intrinsics = intrinsics;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public Intrinsic getIntrinsicForExpression(@NotNull FunctionDescriptor descriptor,
|
||||||
|
// @NotNull JetExpression expression,
|
||||||
|
// @NotNull TranslationContext context) {
|
||||||
|
// assert intrinsics.hasDescriptor(descriptor);
|
||||||
|
// if (JetExpression instanceof JetBinaryExpression) {
|
||||||
|
// return new BinaryOperationIntrinsic()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -35,43 +34,44 @@ public final class Intrinsics {
|
|||||||
// addUnaryIntrinsics(descriptor);
|
// addUnaryIntrinsics(descriptor);
|
||||||
// addAssignmentIntrinsics(descriptor);
|
// addAssignmentIntrinsics(descriptor);
|
||||||
// addEqualsIntrinsics(descriptor);
|
// addEqualsIntrinsics(descriptor);
|
||||||
BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic();
|
descriptorToIntrinsicMap.put(descriptor, null);
|
||||||
descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addEqualsIntrinsics(FunctionDescriptor descriptor) {
|
// private void addEqualsIntrinsics(FunctionDescriptor descriptor) {
|
||||||
BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic();
|
// //BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic();
|
||||||
String functionName = descriptor.getName();
|
// String functionName = descriptor.getName();
|
||||||
if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsValue(functionName)) {
|
// if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsValue(functionName)) {
|
||||||
descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
|
// descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void addUnaryIntrinsics(@NotNull FunctionDescriptor descriptor) {
|
// private void addUnaryIntrinsics(@NotNull FunctionDescriptor descriptor) {
|
||||||
BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic();
|
// BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic();
|
||||||
String functionName = descriptor.getName();
|
// String functionName = descriptor.getName();
|
||||||
if (OperatorConventions.UNARY_OPERATION_NAMES.containsValue(functionName)) {
|
// if (OperatorConventions.UNARY_OPERATION_NAMES.containsValue(functionName)) {
|
||||||
descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
|
// descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void addBinaryIntrinsics(@NotNull FunctionDescriptor descriptor) {
|
// private void addBinaryIntrinsics(@NotNull FunctionDescriptor descriptor) {
|
||||||
String functionName = descriptor.getName();
|
// String functionName = descriptor.getName();
|
||||||
if (OperatorConventions.BINARY_OPERATION_NAMES.containsValue(functionName)) {
|
// if (OperatorConventions.BINARY_OPERATION_NAMES.containsValue(functionName)) {
|
||||||
BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic();
|
// JetToken token = OperatorConventions.getTokenForMethodName(functionName);
|
||||||
descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
|
//// BinaryOperationIntrinsic binaryOperationIntrinsic =
|
||||||
}
|
//// new BinaryOperationIntrinsic(OperatorTable.getBinaryOperator(token));
|
||||||
}
|
//// descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
|
||||||
|
// }
|
||||||
private void addAssignmentIntrinsics(@NotNull FunctionDescriptor descriptor) {
|
// }
|
||||||
String functionName = descriptor.getName();
|
//
|
||||||
if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsValue(functionName)) {
|
// private void addAssignmentIntrinsics(@NotNull FunctionDescriptor descriptor) {
|
||||||
BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic();
|
// String functionName = descriptor.getName();
|
||||||
descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
|
// if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsValue(functionName)) {
|
||||||
}
|
// BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic();
|
||||||
}
|
// descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
|
||||||
|
// }
|
||||||
public boolean isIntrinsic(@NotNull DeclarationDescriptor descriptor) {
|
// }
|
||||||
|
//
|
||||||
|
public boolean hasDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
||||||
if (descriptor instanceof FunctionDescriptor) {
|
if (descriptor instanceof FunctionDescriptor) {
|
||||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor.getOriginal();
|
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor.getOriginal();
|
||||||
return descriptorToIntrinsicMap.containsKey(functionDescriptor);
|
return descriptorToIntrinsicMap.containsKey(functionDescriptor);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class Aliaser {
|
|||||||
static public Aliaser aliasesForStandardClasses(@NotNull JetStandardLibrary standardLibrary,
|
static public Aliaser aliasesForStandardClasses(@NotNull JetStandardLibrary standardLibrary,
|
||||||
@NotNull Namer namer) {
|
@NotNull Namer namer) {
|
||||||
Aliaser result = new Aliaser();
|
Aliaser result = new Aliaser();
|
||||||
result.setAliasForDescriptor(standardLibrary.getArray(), namer.declareStandardClass("Array"));
|
// result.setAliasForDescriptor(standardLibrary.getArray(), namer.declareStandardClass("Array"));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-106
@@ -1,141 +1,48 @@
|
|||||||
package org.jetbrains.k2js.translate.operation;
|
package org.jetbrains.k2js.translate.operation;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import com.google.dart.compiler.util.AstUtil;
|
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
|
||||||
import org.jetbrains.jet.lexer.JetToken;
|
import org.jetbrains.jet.lexer.JetToken;
|
||||||
import org.jetbrains.k2js.translate.general.Translation;
|
import org.jetbrains.k2js.translate.general.Translation;
|
||||||
import org.jetbrains.k2js.translate.general.TranslationContext;
|
import org.jetbrains.k2js.translate.general.TranslationContext;
|
||||||
import org.jetbrains.k2js.translate.reference.ArrayAccessTranslator;
|
|
||||||
import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator;
|
import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Talanov Pavel
|
* @author Talanov Pavel
|
||||||
*/
|
*/
|
||||||
public final class BinaryOperationTranslator extends OperationTranslator {
|
public abstract class BinaryOperationTranslator extends OperationTranslator {
|
||||||
|
|
||||||
@NotNull
|
|
||||||
static public JsExpression translate(@NotNull JetBinaryExpression expression,
|
|
||||||
@NotNull TranslationContext context) {
|
|
||||||
return (new BinaryOperationTranslator(expression, context)).translate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JetBinaryExpression expression;
|
private final JetBinaryExpression expression;
|
||||||
private final boolean isPropertyOnTheLeft;
|
protected final boolean isPropertyOnTheLeft;
|
||||||
private final boolean isVariableReassignment;
|
protected final boolean isVariableReassignment;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsExpression left;
|
protected final JsExpression left;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsExpression right;
|
protected final JsExpression right;
|
||||||
@Nullable
|
|
||||||
private final JsNameRef operationReference;
|
|
||||||
|
|
||||||
private BinaryOperationTranslator(@NotNull JetBinaryExpression expression,
|
protected BinaryOperationTranslator(@NotNull JetBinaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
super(context);
|
super(context);
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
this.isPropertyOnTheLeft = isPropertyAccess(expression.getLeft());
|
this.isPropertyOnTheLeft = isPropertyAccess(expression.getLeft());
|
||||||
this.isVariableReassignment = isVariableReassignment(expression);
|
this.isVariableReassignment = isVariableReassignment(expression);
|
||||||
this.operationReference = getOverloadedOperationReference(expression.getOperationReference());
|
|
||||||
this.right = translateRightExpression();
|
this.right = translateRightExpression();
|
||||||
//TODO: decide whether it is harmful to possibly translateNamespace left expression more than once
|
//TODO: decide whether it is harmful to possibly translateNamespace left expression more than once
|
||||||
this.left = translateLeftExpression();
|
this.left = translateLeftExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
JsExpression translate() {
|
abstract protected JsExpression translate();
|
||||||
if (ArrayAccessTranslator.canBeArraySetterCall(expression)) {
|
|
||||||
return ArrayAccessTranslator.translateAsArraySetterCall(expression, context());
|
|
||||||
}
|
|
||||||
if (isCompareTo()) {
|
|
||||||
return asCompareToOverload();
|
|
||||||
}
|
|
||||||
if (isOverloadedCall()) {
|
|
||||||
return asOverloadedMethodCall();
|
|
||||||
}
|
|
||||||
return asBinaryOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JsExpression asCompareToOverload() {
|
|
||||||
JetToken operationToken = getOperationToken();
|
|
||||||
assert (OperatorConventions.COMPARISON_OPERATIONS.contains(operationToken));
|
|
||||||
JsNumberLiteral zeroLiteral = program().getNumberLiteral(0);
|
|
||||||
JsBinaryOperator correspondingOperator = OperatorTable.getBinaryOperator(operationToken);
|
|
||||||
return new JsBinaryOperation(correspondingOperator, overloadedMethodInvocation(), zeroLiteral);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isOverloadedCall() {
|
|
||||||
return operationReference != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isCompareTo() {
|
|
||||||
if (operationReference == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String nameForOperationSymbol = OperatorConventions.getNameForOperationSymbol(getOperationToken());
|
|
||||||
assert nameForOperationSymbol != null : "Must have a name for overloaded operator";
|
|
||||||
return (nameForOperationSymbol.equals("compareTo"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JsExpression asOverloadedMethodCall() {
|
|
||||||
if (isPropertyOnTheLeft) {
|
|
||||||
return overloadOnProperty();
|
|
||||||
}
|
|
||||||
if (isVariableReassignment) {
|
|
||||||
return nonPropertyReassignment();
|
|
||||||
}
|
|
||||||
return overloadedMethodInvocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsExpression nonPropertyReassignment() {
|
|
||||||
assert left instanceof JsNameRef : "Reassignment should be called on l-value.";
|
|
||||||
return AstUtil.newAssignment((JsNameRef) left, overloadedMethodInvocation());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JsExpression overloadOnProperty() {
|
|
||||||
if (isVariableReassignment) {
|
|
||||||
return setterCall(overloadedMethodInvocation());
|
|
||||||
} else {
|
|
||||||
return overloadedMethodInvocation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: refactor
|
|
||||||
@NotNull
|
|
||||||
private JsExpression asBinaryOperation() {
|
|
||||||
if (isPropertyOnTheLeft && OperatorTable.isAssignment(getOperationToken())) {
|
|
||||||
return setterCall(right);
|
|
||||||
}
|
|
||||||
JetToken token = getOperationToken();
|
|
||||||
if (OperatorTable.hasCorrespondingBinaryOperator(token)) {
|
|
||||||
return new JsBinaryOperation(OperatorTable.getBinaryOperator(token), left, right);
|
|
||||||
}
|
|
||||||
if (OperatorTable.hasCorrespondingFunctionInvocation(token)) {
|
|
||||||
JsInvocation functionInvocation = OperatorTable.getCorrespondingFunctionInvocation(token);
|
|
||||||
functionInvocation.setArguments(left, right);
|
|
||||||
return functionInvocation;
|
|
||||||
}
|
|
||||||
throw new AssertionError("Unsupported token encountered: " + token.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsExpression translateLeftExpression() {
|
private JsExpression translateLeftExpression() {
|
||||||
return Translation.translateAsExpression(expression.getLeft(), context());
|
return Translation.translateAsExpression(expression.getLeft(), context());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JsExpression overloadedMethodInvocation() {
|
|
||||||
AstUtil.setQualifier(operationReference, left);
|
|
||||||
return AstUtil.newInvocation(operationReference, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression translateRightExpression() {
|
private JsExpression translateRightExpression() {
|
||||||
JetExpression rightExpression = expression.getRight();
|
JetExpression rightExpression = expression.getRight();
|
||||||
@@ -144,12 +51,12 @@ public final class BinaryOperationTranslator extends OperationTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JetToken getOperationToken() {
|
protected JetToken getOperationToken() {
|
||||||
return (JetToken) expression.getOperationToken();
|
return (JetToken) expression.getOperationToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsInvocation setterCall(@NotNull JsExpression assignTo) {
|
protected JsInvocation setterCall(@NotNull JsExpression assignTo) {
|
||||||
JsInvocation setterCall =
|
JsInvocation setterCall =
|
||||||
PropertyAccessTranslator.translateAsPropertySetterCall(expression.getLeft(), context());
|
PropertyAccessTranslator.translateAsPropertySetterCall(expression.getLeft(), context());
|
||||||
setterCall.setArguments(assignTo);
|
setterCall.setArguments(assignTo);
|
||||||
|
|||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
package org.jetbrains.k2js.translate.operation;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
||||||
|
import org.jetbrains.jet.lexer.JetToken;
|
||||||
|
import org.jetbrains.k2js.translate.general.TranslationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Talanov Pavel
|
||||||
|
*/
|
||||||
|
public final class IntrinsicBinaryOperationTranslator extends BinaryOperationTranslator {
|
||||||
|
|
||||||
|
protected IntrinsicBinaryOperationTranslator(@NotNull JetBinaryExpression expression,
|
||||||
|
@NotNull TranslationContext context) {
|
||||||
|
super(expression, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected JsExpression translate() {
|
||||||
|
return asBinaryOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: refactor
|
||||||
|
@NotNull
|
||||||
|
private JsExpression asBinaryOperation() {
|
||||||
|
if (isPropertyOnTheLeft && OperatorTable.isAssignment(getOperationToken())) {
|
||||||
|
return setterCall(right);
|
||||||
|
}
|
||||||
|
JetToken token = getOperationToken();
|
||||||
|
if (OperatorTable.hasCorrespondingBinaryOperator(token)) {
|
||||||
|
return new JsBinaryOperation(OperatorTable.getBinaryOperator(token), left, right);
|
||||||
|
}
|
||||||
|
//TODO: implement using intrinsic mechanism
|
||||||
|
// if (OperatorTable.hasCorrespondingFunctionInvocation(token)) {
|
||||||
|
// JsInvocation functionInvocation = OperatorTable.getCorrespondingFunctionInvocation(token);
|
||||||
|
// functionInvocation.setArguments(left, right);
|
||||||
|
// return functionInvocation;
|
||||||
|
// }
|
||||||
|
throw new AssertionError("Unsupported token encountered: " + token.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,18 +7,38 @@ import com.google.dart.compiler.util.AstUtil;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.k2js.translate.general.TranslationContext;
|
import org.jetbrains.k2js.translate.general.TranslationContext;
|
||||||
|
import org.jetbrains.k2js.translate.reference.ArrayAccessTranslator;
|
||||||
import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator;
|
import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator;
|
||||||
import org.jetbrains.k2js.translate.utils.BindingUtils;
|
import org.jetbrains.k2js.translate.utils.BindingUtils;
|
||||||
|
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Talanov Pavel
|
* @author Talanov Pavel
|
||||||
*/
|
*/
|
||||||
public class OperationTranslator extends AbstractTranslator {
|
public class OperationTranslator extends AbstractTranslator {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
static public JsExpression translate(@NotNull JetBinaryExpression expression,
|
||||||
|
@NotNull TranslationContext context) {
|
||||||
|
//TODO: move to translation
|
||||||
|
if (ArrayAccessTranslator.canBeArraySetterCall(expression)) {
|
||||||
|
return ArrayAccessTranslator.translateAsArraySetterCall(expression, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryOperationTranslator translator;
|
||||||
|
if (TranslationUtils.isIntrinsicOperation(context, expression.getOperationReference())) {
|
||||||
|
translator = new IntrinsicBinaryOperationTranslator(expression, context);
|
||||||
|
} else {
|
||||||
|
translator = new OverloadedBinaryOperationTranslator(expression, context);
|
||||||
|
}
|
||||||
|
return translator.translate();
|
||||||
|
}
|
||||||
|
|
||||||
protected OperationTranslator(@NotNull TranslationContext context) {
|
protected OperationTranslator(@NotNull TranslationContext context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
@@ -29,7 +49,7 @@ public class OperationTranslator extends AbstractTranslator {
|
|||||||
if (operationDescriptor == null) {
|
if (operationDescriptor == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (context().intrinsics().isIntrinsic(operationDescriptor)) {
|
if (context().intrinsics().hasDescriptor(operationDescriptor)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!context().isDeclared(operationDescriptor)) {
|
if (!context().isDeclared(operationDescriptor)) {
|
||||||
|
|||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
package org.jetbrains.k2js.translate.operation;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
|
import com.google.dart.compiler.util.AstUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
||||||
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
|
import org.jetbrains.jet.lexer.JetToken;
|
||||||
|
import org.jetbrains.k2js.translate.general.TranslationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Talanov Pavel
|
||||||
|
*/
|
||||||
|
public final class OverloadedBinaryOperationTranslator extends BinaryOperationTranslator {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final JsNameRef operationReference;
|
||||||
|
|
||||||
|
|
||||||
|
protected OverloadedBinaryOperationTranslator(@NotNull JetBinaryExpression expression,
|
||||||
|
@NotNull TranslationContext context) {
|
||||||
|
super(expression, context);
|
||||||
|
JsNameRef overloadedOperationReference = getOverloadedOperationReference(expression.getOperationReference());
|
||||||
|
assert overloadedOperationReference != null;
|
||||||
|
this.operationReference = overloadedOperationReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected JsExpression translate() {
|
||||||
|
if (isCompareTo()) {
|
||||||
|
return asCompareToOverload();
|
||||||
|
}
|
||||||
|
return asOverloadedMethodCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsExpression asCompareToOverload() {
|
||||||
|
JetToken operationToken = getOperationToken();
|
||||||
|
assert (OperatorConventions.COMPARISON_OPERATIONS.contains(operationToken));
|
||||||
|
JsNumberLiteral zeroLiteral = program().getNumberLiteral(0);
|
||||||
|
JsBinaryOperator correspondingOperator = OperatorTable.getBinaryOperator(operationToken);
|
||||||
|
return new JsBinaryOperation(correspondingOperator, overloadedMethodInvocation(), zeroLiteral);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isCompareTo() {
|
||||||
|
String nameForOperationSymbol = OperatorConventions.getNameForOperationSymbol(getOperationToken());
|
||||||
|
assert nameForOperationSymbol != null : "Must have a name for overloaded operator";
|
||||||
|
return (nameForOperationSymbol.equals("compareTo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsExpression asOverloadedMethodCall() {
|
||||||
|
if (isPropertyOnTheLeft && isVariableReassignment) {
|
||||||
|
return propertyReassignment();
|
||||||
|
}
|
||||||
|
if (isVariableReassignment) {
|
||||||
|
return nonPropertyReassignment();
|
||||||
|
}
|
||||||
|
return overloadedMethodInvocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsInvocation propertyReassignment() {
|
||||||
|
return setterCall(overloadedMethodInvocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsExpression nonPropertyReassignment() {
|
||||||
|
assert left instanceof JsNameRef : "Reassignment should be called on l-value.";
|
||||||
|
return AstUtil.newAssignment((JsNameRef) left, overloadedMethodInvocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JsExpression overloadedMethodInvocation() {
|
||||||
|
AstUtil.setQualifier(operationReference, left);
|
||||||
|
return AstUtil.newInvocation(operationReference, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ public final class ArrayAccessTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
|
|
||||||
public static boolean canBeArraySetterCall(@NotNull JetBinaryExpression expression) {
|
public static boolean canBeArraySetterCall(@NotNull JetBinaryExpression expression) {
|
||||||
//TODO: move unsafe cat to util
|
//TODO: move unsafe call to util
|
||||||
return (OperatorTable.isAssignment((JetToken) expression.getOperationToken())
|
return (OperatorTable.isAssignment((JetToken) expression.getOperationToken())
|
||||||
&& (expression.getLeft() instanceof JetArrayAccessExpression));
|
&& (expression.getLeft() instanceof JetArrayAccessExpression));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
|||||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
|
||||||
import org.jetbrains.jet.lang.psi.ValueArgument;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||||
import org.jetbrains.k2js.translate.general.Translation;
|
import org.jetbrains.k2js.translate.general.Translation;
|
||||||
import org.jetbrains.k2js.translate.general.TranslationContext;
|
import org.jetbrains.k2js.translate.general.TranslationContext;
|
||||||
@@ -25,28 +22,28 @@ import java.util.List;
|
|||||||
public final class TranslationUtils {
|
public final class TranslationUtils {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
static public JsBinaryOperation notNullCheck(@NotNull TranslationContext context,
|
public static JsBinaryOperation notNullCheck(@NotNull TranslationContext context,
|
||||||
@NotNull JsExpression expressionToCheck) {
|
@NotNull JsExpression expressionToCheck) {
|
||||||
JsNullLiteral nullLiteral = context.program().getNullLiteral();
|
JsNullLiteral nullLiteral = context.program().getNullLiteral();
|
||||||
return AstUtil.notEqual(expressionToCheck, nullLiteral);
|
return AstUtil.notEqual(expressionToCheck, nullLiteral);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
static public JsBinaryOperation isNullCheck(@NotNull TranslationContext context,
|
public static JsBinaryOperation isNullCheck(@NotNull TranslationContext context,
|
||||||
@NotNull JsExpression expressionToCheck) {
|
@NotNull JsExpression expressionToCheck) {
|
||||||
JsNullLiteral nullLiteral = context.program().getNullLiteral();
|
JsNullLiteral nullLiteral = context.program().getNullLiteral();
|
||||||
return AstUtil.equals(expressionToCheck, nullLiteral);
|
return AstUtil.equals(expressionToCheck, nullLiteral);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
static public JsName getLocalReferencedName(@NotNull TranslationContext context,
|
public static JsName getLocalReferencedName(@NotNull TranslationContext context,
|
||||||
@NotNull String name) {
|
@NotNull String name) {
|
||||||
return context.enclosingScope().findExistingName(name);
|
return context.enclosingScope().findExistingName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
static public List<JsExpression> translateArgumentList(@NotNull List<? extends ValueArgument> jetArguments,
|
public static List<JsExpression> translateArgumentList(@NotNull List<? extends ValueArgument> jetArguments,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
List<JsExpression> jsArguments = new ArrayList<JsExpression>();
|
List<JsExpression> jsArguments = new ArrayList<JsExpression>();
|
||||||
for (ValueArgument argument : jetArguments) {
|
for (ValueArgument argument : jetArguments) {
|
||||||
@@ -56,7 +53,7 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
static public JsExpression translateArgument(@NotNull TranslationContext context, @NotNull ValueArgument argument) {
|
public static JsExpression translateArgument(@NotNull TranslationContext context, @NotNull ValueArgument argument) {
|
||||||
JetExpression jetExpression = argument.getArgumentExpression();
|
JetExpression jetExpression = argument.getArgumentExpression();
|
||||||
if (jetExpression == null) {
|
if (jetExpression == null) {
|
||||||
throw new AssertionError("Argument with no expression encountered!");
|
throw new AssertionError("Argument with no expression encountered!");
|
||||||
@@ -65,21 +62,21 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
static public JsNameRef backingFieldReference(@NotNull TranslationContext context,
|
public static JsNameRef backingFieldReference(@NotNull TranslationContext context,
|
||||||
@NotNull JetProperty expression) {
|
@NotNull JetProperty expression) {
|
||||||
JsName backingFieldName = getBackingFieldName(getPropertyName(expression), context);
|
JsName backingFieldName = getBackingFieldName(getPropertyName(expression), context);
|
||||||
return getThisQualifiedNameReference(context, backingFieldName);
|
return getThisQualifiedNameReference(context, backingFieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
static public JsNameRef backingFieldReference(@NotNull TranslationContext context,
|
public static JsNameRef backingFieldReference(@NotNull TranslationContext context,
|
||||||
@NotNull PropertyDescriptor descriptor) {
|
@NotNull PropertyDescriptor descriptor) {
|
||||||
JsName backingFieldName = getBackingFieldName(descriptor.getName(), context);
|
JsName backingFieldName = getBackingFieldName(descriptor.getName(), context);
|
||||||
return getThisQualifiedNameReference(context, backingFieldName);
|
return getThisQualifiedNameReference(context, backingFieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
static public String getPropertyName(@NotNull JetProperty expression) {
|
public static String getPropertyName(@NotNull JetProperty expression) {
|
||||||
String propertyName = expression.getName();
|
String propertyName = expression.getName();
|
||||||
if (propertyName == null) {
|
if (propertyName == null) {
|
||||||
throw new AssertionError("Property with no name encountered!");
|
throw new AssertionError("Property with no name encountered!");
|
||||||
@@ -177,4 +174,14 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isIntrinsicOperation(@NotNull TranslationContext context,
|
||||||
|
@NotNull JetReferenceExpression expression) {
|
||||||
|
DeclarationDescriptor descriptor =
|
||||||
|
BindingUtils.getDescriptorForReferenceExpression(context.bindingContext(), expression);
|
||||||
|
|
||||||
|
if (descriptor == null) return true;
|
||||||
|
|
||||||
|
return (context.intrinsics().hasDescriptor(descriptor));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ fun box() : Boolean {
|
|||||||
val a = Array<Int>(4)
|
val a = Array<Int>(4)
|
||||||
a[1] = 2
|
a[1] = 2
|
||||||
a[2] = 3
|
a[2] = 3
|
||||||
return a.get(1) == 2
|
return (a[1] == 2) && (a[2] == 3)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user