better script class name
This commit is contained in:
@@ -42,6 +42,8 @@ public class ClosureAnnotator {
|
|||||||
private final Map<JetElement, JvmClassName> classNamesForAnonymousClasses = new HashMap<JetElement, JvmClassName>();
|
private final Map<JetElement, JvmClassName> classNamesForAnonymousClasses = new HashMap<JetElement, JvmClassName>();
|
||||||
private final Map<ClassDescriptor, JvmClassName> classNamesForClassDescriptor = new HashMap<ClassDescriptor, JvmClassName>();
|
private final Map<ClassDescriptor, JvmClassName> classNamesForClassDescriptor = new HashMap<ClassDescriptor, JvmClassName>();
|
||||||
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
||||||
|
private final Map<ScriptDescriptor, JvmClassName> classNameForScript = new HashMap<ScriptDescriptor, JvmClassName>();
|
||||||
|
private final Set<JvmClassName> scriptClassNames = new HashSet<JvmClassName>();
|
||||||
private final Map<DeclarationDescriptor, ClassDescriptorImpl> classesForFunctions = new HashMap<DeclarationDescriptor, ClassDescriptorImpl>();
|
private final Map<DeclarationDescriptor, ClassDescriptorImpl> classesForFunctions = new HashMap<DeclarationDescriptor, ClassDescriptorImpl>();
|
||||||
private final Map<DeclarationDescriptor,ClassDescriptor> enclosing = new HashMap<DeclarationDescriptor, ClassDescriptor>();
|
private final Map<DeclarationDescriptor,ClassDescriptor> enclosing = new HashMap<DeclarationDescriptor, ClassDescriptor>();
|
||||||
|
|
||||||
@@ -86,27 +88,66 @@ public class ClosureAnnotator {
|
|||||||
return classDescriptor;
|
return classDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void registerClassNameForScript(@NotNull ScriptDescriptor scriptDescriptor, @NotNull JvmClassName className) {
|
||||||
|
JvmClassName oldName = classNameForScript.put(scriptDescriptor, className);
|
||||||
|
if (oldName != null) {
|
||||||
|
throw new IllegalStateException("Rewrite at key " + scriptDescriptor + " for name");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scriptClassNames.add(className)) {
|
||||||
|
throw new IllegalStateException("More than one script has class name " + className);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
|
||||||
|
scriptDescriptor,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
Name.special("<script-" + className + ">"));
|
||||||
|
recordName(classDescriptor, className);
|
||||||
|
classDescriptor.initialize(
|
||||||
|
false,
|
||||||
|
Collections.<TypeParameterDescriptor>emptyList(),
|
||||||
|
Collections.singletonList(JetStandardClasses.getAnyType()),
|
||||||
|
JetScope.EMPTY,
|
||||||
|
Collections.<ConstructorDescriptor>emptySet(),
|
||||||
|
null);
|
||||||
|
|
||||||
|
ClassDescriptorImpl oldDescriptor = classesForFunctions.put(scriptDescriptor, classDescriptor);
|
||||||
|
if (oldDescriptor != null) {
|
||||||
|
throw new IllegalStateException("Rewrite at key " + scriptDescriptor + " for class");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerClassNameForScript(@NotNull JetScript jetScript, @NotNull JvmClassName className) {
|
||||||
|
ScriptDescriptor descriptor = bindingContext.get(BindingContext.SCRIPT, jetScript);
|
||||||
|
if (descriptor == null) {
|
||||||
|
throw new IllegalStateException("Descriptor is not found for PSI " + jetScript);
|
||||||
|
}
|
||||||
|
registerClassNameForScript(descriptor, className);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public ClassDescriptor classDescriptorForScrpitDescriptor(@NotNull ScriptDescriptor scriptDescriptor) {
|
public ClassDescriptor classDescriptorForScrpitDescriptor(@NotNull ScriptDescriptor scriptDescriptor) {
|
||||||
ClassDescriptorImpl classDescriptor = classesForFunctions.get(scriptDescriptor);
|
ClassDescriptorImpl classDescriptor = classesForFunctions.get(scriptDescriptor);
|
||||||
if (classDescriptor == null) {
|
if (classDescriptor == null) {
|
||||||
classDescriptor = new ClassDescriptorImpl(
|
throw new IllegalStateException("Class for script is not registered: " + scriptDescriptor);
|
||||||
scriptDescriptor,
|
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
|
||||||
Name.special("<script>"));
|
|
||||||
recordName(classDescriptor, JvmClassName.byInternalName("Script"));
|
|
||||||
classDescriptor.initialize(
|
|
||||||
false,
|
|
||||||
Collections.<TypeParameterDescriptor>emptyList(),
|
|
||||||
Collections.singletonList(JetStandardClasses.getAnyType()),
|
|
||||||
JetScope.EMPTY,
|
|
||||||
Collections.<ConstructorDescriptor>emptySet(),
|
|
||||||
null);
|
|
||||||
classesForFunctions.put(scriptDescriptor, classDescriptor);
|
|
||||||
}
|
}
|
||||||
return classDescriptor;
|
return classDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JvmClassName classNameForScriptPsi(@NotNull JetScript script) {
|
||||||
|
ScriptDescriptor scriptDescriptor = bindingContext.get(BindingContext.SCRIPT, script);
|
||||||
|
if (scriptDescriptor == null) {
|
||||||
|
throw new IllegalStateException("Script descriptor not found by PSI " + script);
|
||||||
|
}
|
||||||
|
return classNameForScriptDescriptor(scriptDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JvmClassName classNameForScriptDescriptor(@NotNull ScriptDescriptor scriptDescriptor) {
|
||||||
|
return classNameForClassDescriptor(classDescriptorForScrpitDescriptor(scriptDescriptor));
|
||||||
|
}
|
||||||
|
|
||||||
private void mapFilesToNamespaces(Collection<JetFile> files) {
|
private void mapFilesToNamespaces(Collection<JetFile> files) {
|
||||||
for (JetFile file : files) {
|
for (JetFile file : files) {
|
||||||
if (file.isScript()) {
|
if (file.isScript()) {
|
||||||
|
|||||||
@@ -2339,7 +2339,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
int index = -1;
|
int index = -1;
|
||||||
|
|
||||||
if (property.isScriptDeclaration()) {
|
if (property.isScriptDeclaration()) {
|
||||||
StackValue field = StackValue.field(typeMapper.mapType(variableDescriptor.getType(), MapTypeMode.VALUE), JvmClassName.byInternalName("Script"), property.getName(), false);
|
JetScript scriptPsi = property.getScript();
|
||||||
|
JvmClassName scriptClassName = state.getInjector().getClosureAnnotator().classNameForScriptPsi(scriptPsi);
|
||||||
|
StackValue field = StackValue.field(typeMapper.mapType(variableDescriptor.getType(), MapTypeMode.VALUE), scriptClassName, property.getName(), false);
|
||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -2366,7 +2368,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
if (property.isScriptDeclaration()) {
|
if (property.isScriptDeclaration()) {
|
||||||
gen(initializer, varType);
|
gen(initializer, varType);
|
||||||
v.putfield("Script", property.getName(), varType.getDescriptor());
|
JetScript scriptPsi = property.getScript();
|
||||||
|
JvmClassName scriptClassName = state.getInjector().getClosureAnnotator().classNameForScriptPsi(scriptPsi);
|
||||||
|
v.putfield(scriptClassName.getInternalName(), property.getName(), varType.getDescriptor());
|
||||||
}
|
}
|
||||||
else if (sharedVarType == null) {
|
else if (sharedVarType == null) {
|
||||||
gen(initializer, varType);
|
gen(initializer, varType);
|
||||||
|
|||||||
@@ -128,6 +128,13 @@ public class GenerationState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void compileCorrectFiles(@NotNull CompilationErrorHandler errorHandler) {
|
public void compileCorrectFiles(@NotNull CompilationErrorHandler errorHandler) {
|
||||||
|
|
||||||
|
for (JetFile file : this.files) {
|
||||||
|
if (file.isScript()) {
|
||||||
|
injector.getClosureAnnotator().registerClassNameForScript(file.getScript(), ScriptCodegen.SCRIPT_DEFAULT_CLASS_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MultiMap<FqName, JetFile> namespaceGrouping = new MultiMap<FqName, JetFile>();
|
MultiMap<FqName, JetFile> namespaceGrouping = new MultiMap<FqName, JetFile>();
|
||||||
for (JetFile file : this.files) {
|
for (JetFile file : this.files) {
|
||||||
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
|
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ public class JetTypeMapper {
|
|||||||
return JvmClassName.byType(asmType);
|
return JvmClassName.byType(asmType);
|
||||||
}
|
}
|
||||||
else if (containingDeclaration instanceof ScriptDescriptor) {
|
else if (containingDeclaration instanceof ScriptDescriptor) {
|
||||||
return JvmClassName.byInternalName("Script");
|
return closureAnnotator.classNameForScriptDescriptor((ScriptDescriptor) containingDeclaration);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration);
|
throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration);
|
||||||
@@ -582,7 +582,7 @@ public class JetTypeMapper {
|
|||||||
thisClass = null;
|
thisClass = null;
|
||||||
}
|
}
|
||||||
else if (functionParent instanceof ScriptDescriptor) {
|
else if (functionParent instanceof ScriptDescriptor) {
|
||||||
thisClass = owner = ownerForDefaultParam = ownerForDefaultImpl = JvmClassName.byInternalName("Script");
|
thisClass = owner = ownerForDefaultParam = ownerForDefaultImpl = closureAnnotator.classNameForScriptDescriptor((ScriptDescriptor) functionParent);
|
||||||
invokeOpcode = INVOKEVIRTUAL;
|
invokeOpcode = INVOKEVIRTUAL;
|
||||||
}
|
}
|
||||||
else if (functionParent instanceof ClassDescriptor) {
|
else if (functionParent instanceof ClassDescriptor) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.psi.JetScript;
|
|||||||
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner;
|
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JdkNames;
|
import org.jetbrains.jet.lang.resolve.java.JdkNames;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
@@ -38,6 +39,8 @@ import javax.inject.Inject;
|
|||||||
*/
|
*/
|
||||||
public class ScriptCodegen {
|
public class ScriptCodegen {
|
||||||
|
|
||||||
|
public static final JvmClassName SCRIPT_DEFAULT_CLASS_NAME = JvmClassName.byInternalName("Script");
|
||||||
|
|
||||||
public static final String LAST_EXPRESSION_VALUE_FIELD_NAME = "rv";
|
public static final String LAST_EXPRESSION_VALUE_FIELD_NAME = "rv";
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -94,11 +97,13 @@ public class ScriptCodegen {
|
|||||||
|
|
||||||
CodegenContexts.ScriptContext context = (CodegenContexts.ScriptContext) CodegenContexts.STATIC.intoScript(scriptDescriptor, classDescriptorForScript);
|
CodegenContexts.ScriptContext context = (CodegenContexts.ScriptContext) CodegenContexts.STATIC.intoScript(scriptDescriptor, classDescriptorForScript);
|
||||||
|
|
||||||
ClassBuilder classBuilder = classFileFactory.newVisitor("Script.class");
|
JvmClassName className = closureAnnotator.classNameForClassDescriptor(classDescriptorForScript);
|
||||||
|
|
||||||
|
ClassBuilder classBuilder = classFileFactory.newVisitor(className.getInternalName() + ".class");
|
||||||
classBuilder.defineClass(scriptDeclaration,
|
classBuilder.defineClass(scriptDeclaration,
|
||||||
Opcodes.V1_6,
|
Opcodes.V1_6,
|
||||||
Opcodes.ACC_PUBLIC,
|
Opcodes.ACC_PUBLIC,
|
||||||
"Script",
|
className.getInternalName(),
|
||||||
null,
|
null,
|
||||||
JdkNames.JL_OBJECT.getInternalName(),
|
JdkNames.JL_OBJECT.getInternalName(),
|
||||||
new String[0]);
|
new String[0]);
|
||||||
@@ -130,10 +135,12 @@ public class ScriptCodegen {
|
|||||||
|
|
||||||
InstructionAdapter instructionAdapter = new InstructionAdapter(mv);
|
InstructionAdapter instructionAdapter = new InstructionAdapter(mv);
|
||||||
|
|
||||||
instructionAdapter.load(0, Type.getObjectType("Script"));
|
JvmClassName className = closureAnnotator.classNameForClassDescriptor(classDescriptorForScript);
|
||||||
|
|
||||||
|
instructionAdapter.load(0, className.getAsmType());
|
||||||
instructionAdapter.invokespecial(JdkNames.JL_OBJECT.getInternalName(), "<init>", "()V");
|
instructionAdapter.invokespecial(JdkNames.JL_OBJECT.getInternalName(), "<init>", "()V");
|
||||||
|
|
||||||
instructionAdapter.load(0, Type.getObjectType("Script"));
|
instructionAdapter.load(0, className.getAsmType());
|
||||||
|
|
||||||
FrameMap frameMap = context.prepareFrame(jetTypeMapper);
|
FrameMap frameMap = context.prepareFrame(jetTypeMapper);
|
||||||
|
|
||||||
@@ -155,7 +162,7 @@ public class ScriptCodegen {
|
|||||||
StackValue stackValue = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state).gen(scriptDeclaration.getBlockExpression());
|
StackValue stackValue = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state).gen(scriptDeclaration.getBlockExpression());
|
||||||
if (stackValue.type != Type.VOID_TYPE) {
|
if (stackValue.type != Type.VOID_TYPE) {
|
||||||
stackValue.put(stackValue.type, instructionAdapter);
|
stackValue.put(stackValue.type, instructionAdapter);
|
||||||
instructionAdapter.putfield("Script", LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor());
|
instructionAdapter.putfield(className.getInternalName(), LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
instructionAdapter.areturn(Type.VOID_TYPE);
|
instructionAdapter.areturn(Type.VOID_TYPE);
|
||||||
|
|||||||
+1
-1
@@ -160,7 +160,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
configuration.getEnvironment().getCompilerDependencies().getRuntimeJar().toURI().toURL()
|
configuration.getEnvironment().getCompilerDependencies().getRuntimeJar().toURI().toURL()
|
||||||
},
|
},
|
||||||
AllModules.class.getClassLoader()));
|
AllModules.class.getClassLoader()));
|
||||||
Class<?> scriptClass = classLoader.loadClass("Script");
|
Class<?> scriptClass = classLoader.loadClass(ScriptCodegen.SCRIPT_DEFAULT_CLASS_NAME.getFqName().getFqName());
|
||||||
scriptClass.getConstructor(String[].class).newInstance(new Object[]{ configuration.getScriptArgs().toArray(new String[0]) });
|
scriptClass.getConstructor(String[].class).newInstance(new Object[]{ configuration.getScriptArgs().toArray(new String[0]) });
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Failed to evaluate script: " + e, e);
|
throw new RuntimeException("Failed to evaluate script: " + e, e);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.jetbrains.jet.codegen.ClassBuilderFactories;
|
|||||||
import org.jetbrains.jet.codegen.CompilationErrorHandler;
|
import org.jetbrains.jet.codegen.CompilationErrorHandler;
|
||||||
import org.jetbrains.jet.codegen.GeneratedClassLoader;
|
import org.jetbrains.jet.codegen.GeneratedClassLoader;
|
||||||
import org.jetbrains.jet.codegen.GenerationState;
|
import org.jetbrains.jet.codegen.GenerationState;
|
||||||
|
import org.jetbrains.jet.codegen.ScriptCodegen;
|
||||||
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
|
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
|
||||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
@@ -109,7 +110,7 @@ public class ReplInterpreter {
|
|||||||
generationState.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION);
|
generationState.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class<?> scriptClass = new GeneratedClassLoader(generationState.getFactory()).loadClass("Script");
|
Class<?> scriptClass = new GeneratedClassLoader(generationState.getFactory()).loadClass(ScriptCodegen.SCRIPT_DEFAULT_CLASS_NAME.getFqName().getFqName());
|
||||||
Constructor<?> scriptInstanceConstructor = scriptClass.getConstructor(new Class<?>[0]);
|
Constructor<?> scriptInstanceConstructor = scriptClass.getConstructor(new Class<?>[0]);
|
||||||
Object scriptInstance = scriptInstanceConstructor.newInstance(new Object[0]);
|
Object scriptInstance = scriptInstanceConstructor.newInstance(new Object[0]);
|
||||||
Field rvField = scriptClass.getDeclaredField("rv");
|
Field rvField = scriptClass.getDeclaredField("rv");
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiNameIdentifierOwner;
|
|||||||
import com.intellij.util.IncorrectOperationException;
|
import com.intellij.util.IncorrectOperationException;
|
||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
@@ -73,6 +74,16 @@ public abstract class JetNamedDeclaration extends JetDeclaration implements PsiN
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isScriptDeclaration() {
|
public boolean isScriptDeclaration() {
|
||||||
return getParent() != null && getParent().getParent() instanceof JetScript;
|
return getScript() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public JetScript getScript() {
|
||||||
|
if (getParent() != null && getParent().getParent() instanceof JetScript) {
|
||||||
|
return (JetScript) getParent().getParent();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ public abstract class CodegenTestCase extends UsefulTestCase {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (myFiles.isScript()) {
|
if (myFiles.isScript()) {
|
||||||
Class<?> scriptClass = loader.loadClass("Script");
|
Class<?> scriptClass = loader.loadClass(ScriptCodegen.SCRIPT_DEFAULT_CLASS_NAME.getFqName().getFqName());
|
||||||
|
|
||||||
Constructor constructor = getConstructor(scriptClass, state.getScriptConstructorMethod());
|
Constructor constructor = getConstructor(scriptClass, state.getScriptConstructorMethod());
|
||||||
scriptInstance = constructor.newInstance(myFiles.getScriptParameterValues().toArray());
|
scriptInstance = constructor.newInstance(myFiles.getScriptParameterValues().toArray());
|
||||||
|
|||||||
Reference in New Issue
Block a user