annotate core/src/luan/impl/LuanJavaCompiler.java @ 665:41f8fdbc3a0a

compile modules
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 07 Apr 2016 17:06:22 -0600
parents e038905512d3
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
9 import java.util.Map;
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
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
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
24 private static class MyJavaFileObject extends SimpleJavaFileObject {
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
25 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
26
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
27 MyJavaFileObject() {
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
28 super(URI.create("whatever"),JavaFileObject.Kind.CLASS);
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
29 }
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
30
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
31 @Override public OutputStream openOutputStream() {
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
32 return baos;
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
33 }
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
34
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
35 byte[] byteCode(String sourceName) {
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
36 byte[] byteCode = baos.toByteArray();
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
37 final int len = sourceName.length();
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
38 int max = byteCode.length-len-3;
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
39 outer:
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
40 for( int i=0; true; i++ ) {
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
41 if( i > max )
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
42 throw new RuntimeException("len="+len);
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
43 if( byteCode[i]==1 && (byteCode[i+1] << 8 | 0xFF & byteCode[i+2]) == len ) {
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
44 for( int j=i+3; j<i+3+len; j++ ) {
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
45 if( byteCode[j] != '$' )
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
46 continue outer;
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
47 }
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
48 System.arraycopy(sourceName.getBytes(),0,byteCode,i+3,len);
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
49 break;
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
50 }
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
51 }
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
52 return byteCode;
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
53 }
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
54 }
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
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
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
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
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
77 if( map.containsKey(className) )
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
78 throw new RuntimeException(className);
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
79 MyJavaFileObject classFile = new MyJavaFileObject();
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
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
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
90 MyJavaFileObject jfo = map.get(name);
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
91 if( jfo != null ) {
41f8fdbc3a0a compile modules
Franklin Schmidt <fschmidt@gmail.com>
parents: 658
diff changeset
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 }