From e1349698968174171b720a1d6f7a36c1b9f8439b Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Wed, 1 Aug 2012 09:58:01 +0300 Subject: [PATCH] making script classes useful/accessable for the rest of the world --- .../jet/codegen/GenerationState.java | 3 +- .../jetbrains/jet/codegen/ScriptCodegen.java | 40 +------ .../compiler/KotlinToJVMBytecodeCompiler.java | 3 +- .../lang/descriptors/ScriptDescriptor.java | 107 +++++++++++++++++- .../jet/lang/parsing/JetParsing.java | 6 +- .../jet/lang/resolve/DescriptorResolver.java | 2 +- .../jet/lang/resolve/ScriptBodyResolver.java | 2 +- .../lang/resolve/ScriptHeaderResolver.java | 28 ++--- .../jet/lang/resolve/ScriptNameUtil.java | 54 +++++++++ .../jet/lang/resolve/TopDownAnalyzer.java | 11 +- .../lang/resolve/TypeHierarchyResolver.java | 10 +- compiler/testData/codegen/script/fib.lang.kt | 2 +- .../testData/codegen/script/fibwp.lang.kt | 1 + .../codegen/script/fibwprunner.ktscript | 4 + .../testData/psi/script/ComplexScript.txt | 2 + compiler/testData/psi/script/Import.txt | 2 + compiler/testData/psi/script/Shebang.txt | 2 + .../testData/psi/script/ShebangIncorrect.txt | 2 + compiler/testData/psi/script/SimpleScript.txt | 2 + .../jet/codegen/CodegenTestCase.java | 3 +- .../jetbrains/jet/codegen/ScriptGenTest.java | 18 +++ 21 files changed, 229 insertions(+), 75 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptNameUtil.java create mode 100644 compiler/testData/codegen/script/fibwprunner.ktscript diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 40c6fd5c329..f970e41208a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.JvmClassName; +import org.jetbrains.jet.lang.resolve.ScriptNameUtil; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.utils.Progress; import org.jetbrains.asm4.commons.Method; @@ -143,7 +144,7 @@ public class GenerationState { public void compileCorrectFiles(@NotNull CompilationErrorHandler errorHandler) { for (JetFile file : this.files) { if (file.isScript()) { - String name = ScriptCodegen.classNameForScript(file); + String name = ScriptNameUtil.classNameForScript(file); injector.getClosureAnnotator().registerClassNameForScript(file.getScript(), JvmClassName.byInternalName(name)); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java index f17a599fafd..c0959ddd0a1 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java @@ -17,18 +17,15 @@ package org.jetbrains.jet.codegen; import com.google.common.collect.Lists; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.util.Pair; 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.parsing.JetParserDefinition; -import org.jetbrains.jet.lang.parsing.JetScriptDefinition; -import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.ScriptNameUtil; import org.jetbrains.jet.lang.resolve.java.JdkNames; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.asm4.MethodVisitor; @@ -37,7 +34,6 @@ import org.jetbrains.asm4.Type; import org.jetbrains.asm4.commons.InstructionAdapter; import javax.inject.Inject; -import java.io.File; import java.util.List; /** @@ -45,10 +41,6 @@ import java.util.List; */ 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 private GenerationState state; @NotNull @@ -99,7 +91,7 @@ public class ScriptCodegen { public void generate(JetScript scriptDeclaration) { - ScriptDescriptor scriptDescriptor = (ScriptDescriptor) state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration); + ScriptDescriptor scriptDescriptor = state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration); ClassDescriptor classDescriptorForScript = closureAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor); @@ -134,7 +126,7 @@ public class ScriptCodegen { Type blockType = jetTypeMapper.mapType(scriptDescriptor.getReturnType(), MapTypeMode.VALUE); - classBuilder.newField(null, Opcodes.ACC_PUBLIC, LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor(), null, null); + classBuilder.newField(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_FINAL, ScriptNameUtil.LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor(), null, null); JvmMethodSignature jvmSignature = jetTypeMapper.mapScriptSignature(scriptDescriptor, importedScripts); @@ -196,7 +188,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(className.getInternalName(), LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor()); + instructionAdapter.putfield(className.getInternalName(), ScriptNameUtil.LAST_EXPRESSION_VALUE_FIELD_NAME, blockType.getDescriptor()); } instructionAdapter.areturn(Type.VOID_TYPE); @@ -213,7 +205,7 @@ public class ScriptCodegen { for (ValueParameterDescriptor parameter : script.getValueParameters()) { Type parameterType = jetTypeMapper.mapType(parameter.getType(), MapTypeMode.VALUE); - int access = Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL; + int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL; classBuilder.newField(null, access, parameter.getName().getIdentifier(), parameterType.getDescriptor(), null, null); } } @@ -252,26 +244,4 @@ public class ScriptCodegen { public String getScriptFieldName(@NotNull ScriptDescriptor scriptDescriptor) { return "script$" + getScriptIndex(scriptDescriptor); } - - public static String classNameForScript(JetFile file) { - JetScriptDefinition scriptDefinition = JetScriptDefinitionProvider.getInstance(file.getProject()).findScriptDefinition(file); - - String name = file.getName(); - int index = name.lastIndexOf('/'); - if(index != -1) - name = name.substring(index+1); - if(name.endsWith(scriptDefinition.getExtension())) - name = name.substring(0, name.length()-scriptDefinition.getExtension().length()); - else { - index = name.indexOf('.'); - if(index != -1) - name = name.substring(0,index); - } - name = Character.toUpperCase(name.charAt(0)) + name.substring(1); - JetNamespaceHeader header = file.getNamespaceHeader(); - if(header != null && header.getName().length() > 0) { - name = header.getName().replace('.','/') + "/" + name; - } - return name; - } } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java index c4e66ec1f21..20556b7adfd 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java @@ -44,6 +44,7 @@ import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.JvmAbi; +import org.jetbrains.jet.lang.resolve.ScriptNameUtil; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.plugin.JetMainDetector; @@ -254,7 +255,7 @@ public class KotlinToJVMBytecodeCompiler { }, parentLoader == null ? AllModules.class.getClassLoader() : parentLoader)); JetFile scriptFile = environment.getSourceFiles().get(0); - return classLoader.loadClass(ScriptCodegen.classNameForScript(scriptFile)); + return classLoader.loadClass(ScriptNameUtil.classNameForScript(scriptFile)); } catch (Exception e) { throw new RuntimeException("Failed to evaluate script: " + e, e); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ScriptDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ScriptDescriptor.java index bbc88078e17..c65634add26 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ScriptDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ScriptDescriptor.java @@ -19,13 +19,28 @@ 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.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.DescriptorResolver; +import org.jetbrains.jet.lang.resolve.ScriptNameUtil; +import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; +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.ClassReceiver; 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.TypeProjection; import org.jetbrains.jet.lang.types.TypeSubstitutor; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; +import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; /** @@ -42,14 +57,75 @@ public class ScriptDescriptor extends DeclarationDescriptorNonRootImpl { private final ScriptCodeDescriptor scriptCodeDescriptor = new ScriptCodeDescriptor(this); private final ReceiverDescriptor implicitReceiver = new ScriptReceiver(this); - public ScriptDescriptor(@Nullable DeclarationDescriptor containingDeclaration, int priority) { + private ClassDescriptorImpl classDescriptor; + + private WritableScopeImpl classScope; + private ClassDescriptorImpl descriptor; + private ClassReceiver classReceiver; + + public ScriptDescriptor(@Nullable DeclarationDescriptor containingDeclaration, int priority, JetScript script, JetScope scriptScope) { super(containingDeclaration, Collections.emptyList(), NAME); this.priority = priority; + + String className = ScriptNameUtil.classNameForScript((JetFile) script.getContainingFile()).replace('/','.'); + + classDescriptor = new ClassDescriptorImpl( + containingDeclaration, + Collections.emptyList(), + Modality.FINAL, + new FqName(className).shortName()); + classScope = new WritableScopeImpl(scriptScope, containingDeclaration, RedeclarationHandler.DO_NOTHING, "script members"); + classScope.changeLockLevel(WritableScope.LockLevel.BOTH); + classDescriptor.initialize( + false, + Collections.emptyList(), + Collections.singletonList(JetStandardClasses.getAnyType()), + classScope, + new HashSet(), + null); + classReceiver = new ClassReceiver(classDescriptor); } - public void initialize(@NotNull JetType returnType) { + public void initialize(@NotNull JetType returnType, JetScript declaration, BindingContext bindingContext) { this.returnType = returnType; scriptCodeDescriptor.initialize(implicitReceiver, valueParameters, returnType); + + PropertyDescriptor propertyDescriptor = new PropertyDescriptor(classDescriptor, + Collections.emptyList(), + Modality.FINAL, + Visibilities.PUBLIC, + false, + false, + Name.identifier(ScriptNameUtil.LAST_EXPRESSION_VALUE_FIELD_NAME), + CallableMemberDescriptor.Kind.DECLARATION); + propertyDescriptor.setType(returnType, Collections.emptyList(), new ClassReceiver(classDescriptor), ReceiverDescriptor.NO_RECEIVER); + propertyDescriptor.initialize(null, null); + classScope.addPropertyDescriptor(propertyDescriptor); + + for (JetDeclaration jetDeclaration : declaration.getDeclarations()) { + if(jetDeclaration instanceof JetProperty) { + VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, jetDeclaration); + assert descriptor != null; + propertyDescriptor = new PropertyDescriptor(classDescriptor, + Collections.emptyList(), + Modality.FINAL, + propertyDescriptor.getVisibility(), + false, + false, + descriptor.getName(), + CallableMemberDescriptor.Kind.DECLARATION); + propertyDescriptor.setType(returnType, Collections.emptyList(), classReceiver, ReceiverDescriptor.NO_RECEIVER); + propertyDescriptor.initialize(null, null); + classScope.addPropertyDescriptor(propertyDescriptor); + } + else if(jetDeclaration instanceof JetNamedFunction) { + SimpleFunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, jetDeclaration); + assert descriptor != null; + SimpleFunctionDescriptor copy = + descriptor.copy(classDescriptor, descriptor.getModality(), false, CallableMemberDescriptor.Kind.DECLARATION, false); + classScope.addFunctionDescriptor(copy); + } + } } public int getPriority() { @@ -88,5 +164,32 @@ public class ScriptDescriptor extends DeclarationDescriptorNonRootImpl { public void setValueParameters(@NotNull List valueParameters) { this.valueParameters = valueParameters; + ConstructorDescriptorImpl constructorDescriptor = + new ConstructorDescriptorImpl(classDescriptor, Collections.emptyList(), true) + .initialize(Collections.emptyList(), valueParameters, Visibilities.PUBLIC); + constructorDescriptor.setReturnType(classDescriptor.getDefaultType()); + + classDescriptor.getConstructors().add(constructorDescriptor); + classDescriptor.setPrimaryConstructor(constructorDescriptor); + + for (ValueParameterDescriptor parameter : valueParameters) { + PropertyDescriptor propertyDescriptor = new PropertyDescriptor(classDescriptor, + Collections.emptyList(), + Modality.FINAL, + Visibilities.PUBLIC, + false, + false, + parameter.getName(), + CallableMemberDescriptor.Kind.DECLARATION); + propertyDescriptor.setType(parameter.getType(), Collections.emptyList(), classReceiver, ReceiverDescriptor.NO_RECEIVER); + //PropertyGetterDescriptor getter = DescriptorResolver.createDefaultGetter(propertyDescriptor); + //getter.initialize(propertyDescriptor.getType()); + propertyDescriptor.initialize(null, null); + classScope.addPropertyDescriptor(propertyDescriptor); + } + } + + public ClassDescriptor getClassDescriptor() { + return classDescriptor; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java index a121449cdca..c4c1f75402f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -108,6 +108,7 @@ public class JetParsing extends AbstractJetParsing { PsiBuilder.Marker fileMarker = mark(); PsiBuilder.Marker namespaceHeader = mark(); + PsiBuilder.Marker firstEntry = mark(); parseModifierList(MODIFIER_LIST, true); if (at(PACKAGE_KEYWORD)) { @@ -115,12 +116,13 @@ public class JetParsing extends AbstractJetParsing { parseNamespaceName(); + firstEntry.drop(); consumeIf(SEMICOLON); - namespaceHeader.done(NAMESPACE_HEADER); } else { - namespaceHeader.rollbackTo(); + firstEntry.rollbackTo(); } + namespaceHeader.done(NAMESPACE_HEADER); PsiBuilder.Marker scriptMarker = mark(); parseImportDirectives(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index cc397011765..4f3e312880c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -875,7 +875,7 @@ public class DescriptorResolver { return getterDescriptor; } - private PropertyGetterDescriptor createDefaultGetter(PropertyDescriptor propertyDescriptor) { + public static PropertyGetterDescriptor createDefaultGetter(PropertyDescriptor propertyDescriptor) { PropertyGetterDescriptor getterDescriptor; getterDescriptor = new PropertyGetterDescriptor( propertyDescriptor, Collections.emptyList(), propertyDescriptor.getModality(), diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java index 857150b7bc6..22bc5a3f9a5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java @@ -81,7 +81,7 @@ public class ScriptBodyResolver { if (returnType == null) { returnType = ErrorUtils.createErrorType("getBlockReturnedType returned null"); } - descriptor.initialize(returnType); + descriptor.initialize(returnType, declaration, trace.getBindingContext()); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptHeaderResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptHeaderResolver.java index 3bf48f0c777..105ef8f0e54 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptHeaderResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptHeaderResolver.java @@ -17,41 +17,27 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.util.Key; -import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.parsing.JetParserDefinition; import org.jetbrains.jet.lang.parsing.JetScriptDefinition; import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.psi.JetPsiUtil; +import org.jetbrains.jet.lang.psi.JetNamespaceHeader; import org.jetbrains.jet.lang.psi.JetScript; -import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.name.FqName; 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; import org.jetbrains.jet.lang.types.TypeUtils; -import org.jetbrains.jet.lang.types.expressions.CoercionStrategy; -import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext; -import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.ref.JetTypeName; import javax.inject.Inject; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; +import java.util.*; /** * @author Stepan Koltsov @@ -127,14 +113,17 @@ public class ScriptHeaderResolver { } public void processScriptHierarchy(@NotNull JetScript script, @NotNull JetScope outerScope) { - NamespaceDescriptorImpl ns = namespaceFactory.createNamespaceDescriptorPathIfNeeded(FqName.ROOT); + JetFile file = (JetFile) script.getContainingFile(); + JetNamespaceHeader namespaceHeader = file.getNamespaceHeader(); + FqName fqName = namespaceHeader != null ? new FqName(namespaceHeader.getQualifiedName()) : FqName.ROOT; + NamespaceDescriptorImpl ns = namespaceFactory.createNamespaceDescriptorPathIfNeeded(fqName); Integer priority = script.getUserData(PRIORITY_KEY); if (priority == null) { priority = 0; } - ScriptDescriptor scriptDescriptor = new ScriptDescriptor(ns, priority); + ScriptDescriptor scriptDescriptor = new ScriptDescriptor(ns, priority, script, outerScope); //WriteThroughScope scriptScope = new WriteThroughScope( // outerScope, ns.getMemberScope(), new TraceBasedRedeclarationHandler(trace)); WritableScopeImpl scriptScope = new WritableScopeImpl(outerScope, scriptDescriptor, RedeclarationHandler.DO_NOTHING, "script"); @@ -142,7 +131,10 @@ public class ScriptHeaderResolver { context.getScriptScopes().put(script, scriptScope); context.getScripts().put(script, scriptDescriptor); + trace.record(BindingContext.SCRIPT, script, scriptDescriptor); + + ((WritableScope)outerScope).addClassifierDescriptor(scriptDescriptor.getClassDescriptor()); } public void resolveScriptDeclarations() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptNameUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptNameUtil.java new file mode 100644 index 00000000000..fc2aa802139 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptNameUtil.java @@ -0,0 +1,54 @@ +/* + * 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; + +import org.jetbrains.jet.lang.parsing.JetScriptDefinition; +import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetNamespaceHeader; + +/** + * @author alex.tkachman + */ +public class ScriptNameUtil { + public static final String LAST_EXPRESSION_VALUE_FIELD_NAME = "rv"; + + private ScriptNameUtil() { + } + + public static String classNameForScript(JetFile file) { + JetScriptDefinition scriptDefinition = JetScriptDefinitionProvider.getInstance(file.getProject()).findScriptDefinition(file); + + String name = file.getName(); + int index = name.lastIndexOf('/'); + if(index != -1) + name = name.substring(index+1); + if(name.endsWith(scriptDefinition.getExtension())) + name = name.substring(0, name.length()-scriptDefinition.getExtension().length()); + else { + index = name.indexOf('.'); + if(index != -1) + name = name.substring(0,index); + } + name = Character.toUpperCase(name.charAt(0)) + (name.length() == 0 ? "" : name.substring(1)); + JetNamespaceHeader header = file.getNamespaceHeader(); + if(header != null && header.getName().length() > 0) { + name = header.getName().replace('.','/') + "/" + name; + } + return name; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 06ea8ed9af9..f188bc41dfb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -35,10 +35,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import javax.inject.Inject; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; /** * @author abreslav @@ -156,8 +153,10 @@ public class TopDownAnalyzer { for (MutableClassDescriptor mutableClassDescriptor : context.getObjects().values()) { mutableClassDescriptor.lockScopes(); } - for (WritableScope namespaceScope : context.getNamespaceScopes().values()) { - namespaceScope.changeLockLevel(WritableScope.LockLevel.READING); + for (Map.Entry namespaceScope : context.getNamespaceScopes().entrySet()) { + // todo: this is hack in favor of REPL + if(!namespaceScope.getKey().isScript()) + namespaceScope.getValue().changeLockLevel(WritableScope.LockLevel.READING); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 764085363b3..566fb301940 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -193,12 +193,6 @@ public class TypeHierarchyResolver { declaration.accept(new JetVisitorVoid() { @Override public void visitJetFile(JetFile file) { - if (file.isScript()) { - JetScript script = file.getScript(); - scriptHeaderResolver.processScriptHierarchy(script, outerScope); - return; - } - NamespaceDescriptorImpl namespaceDescriptor = namespaceFactory.createNamespaceDescriptorPathIfNeeded( file, outerScope, RedeclarationHandler.DO_NOTHING); context.getNamespaceDescriptors().put(file, namespaceDescriptor); @@ -208,6 +202,10 @@ public class TypeHierarchyResolver { namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH); context.getNamespaceScopes().put(file, namespaceScope); + if(file.isScript()) { + scriptHeaderResolver.processScriptHierarchy(file.getScript(), namespaceScope); + } + prepareForDeferredCall(namespaceScope, namespaceDescriptor, file); } diff --git a/compiler/testData/codegen/script/fib.lang.kt b/compiler/testData/codegen/script/fib.lang.kt index fe7143e7cb2..bfcca90b6a3 100644 --- a/compiler/testData/codegen/script/fib.lang.kt +++ b/compiler/testData/codegen/script/fib.lang.kt @@ -5,4 +5,4 @@ fun fib(n: Int): Int { return v } -val result = fib(num) +public val result = fib(num) diff --git a/compiler/testData/codegen/script/fibwp.lang.kt b/compiler/testData/codegen/script/fibwp.lang.kt index 876bbdade33..5b0d322f7a0 100644 --- a/compiler/testData/codegen/script/fibwp.lang.kt +++ b/compiler/testData/codegen/script/fibwp.lang.kt @@ -8,3 +8,4 @@ fun fib(n: Int): Int { } val result = fib(num) +12 \ No newline at end of file diff --git a/compiler/testData/codegen/script/fibwprunner.ktscript b/compiler/testData/codegen/script/fibwprunner.ktscript new file mode 100644 index 00000000000..58edd67826a --- /dev/null +++ b/compiler/testData/codegen/script/fibwprunner.ktscript @@ -0,0 +1,4 @@ +val fibwp = test.Fibwp(5) +val callResult = fibwp.fib(4) +val result = fibwp.num + fibwp.result - 5 +fibwp.rv \ No newline at end of file diff --git a/compiler/testData/psi/script/ComplexScript.txt b/compiler/testData/psi/script/ComplexScript.txt index db57fad6c3b..eeebb6aaa8f 100644 --- a/compiler/testData/psi/script/ComplexScript.txt +++ b/compiler/testData/psi/script/ComplexScript.txt @@ -1,4 +1,6 @@ JetFile: ComplexScript.ktscript + NAMESPACE_HEADER + SCRIPT BLOCK FUN diff --git a/compiler/testData/psi/script/Import.txt b/compiler/testData/psi/script/Import.txt index 643b93e28a1..5be89deca9e 100644 --- a/compiler/testData/psi/script/Import.txt +++ b/compiler/testData/psi/script/Import.txt @@ -1,4 +1,6 @@ JetFile: Import.ktscript + NAMESPACE_HEADER + SCRIPT IMPORT_DIRECTIVE PsiElement(import)('import') diff --git a/compiler/testData/psi/script/Shebang.txt b/compiler/testData/psi/script/Shebang.txt index 8b8111c20af..5dcb4f97483 100644 --- a/compiler/testData/psi/script/Shebang.txt +++ b/compiler/testData/psi/script/Shebang.txt @@ -1,6 +1,8 @@ JetFile: Shebang.ktscript PsiComment(SHEBANG_COMMENT)('#!/usr/bin/env kotlin') PsiWhiteSpace('\n\n') + NAMESPACE_HEADER + SCRIPT BLOCK CALL_EXPRESSION diff --git a/compiler/testData/psi/script/ShebangIncorrect.txt b/compiler/testData/psi/script/ShebangIncorrect.txt index 92f20e35c02..377bfa36822 100644 --- a/compiler/testData/psi/script/ShebangIncorrect.txt +++ b/compiler/testData/psi/script/ShebangIncorrect.txt @@ -1,4 +1,6 @@ JetFile: ShebangIncorrect.ktscript + NAMESPACE_HEADER + SCRIPT BLOCK CALL_EXPRESSION diff --git a/compiler/testData/psi/script/SimpleScript.txt b/compiler/testData/psi/script/SimpleScript.txt index e0da35b59c3..49ccaa2aa37 100644 --- a/compiler/testData/psi/script/SimpleScript.txt +++ b/compiler/testData/psi/script/SimpleScript.txt @@ -1,4 +1,6 @@ JetFile: SimpleScript.ktscript + NAMESPACE_HEADER + SCRIPT BLOCK CALL_EXPRESSION diff --git a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java index 87d6e4fc171..85976f5f41c 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java +++ b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java @@ -27,6 +27,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys; import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode; +import org.jetbrains.jet.lang.resolve.ScriptNameUtil; import org.jetbrains.jet.utils.ExceptionUtils; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.analyzer.AnalyzeExhaust; @@ -188,7 +189,7 @@ public abstract class CodegenTestCase extends UsefulTestCase { try { if (myFiles.isScript()) { - String scriptClassName = ScriptCodegen.classNameForScript(myFiles.getPsiFile()); + String scriptClassName = ScriptNameUtil.classNameForScript(myFiles.getPsiFile()); Class scriptClass = loader.loadClass(scriptClassName); Constructor constructor = getConstructor(scriptClass, state.getScriptConstructorMethod()); diff --git a/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java index 2fc04d1cf0c..6579791524b 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ScriptGenTest.java @@ -127,4 +127,22 @@ public class ScriptGenTest extends CodegenTestCase { throw new RuntimeException(e); } } + + public void testDependentScripts() { + JetScriptDefinitionProvider.getInstance(myEnvironment.getProject()).addScriptDefinition(FIB_SCRIPT_DEFINITION); + loadFiles("script/fibwp.lang.kt", "script/fibwprunner.ktscript"); + System.out.println(generateToText()); + final Class aClass = loadClass("Fibwprunner", generateClassesInFile()); + try { + Constructor constructor = aClass.getConstructor(); + Field result = aClass.getField("result"); + Field rv = aClass.getField("rv"); + Object script = constructor.newInstance(); + assertEquals(12,rv.get(script)); + assertEquals(8,result.get(script)); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } }