Script refactoring, backend: scripts are classes now, remove/refactor 'special code' dealing with scripts

This commit is contained in:
Pavel V. Talanov
2015-11-17 15:13:30 +03:00
parent d037068bba
commit 6563830584
17 changed files with 146 additions and 251 deletions
@@ -368,13 +368,6 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
iv.invokestatic(REFLECTION, "getOrCreateKotlinPackage", iv.invokestatic(REFLECTION, "getOrCreateKotlinPackage",
Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE, getType(Class.class), getType(String.class)), false); 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 { else {
iv.aconst(null); iv.aconst(null);
} }
@@ -48,7 +48,6 @@ import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.codegen.when.SwitchCodegen; import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.ScriptCodeDescriptor;
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor; import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor;
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.diagnostics.Errors;
@@ -311,9 +310,28 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
public void gen(KtElement expr, Type type) { public void gen(KtElement expr, Type type) {
StackValue value = Type.VOID_TYPE.equals(type) ? genStatement(expr) : gen(expr); 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); 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) { public StackValue genLazy(KtElement expr, Type type) {
StackValue value = gen(expr); StackValue value = gen(expr);
return StackValue.coercion(value, type); return StackValue.coercion(value, type);
@@ -1968,21 +1986,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (localOrCaptured != null) { if (localOrCaptured != null) {
return localOrCaptured; 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); throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
} }
@@ -2496,14 +2499,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return StackValue.singleton(receiverDescriptor, typeMapper); return StackValue.singleton(receiverDescriptor, typeMapper);
} }
} }
else if (receiverDescriptor instanceof ScriptDescriptor) {
return generateScriptReceiver
((ScriptDescriptor) receiverDescriptor);
}
else { else {
return StackValue.thisOrOuter(this, receiverDescriptor, isSuper, return StackValue.thisOrOuter(this, receiverDescriptor, isSuper,
receiverValue instanceof CastImplicitClassReceiver || isEnumEntry(receiverDescriptor)); receiverValue instanceof CastImplicitClassReceiver || isEnumEntry(receiverDescriptor));
} }
} }
else if (receiverValue instanceof ScriptReceiver) {
return generateScript((ScriptReceiver) receiverValue);
}
else if (receiverValue instanceof ExtensionReceiver) { else if (receiverValue instanceof ExtensionReceiver) {
return generateReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor()); return generateReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor());
} }
@@ -2520,7 +2524,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return context.generateReceiver(descriptor, state, false); return context.generateReceiver(descriptor, state, false);
} }
private StackValue generateScript(@NotNull ScriptReceiver receiver) { @NotNull
private StackValue generateScriptReceiver(@NotNull ScriptDescriptor receiver) {
CodegenContext cur = context; CodegenContext cur = context;
StackValue result = StackValue.LOCAL_0; StackValue result = StackValue.LOCAL_0;
boolean inStartConstructorContext = cur instanceof ConstructorContext; boolean inStartConstructorContext = cur instanceof ConstructorContext;
@@ -2532,17 +2537,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (cur instanceof ScriptContext) { if (cur instanceof ScriptContext) {
ScriptContext scriptContext = (ScriptContext) cur; ScriptContext scriptContext = (ScriptContext) cur;
ScriptDescriptor receiverDeclarationDescriptor = receiver.getDeclarationDescriptor(); if (scriptContext.getScriptDescriptor() == receiver) {
if (scriptContext.getScriptDescriptor() == receiverDeclarationDescriptor) {
//TODO lazy //TODO lazy
return result; return result;
} }
else { Type currentScriptType = typeMapper.mapType(scriptContext.getScriptDescriptor());
Type currentScriptType = asmTypeForScriptDescriptor(bindingContext, scriptContext.getScriptDescriptor()); Type classType = typeMapper.mapType(receiver);
Type classType = asmTypeForScriptDescriptor(bindingContext, receiverDeclarationDescriptor); String fieldName = scriptContext.getScriptFieldName(receiver);
String fieldName = scriptContext.getScriptFieldName(receiverDeclarationDescriptor); return StackValue.field(classType, currentScriptType, fieldName, false, result, receiver);
return StackValue.field(classType, currentScriptType, fieldName, false, result, receiverDeclarationDescriptor);
}
} }
result = cur.getOuterExpression(result, false); result = cur.getOuterExpression(result, false);
@@ -2558,7 +2560,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@NotNull @NotNull
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) {
return generateThisOrOuter(calleeContainingClass, isSuper, false); return generateThisOrOuter(calleeContainingClass, isSuper, false);
@@ -3321,19 +3322,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
Type varType = asmType(variableDescriptor.getType()); Type varType = asmType(variableDescriptor.getType());
StackValue storeTo; StackValue storeTo = sharedVarType == null ? StackValue.local(index, varType) : StackValue.shared(index, varType);
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);
}
storeTo.store(initializer, v); storeTo.store(initializer, v);
} }
@@ -24,40 +24,20 @@ import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.psi.KtFile; 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.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.registerClassNameForScript;
public class KotlinCodegenFacade { 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( public static void compileCorrectFiles(
@NotNull GenerationState state, @NotNull GenerationState state,
@NotNull CompilationErrorHandler errorHandler @NotNull CompilationErrorHandler errorHandler
) { ) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
prepareForCompilation(state); state.beforeCompile();
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
@@ -273,13 +273,8 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
String outerClassInternalName = null; String outerClassInternalName = null;
if (containing instanceof ClassDescriptor) { if (containing instanceof ClassDescriptor) {
outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName(); outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName();
} /* disabled cause of KT-7775 }
else if (containing instanceof ScriptDescriptor) {
outerClassInternalName = asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) containing).getInternalName();
}*/
String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString(); String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName(); String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName();
v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass)); v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass));
} }
@@ -320,10 +315,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
return FileClasses.getFileClassType(fileClassesProvider, element.getContainingKtFile()); return FileClasses.getFileClassType(fileClassesProvider, element.getContainingKtFile());
} }
} }
/*disabled cause of KT-7775
else if (outermost instanceof ScriptContext) {
return asmTypeForScriptDescriptor(bindingContext, ((ScriptContext) outermost).getScriptDescriptor());
}*/
return null; return null;
} }
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.* import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ScriptReceiver
import org.jetbrains.kotlin.utils.sure import org.jetbrains.kotlin.utils.sure
import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
@@ -52,15 +51,7 @@ public class PropertyReferenceCodegen(
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) { ) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
private val asmType = typeMapper.mapClass(classDescriptor) private val asmType = typeMapper.mapClass(classDescriptor)
private val dispatchReceiverType = private val dispatchReceiverType = if (dispatchReceiver.exists()) dispatchReceiver.type else null
when {
dispatchReceiver is ScriptReceiver -> {
// TODO: fix receiver for scripts, see ScriptReceiver#getType
dispatchReceiver.declarationDescriptor.classDescriptor.defaultType
}
dispatchReceiver.exists() -> dispatchReceiver.type
else -> null
}
private val extensionReceiverType = target.extensionReceiverParameter?.type private val extensionReceiverType = target.extensionReceiverParameter?.type
@@ -23,12 +23,11 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
import org.jetbrains.kotlin.codegen.context.MethodContext; import org.jetbrains.kotlin.codegen.context.MethodContext;
import org.jetbrains.kotlin.codegen.context.ScriptContext; import org.jetbrains.kotlin.codegen.context.ScriptContext;
import org.jetbrains.kotlin.codegen.state.GenerationState; 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.ScriptDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext; 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.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.org.objectweb.asm.MethodVisitor; 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.Collections;
import java.util.List; 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.AsmTypes.OBJECT_TYPE;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.org.objectweb.asm.Opcodes.*; import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -55,18 +52,16 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
ScriptDescriptor scriptDescriptor = bindingContext.get(BindingContext.SCRIPT, declaration); ScriptDescriptor scriptDescriptor = bindingContext.get(BindingContext.SCRIPT, declaration);
assert scriptDescriptor != null; assert scriptDescriptor != null;
ClassDescriptor classDescriptorForScript = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); Type classType = state.getTypeMapper().mapType(scriptDescriptor);
assert classDescriptorForScript != null;
Type classType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor); ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, scriptDescriptor),
ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(declaration, classDescriptorForScript),
classType, declaration.getContainingFile()); classType, declaration.getContainingFile());
List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter(); List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter();
ScriptContext scriptContext = parentContext.intoScript( ScriptContext scriptContext = parentContext.intoScript(
scriptDescriptor, scriptDescriptor,
earlierScripts == null ? Collections.<ScriptDescriptor>emptyList() : earlierScripts, earlierScripts == null ? Collections.<ScriptDescriptor>emptyList() : earlierScripts,
classDescriptorForScript scriptDescriptor,
state.getTypeMapper()
); );
return new ScriptCodegen(declaration, state, scriptContext, builder); return new ScriptCodegen(declaration, state, scriptContext, builder);
} }
@@ -104,8 +99,8 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
protected void generateBody() { protected void generateBody() {
genMembers(); genMembers();
genFieldsForParameters(scriptDescriptor, v); genFieldsForParameters(scriptDescriptor, v);
genConstructor(scriptDescriptor, context.getContextDescriptor(), v, genConstructor(scriptDescriptor, v,
context.intoFunction(scriptDescriptor.getScriptCodeDescriptor())); context.intoFunction(scriptDescriptor.getUnsubstitutedPrimaryConstructor()));
} }
@Override @Override
@@ -115,22 +110,25 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
private void genConstructor( private void genConstructor(
@NotNull ScriptDescriptor scriptDescriptor, @NotNull ScriptDescriptor scriptDescriptor,
@NotNull ClassDescriptor classDescriptorForScript,
@NotNull ClassBuilder classBuilder, @NotNull ClassBuilder classBuilder,
@NotNull MethodContext methodContext @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()); 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( MethodVisitor mv = classBuilder.newMethod(
JvmDeclarationOriginKt.OtherOrigin(scriptDeclaration, scriptDescriptor.getClassDescriptor().getUnsubstitutedPrimaryConstructor()), JvmDeclarationOriginKt.OtherOrigin(scriptDeclaration, scriptDescriptor.getUnsubstitutedPrimaryConstructor()),
ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(), ACC_PUBLIC, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(),
null, null); null, null);
@@ -139,7 +137,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
Type classType = typeMapper.mapType(classDescriptorForScript); Type classType = typeMapper.mapType(scriptDescriptor);
iv.load(0, classType); iv.load(0, classType);
iv.invokespecial("java/lang/Object", "<init>", "()V", false); iv.invokespecial("java/lang/Object", "<init>", "()V", false);
@@ -156,22 +154,23 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes(); Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes();
int add = 0; int add = 0;
for (int i = 0; i < scriptDescriptor.getScriptCodeDescriptor().getValueParameters().size(); i++) { List<ValueParameterDescriptor> valueParameters = scriptDescriptor.getUnsubstitutedPrimaryConstructor().getValueParameters();
ValueParameterDescriptor parameter = scriptDescriptor.getScriptCodeDescriptor().getValueParameters().get(i); for (int i = 0; i < valueParameters.size(); i++) {
ValueParameterDescriptor parameter = valueParameters.get(i);
frameMap.enter(parameter, argTypes[i + add]); frameMap.enter(parameter, argTypes[i + add]);
} }
int offset = 1; int offset = 1;
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) { for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
Type earlierClassType = asmTypeForScriptDescriptor(bindingContext, earlierScript); Type earlierClassType = typeMapper.mapClass(earlierScript);
iv.load(0, classType); iv.load(0, classType);
iv.load(offset, earlierClassType); iv.load(offset, earlierClassType);
offset += earlierClassType.getSize(); offset += earlierClassType.getSize();
iv.putfield(classType.getInternalName(), context.getScriptFieldName(earlierScript), earlierClassType.getDescriptor()); 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()); Type parameterType = typeMapper.mapType(parameter.getType());
iv.load(0, classType); iv.load(0, classType);
iv.load(offset, parameterType); iv.load(offset, parameterType);
@@ -188,16 +187,6 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
} }
}); });
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); iv.areturn(Type.VOID_TYPE);
} }
@@ -207,12 +196,12 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
private void genFieldsForParameters(@NotNull ScriptDescriptor script, @NotNull ClassBuilder classBuilder) { private void genFieldsForParameters(@NotNull ScriptDescriptor script, @NotNull ClassBuilder classBuilder) {
for (ScriptDescriptor earlierScript : context.getEarlierScripts()) { for (ScriptDescriptor earlierScript : context.getEarlierScripts()) {
Type earlierClassName = asmTypeForScriptDescriptor(bindingContext, earlierScript); Type earlierClassName = typeMapper.mapType(earlierScript);
int access = ACC_PRIVATE | ACC_FINAL; int access = ACC_PUBLIC | ACC_FINAL;
classBuilder.newField(NO_ORIGIN, access, context.getScriptFieldName(earlierScript), earlierClassName.getDescriptor(), null, null); 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); Type parameterType = typeMapper.mapType(parameter);
int access = ACC_PUBLIC | ACC_FINAL; int access = ACC_PUBLIC | ACC_FINAL;
classBuilder.newField(JvmDeclarationOriginKt.OtherOrigin(parameter), access, parameter.getName().getIdentifier(), parameterType.getDescriptor(), null, null); classBuilder.newField(JvmDeclarationOriginKt.OtherOrigin(parameter), access, parameter.getName().getIdentifier(), parameterType.getDescriptor(), null, null);
@@ -235,8 +235,8 @@ public abstract class StackValue {
} }
@NotNull @NotNull
private static Field field(@NotNull FieldInfo info) { public static Field field(@NotNull FieldInfo info, @NotNull StackValue receiver) {
return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), true, none()); return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), info.isStatic(), receiver);
} }
@NotNull @NotNull
@@ -593,15 +593,15 @@ public abstract class StackValue {
@NotNull @NotNull
public static Field singleton(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeMapper typeMapper) { 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) { 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) { 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<InstructionAdapter, Unit> lambda) { public static StackValue operation(Type type, Function1<InstructionAdapter, Unit> lambda) {
@@ -158,24 +158,20 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
element.acceptChildren(this); 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 @Override
public void visitKtFile(@NotNull KtFile file) { public void visitKtFile(@NotNull KtFile file) {
if (file.isScript()) { nameStack.push(AsmUtil.internalNameByFqNameWithoutInnerClasses(file.getPackageFqName()));
// 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()));
}
file.acceptChildren(this); file.acceptChildren(this);
nameStack.pop(); nameStack.pop();
if (file.isScript()) {
classStack.pop();
}
} }
@Override @Override
@@ -386,7 +382,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
String peek = peekFromStack(nameStack); String peek = peekFromStack(nameStack);
String name = safeIdentifier(descriptor.getName()).asString(); String name = safeIdentifier(descriptor.getName()).asString();
if (containingDeclaration instanceof ClassDescriptor || containingDeclaration instanceof ScriptDescriptor) { if (containingDeclaration instanceof ClassDescriptor) {
return peek + '$' + name; return peek + '$' + name;
} }
else if (containingDeclaration instanceof PackageFragmentDescriptor) { else if (containingDeclaration instanceof PackageFragmentDescriptor) {
@@ -24,17 +24,13 @@ import org.jetbrains.kotlin.codegen.SamType;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl;
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice; import org.jetbrains.kotlin.util.slicedMap.BasicWritableSlice;
import org.jetbrains.kotlin.util.slicedMap.Slices; import org.jetbrains.kotlin.util.slicedMap.Slices;
import org.jetbrains.kotlin.util.slicedMap.WritableSlice; import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
@@ -43,15 +39,12 @@ import org.jetbrains.org.objectweb.asm.Type;
import java.util.*; import java.util.*;
import static org.jetbrains.kotlin.resolve.BindingContext.*; import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
public class CodegenBinding { public class CodegenBinding {
public static final WritableSlice<ClassDescriptor, MutableClosure> CLOSURE = Slices.createSimpleSlice(); public static final WritableSlice<ClassDescriptor, MutableClosure> CLOSURE = Slices.createSimpleSlice();
public static final WritableSlice<CallableDescriptor, ClassDescriptor> CLASS_FOR_CALLABLE = Slices.createSimpleSlice(); public static final WritableSlice<CallableDescriptor, ClassDescriptor> CLASS_FOR_CALLABLE = Slices.createSimpleSlice();
public static final WritableSlice<ScriptDescriptor, ClassDescriptor> CLASS_FOR_SCRIPT = Slices.createSimpleSlice();
public static final WritableSlice<ClassDescriptor, Type> ASM_TYPE = Slices.createSimpleSlice(); public static final WritableSlice<ClassDescriptor, Type> ASM_TYPE = Slices.createSimpleSlice();
public static final WritableSlice<ClassDescriptor, Boolean> ENUM_ENTRY_CLASS_NEED_SUBCLASS = Slices.createSimpleSetSlice(); public static final WritableSlice<ClassDescriptor, Boolean> 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)); 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 @NotNull
public static ClassDescriptor anonymousClassForCallable( public static ClassDescriptor anonymousClassForCallable(
@NotNull BindingContext bindingContext, @NotNull BindingContext bindingContext,
@@ -163,7 +140,7 @@ public class CodegenBinding {
@NotNull Type asmType, @NotNull Type asmType,
@NotNull JvmFileClassesProvider fileClassesManager @NotNull JvmFileClassesProvider fileClassesManager
) { ) {
KtElement element = (KtElement) descriptorToDeclaration(classDescriptor); KtElement element = (KtElement) DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor);
assert element != null : "No source element for " + classDescriptor; assert element != null : "No source element for " + classDescriptor;
MutableClosure closure = new MutableClosure(classDescriptor, enclosing); MutableClosure closure = new MutableClosure(classDescriptor, enclosing);
@@ -196,29 +173,6 @@ public class CodegenBinding {
innerClasses.add(inner); 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("<script-" + simpleName + ">"), Modality.FINAL,
Collections.singleton(DescriptorUtilsKt.getBuiltIns(descriptor).getAnyType()),
KotlinSourceElementKt.toSourceElement(script));
classDescriptor.initialize(MemberScope.Empty.INSTANCE, Collections.<ConstructorDescriptor>emptySet(), null);
recordClosure(trace, classDescriptor, null, asmType, fileClassesManager);
trace.record(CLASS_FOR_SCRIPT, descriptor, classDescriptor);
}
@NotNull @NotNull
private static Collection<KtFile> allFilesInPackages(BindingContext bindingContext, Collection<KtFile> files) { private static Collection<KtFile> allFilesInPackages(BindingContext bindingContext, Collection<KtFile> files) {
// todo: we use Set and add given files but ignoring other scripts because something non-clear kept in binding // todo: we use Set and add given files but ignoring other scripts because something non-clear kept in binding
@@ -315,9 +315,10 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
public ScriptContext intoScript( public ScriptContext intoScript(
@NotNull ScriptDescriptor script, @NotNull ScriptDescriptor script,
@NotNull List<ScriptDescriptor> earlierScripts, @NotNull List<ScriptDescriptor> 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 @NotNull
@@ -16,30 +16,48 @@
package org.jetbrains.kotlin.codegen.context; package org.jetbrains.kotlin.codegen.context;
import kotlin.CollectionsKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.FieldInfo;
import org.jetbrains.kotlin.codegen.OwnerKind; 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.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ScriptDescriptor; 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; import java.util.List;
public class ScriptContext extends FieldOwnerContext<ClassDescriptor> { public class ScriptContext extends ClassContext {
private final ScriptDescriptor scriptDescriptor; private final ScriptDescriptor scriptDescriptor;
private final List<ScriptDescriptor> earlierScripts; private final List<ScriptDescriptor> earlierScripts;
private final KtExpression lastStatement;
public ScriptContext( public ScriptContext(
@NotNull JetTypeMapper typeMapper,
@NotNull ScriptDescriptor scriptDescriptor, @NotNull ScriptDescriptor scriptDescriptor,
@NotNull List<ScriptDescriptor> earlierScripts, @NotNull List<ScriptDescriptor> earlierScripts,
@NotNull ClassDescriptor contextDescriptor, @NotNull ClassDescriptor contextDescriptor,
@NotNull OwnerKind contextKind, @Nullable CodegenContext parentContext
@Nullable CodegenContext parentContext,
@Nullable MutableClosure closure
) { ) {
super(contextDescriptor, contextKind, parentContext, closure, contextDescriptor, null); super(typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, null);
this.scriptDescriptor = scriptDescriptor; this.scriptDescriptor = scriptDescriptor;
this.earlierScripts = earlierScripts; 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 @NotNull
@@ -47,6 +65,15 @@ public class ScriptContext extends FieldOwnerContext<ClassDescriptor> {
return scriptDescriptor; 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 @NotNull
public List<ScriptDescriptor> getEarlierScripts() { public List<ScriptDescriptor> getEarlierScripts() {
return earlierScripts; return earlierScripts;
@@ -61,6 +88,11 @@ public class ScriptContext extends FieldOwnerContext<ClassDescriptor> {
return "script$" + (index + 1); return "script$" + (index + 1);
} }
@Nullable
public KtExpression getLastStatement() {
return lastStatement;
}
@Override @Override
public String toString() { public String toString() {
return "Script: " + getContextDescriptor().getName().asString(); return "Script: " + getContextDescriptor().getName().asString();
@@ -62,7 +62,6 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags; import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; 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.addInlineMarker;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getConstant; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.getConstant;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral; 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); CodegenContext parent = getContext(descriptor.getContainingDeclaration(), state, sourceFile);
if (descriptor instanceof ClassDescriptor) { if (descriptor instanceof ScriptDescriptor) {
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;
List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter(); List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter();
return parent.intoScript((ScriptDescriptor) descriptor, return parent.intoScript((ScriptDescriptor) descriptor,
earlierScripts == null ? Collections.emptyList() : earlierScripts, 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) { else if (descriptor instanceof FunctionDescriptor) {
return parent.intoFunction((FunctionDescriptor) descriptor); return parent.intoFunction((FunctionDescriptor) descriptor);
@@ -101,6 +101,8 @@ public class GenerationState @JvmOverloads constructor(
public val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics) public val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics)
public val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this) public val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this)
public var earlierScriptsForReplInterpreter: List<ScriptDescriptor>? = null public var earlierScriptsForReplInterpreter: List<ScriptDescriptor>? = null
public var scriptResultFieldName: String? = null
public val shouldGenerateScriptResultValue: Boolean get() = scriptResultFieldName != null
public val reflectionTypes: ReflectionTypes = ReflectionTypes(module) public val reflectionTypes: ReflectionTypes = ReflectionTypes(module)
public val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes() public val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes()
public val factory: ClassFileFactory public val factory: ClassFileFactory
@@ -169,9 +169,6 @@ public class JetTypeMapper {
else if (container instanceof ClassDescriptor) { else if (container instanceof ClassDescriptor) {
return mapClass((ClassDescriptor) container); return mapClass((ClassDescriptor) container);
} }
else if (container instanceof ScriptDescriptor) {
return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container);
}
else { else {
throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor); 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; 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; assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass;
String containerInternalName = computeAsmTypeImpl((ClassDescriptor) container); String containerInternalName = computeAsmTypeImpl((ClassDescriptor) container);
@@ -1392,12 +1385,10 @@ public class JetTypeMapper {
sw.writeParametersStart(); sw.writeParametersStart();
for (ScriptDescriptor importedScript : importedScripts) { for (ScriptDescriptor importedScript : importedScripts) {
ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript); writeParameter(sw, importedScript.getDefaultType());
assert descriptor != null : "Script not found: " + importedScript;
writeParameter(sw, descriptor.getDefaultType());
} }
for (ValueParameterDescriptor valueParameter : script.getScriptCodeDescriptor().getValueParameters()) { for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
writeParameter(sw, valueParameter.getType()); writeParameter(sw, valueParameter.getType());
} }
@@ -22,7 +22,6 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileFactory; import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.impl.PsiFileFactoryImpl; import com.intellij.psi.impl.PsiFileFactoryImpl;
import com.intellij.psi.search.ProjectScope; import com.intellij.psi.search.ProjectScope;
@@ -30,7 +29,6 @@ import com.intellij.testFramework.LightVirtualFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.output.OutputFile; 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.AnalyzerWithCompilerReport;
import org.jetbrains.kotlin.cli.common.messages.DiagnosticMessageReporter; import org.jetbrains.kotlin.cli.common.messages.DiagnosticMessageReporter;
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport; 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.ResolveSession;
import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo; import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.kotlin.resolve.lazy.declarations.*; 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.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.Type;
@@ -85,10 +83,10 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.kotlin.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses; 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 { public class ReplInterpreter {
private static final String SCRIPT_RESULT_FIELD_NAME = "$$result";
private int lineNumber = 0; private int lineNumber = 0;
@Nullable @Nullable
@@ -309,13 +307,14 @@ public class ReplInterpreter {
List<Pair<ScriptDescriptor, Type>> earlierScripts = Lists.newArrayList(); List<Pair<ScriptDescriptor, Type>> earlierScripts = Lists.newArrayList();
for (EarlierLine earlierLine : earlierLines) { for (EarlierLine earlierLine : earlierLines) {
//TODO_R: not needed
earlierScripts.add(Pair.create(earlierLine.getScriptDescriptor(), earlierLine.getClassType())); earlierScripts.add(Pair.create(earlierLine.getScriptDescriptor(), earlierLine.getClassType()));
} }
GenerationState state = new GenerationState(psiFile.getProject(), ClassBuilderFactories.BINARIES, GenerationState state = new GenerationState(psiFile.getProject(), ClassBuilderFactories.BINARIES,
module, trace.getBindingContext(), Collections.singletonList(psiFile)); 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()) { for (OutputFile outputFile : state.getFactory().asList()) {
if(outputFile.getRelativePath().endsWith(".class")) { if(outputFile.getRelativePath().endsWith(".class")) {
@@ -347,14 +346,13 @@ public class ReplInterpreter {
setReplScriptExecuting(false); setReplScriptExecuting(false);
} }
Field rvField = scriptClass.getDeclaredField("rv"); Field rvField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME);
rvField.setAccessible(true); rvField.setAccessible(true);
Object rv = rvField.get(scriptInstance); Object rv = rvField.get(scriptInstance);
earlierLines.add(new EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance, scriptClassType)); earlierLines.add(new EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance, scriptClassType));
KotlinType returnType = scriptDescriptor.getScriptCodeDescriptor().getReturnType(); return LineResult.successful(rv, false);
return LineResult.successful(rv, returnType != null && KotlinBuiltIns.isUnit(returnType));
} }
catch (Throwable e) { catch (Throwable e) {
@SuppressWarnings("UseOfSystemOutOrSystemErr") @SuppressWarnings("UseOfSystemOutOrSystemErr")
@@ -415,12 +413,8 @@ public class ReplInterpreter {
return null; return null;
} }
ScriptDescriptor scriptDescriptor = context.getScripts().get(psiFile.getScript()); LazyScriptDescriptor scriptDescriptor = context.getScripts().get(psiFile.getScript());
lastLineScope = trace.get(BindingContext.SCRIPT_SCOPE, scriptDescriptor); lastLineScope = scriptDescriptor.getScopeForInitializerResolution();
if (lastLineScope == null) {
throw new IllegalStateException("last line scope is not initialized");
}
return scriptDescriptor; return scriptDescriptor;
} }
@@ -435,26 +429,19 @@ public class ReplInterpreter {
List<ScriptDescriptor> earlierScriptDescriptors = new ArrayList<ScriptDescriptor>(earlierScripts.size()); List<ScriptDescriptor> earlierScriptDescriptors = new ArrayList<ScriptDescriptor>(earlierScripts.size());
for (Pair<ScriptDescriptor, Type> pair : earlierScripts) { for (Pair<ScriptDescriptor, Type> pair : earlierScripts) {
ScriptDescriptor earlierDescriptor = pair.first; ScriptDescriptor earlierDescriptor = pair.first;
Type earlierClassType = pair.second; earlierScriptDescriptors.add(earlierDescriptor);
PsiElement jetScript = descriptorToDeclaration(earlierDescriptor);
if (jetScript != null) {
registerClassNameForScript(state.getBindingTrace(), (KtScript) jetScript, earlierClassType, state.getFileClassesProvider());
earlierScriptDescriptors.add(earlierDescriptor);
}
} }
state.setEarlierScriptsForReplInterpreter(earlierScriptDescriptors); state.setEarlierScriptsForReplInterpreter(earlierScriptDescriptors);
} }
public static void compileScript( public static void compileScript(
@NotNull KtScript script, @NotNull KtScript script,
@NotNull Type classType,
@NotNull List<Pair<ScriptDescriptor, Type>> earlierScripts, @NotNull List<Pair<ScriptDescriptor, Type>> earlierScripts,
@NotNull GenerationState state, @NotNull GenerationState state,
@NotNull CompilationErrorHandler errorHandler @NotNull CompilationErrorHandler errorHandler
) { ) {
state.setScriptResultFieldName(SCRIPT_RESULT_FIELD_NAME);
registerEarlierScripts(state, earlierScripts); registerEarlierScripts(state, earlierScripts);
registerClassNameForScript(state.getBindingTrace(), script, classType, state.getFileClassesProvider());
state.beforeCompile(); state.beforeCompile();
KotlinCodegenFacade.generatePackage( KotlinCodegenFacade.generatePackage(
@@ -51,6 +51,7 @@ public class JvmDeclarationOrigin(
public val descriptor: DeclarationDescriptor? public val descriptor: DeclarationDescriptor?
) { ) {
companion object { companion object {
@JvmField
public val NO_ORIGIN: JvmDeclarationOrigin = JvmDeclarationOrigin(OTHER, null, null) public val NO_ORIGIN: JvmDeclarationOrigin = JvmDeclarationOrigin(OTHER, null, null)
} }
} }
@@ -98,7 +98,7 @@ abstract class LightClassDataProvider<T : WithFileStubAndExtraDiagnostics>(
/*disableOptimization=*/false, /*disableOptimization=*/false,
/*useTypeTableInSerializer=*/false, /*useTypeTableInSerializer=*/false,
forExtraDiagnostics) forExtraDiagnostics)
KotlinCodegenFacade.prepareForCompilation(state) state.beforeCompile()
bindingContext = state.bindingContext bindingContext = state.bindingContext