work on intrinsic implementation: binary intrinsics

This commit is contained in:
Pavel Talanov
2011-11-30 22:49:38 +04:00
parent a46fd1143a
commit 5212ee4b00
7 changed files with 90 additions and 44 deletions
@@ -1,19 +1,27 @@
package org.jetbrains.k2js.intrinsic; package org.jetbrains.k2js.intrinsic;
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.lang.psi.JetExpression;
import org.jetbrains.k2js.translate.general.TranslationContext;
import org.jetbrains.k2js.translate.operation.IntrinsicBinaryOperationTranslator;
/** /**
* @author Talanov Pavel * @author Talanov Pavel
*/ */
//public final class BinaryOperationIntrinsic implements Intrinsic { public enum BinaryOperationIntrinsic implements Intrinsic {
//
// @NotNull INSTANCE;
// private final JsBinaryOperator operator;
// /*package*/ BinaryOperationIntrinsic() {
// /*package*/ BinaryOperationIntrinsic() {} }
//
// @NotNull @NotNull
// @Override @Override
// public JsExpression apply(@NotNull JetExpression receiver, @NotNull List<JetExpression> arguments, public JsExpression apply(@NotNull JetExpression expression,
// @NotNull TranslationContext context) { @NotNull TranslationContext context) {
// //return BinaryOperationTranslator.translate() assert expression instanceof JetBinaryExpression : "This intrinsic must be applied to binary operations.";
// } return IntrinsicBinaryOperationTranslator.translate((JetBinaryExpression) expression, context);
//} }
}
@@ -5,15 +5,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.k2js.translate.general.TranslationContext; import org.jetbrains.k2js.translate.general.TranslationContext;
import java.util.List;
/** /**
* @author Talanov Pavel * @author Talanov Pavel
*/ */
public interface Intrinsic { public interface Intrinsic {
@NotNull @NotNull
public JsExpression apply(@NotNull JetExpression receiver, @NotNull List<JetExpression> arguments, public JsExpression apply(@NotNull JetExpression expression,
@NotNull TranslationContext context); @NotNull TranslationContext context);
} }
@@ -4,6 +4,7 @@ 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;
@@ -14,8 +15,8 @@ import java.util.Map;
public final class Intrinsics { public final class Intrinsics {
@NotNull @NotNull
private final Map<FunctionDescriptor, Intrinsic> descriptorToIntrinsicMap = private final Map<DeclarationDescriptor, Intrinsic> descriptorToIntrinsicMap =
new HashMap<FunctionDescriptor, Intrinsic>(); new HashMap<DeclarationDescriptor, Intrinsic>();
public static Intrinsics standardLibraryIntrinsics(@NotNull JetStandardLibrary library) { public static Intrinsics standardLibraryIntrinsics(@NotNull JetStandardLibrary library) {
return new Intrinsics(library); return new Intrinsics(library);
@@ -28,13 +29,13 @@ public final class Intrinsics {
} }
} }
/*package*/ void declareIntrinsic(@NotNull FunctionDescriptor descriptor) { /*package*/ void declareIntrinsic(@NotNull DeclarationDescriptor descriptor) {
//TODO: this is a hack //TODO: this is a hack
// addBinaryIntrinsics(descriptor); descriptorToIntrinsicMap.put(descriptor, null);
addBinaryIntrinsics(descriptor);
// addUnaryIntrinsics(descriptor); // addUnaryIntrinsics(descriptor);
// addAssignmentIntrinsics(descriptor); // addAssignmentIntrinsics(descriptor);
// addEqualsIntrinsics(descriptor); // addEqualsIntrinsics(descriptor);
descriptorToIntrinsicMap.put(descriptor, null);
} }
// private void addEqualsIntrinsics(FunctionDescriptor descriptor) { // private void addEqualsIntrinsics(FunctionDescriptor descriptor) {
@@ -53,16 +54,14 @@ public final class Intrinsics {
// } // }
// } // }
// //
// private void addBinaryIntrinsics(@NotNull FunctionDescriptor descriptor) { private void addBinaryIntrinsics(@NotNull DeclarationDescriptor descriptor) {
// String functionName = descriptor.getName(); String functionName = descriptor.getName();
// if (OperatorConventions.BINARY_OPERATION_NAMES.containsValue(functionName)) { if (OperatorConventions.BINARY_OPERATION_NAMES.containsValue(functionName)) {
// JetToken token = OperatorConventions.getTokenForMethodName(functionName); descriptorToIntrinsicMap.put(descriptor, BinaryOperationIntrinsic.INSTANCE);
//// BinaryOperationIntrinsic binaryOperationIntrinsic = }
//// new BinaryOperationIntrinsic(OperatorTable.getBinaryOperator(token)); }
//// descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic);
// } //
// }
//
// private void addAssignmentIntrinsics(@NotNull FunctionDescriptor descriptor) { // private void addAssignmentIntrinsics(@NotNull FunctionDescriptor descriptor) {
// String functionName = descriptor.getName(); // String functionName = descriptor.getName();
// if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsValue(functionName)) { // if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsValue(functionName)) {
@@ -78,4 +77,10 @@ public final class Intrinsics {
} }
return false; return false;
} }
public Intrinsic getIntrinsic(@NotNull DeclarationDescriptor descriptor) {
Intrinsic intrinsic = descriptorToIntrinsicMap.get(descriptor);
// assert intrinsic != null;
return intrinsic;
}
} }
@@ -11,7 +11,7 @@ import org.jetbrains.jet.lang.resolve.constants.NullValue;
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.general.TranslatorVisitor; import org.jetbrains.k2js.translate.general.TranslatorVisitor;
import org.jetbrains.k2js.translate.operation.BinaryOperationTranslator; import org.jetbrains.k2js.translate.operation.OperationTranslator;
import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator; import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator;
import org.jetbrains.k2js.translate.reference.ArrayAccessTranslator; import org.jetbrains.k2js.translate.reference.ArrayAccessTranslator;
import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator; import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator;
@@ -94,7 +94,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull @NotNull
public JsNode visitBinaryExpression(@NotNull JetBinaryExpression expression, public JsNode visitBinaryExpression(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return BinaryOperationTranslator.translate(expression, context); return OperationTranslator.translate(expression, context);
} }
@Override @Override
@@ -12,8 +12,15 @@ import org.jetbrains.k2js.translate.general.TranslationContext;
*/ */
public final class IntrinsicBinaryOperationTranslator extends BinaryOperationTranslator { public final class IntrinsicBinaryOperationTranslator extends BinaryOperationTranslator {
protected IntrinsicBinaryOperationTranslator(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) { @NotNull
public static JsExpression translate(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
return (new IntrinsicBinaryOperationTranslator(expression, context)).translate();
}
private IntrinsicBinaryOperationTranslator(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
super(expression, context); super(expression, context);
} }
@@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
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.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.k2js.intrinsic.Intrinsic;
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.ArrayAccessTranslator;
@@ -25,18 +26,40 @@ public class OperationTranslator extends AbstractTranslator {
@NotNull @NotNull
static public JsExpression translate(@NotNull JetBinaryExpression expression, static public JsExpression translate(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
//TODO: move to translation JsExpression result = tryToApplyIntrinsic(expression, context);
if (result != null) return result;
if (ArrayAccessTranslator.canBeArraySetterCall(expression)) { if (ArrayAccessTranslator.canBeArraySetterCall(expression)) {
return ArrayAccessTranslator.translateAsArraySetterCall(expression, context); return ArrayAccessTranslator.translateAsArraySetterCall(expression, context);
} }
return translateAsBinary(expression, context);
}
BinaryOperationTranslator translator; @NotNull
private static JsExpression translateAsBinary(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
if (TranslationUtils.isIntrinsicOperation(context, expression.getOperationReference())) { if (TranslationUtils.isIntrinsicOperation(context, expression.getOperationReference())) {
translator = new IntrinsicBinaryOperationTranslator(expression, context); return IntrinsicBinaryOperationTranslator.translate(expression, context);
} else { } else {
translator = new OverloadedBinaryOperationTranslator(expression, context); return OverloadedBinaryOperationTranslator.translate(expression, context);
} }
return translator.translate(); }
@Nullable
private static JsExpression tryToApplyIntrinsic(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
DeclarationDescriptor descriptor = BindingUtils.getDescriptorForReferenceExpression
(context.bindingContext(), expression.getOperationReference());
if (descriptor == null) {
return null;
}
if (!context.intrinsics().hasDescriptor(descriptor)) {
return null;
}
//TODO: should be no nulls here
Intrinsic intrinsic = context.intrinsics().getIntrinsic(descriptor);
if (intrinsic == null) return null;
return intrinsic.apply(expression, context);
} }
protected OperationTranslator(@NotNull TranslationContext context) { protected OperationTranslator(@NotNull TranslationContext context) {
@@ -13,12 +13,17 @@ import org.jetbrains.k2js.translate.general.TranslationContext;
*/ */
public final class OverloadedBinaryOperationTranslator extends BinaryOperationTranslator { public final class OverloadedBinaryOperationTranslator extends BinaryOperationTranslator {
@NotNull
public static JsExpression translate(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
return (new OverloadedBinaryOperationTranslator(expression, context)).translate();
}
@NotNull @NotNull
private final JsNameRef operationReference; private final JsNameRef operationReference;
private OverloadedBinaryOperationTranslator(@NotNull JetBinaryExpression expression,
protected OverloadedBinaryOperationTranslator(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context) {
@NotNull TranslationContext context) {
super(expression, context); super(expression, context);
JsNameRef overloadedOperationReference = getOverloadedOperationReference(expression.getOperationReference()); JsNameRef overloadedOperationReference = getOverloadedOperationReference(expression.getOperationReference());
assert overloadedOperationReference != null; assert overloadedOperationReference != null;