001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories;
018
019 import com.google.common.collect.Lists;
020 import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
021 import com.google.dart.compiler.backend.js.ast.JsExpression;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.kotlin.builtins.PrimitiveType;
025 import org.jetbrains.kotlin.js.translate.context.Namer;
026 import org.jetbrains.kotlin.js.translate.context.TranslationContext;
027 import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic;
028 import org.jetbrains.kotlin.js.patterns.DescriptorPredicate;
029 import org.jetbrains.kotlin.js.patterns.NamePredicate;
030 import org.jetbrains.kotlin.name.Name;
031
032 import java.util.List;
033
034 import static com.intellij.openapi.util.text.StringUtil.decapitalize;
035 import static org.jetbrains.kotlin.js.patterns.PatternBuilder.pattern;
036 import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.assignment;
037
038 public final class ArrayFIF extends CompositeFIF {
039 private static final NamePredicate NUMBER_ARRAY;
040 private static final NamePredicate CHAR_ARRAY;
041 private static final NamePredicate BOOLEAN_ARRAY;
042 private static final NamePredicate LONG_ARRAY;
043 private static final NamePredicate ARRAYS;
044 private static final DescriptorPredicate ARRAY_FACTORY_METHODS;
045
046 static {
047 List<Name> arrayTypeNames = Lists.newArrayList();
048 List<Name> arrayFactoryMethodNames = Lists.newArrayList(Name.identifier("arrayOf"));
049 for (PrimitiveType type : PrimitiveType.values()) {
050 Name arrayTypeName = type.getArrayTypeName();
051 if (type != PrimitiveType.CHAR && type != PrimitiveType.BOOLEAN && type != PrimitiveType.LONG) {
052 arrayTypeNames.add(arrayTypeName);
053 }
054 arrayFactoryMethodNames.add(Name.identifier(decapitalize(arrayTypeName.asString() + "Of")));
055 }
056
057 Name arrayName = Name.identifier("Array");
058 Name booleanArrayName = PrimitiveType.BOOLEAN.getArrayTypeName();
059 Name charArrayName = PrimitiveType.CHAR.getArrayTypeName();
060 Name longArrayName = PrimitiveType.LONG.getArrayTypeName();
061
062 NUMBER_ARRAY = new NamePredicate(arrayTypeNames);
063 CHAR_ARRAY = new NamePredicate(charArrayName);
064 BOOLEAN_ARRAY = new NamePredicate(booleanArrayName);
065 LONG_ARRAY = new NamePredicate(longArrayName);
066
067 arrayTypeNames.add(charArrayName);
068 arrayTypeNames.add(booleanArrayName);
069 arrayTypeNames.add(longArrayName);
070 arrayTypeNames.add(arrayName);
071 ARRAYS = new NamePredicate(arrayTypeNames);
072 ARRAY_FACTORY_METHODS = pattern(Namer.KOTLIN_LOWER_NAME, new NamePredicate(arrayFactoryMethodNames));
073 }
074
075 private static final FunctionIntrinsic ARRAY_INTRINSIC = new FunctionIntrinsic() {
076 @NotNull
077 @Override
078 public JsExpression apply(
079 @Nullable JsExpression receiver,
080 @NotNull List<JsExpression> arguments,
081 @NotNull TranslationContext context
082 ) {
083 assert arguments.size() == 1;
084 return arguments.get(0);
085 }
086 };
087
088 @NotNull
089 public static final FunctionIntrinsic GET_INTRINSIC = new FunctionIntrinsic() {
090 @NotNull
091 @Override
092 public JsExpression apply(@Nullable JsExpression receiver,
093 @NotNull List<JsExpression> arguments,
094 @NotNull TranslationContext context) {
095 assert receiver != null;
096 assert arguments.size() == 1 : "Array get expression must have one argument.";
097 JsExpression indexExpression = arguments.get(0);
098 return new JsArrayAccess(receiver, indexExpression);
099 }
100 };
101
102 @NotNull
103 public static final FunctionIntrinsic SET_INTRINSIC = new FunctionIntrinsic() {
104 @NotNull
105 @Override
106 public JsExpression apply(@Nullable JsExpression receiver,
107 @NotNull List<JsExpression> arguments,
108 @NotNull TranslationContext context) {
109 assert receiver != null;
110 assert arguments.size() == 2 : "Array set expression must have two arguments.";
111 JsExpression indexExpression = arguments.get(0);
112 JsExpression value = arguments.get(1);
113 JsArrayAccess arrayAccess = new JsArrayAccess(receiver, indexExpression);
114 return assignment(arrayAccess, value);
115 }
116 };
117
118 @NotNull
119 public static final FunctionIntrinsicFactory INSTANCE = new ArrayFIF();
120
121 private ArrayFIF() {
122 add(pattern(ARRAYS, "get"), GET_INTRINSIC);
123 add(pattern(ARRAYS, "set"), SET_INTRINSIC);
124 add(pattern(ARRAYS, "size"), LENGTH_PROPERTY_INTRINSIC);
125 add(pattern(ARRAYS, "iterator"), new KotlinFunctionIntrinsic("arrayIterator"));
126 add(pattern(NUMBER_ARRAY, "<init>"),new KotlinFunctionIntrinsic("numberArrayOfSize"));
127 add(pattern(CHAR_ARRAY, "<init>"), new KotlinFunctionIntrinsic("charArrayOfSize"));
128 add(pattern(BOOLEAN_ARRAY, "<init>"), new KotlinFunctionIntrinsic("booleanArrayOfSize"));
129 add(pattern(LONG_ARRAY, "<init>"), new KotlinFunctionIntrinsic("longArrayOfSize"));
130 add(ARRAY_FACTORY_METHODS, ARRAY_INTRINSIC);
131 }
132 }