better script class name

This commit is contained in:
Stepan Koltsov
2012-06-08 04:19:23 +04:00
parent 2d88c74635
commit 8a3d3d21bd
9 changed files with 97 additions and 26 deletions
@@ -42,6 +42,8 @@ public class ClosureAnnotator {
private final Map<JetElement, JvmClassName> classNamesForAnonymousClasses = new HashMap<JetElement, JvmClassName>();
private final Map<ClassDescriptor, JvmClassName> classNamesForClassDescriptor = new HashMap<ClassDescriptor, JvmClassName>();
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,ClassDescriptor> enclosing = new HashMap<DeclarationDescriptor, ClassDescriptor>();
@@ -86,27 +88,66 @@ public class ClosureAnnotator {
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
public ClassDescriptor classDescriptorForScrpitDescriptor(@NotNull ScriptDescriptor scriptDescriptor) {
ClassDescriptorImpl classDescriptor = classesForFunctions.get(scriptDescriptor);
if (classDescriptor == null) {
classDescriptor = new ClassDescriptorImpl(
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);
throw new IllegalStateException("Class for script is not registered: " + scriptDescriptor);
}
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) {
for (JetFile file : files) {
if (file.isScript()) {
@@ -2339,7 +2339,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
int index = -1;
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();
}
else {
@@ -2366,7 +2368,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (initializer != null) {
if (property.isScriptDeclaration()) {
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) {
gen(initializer, varType);
@@ -128,6 +128,13 @@ public class GenerationState {
}
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>();
for (JetFile file : this.files) {
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
@@ -168,7 +168,7 @@ public class JetTypeMapper {
return JvmClassName.byType(asmType);
}
else if (containingDeclaration instanceof ScriptDescriptor) {
return JvmClassName.byInternalName("Script");
return closureAnnotator.classNameForScriptDescriptor((ScriptDescriptor) containingDeclaration);
}
else {
throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration);
@@ -582,7 +582,7 @@ public class JetTypeMapper {
thisClass = null;
}
else if (functionParent instanceof ScriptDescriptor) {
thisClass = owner = ownerForDefaultParam = ownerForDefaultImpl = JvmClassName.byInternalName("Script");
thisClass = owner = ownerForDefaultParam = ownerForDefaultImpl = closureAnnotator.classNameForScriptDescriptor((ScriptDescriptor) functionParent);
invokeOpcode = INVOKEVIRTUAL;
}
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.resolve.BindingContext;
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.Opcodes;
import org.objectweb.asm.Type;
@@ -38,6 +39,8 @@ import javax.inject.Inject;
*/
public class ScriptCodegen {
public static final JvmClassName SCRIPT_DEFAULT_CLASS_NAME = JvmClassName.byInternalName("Script");
public static final String LAST_EXPRESSION_VALUE_FIELD_NAME = "rv";
@NotNull
@@ -94,11 +97,13 @@ public class ScriptCodegen {
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,
Opcodes.V1_6,
Opcodes.ACC_PUBLIC,
"Script",
className.getInternalName(),
null,
JdkNames.JL_OBJECT.getInternalName(),
new String[0]);
@@ -130,10 +135,12 @@ public class ScriptCodegen {
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.load(0, Type.getObjectType("Script"));
instructionAdapter.load(0, className.getAsmType());
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());
if (stackValue.type != Type.VOID_TYPE) {
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);