Mercurial Hosting > luan
changeset 1243:3ffc7c4a3b85
improve Thread.global_callable to allow passing of safe tables
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 05 Jul 2018 00:04:30 -0600 |
parents | ce3279ef1bd9 |
children | d1911842c2be |
files | src/luan/modules/ThreadLuan.java |
diffstat | 1 files changed, 41 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
diff -r ce3279ef1bd9 -r 3ffc7c4a3b85 src/luan/modules/ThreadLuan.java --- a/src/luan/modules/ThreadLuan.java Mon Jun 25 19:34:52 2018 -0600 +++ b/src/luan/modules/ThreadLuan.java Thu Jul 05 00:04:30 2018 -0600 @@ -117,16 +117,43 @@ } - private static boolean isPrimitive(Object v) { - if( v instanceof Object[] ) { + private static class Unsafe { + private final String reason; + + Unsafe(String reason) { + this.reason = reason; + } + } + + private static Object makeSafe(Object v) { + if( v instanceof LuanTable ) { + LuanTable tbl = (LuanTable)v; + if( tbl.getMetatable() != null ) + return new Unsafe("table with metatable"); + LuanTable rtn = new LuanTable(); + for( Map.Entry entry : tbl.rawIterable() ) { + Object key = makeSafe( entry.getKey() ); + if( key instanceof Unsafe ) + return key; + Object value = makeSafe( entry.getValue() ); + if( value instanceof Unsafe ) + return value; + rtn.rawPut(key,value); + } + return rtn; + } else if( v instanceof Object[] ) { Object[] a = (Object[])v; - for( Object obj : a ) { - if( !isPrimitive(obj) ) - return false; + for( int i=0; i<a.length; i++ ) { + Object obj = makeSafe(a[i]); + if( obj instanceof Unsafe ) + return obj; + a[i] = obj; } - return true; + return a; } else { - return v==null || v instanceof String || v instanceof Boolean || v instanceof Number; + if( v==null || v instanceof String || v instanceof Boolean || v instanceof Number ) + return v; + return new Unsafe("type "+Luan.type(v)); } } @@ -141,8 +168,10 @@ } public synchronized Object call(String fnName,Object... args) throws LuanException { - if( !isPrimitive(args) ) - throw new LuanException("can't pass non-primitive type to global_callable "+Arrays.asList(args)); + Object obj = makeSafe(args); + if( obj instanceof Unsafe ) + throw new LuanException("can't pass "+((Unsafe)obj).reason+" to global_callable "+Arrays.asList(args)); + args = (Object[])obj; Object f = fns.get(luan,fnName); if( f == null ) throw new LuanException("function '"+fnName+"' not found in global_callable"); @@ -150,8 +179,9 @@ throw new LuanException("value of '"+fnName+"' not a function in global_callable"); LuanFunction fn = (LuanFunction)f; Object rtn = fn.call(luan,args); - if( !isPrimitive(rtn) ) - throw new LuanException("can't return non-primitive type from global_callable"); + rtn = makeSafe(rtn); + if( rtn instanceof Unsafe ) + throw new LuanException("can't return "+((Unsafe)rtn).reason+" from global_callable"); return rtn; } }