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