diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index 7b723800709..c8015e44f41 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -368,13 +368,6 @@ public class ClosureCodegen extends MemberCodegen { iv.invokestatic(REFLECTION, "getOrCreateKotlinPackage", Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE, getType(Class.class), getType(String.class)), false); } - else if (container instanceof ScriptDescriptor) { - // TODO: correct container for scripts (KScript?) - StackValue value = generateClassLiteralReference( - state.getTypeMapper(), ((ScriptDescriptor) container).getClassDescriptor().getDefaultType() - ); - value.put(K_CLASS_TYPE, iv); - } else { iv.aconst(null); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index f0b4d4a071e..817f63f3110 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -48,7 +48,6 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.codegen.when.SwitchCodegen; import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.descriptors.impl.ScriptCodeDescriptor; import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor; import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; import org.jetbrains.kotlin.diagnostics.Errors; @@ -311,9 +310,28 @@ public class ExpressionCodegen extends KtVisitor impleme public void gen(KtElement expr, Type type) { StackValue value = Type.VOID_TYPE.equals(type) ? genStatement(expr) : gen(expr); + // for repl store the result of the last line into special field + if (value.type != Type.VOID_TYPE && state.getShouldGenerateScriptResultValue()) { + ScriptContext context = getScriptContext(); + if (expr == context.getLastStatement()) { + StackValue.Field resultValue = StackValue.field(context.getResultFieldInfo(), StackValue.LOCAL_0); + resultValue.store(value, v); + return; + } + } + value.put(type, v); } + @NotNull + private ScriptContext getScriptContext() { + CodegenContext context = getContext(); + while (!(context instanceof ScriptContext)) { + context = context.getParentContext(); + } + return (ScriptContext) context; + } + public StackValue genLazy(KtElement expr, Type type) { StackValue value = gen(expr); return StackValue.coercion(value, type); @@ -1968,21 +1986,6 @@ public class ExpressionCodegen extends KtVisitor impleme if (localOrCaptured != null) { return localOrCaptured; } - - DeclarationDescriptor container = descriptor.getContainingDeclaration(); - if (descriptor instanceof ValueParameterDescriptor && container instanceof ScriptCodeDescriptor) { - ScriptCodeDescriptor scriptCodeDescriptor = (ScriptCodeDescriptor) container; - ScriptDescriptor scriptDescriptor = (ScriptDescriptor) scriptCodeDescriptor.getContainingDeclaration(); - Type scriptClassType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor); - ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor; - ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); - //noinspection ConstantConditions - StackValue script = StackValue.thisOrOuter(this, scriptClass, false, false); - Type fieldType = typeMapper.mapType(valueParameterDescriptor); - return StackValue.field(fieldType, scriptClassType, valueParameterDescriptor.getName().getIdentifier(), false, script, - valueParameterDescriptor); - } - throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); } @@ -2496,14 +2499,15 @@ public class ExpressionCodegen extends KtVisitor impleme return StackValue.singleton(receiverDescriptor, typeMapper); } } + else if (receiverDescriptor instanceof ScriptDescriptor) { + return generateScriptReceiver + ((ScriptDescriptor) receiverDescriptor); + } else { return StackValue.thisOrOuter(this, receiverDescriptor, isSuper, receiverValue instanceof CastImplicitClassReceiver || isEnumEntry(receiverDescriptor)); } } - else if (receiverValue instanceof ScriptReceiver) { - return generateScript((ScriptReceiver) receiverValue); - } else if (receiverValue instanceof ExtensionReceiver) { return generateReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor()); } @@ -2520,7 +2524,8 @@ public class ExpressionCodegen extends KtVisitor impleme return context.generateReceiver(descriptor, state, false); } - private StackValue generateScript(@NotNull ScriptReceiver receiver) { + @NotNull + private StackValue generateScriptReceiver(@NotNull ScriptDescriptor receiver) { CodegenContext cur = context; StackValue result = StackValue.LOCAL_0; boolean inStartConstructorContext = cur instanceof ConstructorContext; @@ -2532,17 +2537,14 @@ public class ExpressionCodegen extends KtVisitor impleme if (cur instanceof ScriptContext) { ScriptContext scriptContext = (ScriptContext) cur; - ScriptDescriptor receiverDeclarationDescriptor = receiver.getDeclarationDescriptor(); - if (scriptContext.getScriptDescriptor() == receiverDeclarationDescriptor) { + if (scriptContext.getScriptDescriptor() == receiver) { //TODO lazy return result; } - else { - Type currentScriptType = asmTypeForScriptDescriptor(bindingContext, scriptContext.getScriptDescriptor()); - Type classType = asmTypeForScriptDescriptor(bindingContext, receiverDeclarationDescriptor); - String fieldName = scriptContext.getScriptFieldName(receiverDeclarationDescriptor); - return StackValue.field(classType, currentScriptType, fieldName, false, result, receiverDeclarationDescriptor); - } + Type currentScriptType = typeMapper.mapType(scriptContext.getScriptDescriptor()); + Type classType = typeMapper.mapType(receiver); + String fieldName = scriptContext.getScriptFieldName(receiver); + return StackValue.field(classType, currentScriptType, fieldName, false, result, receiver); } result = cur.getOuterExpression(result, false); @@ -2558,7 +2560,6 @@ public class ExpressionCodegen extends KtVisitor impleme throw new UnsupportedOperationException(); } - @NotNull public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { return generateThisOrOuter(calleeContainingClass, isSuper, false); @@ -3321,19 +3322,7 @@ public class ExpressionCodegen extends KtVisitor impleme Type varType = asmType(variableDescriptor.getType()); - StackValue storeTo; - if (KtPsiUtil.isScriptDeclaration(variableDeclaration)) { - KtScript scriptPsi = KtPsiUtil.getScript(variableDeclaration); - assert scriptPsi != null; - Type scriptClassType = asmTypeForScriptPsi(bindingContext, scriptPsi); - storeTo = StackValue.field(varType, scriptClassType, variableDeclaration.getName(), false, StackValue.LOCAL_0, variableDescriptor); - } - else if (sharedVarType == null) { - storeTo = StackValue.local(index, varType); - } - else { - storeTo = StackValue.shared(index, varType); - } + StackValue storeTo = sharedVarType == null ? StackValue.local(index, varType) : StackValue.shared(index, varType); storeTo.store(initializer, v); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java index 75ae8925781..1fb9f7b1bf5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/KotlinCodegenFacade.java @@ -24,40 +24,20 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; import org.jetbrains.kotlin.psi.KtFile; -import org.jetbrains.kotlin.psi.KtScript; -import org.jetbrains.kotlin.resolve.ScriptNameUtil; -import org.jetbrains.org.objectweb.asm.Type; import java.util.Collection; import java.util.HashSet; import java.util.Set; -import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.registerClassNameForScript; - public class KotlinCodegenFacade { - public static void prepareForCompilation(@NotNull GenerationState state) { - for (KtFile file : state.getFiles()) { - if (file.isScript()) { - KtScript script = file.getScript(); - assert script != null; - - FqName name = ScriptNameUtil.classNameForScript(script); - Type type = AsmUtil.asmTypeByFqNameWithoutInnerClasses(name); - registerClassNameForScript(state.getBindingTrace(), script, type, state.getFileClassesProvider()); - } - } - - state.beforeCompile(); - } - public static void compileCorrectFiles( @NotNull GenerationState state, @NotNull CompilationErrorHandler errorHandler ) { ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); - prepareForCompilation(state); + state.beforeCompile(); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index d4ca04e442c..b3ab185647d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -273,13 +273,8 @@ public abstract class MemberCodegen(state, parentCodegen, context, expression, classBuilder) { private val asmType = typeMapper.mapClass(classDescriptor) - private val dispatchReceiverType = - when { - dispatchReceiver is ScriptReceiver -> { - // TODO: fix receiver for scripts, see ScriptReceiver#getType - dispatchReceiver.declarationDescriptor.classDescriptor.defaultType - } - dispatchReceiver.exists() -> dispatchReceiver.type - else -> null - } + private val dispatchReceiverType = if (dispatchReceiver.exists()) dispatchReceiver.type else null private val extensionReceiverType = target.extensionReceiverParameter?.type diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java index 2243b03a894..536471c18f1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.java @@ -23,12 +23,11 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext; import org.jetbrains.kotlin.codegen.context.MethodContext; import org.jetbrains.kotlin.codegen.context.ScriptContext; import org.jetbrains.kotlin.codegen.state.GenerationState; -import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.descriptors.PropertyDescriptor; import org.jetbrains.kotlin.descriptors.ScriptDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; import org.jetbrains.org.objectweb.asm.MethodVisitor; @@ -38,8 +37,6 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import java.util.Collections; import java.util.List; -import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT; -import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForScriptDescriptor; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; import static org.jetbrains.org.objectweb.asm.Opcodes.*; @@ -55,18 +52,16 @@ public class ScriptCodegen extends MemberCodegen { ScriptDescriptor scriptDescriptor = bindingContext.get(BindingContext.SCRIPT, declaration); assert scriptDescriptor != null; - ClassDescriptor classDescriptorForScript = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); - assert classDescriptorForScript != null; + Type classType = state.getTypeMapper().mapType(scriptDescriptor); - Type classType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor); - - ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, classDescriptorForScript), + ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, scriptDescriptor), classType, declaration.getContainingFile()); List earlierScripts = state.getEarlierScriptsForReplInterpreter(); ScriptContext scriptContext = parentContext.intoScript( scriptDescriptor, earlierScripts == null ? Collections.emptyList() : earlierScripts, - classDescriptorForScript + scriptDescriptor, + state.getTypeMapper() ); return new ScriptCodegen(declaration, state, scriptContext, builder); } @@ -104,8 +99,8 @@ public class ScriptCodegen extends MemberCodegen { protected void generateBody() { genMembers(); genFieldsForParameters(scriptDescriptor, v); - genConstructor(scriptDescriptor, context.getContextDescriptor(), v, - context.intoFunction(scriptDescriptor.getScriptCodeDescriptor())); + genConstructor(scriptDescriptor, v, + context.intoFunction(scriptDescriptor.getUnsubstitutedPrimaryConstructor())); } @Override @@ -115,22 +110,25 @@ public class ScriptCodegen extends MemberCodegen { private void genConstructor( @NotNull ScriptDescriptor scriptDescriptor, - @NotNull ClassDescriptor classDescriptorForScript, @NotNull ClassBuilder classBuilder, @NotNull MethodContext methodContext ) { - //noinspection ConstantConditions - Type blockType = typeMapper.mapType(scriptDescriptor.getScriptCodeDescriptor().getReturnType()); - - PropertyDescriptor scriptResultProperty = scriptDescriptor.getScriptResultProperty(); - classBuilder.newField(JvmDeclarationOriginKt.OtherOrigin(scriptResultProperty), - ACC_PUBLIC | ACC_FINAL, scriptResultProperty.getName().asString(), - blockType.getDescriptor(), null, null); - JvmMethodSignature jvmSignature = typeMapper.mapScriptSignature(scriptDescriptor, context.getEarlierScripts()); + if (state.getShouldGenerateScriptResultValue()) { + FieldInfo resultFieldInfo = context.getResultFieldInfo(); + classBuilder.newField( + JvmDeclarationOrigin.NO_ORIGIN, + ACC_PUBLIC | ACC_FINAL, + resultFieldInfo.getFieldName(), + resultFieldInfo.getFieldType().getDescriptor(), + null, + null + ); + } + MethodVisitor mv = classBuilder.newMethod( - JvmDeclarationOriginKt.OtherOrigin(scriptDeclaration, scriptDescriptor.getClassDescriptor().getUnsubstitutedPrimaryConstructor()), + JvmDeclarationOriginKt.OtherOrigin(scriptDeclaration, scriptDescriptor.getUnsubstitutedPrimaryConstructor()), ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(), null, null); @@ -139,7 +137,7 @@ public class ScriptCodegen extends MemberCodegen { InstructionAdapter iv = new InstructionAdapter(mv); - Type classType = typeMapper.mapType(classDescriptorForScript); + Type classType = typeMapper.mapType(scriptDescriptor); iv.load(0, classType); iv.invokespecial("java/lang/Object", "", "()V", false); @@ -156,22 +154,23 @@ public class ScriptCodegen extends MemberCodegen { Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes(); int add = 0; - for (int i = 0; i < scriptDescriptor.getScriptCodeDescriptor().getValueParameters().size(); i++) { - ValueParameterDescriptor parameter = scriptDescriptor.getScriptCodeDescriptor().getValueParameters().get(i); + List valueParameters = scriptDescriptor.getUnsubstitutedPrimaryConstructor().getValueParameters(); + for (int i = 0; i < valueParameters.size(); i++) { + ValueParameterDescriptor parameter = valueParameters.get(i); frameMap.enter(parameter, argTypes[i + add]); } int offset = 1; for (ScriptDescriptor earlierScript : context.getEarlierScripts()) { - Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript); + Type earlierClassType = typeMapper.mapClass(earlierScript); iv.load(0, classType); iv.load(offset, earlierClassType); offset += earlierClassType.getSize(); iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor()); } - for (ValueParameterDescriptor parameter : scriptDescriptor.getScriptCodeDescriptor().getValueParameters()) { + for (ValueParameterDescriptor parameter : valueParameters) { Type parameterType = typeMapper.mapType(parameter.getType()); iv.load(0, classType); iv.load(offset, parameterType); @@ -188,16 +187,6 @@ public class ScriptCodegen extends MemberCodegen { } }); - StackValue stackValue = codegen.gen(scriptDeclaration.getBlockExpression()); - if (stackValue.type != Type.VOID_TYPE) { - StackValue.Field resultValue = StackValue - .field(blockType, classType, ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME, false, StackValue.LOCAL_0); - resultValue.store(stackValue, iv); - } - else { - stackValue.put(blockType, iv); - } - iv.areturn(Type.VOID_TYPE); } @@ -207,12 +196,12 @@ public class ScriptCodegen extends MemberCodegen { private void genFieldsForParameters(@NotNull ScriptDescriptor script, @NotNull ClassBuilder classBuilder) { for (ScriptDescriptor earlierScript : context.getEarlierScripts()) { - Type earlierClassName = asmTypeForScriptDescriptor(bindingContext, earlierScript); - int access = ACC_PRIVATE | ACC_FINAL; + Type earlierClassName = typeMapper.mapType(earlierScript); + int access = ACC_PUBLIC | ACC_FINAL; classBuilder.newField(NO_ORIGIN, access, context.getScriptFieldName(earlierScript), earlierClassName.getDescriptor(), null, null); } - for (ValueParameterDescriptor parameter : script.getScriptCodeDescriptor().getValueParameters()) { + for (ValueParameterDescriptor parameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) { Type parameterType = typeMapper.mapType(parameter); int access = ACC_PUBLIC | ACC_FINAL; classBuilder.newField(JvmDeclarationOriginKt.OtherOrigin(parameter), access, parameter.getName().getIdentifier(), parameterType.getDescriptor(), null, null); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index dc2cf0c52ad..4c069dd18aa 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -235,8 +235,8 @@ public abstract class StackValue { } @NotNull - private static Field field(@NotNull FieldInfo info) { - return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), true, none()); + public static Field field(@NotNull FieldInfo info, @NotNull StackValue receiver) { + return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), info.isStatic(), receiver); } @NotNull @@ -593,15 +593,15 @@ public abstract class StackValue { @NotNull public static Field singleton(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeMapper typeMapper) { - return field(FieldInfo.createForSingleton(classDescriptor, typeMapper)); + return field(FieldInfo.createForSingleton(classDescriptor, typeMapper), none()); } public static Field singletonViaInstance(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) { - return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, false)); + return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, false), none()); } public static Field oldSingleton(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) { - return field(FieldInfo.createForSingleton(classDescriptor, typeMapper, true)); + return field(FieldInfo.createForSingleton(classDescriptor, typeMapper, true), none()); } public static StackValue operation(Type type, Function1 lambda) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index 82d669392db..30cf2341fb5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -158,24 +158,20 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { element.acceptChildren(this); } + @Override + public void visitScript(@NotNull KtScript script) { + classStack.push(bindingContext.get(SCRIPT, script)); + nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(script.getFqName())); + script.acceptChildren(this); + nameStack.pop(); + classStack.pop(); + } + @Override public void visitKtFile(@NotNull KtFile file) { - if (file.isScript()) { - // TODO: replace with visitScript override - //noinspection ConstantConditions - ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_SCRIPT, bindingContext.get(SCRIPT, file.getScript())); - classStack.push(classDescriptor); - //noinspection ConstantConditions - nameStack.push(asmTypeForScriptPsi(bindingContext, file.getScript()).getInternalName()); - } - else { - nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(file.getPackageFqName())); - } + nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(file.getPackageFqName())); file.acceptChildren(this); nameStack.pop(); - if (file.isScript()) { - classStack.pop(); - } } @Override @@ -386,7 +382,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { String peek = peekFromStack(nameStack); String name = safeIdentifier(descriptor.getName()).asString(); - if (containingDeclaration instanceof ClassDescriptor || containingDeclaration instanceof ScriptDescriptor) { + if (containingDeclaration instanceof ClassDescriptor) { return peek + '$' + name; } else if (containingDeclaration instanceof PackageFragmentDescriptor) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java index 5604afdf90c..1c784a9c782 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java @@ -24,17 +24,13 @@ import org.jetbrains.kotlin.codegen.SamType; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl; import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingTrace; -import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; -import org.jetbrains.kotlin.resolve.scopes.MemberScope; -import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt; +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice; import org.jetbrains.kotlin.util.slicedMap.Slices; import org.jetbrains.kotlin.util.slicedMap.WritableSlice; @@ -43,15 +39,12 @@ import org.jetbrains.org.objectweb.asm.Type; import java.util.*; import static org.jetbrains.kotlin.resolve.BindingContext.*; -import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration; public class CodegenBinding { public static final WritableSlice CLOSURE = Slices.createSimpleSlice(); public static final WritableSlice CLASS_FOR_CALLABLE = Slices.createSimpleSlice(); - public static final WritableSlice CLASS_FOR_SCRIPT = Slices.createSimpleSlice(); - public static final WritableSlice ASM_TYPE = Slices.createSimpleSlice(); public static final WritableSlice ENUM_ENTRY_CLASS_NEED_SUBCLASS = Slices.createSimpleSetSlice(); @@ -89,22 +82,6 @@ public class CodegenBinding { return Boolean.TRUE.equals(bindingContext.get(ENUM_ENTRY_CLASS_NEED_SUBCLASS, classDescriptor)); } - @NotNull - public static Type asmTypeForScriptDescriptor(BindingContext bindingContext, @NotNull ScriptDescriptor scriptDescriptor) { - ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); - //noinspection ConstantConditions - return getAsmType(bindingContext, classDescriptor); - } - - @NotNull - public static Type asmTypeForScriptPsi(BindingContext bindingContext, @NotNull KtScript script) { - ScriptDescriptor scriptDescriptor = bindingContext.get(SCRIPT, script); - if (scriptDescriptor == null) { - throw new IllegalStateException("Script descriptor not found by PSI " + script); - } - return asmTypeForScriptDescriptor(bindingContext, scriptDescriptor); - } - @NotNull public static ClassDescriptor anonymousClassForCallable( @NotNull BindingContext bindingContext, @@ -163,7 +140,7 @@ public class CodegenBinding { @NotNull Type asmType, @NotNull JvmFileClassesProvider fileClassesManager ) { - KtElement element = (KtElement) descriptorToDeclaration(classDescriptor); + KtElement element = (KtElement) DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor); assert element != null : "No source element for " + classDescriptor; MutableClosure closure = new MutableClosure(classDescriptor, enclosing); @@ -196,29 +173,6 @@ public class CodegenBinding { innerClasses.add(inner); } - public static void registerClassNameForScript( - @NotNull BindingTrace trace, - @NotNull KtScript script, - @NotNull Type asmType, - @NotNull JvmFileClassesProvider fileClassesManager - ) { - ScriptDescriptor descriptor = trace.getBindingContext().get(SCRIPT, script); - if (descriptor == null) { - throw new IllegalStateException("Script descriptor is not found for PSI: " + PsiUtilsKt.getElementTextWithContext(script)); - } - - String simpleName = asmType.getInternalName().substring(asmType.getInternalName().lastIndexOf('/') + 1); - ClassDescriptorImpl classDescriptor = - new ClassDescriptorImpl(descriptor, Name.special(""), Modality.FINAL, - Collections.singleton(DescriptorUtilsKt.getBuiltIns(descriptor).getAnyType()), - KotlinSourceElementKt.toSourceElement(script)); - classDescriptor.initialize(MemberScope.Empty.INSTANCE, Collections.emptySet(), null); - - recordClosure(trace, classDescriptor, null, asmType, fileClassesManager); - - trace.record(CLASS_FOR_SCRIPT, descriptor, classDescriptor); - } - @NotNull private static Collection allFilesInPackages(BindingContext bindingContext, Collection files) { // todo: we use Set and add given files but ignoring other scripts because something non-clear kept in binding diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java index 5070cb6ac9e..1ebc7fc0f7e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/CodegenContext.java @@ -315,9 +315,10 @@ public abstract class CodegenContext { public ScriptContext intoScript( @NotNull ScriptDescriptor script, @NotNull List earlierScripts, - @NotNull ClassDescriptor classDescriptor + @NotNull ClassDescriptor classDescriptor, + @NotNull JetTypeMapper typeMapper ) { - return new ScriptContext(script, earlierScripts, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure); + return new ScriptContext(typeMapper, script, earlierScripts, classDescriptor, this); } @NotNull diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ScriptContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ScriptContext.java index fc84e4f0e55..3ee659f2a7c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ScriptContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ScriptContext.java @@ -16,30 +16,48 @@ package org.jetbrains.kotlin.codegen.context; +import kotlin.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.codegen.FieldInfo; import org.jetbrains.kotlin.codegen.OwnerKind; -import org.jetbrains.kotlin.codegen.binding.MutableClosure; +import org.jetbrains.kotlin.codegen.state.GenerationState; +import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.ScriptDescriptor; +import org.jetbrains.kotlin.psi.KtClassInitializer; +import org.jetbrains.kotlin.psi.KtDeclaration; +import org.jetbrains.kotlin.psi.KtExpression; +import org.jetbrains.kotlin.psi.KtScript; +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; +import org.jetbrains.kotlin.resolve.jvm.AsmTypes; import java.util.List; -public class ScriptContext extends FieldOwnerContext { +public class ScriptContext extends ClassContext { private final ScriptDescriptor scriptDescriptor; private final List earlierScripts; + private final KtExpression lastStatement; public ScriptContext( + @NotNull JetTypeMapper typeMapper, @NotNull ScriptDescriptor scriptDescriptor, @NotNull List earlierScripts, @NotNull ClassDescriptor contextDescriptor, - @NotNull OwnerKind contextKind, - @Nullable CodegenContext parentContext, - @Nullable MutableClosure closure + @Nullable CodegenContext parentContext ) { - super(contextDescriptor, contextKind, parentContext, closure, contextDescriptor, null); + super(typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, null); this.scriptDescriptor = scriptDescriptor; this.earlierScripts = earlierScripts; + KtScript script = (KtScript) DescriptorToSourceUtils.getSourceFromDescriptor(scriptDescriptor); + assert script != null : "Declaration should be present for script: " + scriptDescriptor; + KtDeclaration lastDeclaration = CollectionsKt.lastOrNull(script.getDeclarations()); + if (lastDeclaration instanceof KtClassInitializer) { + this.lastStatement = ((KtClassInitializer) lastDeclaration).getBody(); + } + else { + this.lastStatement = null; + } } @NotNull @@ -47,6 +65,15 @@ public class ScriptContext extends FieldOwnerContext { return scriptDescriptor; } + @NotNull + public FieldInfo getResultFieldInfo() { + assert getState().getShouldGenerateScriptResultValue() : "Should not be called unless 'scriptResultFieldName' is set"; + GenerationState state = getState(); + String scriptResultFieldName = state.getScriptResultFieldName(); + assert scriptResultFieldName != null; + return FieldInfo.createForHiddenField(state.getTypeMapper().mapClass(scriptDescriptor), AsmTypes.OBJECT_TYPE, scriptResultFieldName); + } + @NotNull public List getEarlierScripts() { return earlierScripts; @@ -61,6 +88,11 @@ public class ScriptContext extends FieldOwnerContext { return "script$" + (index + 1); } + @Nullable + public KtExpression getLastStatement() { + return lastStatement; + } + @Override public String toString() { return "Script: " + getContextDescriptor().getName().asString(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index d9933221332..08c0e1b28d0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -62,7 +62,6 @@ import java.util.*; import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags; import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; -import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.addInlineMarker; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getConstant; import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral; @@ -598,17 +597,15 @@ public class InlineCodegen extends CallGenerator { CodegenContext parent = getContext(descriptor.getContainingDeclaration(), state, sourceFile); - if (descriptor instanceof ClassDescriptor) { - OwnerKind kind = DescriptorUtils.isInterface(descriptor) ? OwnerKind.DEFAULT_IMPLS : OwnerKind.IMPLEMENTATION; - return parent.intoClass((ClassDescriptor) descriptor, kind, state); - } - else if (descriptor instanceof ScriptDescriptor) { - ClassDescriptor classDescriptorForScript = state.getBindingContext().get(CLASS_FOR_SCRIPT, (ScriptDescriptor) descriptor); - assert classDescriptorForScript != null : "Can't find class for script: " + descriptor; + if (descriptor instanceof ScriptDescriptor) { List earlierScripts = state.getEarlierScriptsForReplInterpreter(); return parent.intoScript((ScriptDescriptor) descriptor, earlierScripts == null ? Collections.emptyList() : earlierScripts, - classDescriptorForScript); + (ClassDescriptor) descriptor, state.getTypeMapper()); + } + else if (descriptor instanceof ClassDescriptor) { + OwnerKind kind = DescriptorUtils.isInterface(descriptor) ? OwnerKind.DEFAULT_IMPLS : OwnerKind.IMPLEMENTATION; + return parent.intoClass((ClassDescriptor) descriptor, kind, state); } else if (descriptor instanceof FunctionDescriptor) { return parent.intoFunction((FunctionDescriptor) descriptor); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt index 3b2d2db6df3..2fdbff3ccb5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -101,6 +101,8 @@ public class GenerationState @JvmOverloads constructor( public val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics) public val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this) public var earlierScriptsForReplInterpreter: List? = null + public var scriptResultFieldName: String? = null + public val shouldGenerateScriptResultValue: Boolean get() = scriptResultFieldName != null public val reflectionTypes: ReflectionTypes = ReflectionTypes(module) public val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes() public val factory: ClassFileFactory diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java index b3a1a7fc80b..e04d4627bc3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java @@ -169,9 +169,6 @@ public class JetTypeMapper { else if (container instanceof ClassDescriptor) { return mapClass((ClassDescriptor) container); } - else if (container instanceof ScriptDescriptor) { - return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container); - } else { throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor); } @@ -580,10 +577,6 @@ public class JetTypeMapper { return fqName.isRoot() ? name : fqName.asString().replace('.', '/') + '/' + name; } - if (container instanceof ScriptDescriptor) { - return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container).getInternalName() + "$" + name; - } - assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass; String containerInternalName = computeAsmTypeImpl((ClassDescriptor) container); @@ -1392,12 +1385,10 @@ public class JetTypeMapper { sw.writeParametersStart(); for (ScriptDescriptor importedScript : importedScripts) { - ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript); - assert descriptor != null : "Script not found: " + importedScript; - writeParameter(sw, descriptor.getDefaultType()); + writeParameter(sw, importedScript.getDefaultType()); } - for (ValueParameterDescriptor valueParameter : script.getScriptCodeDescriptor().getValueParameters()) { + for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) { writeParameter(sw, valueParameter.getType()); } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java index 43f6467b7f4..7143923b4a8 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java @@ -22,7 +22,6 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.impl.PsiFileFactoryImpl; import com.intellij.psi.search.ProjectScope; @@ -30,7 +29,6 @@ import com.intellij.testFramework.LightVirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.output.OutputFile; -import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport; import org.jetbrains.kotlin.cli.common.messages.DiagnosticMessageReporter; import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport; @@ -67,8 +65,8 @@ import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM; import org.jetbrains.kotlin.resolve.lazy.ResolveSession; import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo; import org.jetbrains.kotlin.resolve.lazy.declarations.*; +import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor; import org.jetbrains.kotlin.resolve.scopes.LexicalScope; -import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import org.jetbrains.org.objectweb.asm.Type; @@ -85,10 +83,10 @@ import java.util.Collections; import java.util.List; import static org.jetbrains.kotlin.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses; -import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.registerClassNameForScript; -import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration; public class ReplInterpreter { + private static final String SCRIPT_RESULT_FIELD_NAME = "$$result"; + private int lineNumber = 0; @Nullable @@ -309,13 +307,14 @@ public class ReplInterpreter { List> earlierScripts = Lists.newArrayList(); for (EarlierLine earlierLine : earlierLines) { + //TODO_R: not needed earlierScripts.add(Pair.create(earlierLine.getScriptDescriptor(), earlierLine.getClassType())); } GenerationState state = new GenerationState(psiFile.getProject(), ClassBuilderFactories.BINARIES, module, trace.getBindingContext(), Collections.singletonList(psiFile)); - compileScript(psiFile.getScript(), scriptClassType, earlierScripts, state, CompilationErrorHandler.THROW_EXCEPTION); + compileScript(psiFile.getScript(), earlierScripts, state, CompilationErrorHandler.THROW_EXCEPTION); for (OutputFile outputFile : state.getFactory().asList()) { if(outputFile.getRelativePath().endsWith(".class")) { @@ -347,14 +346,13 @@ public class ReplInterpreter { setReplScriptExecuting(false); } - Field rvField = scriptClass.getDeclaredField("rv"); + Field rvField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME); rvField.setAccessible(true); Object rv = rvField.get(scriptInstance); earlierLines.add(new EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance, scriptClassType)); - KotlinType returnType = scriptDescriptor.getScriptCodeDescriptor().getReturnType(); - return LineResult.successful(rv, returnType != null && KotlinBuiltIns.isUnit(returnType)); + return LineResult.successful(rv, false); } catch (Throwable e) { @SuppressWarnings("UseOfSystemOutOrSystemErr") @@ -415,12 +413,8 @@ public class ReplInterpreter { return null; } - ScriptDescriptor scriptDescriptor = context.getScripts().get(psiFile.getScript()); - lastLineScope = trace.get(BindingContext.SCRIPT_SCOPE, scriptDescriptor); - if (lastLineScope == null) { - throw new IllegalStateException("last line scope is not initialized"); - } - + LazyScriptDescriptor scriptDescriptor = context.getScripts().get(psiFile.getScript()); + lastLineScope = scriptDescriptor.getScopeForInitializerResolution(); return scriptDescriptor; } @@ -435,26 +429,19 @@ public class ReplInterpreter { List earlierScriptDescriptors = new ArrayList(earlierScripts.size()); for (Pair pair : earlierScripts) { ScriptDescriptor earlierDescriptor = pair.first; - Type earlierClassType = pair.second; - - PsiElement jetScript = descriptorToDeclaration(earlierDescriptor); - if (jetScript != null) { - registerClassNameForScript(state.getBindingTrace(), (KtScript) jetScript, earlierClassType, state.getFileClassesProvider()); - earlierScriptDescriptors.add(earlierDescriptor); - } + earlierScriptDescriptors.add(earlierDescriptor); } state.setEarlierScriptsForReplInterpreter(earlierScriptDescriptors); } public static void compileScript( @NotNull KtScript script, - @NotNull Type classType, @NotNull List> earlierScripts, @NotNull GenerationState state, @NotNull CompilationErrorHandler errorHandler ) { + state.setScriptResultFieldName(SCRIPT_RESULT_FIELD_NAME); registerEarlierScripts(state, earlierScripts); - registerClassNameForScript(state.getBindingTrace(), script, classType, state.getFileClassesProvider()); state.beforeCompile(); KotlinCodegenFacade.generatePackage( diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt index 0a5c17803fd..6fd57e7a022 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt @@ -51,6 +51,7 @@ public class JvmDeclarationOrigin( public val descriptor: DeclarationDescriptor? ) { companion object { + @JvmField public val NO_ORIGIN: JvmDeclarationOrigin = JvmDeclarationOrigin(OTHER, null, null) } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassDataProvider.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassDataProvider.kt index e568ad505fe..d010709d8b1 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassDataProvider.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassDataProvider.kt @@ -98,7 +98,7 @@ abstract class LightClassDataProvider( /*disableOptimization=*/false, /*useTypeTableInSerializer=*/false, forExtraDiagnostics) - KotlinCodegenFacade.prepareForCompilation(state) + state.beforeCompile() bindingContext = state.bindingContext