Mercurial Hosting > luan
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 } |