Finishing refactoring intrinsic. Implemented most of FunctionIntrinsics and basic BinaryOperationIntrinsics.

All test pass, need to add tests for type conversion operation though.
This commit is contained in:
Pavel V. Talanov
2012-07-13 15:10:19 +04:00
parent 961260c5c5
commit 62ad7a9b17
41 changed files with 1147 additions and 919 deletions
@@ -98,6 +98,12 @@ public class OperatorConventions {
.put(JetTokens.PLUSEQ, JetTokens.PLUS)
.put(JetTokens.MINUSEQ, JetTokens.MINUS)
.build();
//TODO: use these across frontend
public static final ImmutableBiMap<JetToken, Name> BOOLEAN_OPERATIONS = ImmutableBiMap.<JetToken, Name>builder()
.put(JetTokens.ANDAND, Name.identifier("and"))
.put(JetTokens.OROR, Name.identifier("or"))
.build();
@Nullable
public static Name getNameForOperationSymbol(@NotNull JetToken token) {
@@ -23,7 +23,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.translate.context.generator.Generator;
import org.jetbrains.k2js.translate.context.generator.Rule;
@@ -45,14 +44,12 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
*/
public final class StaticContext {
public static StaticContext generateStaticContext(@NotNull JetStandardLibrary library,
@NotNull BindingContext bindingContext,
@NotNull EcmaVersion ecmaVersion) {
public static StaticContext generateStaticContext(@NotNull BindingContext bindingContext, @NotNull EcmaVersion ecmaVersion) {
JsProgram program = new JsProgram("main");
JsRootScope jsRootScope = program.getRootScope();
Namer namer = Namer.newInstance(jsRootScope);
NamingScope scope = NamingScope.rootScope(jsRootScope);
Intrinsics intrinsics = Intrinsics.standardLibraryIntrinsics(library);
Intrinsics intrinsics = new Intrinsics();
StandardClasses standardClasses = StandardClasses.bindImplementations(namer.getKotlinScope());
return new StaticContext(program, bindingContext, namer, intrinsics, standardClasses, scope, ecmaVersion);
}
@@ -26,7 +26,7 @@ import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.factories.ArrayFIF;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import java.util.Collections;
@@ -44,12 +44,12 @@ public final class ArrayForTranslator extends ForTranslator {
@NotNull
public static JsStatement doTranslate(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
return (new ArrayForTranslator(expression, context).translate());
}
public static boolean isApplicable(@NotNull JetForExpression expression,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
JetExpression loopRange = getLoopRange(expression);
JetType rangeType = BindingUtils.getTypeForExpression(context.bindingContext(), loopRange);
//TODO: better check
@@ -70,10 +70,10 @@ public final class ArrayForTranslator extends ForTranslator {
private ArrayForTranslator(@NotNull JetForExpression forExpression, @NotNull TranslationContext context) {
super(forExpression, context);
loopRange = context.declareTemporary(Translation.translateAsExpression(getLoopRange(expression), context));
FunctionIntrinsic lengthPropertyIntrinsic = context().intrinsics().getLengthPropertyIntrinsic();
JsExpression length = lengthPropertyIntrinsic.apply(loopRange.reference(),
Collections.<JsExpression>emptyList(),
context());
JsExpression length = ArrayFIF.ARRAY_LENGTH_INTRINSIC.apply(loopRange.reference(),
Collections.<JsExpression>emptyList(),
context());
end = context().declareTemporary(length);
index = context().declareTemporary(program().getNumberLiteral(0));
}
@@ -25,7 +25,6 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.k2js.config.Config;
import org.jetbrains.k2js.facade.MainCallParameters;
import org.jetbrains.k2js.facade.exceptions.MainFunctionNotFoundException;
@@ -167,8 +166,7 @@ public final class Translation {
@NotNull MainCallParameters mainCallParameters,
@NotNull Config config) throws MainFunctionNotFoundException {
//TODO: move some of the code somewhere
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, config.getTarget());
StaticContext staticContext = StaticContext.generateStaticContext(bindingContext, config.getTarget());
JsProgram program = staticContext.getProgram();
JsBlock block = program.getGlobalBlock();
@@ -1,41 +0,0 @@
/*
* Copyright 2010-2012 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.translate.intrinsic;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lexer.JetToken;
/**
* @author Pavel Talanov
*/
public abstract class CompareToIntrinsic implements FunctionIntrinsic {
private JetToken comparisonToken = null;
@NotNull
protected JetToken getComparisonToken() {
assert comparisonToken != null : "Should use set token first";
return comparisonToken;
}
public void setComparisonToken(@NotNull JetToken comparisonToken) {
assert OperatorConventions.COMPARISON_OPERATIONS.contains(comparisonToken)
: "Should be a comparison operation";
this.comparisonToken = comparisonToken;
}
}
@@ -16,36 +16,9 @@
package org.jetbrains.k2js.translate.intrinsic;
import com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.intrinsic.array.ArrayGetIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.array.ArraySetIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.primitive.*;
import org.jetbrains.k2js.translate.intrinsic.string.CharAtIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.tuple.TupleAccessIntrinsic;
import org.jetbrains.k2js.translate.operation.OperatorTable;
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getFunctionByName;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getPropertyByName;
//TODO: class is monstrous, should be refactored.
import org.jetbrains.k2js.translate.intrinsic.functions.FunctionIntrinsics;
import org.jetbrains.k2js.translate.intrinsic.operation.BinaryOperationIntrinsics;
/**
* @author Pavel Talanov
@@ -55,249 +28,18 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getPropertyBy
public final class Intrinsics {
@NotNull
private final Map<FunctionDescriptor, FunctionIntrinsic> functionIntrinsics =
new HashMap<FunctionDescriptor, FunctionIntrinsic>();
private final FunctionIntrinsics functionIntrinsics = new FunctionIntrinsics();
@NotNull
private final Map<FunctionDescriptor, EqualsIntrinsic> equalsIntrinsics =
new HashMap<FunctionDescriptor, EqualsIntrinsic>();
@NotNull
private final Map<FunctionDescriptor, CompareToIntrinsic> compareToIntrinsics =
new HashMap<FunctionDescriptor, CompareToIntrinsic>();
@NotNull
private final FunctionIntrinsic lengthPropertyIntrinsic = new BuiltInPropertyIntrinsic("length");
public static Intrinsics standardLibraryIntrinsics(@NotNull JetStandardLibrary library) {
return new Intrinsics(library);
public BinaryOperationIntrinsics getBinaryOperationIntrinsics() {
return binaryOperationIntrinsics;
}
@NotNull
private final JetStandardLibrary library;
private Intrinsics(@NotNull JetStandardLibrary library) {
this.library = library;
declareOperatorIntrinsics();
declareStringIntrinsics();
declareTuplesIntrinsics();
declareArrayIntrinsics();
declareBooleanIntrinsics();
FunctionDescriptor intToDouble = getFunctionByName(library.getInt().getDefaultType().getMemberScope(), Name.identifier("toDouble"));
functionIntrinsics.put(intToDouble, ReturnReceiverIntrinsic.INSTANCE);
FunctionDescriptor doubleToInt = getFunctionByName(library.getDouble().getDefaultType().getMemberScope(), Name.identifier("toInt"));
functionIntrinsics.put(doubleToInt, new CallStandardMethodIntrinsic("Math.floor", true, 0));
FunctionDescriptor toStringFunction = getFunctionByName(library.getLibraryScope(), Name.identifier("toString"));
functionIntrinsics.put(toStringFunction, new BuiltInFunctionIntrinsic("toString"));
}
private void declareBooleanIntrinsics() {
FunctionDescriptor andFunction = getFunctionByName(library.getBoolean().getDefaultType().getMemberScope(), Name.identifier("and"));
functionIntrinsics.put(andFunction, PrimitiveBinaryOperationIntrinsic.newInstance(JetTokens.ANDAND));
FunctionDescriptor orFunction = getFunctionByName(library.getBoolean().getDefaultType().getMemberScope(), Name.identifier("or"));
functionIntrinsics.put(orFunction, PrimitiveBinaryOperationIntrinsic.newInstance(JetTokens.OROR));
FunctionDescriptor notFunction = getFunctionByName(library.getBoolean().getDefaultType().getMemberScope(), Name.identifier("not"));
functionIntrinsics.put(notFunction, PrimitiveUnaryOperationIntrinsic.newInstance(JetTokens.EXCL));
FunctionDescriptor xorFunction = getFunctionByName(library.getBoolean().getDefaultType().getMemberScope(), Name.identifier("xor"));
functionIntrinsics.put(xorFunction, PrimitiveBinaryOperationIntrinsic.newInstance(JsBinaryOperator.BIT_XOR));
}
private final BinaryOperationIntrinsics binaryOperationIntrinsics = new BinaryOperationIntrinsics();
@NotNull
public FunctionIntrinsic getLengthPropertyIntrinsic() {
return lengthPropertyIntrinsic;
}
private void declareTuplesIntrinsics() {
for (int tupleSize = 0; tupleSize <= JetStandardClasses.MAX_TUPLE_ORDER; ++tupleSize) {
declareTupleIntrinsics(tupleSize);
}
}
//TODO: provide generic mechanism or refactor
private void declareArrayIntrinsics() {
List<JetType> arrayTypes = getLibraryArrayTypes();
for (JetType arrayType : arrayTypes) {
declareIntrinsicsForArrayType(arrayType);
}
declareNullConstructorIntrinsic();
}
private void declareNullConstructorIntrinsic() {
FunctionDescriptor nullArrayConstructor = library.getLibraryScope().getFunctions(Name.identifier("arrayOfNulls")).iterator().next();
functionIntrinsics.put(nullArrayConstructor, new CallStandardMethodIntrinsic("Kotlin.nullArray", false, 1));
}
//TODO: some dangerous operation unchecked here
private void declareIntrinsicsForArrayType(@NotNull JetType arrayType) {
JetScope arrayMemberScope = arrayType.getMemberScope();
FunctionDescriptor setFunction = getFunctionByName(arrayMemberScope, Name.identifier("set"));
functionIntrinsics.put(setFunction, ArraySetIntrinsic.INSTANCE);
FunctionDescriptor getFunction = getFunctionByName(arrayMemberScope, Name.identifier("get"));
functionIntrinsics.put(getFunction, ArrayGetIntrinsic.INSTANCE);
PropertyDescriptor sizeProperty = getPropertyByName(arrayMemberScope, Name.identifier("size"));
functionIntrinsics.put(sizeProperty.getGetter(), lengthPropertyIntrinsic);
//TODO: excessive object creation
PropertyDescriptor indicesProperty = getPropertyByName(arrayMemberScope, Name.identifier("indices"));
functionIntrinsics.put(indicesProperty.getGetter(), new CallStandardMethodIntrinsic("Kotlin.arrayIndices", true, 0));
FunctionDescriptor iteratorFunction = getFunctionByName(arrayMemberScope, Name.identifier("iterator"));
functionIntrinsics.put(iteratorFunction, new CallStandardMethodIntrinsic("Kotlin.arrayIterator", true, 0));
ConstructorDescriptor arrayConstructor =
((ClassDescriptor) arrayMemberScope.getContainingDeclaration()).getConstructors().iterator().next();
functionIntrinsics.put(arrayConstructor, new CallStandardMethodIntrinsic("Kotlin.arrayFromFun", false, 2));
}
private List<JetType> getLibraryArrayTypes() {
List<JetType> arrayTypes = Lists.newArrayList();
for (PrimitiveType type : PrimitiveType.values()) {
arrayTypes.add(library.getPrimitiveArrayJetType(type));
}
arrayTypes.add(library.getArray().getDefaultType());
return arrayTypes;
}
private void declareTupleIntrinsics(int tupleSize) {
JetScope libraryScope = library.getLibraryScope();
assert libraryScope != null;
ClassifierDescriptor tupleDescriptor = libraryScope.getClassifier(Name.identifier("Tuple" + tupleSize));
assert tupleDescriptor != null;
declareTupleIntrinsicAccessors(tupleDescriptor, tupleSize);
}
private void declareStringIntrinsics() {
//TODO: same intrinsic for 2 different methods
PropertyDescriptor stringLengthProperty =
getPropertyByName(library.getString().getDefaultType().getMemberScope(), Name.identifier("length"));
functionIntrinsics.put(stringLengthProperty.getGetter(), lengthPropertyIntrinsic);
PropertyDescriptor charSequenceLengthProperty =
getPropertyByName(library.getCharSequence().getDefaultType().getMemberScope(), Name.identifier("length"));
functionIntrinsics.put(charSequenceLengthProperty.getGetter(), lengthPropertyIntrinsic);
FunctionDescriptor getFunction =
getFunctionByName(library.getString().getDefaultType().getMemberScope(), Name.identifier("get"));
functionIntrinsics.put(getFunction, CharAtIntrinsic.INSTANCE);
}
private void declareTupleIntrinsicAccessors(@NotNull ClassifierDescriptor tupleDescriptor,
int tupleSize) {
for (int elementIndex = 0; elementIndex < tupleSize; ++elementIndex) {
Name accessorName = Name.identifier("_" + (elementIndex + 1));
PropertyDescriptor propertyDescriptor =
getPropertyByName(tupleDescriptor.getDefaultType().getMemberScope(), accessorName);
functionIntrinsics.put(propertyDescriptor.getGetter(), new TupleAccessIntrinsic(elementIndex));
}
}
private void declareOperatorIntrinsics() {
IntrinsicDeclarationVisitor visitor = new IntrinsicDeclarationVisitor();
for (DeclarationDescriptor descriptor : library.getLibraryScope().getAllDescriptors()) {
//noinspection NullableProblems
descriptor.accept(visitor, null);
}
}
public boolean isIntrinsic(@NotNull DeclarationDescriptor descriptor) {
//NOTE: that if we want to add other intrinsics we have to modify this method
if (descriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor.getOriginal();
return (equalsIntrinsics.containsKey(functionDescriptor) ||
compareToIntrinsics.containsKey(functionDescriptor) ||
functionIntrinsics.containsKey(functionDescriptor));
}
return false;
}
//NOTE: that if we want to add other intrinsics we have to modify this method
@NotNull
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
FunctionIntrinsic intrinsic = functionIntrinsics.get(descriptor.getOriginal());
if (intrinsic == null) {
intrinsic = equalsIntrinsics.get(descriptor.getOriginal());
}
if (intrinsic == null) {
intrinsic = compareToIntrinsics.get(descriptor.getOriginal());
}
return intrinsic;
}
@NotNull
public CompareToIntrinsic getCompareToIntrinsic(@NotNull FunctionDescriptor descriptor) {
return compareToIntrinsics.get(descriptor.getOriginal());
}
@NotNull
public EqualsIntrinsic getEqualsIntrinsic(@NotNull FunctionDescriptor descriptor) {
return equalsIntrinsics.get(descriptor.getOriginal());
}
@SuppressWarnings("ConstantConditions")
private final class IntrinsicDeclarationVisitor extends DeclarationDescriptorVisitorEmptyBodies<Void, Void> {
@Override
public Void visitClassDescriptor(@NotNull ClassDescriptor descriptor, @Nullable Void nothing) {
for (DeclarationDescriptor memberDescriptor :
descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
//noinspection NullableProblems
memberDescriptor.accept(this, null);
}
return null;
}
@Override
public Void visitFunctionDescriptor(@NotNull FunctionDescriptor descriptor, @Nullable Void nothing) {
if (!isIntrinsic(descriptor)) {
declareOperatorIntrinsic(descriptor);
}
return null;
}
/*package*/ void declareOperatorIntrinsic(@NotNull FunctionDescriptor descriptor) {
tryResolveAsEqualsCompareToOrRangeToIntrinsic(descriptor);
tryResolveAsUnaryIntrinsics(descriptor);
tryResolveAsBinaryIntrinsics(descriptor);
}
private void tryResolveAsEqualsCompareToOrRangeToIntrinsic(@NotNull FunctionDescriptor descriptor) {
Name functionName = descriptor.getName();
if (functionName.equals(COMPARE_TO)) {
compareToIntrinsics.put(descriptor, PrimitiveCompareToIntrinsic.newInstance());
}
if (functionName.equals(EQUALS)) {
equalsIntrinsics.put(descriptor, PrimitiveEqualsIntrinsic.newInstance());
}
if (functionName.equals(Name.identifier("rangeTo"))) {
functionIntrinsics.put(descriptor, PrimitiveRangeToIntrinsic.newInstance());
}
}
private void tryResolveAsUnaryIntrinsics(@NotNull FunctionDescriptor descriptor) {
Name functionName = descriptor.getName();
JetToken token = UNARY_OPERATION_NAMES.inverse().get(functionName);
if (token == null) return;
if (!isUnaryOperation(descriptor)) return;
functionIntrinsics.put(descriptor, PrimitiveUnaryOperationIntrinsic.newInstance(token));
}
private void tryResolveAsBinaryIntrinsics(@NotNull FunctionDescriptor descriptor) {
Name functionName = descriptor.getName();
if (isUnaryOperation(descriptor)) return;
JetToken token = BINARY_OPERATION_NAMES.inverse().get(functionName);
if (token == null) return;
if (!OperatorTable.hasCorrespondingBinaryOperator(token)) return;
functionIntrinsics.put(descriptor, PrimitiveBinaryOperationIntrinsic.newInstance(token));
}
private boolean isUnaryOperation(@NotNull FunctionDescriptor descriptor) {
return !JsDescriptorUtils.hasParameters(descriptor);
}
public FunctionIntrinsics getFunctionIntrinsics() {
return functionIntrinsics;
}
}
@@ -1,44 +0,0 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.array;
import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import java.util.List;
/**
* @author Pavel Talanov
*/
public enum ArrayGetIntrinsic implements FunctionIntrinsic {
INSTANCE;
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
assert arguments.size() == 1 : "Array get expression must have one argument.";
JsExpression indexExpression = arguments.get(0);
return new JsArrayAccess(receiver, indexExpression);
}
}
@@ -1,47 +0,0 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.array;
import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import java.util.List;
/**
* @author Pavel Talanov
*/
public enum ArraySetIntrinsic implements FunctionIntrinsic {
INSTANCE;
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
assert arguments.size() == 2 : "Array set expression must have two arguments.";
JsExpression indexExpression = arguments.get(0);
JsExpression value = arguments.get(1);
JsArrayAccess arrayAccess = AstUtil.newArrayAccess(receiver, indexExpression);
return AstUtil.newAssignment(arrayAccess, value);
}
}
@@ -0,0 +1,107 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions;
import closurecompiler.internal.com.google.common.collect.Lists;
import closurecompiler.internal.com.google.common.collect.Maps;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.factories.*;
import java.util.List;
import java.util.Map;
/**
* @author Pavel Talanov
*/
public final class FunctionIntrinsics {
@NotNull
private static final FunctionIntrinsic NO_INTRINSIC = new FunctionIntrinsic() {
@Override
public boolean exists() {
return false;
}
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
throw new UnsupportedOperationException("FunctionIntrinsic#NO_INTRINSIC_#apply");
}
};
@NotNull
private final Map<FunctionDescriptor, FunctionIntrinsic> intrinsicCache = Maps.newHashMap();
@NotNull
private final List<FunctionIntrinsicFactory> factories = Lists.newArrayList();
public FunctionIntrinsics() {
registerFactories();
}
private void registerFactories() {
register(PrimitiveUnaryOperationFIF.INSTANCE);
register(PrimitiveBinaryOperationFIF.INSTANCE);
register(TupleGetterFIF.INSTANCE);
register(StringOperationFIF.INSTANCE);
register(ArrayFIF.INSTANCE);
register(TopLevelFIF.INSTANCE);
}
private boolean register(@NotNull FunctionIntrinsicFactory instance) {
return factories.add(instance);
}
@NotNull
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
FunctionIntrinsic intrinsic = lookUpCache(descriptor);
if (intrinsic != null) {
return intrinsic;
}
intrinsic = computeAndCacheIntrinsic(descriptor);
return intrinsic;
}
@Nullable
private FunctionIntrinsic lookUpCache(@NotNull FunctionDescriptor descriptor) {
return intrinsicCache.get(descriptor);
}
@NotNull
private FunctionIntrinsic computeAndCacheIntrinsic(@NotNull FunctionDescriptor descriptor) {
FunctionIntrinsic result = computeIntrinsic(descriptor);
intrinsicCache.put(descriptor, result);
return result;
}
@NotNull
private FunctionIntrinsic computeIntrinsic(@NotNull FunctionDescriptor descriptor) {
for (FunctionIntrinsicFactory factory : factories) {
if (factory.getPattern().apply(descriptor)) {
return factory.getIntrinsic(descriptor);
}
}
return NO_INTRINSIC;
}
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.k2js.translate.intrinsic;
package org.jetbrains.k2js.translate.intrinsic.functions.basic;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
@@ -31,7 +31,7 @@ import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
/**
* @author Pavel Talanov
*/
public final class BuiltInFunctionIntrinsic implements FunctionIntrinsic {
public final class BuiltInFunctionIntrinsic extends FunctionIntrinsic {
@NotNull
private final String functionName;
@@ -1,4 +1,4 @@
package org.jetbrains.k2js.translate.intrinsic;
package org.jetbrains.k2js.translate.intrinsic.functions.basic;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
@@ -15,7 +15,7 @@ import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
* @author Pavel Talanov
*/
//TODO: find should be usages
public final class BuiltInPropertyIntrinsic implements FunctionIntrinsic {
public final class BuiltInPropertyIntrinsic extends FunctionIntrinsic {
@NotNull
private final String propertyName;
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.k2js.translate.intrinsic;
package org.jetbrains.k2js.translate.intrinsic.functions.basic;
import com.google.common.collect.Lists;
import com.google.dart.compiler.Source;
@@ -33,7 +33,7 @@ import static org.jetbrains.k2js.translate.utils.JsAstUtils.newInvocation;
/**
* @author Pavel Talanov
*/
public final class CallStandardMethodIntrinsic implements FunctionIntrinsic {
public final class CallStandardMethodIntrinsic extends FunctionIntrinsic {
@NotNull
private final String methodName;
@@ -50,8 +50,8 @@ public final class CallStandardMethodIntrinsic implements FunctionIntrinsic {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert (receiver != null == receiverShouldBeNotNull);
assert arguments.size() == expectedParamsNumber : "Incorrect number of arguments " + arguments.size() + " when expected " + expectedParamsNumber + " on method " + methodName + " " + atLocation(receiver, arguments);
JsNameRef iteratorFunName = AstUtil.newQualifiedNameRef(methodName);
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.k2js.translate.intrinsic;
package org.jetbrains.k2js.translate.intrinsic.functions.basic;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
@@ -28,9 +28,13 @@ import java.util.List;
* <p/>
* Base for intrinsics that substitute standard function calls like Int#plus, Float#minus ... etc
*/
public interface FunctionIntrinsic {
public abstract class FunctionIntrinsic {
@NotNull
JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context);
public abstract JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context);
public boolean exists() {
return true;
}
}
@@ -0,0 +1,99 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions.factories;
import closurecompiler.internal.com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInPropertyIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.CallStandardMethodIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NameChecker;
import java.util.List;
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
/**
* @author Pavel Talanov
*/
public final class ArrayFIF {
@NotNull
private static final NameChecker ARRAYS;
static {
List<Name> arrayTypeNames = Lists.newArrayList();
for (PrimitiveType type : PrimitiveType.values()) {
arrayTypeNames.add(type.getArrayTypeName());
}
arrayTypeNames.add(Name.identifier("Array"));
ARRAYS = new NameChecker(arrayTypeNames);
}
@NotNull
private static final FunctionIntrinsic GET_INTRINSIC = new FunctionIntrinsic() {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
assert arguments.size() == 1 : "Array get expression must have one argument.";
JsExpression indexExpression = arguments.get(0);
return new JsArrayAccess(receiver, indexExpression);
}
};
@NotNull
private static final FunctionIntrinsic SET_INTRINSIC = new FunctionIntrinsic() {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
assert arguments.size() == 2 : "Array set expression must have two arguments.";
JsExpression indexExpression = arguments.get(0);
JsExpression value = arguments.get(1);
JsArrayAccess arrayAccess = AstUtil.newArrayAccess(receiver, indexExpression);
return AstUtil.newAssignment(arrayAccess, value);
}
};
@NotNull
public static final BuiltInPropertyIntrinsic ARRAY_LENGTH_INTRINSIC = new BuiltInPropertyIntrinsic("length");
@NotNull
public static final FunctionIntrinsicFactory INSTANCE = FIFBuilder.start()
.add(pattern(ARRAYS, "get"), GET_INTRINSIC)
.add(pattern(ARRAYS, "set"), SET_INTRINSIC)
.add(pattern(ARRAYS, "<get-size>"), ARRAY_LENGTH_INTRINSIC)
.add(pattern(ARRAYS, "<get-indices>"), new CallStandardMethodIntrinsic("Kotlin.arrayIndices", true, 0))
.add(pattern(ARRAYS, "iterator"), new CallStandardMethodIntrinsic("Kotlin.arrayIterator", true, 0))
.add(pattern(ARRAYS, "<init>"), new CallStandardMethodIntrinsic("Kotlin.arrayFromFun", false, 2))
.build();
private ArrayFIF() {
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions.factories;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.Pattern;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder;
import java.util.Collection;
import java.util.Map;
/**
* @author Pavel Talanov
*/
public final class FIFBuilder {
@NotNull final Map<Pattern, FunctionIntrinsic> patternToIntrinsic = Maps.newHashMap();
private FIFBuilder() {
}
@NotNull
public static FIFBuilder start() {
return new FIFBuilder();
}
@NotNull
public FIFBuilder add(@NotNull Pattern pattern, @NotNull FunctionIntrinsic intrinsic) {
patternToIntrinsic.put(pattern, intrinsic);
return this;
}
@NotNull
public FunctionIntrinsicFactory build() {
return new FunctionIntrinsicFactory() {
@NotNull
@Override
public Pattern getPattern() {
Collection<Pattern> patterns = patternToIntrinsic.keySet();
return PatternBuilder.any(patterns.toArray(new Pattern[patterns.size()]));
}
@NotNull
@Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
for (Pattern pattern : patternToIntrinsic.keySet()) {
if (pattern.apply(descriptor)) {
return patternToIntrinsic.get(pattern);
}
}
throw new IllegalStateException("Must have intrinsic for pattern.");
}
};
}
}
@@ -14,23 +14,21 @@
* limitations under the License.
*/
package org.jetbrains.k2js.translate.intrinsic;
package org.jetbrains.k2js.translate.intrinsic.functions.factories;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.Pattern;
/**
* @author Pavel Talanov
*/
public abstract class EqualsIntrinsic implements FunctionIntrinsic {
public interface FunctionIntrinsicFactory {
@NotNull
private Boolean isNegated = false;
Pattern getPattern();
public void setNegated(boolean isNegated) {
this.isNegated = isNegated;
}
protected boolean isNegated() {
return isNegated;
}
@NotNull
FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor);
}
@@ -0,0 +1,108 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions.factories;
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;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NameChecker;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.Pattern;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder;
import org.jetbrains.k2js.translate.operation.OperatorTable;
import java.util.List;
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
/**
* @author Pavel Talanov
*/
public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
INSTANCE;
@NotNull
private static final FunctionIntrinsic RANGE_TO_INTRINSIC = new FunctionIntrinsic() {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression rangeStart, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert arguments.size() == 1 : "RangeTo must have one argument.";
assert rangeStart != null;
JsExpression rangeEnd = arguments.get(0);
JsBinaryOperation rangeSize = sum(subtract(rangeEnd, rangeStart),
context.program().getNumberLiteral(1));
JsNameRef expr = AstUtil.newQualifiedNameRef("Kotlin.NumberRange");
HasArguments numberRangeConstructorInvocation = context.isEcma5() ? AstUtil.newInvocation(expr) : new JsNew(expr);
//TODO: add tests and correct expression for reversed ranges.
JsBooleanLiteral isRangeReversed = context.program().getFalseLiteral();
setArguments(numberRangeConstructorInvocation, rangeStart, rangeSize, isRangeReversed);
return (JsExpression) numberRangeConstructorInvocation;
}
};
@NotNull
private static final NameChecker BINARY_OPERATIONS = new NameChecker(OperatorConventions.BINARY_OPERATION_NAMES.values());
@NotNull
@Override
public Pattern getPattern() {
//TODO: check that it is binary operation
return PatternBuilder.any(pattern(NameChecker.PRIMITIVE_NUMBERS, BINARY_OPERATIONS),
pattern("Boolean.or|and|xor"),
pattern("String.plus"));
}
@NotNull
@Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
if (descriptor.getName().equals(Name.identifier("rangeTo"))) {
return RANGE_TO_INTRINSIC;
}
final JsBinaryOperator operator = getOperator(descriptor);
return new FunctionIntrinsic() {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert arguments.size() == 1 : "Binary operator should have a receiver and one argument";
return new JsBinaryOperation(operator, receiver, arguments.get(0));
}
};
}
@NotNull
private static JsBinaryOperator getOperator(@NotNull FunctionDescriptor descriptor) {
JetToken token = OperatorConventions.BINARY_OPERATION_NAMES.inverse().get(descriptor.getName());
if (token == null) {
token = OperatorConventions.BOOLEAN_OPERATIONS.inverse().get(descriptor.getName());
}
if (token == null) {
assert descriptor.getName().getName().equals("xor");
return JsBinaryOperator.BIT_XOR;
}
return OperatorTable.getBinaryOperator(token);
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions.factories;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsPrefixOperation;
import com.google.dart.compiler.backend.js.ast.JsUnaryOperator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NameChecker;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.Pattern;
import org.jetbrains.k2js.translate.operation.OperatorTable;
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
import java.util.List;
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.NameChecker.PRIMITIVE_NUMBERS;
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.*;
/**
* @author Pavel Talanov
*/
public enum PrimitiveUnaryOperationFIF implements FunctionIntrinsicFactory {
INSTANCE;
private static final NameChecker UNARY_OPERATIONS = new NameChecker(OperatorConventions.UNARY_OPERATION_NAMES.values());
@NotNull
private static final Pattern UNARY_OPERATION_FOR_PRIMITIVE_NUMBER =
pattern(PRIMITIVE_NUMBERS, UNARY_OPERATIONS);
@NotNull
private static final Pattern NO_PARAMETERS = new Pattern() {
@Override
public boolean apply(@NotNull FunctionDescriptor descriptor) {
return !JsDescriptorUtils.hasParameters(descriptor);
}
};
@NotNull
@Override
public Pattern getPattern() {
Pattern primitiveUnaryOperationNames = any(UNARY_OPERATION_FOR_PRIMITIVE_NUMBER, pattern("Boolean.not"));
return all(primitiveUnaryOperationNames, NO_PARAMETERS);
}
@NotNull
@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);
return new FunctionIntrinsic() {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
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);
}
};
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions.factories;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInPropertyIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.Pattern;
import java.util.List;
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newInvocation;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
/**
* @author Pavel Talanov
*/
public final class StringOperationFIF {
@NotNull
private static final Pattern GET_PATTERN = pattern("String.get");
@NotNull
private static final FunctionIntrinsic GET_INTRINSIC = new FunctionIntrinsic() {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
assert arguments.size() == 1 : "String#get expression must have 1 argument.";
//TODO: provide better way
JsNameRef charAtReference = AstUtil.newQualifiedNameRef("charAt");
setQualifier(charAtReference, receiver);
return newInvocation(charAtReference, arguments);
}
};
@NotNull
public static final FunctionIntrinsicFactory INSTANCE = FIFBuilder.start()
.add(GET_PATTERN, GET_INTRINSIC)
.add(pattern("String.<get-length>"), new BuiltInPropertyIntrinsic("length"))
.add(pattern("CharSequence.<get-length>"), new BuiltInPropertyIntrinsic("length"))
.build();
private StringOperationFIF() {
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions.factories;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInFunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.CallStandardMethodIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.Pattern;
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
/**
* @author Pavel Talanov
*/
public final class TopLevelFIF {
@NotNull
private static final Pattern EXT_TO_STRING = pattern("toString");
@NotNull
public static final FunctionIntrinsicFactory INSTANCE = FIFBuilder.start()
.add(EXT_TO_STRING, new BuiltInFunctionIntrinsic("toString"))
//TODO: add intrinsic for calling equals explicitly
.add(pattern("arrayOfNulls"), new CallStandardMethodIntrinsic("Kotlin.nullArray", false, 1))
.build();
private TopLevelFIF() {
}
}
@@ -0,0 +1,85 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions.factories;
import closurecompiler.internal.com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NameChecker;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.Pattern;
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder;
import java.util.List;
/**
* @author Pavel Talanov
*/
public enum TupleGetterFIF implements FunctionIntrinsicFactory {
INSTANCE;
@NotNull
private static final NameChecker TUPLES;
static {
List<String> tupleNames = Lists.newArrayList();
for (int tupleSize = 0; tupleSize <= JetStandardClasses.MAX_TUPLE_ORDER; ++tupleSize) {
tupleNames.add("Tuple" + tupleSize);
}
TUPLES = new NameChecker(tupleNames);
}
@NotNull
private static final NameChecker TUPLE_UNDERSCORE_ACCESSORS;
static {
List<String> accessorNames = Lists.newArrayList();
for (int tupleSize = 0; tupleSize <= JetStandardClasses.MAX_TUPLE_ORDER; ++tupleSize) {
accessorNames.add("<get-_" + (tupleSize + 1) + ">");
}
TUPLE_UNDERSCORE_ACCESSORS = new NameChecker(accessorNames);
}
@NotNull
@Override
public Pattern getPattern() {
return PatternBuilder.pattern(TUPLES, TUPLE_UNDERSCORE_ACCESSORS);
}
@NotNull
@Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
String nameString = descriptor.getName().getName();
String elementIndexSubString = nameString.substring(6, nameString.length() - 1);
final int elementIndex = Integer.parseInt(elementIndexSubString) - 1;
return new FunctionIntrinsic() {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver,
@NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert arguments.isEmpty() : "Tuple access expression should not have any arguments.";
return AstUtil.newArrayAccess(receiver, context.program().getNumberLiteral(elementIndex));
}
};
}
}
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions.patterns;
import closurecompiler.internal.com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* @author Pavel Talanov
*/
public final class NameChecker {
@NotNull
public static final NameChecker PRIMITIVE_NUMBERS = new NameChecker("Int", "Double", "Float", "Long", "Short");
@NotNull
private final List<Name> validNames = Lists.newArrayList();
public NameChecker(@NotNull String... validNames) {
this(Arrays.asList(validNames));
}
public NameChecker(@NotNull List<String> validNames) {
for (String validName : validNames) {
this.validNames.add(Name.guess(validName));
}
}
public NameChecker(@NotNull Collection<Name> validNames) {
this.validNames.addAll(validNames);
}
public boolean isValid(@NotNull Name name) {
for (Name validName : validNames) {
if (name.equals(validName)) {
return true;
}
}
return false;
}
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.k2js.translate.intrinsic;
package org.jetbrains.k2js.translate.intrinsic.functions.patterns;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
@@ -22,10 +22,7 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
/**
* @author Pavel Talanov
*/
public abstract class FunctionIntrinsicFactory {
public interface Pattern {
public abstract boolean isApplicable(@NotNull FunctionDescriptor descriptor);
@NotNull
public abstract FunctionIntrinsic createIntrinsic(@NotNull FunctionDescriptor descriptor);
boolean apply(@NotNull FunctionDescriptor descriptor);
}
@@ -0,0 +1,134 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.functions.patterns;
import closurecompiler.internal.com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Arrays;
import java.util.List;
/**
* @author Pavel Talanov
*/
public final class PatternBuilder {
public static final NameChecker JET = new NameChecker("jet");
private PatternBuilder() {
}
@NotNull
public static Pattern pattern(@NotNull NameChecker checker, @NotNull String stringWithPattern) {
List<NameChecker> checkers = Lists.newArrayList(checker);
checkers.addAll(parseStringAsCheckerList(stringWithPattern));
return pattern(checkers);
}
@NotNull
public static Pattern pattern(@NotNull String string) {
List<NameChecker> checkers = parseStringAsCheckerList(string);
return pattern(checkers);
}
@NotNull
private static List<NameChecker> parseStringAsCheckerList(@NotNull String stringWithPattern) {
String[] subPatterns = stringWithPattern.split("\\.");
List<NameChecker> checkers = Lists.newArrayList();
for (String subPattern : subPatterns) {
String[] validNames = subPattern.split("\\|");
checkers.add(new NameChecker(validNames));
}
return checkers;
}
@NotNull
private static Pattern pattern(@NotNull List<NameChecker> checkers) {
final List<NameChecker> checkersWithPrefixChecker = Lists.newArrayList(JET);
checkersWithPrefixChecker.addAll(checkers);
return new Pattern() {
@Override
public boolean apply(@NotNull FunctionDescriptor descriptor) {
//TODO: no need to wrap if we check beforehand
try {
return doApply(descriptor);
}
catch (IllegalArgumentException e) {
return false;
}
}
private boolean doApply(@NotNull FunctionDescriptor descriptor) {
List<Name> nameParts = DescriptorUtils.getFQName(descriptor).pathSegments();
if (nameParts.size() != checkersWithPrefixChecker.size()) {
return false;
}
if (!allNamePartsValid(nameParts)) return false;
return true;
}
private boolean allNamePartsValid(@NotNull List<Name> nameParts) {
for (int i = 0; i < nameParts.size(); ++i) {
Name namePart = nameParts.get(i);
NameChecker correspondingPredicate = checkersWithPrefixChecker.get(i);
if (!correspondingPredicate.isValid(namePart)) {
return false;
}
}
return true;
}
};
}
@NotNull
public static Pattern pattern(@NotNull final NameChecker... checkers) {
return pattern(Arrays.asList(checkers));
}
@NotNull
public static Pattern any(@NotNull final Pattern... patterns) {
return new Pattern() {
@Override
public boolean apply(@NotNull FunctionDescriptor descriptor) {
for (Pattern pattern : patterns) {
if (pattern.apply(descriptor)) {
return true;
}
}
return false;
}
};
}
@NotNull
public static Pattern all(@NotNull final Pattern... patterns) {
return new Pattern() {
@Override
public boolean apply(@NotNull FunctionDescriptor descriptor) {
for (Pattern pattern : patterns) {
if (!pattern.apply(descriptor)) {
return false;
}
}
return true;
}
};
}
}
@@ -14,27 +14,20 @@
* limitations under the License.
*/
package org.jetbrains.k2js.translate.intrinsic;
package org.jetbrains.k2js.translate.intrinsic.operation;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.k2js.translate.context.TranslationContext;
import java.util.List;
/**
* @author Pavel Talanov
*/
public enum ReturnReceiverIntrinsic implements FunctionIntrinsic {
public interface BinaryOperationIntrinsic {
INSTANCE;
boolean isApplicable(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context);
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
return receiver;
}
JsExpression apply(@NotNull JetBinaryExpression expression, @NotNull JsExpression left,
@NotNull JsExpression right, @NotNull TranslationContext context);
}
@@ -14,33 +14,39 @@
* limitations under the License.
*/
package org.jetbrains.k2js.translate.intrinsic.tuple;
package org.jetbrains.k2js.translate.intrinsic.operation;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.util.AstUtil;
import closurecompiler.internal.com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import java.util.List;
/**
* @author Pavel Talanov
*/
public final class TupleAccessIntrinsic implements FunctionIntrinsic {
private final int elementIndex;
public TupleAccessIntrinsic(int elementIndex) {
this.elementIndex = elementIndex;
}
public final class BinaryOperationIntrinsics {
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert arguments.isEmpty() : "Tuple access expression should not have any arguments.";
return AstUtil.newArrayAccess(receiver, context.program().getNumberLiteral(elementIndex));
private final List<BinaryOperationIntrinsic> intrinsics = Lists.newArrayList();
{
intrinsics.add(new EqualsIntrinsic());
intrinsics.add(new CompareToInstrinsic());
}
public BinaryOperationIntrinsics() {
}
@Nullable
public BinaryOperationIntrinsic getIntrinsic(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context) {
for (BinaryOperationIntrinsic intrinsic : intrinsics) {
if (intrinsic.isApplicable(expression, context)) {
return intrinsic;
}
}
return null;
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.operation;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.operation.OperatorTable;
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
/**
* @author Pavel Talanov
*/
public final class CompareToInstrinsic implements BinaryOperationIntrinsic {
@Override
public boolean isApplicable(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context) {
if (!OperatorConventions.COMPARISON_OPERATIONS.contains(getOperationToken(expression))) {
return false;
}
FunctionDescriptor functionDescriptor = getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
assert functionDescriptor != null;
return JsDescriptorUtils.isStandardDeclaration(functionDescriptor);
}
@Override
public JsExpression apply(@NotNull JetBinaryExpression expression,
@NotNull JsExpression left,
@NotNull JsExpression right,
@NotNull TranslationContext context) {
JsBinaryOperator operator = OperatorTable.getBinaryOperator(getOperationToken(expression));
return new JsBinaryOperation(operator, left, right);
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.operation;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.equality;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.inequality;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isNullLiteral;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.nullCheck;
/**
* @author Pavel Talanov
*/
public final class EqualsIntrinsic implements BinaryOperationIntrinsic {
@Override
public boolean isApplicable(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context) {
if (!OperatorConventions.EQUALS_OPERATIONS.contains(getOperationToken(expression))) {
return false;
}
FunctionDescriptor functionDescriptor = getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
assert functionDescriptor != null;
return JsDescriptorUtils.isStandardDeclaration(functionDescriptor);
}
@Override
public JsExpression apply(@NotNull JetBinaryExpression expression,
@NotNull JsExpression left,
@NotNull JsExpression right,
@NotNull TranslationContext context) {
boolean isNegated = getOperationToken(expression).equals(JetTokens.EXCLEQ);
if (isNullLiteral(context, right)) {
return nullCheck(context, left, !isNegated);
}
if (isNullLiteral(context, left)) {
return nullCheck(context, right, !isNegated);
}
if (isNegated) {
return inequality(left, right);
}
else {
return equality(left, right);
}
}
}
@@ -1,62 +0,0 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.primitive;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.operation.OperatorTable;
import java.util.List;
/**
* @author Pavel Talanov
*/
public final class PrimitiveBinaryOperationIntrinsic implements FunctionIntrinsic {
@NotNull
public static PrimitiveBinaryOperationIntrinsic newInstance(@NotNull JetToken token) {
JsBinaryOperator operator = OperatorTable.getBinaryOperator(token);
return new PrimitiveBinaryOperationIntrinsic(operator);
}
@NotNull
public static PrimitiveBinaryOperationIntrinsic newInstance(@NotNull JsBinaryOperator operator) {
return new PrimitiveBinaryOperationIntrinsic(operator);
}
@NotNull
private final JsBinaryOperator operator;
private PrimitiveBinaryOperationIntrinsic(@NotNull JsBinaryOperator operator) {
this.operator = operator;
}
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert arguments.size() == 1 : "Binary operator should have a receiver and one argument";
return new JsBinaryOperation(operator, receiver, arguments.get(0));
}
}
@@ -1,52 +0,0 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.primitive;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.CompareToIntrinsic;
import org.jetbrains.k2js.translate.operation.OperatorTable;
import java.util.List;
/**
* @author Pavel Talanov
*/
public final class PrimitiveCompareToIntrinsic extends CompareToIntrinsic {
@NotNull
public static PrimitiveCompareToIntrinsic newInstance() {
return new PrimitiveCompareToIntrinsic();
}
private PrimitiveCompareToIntrinsic() {
}
@NotNull
public JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert arguments.size() == 1 : "Equals operation should have one argument";
JsBinaryOperator operator = OperatorTable.getBinaryOperator(getComparisonToken());
JsExpression argument = arguments.get(0);
return new JsBinaryOperation(operator, receiver, argument);
}
}
@@ -1,65 +0,0 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.primitive;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.EqualsIntrinsic;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.equality;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.inequality;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isNullLiteral;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.nullCheck;
/**
* @author Pavel Talanov
*/
public final class PrimitiveEqualsIntrinsic extends EqualsIntrinsic {
@NotNull
public static PrimitiveEqualsIntrinsic newInstance() {
return new PrimitiveEqualsIntrinsic();
}
private PrimitiveEqualsIntrinsic() {
}
@Override
@NotNull
public JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert arguments.size() == 1 : "Equals operation should have one argument";
assert receiver != null;
JsExpression argument = arguments.get(0);
if (isNullLiteral(context, argument)) {
return nullCheck(context, receiver, !isNegated());
}
if (isNullLiteral(context, receiver)) {
return nullCheck(context, argument, !isNegated());
}
if (isNegated()) {
return inequality(receiver, argument);
}
else {
return equality(receiver, argument);
}
}
}
@@ -1,60 +0,0 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.primitive;
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;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
/**
* @author Pavel Talanov
*/
public final class PrimitiveRangeToIntrinsic implements FunctionIntrinsic {
@NotNull
public static PrimitiveRangeToIntrinsic newInstance() {
return new PrimitiveRangeToIntrinsic();
}
private PrimitiveRangeToIntrinsic() {
}
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression rangeStart, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert arguments.size() == 1 : "RangeTo must have one argument.";
assert rangeStart != null;
JsExpression rangeEnd = arguments.get(0);
JsBinaryOperation rangeSize = sum(subtract(rangeEnd, rangeStart),
context.program().getNumberLiteral(1));
//TODO: provide a way not to hard code this value
JsNameRef expr = AstUtil.newQualifiedNameRef("Kotlin.NumberRange");
HasArguments numberRangeConstructorInvocation = context.isEcma5() ? AstUtil.newInvocation(expr) : new JsNew(expr);
//TODO: add tests and correct expression for reversed ranges.
JsBooleanLiteral isRangeReversed = context.program().getFalseLiteral();
setArguments(numberRangeConstructorInvocation, rangeStart, rangeSize, isRangeReversed);
return (JsExpression) numberRangeConstructorInvocation;
}
}
@@ -1,58 +0,0 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.primitive;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsPrefixOperation;
import com.google.dart.compiler.backend.js.ast.JsUnaryOperator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.operation.OperatorTable;
import java.util.List;
/**
* @author Pavel Talanov
*/
public final class PrimitiveUnaryOperationIntrinsic implements FunctionIntrinsic {
@NotNull
public static PrimitiveUnaryOperationIntrinsic newInstance(@NotNull JetToken token) {
JsUnaryOperator operator = OperatorTable.getUnaryOperator(token);
return new PrimitiveUnaryOperationIntrinsic(operator);
}
@NotNull
private final JsUnaryOperator operator;
private PrimitiveUnaryOperationIntrinsic(@NotNull JsUnaryOperator operator) {
this.operator = operator;
}
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
assert arguments.size() == 0 : "Unary operator should not have arguments.";
//NOTE: cannot use this for increment/decrement
return new JsPrefixOperation(operator, receiver);
}
}
@@ -1,50 +0,0 @@
/*
* Copyright 2010-2012 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.translate.intrinsic.string;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newInvocation;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
/**
* @author Pavel Talanov
*/
public enum CharAtIntrinsic implements FunctionIntrinsic {
INSTANCE;
@NotNull
@Override
public JsExpression apply(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull TranslationContext context) {
assert receiver != null;
assert arguments.size() == 1 : "get Char expression must have 1 arguments.";
//TODO: provide better way
JsNameRef charAtReference = AstUtil.newQualifiedNameRef("charAt");
setQualifier(charAtReference, receiver);
return newInvocation(charAtReference, arguments);
}
}
@@ -29,7 +29,7 @@ import org.jetbrains.k2js.translate.reference.AccessTranslator;
import static org.jetbrains.k2js.translate.utils.BindingUtils.isVariableReassignment;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
import static org.jetbrains.k2js.translate.utils.PsiUtils.isAssignment;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isIntrinsicOperation;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.hasCorrespondingFunctionIntrinsic;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateRightExpression;
/**
@@ -46,7 +46,7 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
@NotNull
public static JsExpression translate(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
if (isIntrinsicOperation(context, expression)) {
if (hasCorrespondingFunctionIntrinsic(context, expression)) {
return IntrinsicAssignmentTranslator.doTranslate(expression, context);
}
return OverloadedAssignmentTranslator.doTranslate(expression, context);
@@ -30,7 +30,7 @@ import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.intrinsic.EqualsIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.operation.BinaryOperationIntrinsic;
import org.jetbrains.k2js.translate.reference.CallBuilder;
import org.jetbrains.k2js.translate.reference.CallType;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
@@ -40,9 +40,9 @@ import static org.jetbrains.k2js.translate.operation.CompareToTranslator.isCompa
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.not;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.isEquals;
import static org.jetbrains.k2js.translate.utils.PsiUtils.*;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.*;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateLeftExpression;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateRightExpression;
/**
@@ -78,6 +78,10 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
@NotNull
private JsExpression translate() {
BinaryOperationIntrinsic intrinsic = getIntrinsicForExpression();
if (intrinsic != null) {
return applyIntrinsic(intrinsic);
}
if (isElvisOperator(expression)) {
return translateAsElvisOperator(expression);
}
@@ -92,12 +96,22 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
}
assert operationDescriptor != null :
"Overloadable operations must have not null descriptor";
if (isEquals(operationDescriptor) && context().intrinsics().isIntrinsic(operationDescriptor)) {
return translateAsEqualsIntrinsic();
}
return translateAsOverloadedBinaryOperation();
}
@Nullable
private BinaryOperationIntrinsic getIntrinsicForExpression() {
return context().intrinsics().getBinaryOperationIntrinsics().getIntrinsic(expression, context());
}
@NotNull
private JsExpression applyIntrinsic(@NotNull BinaryOperationIntrinsic intrinsic) {
return intrinsic.apply(expression,
translateLeftExpression(context(), expression),
translateRightExpression(context(), expression),
context());
}
private static boolean isElvisOperator(@NotNull JetBinaryExpression expression) {
return getOperationToken(expression).equals(JetTokens.ELVIS);
}
@@ -115,14 +129,6 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
return operationDescriptor == null;
}
@NotNull
private JsExpression translateAsEqualsIntrinsic() {
assert operationDescriptor != null : "Equals operation must resolve to descriptor.";
EqualsIntrinsic intrinsic = context().intrinsics().getEqualsIntrinsic(operationDescriptor);
intrinsic.setNegated(expression.getOperationToken().equals(JetTokens.EXCLEQ));
return applyIntrinsicToBinaryExpression(context(), intrinsic, expression);
}
@NotNull
private JsExpression translateAsUnOverloadableBinaryOperation() {
JetToken token = getOperationToken(expression);
@@ -23,17 +23,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
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.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.intrinsic.CompareToIntrinsic;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.isCompareTo;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.applyIntrinsicToBinaryExpression;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isIntrinsicOperation;
/**
* @author Pavel Talanov
@@ -41,7 +37,7 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.isIntrinsicOpe
public final class CompareToTranslator extends AbstractTranslator {
public static boolean isCompareToCall(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
FunctionDescriptor operationDescriptor =
getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
@@ -52,47 +48,27 @@ public final class CompareToTranslator extends AbstractTranslator {
@NotNull
public static JsExpression translate(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
return (new CompareToTranslator(expression, context)).translate();
}
@NotNull
private final JetBinaryExpression expression;
@NotNull
private final FunctionDescriptor descriptor;
private CompareToTranslator(@NotNull JetBinaryExpression expression,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
super(context);
this.expression = expression;
FunctionDescriptor functionDescriptor =
getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
assert functionDescriptor != null : "CompareTo should always have a descriptor";
this.descriptor = functionDescriptor;
assert (OperatorConventions.COMPARISON_OPERATIONS.contains(getOperationToken(expression)));
}
@NotNull
private JsExpression translate() {
if (isIntrinsicOperation(context(), expression)) {
return intrinsicCompareTo();
}
return overloadedCompareTo();
}
@NotNull
private JsExpression overloadedCompareTo() {
JsBinaryOperator correspondingOperator = OperatorTable.getBinaryOperator(getOperationToken(expression));
JsExpression methodCall = BinaryOperationTranslator.translateAsOverloadedCall(expression, context());
return new JsBinaryOperation(correspondingOperator, methodCall, TranslationUtils.zeroLiteral(context()));
}
@NotNull
private JsExpression intrinsicCompareTo() {
CompareToIntrinsic intrinsic = context().intrinsics().getCompareToIntrinsic(descriptor);
intrinsic.setComparisonToken((JetToken) expression.getOperationToken());
return applyIntrinsicToBinaryExpression(context(), intrinsic, expression);
}
}
@@ -34,7 +34,7 @@ import static org.jetbrains.k2js.translate.reference.AccessTranslationUtils.getC
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newSequence;
import static org.jetbrains.k2js.translate.utils.PsiUtils.*;
import static org.jetbrains.k2js.translate.utils.TemporariesUtils.temporariesInitialization;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isIntrinsicOperation;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.hasCorrespondingFunctionIntrinsic;
/**
* @author Pavel Talanov
@@ -49,7 +49,7 @@ public abstract class IncrementTranslator extends AbstractTranslator {
@NotNull
public static JsExpression translate(@NotNull JetUnaryExpression expression,
@NotNull TranslationContext context) {
if (isIntrinsicOperation(context, expression)) {
if (hasCorrespondingFunctionIntrinsic(context, expression)) {
return IntrinsicIncrementTranslator.doTranslate(expression, context);
}
return (new OverloadedIncrementTranslator(expression, context)).translateIncrementExpression();
@@ -27,7 +27,7 @@ import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.VariableAsFunctionResolvedCall;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
import org.jetbrains.k2js.translate.utils.ErrorReportingUtils;
@@ -119,14 +119,19 @@ public final class CallTranslator extends AbstractTranslator {
}
private boolean isIntrinsic() {
return context().intrinsics().isIntrinsic(descriptor);
if (descriptor instanceof FunctionDescriptor) {
FunctionIntrinsic intrinsic = context().intrinsics().getFunctionIntrinsics().getIntrinsic((FunctionDescriptor) descriptor);
return intrinsic.exists();
}
return false;
}
@NotNull
private JsExpression intrinsicInvocation() {
assert descriptor instanceof FunctionDescriptor;
try {
FunctionIntrinsic intrinsic = context().intrinsics().getIntrinsic((FunctionDescriptor) descriptor);
FunctionIntrinsic intrinsic = context().intrinsics().getFunctionIntrinsics().getIntrinsic((FunctionDescriptor) descriptor);
assert intrinsic.exists();
return intrinsic.apply(callParameters.getThisOrReceiverOrNull(), arguments, context());
}
catch (RuntimeException e) {
@@ -25,17 +25,19 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.k2js.config.LibrarySourcesConfig;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
import static org.jetbrains.k2js.translate.utils.BindingUtils.isNotAny;
/**
* @author Pavel Talanov
@@ -53,10 +55,6 @@ public final class JsDescriptorUtils {
return (valueParametersCount(functionDescriptor) > 0);
}
public static boolean isEquals(@NotNull FunctionDescriptor functionDescriptor) {
return (functionDescriptor.getName().equals(OperatorConventions.EQUALS));
}
public static boolean isCompareTo(@NotNull FunctionDescriptor functionDescriptor) {
return (functionDescriptor.getName().equals(OperatorConventions.COMPARE_TO));
}
@@ -65,34 +63,6 @@ public final class JsDescriptorUtils {
return (descriptor instanceof ConstructorDescriptor);
}
@NotNull
public static FunctionDescriptor getFunctionByName(@NotNull JetScope scope,
@NotNull Name name) {
Collection<FunctionDescriptor> functionDescriptors = scope.getFunctions(name);
assert functionDescriptors.size() == 1 :
"In scope " + scope + " supposed to be exactly one " + name + " function.\n" +
"Found: " + functionDescriptors.size();
//noinspection LoopStatementThatDoesntLoop
for (FunctionDescriptor descriptor : functionDescriptors) {
return descriptor;
}
throw new AssertionError("In scope " + scope
+ " supposed to be exactly one " + name + " function.");
}
//TODO: some strange stuff happening to this method
//TODO: inspect
@NotNull
public static PropertyDescriptor getPropertyByName(@NotNull JetScope scope,
@NotNull Name name) {
Collection<VariableDescriptor> variables = scope.getProperties(name);
assert variables.size() == 1 : "Actual size: " + variables.size();
VariableDescriptor variable = variables.iterator().next();
PropertyDescriptor descriptor = (PropertyDescriptor)variable;
assert descriptor != null : "Must have a descriptor.";
return descriptor;
}
@Nullable
public static ClassDescriptor findAncestorClass(@NotNull List<ClassDescriptor> superclassDescriptors) {
for (ClassDescriptor descriptor : superclassDescriptors) {
@@ -103,9 +73,31 @@ public final class JsDescriptorUtils {
return null;
}
@NotNull
public static List<ClassDescriptor> getSuperclassDescriptors(@NotNull ClassDescriptor classDescriptor) {
Collection<? extends JetType> superclassTypes = classDescriptor.getTypeConstructor().getSupertypes();
List<ClassDescriptor> superClassDescriptors = new ArrayList<ClassDescriptor>();
for (JetType type : superclassTypes) {
ClassDescriptor result = getClassDescriptorForType(type);
if (isNotAny(result)) {
superClassDescriptors.add(result);
}
}
return superClassDescriptors;
}
@Nullable
public static ClassDescriptor getSuperclass(@NotNull ClassDescriptor classDescriptor) {
return findAncestorClass(DescriptorUtils.getSuperclassDescriptors(classDescriptor));
return findAncestorClass(getSuperclassDescriptors(classDescriptor));
}
@NotNull
public static ClassDescriptor getClassDescriptorForType(@NotNull JetType type) {
DeclarationDescriptor superClassDescriptor =
type.getConstructor().getDeclarationDescriptor();
assert superClassDescriptor instanceof ClassDescriptor
: "Superclass descriptor of a type should be of type ClassDescriptor";
return (ClassDescriptor) superClassDescriptor;
}
@@ -132,9 +124,9 @@ public final class JsDescriptorUtils {
@NotNull
public static DeclarationDescriptor getDeclarationDescriptorForReceiver
(@NotNull ReceiverDescriptor receiverParameter) {
(@NotNull ReceiverDescriptor receiverParameter) {
DeclarationDescriptor declarationDescriptor =
receiverParameter.getType().getConstructor().getDeclarationDescriptor();
receiverParameter.getType().getConstructor().getDeclarationDescriptor();
//TODO: WHY assert?
assert declarationDescriptor != null;
return declarationDescriptor.getOriginal();
@@ -155,13 +147,26 @@ public final class JsDescriptorUtils {
DeclarationDescriptor containing = descriptor.getContainingDeclaration();
while (containing != null) {
if (containing instanceof ClassDescriptor && !isClassObject(containing)) {
return (ClassDescriptor)containing;
return (ClassDescriptor) containing;
}
containing = containing.getContainingDeclaration();
}
return null;
}
@Nullable
public static NamespaceDescriptor getContainingNamespace(@NotNull DeclarationDescriptor descriptor) {
return DescriptorUtils.getParentOfType(descriptor, NamespaceDescriptor.class);
}
public static boolean isStandardDeclaration(@NotNull DeclarationDescriptor descriptor) {
NamespaceDescriptor namespace = getContainingNamespace(descriptor);
if (namespace == null) {
return false;
}
return namespace.equals(JetStandardLibrary.getInstance().getLibraryScope().getContainingDeclaration());
}
@NotNull
public static List<NamespaceDescriptor> getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor,
@NotNull BindingContext context) {
@@ -232,7 +237,7 @@ public final class JsDescriptorUtils {
while (!(current.getContainingDeclaration() instanceof ModuleDescriptor)) {
result.add(current);
if (current.getContainingDeclaration() instanceof NamespaceDescriptor) {
current = (NamespaceDescriptor)current.getContainingDeclaration();
current = (NamespaceDescriptor) current.getContainingDeclaration();
assert current != null;
}
else {
@@ -26,10 +26,8 @@ import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.google.dart.compiler.util.AstUtil.newAssignment;
@@ -205,13 +203,12 @@ public final class TranslationUtils {
return Translation.translateAsExpression(rightExpression, context);
}
public static boolean isIntrinsicOperation(@NotNull TranslationContext context,
public static boolean hasCorrespondingFunctionIntrinsic(@NotNull TranslationContext context,
@NotNull JetOperationExpression expression) {
FunctionDescriptor operationDescriptor =
BindingUtils.getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
FunctionDescriptor operationDescriptor = getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
if (operationDescriptor == null) return true;
if (context.intrinsics().isIntrinsic(operationDescriptor)) return true;
if (context.intrinsics().getFunctionIntrinsics().getIntrinsic(operationDescriptor).exists()) return true;
return false;
}
@@ -232,15 +229,6 @@ public final class TranslationUtils {
return context.program().getNumberLiteral(0);
}
@NotNull
public static JsExpression applyIntrinsicToBinaryExpression(@NotNull TranslationContext context,
@NotNull FunctionIntrinsic intrinsic,
@NotNull JetBinaryExpression binaryExpression) {
JsExpression left = translateLeftExpression(context, binaryExpression);
JsExpression right = translateRightExpression(context, binaryExpression);
return intrinsic.apply(left, Arrays.asList(right), context);
}
@Nullable
public static JsExpression resolveThisObjectForResolvedCall(@NotNull ResolvedCall<?> call,
@NotNull TranslationContext context) {