Mercurial Hosting > luan
changeset 1578:c922446f53aa
immutable threading
line wrap: on
line diff
--- a/conv.txt Sun Jan 31 16:04:39 2021 -0700 +++ b/conv.txt Mon Feb 08 14:16:19 2021 -0700 @@ -1,3 +1,5 @@ +Thread.global_callable + Luan.try Luan.pcall
--- 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);
--- a/src/luan/LuanCloneable.java Sun Jan 31 16:04:39 2021 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -package luan; - - -public interface LuanCloneable { - public LuanCloneable shallowClone(); - public void deepenClone(LuanCloneable clone,LuanCloner cloner); - public void makeImmutable(LuanImmutabler immutabler) throws LuanException; -}
--- a/src/luan/LuanCloner.java Sun Jan 31 16:04:39 2021 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -package luan; - -import java.util.Map; -import java.util.Collection; -import java.util.IdentityHashMap; - - -public final class LuanCloner { - public enum Type { COMPLETE, INCREMENTAL } - - public final Type type; - private final Map cloned = new IdentityHashMap(); - private Luan luan = null; - - public LuanCloner(Type type) { - this.type = type; - } - - public LuanCloneable clone(LuanCloneable obj) { - if( obj==null ) - return null; - LuanCloneable rtn = (LuanCloneable)cloned.get(obj); - if( rtn == null ) { - if( obj instanceof Luan ) { - if( luan != null ) - throw new RuntimeException("2 luans in "+type+" "+this+" - "+luan+" "+obj); - luan = (Luan)obj; - } - rtn = obj.shallowClone(); - cloned.put(obj,rtn); - obj.deepenClone(rtn,this); - } - return rtn; - } - - public Object[] clone(Object[] obj) { - if( obj==null || obj.length == 0 ) - return obj; - Object[] rtn = (Object[])cloned.get(obj); - if( rtn == null ) { - rtn = obj.clone(); - cloned.put(obj,rtn); - for( int i=0; i<rtn.length; i++ ) { - rtn[i] = get(rtn[i]); - } - } - return rtn; - } - - public Map clone(Map obj) { - if( obj==null ) - return null; - Map rtn = (Map)cloned.get(obj); - if( rtn == null ) { - try { - rtn = obj.getClass().newInstance(); - } catch(InstantiationException e) { - throw new RuntimeException(e); - } catch(IllegalAccessException e) { - throw new RuntimeException(e); - } - cloned.put(obj,rtn); - for( Object stupid : obj.entrySet() ) { - Map.Entry entry = (Map.Entry)stupid; - rtn.put( get(entry.getKey()), get(entry.getValue()) ); - } - } - return rtn; - } - - public Collection clone(Collection obj) { - if( obj==null ) - return null; - Collection rtn = (Collection)cloned.get(obj); - if( rtn == null ) { - 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( get(entry) ); - } - } - return rtn; - } - - public Object get(Object obj) { - if( obj instanceof LuanCloneable ) - return clone((LuanCloneable)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; - } -}
--- a/src/luan/LuanClosure.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/LuanClosure.java Mon Feb 08 14:16:19 2021 -0700 @@ -3,12 +3,11 @@ import luan.impl.Pointer; -public abstract class LuanClosure extends LuanFunction implements LuanCloneable, Cloneable { +public abstract class LuanClosure extends LuanFunction implements LuanMutable { public Pointer[] upValues; public boolean javaOk; public final String sourceName; - private LuanCloner cloner; - private Luan luan; + private boolean immutable = false; public LuanClosure(Pointer[] upValues,boolean javaOk,String sourceName) throws LuanException { this.upValues = upValues; @@ -16,55 +15,18 @@ this.sourceName = sourceName; } - @Override public final LuanClosure shallowClone() { - check(); - try { - return (LuanClosure)clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - - private void check() { - if( cloner != null ) { - completeClone(this,cloner); - cloner = null; - } + @Override public final boolean isImmutable() { + return immutable; } - private void checkLuan(Luan luan) { - check(); - if( this.luan==null ) { - this.luan = luan; - } else if( this.luan != luan ) { - throw new RuntimeException("wrong luan"); - } - } - - @Override public final void deepenClone(LuanCloneable dc,LuanCloner cloner) { - LuanClosure clone = (LuanClosure)dc; - switch( cloner.type ) { - case COMPLETE: - completeClone(clone,cloner); + @Override public final void makeImmutable() { + if(immutable) return; - case INCREMENTAL: - clone.cloner = cloner; - return; - } - } - - private void completeClone(LuanClosure dc,LuanCloner cloner) { - LuanClosure clone = (LuanClosure)dc; - clone.upValues = (Pointer[])cloner.clone(upValues); - clone.luan = (Luan)cloner.clone(luan); - } - - @Override public final void makeImmutable(LuanImmutabler immutabler) throws LuanException { - immutabler.makeImmutable(upValues); + immutable = true; + LuanMutable.makeImmutable(upValues); } @Override public final Object call(Luan luan,Object... args) throws LuanException { - check(); luan.push(this); try { return doCall(luan,args); @@ -75,7 +37,7 @@ } } - @Override public String toString() { + @Override public final String toString() { return super.toString()+"="+sourceName; }
--- a/src/luan/LuanException.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/LuanException.java Mon Feb 08 14:16:19 2021 -0700 @@ -9,9 +9,10 @@ import java.util.HashMap; -public final class LuanException extends Exception implements LuanCloneable { +public final class LuanException extends Exception implements LuanMutable { private LuanTable table; private Map extra = new HashMap(); + private boolean immutable = false; public LuanException(String msg,Throwable cause) { super(msg,cause); @@ -25,19 +26,16 @@ super(cause); } - @Override public LuanException shallowClone() { - return new LuanException(getMessage(),getCause()); + @Override public boolean isImmutable() { + return immutable; } - @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) { - LuanException clone = (LuanException)dc; - clone.table = (LuanTable)cloner.clone(table); - clone.extra = (Map)cloner.clone(extra); - } - - @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { - immutabler.makeImmutable(table); - immutabler.makeImmutable(extra); + @Override public void makeImmutable() { + if(immutable) + return; + immutable = true; + LuanMutable.makeImmutable(table); + LuanMutable.makeImmutable(extra); } public void put(String key,Object value) throws LuanException {
--- a/src/luan/LuanImmutabler.java Sun Jan 31 16:04:39 2021 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package luan; - -import java.util.Map; -import java.util.Set; -import java.util.Collection; -import java.util.Collections; -import java.util.IdentityHashMap; - - -public final class LuanImmutabler { - private final Set handled = Collections.newSetFromMap(new IdentityHashMap()); - private Luan luan = null; - - public void makeImmutable(LuanCloneable obj) throws LuanException { - if( obj==null || !handled.add(obj) ) - return; - if( obj instanceof Luan ) { - if( luan != null ) - throw new RuntimeException("2 luans in "+this+" - "+luan+" "+obj); - luan = (Luan)obj; - } - obj.makeImmutable(this); - } - - public void makeImmutable(Object[] obj) throws LuanException { - if( obj==null || !handled.add(obj) ) - return; - for( Object entry : obj ) { - makeImmutable(entry); - } - } - - public void makeImmutable(Map obj) throws LuanException { - if( obj==null || !handled.add(obj) ) - return; - for( Object stupid : obj.entrySet() ) { - Map.Entry entry = (Map.Entry)stupid; - makeImmutable(entry.getKey()); - makeImmutable(entry.getValue()); - } - } - - public void makeImmutable(Collection obj) throws LuanException { - if( obj==null || !handled.add(obj) ) - return; - for( Object entry : (Collection)obj ) { - makeImmutable(entry); - } - } - - public void makeImmutable(Object obj) throws LuanException { - if( obj instanceof LuanCloneable ) - makeImmutable((LuanCloneable)obj); - else if( obj instanceof Object[] ) - makeImmutable((Object[])obj); - else if( obj instanceof Map ) - makeImmutable((Map)obj); - else if( obj instanceof Collection ) - makeImmutable((Collection)obj); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/LuanMutable.java Mon Feb 08 14:16:19 2021 -0700 @@ -0,0 +1,53 @@ +package luan; + +import java.util.Map; +import java.util.Collection; + + +public interface LuanMutable { + public boolean isImmutable(); + public void makeImmutable(); + + public static void makeImmutable(LuanMutable obj) { + if( obj==null ) + return; + obj.makeImmutable(); + } + + public static void makeImmutable(Object[] a) { + if( a==null ) + return; + for( Object obj : a ) { + makeImmutable(obj); + } + } + + public static void makeImmutable(Map map) { + if( map==null ) + return; + for( Object stupid : map.entrySet() ) { + Map.Entry entry = (Map.Entry)stupid; + makeImmutable(entry.getKey()); + makeImmutable(entry.getValue()); + } + } + + public static void makeImmutable(Collection col) { + if( col==null ) + return; + for( Object obj : col ) { + makeImmutable(obj); + } + } + + public static void makeImmutable(Object obj) { + if( obj instanceof LuanMutable ) + makeImmutable((LuanMutable)obj); + else if( obj instanceof Object[] ) + makeImmutable((Object[])obj); + else if( obj instanceof Map ) + makeImmutable((Map)obj); + else if( obj instanceof Collection ) + makeImmutable((Collection)obj); + } +}
--- a/src/luan/LuanTable.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/LuanTable.java Mon Feb 08 14:16:19 2021 -0700 @@ -13,14 +13,12 @@ import java.util.HashSet; -public final class LuanTable implements LuanCloneable { +public final class LuanTable implements LuanMutable { private Map map = null; private List list = null; private LuanTable metatable = null; public LuanClosure closure; - private LuanCloner cloner; private boolean immutable = false; - private Luan luan; public LuanTable() {} @@ -71,59 +69,23 @@ this.metatable = tbl.metatable; } - @Override public LuanTable shallowClone() { - if(immutable) throw new RuntimeException(); - return new LuanTable(); - } - - @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) { - check(); - LuanTable clone = (LuanTable)dc; - switch( cloner.type ) { - case COMPLETE: - completeClone(clone,cloner); - return; - case INCREMENTAL: - clone.cloner = cloner; - clone.map = map; - clone.list = list; - clone.metatable = metatable; - clone.closure = closure; - return; - } + @Override public boolean isImmutable() { + return immutable; } - private void check() { - if( cloner != null ) { - completeClone(this,cloner); - cloner = null; - } - } - - private void checkLuan(Luan luan) { - check(); - if( this.luan==null ) { - this.luan = luan; - } else if( this.luan != luan ) { - throw new RuntimeException("wrong luan"); - } + @Override public void makeImmutable() { + if(immutable) + return; + immutable = true; + LuanMutable.makeImmutable(map); + LuanMutable.makeImmutable(list); + LuanMutable.makeImmutable(metatable); + LuanMutable.makeImmutable(closure); } - private void completeClone(LuanTable clone,LuanCloner cloner) { - clone.map = cloner.clone(map); - clone.list = (List)cloner.clone(list); - clone.metatable = (LuanTable)cloner.clone(metatable); - clone.closure = (LuanClosure)cloner.clone(closure); - clone.luan = (Luan)cloner.clone(luan); - } - - @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { - check(); - immutabler.makeImmutable(map); - immutabler.makeImmutable(list); - immutabler.makeImmutable(metatable); - immutabler.makeImmutable(closure); - immutable = true; + private void checkMutable() throws LuanException { + if( immutable ) + throw new LuanException("table is immutable"); } public boolean isList() { @@ -135,17 +97,15 @@ } public List<Object> asList() { - check(); return list!=null ? list : Collections.emptyList(); } public Map rawMap() { - check(); return map!=null ? map : Collections.emptyMap(); } public String toStringLuan(Luan luan) throws LuanException { - Object h = getHandler("__to_string"); + Object h = getHandler(luan,"__to_string"); if( h == null ) return rawToString(); LuanFunction fn = Luan.checkFunction(h); @@ -161,7 +121,7 @@ Object value = rawGet(key); if( value != null ) return value; - Object h = getHandler("__index"); + Object h = getHandler(luan,"__index"); if( h==null ) return null; if( h instanceof LuanFunction ) { @@ -172,7 +132,6 @@ } public Object rawGet(Object key) { - check(); if( list != null ) { Integer iT = Luan.asInteger(key); if( iT != null ) { @@ -192,7 +151,7 @@ public void put(Luan luan,Object key,Object value) throws LuanException { //checkLuan(luan); - Object h = getHandler("__new_index"); + Object h = getHandler(luan,"__new_index"); if( h==null || rawGet(key)!=null ) { rawPut(key,value); return; @@ -211,9 +170,7 @@ } public Object rawPut(Object key,Object val) throws LuanException { - if( immutable ) - throw new LuanException("table is immutable"); - check(); + checkMutable(); if( key==null ) throw new LuanException("table index is nil"); Integer iT = Luan.asInteger(key); @@ -284,34 +241,34 @@ return list; } - public void rawInsert(int pos,Object value) { - check(); + public void rawInsert(int pos,Object value) throws LuanException { + checkMutable(); if( value==null ) throw new IllegalArgumentException("can't insert a nil value"); list().add(pos-1,value); mapToList(); } - public void rawAdd(Object value) { - check(); + public void rawAdd(Object value) throws LuanException { + checkMutable(); if( value==null ) throw new IllegalArgumentException("can't insert a nil value"); list().add(value); mapToList(); } - public Object removeFromList(int pos) { - check(); + public Object removeFromList(int pos) throws LuanException { + checkMutable(); return list().remove(pos-1); } - public void rawSort(Comparator<Object> cmp) { - check(); + public void rawSort(Comparator<Object> cmp) throws LuanException { + checkMutable(); Collections.sort(list(),cmp); } public int length(Luan luan) throws LuanException { - Object h = getHandler("__len"); + Object h = getHandler(luan,"__len"); if( h != null ) { LuanFunction fn = Luan.checkFunction(h); return (Integer)Luan.first(fn.call(luan,this)); @@ -320,7 +277,6 @@ } public int rawLength() { - check(); return list==null ? 0 : list.size(); } @@ -343,7 +299,7 @@ } public Iterator<Map.Entry> iterator(final Luan luan) throws LuanException { - if( getHandler("__pairs") == null ) + if( getHandler(luan,"__pairs") == null ) return rawIterator(); final LuanFunction fn = pairs(luan); return new Iterator<Map.Entry>() { @@ -380,7 +336,7 @@ } public LuanFunction pairs(Luan luan) throws LuanException { - Object h = getHandler("__pairs"); + Object h = getHandler(luan,"__pairs"); if( h != null ) { if( h instanceof LuanFunction ) { LuanFunction fn = (LuanFunction)h; @@ -408,7 +364,6 @@ } public Iterator<Map.Entry> rawIterator() { - check(); if( list == null ) { if( map == null ) return Collections.<Map.Entry>emptyList().iterator(); @@ -462,25 +417,22 @@ } public LuanTable rawSubList(int from,int to) { - check(); LuanTable tbl = new LuanTable(); tbl.list = new ArrayList<Object>(list().subList(from-1,to-1)); return tbl; } public LuanTable getMetatable() { - check(); return metatable; } public void setMetatable(LuanTable metatable) throws LuanException { - check(); + checkMutable(); this.metatable = metatable; } - public Object getHandler(String op) throws LuanException { - check(); - return metatable==null ? null : metatable.rawGet(op); + public Object getHandler(Luan luan,String op) throws LuanException { + return metatable==null ? null : luan==null ? metatable.rawGet(op) : metatable.get(luan,op); } private static Map<Object,Object> newMap() { @@ -511,8 +463,8 @@ return map; } - public void rawClear() { - check(); + public void rawClear() throws LuanException { + checkMutable(); map = null; list = null; } @@ -540,15 +492,14 @@ } public Object remove(Object key) throws LuanException { - if( immutable ) - throw new LuanException("table is immutable"); + checkMutable(); Object old = rawGet(key); rawPut(key,null); return old; } protected void finalize() throws Throwable { - Object h = getHandler("__gc"); + Object h = getHandler(null,"__gc"); if( h != null ) { LuanFunction fn = Luan.checkFunction(h); fn.call(new Luan(),this); // ??? should be immutable
--- a/src/luan/host/WebHandler.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/host/WebHandler.java Mon Feb 08 14:16:19 2021 -0700 @@ -59,9 +59,9 @@ return domainHandler.handle(request); } - public static Object callSite(Luan luan,String domain,String fnName,Object... args) throws LuanException { + public static Object callSite(String domain,String fnName,Object... args) throws LuanException { LuanHandler luanHandler = (LuanHandler)domainHandler.getHandler(domain); - return luanHandler.call_rpc(luan,fnName,args); + return luanHandler.call_rpc(fnName,args); } private static void initLuan(Luan luan,String dir,String domain) {
--- a/src/luan/impl/LuanImpl.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/impl/LuanImpl.java Mon Feb 08 14:16:19 2021 -0700 @@ -33,7 +33,7 @@ if( o instanceof Number ) return -((Number)o).doubleValue(); if( o instanceof LuanTable ) { - LuanFunction fn = Luan.getHandlerFunction("__unm",(LuanTable)o); + LuanFunction fn = luan.getHandlerFunction("__unm",(LuanTable)o); if( fn != null ) { return Luan.first(fn.call(luan,o)); } @@ -42,7 +42,7 @@ } private static Object arithmetic(Luan luan,String op,Object o1,Object o2) throws LuanException { - LuanFunction fn = Luan.getBinHandler(op,o1,o2); + LuanFunction fn = luan.getBinHandler(op,o1,o2); if( fn != null ) return Luan.first(fn.call(luan,o1,o2)); String type = !(o1 instanceof Number) ? Luan.type(o1) : Luan.type(o2); @@ -89,7 +89,7 @@ } public static Object concat(Luan luan,Object o1,Object o2) throws LuanException { - LuanFunction fn = Luan.getBinHandler("__concat",o1,o2); + LuanFunction fn = luan.getBinHandler("__concat",o1,o2); if( fn != null ) return Luan.first(fn.call(luan,o1,o2)); String s1 = luan.luanToString(o1); @@ -136,10 +136,10 @@ String s2 = (String)o2; return s1.compareTo(s2) <= 0; } - LuanFunction fn = Luan.getBinHandler("__le",o1,o2); + LuanFunction fn = luan.getBinHandler("__le",o1,o2); if( fn != null ) return Luan.checkBoolean( Luan.first(fn.call(luan,o1,o2)) ); - fn = Luan.getBinHandler("__lt",o1,o2); + fn = luan.getBinHandler("__lt",o1,o2); if( fn != null ) return !Luan.checkBoolean( Luan.first(fn.call(luan,o2,o1)) ); throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
--- a/src/luan/impl/Pointer.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/impl/Pointer.java Mon Feb 08 14:16:19 2021 -0700 @@ -1,12 +1,10 @@ package luan.impl; -import luan.LuanCloneable; -import luan.LuanCloner; -import luan.LuanImmutabler; +import luan.LuanMutable; import luan.LuanException; -public final class Pointer implements LuanCloneable { +public final class Pointer implements LuanMutable { private Object o; private boolean immutable = false; @@ -16,17 +14,15 @@ this.o = o; } - @Override public Pointer shallowClone() { - return new Pointer(); + @Override public boolean isImmutable() { + return immutable; } - @Override public void deepenClone(LuanCloneable clone,LuanCloner cloner) { - ((Pointer)clone).o = cloner.get(o); - } - - @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { - immutabler.makeImmutable(o); + @Override public void makeImmutable() { + if(immutable) + return; immutable = true; + LuanMutable.makeImmutable(o); } public Object get() {
--- a/src/luan/modules/BasicLuan.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/BasicLuan.java Mon Feb 08 14:16:19 2021 -0700 @@ -14,9 +14,7 @@ import luan.LuanTable; import luan.LuanFunction; import luan.LuanException; -import luan.LuanCloner; -import luan.LuanCloneable; -import luan.LuanImmutabler; +import luan.LuanMutable; import luan.modules.parsers.LuanToString; @@ -51,7 +49,7 @@ return t.pairs(luan); } - private static class Ipairs extends LuanFunction implements LuanCloneable, Cloneable { + private static final class Ipairs extends LuanFunction implements LuanMutable { List<Object> list; int i = 0; final int size; @@ -68,21 +66,12 @@ return new Object[]{i,val}; } - @Override public final Ipairs shallowClone() { - try { - return (Ipairs)clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } + @Override public boolean isImmutable() { + return false; } - @Override public final void deepenClone(LuanCloneable dc,LuanCloner cloner) { - Ipairs clone = (Ipairs)dc; - clone.list = (List)cloner.clone(list); - } - - @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { - throw new LuanException("ipairs cannot be made immutable"); + @Override public void makeImmutable() { + throw new RuntimeException("ipairs cannot be made immutable"); } } @@ -100,9 +89,9 @@ return obj!=null ? obj : metatable; } - public static void set_metatable(LuanTable table,LuanTable metatable) throws LuanException { + public static void set_metatable(Luan luan,LuanTable table,LuanTable metatable) throws LuanException { Utils.checkNotNull(table); - if( table.getHandler("__metatable") != null ) + if( table.getHandler(luan,"__metatable") != null ) throw new LuanException("cannot change a protected metatable"); table.setMetatable(metatable); } @@ -175,7 +164,7 @@ }; } - private static class Values extends LuanFunction implements LuanCloneable, Cloneable { + private static final class Values extends LuanFunction implements LuanMutable { Object[] args; int i = 0; @@ -190,21 +179,12 @@ return new Object[]{i,val}; } - @Override public final Values shallowClone() { - try { - return (Values)clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } + @Override public boolean isImmutable() { + return false; } - @Override public final void deepenClone(LuanCloneable dc,LuanCloner cloner) { - Values clone = (Values)dc; - clone.args = (Object[])cloner.clone(args); - } - - @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { - throw new LuanException("values cannot be made immutable"); + @Override public void makeImmutable() { + throw new RuntimeException("values cannot be made immutable"); } } @@ -248,5 +228,25 @@ return jts.toString(Luan.toJava(obj)); } + public static Object get_local_cloned(Luan luan,Object obj,Object key) { + return luan.getLocalCloned(obj,key); + } + + public static void set_local_cloned(Luan luan,Object obj,Object key,Object value) { + luan.setLocalCloned(obj,key,value); + } + + public static Object get_local_only(Luan luan,Object obj,Object key) { + return luan.getLocalOnly(obj,key); + } + + public static void set_local_only(Luan luan,Object obj,Object key,Object value) { + luan.setLocalOnly(obj,key,value); + } + + public static boolean is_immutable(LuanMutable m) { + return m.isImmutable(); + } + private void BasicLuan() {} // never }
--- a/src/luan/modules/Boot.luan Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/Boot.luan Mon Feb 08 14:16:19 2021 -0700 @@ -14,6 +14,10 @@ local LuanUrl = require "java:luan.modules.url.LuanUrl" local LuanJava = require "java:luan.Luan" local LuanTable = require "java:luan.LuanTable" +local get_local_cloned = BasicLuan.get_local_cloned +local set_local_cloned = BasicLuan.set_local_cloned +local is_immutable = BasicLuan.is_immutable +local raw_set = BasicLuan.raw_set local Boot = {} @@ -38,6 +42,19 @@ Boot.no_security = no_security +local local_metatable = { + __index = get_local_cloned +} +function local_metatable.__new_index(tbl,key,value) + if is_immutable(tbl) then + set_local_cloned(tbl,key,value) + else + raw_set(tbl,key,value) + end +end +Boot.local_metatable = local_metatable + + local function new_LuanIn(io) local this = {} this.java = io @@ -87,6 +104,7 @@ end local schemes = {} +set_metatable(schemes,local_metatable) --LuanTable.setSecurity(schemes,"schemes") function schemes.null(path)
--- a/src/luan/modules/Io.luan Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/Io.luan Mon Feb 08 14:16:19 2021 -0700 @@ -3,9 +3,31 @@ local System = require "java:java.lang.System" local Boot = require "luan:Boot.luan" local LuanException = require "java:luan.LuanException" +local Luan = require "luan:Luan.luan" +local error = Luan.error +local get_local_cloned = Luan.get_local_cloned +local set_local_cloned = Luan.set_local_cloned +local raw_set = Luan.raw_set +local set_metatable = Luan.set_metatable local Io = {} +local mt = {} +function mt.__index(tbl,key) + if key=="stdin" or key=="stdout" or key=="stderr" then + return get_local_cloned(tbl,key) + else + return nil + end +end +function mt.__new_index(tbl,key,value) + if key=="stdin" or key=="stdout" or key=="stderr" then + set_local_cloned(tbl,key,value) + else + raw_set(tbl,key,value) + end +end +set_metatable(Io,mt) Io.dns_lookup = IoLuan.dns_lookup Io.ip = IoLuan.ip @@ -20,8 +42,6 @@ -- used by http and rpc Io.password = "password" -local Luan = require "luan:Luan.luan" -local error = Luan.error local to_string = Luan.to_string or error() local type = Luan.type or error() local ipairs = Luan.ipairs or error()
--- a/src/luan/modules/IoLuan.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/IoLuan.java Mon Feb 08 14:16:19 2021 -0700 @@ -643,7 +643,7 @@ } public static LuanTable dns_lookup(String domain,String type) - throws NamingException + throws NamingException, LuanException { LuanTable tbl = new LuanTable(); InitialDirContext idc = new InitialDirContext();
--- a/src/luan/modules/JavaLuan.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/JavaLuan.java Mon Feb 08 14:16:19 2021 -0700 @@ -22,8 +22,6 @@ import luan.LuanException; import luan.LuanFunction; import luan.LuanJavaFunction; -import luan.LuanCloner; -import luan.LuanImmutabler; public final class JavaLuan {
--- a/src/luan/modules/Luan.luan Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/Luan.luan Mon Feb 08 14:16:19 2021 -0700 @@ -7,6 +7,8 @@ local error = Boot.error Luan.error = error +Luan.get_local_cloned = BasicLuan.get_local_cloned +Luan.get_local_only = BasicLuan.get_local_only Luan.get_metatable = BasicLuan.get_metatable Luan.hash_code = BasicLuan.hash_code Luan.ipairs = BasicLuan.ipairs @@ -21,6 +23,8 @@ Luan.raw_get = BasicLuan.raw_get Luan.raw_len = BasicLuan.raw_len Luan.raw_set = BasicLuan.raw_set +Luan.set_local_cloned = BasicLuan.set_local_cloned +Luan.set_local_only = BasicLuan.set_local_only Luan.set_metatable = BasicLuan.set_metatable Luan.stringify = BasicLuan.stringify Luan.to_string = BasicLuan.to_string
--- a/src/luan/modules/Package.luan Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/Package.luan Mon Feb 08 14:16:19 2021 -0700 @@ -1,9 +1,21 @@ require "java" local PackageLuan = require "java:luan.modules.PackageLuan" +local BasicLuan = require "java:luan.modules.BasicLuan" +local set_metatable = BasicLuan.set_metatable local Package = {} -Package.loaded = PackageLuan.loaded() Package.load = PackageLuan.load +local loaded = PackageLuan.loaded -- returns java map +local mt = {} +function mt.__index(_,key) + return loaded().get(key) +end +function mt.__new_index(_,key,value) + loaded().put(key,value) +end +Package.loaded = {} +set_metatable(Package.loaded,mt) + return Package
--- a/src/luan/modules/PackageLuan.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/PackageLuan.java Mon Feb 08 14:16:19 2021 -0700 @@ -5,12 +5,13 @@ import java.io.IOException; import java.util.Arrays; import java.util.Collections; +import java.util.Map; +import java.util.HashMap; import goodjava.io.IoUtils; import luan.Luan; import luan.LuanTable; import luan.LuanFunction; import luan.LuanJavaFunction; -import luan.LuanCloner; import luan.LuanException; @@ -29,13 +30,13 @@ return fn; } - public static LuanTable loaded(Luan luan) { - LuanTable tbl = (LuanTable)luan.registry().get("Package.loaded"); - if( tbl == null ) { - tbl = new LuanTable(); - luan.registry().put("Package.loaded",tbl); + public static Map loaded(Luan luan) { + Map map = (Map)luan.registry().get("Package.loaded"); + if( map == null ) { + map = new HashMap(); + luan.registry().put("Package.loaded",map); } - return tbl; + return map; } public static Object require(Luan luan,String modName) throws LuanException { @@ -50,8 +51,8 @@ } public static Object load(Luan luan,String modName) throws LuanException { - LuanTable loaded = loaded(luan); - Object mod = loaded.rawGet(modName); + Map loaded = loaded(luan); + Object mod = loaded.get(modName); if( mod == null ) { if( modName.equals("luan:Boot.luan") ) { String src; @@ -82,14 +83,14 @@ loader.call(luan,modName) ); if( mod == null ) { - mod = loaded.rawGet(modName); + mod = loaded.get(modName); if( mod != null ) return mod; throw new LuanException( "module '"+modName+"' returned nil" ); } } } - loaded.rawPut(modName,mod); + loaded.put(modName,mod); } return mod; }
--- a/src/luan/modules/Rpc.luan Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/Rpc.luan Mon Feb 08 14:16:19 2021 -0700 @@ -126,6 +126,7 @@ end_function Rpc.functions = {} +Luan.set_metatable( Rpc.functions, Boot.local_metatable ) local function rpc_responder(socket,fns) local server = RpcServer.new(socket)
--- a/src/luan/modules/TableLuan.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/TableLuan.java Mon Feb 08 14:16:19 2021 -0700 @@ -112,7 +112,7 @@ return list.rawSubList(from,to); } - public static void clear(LuanTable tbl) { + public static void clear(LuanTable tbl) throws LuanException { tbl.rawClear(); }
--- a/src/luan/modules/Thread.luan Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/Thread.luan Mon Feb 08 14:16:19 2021 -0700 @@ -34,12 +34,20 @@ ThreadLuan.schedule(fn,options) end +function Thread.schedule_closure(init_fn,options) + local function safe_init() + return safe(init_fn()) + end + options = options or {} + ThreadLuan.schedule_closure(safe_init,options) +end + local forever = Time.period{years=100} -function Thread.global_callable(name,fns,timeout) +function Thread.global_callable(name,init_fn,timeout) timeout = timeout or forever - local callable = ThreadLuan.globalCallable(name,fns,timeout) + local callable = ThreadLuan.globalCallable(name,init_fn,timeout) local mt = {} function mt.__index(_,key) return function(...) @@ -54,27 +62,21 @@ Thread.remove_global_callable = ThreadLuan.removeGlobalCallable function Thread.global_map(name,timeout) - timeout = timeout or forever + local function init() + local map = {} + local fns = {} - local map = {} - local fns = {} - - function fns.get(key) - return map[key] - end + function fns.__index(_,key) + return map[key] + end - function fns.put(key,value) - map[key] = value - end + function fns.__new_index(_,key,value) + map[key] = value + end - local callable = ThreadLuan.globalCallable(name,fns,timeout) - local mt = {} - function mt.__index(_,key) - return callable.call("get",key) + return fns end - function mt.__new_index(_,key,value) - return callable.call("put",key,value) - end + local mt = Thread.global_callable(name,init,timeout) local tbl = {} set_metatable(tbl,mt) return tbl @@ -94,15 +96,4 @@ end --- remove -function Thread.new_synchronizer() - local lock = ReentrantLock.new() - return function(fn) - return function(...) - return run_in_lock(lock,default_time_out,fn,...) - end - end -end - - return Thread
--- a/src/luan/modules/ThreadLuan.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/ThreadLuan.java Mon Feb 08 14:16:19 2021 -0700 @@ -17,8 +17,7 @@ import luan.LuanFunction; import luan.LuanTable; import luan.LuanException; -import luan.LuanCloner; -import luan.LuanCloneable; +import luan.LuanMutable; import luan.modules.logging.LuanLogger; import goodjava.logging.Logger; import goodjava.logging.LoggerFactory; @@ -45,10 +44,9 @@ }; } - public static void fork(Luan luan,LuanFunction fn) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - luan = (Luan)cloner.get(luan); - fn = (LuanFunction)cloner.get(fn); + public static void fork(Luan luan,LuanFunction fn) throws LuanException { + luan = new Luan(luan); + LuanMutable.makeImmutable(fn); exec.execute(runnable(luan,fn)); } @@ -60,9 +58,26 @@ logger.error(src+" cancel="+b+" isCancelled="+sf.isCancelled()+" isDone="+sf.isDone()+" "+sf); } + public static synchronized void schedule_closure(Luan luan,LuanFunction initFn,LuanTable options) + throws LuanException + { + final Luan newLuan = new Luan(luan); + LuanMutable.makeImmutable(initFn); + LuanFunction fn = (LuanFunction)initFn.call(newLuan); + scheduleFn(luan,newLuan,fn,options); + } + public static synchronized void schedule(Luan luan,LuanFunction fn,LuanTable options) throws LuanException { + final Luan newLuan = new Luan(luan); + LuanMutable.makeImmutable(fn); + scheduleFn(luan,newLuan,fn,options); + } + + private static synchronized void scheduleFn(Luan luan,final Luan newLuan,LuanFunction fn,LuanTable options) + throws LuanException + { options = new LuanTable(options); Number delay = Utils.removeNumber(options,"delay"); Number repeatingDelay = Utils.removeNumber(options,"repeating_delay"); @@ -77,10 +92,7 @@ if( sf != null ) cancel(sf,"id "+id); } - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - final Luan newLuan = (Luan)cloner.clone(luan); - final LuanFunction newFn = (LuanFunction)cloner.get(fn); - final Runnable r = runnable(newLuan,newFn); + final Runnable r = runnable(newLuan,fn); final ScheduledFuture sf; if( repeatingDelay != null ) { if( delay==null ) @@ -106,104 +118,24 @@ scheduleds.put(id,sf); } -/* - public static class GlobalMap { - - private static class Value { - final long time = System.currentTimeMillis(); - final Object v; - - Value(Object v) { - this.v = v; - } - } - - public long timeout = 60000L; // one minute - private Map<String,Value> map = new LinkedHashMap<String,Value>() { - protected boolean removeEldestEntry(Map.Entry<String,Value> eldest) { - return eldest.getValue().time < System.currentTimeMillis() - timeout; - } - }; - - public synchronized Object get(String key) { - Value val = map.get(key); - return val==null ? null : val.v; - } - - public synchronized Object put(String key,Object v) throws LuanException { - Value val; - if( v == null ) { - val = map.remove(key); - } else { - if( !(v instanceof String || v instanceof Boolean || v instanceof Number) ) - throw new LuanException("can't assign type "+Luan.type(v)+" to Thread.global"); - val = map.put(key,new Value(v)); - } - return val==null ? null : val.v; - } - } -*/ public static void sleep(long millis) throws InterruptedException { Thread.sleep(millis); } - private static class Unsafe { - private final String reason; - - Unsafe(String reason) { - this.reason = reason; - } - } - - private static Object makeSafe(Object v) throws LuanException { - 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( int i=0; i<a.length; i++ ) { - Object obj = makeSafe(a[i]); - if( obj instanceof Unsafe ) - return obj; - a[i] = obj; - } - return a; - } else { - if( v instanceof LuanCloneable ) - return new Unsafe("type "+Luan.type(v)); - return v; - } - } - public static final class Callable { private long expires; private final Luan luan = new Luan(); private final LuanTable fns; - Callable(LuanTable fns) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - this.fns = (LuanTable)cloner.get(fns); + Callable(LuanFunction initFn) throws LuanException { + LuanMutable.makeImmutable(initFn); + this.fns = (LuanTable)initFn.call(luan); } public synchronized Object call(Luan callerLuan,String fnName,Object... args) throws LuanException { - 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; + LuanMutable.makeImmutable(args); Object f = fns.get(luan,fnName); if( f == null ) throw new LuanException("function '"+fnName+"' not found in global_callable"); @@ -211,9 +143,7 @@ throw new LuanException("value of '"+fnName+"' not a function in global_callable"); LuanFunction fn = (LuanFunction)f; Object rtn = fn.call(luan,args); - rtn = makeSafe(rtn); - if( rtn instanceof Unsafe ) - throw new LuanException("can't return "+((Unsafe)rtn).reason+" from global_callable"); + LuanMutable.makeImmutable(rtn); return rtn; } } @@ -229,11 +159,11 @@ } } - public static synchronized Callable globalCallable(String name,LuanTable fns,long timeout) { + public static synchronized Callable globalCallable(String name,LuanFunction initFn,long timeout) throws LuanException { Callable callable = callableMap.get(name); if( callable == null ) { sweep(); - callable = new Callable(fns); + callable = new Callable(initFn); callableMap.put(name,callable); } callable.expires = System.currentTimeMillis() + timeout;
--- a/src/luan/modules/http/Http.luan Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/http/Http.luan Mon Feb 08 14:16:19 2021 -0700 @@ -4,6 +4,12 @@ local ipairs = Luan.ipairs or error() local pairs = Luan.pairs or error() local type = Luan.type or error() +local set_metatable = Luan.set_metatable or error() +local get_local_cloned = Luan.get_local_cloned or error() +local set_local_cloned = Luan.set_local_cloned or error() +local get_local_only = Luan.get_local_only or error() +local set_local_only = Luan.set_local_only or error() +local raw_set = Luan.raw_set or error() local Io = require "luan:Io.luan" local Html = require "luan:Html.luan" local Table = require "luan:Table.luan" @@ -29,6 +35,26 @@ local Http = {} +local mt = {} +function mt.__index(tbl,key) + if key=="error_priority" then + return get_local_cloned(tbl,key) + elseif key=="request" or key=="response" then + return get_local_only(tbl,key) + else + return nil + end +end +function mt.__new_index(tbl,key,value) + if key=="error_priority" then + set_local_cloned(tbl,key,value) + elseif key=="request" or key=="response" then + set_local_only(tbl,key,value) + else + raw_set(tbl,key,value) + end +end +set_metatable(Http,mt) local old_java_to_table_shallow = Table.java_to_table_shallow or error()
--- a/src/luan/modules/http/LuanDomainHandler.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/http/LuanDomainHandler.java Mon Feb 08 14:16:19 2021 -0700 @@ -6,7 +6,6 @@ import goodjava.webserver.handlers.DomainHandler; import luan.Luan; import luan.LuanTable; -import luan.LuanCloner; import luan.LuanFunction; import luan.LuanException; import luan.modules.logging.LuanLogger; @@ -19,8 +18,7 @@ public LuanDomainHandler(Luan luanInit) { LuanLogger.initThreadLogging(); - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - this.luanInit = (Luan)cloner.clone(luanInit); + this.luanInit = new Luan(luanInit); } @Override public Handler newHandler(String domain) { @@ -29,8 +27,7 @@ } protected Luan newLuan(final String domain) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - Luan luan = (Luan)cloner.clone(luanInit); + Luan luan = new Luan(luanInit); LuanFunction reset_luan = new LuanFunction() { @Override public Object call(Luan luan,Object[] args) { domainHandler.removeHandler(domain);
--- a/src/luan/modules/http/LuanHandler.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/http/LuanHandler.java Mon Feb 08 14:16:19 2021 -0700 @@ -27,7 +27,6 @@ import luan.LuanTable; import luan.LuanFunction; import luan.LuanJavaFunction; -import luan.LuanCloner; import luan.LuanException; import luan.modules.PackageLuan; import luan.modules.BasicLuan; @@ -87,8 +86,7 @@ private Luan newLuan() { Luan luan; synchronized(luanInit) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - luan = (Luan)cloner.clone(luanInit); + luan = new Luan(luanInit); } LuanLogger.startThreadLogging(luan); try { @@ -138,20 +136,19 @@ //logger.info("close "+domain+" "+(obj!=null)); } - public Object call_rpc(Luan luan,String fnName,Object... args) throws LuanException { + public Object call_rpc(String fnName,Object... args) throws LuanException { rwLock.readLock().lock(); LuanLogger.startThreadLogging(currentLuan); try { LuanFunction fn; - synchronized(luanInit) { - enableLoad("luan:Rpc.luan"); + Luan luan; + synchronized(currentLuan) { LuanTable rpc = (LuanTable)currentLuan.require("luan:Rpc.luan"); - LuanTable fns = (LuanTable)rpc.get(luan,"functions"); - fn = (LuanFunction)fns.get(luan,fnName); + LuanTable fns = (LuanTable)rpc.get(currentLuan,"functions"); + fn = (LuanFunction)fns.get(currentLuan,fnName); if( fn == null ) throw new LuanException( "function not found: " + fnName ); - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - fn = (LuanFunction)cloner.get(fn); + luan = new Luan(currentLuan); } return fn.call(luan,args); } finally { @@ -185,13 +182,9 @@ } private void eval_in_root(String text) throws LuanException { - Luan luan; - synchronized(luanInit) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - luan = (Luan)cloner.clone(currentLuan); + synchronized(currentLuan) { + currentLuan.load(text,"<eval_in_root>",false,null).call(currentLuan); } - luan.load(text,"<eval_in_root>",false,null).call(luan); - currentLuan = luan; } private void dont_gc() { @@ -249,11 +242,10 @@ private Response handleError(Request request,LuanException e) throws LuanException { -//e.printStackTrace(); + //e.printStackTrace(); Luan luan; - synchronized(luanInit) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - luan = (Luan)cloner.clone(currentLuan); + synchronized(currentLuan) { + luan = new Luan(currentLuan); } LuanTable module = (LuanTable)luan.require("luan:http/Http.luan"); return (Response)module.fn("handle_error").call( luan, request, e.table(luan) ); @@ -265,17 +257,15 @@ String modName = "site:" + request.path +".luan"; LuanFunction fn; Luan luan; - synchronized(luanInit) { - enableLoad("luan:http/Http.luan",modName); + synchronized(currentLuan) { currentLuan.require("luan:http/Http.luan"); Object mod = PackageLuan.load(currentLuan,modName); if( mod.equals(Boolean.FALSE) ) return null; if( !(mod instanceof LuanFunction) ) throw new LuanException( "module '"+modName+"' must return a function" ); - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - luan = (Luan)cloner.clone(currentLuan); - fn = (LuanFunction)cloner.get(mod); + luan = new Luan(currentLuan); + fn = (LuanFunction)mod; } LuanTable module = (LuanTable)luan.require("luan:http/Http.luan"); module.fn("new_request").call(luan,request); @@ -289,15 +279,12 @@ { LuanFunction fn; Luan luan; - synchronized(luanInit) { - enableLoad("luan:http/Http.luan"); + synchronized(currentLuan) { LuanTable module = (LuanTable)currentLuan.require("luan:http/Http.luan"); fn = module.fn("not_found_handler"); if( fn == null ) return null; - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - luan = (Luan)cloner.clone(currentLuan); - fn = (LuanFunction)cloner.get(fn); + luan = new Luan(currentLuan); } LuanTable module = (LuanTable)luan.require("luan:http/Http.luan"); module.fn("new_request").call(luan,request); @@ -309,15 +296,4 @@ return handled ? (Response)module.fn("finish").call(luan) : null; } - private void enableLoad(String... mods) throws LuanException { - LuanTable loaded = PackageLuan.loaded(currentLuan); - for( String mod : mods ) { - if( loaded.rawGet(mod) == null ) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - currentLuan = (Luan)cloner.clone(currentLuan); - break; - } - } - } - }
--- a/src/luan/modules/http/tools/Shell.luan Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/http/tools/Shell.luan Mon Feb 08 14:16:19 2021 -0700 @@ -7,6 +7,7 @@ local concat = Table.concat or error() local pack = Table.pack or error() local unpack = Table.unpack or error() +local copy = Table.copy or error() local Time = require "luan:Time.luan" local Thread = require "luan:Thread.luan" local Html = require "luan:Html.luan" @@ -20,36 +21,43 @@ local Shell = {} -local count = 0 -local new_session = Thread.global_callable("shell.new_session",{next=function() - count = count + 1 - return to_string(count) -end}).next +local function counter() + local fns = {} + local count = 0 + function fns.next() + count = count + 1 + return to_string(count) + end + return fns +end +local new_session = Thread.global_callable("shell.new_session",counter).next -local env = {} -Shell.env = env - -local fns = {} +Shell.env = {} -function fns.run(cmd) - try - local line +local function init_env() + local env = copy(Shell.env) + local fns = {} + function fns.run(cmd) try - line = load("return "..cmd,"<web_shell>",env) + local line + try + line = load("return "..cmd,"<web_shell>",env) + catch e + line = load(cmd,"<web_shell>",env) + end + return line() catch e - line = load(cmd,"<web_shell>",env) + --Io.print_to(Io.stderr,e) + return to_string(e) end - return line() - catch e --- Io.print_to(Io.stderr,e) - return to_string(e) end + return fns end local timeout = Time.period{hours=10} local function get_session(session_id) - return Thread.global_callable("shell.session"..session_id,fns,timeout) + return Thread.global_callable("shell.session"..session_id,init_env,timeout) end function Shell.respond()
--- a/src/luan/modules/logging/LuanLogger.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/logging/LuanLogger.java Mon Feb 08 14:16:19 2021 -0700 @@ -52,7 +52,10 @@ if( !(globalAppender instanceof ThreadLocalAppender) ) return; ThreadLocalAppender tla = (ThreadLocalAppender)globalAppender; - Appender appender = (Appender)luan.registry().get(KEY); + Appender appender; + synchronized(luan) { + appender = (Appender)luan.registry().get(KEY); + } if( appender == null ) appender = tla.defaultAppender; tla.threadLocal.set(appender);
--- a/src/luan/modules/lucene/Lucene.luan Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/lucene/Lucene.luan Mon Feb 08 14:16:19 2021 -0700 @@ -5,6 +5,8 @@ local pairs = Luan.pairs or error() local type = Luan.type or error() local set_metatable = Luan.set_metatable or error() +local get_local_cloned = Luan.get_local_cloned +local set_local_cloned = Luan.set_local_cloned local Boot = require "luan:Boot.luan" local Html = require "luan:Html.luan" local Number = require "luan:Number.luan" @@ -25,6 +27,11 @@ local Lucene = {} local indexes = {} +local indexes_mt = { + __index = get_local_cloned + __new_index = set_local_cloned +} +set_metatable(indexes,indexes_mt) function Rpc.functions.lucene_backup(password,name) Io.password == password or error "wrong password" @@ -62,10 +69,8 @@ function Lucene.index(index_dir,options) local index = {} - if options.name ~= nil then - indexes[options.name] = index - options.name = nil - end + local options_name = options.name + options.name = nil index.dir = index_dir index_dir = get_file(index_dir) options = options or {} @@ -74,6 +79,10 @@ local java_index = LuceneIndex.getLuceneIndex(index_dir,options) index.java = java_index + if options_name ~= nil then + indexes[options_name] = index + end + index.indexed_fields = {} local mt = {} set_metatable(index.indexed_fields,mt)
--- a/src/luan/modules/lucene/SupplementingConfig.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/lucene/SupplementingConfig.java Mon Feb 08 14:16:19 2021 -0700 @@ -13,7 +13,7 @@ import luan.Luan; import luan.LuanFunction; import luan.LuanTable; -import luan.LuanCloner; +import luan.LuanMutable; import luan.LuanException; import luan.LuanRuntimeException; @@ -22,11 +22,11 @@ private final Luan luan; private final LuanFunction supplementer; - SupplementingConfig(Version luceneVersion,MultiFieldParser mfp,Luan luan,LuanFunction supplementer) { + SupplementingConfig(Version luceneVersion,MultiFieldParser mfp,Luan luan,LuanFunction supplementer) throws LuanException { super(luceneVersion,mfp); - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - this.luan = (Luan)cloner.get(luan); - this.supplementer = (LuanFunction)cloner.get(supplementer); + this.luan = new Luan(luan); + LuanMutable.makeImmutable(supplementer); + this.supplementer = supplementer; } @Override public IndexWriterConfig newLuceneConfig() { @@ -41,7 +41,9 @@ return super.getMoreFieldInfo(storedFields); try { LuanTable tbl = toTable(storedFields); - tbl = (LuanTable)supplementer.call(luan,tbl); + synchronized(luan) { + tbl = (LuanTable)supplementer.call(luan,tbl); + } if( tbl == null ) { return super.getMoreFieldInfo(storedFields); } else {
--- a/src/luan/modules/parsers/LuanParser.java Sun Jan 31 16:04:39 2021 -0700 +++ b/src/luan/modules/parsers/LuanParser.java Mon Feb 08 14:16:19 2021 -0700 @@ -263,8 +263,13 @@ spaces(); Object obj = value(); if( obj != null ) { - if( obj != NULL ) - tbl.rawAdd(obj); + if( obj != NULL ) { + try { + tbl.rawAdd(obj); + } catch(LuanException e) { + throw new RuntimeException(e); + } + } spaces(); continue; }