comparison src/luan/modules/ThreadLuan.java @ 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 d3a3ca116e42
children 9fa8b8389578
comparison
equal deleted inserted replaced
1242:ce3279ef1bd9 1243:3ffc7c4a3b85
115 public static void sleep(long millis) throws InterruptedException { 115 public static void sleep(long millis) throws InterruptedException {
116 Thread.sleep(millis); 116 Thread.sleep(millis);
117 } 117 }
118 118
119 119
120 private static boolean isPrimitive(Object v) { 120 private static class Unsafe {
121 if( v instanceof Object[] ) { 121 private final String reason;
122
123 Unsafe(String reason) {
124 this.reason = reason;
125 }
126 }
127
128 private static Object makeSafe(Object v) {
129 if( v instanceof LuanTable ) {
130 LuanTable tbl = (LuanTable)v;
131 if( tbl.getMetatable() != null )
132 return new Unsafe("table with metatable");
133 LuanTable rtn = new LuanTable();
134 for( Map.Entry entry : tbl.rawIterable() ) {
135 Object key = makeSafe( entry.getKey() );
136 if( key instanceof Unsafe )
137 return key;
138 Object value = makeSafe( entry.getValue() );
139 if( value instanceof Unsafe )
140 return value;
141 rtn.rawPut(key,value);
142 }
143 return rtn;
144 } else if( v instanceof Object[] ) {
122 Object[] a = (Object[])v; 145 Object[] a = (Object[])v;
123 for( Object obj : a ) { 146 for( int i=0; i<a.length; i++ ) {
124 if( !isPrimitive(obj) ) 147 Object obj = makeSafe(a[i]);
125 return false; 148 if( obj instanceof Unsafe )
126 } 149 return obj;
127 return true; 150 a[i] = obj;
151 }
152 return a;
128 } else { 153 } else {
129 return v==null || v instanceof String || v instanceof Boolean || v instanceof Number; 154 if( v==null || v instanceof String || v instanceof Boolean || v instanceof Number )
155 return v;
156 return new Unsafe("type "+Luan.type(v));
130 } 157 }
131 } 158 }
132 159
133 public static final class Callable { 160 public static final class Callable {
134 private long expires; 161 private long expires;
139 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); 166 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
140 this.fns = (LuanTable)cloner.get(fns); 167 this.fns = (LuanTable)cloner.get(fns);
141 } 168 }
142 169
143 public synchronized Object call(String fnName,Object... args) throws LuanException { 170 public synchronized Object call(String fnName,Object... args) throws LuanException {
144 if( !isPrimitive(args) ) 171 Object obj = makeSafe(args);
145 throw new LuanException("can't pass non-primitive type to global_callable "+Arrays.asList(args)); 172 if( obj instanceof Unsafe )
173 throw new LuanException("can't pass "+((Unsafe)obj).reason+" to global_callable "+Arrays.asList(args));
174 args = (Object[])obj;
146 Object f = fns.get(luan,fnName); 175 Object f = fns.get(luan,fnName);
147 if( f == null ) 176 if( f == null )
148 throw new LuanException("function '"+fnName+"' not found in global_callable"); 177 throw new LuanException("function '"+fnName+"' not found in global_callable");
149 if( !(f instanceof LuanFunction) ) 178 if( !(f instanceof LuanFunction) )
150 throw new LuanException("value of '"+fnName+"' not a function in global_callable"); 179 throw new LuanException("value of '"+fnName+"' not a function in global_callable");
151 LuanFunction fn = (LuanFunction)f; 180 LuanFunction fn = (LuanFunction)f;
152 Object rtn = fn.call(luan,args); 181 Object rtn = fn.call(luan,args);
153 if( !isPrimitive(rtn) ) 182 rtn = makeSafe(rtn);
154 throw new LuanException("can't return non-primitive type from global_callable"); 183 if( rtn instanceof Unsafe )
184 throw new LuanException("can't return "+((Unsafe)rtn).reason+" from global_callable");
155 return rtn; 185 return rtn;
156 } 186 }
157 } 187 }
158 188
159 private static Map<String,Callable> callableMap = new HashMap<String,Callable>(); 189 private static Map<String,Callable> callableMap = new HashMap<String,Callable>();