script: make top level declarations class members
This commit is contained in:
@@ -42,7 +42,7 @@ 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<FunctionDescriptor, ClassDescriptorImpl> classesForFunctions = new HashMap<FunctionDescriptor, ClassDescriptorImpl>();
|
||||
private final Map<DeclarationDescriptor, ClassDescriptorImpl> classesForFunctions = new HashMap<DeclarationDescriptor, ClassDescriptorImpl>();
|
||||
private final Map<DeclarationDescriptor,ClassDescriptor> enclosing = new HashMap<DeclarationDescriptor, ClassDescriptor>();
|
||||
|
||||
private final MultiMap<FqName, JetFile> namespaceName2Files = MultiMap.create();
|
||||
@@ -86,6 +86,27 @@ public class ClosureAnnotator {
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
private void mapFilesToNamespaces(Collection<JetFile> files) {
|
||||
for (JetFile file : files) {
|
||||
if (file.isScript()) {
|
||||
|
||||
@@ -129,8 +129,8 @@ public abstract class CodegenContext {
|
||||
return new CodegenContexts.ConstructorContext(descriptor, getContextKind(), this, typeMapper);
|
||||
}
|
||||
|
||||
public CodegenContext intoScript(ScriptDescriptor script) {
|
||||
return new CodegenContexts.ScriptContext(script, OwnerKind.IMPLEMENTATION, this, closure);
|
||||
public CodegenContext intoScript(@NotNull ScriptDescriptor script, @NotNull ClassDescriptor classDescriptor) {
|
||||
return new CodegenContexts.ScriptContext(classDescriptor, OwnerKind.IMPLEMENTATION, this, closure);
|
||||
}
|
||||
|
||||
public CodegenContexts.ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, JvmClassName internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) {
|
||||
|
||||
@@ -165,22 +165,27 @@ public class CodegenContexts {
|
||||
|
||||
public static class ScriptContext extends CodegenContext {
|
||||
|
||||
@NotNull
|
||||
private final ClassDescriptor classDescriptor;
|
||||
|
||||
public ScriptContext(
|
||||
@NotNull DeclarationDescriptor contextDescriptor,
|
||||
@NotNull ClassDescriptor contextDescriptor,
|
||||
@NotNull OwnerKind contextKind,
|
||||
@Nullable CodegenContext parentContext,
|
||||
@Nullable ObjectOrClosureCodegen closureCodegen) {
|
||||
super(contextDescriptor, contextKind, parentContext, closureCodegen);
|
||||
|
||||
this.classDescriptor = contextDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassDescriptor getThisDescriptor() {
|
||||
return null;
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
throw new IllegalStateException();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
@@ -741,6 +742,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
@Override
|
||||
public StackValue visitNamedFunction(JetNamedFunction function, StackValue data) {
|
||||
assert data == StackValue.none();
|
||||
|
||||
if (function.isScriptDeclaration()) {
|
||||
return StackValue.none();
|
||||
}
|
||||
|
||||
StackValue closure = genClosure(function);
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
|
||||
int index = myFrameMap.getIndex(descriptor);
|
||||
@@ -844,7 +850,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.mark(blockStart);
|
||||
|
||||
for (JetElement statement : statements) {
|
||||
if (statement instanceof JetNamedDeclaration) {
|
||||
JetNamedDeclaration declaration = (JetNamedDeclaration) statement;
|
||||
if (declaration.isScriptDeclaration()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (statement instanceof JetProperty) {
|
||||
JetProperty property = (JetProperty) statement;
|
||||
final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, statement);
|
||||
assert variableDescriptor != null;
|
||||
|
||||
@@ -877,6 +891,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
v.mark(blockEnd);
|
||||
|
||||
for (JetElement statement : Lists.reverse(statements)) {
|
||||
if (statement instanceof JetNamedDeclaration) {
|
||||
JetNamedDeclaration declaration = (JetNamedDeclaration) statement;
|
||||
if (declaration.isScriptDeclaration()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(statement instanceof JetNamedFunction) {
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, statement);
|
||||
myFrameMap.leave(descriptor);
|
||||
@@ -884,6 +905,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
if (statement instanceof JetProperty) {
|
||||
JetProperty var = (JetProperty) statement;
|
||||
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var);
|
||||
assert variableDescriptor != null;
|
||||
|
||||
@@ -1367,8 +1389,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
private boolean isCallAsFunctionObject(FunctionDescriptor fd) {
|
||||
return fd instanceof ExpressionAsFunctionDescriptor
|
||||
|| (fd instanceof SimpleFunctionDescriptor && (fd.getContainingDeclaration() instanceof FunctionDescriptor || fd.getContainingDeclaration() instanceof ScriptDescriptor));
|
||||
if (fd.getContainingDeclaration() instanceof ScriptDescriptor) {
|
||||
JetNamedFunction psi = (JetNamedFunction) BindingContextUtils.descriptorToDeclaration(bindingContext, fd);
|
||||
return !psi.isScriptDeclaration();
|
||||
}
|
||||
else if (fd instanceof ExpressionAsFunctionDescriptor) {
|
||||
return true;
|
||||
}
|
||||
else if (fd instanceof SimpleFunctionDescriptor && (fd.getContainingDeclaration() instanceof FunctionDescriptor || fd.getContainingDeclaration() instanceof ScriptDescriptor)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) {
|
||||
@@ -1421,6 +1454,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if(type != null)
|
||||
StackValue.onStack(exprType).put(type, v);
|
||||
}
|
||||
else if (descriptor instanceof ScriptReceiver) {
|
||||
ScriptReceiver scriptReceiver = (ScriptReceiver) descriptor;
|
||||
ScriptDescriptor script = (ScriptDescriptor) scriptReceiver.getDeclarationDescriptor();
|
||||
ClassDescriptor classDescriptorForScript = state.getInjector().getClosureAnnotator().classDescriptorForScrpitDescriptor(script);
|
||||
generateThisOrOuter(classDescriptorForScript);
|
||||
}
|
||||
else if(descriptor instanceof ExtensionReceiver) {
|
||||
Type exprType = asmType(descriptor.getType());
|
||||
ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor;
|
||||
@@ -2283,17 +2322,30 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
@Override
|
||||
public StackValue visitProperty(JetProperty property, StackValue receiver) {
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, property);
|
||||
int index = lookupLocal(variableDescriptor);
|
||||
|
||||
if (index < 0) {
|
||||
throw new IllegalStateException("Local variable not found for " + variableDescriptor);
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, property);
|
||||
|
||||
Type sharedVarType = null;
|
||||
int index = -1;
|
||||
|
||||
if (property.isScriptDeclaration()) {
|
||||
StackValue field = StackValue.field(typeMapper.mapType(variableDescriptor.getType(), MapTypeMode.VALUE), JvmClassName.byInternalName("Script"), property.getName(), false);
|
||||
return StackValue.none();
|
||||
}
|
||||
else {
|
||||
index = lookupLocal(variableDescriptor);
|
||||
|
||||
if (index < 0) {
|
||||
throw new IllegalStateException("Local variable not found for " + variableDescriptor);
|
||||
}
|
||||
|
||||
sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
|
||||
assert variableDescriptor != null;
|
||||
|
||||
}
|
||||
|
||||
final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
|
||||
assert variableDescriptor != null;
|
||||
Type varType = asmType(variableDescriptor.getType());
|
||||
if(sharedVarType != null) {
|
||||
if (sharedVarType != null) {
|
||||
v.anew(sharedVarType);
|
||||
v.dup();
|
||||
v.invokespecial(sharedVarType.getInternalName(), "<init>", "()V");
|
||||
@@ -2302,7 +2354,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
JetExpression initializer = property.getInitializer();
|
||||
if (initializer != null) {
|
||||
if(sharedVarType == null) {
|
||||
if (property.isScriptDeclaration()) {
|
||||
gen(initializer, varType);
|
||||
v.putfield("Script", property.getName(), varType.getDescriptor());
|
||||
}
|
||||
else if (sharedVarType == null) {
|
||||
gen(initializer, varType);
|
||||
v.store(index, varType);
|
||||
}
|
||||
|
||||
@@ -699,7 +699,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
curParam++;
|
||||
}
|
||||
|
||||
generateInitializers(codegen, iv);
|
||||
generateInitializers(codegen, iv, myClass.getDeclarations(), bindingContext, typeMapper);
|
||||
|
||||
generateTraitMethods(codegen);
|
||||
|
||||
@@ -915,8 +915,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
|
||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||
public static void generateInitializers(@NotNull ExpressionCodegen codegen, @NotNull InstructionAdapter iv, @NotNull List<JetDeclaration> declarations,
|
||||
@NotNull BindingContext bindingContext, @NotNull JetTypeMapper typeMapper) {
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, declaration);
|
||||
if (bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||
|
||||
@@ -167,6 +167,9 @@ public class JetTypeMapper {
|
||||
}
|
||||
return JvmClassName.byType(asmType);
|
||||
}
|
||||
else if (containingDeclaration instanceof ScriptDescriptor) {
|
||||
return JvmClassName.byInternalName("Script");
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration);
|
||||
}
|
||||
@@ -578,6 +581,10 @@ public class JetTypeMapper {
|
||||
invokeOpcode = INVOKESPECIAL;
|
||||
thisClass = null;
|
||||
}
|
||||
else if (functionParent instanceof ScriptDescriptor) {
|
||||
thisClass = owner = ownerForDefaultParam = ownerForDefaultImpl = JvmClassName.byInternalName("Script");
|
||||
invokeOpcode = INVOKEVIRTUAL;
|
||||
}
|
||||
else if (functionParent instanceof ClassDescriptor) {
|
||||
|
||||
FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
|
||||
|
||||
@@ -18,9 +18,12 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
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.objectweb.asm.MethodVisitor;
|
||||
@@ -43,6 +46,12 @@ public class ScriptCodegen {
|
||||
private ClassFileFactory classFileFactory;
|
||||
@NotNull
|
||||
private JetTypeMapper jetTypeMapper;
|
||||
@NotNull
|
||||
private MemberCodegen memberCodegen;
|
||||
@NotNull
|
||||
private ClosureAnnotator closureAnnotator;
|
||||
@NotNull
|
||||
private BindingContext bindingContext;
|
||||
|
||||
|
||||
@Inject
|
||||
@@ -60,13 +69,30 @@ public class ScriptCodegen {
|
||||
this.jetTypeMapper = jetTypeMapper;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setMemberCodegen(@NotNull MemberCodegen memberCodegen) {
|
||||
this.memberCodegen = memberCodegen;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setClosureAnnotator(@NotNull ClosureAnnotator closureAnnotator) {
|
||||
this.closureAnnotator = closureAnnotator;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setBindingContext(@NotNull BindingContext bindingContext) {
|
||||
this.bindingContext = bindingContext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void generate(JetScript scriptDeclaration) {
|
||||
|
||||
ScriptDescriptor scriptDescriptor = (ScriptDescriptor) state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration);
|
||||
|
||||
CodegenContext context = CodegenContexts.STATIC.intoScript(scriptDescriptor);
|
||||
ClassDescriptor classDescriptorForScript = closureAnnotator.classDescriptorForScrpitDescriptor(scriptDescriptor);
|
||||
|
||||
CodegenContexts.ScriptContext context = (CodegenContexts.ScriptContext) CodegenContexts.STATIC.intoScript(scriptDescriptor, classDescriptorForScript);
|
||||
|
||||
ClassBuilder classBuilder = classFileFactory.newVisitor("Script.class");
|
||||
classBuilder.defineClass(scriptDeclaration,
|
||||
@@ -77,13 +103,17 @@ public class ScriptCodegen {
|
||||
JdkNames.JL_OBJECT.getInternalName(),
|
||||
new String[0]);
|
||||
|
||||
genConstructor(scriptDeclaration, scriptDescriptor, classBuilder, context);
|
||||
genMembers(scriptDeclaration, context, classBuilder);
|
||||
genConstructor(scriptDeclaration, scriptDescriptor, classDescriptorForScript, classBuilder, context.intoFunction(scriptDescriptor.getScriptCodeDescriptor()));
|
||||
|
||||
classBuilder.done();
|
||||
}
|
||||
|
||||
private void genConstructor(
|
||||
@NotNull JetScript scriptDeclaration, @NotNull ScriptDescriptor scriptDescriptor,
|
||||
@NotNull ClassBuilder classBuilder, @NotNull CodegenContext outerContext) {
|
||||
@NotNull JetScript scriptDeclaration,
|
||||
@NotNull ScriptDescriptor scriptDescriptor,
|
||||
@NotNull ClassDescriptor classDescriptorForScript,
|
||||
@NotNull ClassBuilder classBuilder, @NotNull CodegenContext context) {
|
||||
|
||||
Type blockType = jetTypeMapper.mapType(scriptDescriptor.getReturnType(), MapTypeMode.VALUE);
|
||||
|
||||
@@ -105,8 +135,6 @@ public class ScriptCodegen {
|
||||
|
||||
instructionAdapter.load(0, Type.getObjectType("Script"));
|
||||
|
||||
CodegenContext context = outerContext.intoScript(scriptDescriptor);
|
||||
|
||||
FrameMap frameMap = context.prepareFrame(jetTypeMapper);
|
||||
|
||||
Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes();
|
||||
@@ -117,6 +145,12 @@ public class ScriptCodegen {
|
||||
frameMap.enter(parameter, argTypes[i+add].getSize());
|
||||
}
|
||||
|
||||
ImplementationBodyCodegen.generateInitializers(
|
||||
new ExpressionCodegen(instructionAdapter, frameMap, Type.VOID_TYPE, context, state),
|
||||
instructionAdapter,
|
||||
scriptDeclaration.getDeclarations(),
|
||||
bindingContext,
|
||||
jetTypeMapper);
|
||||
|
||||
StackValue stackValue = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state).gen(scriptDeclaration.getBlockExpression());
|
||||
if (stackValue.type != Type.VOID_TYPE) {
|
||||
@@ -128,4 +162,10 @@ public class ScriptCodegen {
|
||||
mv.visitMaxs(-1, -1);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void genMembers(@NotNull JetScript scriptDeclaration, @NotNull CodegenContext context, @NotNull ClassBuilder classBuilder) {
|
||||
for (JetDeclaration decl : scriptDeclaration.getDeclarations()) {
|
||||
memberCodegen.generateFunctionOrProperty((JetTypeParameterListOwner) decl, context, classBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,8 +99,11 @@ public class InjectorForJvmCodegen {
|
||||
this.classCodegen.setJetTypeMapper(jetTypeMapper);
|
||||
this.classCodegen.setState(generationState);
|
||||
|
||||
this.scriptCodegen.setBindingContext(bindingContext);
|
||||
this.scriptCodegen.setClassFileFactory(classFileFactory);
|
||||
this.scriptCodegen.setClosureAnnotator(closureAnnotator);
|
||||
this.scriptCodegen.setJetTypeMapper(jetTypeMapper);
|
||||
this.scriptCodegen.setMemberCodegen(memberCodegen);
|
||||
this.scriptCodegen.setState(generationState);
|
||||
|
||||
this.intrinsics.setMyProject(project);
|
||||
@@ -111,8 +114,8 @@ public class InjectorForJvmCodegen {
|
||||
|
||||
this.memberCodegen.setState(generationState);
|
||||
|
||||
closureAnnotator.setBindingContext(bindingContext);
|
||||
closureAnnotator.setFiles(listOfJetFile);
|
||||
this.closureAnnotator.setBindingContext(bindingContext);
|
||||
this.closureAnnotator.setFiles(listOfJetFile);
|
||||
|
||||
jetTypeMapper.init();
|
||||
|
||||
@@ -158,4 +161,8 @@ public class InjectorForJvmCodegen {
|
||||
return this.memberCodegen;
|
||||
}
|
||||
|
||||
public ClosureAnnotator getClosureAnnotator() {
|
||||
return this.closureAnnotator;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
@@ -32,6 +36,13 @@ public class ScriptCodeDescriptor extends FunctionDescriptorImpl {
|
||||
setVisibility(Visibilities.LOCAL);
|
||||
}
|
||||
|
||||
public void initialize(
|
||||
@NotNull ReceiverDescriptor expectedThisObject,
|
||||
@NotNull List<ValueParameterDescriptor> valueParameters,
|
||||
@NotNull JetType returnType) {
|
||||
super.initialize(null, expectedThisObject, Collections.<TypeParameterDescriptor>emptyList(), valueParameters, returnType, Modality.FINAL, Visibilities.LOCAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal, Kind kind) {
|
||||
throw new IllegalStateException("no need to copy script code descriptor");
|
||||
|
||||
@@ -20,6 +20,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
|
||||
@@ -36,6 +38,7 @@ public class ScriptDescriptor extends DeclarationDescriptorImpl {
|
||||
private List<ValueParameterDescriptor> valueParameters;
|
||||
|
||||
private final ScriptCodeDescriptor scriptCodeDescriptor = new ScriptCodeDescriptor(this);
|
||||
private final ReceiverDescriptor implicitReceiver = new ScriptReceiver(this);
|
||||
|
||||
public ScriptDescriptor(@Nullable DeclarationDescriptor containingDeclaration) {
|
||||
super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), NAME);
|
||||
@@ -44,6 +47,7 @@ public class ScriptDescriptor extends DeclarationDescriptorImpl {
|
||||
public void initialize(@NotNull JetType returnType, @NotNull List<ValueParameterDescriptor> valueParameters) {
|
||||
this.returnType = returnType;
|
||||
this.valueParameters = valueParameters;
|
||||
scriptCodeDescriptor.initialize(implicitReceiver, valueParameters, returnType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -61,6 +65,11 @@ public class ScriptDescriptor extends DeclarationDescriptorImpl {
|
||||
return scriptCodeDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ReceiverDescriptor getImplicitReceiver() {
|
||||
return implicitReceiver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeclarationDescriptor substitute(TypeSubstitutor substitutor) {
|
||||
throw new IllegalStateException("nothing to substitute in script");
|
||||
|
||||
@@ -71,4 +71,8 @@ public abstract class JetNamedDeclaration extends JetDeclaration implements PsiN
|
||||
PsiElement identifier = getNameIdentifier();
|
||||
return identifier != null ? identifier.getTextRange().getStartOffset() : getTextRange().getStartOffset();
|
||||
}
|
||||
|
||||
public boolean isScriptDeclaration() {
|
||||
return getParent() != null && getParent().getParent() instanceof JetScript;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,11 @@ public class JetScript extends JetDeclaration {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, JetImportDirective.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetDeclaration> getDeclarations() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(getBlockExpression(), JetDeclaration.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull JetVisitorVoid visitor) {
|
||||
visitor.visitScript(this);
|
||||
|
||||
@@ -489,11 +489,32 @@ public class DescriptorResolver {
|
||||
|
||||
@NotNull
|
||||
public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, JetScope scope, JetProperty property, DataFlowInfo dataFlowInfo, BindingTrace trace) {
|
||||
VariableDescriptorImpl variableDescriptor = resolveLocalVariableDescriptorWithType(containingDeclaration, property, null, trace);
|
||||
if (property.isScriptDeclaration()) {
|
||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
|
||||
containingDeclaration,
|
||||
annotationResolver.createAnnotationStubs(property.getModifierList(), trace),
|
||||
Modality.FINAL,
|
||||
Visibilities.INTERNAL,
|
||||
property.isVar(),
|
||||
false,
|
||||
JetPsiUtil.safeName(property.getName()),
|
||||
CallableMemberDescriptor.Kind.DECLARATION
|
||||
);
|
||||
|
||||
JetType type = getVariableType(scope, property, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
|
||||
variableDescriptor.setOutType(type);
|
||||
return variableDescriptor;
|
||||
JetType type = getVariableType(scope, property, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
|
||||
|
||||
propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(), scope.getImplicitReceiver(), (JetType) null);
|
||||
trace.record(BindingContext.VARIABLE, property, propertyDescriptor);
|
||||
return propertyDescriptor;
|
||||
|
||||
}
|
||||
else {
|
||||
VariableDescriptorImpl variableDescriptor = resolveLocalVariableDescriptorWithType(containingDeclaration, property, null, trace);
|
||||
|
||||
JetType type = getVariableType(scope, property, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
|
||||
variableDescriptor.setOutType(type);
|
||||
return variableDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -108,6 +108,10 @@ public class DescriptorUtils {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||
return classDescriptor.getImplicitReceiver();
|
||||
}
|
||||
else if (containingDeclaration instanceof ScriptDescriptor) {
|
||||
ScriptDescriptor scriptDescriptor = (ScriptDescriptor) containingDeclaration;
|
||||
return scriptDescriptor.getImplicitReceiver();
|
||||
}
|
||||
return NO_RECEIVER;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver;
|
||||
import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
@@ -155,6 +156,8 @@ public class ScriptResolver {
|
||||
|
||||
List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
|
||||
|
||||
scope.setImplicitReceiver(descriptor.getImplicitReceiver());
|
||||
|
||||
int index = 0;
|
||||
for (AnalyzerScriptParameter scriptParameter : topDownAnalysisParameters.getScriptParameters()) {
|
||||
ValueParameterDescriptor parameter = resolveScriptParameter(scriptParameter, index, descriptor);
|
||||
|
||||
+5
@@ -61,6 +61,11 @@ public class AutoCastUtils {
|
||||
return castThis(dataFlowInfo, receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ReceiverDescriptor> visitScriptReceiver(ScriptReceiver receiver, Object data) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ReceiverDescriptor> visitExpressionReceiver(ExpressionReceiver receiver, Object data) {
|
||||
// JetExpression expression = receiver.getExpression();
|
||||
|
||||
+4
@@ -39,4 +39,8 @@ public class ReceiverDescriptorVisitor<R, D> {
|
||||
public R visitClassReceiver(ClassReceiver receiver, D data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public R visitScriptReceiver(ScriptReceiver receiver, D data) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.scopes.receivers;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public class ScriptReceiver implements ThisReceiverDescriptor {
|
||||
|
||||
@NotNull
|
||||
private final ScriptDescriptor scriptDescriptor;
|
||||
|
||||
public ScriptReceiver(@NotNull ScriptDescriptor scriptDescriptor) {
|
||||
this.scriptDescriptor = scriptDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DeclarationDescriptor getDeclarationDescriptor() {
|
||||
return scriptDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getType() {
|
||||
// not sure
|
||||
return JetStandardClasses.getAnyType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitScriptReceiver(this, data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
val x = 12
|
||||
|
||||
// expected: x: 12
|
||||
@@ -18,6 +18,8 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
@@ -37,9 +39,11 @@ public class ScriptGenTest extends CodegenTestCase {
|
||||
blackBoxFile("script/string.ktscript");
|
||||
}
|
||||
|
||||
public void testTopLevelFunction() {
|
||||
public void testTopLevelFunction() throws Exception {
|
||||
blackBoxFile("script/topLevelFunction.ktscript");
|
||||
// TODO: check function is visible as instance field (it is currently not)
|
||||
Method method = scriptInstance.getClass().getMethod("factorial", new Class<?>[]{ int.class });
|
||||
Object r = method.invoke(scriptInstance, 4);
|
||||
assertEquals(24, r);
|
||||
}
|
||||
|
||||
public void testTopLevelFunctionClosure() {
|
||||
@@ -58,6 +62,10 @@ public class ScriptGenTest extends CodegenTestCase {
|
||||
blackBoxFile("script/secondLevelVal.ktscript");
|
||||
}
|
||||
|
||||
public void testTopLevelProperty() {
|
||||
blackBoxFile("script/topLevelProperty.ktscript");
|
||||
}
|
||||
|
||||
public void testScriptParameter() {
|
||||
blackBoxFile("script/parameter.ktscript");
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ public class AllInjectorsGenerator {
|
||||
generator.addField(true, IntrinsicMethods.class, "intrinsics", null);
|
||||
generator.addPublicField(ClassFileFactory.class);
|
||||
generator.addPublicField(MemberCodegen.class);
|
||||
generator.addPublicField(ClosureAnnotator.class);
|
||||
generator.generate("compiler/backend/src", "org.jetbrains.jet.di", "InjectorForJvmCodegen");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user