Mercurial Hosting > luan
changeset 1561:e1a13e707bf3
start immutable
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 05 Nov 2020 20:24:09 -0700 |
parents | 33a53c43e2f7 |
children | b89212fd04b5 |
files | src/luan/Luan.java src/luan/LuanCloneable.java src/luan/LuanCloner.java src/luan/LuanClosure.java src/luan/LuanException.java src/luan/LuanFunction.java src/luan/LuanImmutabler.java src/luan/LuanTable.java src/luan/impl/Compiled.java src/luan/impl/LuanCompiler.java src/luan/impl/LuanParser.java src/luan/impl/Pointer.java src/luan/modules/BasicLuan.java src/luan/modules/JavaLuan.java |
diffstat | 14 files changed, 186 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- a/src/luan/Luan.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/Luan.java Thu Nov 05 20:24:09 2020 -0700 @@ -43,6 +43,8 @@ isLocked = true; } + @Override public void makeImmutable(LuanImmutabler immutabler) {} + public LuanClosure peek() { return peek(1); }
--- a/src/luan/LuanCloneable.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/LuanCloneable.java Thu Nov 05 20:24:09 2020 -0700 @@ -4,4 +4,5 @@ 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 Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/LuanCloner.java Thu Nov 05 20:24:09 2020 -0700 @@ -34,7 +34,7 @@ } public Object[] clone(Object[] obj) { - if( obj.length == 0 ) + if( obj==null || obj.length == 0 ) return obj; Object[] rtn = (Object[])cloned.get(obj); if( rtn == null ) { @@ -48,6 +48,8 @@ } public Map clone(Map obj) { + if( obj==null ) + return null; Map rtn = (Map)cloned.get(obj); if( rtn == null ) { try { @@ -57,6 +59,7 @@ } 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()) ); @@ -66,6 +69,8 @@ } public Collection clone(Collection obj) { + if( obj==null ) + return null; Collection rtn = (Collection)cloned.get(obj); if( rtn == null ) { try {
--- a/src/luan/LuanClosure.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/LuanClosure.java Thu Nov 05 20:24:09 2020 -0700 @@ -21,6 +21,11 @@ super.completeClone(dc,cloner); } + @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { + immutabler.makeImmutable(upValues); + super.makeImmutable(immutabler); + } + @Override public final Object call(Object... args) throws LuanException { Luan luan = luan(); luan.push(this);
--- a/src/luan/LuanException.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/LuanException.java Thu Nov 05 20:24:09 2020 -0700 @@ -35,6 +35,11 @@ clone.extra = (Map)cloner.clone(extra); } + @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { + immutabler.makeImmutable(table); + immutabler.makeImmutable(extra); + } + public void put(String key,Object value) throws LuanException { if( table == null ) { extra.put(key,value);
--- a/src/luan/LuanFunction.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/LuanFunction.java Thu Nov 05 20:24:09 2020 -0700 @@ -58,6 +58,10 @@ clone.luan = (Luan)cloner.clone(luan); } + @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { + immutabler.makeImmutable(luan); + } + public Luan luan() { check(); return luan;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/LuanImmutabler.java Thu Nov 05 20:24:09 2020 -0700 @@ -0,0 +1,61 @@ +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); + } +}
--- a/src/luan/LuanTable.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/LuanTable.java Thu Nov 05 20:24:09 2020 -0700 @@ -21,12 +21,13 @@ public LuanClosure closure; private LuanCloner cloner; private String security = null; + private boolean immutable = false; public LuanTable(Luan luan) { this.luan = luan; } - public LuanTable(Luan luan,List list){ + public LuanTable(Luan luan,List list) { this.luan = luan; list(); int n = list.size(); @@ -48,7 +49,7 @@ } } - public LuanTable(Luan luan,Set set){ + public LuanTable(Luan luan,Set set) { this.luan = luan; for( Object el : set ) { if( el != null ) @@ -66,6 +67,7 @@ } @Override public LuanTable shallowClone() { + if(immutable) throw new RuntimeException(); return new LuanTable(luan); } @@ -101,25 +103,22 @@ private void completeClone(LuanTable clone,LuanCloner cloner) { clone.luan = (Luan)cloner.clone(luan); - if( map != null ) { - Map newMap = newMap(); - for( Object stupid : map.entrySet() ) { - Map.Entry entry = (Map.Entry)stupid; - newMap.put( cloner.get(entry.getKey()), cloner.get(entry.getValue()) ); - } - clone.map = newMap; - } - if( list != null ) { - List newList = new ArrayList<Object>(); - for( Object obj : list ) { - newList.add(cloner.get(obj)); - } - clone.list = newList; - } + clone.map = cloner.clone(map); + clone.list = (List)cloner.clone(list); clone.metatable = (LuanTable)cloner.clone(metatable); clone.closure = (LuanClosure)cloner.clone(closure); } + @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { + check(); + immutabler.makeImmutable(luan); + immutabler.makeImmutable(map); + immutabler.makeImmutable(list); + immutabler.makeImmutable(metatable); + immutabler.makeImmutable(closure); + immutable = true; + } + public boolean isList() { return map==null || map.isEmpty(); } @@ -203,6 +202,8 @@ } public Object rawPut(Object key,Object val) throws LuanException { + if( immutable ) + throw new LuanException("table is immutable"); if( security != null ) Luan.checkSecurity(luan,"table",security,"put",key,val); return rawPut2(key,val); @@ -479,7 +480,7 @@ return metatable==null ? null : metatable.get(op); } - private Map<Object,Object> newMap() { + private static Map<Object,Object> newMap() { return new LinkedHashMap<Object,Object>(); } @@ -535,7 +536,9 @@ return n; } - public Object remove(Object key) { + public Object remove(Object key) throws LuanException { + if( immutable ) + throw new LuanException("table is immutable"); Object old = rawGet(key); rawPut2(key,null); return old;
--- a/src/luan/impl/Compiled.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/impl/Compiled.java Thu Nov 05 20:24:09 2020 -0700 @@ -133,7 +133,7 @@ } - private static final int VERSION = 3; + private static final int VERSION = 4; private static final File tmpDir; static { File f = new File(System.getProperty("java.io.tmpdir"));
--- a/src/luan/impl/LuanCompiler.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/impl/LuanCompiler.java Thu Nov 05 20:24:09 2020 -0700 @@ -40,9 +40,9 @@ } catch(InvocationTargetException e) { throw new RuntimeException(e); } - closure.upValues[0].o = PackageLuan.requireFn(luan); + closure.upValues[0].set( PackageLuan.requireFn(luan) ); if( env != null ) { - closure.upValues[1].o = env; + closure.upValues[1].set(env); env.closure = closure; } return closure;
--- a/src/luan/impl/LuanParser.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/impl/LuanParser.java Thu Nov 05 20:24:09 2020 -0700 @@ -17,6 +17,7 @@ private interface Sym { public Expr exp(); + public Stmts set(Expr val); } private int symCounter = 0; @@ -72,11 +73,33 @@ if( !isPointer ) return javaName; else - return javaName + ".o"; + return javaName + ".get()"; } } ); return exp; } + + @Override public Stmts set(Expr val) { + Stmts stmt = new Stmts(); + stmt.add( new Object() { + @Override public String toString() { + if( !isPointer ) + return javaName + " = "; + else + return javaName + ".set("; + } + } ); + stmt.addAll( val.single() ); + stmt.add( new Object() { + @Override public String toString() { + if( !isPointer ) + return "; "; + else + return "); "; + } + } ); + return stmt; + } } private class UpSym implements Sym { @@ -89,20 +112,28 @@ this.i = i; this.value = value; } -/* - String init() { - return "upValues[" + i + "] = " + value + "; "; - } -*/ + @Override public Expr exp() { Expr exp = new Expr(Val.SINGLE,false); exp.add( new Object() { @Override public String toString() { - return "upValues[" + i + "].o"; + return "upValues[" + i + "].get()"; } } ); return exp; } + + @Override public Stmts set(Expr val) { + Stmts stmt = new Stmts(); + stmt.add( new Object() { + @Override public String toString() { + return "upValues[" + i + "].set("; + } + } ); + stmt.addAll( val.single() ); + stmt.add( "); " ); + return stmt; + } } private final class Frame { @@ -1312,15 +1343,9 @@ public Stmts set(Expr val) throws ParseException { Sym sym = getSym(name); - if( sym != null ) { - Stmts stmt = new Stmts(); - stmt.addAll( sym.exp() ); - stmt.add( " = " ); - stmt.addAll( val.single() ); - stmt.add( "; " ); - return stmt; - } - Expr envExpr = env(); + if( sym != null ) + return sym.set(val); + Expr envExpr = env(); if( envExpr != null ) return indexVar( envExpr, constExpStr(name) ).set(val); parser.failure(null); @@ -2087,47 +2112,7 @@ } return lines; } -/* - private Expr toFnExp(Stmts stmt,List<UpSym> upValueSymbols,String name) { - stmt.addNewLines(); - if( !stmt.hasReturn ) - stmt.add( "return LuanFunction.NOTHING; " ); - Expr exp = new Expr(Val.SINGLE,false); - exp.add( "" - +"new LuanClosure(luan(),"+upValueSymbols.size()+",javaOk,sourceName) { " - +"{ " - + init(upValueSymbols) - +"} " - +"@Override public Object doCall(Luan luan,Object[] args) throws LuanException { " - ); - if( name != null ) { - exp.add( "" - +"return _" + name + "(luan,args); " - +"} " - +"private Object _" + name + "(Luan luan,Object[] args) throws LuanException { " - ); - } - exp.add( "" - +"final Pointer[] parentUpValues = upValues; " - +"Object t; " - +"Object[] a; " - ); - exp.addAll( stmt ); - exp.add( "" - +"} " - +"} " - ); - return exp; - } - private static String init(List<UpSym> upValueSymbols) { - StringBuilder sb = new StringBuilder(); - for( UpSym upSym : upValueSymbols ) { - sb.append( upSym.init() ); - } - return sb.toString(); - } -*/ private static String toUpValues(List<UpSym> upValueSymbols) { StringBuilder sb = new StringBuilder(); sb.append( "new Pointer[]{ " );
--- a/src/luan/impl/Pointer.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/impl/Pointer.java Thu Nov 05 20:24:09 2020 -0700 @@ -2,10 +2,13 @@ import luan.LuanCloneable; import luan.LuanCloner; +import luan.LuanImmutabler; +import luan.LuanException; public final class Pointer implements LuanCloneable { - public Object o; + private Object o; + private boolean immutable = false; public Pointer() {} @@ -20,4 +23,19 @@ @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); + immutable = true; + } + + public Object get() { + return o; + } + + public void set(Object o) throws LuanException { + if( immutable ) + throw new LuanException("variable is immutable"); + this.o = o; + } }
--- a/src/luan/modules/BasicLuan.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/modules/BasicLuan.java Thu Nov 05 20:24:09 2020 -0700 @@ -15,6 +15,7 @@ import luan.LuanFunction; import luan.LuanException; import luan.LuanCloner; +import luan.LuanImmutabler; import luan.modules.parsers.LuanToString; @@ -72,6 +73,10 @@ clone.list = (List)cloner.clone(list); super.completeClone(dc,cloner); } + + @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { + throw new LuanException("ipairs cannot be made immutable"); + } } public static LuanFunction ipairs(LuanTable t) throws LuanException { @@ -184,6 +189,10 @@ clone.args = (Object[])cloner.clone(args); super.completeClone(dc,cloner); } + + @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { + throw new LuanException("values cannot be made immutable"); + } } public static LuanFunction values(final Object... args) throws LuanException {
--- a/src/luan/modules/JavaLuan.java Thu Oct 22 00:33:04 2020 -0600 +++ b/src/luan/modules/JavaLuan.java Thu Nov 05 20:24:09 2020 -0700 @@ -23,6 +23,7 @@ import luan.LuanFunction; import luan.LuanJavaFunction; import luan.LuanCloner; +import luan.LuanImmutabler; public final class JavaLuan { @@ -379,6 +380,13 @@ AmbiguousJavaFunction clone = (AmbiguousJavaFunction)dc; clone.fnMap = (Map)cloner.clone(fnMap); clone.varArgs = (List)cloner.clone(varArgs); + // no call to super? + } + + @Override public void makeImmutable(LuanImmutabler immutabler) throws LuanException { + immutabler.makeImmutable(fnMap); + immutabler.makeImmutable(varArgs); + super.makeImmutable(immutabler); } @Override public Object call(Object[] args) throws LuanException {