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.asm4.Type;
022    
023    import java.util.ArrayList;
024    import java.util.Collections;
025    import java.util.List;
026    
027    public class  ParametersBuilder {
028    
029        private final List<ParameterInfo> params = new ArrayList<ParameterInfo>();
030        private final List<CapturedParamInfo> capturedParams = new ArrayList<CapturedParamInfo>();
031    
032        private int nextIndex = 0;
033        private int nextCaptured = 0;
034    
035        public static ParametersBuilder newBuilder() {
036            return new ParametersBuilder();
037        }
038    
039        public ParameterInfo addThis(Type type, boolean skipped) {
040            ParameterInfo info = new ParameterInfo(type, skipped, nextIndex, -1);
041            addParameter(info);
042            return info;
043        }
044    
045        public ParametersBuilder addNextParameter(Type type, boolean skipped, @Nullable ParameterInfo original) {
046            addParameter(new ParameterInfo(type, skipped, nextIndex, original != null ? original.getIndex() : -1));
047            return this;
048        }
049    
050        public CapturedParamInfo addCapturedParam(
051                @NotNull CapturedParamInfo param,
052                @Nullable CapturedParamInfo originalField
053        ) {
054            CapturedParamInfo info = new CapturedParamInfo(param.desc, param.isSkipped, nextCaptured, originalField != null ? originalField.getIndex() : -1);
055            info.setLambda(param.getLambda());
056            return addCapturedParameter(info);
057        }
058    
059        public CapturedParamInfo addCapturedParam(
060                String fieldName,
061                Type type,
062                boolean skipped,
063                @Nullable ParameterInfo original,
064                CapturedParamOwner containingLambda
065        ) {
066            CapturedParamInfo info =
067                    new CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), skipped, nextCaptured,
068                                          original != null ? original.getIndex() : -1);
069            if (original != null) {
070                info.setLambda(original.getLambda());
071            }
072            return addCapturedParameter(info);
073        }
074    
075        private void addParameter(ParameterInfo info) {
076            params.add(info);
077            nextIndex += info.getType().getSize();
078        }
079    
080        private CapturedParamInfo addCapturedParameter(CapturedParamInfo info) {
081            capturedParams.add(info);
082            nextCaptured += info.getType().getSize();
083            return info;
084        }
085    
086        public List<ParameterInfo> build() {
087            return Collections.unmodifiableList(params);
088        }
089    
090        public List<CapturedParamInfo> buildCaptured() {
091            return Collections.unmodifiableList(capturedParams);
092        }
093    
094        public List<ParameterInfo> buildWithStubs() {
095            return Parameters.addStubs(build());
096        }
097    
098        public List<CapturedParamInfo> buildCapturedWithStubs() {
099            return Parameters.shiftAndAddStubs(buildCaptured(), nextIndex);
100        }
101    
102        public Parameters buildParameters() {
103            return new Parameters(buildWithStubs(), buildCapturedWithStubs());
104        }
105    }