diff src/luan/Luan.java @ 1578:c922446f53aa

immutable threading
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 08 Feb 2021 14:16:19 -0700
parents 8fbcc4747091
children 2975c932864d
line wrap: on
line diff
--- a/src/luan/Luan.java	Sun Jan 31 16:04:39 2021 -0700
+++ b/src/luan/Luan.java	Mon Feb 08 14:16:19 2021 -0700
@@ -10,6 +10,7 @@
 import java.util.Iterator;
 import java.util.Arrays;
 import java.util.Set;
+import java.util.Collection;
 import goodjava.logging.Logger;
 import goodjava.logging.LoggerFactory;
 import luan.modules.JavaLuan;
@@ -19,31 +20,117 @@
 import luan.impl.LuanCompiler;
 
 
-public final class Luan implements LuanCloneable {
+public final class Luan {
 	private static final Logger logger = LoggerFactory.getLogger(Luan.class);
 
 	private final List<LuanClosure> stack = new ArrayList<LuanClosure>();
-	private Map registry;
-	private boolean isLocked = false;
+	private final Map registry;
+	private final Map localOnly = new HashMap();
 
 	public Luan() {
 		registry = new HashMap();
 	}
 
-	private Luan(Luan luan) {}
+	public Luan(Luan luan) {
+		LuanMutable.makeImmutable(luan.registry);
+		this.registry = clone(luan.registry);
+	}
+
+	private static Object[] clone(Object[] obj) {
+		if( obj.length == 0 )
+			return obj;
+		Object[] rtn = obj.clone();
+		for( int i=0; i<rtn.length; i++ ) {
+			rtn[i] = clone(rtn[i]);
+		}
+		return rtn;
+	}
 
-	@Override public Luan shallowClone() {
-		return new Luan(this);
+	private static Map clone(Map obj) {
+		Map rtn;
+		try {
+			rtn = obj.getClass().newInstance();
+		} catch(InstantiationException e) {
+			throw new RuntimeException(e);
+		} catch(IllegalAccessException e) {
+			throw new RuntimeException(e);
+		}
+		for( Object stupid : obj.entrySet() ) {
+			Map.Entry entry = (Map.Entry)stupid;
+			rtn.put( clone(entry.getKey()), clone(entry.getValue()) );
+		}
+		return rtn;
+	}
+
+	private static Collection clone(Collection obj) {
+		Collection rtn;
+		try {
+			rtn = obj.getClass().newInstance();
+		} catch(InstantiationException e) {
+			throw new RuntimeException(e);
+		} catch(IllegalAccessException e) {
+			throw new RuntimeException(e);
+		}
+		for( Object entry : (Collection)obj ) {
+			rtn.add( clone(entry) );
+		}
+		return rtn;
 	}
 
-	@Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) {
-		Luan clone = (Luan)dc;
-		clone.registry = cloner.clone(registry);
-		if( cloner.type == LuanCloner.Type.INCREMENTAL )
-			isLocked = true;
+	private static Object clone(Object obj) {
+		if( obj instanceof Object[] )
+			return clone((Object[])obj);
+		if( obj instanceof Map )
+			return clone((Map)obj);
+		if( obj instanceof Collection )
+			return clone((Collection)obj);
+		return obj;
+	}
+
+	private Map clonedLocals(Object obj) {
+		Map locals = (Map)registry.get("Luan.local");
+		if( locals==null ) {
+			locals = new HashMap();
+			registry.put("Luan.local",locals);
+		}
+		Map local = (Map)locals.get(obj);
+		if( local==null ) {
+			local = new HashMap();
+			locals.put(obj,local);
+		}
+		return local;
 	}
 
-	@Override public void makeImmutable(LuanImmutabler immutabler) {}
+	public Object getLocalCloned(Object obj,Object key) {
+		return clonedLocals(obj).get(key);
+	}
+
+	public void setLocalCloned(Object obj,Object key,Object value) {
+		if( value==null )
+			clonedLocals(obj).remove(key);
+		else
+			clonedLocals(obj).put(key,value);
+	}
+
+	private Map onlyLocals(Object obj) {
+		Map local = (Map)localOnly.get(obj);
+		if( local==null ) {
+			local = new HashMap();
+			localOnly.put(obj,local);
+		}
+		return local;
+	}
+
+	public Object getLocalOnly(Object obj,Object key) {
+		return onlyLocals(obj).get(key);
+	}
+
+	public void setLocalOnly(Object obj,Object key,Object value) {
+		if( value==null )
+			onlyLocals(obj).remove(key);
+		else
+			onlyLocals(obj).put(key,value);
+	}
 
 	public LuanClosure peek() {
 		return peek(1);
@@ -55,8 +142,6 @@
 	}
 
 	void push(LuanClosure closure) {
-		if( isLocked )
-			throw new RuntimeException(this+" is locked "+closure);
 		stack.add(closure);
 	}
 
@@ -118,7 +203,7 @@
 		throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
 	}
 
-	public static LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException {
+	public LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException {
 		if( o1 instanceof LuanTable ) {
 			LuanFunction f1 = getHandlerFunction(op,(LuanTable)o1);
 			if( f1 != null )
@@ -127,8 +212,8 @@
 		return o2 instanceof LuanTable ? getHandlerFunction(op,(LuanTable)o2) : null;
 	}
 
-	public static LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException {
-		Object f = t.getHandler(op);
+	public LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException {
+		Object f = t.getHandler(this,op);
 		if( f == null )
 			return null;
 		return Luan.checkFunction(f);