001/* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.jetbrains.k2js.translate.intrinsic.functions.factories; 018 019import com.google.common.base.Predicate; 020import com.google.common.base.Predicates; 021import com.google.dart.compiler.backend.js.ast.JsExpression; 022import com.google.dart.compiler.backend.js.ast.JsPrefixOperation; 023import com.google.dart.compiler.backend.js.ast.JsUnaryOperator; 024import org.jetbrains.annotations.NotNull; 025import org.jetbrains.annotations.Nullable; 026import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; 027import org.jetbrains.jet.lang.resolve.name.Name; 028import org.jetbrains.jet.lang.types.expressions.OperatorConventions; 029import org.jetbrains.jet.lexer.JetToken; 030import org.jetbrains.k2js.translate.context.TranslationContext; 031import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic; 032import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredicate; 033import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate; 034import org.jetbrains.k2js.translate.operation.OperatorTable; 035import org.jetbrains.k2js.translate.utils.JsDescriptorUtils; 036 037import java.util.List; 038 039import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate.PRIMITIVE_NUMBERS; 040import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern; 041 042public enum PrimitiveUnaryOperationFIF implements FunctionIntrinsicFactory { 043 044 INSTANCE; 045 046 private static final NamePredicate UNARY_OPERATIONS = new NamePredicate(OperatorConventions.UNARY_OPERATION_NAMES.values()); 047 @NotNull 048 private static final DescriptorPredicate UNARY_OPERATION_FOR_PRIMITIVE_NUMBER = 049 pattern(PRIMITIVE_NUMBERS, UNARY_OPERATIONS); 050 @NotNull 051 private static final Predicate<FunctionDescriptor> PRIMITIVE_UNARY_OPERATION_NAMES = 052 Predicates.or(UNARY_OPERATION_FOR_PRIMITIVE_NUMBER, pattern("Boolean.not"), pattern("Int.inv")); 053 @NotNull 054 private static final DescriptorPredicate NO_PARAMETERS = new DescriptorPredicate() { 055 @Override 056 public boolean apply(@Nullable FunctionDescriptor descriptor) { 057 assert descriptor != null; 058 return !JsDescriptorUtils.hasParameters(descriptor); 059 } 060 }; 061 @NotNull 062 private static final Predicate<FunctionDescriptor> PATTERN = Predicates.and(PRIMITIVE_UNARY_OPERATION_NAMES, NO_PARAMETERS); 063 064 @NotNull 065 @Override 066 public Predicate<FunctionDescriptor> getPredicate() { 067 return PATTERN; 068 } 069 070 @NotNull 071 @Override 072 public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) { 073 Name name = descriptor.getName(); 074 075 JsUnaryOperator jsOperator = null; 076 if ("inv".equals(name.asString())) { 077 jsOperator = JsUnaryOperator.BIT_NOT; 078 } 079 else { 080 JetToken jetToken = OperatorConventions.UNARY_OPERATION_NAMES.inverse().get(name); 081 jsOperator = OperatorTable.getUnaryOperator(jetToken); 082 } 083 084 final JsUnaryOperator finalJsOperator = jsOperator; 085 return new FunctionIntrinsic() { 086 @NotNull 087 @Override 088 public JsExpression apply(@Nullable JsExpression receiver, 089 @NotNull List<JsExpression> arguments, 090 @NotNull TranslationContext context) { 091 assert receiver != null; 092 assert arguments.size() == 0 : "Unary operator should not have arguments."; 093 //NOTE: cannot use this for increment/decrement 094 return new JsPrefixOperation(finalJsOperator, receiver); 095 } 096 }; 097 } 098 099}