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.context;
018    
019    import kotlin.collections.CollectionsKt;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.kotlin.codegen.FieldInfo;
023    import org.jetbrains.kotlin.codegen.OwnerKind;
024    import org.jetbrains.kotlin.codegen.state.GenerationState;
025    import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
026    import org.jetbrains.kotlin.descriptors.ClassDescriptor;
027    import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
028    import org.jetbrains.kotlin.psi.KtAnonymousInitializer;
029    import org.jetbrains.kotlin.psi.KtDeclaration;
030    import org.jetbrains.kotlin.psi.KtExpression;
031    import org.jetbrains.kotlin.psi.KtScript;
032    import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
033    import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
034    
035    import java.util.List;
036    
037    public class ScriptContext extends ClassContext {
038        private final ScriptDescriptor scriptDescriptor;
039        private final List<ScriptDescriptor> earlierScripts;
040        private final KtExpression lastStatement;
041    
042        public ScriptContext(
043                @NotNull JetTypeMapper typeMapper,
044                @NotNull ScriptDescriptor scriptDescriptor,
045                @NotNull List<ScriptDescriptor> earlierScripts,
046                @NotNull ClassDescriptor contextDescriptor,
047                @Nullable CodegenContext parentContext
048        ) {
049            super(typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, null);
050            this.scriptDescriptor = scriptDescriptor;
051            this.earlierScripts = earlierScripts;
052            KtScript script = (KtScript) DescriptorToSourceUtils.getSourceFromDescriptor(scriptDescriptor);
053            assert script != null : "Declaration should be present for script: " + scriptDescriptor;
054            KtDeclaration lastDeclaration = CollectionsKt.lastOrNull(script.getDeclarations());
055            if (lastDeclaration instanceof KtAnonymousInitializer) {
056                this.lastStatement = ((KtAnonymousInitializer) lastDeclaration).getBody();
057            }
058            else {
059                this.lastStatement = null;
060            }
061        }
062    
063        @NotNull
064        public ScriptDescriptor getScriptDescriptor() {
065            return scriptDescriptor;
066        }
067    
068        @NotNull
069        public FieldInfo getResultFieldInfo() {
070            assert getState().getReplSpecific().getShouldGenerateScriptResultValue() : "Should not be called unless 'scriptResultFieldName' is set";
071            GenerationState state = getState();
072            String scriptResultFieldName = state.getReplSpecific().getScriptResultFieldName();
073            assert scriptResultFieldName != null;
074            return FieldInfo.createForHiddenField(state.getTypeMapper().mapClass(scriptDescriptor), AsmTypes.OBJECT_TYPE, scriptResultFieldName);
075        }
076    
077        @NotNull
078        public List<ScriptDescriptor> getEarlierScripts() {
079            return earlierScripts;
080        }
081    
082        @NotNull
083        public String getScriptFieldName(@NotNull ScriptDescriptor scriptDescriptor) {
084            int index = earlierScripts.indexOf(scriptDescriptor);
085            if (index < 0) {
086                throw new IllegalStateException("Unregistered script: " + scriptDescriptor);
087            }
088            return "script$" + (index + 1);
089        }
090    
091        @Nullable
092        public KtExpression getLastStatement() {
093            return lastStatement;
094        }
095    
096        @Override
097        public String toString() {
098            return "Script: " + getContextDescriptor().getName().asString();
099        }
100    }