module compiler: initial working version

This commit is contained in:
Dmitry Jemerov
2011-10-31 13:35:18 +01:00
parent 344dea0ad5
commit b39ea7a876
8 changed files with 121 additions and 35 deletions
+1
View File
@@ -29,6 +29,7 @@
<target name="jarRT" depends="compileRT">
<jar destfile="${output}/kotlin-runtime.jar">
<fileset dir="${output}/classes/runtime"/>
<fileset dir="${basedir}/stdlib/ktSrc"/>
</jar>
</target>
@@ -0,0 +1,23 @@
package org.jetbrains.jet.codegen;
/**
* @author yole
*/
public class GeneratedClassLoader extends ClassLoader {
private final ClassFileFactory state;
public GeneratedClassLoader(ClassFileFactory state) {
super(GeneratedClassLoader.class.getClassLoader());
this.state = state;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String file = name.replace('.', '/') + ".class";
if (state.files().contains(file)) {
byte[] bytes = state.asBytes(file);
return defineClass(name, bytes, 0, bytes.length);
}
return super.findClass(name);
}
}
+1
View File
@@ -10,6 +10,7 @@
<orderEntry type="module" module-name="backend" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="module" module-name="frontend.java" />
<orderEntry type="module" module-name="stdlib" />
</component>
</module>
@@ -2,14 +2,16 @@ package org.jetbrains.jet.cli;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
import com.sampullara.cli.Args;
import com.sampullara.cli.Argument;
import jet.modules.IModuleBuilder;
import jet.modules.IModuleSetBuilder;
import org.jetbrains.jet.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GeneratedClassLoader;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.plugin.JetMainDetector;
@@ -17,6 +19,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
@@ -66,9 +69,19 @@ public class KotlinCompiler {
if (unpackedRuntimePath != null) {
environment.addToClasspath(unpackedRuntimePath);
}
else {
final File runtimeJarPath = getRuntimeJarPath();
if (runtimeJarPath != null && runtimeJarPath.exists()) {
environment.addToClasspath(runtimeJarPath);
}
else {
System.out.println("No runtime library found");
return;
}
}
if (arguments.module != null) {
compileModule(environment, arguments.module);
compileModuleScript(environment, arguments.module);
return;
}
@@ -98,30 +111,82 @@ public class KotlinCompiler {
}
}
private static void compileModule(JetCoreEnvironment environment, String moduleFile) {
final FileIndexFacade instance = FileIndexFacade.getInstance(environment.getProject());
VirtualFile jetObject = environment.getLocalFileSystem().findFileByPath(KotlinCompiler.class.getClassLoader().getResource("jet/JetObject.class").getPath());
instance.isInLibraryClasses(jetObject);
CompileSession moduleCompileSession = new CompileSession(environment);
moduleCompileSession.addSources(moduleFile);
private static void compileModuleScript(JetCoreEnvironment environment, String moduleFile) {
CompileSession scriptCompileSession = new CompileSession(environment);
scriptCompileSession.addSources(moduleFile);
URL url = KotlinCompiler.class.getClassLoader().getResource("ModuleBuilder.kt");
if (url != null) {
// TODO
String path = url.getPath();
if (path.startsWith("file:")) {
path = path.substring(5);
}
final VirtualFile vFile = environment.getJarFileSystem().findFileByPath(path);
if (vFile == null) {
System.out.println("Couldn't load ModuleBuilder.kt from runtime jar: "+ url);
return;
}
scriptCompileSession.addSources(vFile);
}
else {
// building from source
final String homeDirectory = getHomeDirectory();
final File file = new File(homeDirectory, "stdlib/ktSrc/ModuleBuilder.kt");
moduleCompileSession.addSources(environment.getLocalFileSystem().findFileByPath(file.getPath()));
scriptCompileSession.addSources(environment.getLocalFileSystem().findFileByPath(file.getPath()));
}
if (!scriptCompileSession.analyze()) {
return;
}
final ClassFileFactory factory = scriptCompileSession.generate();
final IModuleSetBuilder moduleSetBuilder = runDefineModules(moduleFile, factory);
for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) {
compileModule(environment, moduleBuilder, new File(moduleFile).getParent());
}
}
private static IModuleSetBuilder runDefineModules(String moduleFile, ClassFileFactory factory) {
GeneratedClassLoader loader = new GeneratedClassLoader(factory);
try {
Class moduleSetBuilderClass = loader.loadClass("kotlin.modules.ModuleSetBuilder");
final IModuleSetBuilder moduleSetBuilder = (IModuleSetBuilder) moduleSetBuilderClass.newInstance();
Class namespaceClass = loader.loadClass("namespace");
final Method[] methods = namespaceClass.getMethods();
boolean modulesDefined = false;
for (Method method : methods) {
if (method.getName().equals("defineModules")) {
method.invoke(null, moduleSetBuilder);
modulesDefined = true;
break;
}
}
if (!modulesDefined) {
System.out.println("Module script " + moduleFile + " must define a defineModules() method");
return null;
}
return moduleSetBuilder;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static void compileModule(JetCoreEnvironment environment, IModuleBuilder moduleBuilder, String directory) {
CompileSession moduleCompileSession = new CompileSession(environment);
for (String sourceFile : moduleBuilder.getSourceFiles()) {
moduleCompileSession.addSources(new File(directory, sourceFile).getPath());
}
for (String classpathRoot : moduleBuilder.getClasspathRoots()) {
environment.addToClasspath(new File(classpathRoot));
}
if (!moduleCompileSession.analyze()) {
return;
}
final ClassFileFactory factory = moduleCompileSession.generate();
ClassFileFactory factory = moduleCompileSession.generate();
writeToJar(factory, new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(), null, true);
}
private static String getHomeDirectory() {
@@ -88,7 +88,7 @@ public abstract class CodegenTestCase extends JetLiteFixture {
protected String blackBox() throws Exception {
ClassFileFactory codegens = generateClassesInFile();
CodegensClassLoader loader = new CodegensClassLoader(codegens);
GeneratedClassLoader loader = new GeneratedClassLoader(codegens);
final JetNamespace namespace = myFile.getRootNamespace();
String fqName = NamespaceCodegen.getJVMClassName(namespace.getFQName()).replace("/", ".");
@@ -215,23 +215,4 @@ public abstract class CodegenTestCase extends JetLiteFixture {
return super.loadClass(name);
}
}
private static class CodegensClassLoader extends ClassLoader {
private final ClassFileFactory state;
public CodegensClassLoader(ClassFileFactory state) {
super(CodegenTestCase.class.getClassLoader());
this.state = state;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String file = name.replace('.', '/') + ".class";
if (state.files().contains(file)) {
byte[] bytes = state.asBytes(file);
return defineClass(name, bytes, 0, bytes.length);
}
return super.findClass(name);
}
}
}
+6 -2
View File
@@ -5,13 +5,16 @@ namespace modules {
import java.util.*
import jet.modules.*
class ModuleSetBuilder() {
val modules: ArrayList<ModuleBuilder> = ArrayList<ModuleBuilder>()
class ModuleSetBuilder(): IModuleSetBuilder {
val modules: ArrayList<IModuleBuilder?> = ArrayList<IModuleBuilder?>()
fun module(name: String, callback: fun ModuleBuilder.()) {
val builder = ModuleBuilder(name)
builder.callback()
modules.add(builder)
}
override fun getModules(): List<IModuleBuilder?>? = modules
}
class SourcesBuilder(val parent: ModuleBuilder) {
@@ -46,6 +49,7 @@ class ModuleBuilder(val name: String): IModuleBuilder {
override fun getSourceFiles(): List<String?>? = sourceFiles
override fun getClasspathRoots(): List<String?>? = classpathRoots
override fun getModuleName(): String? = name
}
}
@@ -6,6 +6,7 @@ import java.util.List;
* @author yole
*/
public interface IModuleBuilder {
String getModuleName();
List<String> getSourceFiles();
List<String> getClasspathRoots();
}
@@ -0,0 +1,10 @@
package jet.modules;
import java.util.List;
/**
* @author yole
*/
public interface IModuleSetBuilder {
List<IModuleBuilder> getModules();
}