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
--- 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;
 		}
 	}