From e12b5740103eae1252f4376f3dcf3a93288c3559 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Sat, 1 Oct 2011 10:55:13 +0200 Subject: [PATCH 01/10] ifBlock test --- idea/testData/codegen/controlStructures/ifBlock.jet | 0 .../jetbrains/jet/codegen/ControlStructuresTest.java | 10 ++++++++++ 2 files changed, 10 insertions(+) create mode 100644 idea/testData/codegen/controlStructures/ifBlock.jet diff --git a/idea/testData/codegen/controlStructures/ifBlock.jet b/idea/testData/codegen/controlStructures/ifBlock.jet new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java b/idea/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java index 3f154a44c31..37240187769 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java @@ -84,6 +84,16 @@ public class ControlStructuresTest extends CodegenTestCase { assertEquals("IntelliJ IDEA", main.invoke(null, args)); } + public void testIfBlock() throws Exception { + loadFile(); + System.out.println(generateToText()); + final Method main = generateFunction(); + List args = Arrays.asList("IntelliJ", " ", "IDEA"); + assertEquals("TTT", main.invoke(null, args)); + args = Arrays.asList("JetBrains"); + assertEquals("F", main.invoke(null, args)); + } + public void testForInArray() throws Exception { loadFile(); System.out.println(generateToText()); From a2f510932c2132f6d8092be9d88a69047c8ea0d5 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Sat, 1 Oct 2011 10:56:24 +0200 Subject: [PATCH 02/10] testdata --- idea/testData/codegen/controlStructures/ifBlock.jet | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/idea/testData/codegen/controlStructures/ifBlock.jet b/idea/testData/codegen/controlStructures/ifBlock.jet index e69de29bb2d..4905fb2efc6 100644 --- a/idea/testData/codegen/controlStructures/ifBlock.jet +++ b/idea/testData/codegen/controlStructures/ifBlock.jet @@ -0,0 +1,10 @@ +import java.util.* + +fun concat(l: List): String? { + val sb = StringBuilder() + for(s in l) { + val x = if(l.size() > 1) { "T" } else { "F" }; + sb.append(x) + } + return sb.toString() +} From b3783e37c873578bfd70122e9e3ea916fdda2d45 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Sat, 1 Oct 2011 11:26:00 +0200 Subject: [PATCH 03/10] JetLiteFixture uses CoreEnvironment instead of code copy-pasted from IDEA lite fixture --- .../org/jetbrains/jet/JetLiteFixture.java | 122 +++--------------- 1 file changed, 19 insertions(+), 103 deletions(-) diff --git a/idea/tests/org/jetbrains/jet/JetLiteFixture.java b/idea/tests/org/jetbrains/jet/JetLiteFixture.java index a2142bee57c..36ac21bd281 100644 --- a/idea/tests/org/jetbrains/jet/JetLiteFixture.java +++ b/idea/tests/org/jetbrains/jet/JetLiteFixture.java @@ -1,45 +1,23 @@ package org.jetbrains.jet; -import com.intellij.ide.startup.impl.StartupManagerImpl; -import com.intellij.lang.*; -import com.intellij.lang.impl.PsiBuilderFactoryImpl; -import com.intellij.mock.*; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; +import com.intellij.core.CoreEnvironment; +import com.intellij.lang.Language; import com.intellij.openapi.fileEditor.impl.LoadTextUtil; -import com.intellij.openapi.fileTypes.FileTypeFactory; -import com.intellij.openapi.fileTypes.FileTypeManager; -import com.intellij.openapi.options.SchemesManagerFactory; -import com.intellij.openapi.progress.impl.ProgressManagerImpl; -import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.psi.*; -import com.intellij.psi.impl.PsiCachedValuesFactory; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; import com.intellij.psi.impl.PsiFileFactoryImpl; -import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; -import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl; -import com.intellij.psi.util.CachedValuesManager; import com.intellij.testFramework.LightVirtualFile; -import com.intellij.testFramework.MockSchemesManagerFactory; -import com.intellij.testFramework.PlatformLiteFixture; import com.intellij.testFramework.TestDataFile; -import com.intellij.util.CachedValuesManagerImpl; -import com.intellij.util.Function; -import com.intellij.util.messages.MessageBus; -import com.intellij.util.messages.MessageBusFactory; +import com.intellij.testFramework.UsefulTestCase; import org.jetbrains.annotations.NonNls; import org.jetbrains.jet.lang.parsing.JetParserDefinition; -import org.picocontainer.MutablePicoContainer; -import org.picocontainer.PicoContainer; -import org.picocontainer.PicoInitializationException; -import org.picocontainer.PicoIntrospectionException; -import org.picocontainer.defaults.AbstractComponentAdapter; +import org.jetbrains.jet.plugin.JetFileType; +import org.jetbrains.jet.plugin.JetLanguage; import java.io.File; import java.io.IOException; @@ -47,20 +25,17 @@ import java.io.IOException; /** * @author abreslav */ -public abstract class JetLiteFixture extends PlatformLiteFixture { +public abstract class JetLiteFixture extends UsefulTestCase { protected String myFileExt; @NonNls protected final String myFullDataPath; protected PsiFile myFile; - private MockPsiManager myPsiManager; - private PsiFileFactoryImpl myFileFactory; protected Language myLanguage; - protected final ParserDefinition[] myDefinitions; + private CoreEnvironment myEnvironment; public JetLiteFixture(@NonNls String dataPath) { myFileExt = "jet"; myFullDataPath = getTestDataPath() + "/" + dataPath; - myDefinitions = new ParserDefinition[] {new JetParserDefinition()}; } protected String getTestDataPath() { @@ -70,57 +45,17 @@ public abstract class JetLiteFixture extends PlatformLiteFixture { @Override protected void setUp() throws Exception { super.setUp(); - initApplication(); - getApplication().getPicoContainer().registerComponent(new AbstractComponentAdapter("com.intellij.openapi.progress.ProgressManager", Object.class) { - @Override - public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException { - return new ProgressManagerImpl(getApplication()); - } - - @Override - public void verify(PicoContainer container) throws PicoIntrospectionException { - } - }); - myProject = disposeOnTearDown(new MockProjectEx(getTestRootDisposable())); - myPsiManager = new MockPsiManager(myProject); - myFileFactory = new PsiFileFactoryImpl(myPsiManager); - final MutablePicoContainer appContainer = getApplication().getPicoContainer(); - registerComponentInstance(appContainer, MessageBus.class, MessageBusFactory.newMessageBus(getApplication())); - registerComponentInstance(appContainer, SchemesManagerFactory.class, new MockSchemesManagerFactory()); - final MockEditorFactory editorFactory = new MockEditorFactory(); - registerComponentInstance(appContainer, EditorFactory.class, editorFactory); - registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl(new Function() { - @Override - public Document fun(CharSequence charSequence) { - return editorFactory.createDocument(charSequence); - } - }, FileDocumentManagerImpl.DOCUMENT_KEY)); - registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager()); - myLanguage = myLanguage == null && myDefinitions != null && myDefinitions.length > 0 - ? myDefinitions[0].getFileNodeType().getLanguage() - : myLanguage; - registerComponentInstance(appContainer, FileTypeManager.class, new MockFileTypeManager(new MockLanguageFileType(myLanguage, myFileExt))); - registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl()); - registerApplicationService(DefaultASTFactory.class, new DefaultASTFactoryImpl()); - registerApplicationService(ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl()); - myProject.registerService(CachedValuesManager.class, new CachedValuesManagerImpl(myProject, new PsiCachedValuesFactory(myPsiManager))); - myProject.registerService(PsiManager.class, myPsiManager); - myProject.registerService(StartupManager.class, new StartupManagerImpl(myProject)); - myProject.registerService(PsiFileFactory.class, new PsiFileFactoryImpl(myPsiManager)); - - registerExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class); - - for (ParserDefinition definition : myDefinitions) { - addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition); - } + myEnvironment = new CoreEnvironment(getTestRootDisposable()); + myEnvironment.registerFileType(JetFileType.INSTANCE, ".jet"); + myLanguage = JetLanguage.INSTANCE; + myEnvironment.registerParserDefinition(new JetParserDefinition()); } @Override protected void tearDown() throws Exception { - super.tearDown(); myFile = null; - myProject = null; - myPsiManager = null; + myEnvironment = null; + super.tearDown(); } protected String loadFile(@NonNls @TestDataFile String name) throws IOException { @@ -141,7 +76,8 @@ public abstract class JetLiteFixture extends PlatformLiteFixture { protected PsiFile createFile(@NonNls String name, String text) { LightVirtualFile virtualFile = new LightVirtualFile(name, myLanguage, text); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); - return myFileFactory.trySetupPsiForFile(virtualFile, myLanguage, true, false); + PsiFileFactoryImpl psiFileFactory = (PsiFileFactoryImpl) PsiFileFactory.getInstance(myEnvironment.getProject()); + return psiFileFactory.trySetupPsiForFile(virtualFile, myLanguage, true, false); } protected static void ensureParsed(PsiFile file) { @@ -153,26 +89,6 @@ public abstract class JetLiteFixture extends PlatformLiteFixture { }); } - protected void registerApplicationService(final Class aClass, T object) { - getApplication().registerService(aClass, object); - Disposer.register(myProject, new Disposable() { - @Override - public void dispose() { - getApplication().getPicoContainer().unregisterComponent(aClass.getName()); - } - }); - } - - protected void addExplicitExtension(final LanguageExtension instance, final Language language, final T object) { - instance.addExplicitExtension(language, object); - Disposer.register(myProject, new Disposable() { - @Override - public void dispose() { - instance.removeExplicitExtension(language, object); - } - }); - } - protected void prepareForTest(String name) throws IOException { String text = loadFile(name + "." + myFileExt); createAndCheckPsiFile(name, text); From ae2ecc52f917f405edab78e79cf059143bc43ea5 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 14 Oct 2011 07:47:25 +0200 Subject: [PATCH 04/10] compilation fixed --- idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java | 3 +-- idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java index 8d275884991..41afaea579c 100644 --- a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java +++ b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java @@ -18,7 +18,6 @@ import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.lang.types.expressions.JetTypeInferrerServices; import org.jetbrains.jet.parsing.JetParsingTest; import java.io.File; @@ -106,7 +105,7 @@ public class JetResolveTest extends ExtensibleResolveTestCase { @NotNull private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, List typeArguments, String name, JetType... parameterType) { List parameterTypeList = Arrays.asList(parameterType); - JetTypeInferrerServices typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext()); + JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext()); OverloadResolutionResults functions = typeInferrerServices.getCallResolver().resolveExactSignature( classDescriptor.getMemberScope(typeArguments), ReceiverDescriptor.NO_RECEIVER, name, parameterTypeList); diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 54aeedef944..b9cedae1ee7 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -20,7 +20,6 @@ import org.jetbrains.jet.lang.resolve.scopes.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.lang.types.expressions.JetTypeInferrer; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.parsing.JetParsingTest; From 7831fc3dc143da2fd2c79254515ee7fd6908d634 Mon Sep 17 00:00:00 2001 From: svtk Date: Fri, 14 Oct 2011 19:08:23 +0400 Subject: [PATCH 05/10] b3783e 'JetLiteFixture uses CoreEnvironment...' reverted --- .../org/jetbrains/jet/JetLiteFixture.java | 122 +++++++++++++++--- 1 file changed, 103 insertions(+), 19 deletions(-) diff --git a/idea/tests/org/jetbrains/jet/JetLiteFixture.java b/idea/tests/org/jetbrains/jet/JetLiteFixture.java index 36ac21bd281..a2142bee57c 100644 --- a/idea/tests/org/jetbrains/jet/JetLiteFixture.java +++ b/idea/tests/org/jetbrains/jet/JetLiteFixture.java @@ -1,23 +1,45 @@ package org.jetbrains.jet; -import com.intellij.core.CoreEnvironment; -import com.intellij.lang.Language; +import com.intellij.ide.startup.impl.StartupManagerImpl; +import com.intellij.lang.*; +import com.intellij.lang.impl.PsiBuilderFactoryImpl; +import com.intellij.mock.*; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; import com.intellij.openapi.fileEditor.impl.LoadTextUtil; +import com.intellij.openapi.fileTypes.FileTypeFactory; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.options.SchemesManagerFactory; +import com.intellij.openapi.progress.impl.ProgressManagerImpl; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.*; +import com.intellij.psi.impl.PsiCachedValuesFactory; import com.intellij.psi.impl.PsiFileFactoryImpl; +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl; +import com.intellij.psi.util.CachedValuesManager; import com.intellij.testFramework.LightVirtualFile; +import com.intellij.testFramework.MockSchemesManagerFactory; +import com.intellij.testFramework.PlatformLiteFixture; import com.intellij.testFramework.TestDataFile; -import com.intellij.testFramework.UsefulTestCase; +import com.intellij.util.CachedValuesManagerImpl; +import com.intellij.util.Function; +import com.intellij.util.messages.MessageBus; +import com.intellij.util.messages.MessageBusFactory; import org.jetbrains.annotations.NonNls; import org.jetbrains.jet.lang.parsing.JetParserDefinition; -import org.jetbrains.jet.plugin.JetFileType; -import org.jetbrains.jet.plugin.JetLanguage; +import org.picocontainer.MutablePicoContainer; +import org.picocontainer.PicoContainer; +import org.picocontainer.PicoInitializationException; +import org.picocontainer.PicoIntrospectionException; +import org.picocontainer.defaults.AbstractComponentAdapter; import java.io.File; import java.io.IOException; @@ -25,17 +47,20 @@ import java.io.IOException; /** * @author abreslav */ -public abstract class JetLiteFixture extends UsefulTestCase { +public abstract class JetLiteFixture extends PlatformLiteFixture { protected String myFileExt; @NonNls protected final String myFullDataPath; protected PsiFile myFile; + private MockPsiManager myPsiManager; + private PsiFileFactoryImpl myFileFactory; protected Language myLanguage; - private CoreEnvironment myEnvironment; + protected final ParserDefinition[] myDefinitions; public JetLiteFixture(@NonNls String dataPath) { myFileExt = "jet"; myFullDataPath = getTestDataPath() + "/" + dataPath; + myDefinitions = new ParserDefinition[] {new JetParserDefinition()}; } protected String getTestDataPath() { @@ -45,17 +70,57 @@ public abstract class JetLiteFixture extends UsefulTestCase { @Override protected void setUp() throws Exception { super.setUp(); - myEnvironment = new CoreEnvironment(getTestRootDisposable()); - myEnvironment.registerFileType(JetFileType.INSTANCE, ".jet"); - myLanguage = JetLanguage.INSTANCE; - myEnvironment.registerParserDefinition(new JetParserDefinition()); + initApplication(); + getApplication().getPicoContainer().registerComponent(new AbstractComponentAdapter("com.intellij.openapi.progress.ProgressManager", Object.class) { + @Override + public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException { + return new ProgressManagerImpl(getApplication()); + } + + @Override + public void verify(PicoContainer container) throws PicoIntrospectionException { + } + }); + myProject = disposeOnTearDown(new MockProjectEx(getTestRootDisposable())); + myPsiManager = new MockPsiManager(myProject); + myFileFactory = new PsiFileFactoryImpl(myPsiManager); + final MutablePicoContainer appContainer = getApplication().getPicoContainer(); + registerComponentInstance(appContainer, MessageBus.class, MessageBusFactory.newMessageBus(getApplication())); + registerComponentInstance(appContainer, SchemesManagerFactory.class, new MockSchemesManagerFactory()); + final MockEditorFactory editorFactory = new MockEditorFactory(); + registerComponentInstance(appContainer, EditorFactory.class, editorFactory); + registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl(new Function() { + @Override + public Document fun(CharSequence charSequence) { + return editorFactory.createDocument(charSequence); + } + }, FileDocumentManagerImpl.DOCUMENT_KEY)); + registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager()); + myLanguage = myLanguage == null && myDefinitions != null && myDefinitions.length > 0 + ? myDefinitions[0].getFileNodeType().getLanguage() + : myLanguage; + registerComponentInstance(appContainer, FileTypeManager.class, new MockFileTypeManager(new MockLanguageFileType(myLanguage, myFileExt))); + registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl()); + registerApplicationService(DefaultASTFactory.class, new DefaultASTFactoryImpl()); + registerApplicationService(ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl()); + myProject.registerService(CachedValuesManager.class, new CachedValuesManagerImpl(myProject, new PsiCachedValuesFactory(myPsiManager))); + myProject.registerService(PsiManager.class, myPsiManager); + myProject.registerService(StartupManager.class, new StartupManagerImpl(myProject)); + myProject.registerService(PsiFileFactory.class, new PsiFileFactoryImpl(myPsiManager)); + + registerExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class); + + for (ParserDefinition definition : myDefinitions) { + addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition); + } } @Override protected void tearDown() throws Exception { - myFile = null; - myEnvironment = null; super.tearDown(); + myFile = null; + myProject = null; + myPsiManager = null; } protected String loadFile(@NonNls @TestDataFile String name) throws IOException { @@ -76,8 +141,7 @@ public abstract class JetLiteFixture extends UsefulTestCase { protected PsiFile createFile(@NonNls String name, String text) { LightVirtualFile virtualFile = new LightVirtualFile(name, myLanguage, text); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); - PsiFileFactoryImpl psiFileFactory = (PsiFileFactoryImpl) PsiFileFactory.getInstance(myEnvironment.getProject()); - return psiFileFactory.trySetupPsiForFile(virtualFile, myLanguage, true, false); + return myFileFactory.trySetupPsiForFile(virtualFile, myLanguage, true, false); } protected static void ensureParsed(PsiFile file) { @@ -89,6 +153,26 @@ public abstract class JetLiteFixture extends UsefulTestCase { }); } + protected void registerApplicationService(final Class aClass, T object) { + getApplication().registerService(aClass, object); + Disposer.register(myProject, new Disposable() { + @Override + public void dispose() { + getApplication().getPicoContainer().unregisterComponent(aClass.getName()); + } + }); + } + + protected void addExplicitExtension(final LanguageExtension instance, final Language language, final T object) { + instance.addExplicitExtension(language, object); + Disposer.register(myProject, new Disposable() { + @Override + public void dispose() { + instance.removeExplicitExtension(language, object); + } + }); + } + protected void prepareForTest(String name) throws IOException { String text = loadFile(name + "." + myFileExt); createAndCheckPsiFile(name, text); From ada54665dbc5f7262d559495e457c84784f93a28 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sat, 15 Oct 2011 13:05:10 +0200 Subject: [PATCH 06/10] closure shared vars --- .../jetbrains/jet/codegen/ClassContext.java | 10 +- .../jetbrains/jet/codegen/ClosureCodegen.java | 14 +- .../jet/codegen/ExpressionCodegen.java | 68 ++++++- .../org/jetbrains/jet/codegen/FrameMap.java | 1 + .../jet/codegen/FunctionCodegen.java | 17 ++ .../jetbrains/jet/codegen/JetTypeMapper.java | 9 + .../org/jetbrains/jet/codegen/StackValue.java | 125 +++++++++++- .../classes/enclosingLocalVariable.jet | 2 +- idea/testData/codegen/regressions/kt344.jet | 179 ++++++++++++++++++ .../jetbrains/jet/codegen/ClassGenTest.java | 6 + .../jet/codegen/ClosuresGenTest.java | 1 + stdlib/src/jet/refs/SharedVar.java | 39 ++++ 12 files changed, 448 insertions(+), 23 deletions(-) create mode 100644 idea/testData/codegen/regressions/kt344.jet create mode 100644 stdlib/src/jet/refs/SharedVar.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java index e0fe6e08cb3..77aa758764c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java @@ -146,7 +146,15 @@ public class ClassContext { if (answer != null) return answer; final StackValue thisContext = getThisExpression(); - thisContext.put(thisContext.type, v); + if(thisContext instanceof StackValue.Local) { + } + else if(thisContext instanceof StackValue.InstanceField) { + StackValue.InstanceField instanceField = (StackValue.InstanceField) thisContext; + v.getfield(instanceField.owner, instanceField.name, instanceField.type.getDescriptor()); + } + else { + throw new UnsupportedOperationException(); + } } return parentContext != null ? parentContext.lookupInContext(d, v) : null; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 2e04ada073d..7341765d51e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -67,11 +67,13 @@ public class ClosureCodegen { final int idx = exprContext.lookupLocal(vd); if (idx < 0) return null; - final Type type = state.getTypeMapper().mapType(vd.getOutType()); + final Type sharedVarType = exprContext.getSharedVarType(vd); + Type localType = state.getTypeMapper().mapType(vd.getOutType()); + final Type type = sharedVarType != null ? sharedVarType : localType; StackValue outerValue = StackValue.local(idx, type); - final String fieldName = "$" + (closure.size() + 1); - StackValue innerValue = StackValue.field(type, name, fieldName, false); + final String fieldName = "$" + (closure.size() + 1); // + "$" + vd.getName(); + StackValue innerValue = sharedVarType != null ? StackValue.fieldForSharedVar(localType, name, fieldName) : StackValue.field(type, name, fieldName, false); cv.visitField(Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null); answer = new EnclosedValueDescriptor(d, innerValue, outerValue); closure.put(d, answer); @@ -120,7 +122,7 @@ public class ClosureCodegen { final Method constructor = generateConstructor(funClass, captureThis, funDescriptor.getReturnType()); if (captureThis) { - cv.visitField(Opcodes.ACC_PRIVATE, "this$0", enclosingType.getDescriptor(), null, null); + cv.visitField(0, "this$0", enclosingType.getDescriptor(), null, null); } cv.visitEnd(); @@ -192,7 +194,9 @@ public class ClosureCodegen { } for (DeclarationDescriptor descriptor : closure.keySet()) { - argTypes[i++] = state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()); + final Type sharedVarType = exprContext.getSharedVarType(descriptor); + final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()); + argTypes[i++] = type; } final Method constructor = new Method("", Type.VOID_TYPE, argTypes); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index f231cdf3426..2a5a9bed97e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -551,7 +551,7 @@ public class ExpressionCodegen extends JetVisitor { final Method cons = closure.getConstructor(); if (closure.isCaptureThis()) { - thisToStack(); + v.load(0, JetTypeMapper.TYPE_OBJECT); } for (int i = 0; i < closure.getArgs().size(); i++) { @@ -576,6 +576,20 @@ public class ExpressionCodegen extends JetVisitor { return StackValue.onStack(type); } + Type getSharedVarType(DeclarationDescriptor variableDescriptor) { + if(!(variableDescriptor instanceof VariableDescriptor)) + return null; + + Boolean aBoolean = bindingContext.get(BindingContext.MUST_BE_WRAPPED_IN_A_REF, (VariableDescriptor) variableDescriptor); + if (aBoolean != null && aBoolean) { + JetType outType = ((VariableDescriptor) variableDescriptor).getOutType(); + return StackValue.sharedTypeForType(typeMapper.mapType(outType)); + } + else { + return null; + } + } + private StackValue generateBlock(List statements) { Label blockStart = new Label(); v.mark(blockStart); @@ -584,7 +598,9 @@ public class ExpressionCodegen extends JetVisitor { if (statement instanceof JetProperty) { final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, statement); assert variableDescriptor != null; - final Type type = typeMapper.mapType(variableDescriptor.getOutType()); + + final Type sharedVarType = getSharedVarType(variableDescriptor); + final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); myMap.enter(variableDescriptor, type.getSize()); } } @@ -608,10 +624,17 @@ public class ExpressionCodegen extends JetVisitor { JetProperty var = (JetProperty) statement; VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var); assert variableDescriptor != null; - Type outType = typeMapper.mapType(variableDescriptor.getOutType()); int index = myMap.leave(variableDescriptor); - v.visitLocalVariable(var.getName(), outType.getDescriptor(), null, blockStart, blockEnd, index); + + final Type sharedVarType = getSharedVarType(variableDescriptor); + final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); + if(sharedVarType != null) { + v.aconst(null); + v.store(index, JetTypeMapper.TYPE_OBJECT); + } + + v.visitLocalVariable(var.getName(), type.getDescriptor(), null, blockStart, blockEnd, index); } } @@ -699,8 +722,14 @@ public class ExpressionCodegen extends JetVisitor { else { int index = lookupLocal(descriptor); if (index >= 0) { + Type sharedVarType = getSharedVarType(descriptor); final JetType outType = ((VariableDescriptor) descriptor).getOutType(); - return StackValue.local(index, typeMapper.mapType(outType)); + if(sharedVarType != null) { + return StackValue.shared(index, typeMapper.mapType(outType)); + } + else { + return StackValue.local(index, typeMapper.mapType(outType)); + } } else if (descriptor instanceof PropertyDescriptor) { final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; @@ -785,6 +814,12 @@ public class ExpressionCodegen extends JetVisitor { if (value == null) { throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); } + + if(value instanceof StackValue.FieldForSharedVar) { + StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; + Type sharedType = StackValue.sharedTypeForType(value.type); + v.visitFieldInsn(Opcodes.GETFIELD, fieldForSharedVar.owner, fieldForSharedVar.name, sharedType.getDescriptor()); + } return value; } } @@ -1617,12 +1652,27 @@ public class ExpressionCodegen extends JetVisitor { assert index >= 0; + final Type sharedVarType = getSharedVarType(variableDescriptor); + assert variableDescriptor != null; + Type varType = typeMapper.mapType(variableDescriptor.getOutType()); + if(sharedVarType != null) { + v.anew(sharedVarType); + v.dup(); + v.invokespecial(sharedVarType.getInternalName(), "", "()V"); + v.store(index, JetTypeMapper.TYPE_OBJECT); + } + JetExpression initializer = property.getInitializer(); if (initializer != null) { - assert variableDescriptor != null; - Type type = typeMapper.mapType(variableDescriptor.getOutType()); - gen(initializer, type); - v.store(index, type); + if(sharedVarType == null) { + gen(initializer, varType); + v.store(index, varType); + } + else { + v.load(index, JetTypeMapper.TYPE_OBJECT); + gen(initializer, varType); + v.putfield(sharedVarType.getInternalName(), "ref", sharedVarType == JetTypeMapper.TYPE_SHARED_VAR ? "Ljava/lang/Object;" : varType.getDescriptor()); + } } return StackValue.none(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FrameMap.java b/compiler/backend/src/org/jetbrains/jet/codegen/FrameMap.java index bf6c4710c31..3bcaf17e855 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FrameMap.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FrameMap.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.codegen; import gnu.trove.TObjectIntHashMap; import gnu.trove.TObjectIntIterator; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.resolve.BindingContext; import java.util.ArrayList; import java.util.List; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index d7b0b188569..1fcd98e320c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -98,6 +98,23 @@ public class FunctionCodegen { iv.areturn(jvmSignature.getReturnType()); } else { + for (int i = 0; i < paramDescrs.size(); i++) { + ValueParameterDescriptor parameter = paramDescrs.get(i); + + Type sharedVarType = codegen.getSharedVarType(parameter); + Type localVarType = state.getTypeMapper().mapType(parameter.getOutType()); + if(sharedVarType != null) { + int index = frameMap.getIndex(parameter); + mv.visitTypeInsn(Opcodes.NEW, sharedVarType.getInternalName()); + mv.visitInsn(Opcodes.DUP); + mv.visitInsn(Opcodes.DUP); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, sharedVarType.getInternalName(), "", "()V"); + mv.visitVarInsn(localVarType.getOpcode(Opcodes.ILOAD), index); + mv.visitFieldInsn(Opcodes.PUTFIELD, sharedVarType.getInternalName(), "ref", StackValue.refType(localVarType).getDescriptor()); + mv.visitVarInsn(sharedVarType.getOpcode(Opcodes.ISTORE), index); + } + } + codegen.returnExpression(bodyExpressions); } mv.visitMaxs(0, 0); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index b8e221c52a9..9cf08cd2482 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -59,6 +59,15 @@ public class JetTypeMapper { public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1"); public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator"); public static final Type TYPE_INT_RANGE = Type.getObjectType("jet/IntRange"); + public static final Type TYPE_SHARED_VAR = Type.getObjectType("jet/refs/SharedVar$Object"); + public static final Type TYPE_SHARED_INT = Type.getObjectType("jet/refs/SharedVar$Int"); + public static final Type TYPE_SHARED_DOUBLE = Type.getObjectType("jet/refs/SharedVar$Double"); + public static final Type TYPE_SHARED_FLOAT = Type.getObjectType("jet/refs/SharedVar$Float"); + public static final Type TYPE_SHARED_BYTE = Type.getObjectType("jet/refs/SharedVar$Byte"); + public static final Type TYPE_SHARED_SHORT = Type.getObjectType("jet/refs/SharedVar$Short"); + public static final Type TYPE_SHARED_CHAR = Type.getObjectType("jet/refs/SharedVar$Char"); + public static final Type TYPE_SHARED_LONG = Type.getObjectType("jet/refs/SharedVar$Long"); + public static final Type TYPE_SHARED_BOOLEAN = Type.getObjectType("jet/refs/SharedVar$Boolean"); public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { this.standardLibrary = standardLibrary; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index f60fc9804cc..52ff48a6183 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -11,6 +11,7 @@ import org.objectweb.asm.commons.Method; /** * @author yole + * @author alex.tkachman */ public abstract class StackValue { public final Type type; @@ -59,6 +60,10 @@ public abstract class StackValue { return new Local(index, type); } + public static StackValue shared(int index, Type type) { + return new Shared(index, type); + } + public static StackValue onStack(Type type) { return type == Type.VOID_TYPE ? none() : new OnStack(type); } @@ -225,7 +230,11 @@ public abstract class StackValue { public static StackValue none() { return None.INSTANCE; } - + + public static StackValue fieldForSharedVar(Type type, String name, String fieldName) { + return new FieldForSharedVar(type, name, fieldName); + } + private static class None extends StackValue { public static None INSTANCE = new None(); private None() { @@ -496,9 +505,9 @@ public abstract class StackValue { } - private static class Field extends StackValue { - private final String owner; - private final String name; + static class Field extends StackValue { + final String owner; + final String name; private final boolean isStatic; public Field(Type type, String owner, String name, boolean isStatic) { @@ -531,9 +540,9 @@ public abstract class StackValue { } } - private static class InstanceField extends StackValue { - private final String owner; - private final String name; + static class InstanceField extends StackValue { + final String owner; + final String name; public InstanceField(Type type, String owner, String name) { super(type); @@ -625,4 +634,106 @@ public abstract class StackValue { generator.gen(expression, type); } } + + public static class Shared extends StackValue { + private final int index; + + public Shared(int index, Type type) { + super(type); + this.index = index; + } + + @Override + public void put(Type type, InstructionAdapter v) { + v.load(index, JetTypeMapper.TYPE_OBJECT); + Type refType = refType(this.type); + Type sharedType = sharedTypeForType(this.type); + v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor()); + StackValue.onStack(refType).coerce(this.type, v); + StackValue.onStack(this.type).coerce(type, v); + } + + @Override + public void store(InstructionAdapter v) { + v.load(index, JetTypeMapper.TYPE_OBJECT); + v.swap(); + Type refType = refType(this.type); + Type sharedType = sharedTypeForType(this.type); + v.visitFieldInsn(Opcodes.PUTFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor()); + } + } + + public static Type sharedTypeForType(Type type) { + switch(type.getSort()) { + case Type.OBJECT: + case Type.ARRAY: + return JetTypeMapper.TYPE_SHARED_VAR; + + case Type.BYTE: + return JetTypeMapper.TYPE_SHARED_BYTE; + + case Type.SHORT: + return JetTypeMapper.TYPE_SHARED_SHORT; + + case Type.CHAR: + return JetTypeMapper.TYPE_SHARED_CHAR; + + case Type.INT: + return JetTypeMapper.TYPE_SHARED_INT; + + case Type.BOOLEAN: + return JetTypeMapper.TYPE_SHARED_BOOLEAN; + + case Type.FLOAT: + return JetTypeMapper.TYPE_SHARED_FLOAT; + + case Type.DOUBLE: + return JetTypeMapper.TYPE_SHARED_DOUBLE; + + default: + throw new UnsupportedOperationException(); + } + } + + public static Type refType(Type type) { + if(type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) + return JetTypeMapper.TYPE_OBJECT; + + return type; + } + + static class FieldForSharedVar extends StackValue { + final String owner; + final String name; + + public FieldForSharedVar(Type type, String owner, String name) { + super(type); + this.owner = owner; + this.name = name; + } + + @Override + public void dupReceiver(InstructionAdapter v, int below) { + if (below == 1) { + v.dupX1(); + } + else { + v.dup(); + } + } + + @Override + public void put(Type type, InstructionAdapter v) { + Type sharedType = sharedTypeForType(this.type); + Type refType = refType(this.type); + v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor()); + StackValue.onStack(refType).coerce(this.type, v); + StackValue.onStack(this.type).coerce(type, v); + } + + @Override + public void store(InstructionAdapter v) { + v.visitFieldInsn(Opcodes.PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor()); + } + } } diff --git a/idea/testData/codegen/classes/enclosingLocalVariable.jet b/idea/testData/codegen/classes/enclosingLocalVariable.jet index aaf5081cefb..d2dbe243469 100644 --- a/idea/testData/codegen/classes/enclosingLocalVariable.jet +++ b/idea/testData/codegen/classes/enclosingLocalVariable.jet @@ -1,6 +1,6 @@ fun box() : String { val cl = 39 - return if (sum(200, { cl }) == 239) "OK" else "FAIL" + return if (sum(200, { val m = { val r = { cl }; r() }; m() }) == 239) "OK" else "FAIL" } fun sum(arg:Int, f : fun () : Int) : Int { diff --git a/idea/testData/codegen/regressions/kt344.jet b/idea/testData/codegen/regressions/kt344.jet new file mode 100644 index 00000000000..c551963b701 --- /dev/null +++ b/idea/testData/codegen/regressions/kt344.jet @@ -0,0 +1,179 @@ +fun s0() : Boolean { + val y = "222" + val foo = { + val bar = { y } + bar () + } + return foo() == "222" +} + +fun s1() : Boolean { + var x = "222" + val foo = { + val bar = { + x = "aaa" + } + bar () + } + foo() + return x == "aaa" +} + +fun t1() : Boolean { + var x = "111" + + val y = x + "22" + val foo = { + x = x + "45" + y + x = x.substring(3) + x += "aaa" + () + } + foo() + + x += "bbb" + System.out?.println(x) + return x == "4511122aaabbb" +} + +fun t2() : Boolean { + var x = 111 + val y = x + 22 + val foo = { + x = x + 5 + y + x += 5 + x++ + () + } + foo() + x -= 55 + System.out?.println(x) + return x == 200 +} + +fun t3() : Boolean { + var x = true + val foo = { + x = false + () + } + foo() + return !x +} + +fun t4() : Boolean { + var x = 100.flt + val y = x + 22 + val foo = { + x = x + 200.flt + y + x += 18 + () + } + foo() + System.out?.println(x) + return x == 440.flt +} + +fun t5() : Boolean { + var x = 100.dbl + val y = x + 22 + val foo = { + x = x + 200.dbl + y + x -= 22 + () + } + foo() + System.out?.println(x) + return x == 400.dbl +} + +fun t6() : Boolean { + var x = 20.byt + val y = x + 22 + val foo = { + x = (x + 20.byt + y).byt + x += 2 + x-- + () + } + foo() + System.out?.println(x) + return x == 83.byt +} + +fun t7() : Boolean { + var x : Char = 'a' + val foo = { + x = 'b' + () + } + foo() + System.out?.println(x) + return x == 'b' +} + +fun t8() : Boolean { + var x = 20.sht + val foo = { + val bar = { + x = 30.sht + () + } + bar() + () + } + foo() + return x == 30.sht +} + +fun t9(x: Int) : Boolean { + while(x < 100) { + x++ + } + return x == 100 +} + +fun t10() : Boolean { + var y = 1 + val foo = { + val bar = { + y = y + 1 + } + bar() + } + foo() + return y == 2 +} + +fun t11(x: Int) : Int { + val foo = { + x = x + 1 + val bar = { + x = x + 1 + x += 3 + } + bar() + } + while(x < 100) { + foo() + } + return x +} + +fun box(): String { + if (!s0()) return "fail" + if (!s1()) return "fail" + if (!t1()) return "fail" + if (!t2()) return "fail" + if (!t3()) return "fail" + if (!t4()) return "fail" + if (!t5()) return "fail" + if (!t6()) return "fail" + if (!t7()) return "fail" + if (!t8()) return "fail" + if (!t9(0)) return "fail" + if (!t10()) return "fail" + if (t11(1) != 104) return "fail" + + return "OK" +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 72a131c61c6..97e4098243d 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -190,4 +190,10 @@ public class ClassGenTest extends CodegenTestCase { blackBoxFile("regressions/kt343.jet"); System.out.println(generateToText()); } + + public void testKt344 () throws Exception { + loadFile("regressions/kt344.jet"); + System.out.println(generateToText()); + blackBox(); + } } diff --git a/idea/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java index 7d5f4a68fc8..07b094c344d 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClosuresGenTest.java @@ -27,6 +27,7 @@ public class ClosuresGenTest extends CodegenTestCase { public void testEnclosingLocalVariable() throws Exception { blackBoxFile("classes/enclosingLocalVariable.jet"); + System.out.println(generateToText()); } public void testDoubleEnclosedLocalVariable() throws Exception { diff --git a/stdlib/src/jet/refs/SharedVar.java b/stdlib/src/jet/refs/SharedVar.java new file mode 100644 index 00000000000..0bd99c66965 --- /dev/null +++ b/stdlib/src/jet/refs/SharedVar.java @@ -0,0 +1,39 @@ +package jet.refs; + +public final class SharedVar { + public static final class Object { + public T ref; + } + + public static final class Byte { + public byte ref; + } + + public static final class Short { + public short ref; + } + + public static final class Int { + public int ref; + } + + public static final class Long { + public long ref; + } + + public static final class Float { + public float ref; + } + + public static final class Double { + public double ref; + } + + public static final class Char { + public char ref; + } + + public static final class Boolean { + public boolean ref; + } +} From f29768efe98739f22eb482b020b2e738f85c55c9 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sun, 16 Oct 2011 19:16:55 +0200 Subject: [PATCH 07/10] object literals shared vars --- .../jet/codegen/ClassBodyCodegen.java | 4 +- .../jetbrains/jet/codegen/ClassCodegen.java | 8 +-- .../jetbrains/jet/codegen/ClassContext.java | 17 +++--- .../jetbrains/jet/codegen/ClosureCodegen.java | 40 +------------ .../jet/codegen/ExpressionCodegen.java | 25 ++++++-- .../jet/codegen/FunctionOrClosureCodegen.java | 57 +++++++++++++++++++ .../jet/codegen/GenerationState.java | 17 ++++-- .../codegen/ImplementationBodyCodegen.java | 29 +++++++++- .../codegen/objects/objectLiteral.jet | 17 ++++-- idea/testData/codegen/regressions/kt344.jet | 17 ++++++ .../jetbrains/jet/codegen/ObjectGenTest.java | 1 + .../jet/codegen/PropertyGenTest.java | 2 +- 12 files changed, 163 insertions(+), 71 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/FunctionOrClosureCodegen.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 6ffc688431f..4ab6dfeb815 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -40,10 +40,10 @@ public abstract class ClassBodyCodegen { public void generate() { generateDeclaration(); - generateSyntheticParts(); - generateClassBody(); + generateSyntheticParts(); + generateStaticInitializer(); v.visitEnd(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index 60dc3bc46f0..86ebc6554ad 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -4,8 +4,6 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Type; -import org.objectweb.asm.commons.InstructionAdapter; /** * @author max @@ -25,7 +23,7 @@ public class ClassCodegen { generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION); - final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION); + final ClassContext contextForInners = parentContext.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION); for (JetDeclaration declaration : aClass.getDeclarations()) { if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) { generate(contextForInners, (JetClass) declaration); @@ -36,11 +34,11 @@ public class ClassCodegen { private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) { ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); ClassVisitor v = state.forClassImplementation(descriptor); - new ImplementationBodyCodegen(aClass, parentContext.intoClass(descriptor, kind), v, state).generate(); + new ImplementationBodyCodegen(aClass, parentContext.intoClass(null, descriptor, kind), v, state).generate(); if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) { v = state.forTraitImplementation(descriptor); - new TraitImplBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL), v, state).generate(); + new TraitImplBodyCodegen(aClass, parentContext.intoClass(null, descriptor, OwnerKind.TRAIT_IMPL), v, state).generate(); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java index 77aa758764c..3e1200388ab 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java @@ -1,6 +1,3 @@ -/* - * @author max - */ package org.jetbrains.jet.codegen; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; @@ -14,18 +11,22 @@ import org.objectweb.asm.commons.InstructionAdapter; import java.util.HashMap; +/* + * @author max + * @author alex.tkachman + */ public class ClassContext { public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null, null); private final DeclarationDescriptor contextType; private final OwnerKind contextKind; private final StackValue thisExpression; private final ClassContext parentContext; - private final ClosureCodegen closure; + public final FunctionOrClosureCodegen closure; private boolean thisWasUsed = false; HashMap typeInfoConstants; - public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, ClosureCodegen closureCodegen) { + public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) { this.contextType = contextType; this.contextKind = contextKind; this.thisExpression = thisExpression; @@ -60,11 +61,11 @@ public class ClassContext { return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this, null); } - public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind) { + public ClassContext intoClass(FunctionOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) { final StackValue thisValue; thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); - return new ClassContext(descriptor, kind, thisValue, this, null); + return new ClassContext(descriptor, kind, thisValue, this, closure); } public ClassContext intoFunction(FunctionDescriptor descriptor) { @@ -140,7 +141,7 @@ public class ClassContext { } public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) { - final ClosureCodegen top = closure; + final FunctionOrClosureCodegen top = closure; if (top != null) { final StackValue answer = top.lookupInContext(d); if (answer != null) return answer; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 7341765d51e..8e507409cb9 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -26,19 +26,10 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -public class ClosureCodegen { - public final GenerationState state; - private final ExpressionCodegen exprContext; - private final ClassContext context; - private ClassVisitor cv = null; - public String name = null; - - private Map closure = new LinkedHashMap(); +public class ClosureCodegen extends FunctionOrClosureCodegen { public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, ClassContext context) { - this.state = state; - this.exprContext = exprContext; - this.context = context; + super(exprContext, context, state); } public static Method erasedInvokeSignature(FunctionDescriptor fd) { @@ -57,33 +48,6 @@ public class ClosureCodegen { return state.getTypeMapper().mapSignature("invoke", fd); } - public StackValue lookupInContext(DeclarationDescriptor d) { - if (d instanceof VariableDescriptor) { - VariableDescriptor vd = (VariableDescriptor) d; - - EnclosedValueDescriptor answer = closure.get(vd); - if (answer != null) return answer.getInnerValue(); - - final int idx = exprContext.lookupLocal(vd); - if (idx < 0) return null; - - final Type sharedVarType = exprContext.getSharedVarType(vd); - Type localType = state.getTypeMapper().mapType(vd.getOutType()); - final Type type = sharedVarType != null ? sharedVarType : localType; - - StackValue outerValue = StackValue.local(idx, type); - final String fieldName = "$" + (closure.size() + 1); // + "$" + vd.getName(); - StackValue innerValue = sharedVarType != null ? StackValue.fieldForSharedVar(localType, name, fieldName) : StackValue.field(type, name, fieldName, false); - cv.visitField(Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null); - answer = new EnclosedValueDescriptor(d, innerValue, outerValue); - closure.put(d, answer); - - return innerValue; - } - - return null; - } - public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) { final Pair nameAndVisitor = state.forAnonymousSubclass(fun); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 2a5a9bed97e..3f7cba76ff2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -566,14 +566,27 @@ public class ExpressionCodegen extends JetVisitor { @Override public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) { - GeneratedAnonymousClassDescriptor descriptor = state.generateObjectLiteral(expression, this, context); - Type type = Type.getObjectType(descriptor.getClassname()); + FunctionOrClosureCodegen closureCodegen = new FunctionOrClosureCodegen(this, context, state); + GeneratedAnonymousClassDescriptor closure = state.generateObjectLiteral(expression, closureCodegen); + Type type = Type.getObjectType(closure.getClassname()); v.anew(type); v.dup(); - v.load(0, JetTypeMapper.TYPE_OBJECT); - String jvmDescriptor = descriptor.getConstructor().getDescriptor().replace("(","(" + typeMapper.jetImplementationType((ClassDescriptor) contextType())); - v.invokespecial(descriptor.getClassname(), "", jvmDescriptor); - return StackValue.onStack(type); + final List consArgTypes = new LinkedList(Arrays.asList(closure.getConstructor().getArgumentTypes())); + + if (consArgTypes.size() > 0) { + v.load(0, JetTypeMapper.TYPE_OBJECT); + } + + for (DeclarationDescriptor descriptor : closureCodegen.closure.keySet()) { + final Type sharedVarType = getSharedVarType(descriptor); + consArgTypes.add(sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType())); + final EnclosedValueDescriptor valueDescriptor = closureCodegen.closure.get(descriptor); + valueDescriptor.getOuterValue().put(sharedVarType, v); + } + + Method cons = new Method("", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()])); + v.invokespecial(closure.getClassname(), "", cons.getDescriptor()); + return StackValue.onStack(Type.getObjectType(closure.getClassname())); } Type getSharedVarType(DeclarationDescriptor variableDescriptor) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionOrClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionOrClosureCodegen.java new file mode 100644 index 00000000000..a6a57ece6b5 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionOrClosureCodegen.java @@ -0,0 +1,57 @@ +package org.jetbrains.jet.codegen; + +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author alex.tkachman + */ +public class FunctionOrClosureCodegen { + public final GenerationState state; + protected final ExpressionCodegen exprContext; + protected final ClassContext context; + protected ClassVisitor cv = null; + public String name = null; + protected Map closure = new LinkedHashMap(); + + public FunctionOrClosureCodegen(ExpressionCodegen exprContext, ClassContext context, GenerationState state) { + this.exprContext = exprContext; + this.context = context; + this.state = state; + } + + public StackValue lookupInContext(DeclarationDescriptor d) { + if (d instanceof VariableDescriptor) { + VariableDescriptor vd = (VariableDescriptor) d; + + EnclosedValueDescriptor answer = closure.get(vd); + if (answer != null) return answer.getInnerValue(); + + final int idx = exprContext.lookupLocal(vd); + if (idx < 0) return null; + + final Type sharedVarType = exprContext.getSharedVarType(vd); + Type localType = state.getTypeMapper().mapType(vd.getOutType()); + final Type type = sharedVarType != null ? sharedVarType : localType; + + StackValue outerValue = StackValue.local(idx, type); + final String fieldName = "$" + (closure.size() + 1); // + "$" + vd.getName(); + StackValue innerValue = sharedVarType != null ? StackValue.fieldForSharedVar(localType, name, fieldName) : StackValue.field(type, name, fieldName, false); + + cv.visitField(Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null); + + answer = new EnclosedValueDescriptor(d, innerValue, outerValue); + closure.put(d, answer); + + return innerValue; + } + + return null; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 39862f0051e..51713dc8fb4 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -9,6 +9,7 @@ import com.intellij.util.containers.Stack; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -120,13 +121,19 @@ public class GenerationState { } } - public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) { - Pair nameAndVisitor = forAnonymousSubclass(literal.getObjectDeclaration()); + public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) { + JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); + Pair nameAndVisitor = forAnonymousSubclass(objectDeclaration); - final ClassContext objectContext = classContext.intoClass(getBindingContext().get(BindingContext.CLASS, literal.getObjectDeclaration()), OwnerKind.IMPLEMENTATION); + closure.cv = nameAndVisitor.getSecond(); + closure.name = nameAndVisitor.getFirst(); + final ClassContext objectContext = closure.context.intoClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION); - new ImplementationBodyCodegen(literal.getObjectDeclaration(), objectContext, nameAndVisitor.getSecond(), this).generate(); - return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("", "()V"), false); + new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(); + + ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration); + CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION); + return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature(), false); } public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index bdf2d80bc06..5dd9bf9f711 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -225,6 +225,22 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { callableMethod = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind); method = callableMethod.getSignature(); } + + int firstClosureIndex = -1; + if(context.closure != null) { + final List consArgTypes = new LinkedList(Arrays.asList(method.getArgumentTypes())); + + firstClosureIndex = consArgTypes.size()+1; + + Map closure = context.closure.closure; + for (DeclarationDescriptor descriptor : closure.keySet()) { + final Type sharedVarType = context.closure.exprContext.getSharedVarType(descriptor); + consArgTypes.add(sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType())); + } + + method = new Method("", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()])); + } + int flags = Opcodes.ACC_PUBLIC; // TODO final MethodVisitor mv = v.visitMethod(flags, "", method.getDescriptor(), null, null); mv.visitCode(); @@ -300,7 +316,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.putfield(classname, delegateField, fieldDesc); JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor); - final ClassContext delegateContext = context.intoClass(superClassDescriptor, + final ClassContext delegateContext = context.intoClass(null, superClassDescriptor, new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false), JetTypeMapper.jvmNameForInterface(superClassDescriptor))); generateDelegates(superClass, delegateContext, overridden); @@ -322,6 +338,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv); } + if(context.closure != null) { + Map closure = context.closure.closure; + int k = 0; + for (DeclarationDescriptor varDescr : closure.keySet()) { + final Type sharedVarType = context.closure.exprContext.getSharedVarType(varDescr); + iv.load(0, JetTypeMapper.TYPE_OBJECT); + iv.load(firstClosureIndex + k, StackValue.refType(sharedVarType)); + iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$" + (k+1), sharedVarType.getDescriptor()); + } + } + generateInitializers(codegen, iv); generateTraitMethods(codegen); diff --git a/idea/testData/codegen/objects/objectLiteral.jet b/idea/testData/codegen/objects/objectLiteral.jet index 1ea5a0355bc..a457840fefc 100644 --- a/idea/testData/codegen/objects/objectLiteral.jet +++ b/idea/testData/codegen/objects/objectLiteral.jet @@ -1,10 +1,17 @@ -class C() { - val child = object { - fun toString(): String = "child" +class C(x: Int, val y : Int) { + fun initChild(x: Int) : java.lang.Object { + return object : java.lang.Object() { + override fun toString(): String? { + x = x + y + return "child" + x + } + } } + + val child = initChild(x) } fun box(): String { - val c = C() - return if (c.child.toString() == "child") "OK" else "fail" + val c = C(10,3) + return if (c.child.toString() == "child13" && c.child.toString() == "child16" && c.child.toString() == "child19") "OK" else "fail" } diff --git a/idea/testData/codegen/regressions/kt344.jet b/idea/testData/codegen/regressions/kt344.jet index c551963b701..3274de6aa23 100644 --- a/idea/testData/codegen/regressions/kt344.jet +++ b/idea/testData/codegen/regressions/kt344.jet @@ -1,3 +1,4 @@ +/* fun s0() : Boolean { val y = "222" val foo = { @@ -159,8 +160,22 @@ fun t11(x: Int) : Int { } return x } +*/ +fun t12(x: Int) : Int { + var y = x + val runnable = object : Runnable { + override fun run () { + y = y + 1 + } + } + while(y < 100) { + runnable.run() + } + return y +} fun box(): String { +/* if (!s0()) return "fail" if (!s1()) return "fail" if (!t1()) return "fail" @@ -174,6 +189,8 @@ fun box(): String { if (!t9(0)) return "fail" if (!t10()) return "fail" if (t11(1) != 104) return "fail" +*/ + if (t12(0) != 100) return "fail" return "OK" } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/codegen/ObjectGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ObjectGenTest.java index 286900722d5..9980b8c9fae 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ObjectGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ObjectGenTest.java @@ -10,6 +10,7 @@ public class ObjectGenTest extends CodegenTestCase { public void testObjectLiteral() throws Exception { blackBoxFile("objects/objectLiteral.jet"); + System.out.println(generateToText()); } public void testMethodOnObject() throws Exception { diff --git a/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java b/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java index cd81cc54e01..ed9beaf4e74 100644 --- a/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java @@ -19,7 +19,7 @@ public class PropertyGenTest extends CodegenTestCase { final Class aClass = loadImplementationClass(generateClassesInFile(), "PrivateVal"); final Field[] fields = aClass.getDeclaredFields(); assertEquals(2, fields.length); // $typeInfo, prop - final Field field = fields[1]; + final Field field = fields[0]; assertEquals("prop", field.getName()); } From fa3c8b4cfeeba78df03c76eec341eaa1405221fb Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 17 Oct 2011 13:58:57 +0200 Subject: [PATCH 08/10] lazy icon loading --- .../src/org/jetbrains/jet/plugin/JetFileType.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/plugin/JetFileType.java b/compiler/frontend/src/org/jetbrains/jet/plugin/JetFileType.java index 1dcc9763674..4d9461ae798 100644 --- a/compiler/frontend/src/org/jetbrains/jet/plugin/JetFileType.java +++ b/compiler/frontend/src/org/jetbrains/jet/plugin/JetFileType.java @@ -5,13 +5,20 @@ package org.jetbrains.jet.plugin; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.NotNullLazyValue; import org.jetbrains.annotations.NotNull; import javax.swing.*; public class JetFileType extends LanguageFileType { public static final JetFileType INSTANCE = new JetFileType(); - private final Icon myIcon = IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/kotlin16x16.png"); + private final NotNullLazyValue myIcon = new NotNullLazyValue() { + @NotNull + @Override + protected Icon compute() { + return IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/kotlin16x16.png"); + } + }; private JetFileType() { super(JetLanguage.INSTANCE); @@ -33,7 +40,7 @@ public class JetFileType extends LanguageFileType { } public Icon getIcon() { - return myIcon; + return myIcon.getValue(); } @Override From 5a1bca06154df7534331e9652c9da7d767e91a80 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 17 Oct 2011 17:02:47 +0200 Subject: [PATCH 09/10] standalone compiler --- .idea/modules.xml | 1 + compiler/cli/cli.iml | 15 +++ .../org/jetbrains/jet/cli/KotlinCompiler.java | 114 ++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 compiler/cli/cli.iml create mode 100644 compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java diff --git a/.idea/modules.xml b/.idea/modules.xml index 2df90c07743..4959db82cd6 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -4,6 +4,7 @@ + diff --git a/compiler/cli/cli.iml b/compiler/cli/cli.iml new file mode 100644 index 00000000000..de82ce75e19 --- /dev/null +++ b/compiler/cli/cli.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java new file mode 100644 index 00000000000..576f436dd8d --- /dev/null +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -0,0 +1,114 @@ +package org.jetbrains.jet.cli; + +import com.google.common.collect.Lists; +import com.intellij.core.JavaCoreEnvironment; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import org.jetbrains.jet.codegen.ClassFileFactory; +import org.jetbrains.jet.codegen.GenerationState; +import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.parsing.JetParserDefinition; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetNamespace; +import org.jetbrains.jet.lang.resolve.AnalyzingUtils; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; +import org.jetbrains.jet.plugin.JetFileType; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +/** + * @author yole + */ +public class KotlinCompiler { + public static void main(String[] args) { + System.setProperty("java.awt.headless", "true"); + if (args.length < 1) { + System.out.println("Usage: KotlinCompiler "); + return; + } + String javaHome = System.getenv("JAVA_HOME"); + if (javaHome == null) { + System.out.println("JAVA_HOME environment variable needs to be defined"); + return; + } + File rtJar = findRtJar(javaHome); + if (rtJar == null || !rtJar.exists()) { + System.out.print("No rt.jar found under JAVA_HOME"); + return; + } + + Disposable root = new Disposable() { + @Override + public void dispose() { + } + }; + JavaCoreEnvironment environment = new JavaCoreEnvironment(root); + environment.addToClasspath(rtJar); + + environment.registerFileType(JetFileType.INSTANCE, "kt"); + environment.registerParserDefinition(new JetParserDefinition()); + VirtualFile vFile = environment.getLocalFileSystem().findFileByPath(args [0]); + + Project project = environment.getProject(); + GenerationState generationState = new GenerationState(project, false); + List namespaces = Lists.newArrayList(); + PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile); + if (psiFile instanceof JetFile) { + namespaces.add(((JetFile) psiFile).getRootNamespace()); + } + + BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(project, namespaces, JetControlFlowDataTraceFactory.EMPTY); + + boolean errors = false; + for (Diagnostic diagnostic : bindingContext.getDiagnostics()) { + switch (diagnostic.getSeverity()) { + case ERROR: + errors = true; + report(diagnostic); + break; + case INFO: + report(diagnostic); + break; + case WARNING: + report(diagnostic); + break; + } + } + + if (!errors) { + generationState.compileCorrectNamespaces(bindingContext, namespaces); + + final ClassFileFactory factory = generationState.getFactory(); + List files = factory.files(); + for (String file : files) { + File target = new File(vFile.getParent().getPath(), file); + try { + FileUtil.writeToFile(target, factory.asBytes(file)); + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } + } + + } + + private static void report(Diagnostic diagnostic) { + System.out.println(diagnostic.getMessage()); + } + + private static File findRtJar(String javaHome) { + File rtJar = new File(javaHome, "jre/lib/rt.jar"); + if (rtJar.exists()) { + return rtJar; + } + return null; + } +} From 3083fde2dda88949a0c80564f9a161633a02812f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 17 Oct 2011 18:01:02 +0200 Subject: [PATCH 10/10] binary distribution for Kotlin --- .idea/ant.xml | 8 +++ build.xml | 64 ++++++++++++++++++++++++ compiler/cli/bin/kotlinc | 96 ++++++++++++++++++++++++++++++++++++ compiler/cli/bin/kotlinc.bat | 51 +++++++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 build.xml create mode 100644 compiler/cli/bin/kotlinc create mode 100644 compiler/cli/bin/kotlinc.bat diff --git a/.idea/ant.xml b/.idea/ant.xml index 544e1256edb..37ffae42808 100644 --- a/.idea/ant.xml +++ b/.idea/ant.xml @@ -26,6 +26,14 @@ + + + + + + + + diff --git a/build.xml b/build.xml new file mode 100644 index 00000000000..9f10c18ad52 --- /dev/null +++ b/build.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/compiler/cli/bin/kotlinc b/compiler/cli/bin/kotlinc new file mode 100644 index 00000000000..6763c5e7605 --- /dev/null +++ b/compiler/cli/bin/kotlinc @@ -0,0 +1,96 @@ +#!/bin/bash --posix +# +############################################################################## +# Copyright 2002-2011, LAMP/EPFL +# Copyright 2011, JetBrains +# +# This is free software; see the distribution for copying conditions. +# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. +############################################################################## + +cygwin=false; +case "`uname`" in + CYGWIN*) cygwin=true ;; +esac + +# Finding the root folder for this Kotlin distribution +SOURCE=$0; +SCRIPT=`basename "$SOURCE"`; +while [ -h "$SOURCE" ]; do + SCRIPT=`basename "$SOURCE"`; + LOOKUP=`ls -ld "$SOURCE"`; + TARGET=`expr "$LOOKUP" : '.*-> \(.*\)$'`; + if expr "${TARGET:-.}/" : '/.*/$' > /dev/null; then + SOURCE=${TARGET:-.}; + else + SOURCE=`dirname "$SOURCE"`/${TARGET:-.}; + fi; +done; + +# see #2092 +KOTLIN_HOME=`dirname "$SOURCE"` +KOTLIN_HOME=`cd "$KOTLIN_HOME"; pwd -P` +KOTLIN_HOME=`cd "$KOTLIN_HOME"/..; pwd` + +# Remove spaces from KOTLIN_HOME on windows +if $cygwin; then + KOTLIN_HOME=`cygpath --windows --short-name "$KOTLIN_HOME"` + KOTLIN_HOME=`cygpath --unix "$KOTLIN_HOME"` +fi + +# Constructing the extension classpath +TOOL_CLASSPATH="" +if [ -z "$TOOL_CLASSPATH" ] ; then + for ext in "$KOTLIN_HOME"/lib/* ; do + if [ -z "$TOOL_CLASSPATH" ] ; then + TOOL_CLASSPATH="$ext" + else + TOOL_CLASSPATH="$TOOL_CLASSPATH:$ext" + fi + done +fi + +[ -n "$JAVA_OPTS" ] || JAVA_OPTS="-Xmx256M -Xms32M" + +# break out -D and -J options and add them to JAVA_OPTS as well +# so they reach the underlying JVM in time to do some good. The +# -D options will be available as system properties. +declare -a java_args +declare -a kotlin_args + +while [ $# -gt 0 ]; do + case "$1" in + -D*) + # pass to kotlin as well: otherwise we lose it sometimes when we + # need it, e.g. communicating with a server compiler. + java_args=("${java_args[@]}" "$1") + kotlin_args=("${kotlin_args[@]}" "$1") + shift + ;; + -J*) + # as with -D, pass to scala even though it will almost + # never be used. + java_args=("${java_args[@]}" "${1:2}") + kotlin_args=("${kotlin_args[@]}" "$1") + shift + ;; + *) + kotlin_args=("${kotlin_args[@]}" "$1") + shift + ;; + esac +done + +# reset "$@" to the remaining args +set -- "${kotlin_args[@]}" + +if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then + JAVACMD="$JAVA_HOME/bin/java" +fi + +"${JAVACMD:=java}" \ + $JAVA_OPTS \ + "${java_args[@]}" \ + ${CPSELECT}${TOOL_CLASSPATH} \ + org.jetbrains.jet.cli.KotlinCompiler "$@" diff --git a/compiler/cli/bin/kotlinc.bat b/compiler/cli/bin/kotlinc.bat new file mode 100644 index 00000000000..20d2e1795d8 --- /dev/null +++ b/compiler/cli/bin/kotlinc.bat @@ -0,0 +1,51 @@ +rem based on scalac.bat from the Scala distribution +rem ########################################################################## +rem # Copyright 2002-2011, LAMP/EPFL +rem # Copyright 2011, JetBrains +rem # +rem # This is free software; see the distribution for copying conditions. +rem # There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A +rem # PARTICULAR PURPOSE. +rem ########################################################################## +@echo off + +@setlocal +call :set_home + +if not "%JAVA_HOME%"=="" ( + if exist "%JAVA_HOME%\bin\java.exe" set "_JAVACMD=%JAVA_HOME%\bin\java.exe" +) + +if "%_JAVACMD%"=="" set _JAVACMD=java + +rem We use the value of the JAVA_OPTS environment variable if defined +set _JAVA_OPTS=-Xmx256M -Xms32M + +set _TOOL_CLASSPATH= +if "%_TOOL_CLASSPATH%"=="" ( + for %%f in ("%_KOTLIN_HOME%\lib\*") do call :add_cpath "%%f" + for /d %%f in ("%_KOTLIN_HOME%\lib\*") do call :add_cpath "%%f" +) + +"%_JAVACMD%" %_JAVA_OPTS% cp "%_TOOL_CLASSPATH%" org.jetbrains.jet.cli.KotlinCompiler %* +goto end + +rem ########################################################################## +rem # subroutines + +:add_cpath + if "%_TOOL_CLASSPATH%"=="" ( + set _TOOL_CLASSPATH=%~1 + ) else ( + set _TOOL_CLASSPATH=%_TOOL_CLASSPATH%;%~1 + ) +goto :eof + +:set_home + set _BIN_DIR= + for %%i in (%~sf0) do set _BIN_DIR=%_BIN_DIR%%%~dpsi + set _KOTLIN_HOME=%_BIN_DIR%.. +goto :eof + +:end +@endlocal