Mercurial Hosting > luan
annotate src/luan/impl/LuanJavaCompiler.java @ 1392:002152af497a
hosted postgres
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 06 Sep 2019 00:19:47 -0600 |
parents | 1a68fc55a80c |
children |
rev | line source |
---|---|
648
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
1 package luan.impl; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
2 |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
3 import java.io.OutputStream; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
4 import java.io.ByteArrayOutputStream; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
5 import java.io.StringWriter; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
6 import java.io.IOException; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
7 import java.net.URI; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
8 import java.util.Collections; |
665 | 9 import java.util.Map; |
10 import java.util.HashMap; | |
648
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
11 import javax.tools.FileObject; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
12 import javax.tools.JavaFileObject; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
13 import javax.tools.SimpleJavaFileObject; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
14 import javax.tools.JavaCompiler; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
15 import javax.tools.ToolProvider; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
16 import javax.tools.JavaFileManager; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
17 import javax.tools.StandardJavaFileManager; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
18 import javax.tools.ForwardingJavaFileManager; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
19 |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
20 |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
21 public final class LuanJavaCompiler { |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
22 private LuanJavaCompiler() {} // never |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
23 |
665 | 24 private static class MyJavaFileObject extends SimpleJavaFileObject { |
25 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
26 | |
27 MyJavaFileObject() { | |
28 super(URI.create("whatever"),JavaFileObject.Kind.CLASS); | |
29 } | |
30 | |
31 @Override public OutputStream openOutputStream() { | |
32 return baos; | |
33 } | |
34 | |
35 byte[] byteCode(String sourceName) { | |
36 byte[] byteCode = baos.toByteArray(); | |
37 final int len = sourceName.length(); | |
38 int max = byteCode.length-len-3; | |
39 outer: | |
40 for( int i=0; true; i++ ) { | |
41 if( i > max ) | |
42 throw new RuntimeException("len="+len); | |
43 if( byteCode[i]==1 && (byteCode[i+1] << 8 | 0xFF & byteCode[i+2]) == len ) { | |
44 for( int j=i+3; j<i+3+len; j++ ) { | |
45 if( byteCode[j] != '$' ) | |
46 continue outer; | |
47 } | |
48 System.arraycopy(sourceName.getBytes(),0,byteCode,i+3,len); | |
49 break; | |
50 } | |
51 } | |
52 return byteCode; | |
53 } | |
54 } | |
55 | |
648
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
56 public static Class compile(final String className,final String sourceName,final String code) throws ClassNotFoundException { |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
57 final int len = sourceName.length(); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
58 StringBuilder sb = new StringBuilder(sourceName); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
59 for( int i=0; i<len; i++ ) |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
60 sb.setCharAt(i,'$'); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
61 JavaFileObject sourceFile = new SimpleJavaFileObject(URI.create(sb.toString()),JavaFileObject.Kind.SOURCE) { |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
62 @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
63 return code; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
64 } |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
65 @Override public String getName() { |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
66 return sourceName; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
67 } |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
68 @Override public boolean isNameCompatible(String simpleName,JavaFileObject.Kind kind) { |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
69 return true; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
70 } |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
71 }; |
665 | 72 final Map<String,MyJavaFileObject> map = new HashMap<String,MyJavaFileObject>(); |
648
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
73 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
74 StandardJavaFileManager sjfm = compiler.getStandardFileManager(null,null,null); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
75 ForwardingJavaFileManager fjfm = new ForwardingJavaFileManager(sjfm) { |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
76 @Override public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { |
665 | 77 if( map.containsKey(className) ) |
78 throw new RuntimeException(className); | |
79 MyJavaFileObject classFile = new MyJavaFileObject(); | |
80 map.put(className,classFile); | |
648
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
81 return classFile; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
82 } |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
83 }; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
84 StringWriter out = new StringWriter(); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
85 boolean b = compiler.getTask(out, fjfm, null, null, null, Collections.singletonList(sourceFile)).call(); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
86 if( !b ) |
652
067d9470184d
compile SetStmt and ForStmt
Franklin Schmidt <fschmidt@gmail.com>
parents:
650
diff
changeset
|
87 throw new RuntimeException("\n"+out+"\ncode:\n"+code+"\n"); |
648
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
88 ClassLoader cl = new ClassLoader() { |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
89 @Override protected Class<?> findClass(String name) throws ClassNotFoundException { |
665 | 90 MyJavaFileObject jfo = map.get(name); |
91 if( jfo != null ) { | |
92 byte[] byteCode = jfo.byteCode(sourceName); | |
648
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
93 return defineClass(name, byteCode, 0, byteCode.length); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
94 } |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
95 return super.findClass(name); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
96 } |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
97 }; |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
98 return cl.loadClass(className); |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
99 } |
e387e4021afe
start compiler with len operator
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
100 } |