From 714339317259d50d5e5623b6c69016dda960ca01 Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Tue, 19 Mar 2013 14:59:48 +0400 Subject: [PATCH] Added support bitwise operations in js translator --- .../test/semantics/BitwiseOperationsTest.java | 27 +++++++++++++++ .../PrimitiveBinaryOperationFIF.java | 21 +++++++++++- .../factories/PrimitiveUnaryOperationFIF.java | 17 +++++++--- .../test/language/BitwiseOperationsTest.kt | 34 +++++++++++++++++++ 4 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 js/js.tests/test/org/jetbrains/k2js/test/semantics/BitwiseOperationsTest.java create mode 100644 libraries/stdlib/test/language/BitwiseOperationsTest.kt diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/BitwiseOperationsTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/BitwiseOperationsTest.java new file mode 100644 index 00000000000..a936f2d7d6d --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/BitwiseOperationsTest.java @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.test.semantics; + +import junit.framework.Test; + +//NOTE: well, it has tests +@SuppressWarnings("JUnitTestCaseWithNoTests") +public final class BitwiseOperationsTest extends JsUnitTestBase { + public static Test suite() throws Exception { + return createTestSuiteForFile("libraries/stdlib/test/language/BitwiseOperationsTest.kt"); + } +} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java index bc11653fa87..5dbb4d127c7 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java @@ -18,6 +18,7 @@ package org.jetbrains.k2js.translate.intrinsic.functions.factories; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableMap; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; @@ -29,6 +30,7 @@ import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredicate; import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate; import org.jetbrains.k2js.translate.operation.OperatorTable; @@ -79,12 +81,23 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory { @NotNull private static final NamePredicate BINARY_OPERATIONS = new NamePredicate(OperatorConventions.BINARY_OPERATION_NAMES.values()); + private static final DescriptorPredicate INT_WITH_BIT_OPERATIONS = pattern("Int.or|and|xor|shl|shr|ushr"); + + private static final ImmutableMap BINARY_BITWISE_OPERATIONS = ImmutableMap.builder() + .put("or", JsBinaryOperator.BIT_OR) + .put("and", JsBinaryOperator.BIT_AND) + .put("xor", JsBinaryOperator.BIT_XOR) + .put("shl", JsBinaryOperator.SHL) + .put("shr", JsBinaryOperator.SHR) + .put("ushr", JsBinaryOperator.SHRU) + .build(); @NotNull @Override public Predicate getPredicate() { //TODO: check that it is binary operation - return Predicates.or(pattern(NamePredicate.PRIMITIVE_NUMBERS, BINARY_OPERATIONS), + return Predicates.or(INT_WITH_BIT_OPERATIONS, + pattern(NamePredicate.PRIMITIVE_NUMBERS, BINARY_OPERATIONS), pattern("Boolean.or|and|xor"), pattern("String.plus")); } @@ -98,6 +111,12 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory { if (descriptor.getName().equals(Name.identifier("rangeTo"))) { return RANGE_TO_INTRINSIC; } + if (INT_WITH_BIT_OPERATIONS.apply(descriptor)) { + JsBinaryOperator op = BINARY_BITWISE_OPERATIONS.get(descriptor.getName().getName()); + if (op != null) { + return new PrimitiveBinaryOperationFunctionIntrinsic(op); + } + } JsBinaryOperator operator = getOperator(descriptor); return new PrimitiveBinaryOperationFunctionIntrinsic(operator); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveUnaryOperationFIF.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveUnaryOperationFIF.java index a99571277f2..af747aefb74 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveUnaryOperationFIF.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/PrimitiveUnaryOperationFIF.java @@ -49,7 +49,7 @@ public enum PrimitiveUnaryOperationFIF implements FunctionIntrinsicFactory { pattern(PRIMITIVE_NUMBERS, UNARY_OPERATIONS); @NotNull private static final Predicate PRIMITIVE_UNARY_OPERATION_NAMES = - Predicates.or(UNARY_OPERATION_FOR_PRIMITIVE_NUMBER, pattern("Boolean.not")); + Predicates.or(UNARY_OPERATION_FOR_PRIMITIVE_NUMBER, pattern("Boolean.not"), pattern("Int.inv")); @NotNull private static final DescriptorPredicate NO_PARAMETERS = new DescriptorPredicate() { @Override @@ -71,8 +71,17 @@ public enum PrimitiveUnaryOperationFIF implements FunctionIntrinsicFactory { @Override public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) { Name name = descriptor.getName(); - JetToken jetToken = OperatorConventions.UNARY_OPERATION_NAMES.inverse().get(name); - final JsUnaryOperator jsOperator = OperatorTable.getUnaryOperator(jetToken); + + JsUnaryOperator jsOperator = null; + if ("inv".equals(name.getName())) { + jsOperator = JsUnaryOperator.BIT_NOT; + } + else { + JetToken jetToken = OperatorConventions.UNARY_OPERATION_NAMES.inverse().get(name); + jsOperator = OperatorTable.getUnaryOperator(jetToken); + } + + final JsUnaryOperator finalJsOperator = jsOperator; return new FunctionIntrinsic() { @NotNull @Override @@ -82,7 +91,7 @@ public enum PrimitiveUnaryOperationFIF implements FunctionIntrinsicFactory { assert receiver != null; assert arguments.size() == 0 : "Unary operator should not have arguments."; //NOTE: cannot use this for increment/decrement - return new JsPrefixOperation(jsOperator, receiver); + return new JsPrefixOperation(finalJsOperator, receiver); } }; } diff --git a/libraries/stdlib/test/language/BitwiseOperationsTest.kt b/libraries/stdlib/test/language/BitwiseOperationsTest.kt new file mode 100644 index 00000000000..6f2d976e3d1 --- /dev/null +++ b/libraries/stdlib/test/language/BitwiseOperationsTest.kt @@ -0,0 +1,34 @@ +package test + +import kotlin.test.* +import org.junit.Test as test + +class BitwiseOperationsTest { + test fun orForInt() { + assertEquals(3, 2 or 1) + } + + test fun andForInt() { + assertEquals(0, 1 and 0) + } + + test fun xorForInt() { + assertEquals(1, 2 xor 3) + } + + test fun shlForInt() { + assertEquals(4, 1 shl 2) + } + + test fun shrForInt() { + assertEquals(1, 2 shr 1) + } + + test fun ushrForInt() { + assertEquals(2147483647, -1 ushr 1) + } + + test fun invForInt() { + assertEquals(0, (-1).inv()) + } +} \ No newline at end of file