X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fjagi%2Ffs%2FCompiler.java;h=2f0d81ce512bf83c17ac086b5466f7fc00e6cd96;hb=d7e59902e059954a7f764c8b09da2dff76bc5ee4;hp=e7a66a19a1e43c7530f74aae7c534102c32a94fe;hpb=2be6677a7e36d486834ae804d5db08aaea7e32a6;p=jagi.git diff --git a/src/jagi/fs/Compiler.java b/src/jagi/fs/Compiler.java index e7a66a1..2f0d81c 100644 --- a/src/jagi/fs/Compiler.java +++ b/src/jagi/fs/Compiler.java @@ -3,12 +3,15 @@ package jagi.fs; import jagi.*; import java.util.*; import java.util.regex.*; +import java.util.logging.*; import java.nio.file.*; import java.nio.file.attribute.*; import java.io.*; import java.net.*; public class Compiler { + private static final Logger log = Logger.getLogger("jagi-fs"); + private static final Path cwd = Paths.get("").toAbsolutePath(); private final Map files = new HashMap<>(); private final Map libs = new HashMap<>(); private final Collection searchpath = new ArrayList<>(); @@ -84,15 +87,17 @@ public class Compiler { } public static class Compilation implements AutoCloseable { - public final Path dir, srcdir, outdir; + public final Path dir, srcdir, outdir, libdir; private final List infiles = new ArrayList<>(); private final List classpath = new ArrayList<>(); private List output = null; + private boolean haslib; public Compilation() throws IOException { dir = Files.createTempDirectory("javac"); srcdir = dir.resolve("src"); outdir = dir.resolve("out"); + libdir = dir.resolve("lib"); Files.createDirectory(srcdir); Files.createDirectory(outdir); } @@ -105,6 +110,32 @@ public class Compiler { classpath.add(p); } + public void addlib(String clnm, byte[] contents) throws IOException { + if(!haslib) { + Files.createDirectory(libdir); + classpath(libdir); + haslib = true; + } + Path p = libdir; + int p1 = 0; + while(true) { + int p2 = clnm.indexOf('.', p1); + if(p2 < 0) + break; + p = p.resolve(clnm.substring(p1, p2)); + if(!Files.isDirectory(p)) + Files.createDirectory(p); + p1 = p2 + 1; + } + p = p.resolve(clnm.substring(p1) + ".class"); + Files.write(p, contents); + } + + public void addlib(Map classes) throws IOException { + for(Map.Entry ent : classes.entrySet()) + addlib(ent.getKey(), ent.getValue()); + } + public boolean compile() throws IOException { List args = new ArrayList<>(); args.add("javac"); @@ -235,6 +266,12 @@ public class Compiler { } private Path findlib(String nm) { + try { + Path p = Paths.get(nm); + if(Files.isRegularFile(p)) + return(p); + } catch(InvalidPathException e) { + } for(Path dir : searchpath) { Path jar = dir.resolve(nm + ".jar"); if(Files.isRegularFile(jar)) @@ -245,10 +282,12 @@ public class Compiler { private static final Pattern classpat = Pattern.compile("^((public|abstract)\\s+)*(class|interface)\\s+(\\S+)"); private static final Pattern libpat = Pattern.compile("\\$use\\s*:\\s*(\\S+)"); + private static final Pattern incpat = Pattern.compile("\\$include\\s*:\\s*(\\S+)"); public class Module { public final Path file; - public final ClassLoader code; + public final BufferedClassLoader code; public final Collection classpath = new ArrayList<>(); + public final Collection include = new ArrayList<>(); public Module(Path file) throws IOException { this.file = file; @@ -259,10 +298,12 @@ public class Compiler { if(!c.compile()) throw(new CompilationException(file, c.output())); ClassLoader parent = Compiler.class.getClassLoader(); - if(!classpath.isEmpty()) { + if(!classpath.isEmpty() || !include.isEmpty()) { Collection libs = new ArrayList<>(); for(Path cp : classpath) libs.add(libloader(cp)); + for(Module mod : include) + libs.add(mod.code); parent = new LibClassLoader(parent, libs); } code = new BufferedClassLoader(parent, c.classes()); @@ -281,6 +322,26 @@ public class Compiler { throw(new CompilationException(file, Arrays.asList("no such library: " + m.group(1)))); classpath.add(lib); } + m = incpat.matcher(ln); + if(m.find()) { + String nm = m.group(1); + File f= null; + if(f == null) { + Path p = file.resolveSibling(nm); + if(Files.isRegularFile(p)) + f = file(p); + } + if(f == null) { + Path p = cwd.resolve(nm); + if(Files.isRegularFile(p)) + f = file(p); + } + if(f == null) + throw(new CompilationException(file, Arrays.asList("no such file to include: " + nm))); + f.update(); + c.addlib(f.mod().code.contents); + include.add(f.mod()); + } m = classpat.matcher(ln); if(m.find()) { String clnm = m.group(4); @@ -317,8 +378,16 @@ public class Compiler { synchronized(this) { FileTime mtime = Files.getLastModifiedTime(name); if((this.mtime == null) || (this.mtime.compareTo(mtime) < 0)) { - mod = new Module(name); + Module pmod = this.mod; + this.mod = new Module(name); this.mtime = mtime; + if(pmod instanceof AutoCloseable) { + try { + ((AutoCloseable)pmod).close(); + } catch(Exception e) { + log.log(Level.WARNING, String.format("Error when disposing updated module %s", pmod.file), e); + } + } } } }