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.jet.codegen.inline;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.jet.codegen.FrameMap;
022    import org.jetbrains.jet.codegen.StackValue;
023    import org.jetbrains.org.objectweb.asm.Type;
024    
025    import java.util.ArrayList;
026    import java.util.Collections;
027    import java.util.List;
028    
029    public class  ParametersBuilder {
030    
031        private final List<ParameterInfo> params = new ArrayList<ParameterInfo>();
032        private final List<CapturedParamInfo> capturedParams = new ArrayList<CapturedParamInfo>();
033    
034        private int nextIndex = 0;
035        private int nextCaptured = 0;
036    
037        @NotNull
038        public static ParametersBuilder newBuilder() {
039            return new ParametersBuilder();
040        }
041    
042        @NotNull
043        public ParameterInfo addThis(@NotNull Type type, boolean skipped) {
044            ParameterInfo info = new ParameterInfo(type, skipped, nextIndex, -1);
045            addParameter(info);
046            return info;
047        }
048    
049        @NotNull
050        public ParameterInfo addNextParameter(@NotNull Type type, boolean skipped, @Nullable StackValue remapValue) {
051            return addParameter(new ParameterInfo(type, skipped, nextIndex, remapValue));
052        }
053    
054        @NotNull
055        public CapturedParamInfo addCapturedParam(
056                @NotNull CapturedParamInfo original,
057                @NotNull String newFieldName
058        ) {
059            CapturedParamInfo info = new CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextCaptured, original.getIndex());
060            info.setLambda(original.getLambda());
061            return addCapturedParameter(info);
062        }
063    
064        @NotNull
065        public CapturedParamInfo addCapturedParam(
066                @NotNull CapturedParamDesc desc,
067                @NotNull String newFieldName
068        ) {
069            CapturedParamInfo info = new CapturedParamInfo(desc, newFieldName, false, nextCaptured, null);
070            return addCapturedParameter(info);
071        }
072    
073        @NotNull
074        public CapturedParamInfo addCapturedParamCopy(
075                @NotNull CapturedParamInfo copyFrom
076        ) {
077            CapturedParamInfo info = copyFrom.newIndex(nextCaptured);
078            return addCapturedParameter(info);
079        }
080    
081        @NotNull
082        public CapturedParamInfo addCapturedParam(
083                @NotNull CapturedParamOwner containingLambda,
084                @NotNull String fieldName,
085                @NotNull Type type,
086                boolean skipped,
087                @Nullable ParameterInfo original
088        ) {
089            CapturedParamInfo info =
090                    new CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), skipped, nextCaptured,
091                                          original != null ? original.getIndex() : -1);
092            if (original != null) {
093                info.setLambda(original.getLambda());
094            }
095            return addCapturedParameter(info);
096        }
097    
098        @NotNull
099        private ParameterInfo addParameter(ParameterInfo info) {
100            params.add(info);
101            nextIndex += info.getType().getSize();
102            return info;
103        }
104    
105        @NotNull
106        private CapturedParamInfo addCapturedParameter(CapturedParamInfo info) {
107            capturedParams.add(info);
108            nextCaptured += info.getType().getSize();
109            return info;
110        }
111    
112        @NotNull
113        public List<ParameterInfo> listNotCaptured() {
114            return Collections.unmodifiableList(params);
115        }
116    
117        @NotNull
118        public List<CapturedParamInfo> listCaptured() {
119            return Collections.unmodifiableList(capturedParams);
120        }
121    
122        @NotNull
123        public List<ParameterInfo> listAllParams() {
124            List<ParameterInfo> list = new ArrayList<ParameterInfo>(params);
125            list.addAll(capturedParams);
126            return list;
127        }
128    
129        @NotNull
130        private List<ParameterInfo> buildWithStubs() {
131            return Parameters.addStubs(listNotCaptured());
132        }
133    
134        private List<CapturedParamInfo> buildCapturedWithStubs() {
135            return Parameters.shiftAndAddStubs(listCaptured(), nextIndex);
136        }
137    
138        public Parameters buildParameters() {
139            return new Parameters(buildWithStubs(), buildCapturedWithStubs());
140        }
141    
142        public int getNextValueParameterIndex() {
143            return nextIndex;
144        }
145    }