comparison src/luan/modules/JavaLuan.java @ 1335:e0cf0d108a77

major cleanup
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 14 Feb 2019 03:10:45 -0700
parents 25746915a241
children 8d95711f6615
comparison
equal deleted inserted replaced
1334:c88b486a9511 1335:e0cf0d108a77
20 import luan.Luan; 20 import luan.Luan;
21 import luan.LuanTable; 21 import luan.LuanTable;
22 import luan.LuanException; 22 import luan.LuanException;
23 import luan.LuanFunction; 23 import luan.LuanFunction;
24 import luan.LuanJavaFunction; 24 import luan.LuanJavaFunction;
25 import luan.LuanCloner;
25 26
26 27
27 public final class JavaLuan { 28 public final class JavaLuan {
28 29
29 public static void java(Luan luan) throws LuanException { 30 public static void java(Luan luan) throws LuanException {
30 Luan.checkSecurity(luan,"java"); 31 Luan.checkSecurity(luan,"java");
31 luan.peek().javaOk = true; 32 luan.peek().javaOk = true;
32 } 33 }
33 34
34 public static final LuanFunction javaFn; 35 public static LuanFunction javaFn(Luan luan) {
35 static { 36 LuanFunction fn = (LuanFunction)luan.registry().get("JavaLuan.java");
36 try { 37 if( fn == null ) {
37 javaFn = new LuanJavaFunction(JavaLuan.class.getMethod("java",Luan.class),null); 38 try {
38 } catch(NoSuchMethodException e) { 39 fn = new LuanJavaFunction(luan,JavaLuan.class.getMethod("java",Luan.class),null);
39 throw new RuntimeException(e); 40 } catch(NoSuchMethodException e) {
40 } 41 throw new RuntimeException(e);
42 }
43 luan.registry().put("JavaLuan.java",fn);
44 }
45 return fn;
41 } 46 }
42 47
43 private static void checkJava(Luan luan) throws LuanException { 48 private static void checkJava(Luan luan) throws LuanException {
44 if( !luan.peek().javaOk ) 49 if( !luan.peek().javaOk )
45 throw new LuanException("Java isn't allowed"); 50 throw new LuanException("Java isn't allowed");
57 return cls; 62 return cls;
58 } else if( "new".equals(name) ) { 63 } else if( "new".equals(name) ) {
59 Constructor[] constructors = cls.getConstructors(); 64 Constructor[] constructors = cls.getConstructors();
60 if( constructors.length > 0 ) { 65 if( constructors.length > 0 ) {
61 if( constructors.length==1 ) { 66 if( constructors.length==1 ) {
62 return new LuanJavaFunction(constructors[0],null); 67 return new LuanJavaFunction(luan,constructors[0],null);
63 } else { 68 } else {
64 List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>(); 69 List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>();
65 for( Constructor constructor : constructors ) { 70 for( Constructor constructor : constructors ) {
66 fns.add(new LuanJavaFunction(constructor,null)); 71 fns.add(new LuanJavaFunction(luan,constructor,null));
67 } 72 }
68 return new AmbiguousJavaFunction(fns); 73 return new AmbiguousJavaFunction(fns);
69 } 74 }
70 } 75 }
71 /* 76 /*
72 } else if( "assert".equals(name) ) { 77 } else if( "assert".equals(name) ) {
73 return new LuanJavaFunction(assertClass,new AssertClass(cls)); 78 return new LuanJavaFunction(assertClass,new AssertClass(cls));
74 */ 79 */
75 } else if( "luan_proxy".equals(name) ) { 80 } else if( "luan_proxy".equals(name) ) {
76 return new LuanJavaFunction(luan_proxyMethod,st); 81 return new LuanJavaFunction(luan,luan_proxyMethod,st);
77 } else { 82 } else {
78 List<Member> members = getStaticMembers(cls,name); 83 List<Member> members = getStaticMembers(cls,name);
79 if( !members.isEmpty() ) { 84 if( !members.isEmpty() ) {
80 return member(null,members); 85 return member(luan,null,members);
81 } 86 }
82 } 87 }
83 } 88 }
84 } else { 89 } else {
85 cls = obj.getClass(); 90 cls = obj.getClass();
93 } 98 }
94 // throw new LuanException(luan,"invalid member '"+key+"' for java array: "+obj); 99 // throw new LuanException(luan,"invalid member '"+key+"' for java array: "+obj);
95 } else if( key instanceof String ) { 100 } else if( key instanceof String ) {
96 String name = (String)key; 101 String name = (String)key;
97 if( "instanceof".equals(name) ) { 102 if( "instanceof".equals(name) ) {
98 return new LuanJavaFunction(instanceOf,new InstanceOf(obj)); 103 return new LuanJavaFunction(luan,instanceOf,new InstanceOf(obj));
99 } else { 104 } else {
100 List<Member> members = getMembers(cls,name); 105 List<Member> members = getMembers(cls,name);
101 if( !members.isEmpty() ) { 106 if( !members.isEmpty() ) {
102 return member(obj,members); 107 return member(luan,obj,members);
103 } 108 }
104 } 109 }
105 } 110 }
106 } 111 }
107 //System.out.println("invalid member '"+key+"' for java object: "+obj); 112 //System.out.println("invalid member '"+key+"' for java object: "+obj);
108 throw new LuanException( "invalid index '"+key+"' for java "+cls ); 113 throw new LuanException( "invalid index '"+key+"' for java "+cls );
109 } 114 }
110 115
111 private static Object member(Object obj,List<Member> members) throws LuanException { 116 private static Object member(Luan luan,Object obj,List<Member> members) throws LuanException {
112 try { 117 try {
113 if( members.size()==1 ) { 118 if( members.size()==1 ) {
114 Member member = members.get(0); 119 Member member = members.get(0);
115 if( member instanceof Static ) { 120 if( member instanceof Static ) {
116 return member; 121 return member;
118 Field field = (Field)member; 123 Field field = (Field)member;
119 Object rtn = field.get(obj); 124 Object rtn = field.get(obj);
120 return rtn instanceof Object[] ? Arrays.asList((Object[])rtn) : rtn; 125 return rtn instanceof Object[] ? Arrays.asList((Object[])rtn) : rtn;
121 } else { 126 } else {
122 Method method = (Method)member; 127 Method method = (Method)member;
123 return new LuanJavaFunction(method,obj); 128 return new LuanJavaFunction(luan,method,obj);
124 } 129 }
125 } else { 130 } else {
126 List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>(); 131 List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>();
127 for( Member member : members ) { 132 for( Member member : members ) {
128 Method method = (Method)member; 133 Method method = (Method)member;
129 fns.add(new LuanJavaFunction(method,obj)); 134 fns.add(new LuanJavaFunction(luan,method,obj));
130 } 135 }
131 return new AmbiguousJavaFunction(fns); 136 return new AmbiguousJavaFunction(fns);
132 } 137 }
133 } catch(IllegalAccessException e) { 138 } catch(IllegalAccessException e) {
134 throw new RuntimeException(e); 139 throw new RuntimeException(e);
307 312
308 @Override public boolean isSynthetic() { 313 @Override public boolean isSynthetic() {
309 return cls.isSynthetic(); 314 return cls.isSynthetic();
310 } 315 }
311 316
312 public Object luan_proxy(final Luan luan,final LuanTable t) throws LuanException { 317 public Object luan_proxy(final LuanTable t) throws LuanException {
313 return Proxy.newProxyInstance( 318 return Proxy.newProxyInstance(
314 cls.getClassLoader(), 319 cls.getClassLoader(),
315 new Class[]{cls}, 320 new Class[]{cls},
316 new InvocationHandler() { 321 new InvocationHandler() {
317 public Object invoke(Object proxy,Method method, Object[] args) 322 public Object invoke(Object proxy,Method method, Object[] args)
322 String name = method.getName(); 327 String name = method.getName();
323 Object fnObj = t.get(name); 328 Object fnObj = t.get(name);
324 if( fnObj == null ) 329 if( fnObj == null )
325 throw new NullPointerException("luan_proxy couldn't find method '"+name+"'"); 330 throw new NullPointerException("luan_proxy couldn't find method '"+name+"'");
326 LuanFunction fn = Luan.checkFunction(fnObj); 331 LuanFunction fn = Luan.checkFunction(fnObj);
327 return Luan.first(fn.call(luan,args)); 332 return Luan.first(fn.call(args));
328 } 333 }
329 } 334 }
330 ); 335 );
331 } 336 }
332 } 337 }
333 private static final Method luan_proxyMethod; 338 private static final Method luan_proxyMethod;
334 static { 339 static {
335 try { 340 try {
336 luan_proxyMethod = Static.class.getMethod("luan_proxy",Luan.class,LuanTable.class); 341 luan_proxyMethod = Static.class.getMethod("luan_proxy",LuanTable.class);
337 luan_proxyMethod.setAccessible(true); 342 luan_proxyMethod.setAccessible(true);
338 } catch(NoSuchMethodException e) { 343 } catch(NoSuchMethodException e) {
339 throw new RuntimeException(e); 344 throw new RuntimeException(e);
340 } 345 }
341 } 346 }
359 public int compare(LuanJavaFunction fn1,LuanJavaFunction fn2) { 364 public int compare(LuanJavaFunction fn1,LuanJavaFunction fn2) {
360 return fn2.getParameterCount() - fn1.getParameterCount(); 365 return fn2.getParameterCount() - fn1.getParameterCount();
361 } 366 }
362 }; 367 };
363 368
364 private static class AmbiguousJavaFunction extends LuanFunction { 369 private static final class AmbiguousJavaFunction extends LuanFunction {
365 private final Map<Integer,List<LuanJavaFunction>> fnMap = new HashMap<Integer,List<LuanJavaFunction>>(); 370 private Map<Integer,List<LuanJavaFunction>> fnMap = new HashMap<Integer,List<LuanJavaFunction>>();
366 private List<LuanJavaFunction> varArgs = new ArrayList<LuanJavaFunction>(); 371 private List<LuanJavaFunction> varArgs = new ArrayList<LuanJavaFunction>();
367 372
368 AmbiguousJavaFunction(List<LuanJavaFunction> fns) { 373 AmbiguousJavaFunction(List<LuanJavaFunction> fns) {
374 super(true);
369 for( LuanJavaFunction fn : fns ) { 375 for( LuanJavaFunction fn : fns ) {
370 if( fn.isVarArgs() ) { 376 if( fn.isVarArgs() ) {
371 varArgs.add(fn); 377 varArgs.add(fn);
372 } else { 378 } else {
373 Integer n = fn.getParameterCount(); 379 Integer n = fn.getParameterCount();
380 } 386 }
381 } 387 }
382 Collections.sort(varArgs,varArgsSorter); 388 Collections.sort(varArgs,varArgsSorter);
383 } 389 }
384 390
385 @Override public Object call(Luan luan,Object[] args) throws LuanException { 391 @Override protected void completeClone(LuanFunction dc,LuanCloner cloner) {
392 AmbiguousJavaFunction clone = (AmbiguousJavaFunction)dc;
393 clone.fnMap = (Map)cloner.clone(fnMap);
394 clone.varArgs = (List)cloner.clone(varArgs);
395 }
396
397 @Override public Object call(Object[] args) throws LuanException {
386 List<LuanJavaFunction> list = fnMap.get(args.length); 398 List<LuanJavaFunction> list = fnMap.get(args.length);
387 if( list != null ) { 399 if( list != null ) {
388 for( LuanJavaFunction fn : list ) { 400 for( LuanJavaFunction fn : list ) {
389 try { 401 try {
390 return fn.rawCall(luan,args); 402 return fn.rawCall(args);
391 } catch(IllegalArgumentException e) {} 403 } catch(IllegalArgumentException e) {}
392 } 404 }
393 } 405 }
394 for( LuanJavaFunction fn : varArgs ) { 406 for( LuanJavaFunction fn : varArgs ) {
395 try { 407 try {
396 return fn.rawCall(luan,args); 408 return fn.rawCall(args);
397 } catch(IllegalArgumentException e) {} 409 } catch(IllegalArgumentException e) {}
398 } 410 }
399 throw new LuanException("no method matched args: "+Arrays.asList(args)); 411 throw new LuanException("no method matched args: "+Arrays.asList(args));
400 } 412 }
401 } 413 }