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